aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2017-11-28 20:47:41 -0500
committerJames Morris <james.l.morris@oracle.com>2017-11-28 20:47:41 -0500
commitcf40a76e7d5874bb25f4404eecc58a2e033af885 (patch)
tree8fd81cbea03c87b3d41d7ae5b1d11eadd35d6ef5 /tools
parentab5348c9c23cd253f5902980d2d8fe067dc24c82 (diff)
parent4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323 (diff)
Merge tag 'v4.15-rc1' into next-seccomp
Linux 4.15-rc1
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile32
-rw-r--r--tools/accounting/Makefile1
-rw-r--r--tools/accounting/getdelays.c1
-rw-r--r--tools/arch/alpha/include/asm/barrier.h1
-rw-r--r--tools/arch/alpha/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/alpha/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/arc/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/arm/include/uapi/asm/kvm.h9
-rw-r--r--tools/arch/arm/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/arm/include/uapi/asm/perf_regs.h1
-rw-r--r--tools/arch/arm64/include/asm/barrier.h1
-rw-r--r--tools/arch/arm64/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/arm64/include/uapi/asm/kvm.h4
-rw-r--r--tools/arch/arm64/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/arm64/include/uapi/asm/perf_regs.h1
-rw-r--r--tools/arch/frv/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/frv/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/h8300/include/asm/bitsperlong.h1
-rw-r--r--tools/arch/h8300/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/hexagon/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/hexagon/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/ia64/include/asm/barrier.h1
-rw-r--r--tools/arch/ia64/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/ia64/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/m32r/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/m32r/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/microblaze/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/microblaze/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/mips/include/asm/barrier.h1
-rw-r--r--tools/arch/mips/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/mips/include/uapi/asm/kvm.h1
-rw-r--r--tools/arch/mips/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/mn10300/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/parisc/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/parisc/include/uapi/asm/mman.h3
-rw-r--r--tools/arch/powerpc/include/asm/barrier.h1
-rw-r--r--tools/arch/powerpc/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/powerpc/include/uapi/asm/kvm.h7
-rw-r--r--tools/arch/powerpc/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/powerpc/include/uapi/asm/perf_regs.h1
-rw-r--r--tools/arch/s390/include/asm/barrier.h1
-rw-r--r--tools/arch/s390/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/s390/include/uapi/asm/kvm.h19
-rw-r--r--tools/arch/s390/include/uapi/asm/kvm_perf.h1
-rw-r--r--tools/arch/s390/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/s390/include/uapi/asm/sie.h1
-rw-r--r--tools/arch/score/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/score/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/sh/include/asm/barrier.h1
-rw-r--r--tools/arch/sh/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/sparc/include/asm/barrier.h1
-rw-r--r--tools/arch/sparc/include/asm/barrier_32.h1
-rw-r--r--tools/arch/sparc/include/asm/barrier_64.h1
-rw-r--r--tools/arch/sparc/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/sparc/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/tile/include/asm/barrier.h1
-rw-r--r--tools/arch/tile/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/tile/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/x86/include/asm/atomic.h3
-rw-r--r--tools/arch/x86/include/asm/barrier.h1
-rw-r--r--tools/arch/x86/include/asm/cmpxchg.h1
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h6
-rw-r--r--tools/arch/x86/include/asm/disabled-features.h4
-rw-r--r--tools/arch/x86/include/asm/rmwcc.h1
-rw-r--r--tools/arch/x86/include/asm/unistd_32.h4
-rw-r--r--tools/arch/x86/include/asm/unistd_64.h4
-rw-r--r--tools/arch/x86/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/x86/include/uapi/asm/kvm.h1
-rw-r--r--tools/arch/x86/include/uapi/asm/kvm_perf.h1
-rw-r--r--tools/arch/x86/include/uapi/asm/mman.h1
-rw-r--r--tools/arch/x86/include/uapi/asm/perf_regs.h1
-rw-r--r--tools/arch/x86/include/uapi/asm/svm.h1
-rw-r--r--tools/arch/x86/include/uapi/asm/unistd.h18
-rw-r--r--tools/arch/x86/include/uapi/asm/vmx.h1
-rw-r--r--tools/arch/x86/lib/memcpy_64.S4
-rw-r--r--tools/arch/x86/lib/memset_64.S1
-rw-r--r--tools/arch/xtensa/include/uapi/asm/mman.h1
-rw-r--r--tools/bpf/Makefile (renamed from tools/net/Makefile)19
-rw-r--r--tools/bpf/bpf_asm.c (renamed from tools/net/bpf_asm.c)0
-rw-r--r--tools/bpf/bpf_dbg.c (renamed from tools/net/bpf_dbg.c)0
-rw-r--r--tools/bpf/bpf_exp.l (renamed from tools/net/bpf_exp.l)0
-rw-r--r--tools/bpf/bpf_exp.y (renamed from tools/net/bpf_exp.y)0
-rw-r--r--tools/bpf/bpf_jit_disasm.c (renamed from tools/net/bpf_jit_disasm.c)3
-rw-r--r--tools/bpf/bpftool/Documentation/Makefile34
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-map.rst131
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-prog.rst150
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool.rst56
-rw-r--r--tools/bpf/bpftool/Makefile92
-rw-r--r--tools/bpf/bpftool/bash-completion/bpftool354
-rw-r--r--tools/bpf/bpftool/common.c405
-rw-r--r--tools/bpf/bpftool/jit_disasm.c162
-rw-r--r--tools/bpf/bpftool/json_writer.c356
-rw-r--r--tools/bpf/bpftool/json_writer.h72
-rw-r--r--tools/bpf/bpftool/main.c331
-rw-r--r--tools/bpf/bpftool/main.h122
-rw-r--r--tools/bpf/bpftool/map.c899
-rw-r--r--tools/bpf/bpftool/prog.c672
-rw-r--r--tools/build/Makefile1
-rw-r--r--tools/build/Makefile.build1
-rw-r--r--tools/build/Makefile.feature3
-rw-r--r--tools/build/feature/Makefile7
-rw-r--r--tools/build/feature/test-all.c6
-rw-r--r--tools/build/feature/test-backtrace.c1
-rw-r--r--tools/build/feature/test-bionic.c1
-rw-r--r--tools/build/feature/test-bpf.c3
-rw-r--r--tools/build/feature/test-clang.cpp1
-rw-r--r--tools/build/feature/test-compile.c1
-rw-r--r--tools/build/feature/test-cplus-demangle.c1
-rw-r--r--tools/build/feature/test-cxx.cpp1
-rw-r--r--tools/build/feature/test-dwarf.c1
-rw-r--r--tools/build/feature/test-dwarf_getlocations.c1
-rw-r--r--tools/build/feature/test-get_cpuid.c1
-rw-r--r--tools/build/feature/test-glibc.c1
-rw-r--r--tools/build/feature/test-gtk2-infobar.c1
-rw-r--r--tools/build/feature/test-gtk2.c1
-rw-r--r--tools/build/feature/test-jvmti.c1
-rw-r--r--tools/build/feature/test-libaudit.c1
-rw-r--r--tools/build/feature/test-libbabeltrace.c1
-rw-r--r--tools/build/feature/test-libbfd.c1
-rw-r--r--tools/build/feature/test-libcrypto.c1
-rw-r--r--tools/build/feature/test-libdw-dwarf-unwind.c1
-rw-r--r--tools/build/feature/test-libelf-gelf_getnote.c1
-rw-r--r--tools/build/feature/test-libelf-getphdrnum.c1
-rw-r--r--tools/build/feature/test-libelf-getshdrstrndx.c1
-rw-r--r--tools/build/feature/test-libelf-mmap.c1
-rw-r--r--tools/build/feature/test-libelf.c1
-rw-r--r--tools/build/feature/test-libnuma.c1
-rw-r--r--tools/build/feature/test-libperl.c1
-rw-r--r--tools/build/feature/test-libpython-version.c1
-rw-r--r--tools/build/feature/test-libpython.c1
-rw-r--r--tools/build/feature/test-libslang.c1
-rw-r--r--tools/build/feature/test-libunwind-aarch64.c1
-rw-r--r--tools/build/feature/test-libunwind-arm.c1
-rw-r--r--tools/build/feature/test-libunwind-debug-frame-aarch64.c1
-rw-r--r--tools/build/feature/test-libunwind-debug-frame-arm.c1
-rw-r--r--tools/build/feature/test-libunwind-debug-frame.c1
-rw-r--r--tools/build/feature/test-libunwind-x86.c1
-rw-r--r--tools/build/feature/test-libunwind-x86_64.c1
-rw-r--r--tools/build/feature/test-libunwind.c1
-rw-r--r--tools/build/feature/test-llvm-version.cpp1
-rw-r--r--tools/build/feature/test-llvm.cpp1
-rw-r--r--tools/build/feature/test-lzma.c1
-rw-r--r--tools/build/feature/test-numa_num_possible_cpus.c1
-rw-r--r--tools/build/feature/test-pthread-attr-setaffinity-np.c1
-rw-r--r--tools/build/feature/test-sched_getcpu.c1
-rw-r--r--tools/build/feature/test-sdt.c1
-rw-r--r--tools/build/feature/test-setns.c7
-rw-r--r--tools/build/feature/test-stackprotector-all.c1
-rw-r--r--tools/build/feature/test-sync-compare-and-swap.c1
-rw-r--r--tools/build/feature/test-timerfd.c1
-rw-r--r--tools/build/feature/test-zlib.c1
-rw-r--r--tools/build/fixdep.c1
-rw-r--r--tools/build/tests/ex/Makefile3
-rw-r--r--tools/build/tests/ex/a.c1
-rw-r--r--tools/build/tests/ex/arch/e.c1
-rw-r--r--tools/build/tests/ex/arch/f.c1
-rw-r--r--tools/build/tests/ex/b.c1
-rw-r--r--tools/build/tests/ex/c.c1
-rw-r--r--tools/build/tests/ex/d.c1
-rw-r--r--tools/build/tests/ex/ex.c1
-rw-r--r--tools/build/tests/ex/inc.c1
-rwxr-xr-xtools/build/tests/run.sh1
-rw-r--r--tools/cgroup/Makefile1
-rw-r--r--tools/cgroup/cgroup_event_listener.c1
-rw-r--r--tools/firewire/Makefile1
-rw-r--r--tools/firewire/decode-fcp.c1
-rw-r--r--tools/firewire/list.h1
-rw-r--r--tools/firewire/nosy-dump.h1
-rw-r--r--tools/gpio/Makefile1
-rw-r--r--tools/gpio/gpio-utils.c17
-rw-r--r--tools/hv/Makefile1
-rwxr-xr-xtools/hv/bondvf.sh232
-rw-r--r--tools/hv/hv_fcopy_daemon.c32
-rwxr-xr-xtools/hv/hv_get_dhcp_info.sh1
-rw-r--r--tools/hv/hv_kvp_daemon.c2
-rwxr-xr-xtools/hv/hv_set_ifconfig.sh1
-rw-r--r--tools/hv/hv_vss_daemon.c7
-rw-r--r--tools/hv/lsvmbus1
-rw-r--r--tools/iio/Build3
-rw-r--r--tools/iio/Makefile77
-rw-r--r--tools/include/asm-generic/atomic-gcc.h3
-rw-r--r--tools/include/asm-generic/bitops.h1
-rw-r--r--tools/include/asm-generic/bitops/__ffs.h1
-rw-r--r--tools/include/asm-generic/bitops/__fls.h1
-rw-r--r--tools/include/asm-generic/bitops/arch_hweight.h1
-rw-r--r--tools/include/asm-generic/bitops/atomic.h1
-rw-r--r--tools/include/asm-generic/bitops/const_hweight.h1
-rw-r--r--tools/include/asm-generic/bitops/find.h1
-rw-r--r--tools/include/asm-generic/bitops/fls.h1
-rw-r--r--tools/include/asm-generic/bitops/fls64.h1
-rw-r--r--tools/include/asm-generic/bitops/hweight.h1
-rw-r--r--tools/include/asm-generic/bitsperlong.h1
-rw-r--r--tools/include/asm-generic/hugetlb_encode.h34
-rw-r--r--tools/include/asm/alternative-asm.h1
-rw-r--r--tools/include/asm/atomic.h1
-rw-r--r--tools/include/asm/barrier.h1
-rw-r--r--tools/include/asm/bug.h1
-rw-r--r--tools/include/asm/export.h7
-rw-r--r--tools/include/linux/atomic.h1
-rw-r--r--tools/include/linux/bitmap.h1
-rw-r--r--tools/include/linux/bitops.h1
-rw-r--r--tools/include/linux/bug.h1
-rw-r--r--tools/include/linux/compiler-gcc.h10
-rw-r--r--tools/include/linux/compiler.h1
-rw-r--r--tools/include/linux/coresight-pmu.h6
-rw-r--r--tools/include/linux/debug_locks.h1
-rw-r--r--tools/include/linux/err.h1
-rw-r--r--tools/include/linux/filter.h1
-rw-r--r--tools/include/linux/hardirq.h1
-rw-r--r--tools/include/linux/hashtable.h1
-rw-r--r--tools/include/linux/irqflags.h1
-rw-r--r--tools/include/linux/kallsyms.h1
-rw-r--r--tools/include/linux/kern_levels.h1
-rw-r--r--tools/include/linux/kernel.h1
-rw-r--r--tools/include/linux/kmemcheck.h9
-rw-r--r--tools/include/linux/list.h1
-rw-r--r--tools/include/linux/lockdep.h1
-rw-r--r--tools/include/linux/module.h1
-rw-r--r--tools/include/linux/poison.h6
-rw-r--r--tools/include/linux/rcu.h1
-rw-r--r--tools/include/linux/refcount.h1
-rw-r--r--tools/include/linux/spinlock.h1
-rw-r--r--tools/include/linux/stacktrace.h1
-rw-r--r--tools/include/linux/string.h13
-rw-r--r--tools/include/linux/stringify.h1
-rw-r--r--tools/include/linux/time64.h1
-rw-r--r--tools/include/linux/types.h1
-rw-r--r--tools/include/linux/unaligned/packed_struct.h1
-rw-r--r--tools/include/tools/be_byteshift.h1
-rw-r--r--tools/include/tools/endian.h1
-rw-r--r--tools/include/tools/le_byteshift.h1
-rw-r--r--tools/include/uapi/asm-generic/fcntl.h220
-rw-r--r--tools/include/uapi/asm-generic/ioctls.h119
-rw-r--r--tools/include/uapi/asm-generic/mman-common.h16
-rw-r--r--tools/include/uapi/asm-generic/mman.h3
-rw-r--r--tools/include/uapi/drm/drm.h955
-rw-r--r--tools/include/uapi/drm/i915_drm.h1522
-rw-r--r--tools/include/uapi/linux/bpf.h246
-rw-r--r--tools/include/uapi/linux/bpf_common.h1
-rw-r--r--tools/include/uapi/linux/fcntl.h22
-rw-r--r--tools/include/uapi/linux/hw_breakpoint.h1
-rw-r--r--tools/include/uapi/linux/kcmp.h27
-rw-r--r--tools/include/uapi/linux/kvm.h1421
-rw-r--r--tools/include/uapi/linux/mman.h25
-rw-r--r--tools/include/uapi/linux/perf_event.h62
-rw-r--r--tools/include/uapi/linux/prctl.h200
-rw-r--r--tools/include/uapi/linux/sched.h53
-rw-r--r--tools/include/uapi/linux/stat.h1
-rw-r--r--tools/include/uapi/linux/vhost.h210
-rw-r--r--tools/include/uapi/sound/asound.h1027
-rw-r--r--tools/kvm/kvm_stat/Makefile1
-rwxr-xr-xtools/kvm/kvm_stat/kvm_stat52
-rw-r--r--tools/laptop/dslm/Makefile1
-rw-r--r--tools/laptop/freefall/Makefile1
-rw-r--r--tools/leds/Makefile1
-rw-r--r--tools/leds/led_hw_brightness_mon.c1
-rw-r--r--tools/leds/uledmon.c1
-rw-r--r--tools/lguest/.gitignore2
-rw-r--r--tools/lguest/Makefile14
-rw-r--r--tools/lguest/extract58
-rw-r--r--tools/lguest/lguest.c3420
-rw-r--r--tools/lguest/lguest.txt125
-rw-r--r--tools/lib/api/Makefile17
-rw-r--r--tools/lib/api/cpu.c1
-rw-r--r--tools/lib/api/cpu.h1
-rw-r--r--tools/lib/api/debug-internal.h1
-rw-r--r--tools/lib/api/debug.c1
-rw-r--r--tools/lib/api/debug.h1
-rw-r--r--tools/lib/api/fd/array.h1
-rw-r--r--tools/lib/api/fs/fs.c1
-rw-r--r--tools/lib/api/fs/fs.h1
-rw-r--r--tools/lib/api/fs/tracing_path.c1
-rw-r--r--tools/lib/api/fs/tracing_path.h1
-rw-r--r--tools/lib/bpf/Makefile13
-rw-r--r--tools/lib/bpf/bpf.c104
-rw-r--r--tools/lib/bpf/bpf.h23
-rw-r--r--tools/lib/bpf/libbpf.c211
-rw-r--r--tools/lib/bpf/libbpf.h3
-rw-r--r--tools/lib/hweight.c1
-rw-r--r--tools/lib/lockdep/Makefile1
-rw-r--r--tools/lib/lockdep/common.c1
-rw-r--r--tools/lib/lockdep/include/liblockdep/common.h1
-rw-r--r--tools/lib/lockdep/include/liblockdep/mutex.h1
-rw-r--r--tools/lib/lockdep/include/liblockdep/rwlock.h1
-rw-r--r--tools/lib/lockdep/lockdep.c1
-rw-r--r--tools/lib/lockdep/preload.c1
-rwxr-xr-xtools/lib/lockdep/run_tests.sh1
-rw-r--r--tools/lib/lockdep/tests/AA.c1
-rw-r--r--tools/lib/lockdep/tests/ABA.c1
-rw-r--r--tools/lib/lockdep/tests/ABBA.c1
-rw-r--r--tools/lib/lockdep/tests/ABBA_2threads.c1
-rw-r--r--tools/lib/lockdep/tests/ABBCCA.c1
-rw-r--r--tools/lib/lockdep/tests/ABBCCDDA.c1
-rw-r--r--tools/lib/lockdep/tests/ABCABC.c1
-rw-r--r--tools/lib/lockdep/tests/ABCDBCDA.c1
-rw-r--r--tools/lib/lockdep/tests/ABCDBDDA.c1
-rw-r--r--tools/lib/lockdep/tests/WW.c1
-rw-r--r--tools/lib/lockdep/tests/common.h1
-rw-r--r--tools/lib/lockdep/tests/unlock_balance.c1
-rw-r--r--tools/lib/str_error_r.c1
-rw-r--r--tools/lib/string.c42
-rw-r--r--tools/lib/subcmd/Makefile3
-rw-r--r--tools/lib/subcmd/exec-cmd.c1
-rw-r--r--tools/lib/subcmd/exec-cmd.h1
-rw-r--r--tools/lib/subcmd/help.c3
-rw-r--r--tools/lib/subcmd/help.h1
-rw-r--r--tools/lib/subcmd/pager.c1
-rw-r--r--tools/lib/subcmd/pager.h1
-rw-r--r--tools/lib/subcmd/parse-options.c19
-rw-r--r--tools/lib/subcmd/parse-options.h1
-rw-r--r--tools/lib/subcmd/run-command.c1
-rw-r--r--tools/lib/subcmd/run-command.h1
-rw-r--r--tools/lib/subcmd/sigchain.c1
-rw-r--r--tools/lib/subcmd/sigchain.h1
-rw-r--r--tools/lib/subcmd/subcmd-config.c1
-rw-r--r--tools/lib/subcmd/subcmd-config.h1
-rw-r--r--tools/lib/subcmd/subcmd-util.h1
-rw-r--r--tools/lib/symbol/kallsyms.c1
-rw-r--r--tools/lib/symbol/kallsyms.h1
-rw-r--r--tools/lib/traceevent/Makefile1
-rw-r--r--tools/lib/traceevent/parse-filter.c6
-rw-r--r--tools/lib/traceevent/plugin_cfg80211.c1
-rw-r--r--tools/lib/traceevent/plugin_scsi.c1
-rw-r--r--tools/lib/traceevent/plugin_xen.c1
-rw-r--r--tools/lib/vsprintf.c1
-rwxr-xr-xtools/nfsd/inject_fault.sh1
-rw-r--r--tools/objtool/.gitignore2
-rw-r--r--tools/objtool/Build3
-rw-r--r--tools/objtool/Documentation/stack-validation.txt62
-rw-r--r--tools/objtool/Makefile23
-rw-r--r--tools/objtool/arch.h5
-rw-r--r--tools/objtool/arch/x86/Build10
-rw-r--r--tools/objtool/arch/x86/decode.c110
-rw-r--r--tools/objtool/arch/x86/include/asm/inat.h (renamed from tools/objtool/arch/x86/insn/inat.h)12
-rw-r--r--tools/objtool/arch/x86/include/asm/inat_types.h (renamed from tools/objtool/arch/x86/insn/inat_types.h)0
-rw-r--r--tools/objtool/arch/x86/include/asm/insn.h (renamed from tools/objtool/arch/x86/insn/insn.h)2
-rw-r--r--tools/objtool/arch/x86/include/asm/orc_types.h107
-rw-r--r--tools/objtool/arch/x86/lib/inat.c (renamed from tools/objtool/arch/x86/insn/inat.c)2
-rw-r--r--tools/objtool/arch/x86/lib/insn.c (renamed from tools/objtool/arch/x86/insn/insn.c)4
-rw-r--r--tools/objtool/arch/x86/lib/x86-opcode-map.txt (renamed from tools/objtool/arch/x86/insn/x86-opcode-map.txt)0
-rw-r--r--tools/objtool/arch/x86/tools/gen-insn-attr-x86.awk (renamed from tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk)1
-rw-r--r--tools/objtool/builtin-check.c7
-rw-r--r--tools/objtool/builtin-orc.c70
-rw-r--r--tools/objtool/builtin.h1
-rw-r--r--tools/objtool/cfi.h2
-rw-r--r--tools/objtool/check.c505
-rw-r--r--tools/objtool/check.h22
-rw-r--r--tools/objtool/elf.c243
-rw-r--r--tools/objtool/elf.h15
-rw-r--r--tools/objtool/objtool.c9
-rw-r--r--tools/objtool/orc.h30
-rw-r--r--tools/objtool/orc_dump.c212
-rw-r--r--tools/objtool/orc_gen.c214
-rwxr-xr-xtools/objtool/sync-check.sh29
-rw-r--r--tools/pci/pcitest.c1
-rw-r--r--tools/pci/pcitest.sh1
-rw-r--r--tools/pcmcia/Makefile1
-rw-r--r--tools/perf/Build2
-rw-r--r--tools/perf/Documentation/Makefile2
-rw-r--r--tools/perf/Documentation/intel-pt.txt8
-rw-r--r--tools/perf/Documentation/perf-annotate.txt6
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt5
-rw-r--r--tools/perf/Documentation/perf-list.txt11
-rw-r--r--tools/perf/Documentation/perf-mem.txt4
-rw-r--r--tools/perf/Documentation/perf-probe.txt14
-rw-r--r--tools/perf/Documentation/perf-record.txt12
-rw-r--r--tools/perf/Documentation/perf-report.txt4
-rw-r--r--tools/perf/Documentation/perf-sched.txt8
-rw-r--r--tools/perf/Documentation/perf-script.txt11
-rw-r--r--tools/perf/Documentation/perf-stat.txt11
-rw-r--r--tools/perf/Documentation/perf-top.txt7
-rw-r--r--tools/perf/Documentation/perf-trace.txt2
-rw-r--r--tools/perf/Documentation/perf.data-file-format.txt10
-rw-r--r--tools/perf/MANIFEST79
-rw-r--r--tools/perf/Makefile1
-rw-r--r--tools/perf/Makefile.config31
-rw-r--r--tools/perf/Makefile.perf136
-rw-r--r--tools/perf/arch/arm/annotate/instructions.c4
-rw-r--r--tools/perf/arch/arm/include/dwarf-regs-table.h1
-rw-r--r--tools/perf/arch/arm/include/perf_regs.h1
-rw-r--r--tools/perf/arch/arm/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/arch/arm/tests/regs_load.S1
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c28
-rw-r--r--tools/perf/arch/arm/util/unwind-libdw.c1
-rw-r--r--tools/perf/arch/arm/util/unwind-libunwind.c1
-rw-r--r--tools/perf/arch/arm64/Makefile1
-rw-r--r--tools/perf/arch/arm64/annotate/instructions.c4
-rw-r--r--tools/perf/arch/arm64/include/dwarf-regs-table.h1
-rw-r--r--tools/perf/arch/arm64/include/perf_regs.h1
-rw-r--r--tools/perf/arch/arm64/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/arch/arm64/tests/regs_load.S1
-rw-r--r--tools/perf/arch/arm64/util/unwind-libunwind.c1
-rw-r--r--tools/perf/arch/common.c1
-rw-r--r--tools/perf/arch/common.h1
-rw-r--r--tools/perf/arch/powerpc/Makefile1
-rw-r--r--tools/perf/arch/powerpc/annotate/instructions.c5
-rw-r--r--tools/perf/arch/powerpc/include/arch-tests.h1
-rw-r--r--tools/perf/arch/powerpc/include/dwarf-regs-table.h1
-rw-r--r--tools/perf/arch/powerpc/include/perf_regs.h1
-rw-r--r--tools/perf/arch/powerpc/tests/arch-tests.c1
-rw-r--r--tools/perf/arch/powerpc/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/arch/powerpc/tests/regs_load.S1
-rw-r--r--tools/perf/arch/powerpc/util/book3s_hcalls.h1
-rw-r--r--tools/perf/arch/powerpc/util/book3s_hv_exits.h1
-rw-r--r--tools/perf/arch/powerpc/util/header.c1
-rw-r--r--tools/perf/arch/powerpc/util/kvm-stat.c1
-rw-r--r--tools/perf/arch/powerpc/util/perf_regs.c1
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c2
-rw-r--r--tools/perf/arch/powerpc/util/unwind-libdw.c1
-rw-r--r--tools/perf/arch/s390/annotate/instructions.c5
-rw-r--r--tools/perf/arch/s390/include/dwarf-regs-table.h72
-rw-r--r--tools/perf/arch/s390/include/perf_regs.h95
-rw-r--r--tools/perf/arch/s390/util/Build3
-rw-r--r--tools/perf/arch/s390/util/auxtrace.c118
-rw-r--r--tools/perf/arch/s390/util/dwarf-regs.c12
-rw-r--r--tools/perf/arch/s390/util/machine.c1
-rw-r--r--tools/perf/arch/s390/util/unwind-libdw.c63
-rw-r--r--tools/perf/arch/sh/include/dwarf-regs-table.h1
-rw-r--r--tools/perf/arch/sparc/include/dwarf-regs-table.h1
-rw-r--r--tools/perf/arch/x86/Makefile3
-rw-r--r--tools/perf/arch/x86/annotate/instructions.c61
-rwxr-xr-xtools/perf/arch/x86/entry/syscalls/syscalltbl.sh1
-rw-r--r--tools/perf/arch/x86/include/arch-tests.h11
-rw-r--r--tools/perf/arch/x86/include/dwarf-regs-table.h1
-rw-r--r--tools/perf/arch/x86/include/perf_regs.h1
-rw-r--r--tools/perf/arch/x86/tests/Build1
-rw-r--r--tools/perf/arch/x86/tests/arch-tests.c5
-rw-r--r--tools/perf/arch/x86/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-32.c1
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-64.c1
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-src.c1
-rw-r--r--tools/perf/arch/x86/tests/insn-x86.c3
-rw-r--r--tools/perf/arch/x86/tests/intel-cqm.c3
-rw-r--r--tools/perf/arch/x86/tests/perf-time-to-tsc.c3
-rw-r--r--tools/perf/arch/x86/tests/rdpmc.c3
-rw-r--r--tools/perf/arch/x86/tests/regs_load.S1
-rw-r--r--tools/perf/arch/x86/util/group.c1
-rw-r--r--tools/perf/arch/x86/util/header.c1
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c3
-rw-r--r--tools/perf/arch/x86/util/kvm-stat.c1
-rw-r--r--tools/perf/arch/x86/util/perf_regs.c1
-rw-r--r--tools/perf/arch/x86/util/pmu.c1
-rw-r--r--tools/perf/arch/x86/util/tsc.c1
-rw-r--r--tools/perf/arch/x86/util/unwind-libdw.c1
-rw-r--r--tools/perf/arch/x86/util/unwind-libunwind.c1
-rw-r--r--tools/perf/arch/xtensa/include/dwarf-regs-table.h1
-rw-r--r--tools/perf/bench/bench.h1
-rw-r--r--tools/perf/bench/futex-hash.c1
-rw-r--r--tools/perf/bench/futex-lock-pi.c1
-rw-r--r--tools/perf/bench/futex-requeue.c1
-rw-r--r--tools/perf/bench/futex-wake-parallel.c1
-rw-r--r--tools/perf/bench/futex-wake.c1
-rw-r--r--tools/perf/bench/futex.h1
-rw-r--r--tools/perf/bench/mem-functions.c1
-rw-r--r--tools/perf/bench/mem-memcpy-arch.h1
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm-def.h1
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm.S1
-rw-r--r--tools/perf/bench/mem-memset-arch.h1
-rw-r--r--tools/perf/bench/mem-memset-x86-64-asm-def.h1
-rw-r--r--tools/perf/bench/mem-memset-x86-64-asm.S1
-rw-r--r--tools/perf/bench/numa.c1
-rw-r--r--tools/perf/bench/sched-messaging.c1
-rw-r--r--tools/perf/bench/sched-pipe.c1
-rw-r--r--tools/perf/builtin-annotate.c34
-rw-r--r--tools/perf/builtin-bench.c1
-rw-r--r--tools/perf/builtin-buildid-cache.c63
-rw-r--r--tools/perf/builtin-buildid-list.c17
-rw-r--r--tools/perf/builtin-c2c.c12
-rw-r--r--tools/perf/builtin-config.c28
-rw-r--r--tools/perf/builtin-data.c3
-rw-r--r--tools/perf/builtin-diff.c19
-rw-r--r--tools/perf/builtin-evlist.c13
-rw-r--r--tools/perf/builtin-ftrace.c2
-rw-r--r--tools/perf/builtin-help.c7
-rw-r--r--tools/perf/builtin-inject.c38
-rw-r--r--tools/perf/builtin-kmem.c15
-rw-r--r--tools/perf/builtin-kvm.c19
-rw-r--r--tools/perf/builtin-list.c8
-rw-r--r--tools/perf/builtin-lock.c13
-rw-r--r--tools/perf/builtin-mem.c111
-rw-r--r--tools/perf/builtin-probe.c45
-rw-r--r--tools/perf/builtin-record.c171
-rw-r--r--tools/perf/builtin-report.c78
-rw-r--r--tools/perf/builtin-sched.c29
-rw-r--r--tools/perf/builtin-script.c739
-rw-r--r--tools/perf/builtin-stat.c155
-rw-r--r--tools/perf/builtin-timechart.c18
-rw-r--r--tools/perf/builtin-top.c35
-rw-r--r--tools/perf/builtin-trace.c865
-rw-r--r--tools/perf/builtin-version.c1
-rw-r--r--tools/perf/builtin.h1
-rwxr-xr-xtools/perf/check-headers.sh28
-rw-r--r--tools/perf/jvmti/jvmti_agent.h1
-rw-r--r--tools/perf/jvmti/libjvmti.c1
-rw-r--r--tools/perf/perf-archive.sh1
-rw-r--r--tools/perf/perf-completion.sh1
-rw-r--r--tools/perf/perf-read-vdso.c1
-rw-r--r--tools/perf/perf-sys.h29
-rw-r--r--tools/perf/perf.c31
-rw-r--r--tools/perf/perf.h4
-rw-r--r--tools/perf/pmu-events/README4
-rw-r--r--tools/perf/pmu-events/arch/powerpc/mapfile.csv16
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/cache.json137
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/floating-point.json32
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/frontend.json372
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/marked.json647
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/memory.json132
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/other.json2392
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/pipeline.json552
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/pmc.json122
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/translation.json232
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwell/bdw-metrics.json164
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json164
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/bdx-metrics.json164
-rw-r--r--tools/perf/pmu-events/arch/x86/goldmontplus/cache.json1453
-rw-r--r--tools/perf/pmu-events/arch/x86/goldmontplus/frontend.json62
-rw-r--r--tools/perf/pmu-events/arch/x86/goldmontplus/memory.json38
-rw-r--r--tools/perf/pmu-events/arch/x86/goldmontplus/other.json98
-rw-r--r--tools/perf/pmu-events/arch/x86/goldmontplus/pipeline.json544
-rw-r--r--tools/perf/pmu-events/arch/x86/goldmontplus/virtual-memory.json218
-rw-r--r--tools/perf/pmu-events/arch/x86/haswell/hsw-metrics.json158
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/hsx-metrics.json158
-rw-r--r--tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json164
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/ivt-metrics.json164
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/jkt-metrics.json140
-rw-r--r--tools/perf/pmu-events/arch/x86/mapfile.csv2
-rw-r--r--tools/perf/pmu-events/arch/x86/sandybridge/snb-metrics.json140
-rw-r--r--tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json164
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/cache.json1672
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/floating-point.json88
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/frontend.json482
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/memory.json1396
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/other.json72
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/pipeline.json950
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json164
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/uncore-memory.json172
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/uncore-other.json1156
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/virtual-memory.json284
-rw-r--r--tools/perf/pmu-events/jevents.c47
-rw-r--r--tools/perf/pmu-events/jevents.h3
-rw-r--r--tools/perf/pmu-events/jsmn.h1
-rw-r--r--tools/perf/pmu-events/json.h1
-rw-r--r--tools/perf/pmu-events/pmu-events.h2
-rwxr-xr-xtools/perf/python/tracepoint.py1
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Makefile.PL1
-rwxr-xr-xtools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py1
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py1
-rw-r--r--tools/perf/scripts/python/bin/export-to-sqlite-record8
-rw-r--r--tools/perf/scripts/python/bin/export-to-sqlite-report29
-rw-r--r--tools/perf/scripts/python/call-graph-from-sql.py (renamed from tools/perf/scripts/python/call-graph-from-postgresql.py)70
-rw-r--r--tools/perf/scripts/python/event_analyzing_sample.py1
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py5
-rw-r--r--tools/perf/scripts/python/export-to-sqlite.py451
-rwxr-xr-xtools/perf/scripts/python/net_dropmonitor.py1
-rw-r--r--tools/perf/scripts/python/netdev-times.py1
-rwxr-xr-xtools/perf/scripts/python/stackcollapse.py1
-rw-r--r--tools/perf/scripts/python/stat-cpi.py1
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/attr.c17
-rw-r--r--tools/perf/tests/attr.py55
-rw-r--r--tools/perf/tests/attr/base-record8
-rw-r--r--tools/perf/tests/attr/base-stat4
-rw-r--r--tools/perf/tests/attr/test-record-C01
-rw-r--r--tools/perf/tests/attr/test-record-basic1
-rw-r--r--tools/perf/tests/attr/test-record-branch-any2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-any2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-any_call2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-any_ret2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-hv2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-ind_call2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-k2
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-u2
-rw-r--r--tools/perf/tests/attr/test-record-count1
-rw-r--r--tools/perf/tests/attr/test-record-data3
-rw-r--r--tools/perf/tests/attr/test-record-freq1
-rw-r--r--tools/perf/tests/attr/test-record-graph-default1
-rw-r--r--tools/perf/tests/attr/test-record-graph-dwarf4
-rw-r--r--tools/perf/tests/attr/test-record-graph-fp1
-rw-r--r--tools/perf/tests/attr/test-record-group2
-rw-r--r--tools/perf/tests/attr/test-record-group-sampling3
-rw-r--r--tools/perf/tests/attr/test-record-group12
-rw-r--r--tools/perf/tests/attr/test-record-no-buffering (renamed from tools/perf/tests/attr/test-record-no-delay)4
-rw-r--r--tools/perf/tests/attr/test-record-no-inherit1
-rw-r--r--tools/perf/tests/attr/test-record-no-samples1
-rw-r--r--tools/perf/tests/attr/test-record-period1
-rw-r--r--tools/perf/tests/attr/test-record-raw2
-rw-r--r--tools/perf/tests/attr/test-stat-C05
-rw-r--r--tools/perf/tests/attr/test-stat-basic1
-rw-r--r--tools/perf/tests/attr/test-stat-default6
-rw-r--r--tools/perf/tests/attr/test-stat-detailed-110
-rw-r--r--tools/perf/tests/attr/test-stat-detailed-216
-rw-r--r--tools/perf/tests/attr/test-stat-detailed-318
-rw-r--r--tools/perf/tests/attr/test-stat-group2
-rw-r--r--tools/perf/tests/attr/test-stat-group12
-rw-r--r--tools/perf/tests/attr/test-stat-no-inherit1
-rw-r--r--tools/perf/tests/backward-ring-buffer.c3
-rw-r--r--tools/perf/tests/bitmap.c3
-rw-r--r--tools/perf/tests/bp_signal.c3
-rw-r--r--tools/perf/tests/bp_signal_overflow.c3
-rw-r--r--tools/perf/tests/bpf-script-test-prologue.c4
-rw-r--r--tools/perf/tests/bpf.c20
-rw-r--r--tools/perf/tests/builtin-test.c190
-rw-r--r--tools/perf/tests/clang.c5
-rw-r--r--tools/perf/tests/code-reading.c8
-rw-r--r--tools/perf/tests/cpumap.c5
-rw-r--r--tools/perf/tests/dso-data.c7
-rw-r--r--tools/perf/tests/dwarf-unwind.c5
-rw-r--r--tools/perf/tests/event-times.c3
-rw-r--r--tools/perf/tests/event_update.c3
-rw-r--r--tools/perf/tests/evsel-roundtrip-name.c3
-rw-r--r--tools/perf/tests/evsel-tp-sched.c3
-rw-r--r--tools/perf/tests/expr.c8
-rw-r--r--tools/perf/tests/fdarray.c5
-rw-r--r--tools/perf/tests/hists_common.c1
-rw-r--r--tools/perf/tests/hists_common.h1
-rw-r--r--tools/perf/tests/hists_cumulate.c3
-rw-r--r--tools/perf/tests/hists_filter.c3
-rw-r--r--tools/perf/tests/hists_link.c3
-rw-r--r--tools/perf/tests/hists_output.c3
-rw-r--r--tools/perf/tests/is_printable_array.c3
-rw-r--r--tools/perf/tests/keep-tracking.c3
-rw-r--r--tools/perf/tests/kmod-path.c3
-rw-r--r--tools/perf/tests/llvm.c3
-rw-r--r--tools/perf/tests/llvm.h1
-rw-r--r--tools/perf/tests/mem.c56
-rw-r--r--tools/perf/tests/mmap-basic.c3
-rw-r--r--tools/perf/tests/mmap-thread-lookup.c5
-rw-r--r--tools/perf/tests/openat-syscall-all-cpus.c5
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c3
-rw-r--r--tools/perf/tests/openat-syscall.c5
-rw-r--r--tools/perf/tests/parse-events.c3
-rw-r--r--tools/perf/tests/parse-no-sample-id-all.c3
-rw-r--r--tools/perf/tests/perf-hooks.c3
-rw-r--r--tools/perf/tests/perf-record.c3
-rwxr-xr-xtools/perf/tests/perf-targz-src-pkg1
-rw-r--r--tools/perf/tests/pmu.c3
-rw-r--r--tools/perf/tests/python-use.c3
-rw-r--r--tools/perf/tests/sample-parsing.c9
-rw-r--r--tools/perf/tests/sdt.c13
-rw-r--r--tools/perf/tests/shell/lib/probe.sh6
-rw-r--r--tools/perf/tests/shell/lib/probe_vfs_getname.sh23
-rwxr-xr-xtools/perf/tests/shell/probe_vfs_getname.sh14
-rwxr-xr-xtools/perf/tests/shell/record+script_probe_vfs_getname.sh41
-rwxr-xr-xtools/perf/tests/shell/trace+probe_libc_inet_pton.sh46
-rwxr-xr-xtools/perf/tests/shell/trace+probe_vfs_getname.sh35
-rw-r--r--tools/perf/tests/stat.c7
-rw-r--r--tools/perf/tests/sw-clock.c3
-rw-r--r--tools/perf/tests/switch-tracking.c3
-rw-r--r--tools/perf/tests/task-exit.c3
-rw-r--r--tools/perf/tests/tests.h115
-rw-r--r--tools/perf/tests/thread-map.c7
-rw-r--r--tools/perf/tests/thread-mg-share.c3
-rw-r--r--tools/perf/tests/topology.c25
-rw-r--r--tools/perf/tests/unit_number__scnprintf.c3
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c3
-rw-r--r--tools/perf/trace/beauty/Build8
-rw-r--r--tools/perf/trace/beauty/beauty.h93
-rw-r--r--tools/perf/trace/beauty/clone.c75
-rwxr-xr-xtools/perf/trace/beauty/drm_ioctl.sh13
-rw-r--r--tools/perf/trace/beauty/eventfd.c1
-rw-r--r--tools/perf/trace/beauty/fcntl.c100
-rw-r--r--tools/perf/trace/beauty/flock.c1
-rw-r--r--tools/perf/trace/beauty/futex_op.c1
-rw-r--r--tools/perf/trace/beauty/ioctl.c162
-rw-r--r--tools/perf/trace/beauty/kcmp.c44
-rwxr-xr-xtools/perf/trace/beauty/kcmp_type.sh10
-rwxr-xr-xtools/perf/trace/beauty/kvm_ioctl.sh11
-rwxr-xr-xtools/perf/trace/beauty/madvise_behavior.sh10
-rw-r--r--tools/perf/trace/beauty/mmap.c42
-rw-r--r--tools/perf/trace/beauty/mode_t.c1
-rw-r--r--tools/perf/trace/beauty/msg_flags.c1
-rw-r--r--tools/perf/trace/beauty/open_flags.c30
-rw-r--r--tools/perf/trace/beauty/perf_event_open.c1
-rwxr-xr-xtools/perf/trace/beauty/perf_ioctl.sh10
-rw-r--r--tools/perf/trace/beauty/pid.c5
-rw-r--r--tools/perf/trace/beauty/pkey_alloc.c50
-rwxr-xr-xtools/perf/trace/beauty/pkey_alloc_access_rights.sh10
-rw-r--r--tools/perf/trace/beauty/prctl.c82
-rwxr-xr-xtools/perf/trace/beauty/prctl_option.sh17
-rw-r--r--tools/perf/trace/beauty/sched_policy.c1
-rw-r--r--tools/perf/trace/beauty/seccomp.c1
-rw-r--r--tools/perf/trace/beauty/signum.c1
-rwxr-xr-xtools/perf/trace/beauty/sndrv_ctl_ioctl.sh8
-rwxr-xr-xtools/perf/trace/beauty/sndrv_pcm_ioctl.sh8
-rw-r--r--tools/perf/trace/beauty/socket_type.c1
-rwxr-xr-xtools/perf/trace/beauty/vhost_virtio_ioctl.sh17
-rw-r--r--tools/perf/trace/beauty/waitid_options.c1
-rw-r--r--tools/perf/ui/browser.c33
-rw-r--r--tools/perf/ui/browser.h3
-rw-r--r--tools/perf/ui/browsers/annotate.c98
-rw-r--r--tools/perf/ui/browsers/header.c1
-rw-r--r--tools/perf/ui/browsers/hists.c192
-rw-r--r--tools/perf/ui/browsers/hists.h1
-rw-r--r--tools/perf/ui/browsers/map.c1
-rw-r--r--tools/perf/ui/browsers/map.h1
-rw-r--r--tools/perf/ui/browsers/scripts.c1
-rw-r--r--tools/perf/ui/gtk/annotate.c7
-rw-r--r--tools/perf/ui/gtk/browser.c1
-rw-r--r--tools/perf/ui/gtk/gtk.h1
-rw-r--r--tools/perf/ui/gtk/helpline.c1
-rw-r--r--tools/perf/ui/gtk/hists.c1
-rw-r--r--tools/perf/ui/gtk/progress.c1
-rw-r--r--tools/perf/ui/gtk/setup.c1
-rw-r--r--tools/perf/ui/gtk/util.c1
-rw-r--r--tools/perf/ui/helpline.c1
-rw-r--r--tools/perf/ui/helpline.h1
-rw-r--r--tools/perf/ui/hist.c10
-rw-r--r--tools/perf/ui/keysyms.h1
-rw-r--r--tools/perf/ui/libslang.h1
-rw-r--r--tools/perf/ui/progress.c16
-rw-r--r--tools/perf/ui/progress.h13
-rw-r--r--tools/perf/ui/setup.c1
-rw-r--r--tools/perf/ui/stdio/hist.c94
-rw-r--r--tools/perf/ui/tui/helpline.c1
-rw-r--r--tools/perf/ui/tui/progress.c33
-rw-r--r--tools/perf/ui/tui/setup.c1
-rw-r--r--tools/perf/ui/tui/tui.h1
-rw-r--r--tools/perf/ui/tui/util.c1
-rw-r--r--tools/perf/ui/ui.h1
-rw-r--r--tools/perf/ui/util.c1
-rw-r--r--tools/perf/ui/util.h1
-rw-r--r--tools/perf/util/Build9
-rwxr-xr-xtools/perf/util/PERF-VERSION-GEN1
-rw-r--r--tools/perf/util/annotate.c149
-rw-r--r--tools/perf/util/annotate.h23
-rw-r--r--tools/perf/util/auxtrace.c4
-rw-r--r--tools/perf/util/auxtrace.h4
-rw-r--r--tools/perf/util/block-range.c1
-rw-r--r--tools/perf/util/block-range.h1
-rw-r--r--tools/perf/util/bpf-loader.c3
-rw-r--r--tools/perf/util/bpf-loader.h1
-rw-r--r--tools/perf/util/bpf-prologue.c50
-rw-r--r--tools/perf/util/bpf-prologue.h1
-rw-r--r--tools/perf/util/branch.c147
-rw-r--r--tools/perf/util/branch.h25
-rw-r--r--tools/perf/util/build-id.c130
-rw-r--r--tools/perf/util/build-id.h17
-rw-r--r--tools/perf/util/c++/clang-c.h1
-rw-r--r--tools/perf/util/c++/clang-test.cpp1
-rw-r--r--tools/perf/util/c++/clang.cpp1
-rw-r--r--tools/perf/util/c++/clang.h1
-rw-r--r--tools/perf/util/cache.h1
-rw-r--r--tools/perf/util/callchain.c417
-rw-r--r--tools/perf/util/callchain.h17
-rw-r--r--tools/perf/util/cgroup.c9
-rw-r--r--tools/perf/util/cgroup.h1
-rw-r--r--tools/perf/util/cloexec.c1
-rw-r--r--tools/perf/util/cloexec.h1
-rw-r--r--tools/perf/util/color.c1
-rw-r--r--tools/perf/util/color.h1
-rw-r--r--tools/perf/util/comm.c19
-rw-r--r--tools/perf/util/comm.h1
-rw-r--r--tools/perf/util/compress.h1
-rw-r--r--tools/perf/util/config.c19
-rw-r--r--tools/perf/util/config.h1
-rw-r--r--tools/perf/util/counts.c1
-rw-r--r--tools/perf/util/counts.h2
-rw-r--r--tools/perf/util/cpumap.c1
-rw-r--r--tools/perf/util/cpumap.h1
-rw-r--r--tools/perf/util/ctype.c1
-rw-r--r--tools/perf/util/data-convert-bt.c139
-rw-r--r--tools/perf/util/data-convert-bt.h1
-rw-r--r--tools/perf/util/data-convert.h1
-rw-r--r--tools/perf/util/data.c107
-rw-r--r--tools/perf/util/data.h39
-rw-r--r--tools/perf/util/debug.c32
-rw-r--r--tools/perf/util/debug.h1
-rw-r--r--tools/perf/util/demangle-java.c1
-rw-r--r--tools/perf/util/demangle-java.h1
-rw-r--r--tools/perf/util/demangle-rust.c1
-rw-r--r--tools/perf/util/demangle-rust.h1
-rw-r--r--tools/perf/util/dso.c42
-rw-r--r--tools/perf/util/dso.h10
-rw-r--r--tools/perf/util/dump-insn.c1
-rw-r--r--tools/perf/util/dump-insn.h1
-rw-r--r--tools/perf/util/dwarf-regs.c1
-rw-r--r--tools/perf/util/env.c1
-rw-r--r--tools/perf/util/env.h1
-rw-r--r--tools/perf/util/event.c164
-rw-r--r--tools/perf/util/event.h16
-rw-r--r--tools/perf/util/evlist.c264
-rw-r--r--tools/perf/util/evlist.h92
-rw-r--r--tools/perf/util/evsel.c246
-rw-r--r--tools/perf/util/evsel.h18
-rw-r--r--tools/perf/util/evsel_fprintf.c38
-rw-r--r--tools/perf/util/expr.h3
-rw-r--r--tools/perf/util/expr.y76
-rw-r--r--tools/perf/util/find-vdso-map.c1
-rw-r--r--tools/perf/util/genelf.h1
-rwxr-xr-xtools/perf/util/generate-cmdlist.sh1
-rw-r--r--tools/perf/util/group.h1
-rw-r--r--tools/perf/util/header.c1035
-rw-r--r--tools/perf/util/header.h17
-rw-r--r--tools/perf/util/help-unknown-cmd.c1
-rw-r--r--tools/perf/util/hist.c19
-rw-r--r--tools/perf/util/hist.h2
-rw-r--r--tools/perf/util/include/asm/asm-offsets.h1
-rw-r--r--tools/perf/util/include/asm/cpufeature.h1
-rw-r--r--tools/perf/util/include/asm/dwarf2.h1
-rw-r--r--tools/perf/util/include/asm/uaccess.h1
-rw-r--r--tools/perf/util/include/dwarf-regs.h1
-rw-r--r--tools/perf/util/include/linux/linkage.h1
-rw-r--r--tools/perf/util/intel-bts.c6
-rw-r--r--tools/perf/util/intel-pt-decoder/Build2
-rw-r--r--tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk1
-rw-r--r--tools/perf/util/intel-pt.c6
-rw-r--r--tools/perf/util/intlist.h1
-rw-r--r--tools/perf/util/jit.h3
-rw-r--r--tools/perf/util/jitdump.c11
-rw-r--r--tools/perf/util/kvm-stat.h1
-rw-r--r--tools/perf/util/levenshtein.c1
-rw-r--r--tools/perf/util/levenshtein.h1
-rw-r--r--tools/perf/util/libunwind/arm64.c1
-rw-r--r--tools/perf/util/libunwind/x86_32.c1
-rw-r--r--tools/perf/util/llvm-utils.c3
-rw-r--r--tools/perf/util/llvm-utils.h1
-rw-r--r--tools/perf/util/lzma.c1
-rw-r--r--tools/perf/util/machine.c353
-rw-r--r--tools/perf/util/machine.h34
-rw-r--r--tools/perf/util/map.c58
-rw-r--r--tools/perf/util/map.h6
-rw-r--r--tools/perf/util/mem-events.c55
-rw-r--r--tools/perf/util/mem-events.h1
-rw-r--r--tools/perf/util/memswap.c1
-rw-r--r--tools/perf/util/memswap.h1
-rw-r--r--tools/perf/util/metricgroup.c490
-rw-r--r--tools/perf/util/metricgroup.h31
-rw-r--r--tools/perf/util/mmap.c352
-rw-r--r--tools/perf/util/mmap.h97
-rw-r--r--tools/perf/util/namespaces.c212
-rw-r--r--tools/perf/util/namespaces.h43
-rw-r--r--tools/perf/util/ordered-events.c1
-rw-r--r--tools/perf/util/ordered-events.h1
-rw-r--r--tools/perf/util/parse-branch-options.c2
-rw-r--r--tools/perf/util/parse-branch-options.h1
-rw-r--r--tools/perf/util/parse-events.c153
-rw-r--r--tools/perf/util/parse-events.h23
-rw-r--r--tools/perf/util/parse-events.l44
-rw-r--r--tools/perf/util/parse-events.y94
-rw-r--r--tools/perf/util/parse-regs-options.c1
-rw-r--r--tools/perf/util/parse-regs-options.h1
-rw-r--r--tools/perf/util/path.c1
-rw-r--r--tools/perf/util/path.h1
-rw-r--r--tools/perf/util/perf-hooks.c1
-rw-r--r--tools/perf/util/perf-hooks.h1
-rw-r--r--tools/perf/util/perf_regs.c1
-rw-r--r--tools/perf/util/perf_regs.h1
-rw-r--r--tools/perf/util/pmu.c112
-rw-r--r--tools/perf/util/pmu.h4
-rw-r--r--tools/perf/util/print_binary.c31
-rw-r--r--tools/perf/util/print_binary.h19
-rw-r--r--tools/perf/util/probe-event.c88
-rw-r--r--tools/perf/util/probe-event.h11
-rw-r--r--tools/perf/util/probe-file.c20
-rw-r--r--tools/perf/util/probe-file.h5
-rw-r--r--tools/perf/util/probe-finder.h1
-rw-r--r--tools/perf/util/pstack.c1
-rw-r--r--tools/perf/util/pstack.h1
-rw-r--r--tools/perf/util/python-ext-sources2
-rw-r--r--tools/perf/util/python.c1
-rw-r--r--tools/perf/util/quote.c1
-rw-r--r--tools/perf/util/quote.h1
-rw-r--r--tools/perf/util/rb_resort.h6
-rw-r--r--tools/perf/util/rblist.h1
-rw-r--r--tools/perf/util/record.c1
-rw-r--r--tools/perf/util/rwsem.c32
-rw-r--r--tools/perf/util/rwsem.h19
-rw-r--r--tools/perf/util/sane_ctype.h1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c246
-rw-r--r--tools/perf/util/session.c81
-rw-r--r--tools/perf/util/session.h7
-rw-r--r--tools/perf/util/setns.c8
-rw-r--r--tools/perf/util/smt.c44
-rw-r--r--tools/perf/util/smt.h6
-rw-r--r--tools/perf/util/sort.c51
-rw-r--r--tools/perf/util/sort.h3
-rw-r--r--tools/perf/util/srcline.c303
-rw-r--r--tools/perf/util/srcline.h27
-rw-r--r--tools/perf/util/stat-shadow.c165
-rw-r--r--tools/perf/util/stat.c27
-rw-r--r--tools/perf/util/stat.h12
-rw-r--r--tools/perf/util/strbuf.c1
-rw-r--r--tools/perf/util/strbuf.h1
-rw-r--r--tools/perf/util/strfilter.c1
-rw-r--r--tools/perf/util/strfilter.h1
-rw-r--r--tools/perf/util/string.c1
-rw-r--r--tools/perf/util/string2.h1
-rw-r--r--tools/perf/util/strlist.h1
-rw-r--r--tools/perf/util/svghelper.h1
-rw-r--r--tools/perf/util/symbol-elf.c32
-rw-r--r--tools/perf/util/symbol-minimal.c3
-rw-r--r--tools/perf/util/symbol.c123
-rw-r--r--tools/perf/util/symbol.h8
-rw-r--r--tools/perf/util/symbol_fprintf.c1
-rw-r--r--tools/perf/util/syscalltbl.c35
-rw-r--r--tools/perf/util/syscalltbl.h4
-rw-r--r--tools/perf/util/target.h1
-rw-r--r--tools/perf/util/term.c1
-rw-r--r--tools/perf/util/term.h1
-rw-r--r--tools/perf/util/thread.c61
-rw-r--r--tools/perf/util/thread.h5
-rw-r--r--tools/perf/util/thread_map.c1
-rw-r--r--tools/perf/util/thread_map.h1
-rw-r--r--tools/perf/util/time-utils.c1
-rw-r--r--tools/perf/util/time-utils.h1
-rw-r--r--tools/perf/util/tool.h11
-rw-r--r--tools/perf/util/top.h2
-rw-r--r--tools/perf/util/trace-event-info.c1
-rw-r--r--tools/perf/util/trace-event-read.c1
-rw-r--r--tools/perf/util/trace-event.c1
-rw-r--r--tools/perf/util/trace-event.h1
-rw-r--r--tools/perf/util/trigger.h1
-rw-r--r--tools/perf/util/tsc.c1
-rw-r--r--tools/perf/util/tsc.h1
-rw-r--r--tools/perf/util/units.c1
-rw-r--r--tools/perf/util/units.h1
-rw-r--r--tools/perf/util/unwind-libdw.c1
-rw-r--r--tools/perf/util/unwind-libdw.h1
-rw-r--r--tools/perf/util/unwind-libunwind-local.c1
-rw-r--r--tools/perf/util/unwind-libunwind.c1
-rw-r--r--tools/perf/util/unwind.h1
-rw-r--r--tools/perf/util/usage.c1
-rw-r--r--tools/perf/util/util-cxx.h1
-rw-r--r--tools/perf/util/util.c57
-rw-r--r--tools/perf/util/util.h16
-rw-r--r--tools/perf/util/values.c18
-rw-r--r--tools/perf/util/values.h1
-rw-r--r--tools/perf/util/vdso.c5
-rw-r--r--tools/perf/util/vdso.h1
-rw-r--r--tools/perf/util/xyarray.c3
-rw-r--r--tools/perf/util/xyarray.h13
-rw-r--r--tools/perf/util/zlib.c2
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslinuxtbl.c105
-rw-r--r--tools/power/acpi/tools/acpidump/Makefile1
-rw-r--r--tools/power/acpi/tools/acpidump/apdump.c3
-rw-r--r--tools/power/acpi/tools/acpidump/apfiles.c2
-rw-r--r--tools/power/acpi/tools/acpidump/apmain.c6
-rw-r--r--tools/power/cpupower/.gitignore3
-rw-r--r--tools/power/cpupower/Makefile8
-rw-r--r--tools/power/cpupower/bench/Makefile1
-rw-r--r--tools/power/cpupower/debug/i386/Makefile1
-rw-r--r--tools/power/cpupower/debug/kernel/Makefile1
-rw-r--r--tools/power/cpupower/debug/x86_64/Makefile1
-rw-r--r--tools/power/cpupower/lib/cpuidle.h1
-rw-r--r--tools/power/cpupower/lib/cpupower.h1
-rw-r--r--tools/power/cpupower/lib/cpupower_intern.h1
-rw-r--r--tools/power/cpupower/utils/builtin.h1
-rw-r--r--tools/power/cpupower/utils/cpufreq-info.c2
-rw-r--r--tools/power/cpupower/utils/cpuidle-set.c1
-rw-r--r--tools/power/cpupower/utils/cpupower.c15
-rw-r--r--tools/power/cpupower/utils/helpers/amd.c1
-rw-r--r--tools/power/cpupower/utils/helpers/bitmask.c1
-rw-r--r--tools/power/cpupower/utils/helpers/bitmask.h1
-rw-r--r--tools/power/cpupower/utils/helpers/cpuid.c5
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h5
-rw-r--r--tools/power/cpupower/utils/helpers/misc.c3
-rw-r--r--tools/power/cpupower/utils/helpers/msr.c1
-rw-r--r--tools/power/cpupower/utils/helpers/pci.c1
-rw-r--r--tools/power/cpupower/utils/helpers/sysfs.h1
-rw-r--r--tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c4
-rw-r--r--tools/power/cpupower/utils/idle_monitor/mperf_monitor.c3
-rw-r--r--tools/power/cpupower/utils/idle_monitor/nhm_idle.c8
-rw-r--r--tools/power/cpupower/utils/idle_monitor/snb_idle.c4
-rwxr-xr-xtools/power/cpupower/utils/version-gen.sh1
-rw-r--r--tools/power/pm-graph/Makefile20
-rwxr-xr-xtools/power/pm-graph/analyze_boot.py586
-rwxr-xr-xtools/power/pm-graph/analyze_suspend.py534
-rw-r--r--tools/power/pm-graph/bootgraph.861
-rw-r--r--tools/power/pm-graph/sleepgraph.848
-rw-r--r--tools/power/x86/turbostat/Makefile1
-rw-r--r--tools/power/x86/turbostat/turbostat.c10
-rw-r--r--tools/power/x86/x86_energy_perf_policy/Makefile1
-rw-r--r--tools/scripts/Makefile.arch1
-rw-r--r--tools/scripts/Makefile.include7
-rw-r--r--tools/spi/Build2
-rw-r--r--tools/spi/Makefile64
-rw-r--r--tools/spi/spidev_fdx.c1
-rw-r--r--tools/testing/fault-injection/failcmd.sh1
-rwxr-xr-xtools/testing/ktest/compare-ktest-sample.pl1
-rw-r--r--tools/testing/nvdimm/Kbuild2
-rw-r--r--tools/testing/nvdimm/Makefile1
-rw-r--r--tools/testing/nvdimm/config_check.c1
-rw-r--r--tools/testing/nvdimm/test/Kbuild1
-rw-r--r--tools/testing/nvdimm/test/nfit.c326
-rw-r--r--tools/testing/nvdimm/test/nfit_test.h52
-rw-r--r--tools/testing/radix-tree/Makefile1
-rw-r--r--tools/testing/radix-tree/linux.c1
-rw-r--r--tools/testing/radix-tree/linux/gfp.h1
-rw-r--r--tools/testing/radix-tree/linux/kernel.h1
-rw-r--r--tools/testing/radix-tree/linux/percpu.h1
-rw-r--r--tools/testing/radix-tree/linux/preempt.h1
-rw-r--r--tools/testing/radix-tree/linux/radix-tree.h1
-rw-r--r--tools/testing/radix-tree/linux/rcupdate.h1
-rw-r--r--tools/testing/radix-tree/linux/slab.h1
-rw-r--r--tools/testing/radix-tree/main.c1
-rw-r--r--tools/testing/radix-tree/multiorder.c2
-rw-r--r--tools/testing/radix-tree/regression.h1
-rw-r--r--tools/testing/radix-tree/regression1.c1
-rw-r--r--tools/testing/radix-tree/regression2.c1
-rw-r--r--tools/testing/radix-tree/regression3.c1
-rw-r--r--tools/testing/radix-tree/tag_check.c1
-rw-r--r--tools/testing/radix-tree/test.c1
-rw-r--r--tools/testing/radix-tree/test.h1
-rw-r--r--tools/testing/scatterlist/Makefile30
-rw-r--r--tools/testing/scatterlist/linux/mm.h125
-rw-r--r--tools/testing/scatterlist/main.c79
-rw-r--r--tools/testing/selftests/Makefile22
-rw-r--r--tools/testing/selftests/android/Makefile46
-rw-r--r--tools/testing/selftests/android/ion/.gitignore2
-rw-r--r--tools/testing/selftests/android/ion/Makefile16
-rw-r--r--tools/testing/selftests/android/ion/README101
-rw-r--r--tools/testing/selftests/android/ion/config4
-rw-r--r--tools/testing/selftests/android/ion/ion.h143
-rwxr-xr-xtools/testing/selftests/android/ion/ion_test.sh55
-rw-r--r--tools/testing/selftests/android/ion/ionapp_export.c135
-rw-r--r--tools/testing/selftests/android/ion/ionapp_import.c88
-rw-r--r--tools/testing/selftests/android/ion/ionutils.c259
-rw-r--r--tools/testing/selftests/android/ion/ionutils.h55
-rw-r--r--tools/testing/selftests/android/ion/ipcsocket.c227
-rw-r--r--tools/testing/selftests/android/ion/ipcsocket.h35
-rwxr-xr-xtools/testing/selftests/android/run.sh3
-rw-r--r--tools/testing/selftests/bpf/Makefile26
-rw-r--r--tools/testing/selftests/bpf/bpf_endian.h1
-rw-r--r--tools/testing/selftests/bpf/bpf_helpers.h77
-rw-r--r--tools/testing/selftests/bpf/bpf_util.h18
-rw-r--r--tools/testing/selftests/bpf/cgroup_helpers.c178
-rw-r--r--tools/testing/selftests/bpf/cgroup_helpers.h17
-rw-r--r--tools/testing/selftests/bpf/dev_cgroup.c60
-rw-r--r--tools/testing/selftests/bpf/include/uapi/linux/types.h1
-rw-r--r--tools/testing/selftests/bpf/sockmap_parse_prog.c35
-rw-r--r--tools/testing/selftests/bpf/sockmap_verdict_prog.c66
-rw-r--r--tools/testing/selftests/bpf/test_align.c462
-rw-r--r--tools/testing/selftests/bpf/test_dev_cgroup.c93
-rwxr-xr-xtools/testing/selftests/bpf/test_kmod.sh1
-rw-r--r--tools/testing/selftests/bpf/test_lpm_map.c202
-rw-r--r--tools/testing/selftests/bpf/test_maps.c500
-rw-r--r--tools/testing/selftests/bpf/test_pkt_md_access.c11
-rw-r--r--tools/testing/selftests/bpf/test_progs.c256
-rw-r--r--tools/testing/selftests/bpf/test_tag.c1
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c2549
-rw-r--r--tools/testing/selftests/bpf/test_verifier_log.c171
-rw-r--r--tools/testing/selftests/bpf/test_xdp_meta.c53
-rwxr-xr-xtools/testing/selftests/bpf/test_xdp_meta.sh51
-rw-r--r--tools/testing/selftests/bpf/test_xdp_redirect.c28
-rwxr-xr-xtools/testing/selftests/bpf/test_xdp_redirect.sh59
-rw-r--r--tools/testing/selftests/breakpoints/Makefile9
-rw-r--r--tools/testing/selftests/breakpoints/breakpoint_test.c4
-rw-r--r--tools/testing/selftests/breakpoints/breakpoint_test_arm64.c1
-rw-r--r--tools/testing/selftests/capabilities/Makefile1
-rw-r--r--tools/testing/selftests/capabilities/test_execve.c194
-rw-r--r--tools/testing/selftests/capabilities/validate_cap.c25
-rw-r--r--tools/testing/selftests/cpu-hotplug/Makefile1
-rw-r--r--tools/testing/selftests/cpu-hotplug/config1
-rwxr-xr-xtools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh15
-rw-r--r--tools/testing/selftests/cpufreq/Makefile1
-rwxr-xr-xtools/testing/selftests/cpufreq/cpu.sh1
-rwxr-xr-xtools/testing/selftests/cpufreq/cpufreq.sh1
-rwxr-xr-xtools/testing/selftests/cpufreq/governor.sh1
-rwxr-xr-xtools/testing/selftests/cpufreq/main.sh1
-rwxr-xr-xtools/testing/selftests/cpufreq/module.sh1
-rwxr-xr-xtools/testing/selftests/cpufreq/special-tests.sh1
-rwxr-xr-xtools/testing/selftests/drivers/gpu/drm_mm.sh1
-rwxr-xr-xtools/testing/selftests/drivers/gpu/i915.sh1
-rw-r--r--tools/testing/selftests/efivarfs/create-read.c1
-rwxr-xr-xtools/testing/selftests/efivarfs/efivarfs.sh1
-rw-r--r--tools/testing/selftests/efivarfs/open-unlink.c1
-rw-r--r--tools/testing/selftests/exec/Makefile1
-rw-r--r--tools/testing/selftests/exec/execveat.c27
-rw-r--r--tools/testing/selftests/filesystems/Makefile1
-rw-r--r--tools/testing/selftests/filesystems/dnotify_test.c1
-rwxr-xr-xtools/testing/selftests/firmware/fw_fallback.sh68
-rwxr-xr-xtools/testing/selftests/firmware/fw_filesystem.sh276
-rw-r--r--tools/testing/selftests/ftrace/Makefile1
-rw-r--r--tools/testing/selftests/ftrace/config4
-rwxr-xr-xtools/testing/selftests/ftrace/ftracetest58
-rw-r--r--tools/testing/selftests/ftrace/test.d/00basic/basic2.tc1
-rw-r--r--tools/testing/selftests/ftrace/test.d/00basic/basic3.tc1
-rw-r--r--tools/testing/selftests/ftrace/test.d/00basic/basic4.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/event-enable.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/event-pid.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc1
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc6
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc5
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/instances/instance-event.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/instances/instance.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc1
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc1
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc1
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_module.tc1
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_maxactive.tc1
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/template1
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc3
-rw-r--r--tools/testing/selftests/futex/Makefile10
-rw-r--r--tools/testing/selftests/futex/functional/Makefile1
-rw-r--r--tools/testing/selftests/futex/functional/futex_requeue_pi.c8
-rw-r--r--tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c3
-rw-r--r--tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c5
-rw-r--r--tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c6
-rw-r--r--tools/testing/selftests/futex/functional/futex_wait_timeout.c5
-rw-r--r--tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c3
-rw-r--r--tools/testing/selftests/futex/functional/futex_wait_wouldblock.c3
-rw-r--r--tools/testing/selftests/futex/include/logging.h20
-rw-r--r--tools/testing/selftests/gpio/Makefile1
-rwxr-xr-xtools/testing/selftests/gpio/gpio-mockup-sysfs.sh1
-rwxr-xr-xtools/testing/selftests/gpio/gpio-mockup.sh1
-rw-r--r--tools/testing/selftests/ia64/Makefile1
-rw-r--r--tools/testing/selftests/intel_pstate/Makefile3
-rw-r--r--tools/testing/selftests/intel_pstate/aperf.c1
-rw-r--r--tools/testing/selftests/intel_pstate/msr.c1
-rwxr-xr-xtools/testing/selftests/intel_pstate/run.sh12
-rw-r--r--tools/testing/selftests/ipc/Makefile1
-rw-r--r--tools/testing/selftests/ipc/msgque.c1
-rw-r--r--tools/testing/selftests/kcmp/kcmp_test.c61
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/kmod/kmod.sh4
-rw-r--r--tools/testing/selftests/kselftest.h30
-rw-r--r--tools/testing/selftests/kselftest_harness.h39
-rw-r--r--tools/testing/selftests/lib.mk63
-rwxr-xr-xtools/testing/selftests/lib/bitmap.sh1
-rwxr-xr-xtools/testing/selftests/lib/prime_numbers.sh1
-rwxr-xr-xtools/testing/selftests/lib/printf.sh1
-rw-r--r--tools/testing/selftests/locking/ww_mutex.sh1
-rw-r--r--tools/testing/selftests/media_tests/Makefile1
-rwxr-xr-xtools/testing/selftests/media_tests/bind_unbind_sample.sh1
-rwxr-xr-xtools/testing/selftests/media_tests/open_loop_test.sh1
-rw-r--r--tools/testing/selftests/membarrier/membarrier_test.c1
-rw-r--r--tools/testing/selftests/memfd/Makefile3
-rw-r--r--tools/testing/selftests/memfd/fuse_mnt.c1
-rw-r--r--tools/testing/selftests/memfd/fuse_test.c3
-rw-r--r--tools/testing/selftests/memfd/memfd_test.c373
-rwxr-xr-xtools/testing/selftests/memfd/run_fuse_test.sh1
-rwxr-xr-xtools/testing/selftests/memfd/run_tests.sh69
-rw-r--r--tools/testing/selftests/memory-hotplug/Makefile5
-rwxr-xr-xtools/testing/selftests/memory-hotplug/mem-on-off-test.sh1
-rw-r--r--tools/testing/selftests/mount/Makefile1
-rw-r--r--tools/testing/selftests/mount/unprivileged-remount-test.c1
-rw-r--r--tools/testing/selftests/mqueue/Makefile5
-rw-r--r--tools/testing/selftests/net/.gitignore2
-rw-r--r--tools/testing/selftests/net/Makefile9
-rw-r--r--tools/testing/selftests/net/msg_zerocopy.c697
-rwxr-xr-xtools/testing/selftests/net/msg_zerocopy.sh112
-rwxr-xr-xtools/testing/selftests/net/netdevice.sh3
-rw-r--r--tools/testing/selftests/net/reuseaddr_conflict.c114
-rw-r--r--tools/testing/selftests/net/reuseport_bpf_cpu.c1
-rw-r--r--tools/testing/selftests/net/reuseport_bpf_numa.c1
-rw-r--r--tools/testing/selftests/net/reuseport_dualstack.c1
-rwxr-xr-xtools/testing/selftests/net/rtnetlink.sh543
-rwxr-xr-xtools/testing/selftests/net/run_afpackettests1
-rwxr-xr-xtools/testing/selftests/net/run_netsocktests1
-rw-r--r--tools/testing/selftests/net/socket.c1
-rwxr-xr-xtools/testing/selftests/net/test_bpf.sh1
-rw-r--r--tools/testing/selftests/networking/timestamping/.gitignore1
-rw-r--r--tools/testing/selftests/networking/timestamping/Makefile5
-rw-r--r--tools/testing/selftests/networking/timestamping/hwtstamp_config.c1
-rw-r--r--tools/testing/selftests/networking/timestamping/rxtimestamp.c389
-rw-r--r--tools/testing/selftests/nsfs/config3
-rw-r--r--tools/testing/selftests/nsfs/owner.c1
-rw-r--r--tools/testing/selftests/nsfs/pidns.c1
-rwxr-xr-xtools/testing/selftests/ntb/ntb_test.sh4
-rw-r--r--tools/testing/selftests/powerpc/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/context_switch.c17
-rw-r--r--tools/testing/selftests/powerpc/cache_shape/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/copyloops/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/copyloops/asm/export.h1
-rw-r--r--tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h1
-rw-r--r--tools/testing/selftests/powerpc/copyloops/validate.c1
-rw-r--r--tools/testing/selftests/powerpc/dscr/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/dscr/dscr.h2
-rw-r--r--tools/testing/selftests/powerpc/dscr/dscr_default_test.c2
-rw-r--r--tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c6
-rw-r--r--tools/testing/selftests/powerpc/include/basic_asm.h1
-rw-r--r--tools/testing/selftests/powerpc/include/instructions.h1
-rw-r--r--tools/testing/selftests/powerpc/math/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/mm/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/mm/hugetlb_vs_thp_test.c1
-rw-r--r--tools/testing/selftests/powerpc/pmu/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/ptrace/Makefile3
-rw-r--r--tools/testing/selftests/powerpc/signal/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/stringloops/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h1
-rw-r--r--tools/testing/selftests/powerpc/stringloops/memcmp.c1
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/check.S1
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/common.h1
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S3
-rw-r--r--tools/testing/selftests/powerpc/syscalls/ipc.h1
-rw-r--r--tools/testing/selftests/powerpc/tm/.gitignore1
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile5
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-resched-dscr.c13
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-syscall-asm.S1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-unavailable.c371
-rw-r--r--tools/testing/selftests/powerpc/tm/tm.h5
-rw-r--r--tools/testing/selftests/powerpc/vphn/test-vphn.c1
-rw-r--r--tools/testing/selftests/prctl/Makefile1
-rw-r--r--tools/testing/selftests/prctl/disable-tsc-ctxt-sw-stress-test.c1
-rw-r--r--tools/testing/selftests/prctl/disable-tsc-on-off-stress-test.c1
-rw-r--r--tools/testing/selftests/prctl/disable-tsc-test.c1
-rw-r--r--tools/testing/selftests/pstore/.gitignore2
-rw-r--r--tools/testing/selftests/pstore/Makefile1
-rw-r--r--tools/testing/selftests/ptp/Makefile2
-rw-r--r--tools/testing/selftests/ptrace/peeksiginfo.c1
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/config_override.sh61
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/configcheck.sh2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/configinit.sh2
-rw-r--r--tools/testing/selftests/rcutorture/bin/functions.sh27
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-build.sh13
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh60
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh38
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/parse-build.sh2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/parse-torture.sh2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-C.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-u3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot2
-rw-r--r--tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt2
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/Makefile1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h1
-rwxr-xr-xtools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/assume.h1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/barriers.h6
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/bug_on.h1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/combined_source.c1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/config.h1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/include_srcu.c1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/int_typedefs.h1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/locks.h1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.c1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/percpu.h1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.c1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/simple_sync_srcu.c1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/workqueues.h1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/Makefile1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/test.c1
-rwxr-xr-xtools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/test_script.sh1
-rw-r--r--tools/testing/selftests/seccomp/.gitignore1
-rw-r--r--tools/testing/selftests/seccomp/Makefile19
-rw-r--r--tools/testing/selftests/seccomp/seccomp_benchmark.c99
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c630
-rw-r--r--tools/testing/selftests/sigaltstack/sas.c58
-rw-r--r--tools/testing/selftests/splice/.gitignore1
-rw-r--r--tools/testing/selftests/splice/Makefile6
-rw-r--r--tools/testing/selftests/splice/default_file_splice_read.c1
-rwxr-xr-xtools/testing/selftests/splice/default_file_splice_read.sh1
-rwxr-xr-xtools/testing/selftests/static_keys/test_static_keys.sh1
-rw-r--r--tools/testing/selftests/sync/Makefile25
-rw-r--r--tools/testing/selftests/sync/sync_test.c71
-rw-r--r--tools/testing/selftests/sync/synctest.h3
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/sysctl/sysctl.sh0
-rw-r--r--tools/testing/selftests/tc-testing/.gitignore1
-rw-r--r--tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt12
-rw-r--r--tools/testing/selftests/tc-testing/creating-testcases/example.json55
-rw-r--r--tools/testing/selftests/tc-testing/creating-testcases/template.json15
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/gact.json469
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/ife.json52
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json223
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/police.json527
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/simple.json130
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json320
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json372
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/tests.json1115
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/tests.json23
-rwxr-xr-xtools/testing/selftests/tc-testing/tdc.py52
-rwxr-xr-xtools/testing/selftests/tc-testing/tdc_batch.py62
-rw-r--r--tools/testing/selftests/tc-testing/tdc_config.py17
-rw-r--r--tools/testing/selftests/tc-testing/tdc_config_local_template.py23
-rw-r--r--tools/testing/selftests/tc-testing/tdc_helper.py5
-rw-r--r--tools/testing/selftests/timers/.gitignore2
-rw-r--r--tools/testing/selftests/timers/Makefile24
-rw-r--r--tools/testing/selftests/timers/adjtick.c11
-rw-r--r--tools/testing/selftests/timers/alarmtimer-suspend.c11
-rw-r--r--tools/testing/selftests/timers/change_skew.c11
-rw-r--r--tools/testing/selftests/timers/clocksource-switch.c13
-rw-r--r--tools/testing/selftests/timers/freq-step.c15
-rw-r--r--tools/testing/selftests/timers/inconsistency-check.c11
-rw-r--r--tools/testing/selftests/timers/leap-a-day.c28
-rw-r--r--tools/testing/selftests/timers/leapcrash.c13
-rw-r--r--tools/testing/selftests/timers/mqueue-lat.c11
-rw-r--r--tools/testing/selftests/timers/nanosleep.c11
-rw-r--r--tools/testing/selftests/timers/nsleep-lat.c11
-rw-r--r--tools/testing/selftests/timers/raw_skew.c12
-rw-r--r--tools/testing/selftests/timers/rtctest.c7
-rw-r--r--tools/testing/selftests/timers/set-2038.c11
-rw-r--r--tools/testing/selftests/timers/set-tai.c11
-rw-r--r--tools/testing/selftests/timers/set-timer-lat.c117
-rw-r--r--tools/testing/selftests/timers/set-tz.c11
-rw-r--r--tools/testing/selftests/timers/skew_consistency.c11
-rw-r--r--tools/testing/selftests/timers/threadtest.c12
-rw-r--r--tools/testing/selftests/timers/valid-adjtimex.c11
-rwxr-xr-xtools/testing/selftests/user/test_user_copy.sh1
-rw-r--r--tools/testing/selftests/vDSO/Makefile1
-rw-r--r--tools/testing/selftests/vDSO/vdso_test.c19
-rw-r--r--tools/testing/selftests/vm/.gitignore2
-rw-r--r--tools/testing/selftests/vm/Makefile2
-rw-r--r--tools/testing/selftests/vm/compaction_test.c1
-rw-r--r--tools/testing/selftests/vm/gup_benchmark.c91
-rw-r--r--tools/testing/selftests/vm/hugepage-mmap.c1
-rw-r--r--tools/testing/selftests/vm/hugepage-shm.c1
-rw-r--r--tools/testing/selftests/vm/map_hugetlb.c1
-rw-r--r--tools/testing/selftests/vm/mlock-random-test.c1
-rw-r--r--tools/testing/selftests/vm/mlock2-tests.c1
-rw-r--r--tools/testing/selftests/vm/mlock2.h1
-rw-r--r--tools/testing/selftests/vm/on-fault-limit.c1
-rwxr-xr-xtools/testing/selftests/vm/run_vmtests1
-rw-r--r--tools/testing/selftests/vm/thuge-gen.c1
-rw-r--r--tools/testing/selftests/vm/userfaultfd.c300
-rw-r--r--tools/testing/selftests/watchdog/Makefile8
-rw-r--r--tools/testing/selftests/watchdog/watchdog-test.c191
-rw-r--r--tools/testing/selftests/x86/5lvl.c177
-rw-r--r--tools/testing/selftests/x86/Makefile5
-rw-r--r--tools/testing/selftests/x86/entry_from_vm86.c89
-rw-r--r--tools/testing/selftests/x86/fsgsbase.c41
-rw-r--r--tools/testing/selftests/x86/ioperm.c1
-rw-r--r--tools/testing/selftests/x86/iopl.c1
-rw-r--r--tools/testing/selftests/x86/ldt_gdt.c89
-rw-r--r--tools/testing/selftests/x86/mpx-debug.h1
-rw-r--r--tools/testing/selftests/x86/mpx-dig.c1
-rw-r--r--tools/testing/selftests/x86/mpx-hw.h5
-rw-r--r--tools/testing/selftests/x86/mpx-mini-test.c3
-rw-r--r--tools/testing/selftests/x86/mpx-mm.h1
-rw-r--r--tools/testing/selftests/x86/pkey-helpers.h6
-rw-r--r--tools/testing/selftests/x86/protection_keys.c48
-rw-r--r--tools/testing/selftests/x86/ptrace_syscall.c1
-rw-r--r--tools/testing/selftests/x86/raw_syscall_helper_32.S1
-rw-r--r--tools/testing/selftests/x86/test_FCMOV.c1
-rw-r--r--tools/testing/selftests/x86/test_FCOMI.c1
-rw-r--r--tools/testing/selftests/x86/test_FISTTP.c1
-rw-r--r--tools/testing/selftests/x86/test_vdso.c1
-rw-r--r--tools/testing/selftests/zram/Makefile1
-rwxr-xr-xtools/testing/selftests/zram/zram.sh1
-rw-r--r--tools/testing/vsock/.gitignore2
-rw-r--r--tools/testing/vsock/Makefile9
-rw-r--r--tools/testing/vsock/README36
-rw-r--r--tools/testing/vsock/control.c219
-rw-r--r--tools/testing/vsock/control.h13
-rw-r--r--tools/testing/vsock/timeout.c64
-rw-r--r--tools/testing/vsock/timeout.h14
-rw-r--r--tools/testing/vsock/vsock_diag_test.c681
-rw-r--r--tools/thermal/tmon/Makefile19
-rw-r--r--tools/thermal/tmon/tmon.81
-rw-r--r--tools/usb/Makefile1
-rw-r--r--tools/usb/ffs-aio-example/multibuff/host_app/Makefile1
-rw-r--r--tools/usb/hcd-tests.sh1
-rw-r--r--tools/usb/usbip/Makefile.am4
-rwxr-xr-xtools/usb/usbip/cleanup.sh1
-rw-r--r--tools/usb/usbip/libsrc/Makefile.am1
-rw-r--r--tools/usb/usbip/libsrc/list.h1
-rw-r--r--tools/usb/usbip/libsrc/sysfs_utils.c1
-rw-r--r--tools/usb/usbip/libsrc/sysfs_utils.h1
-rw-r--r--tools/usb/usbip/libsrc/usbip_common.c1
-rw-r--r--tools/usb/usbip/libsrc/usbip_common.h1
-rw-r--r--tools/usb/usbip/libsrc/vhci_driver.c1
-rw-r--r--tools/usb/usbip/libsrc/vhci_driver.h1
-rw-r--r--tools/usb/usbip/src/Makefile.am1
-rw-r--r--tools/usb/usbip/src/usbip_attach.c35
-rw-r--r--tools/usb/usbip/src/usbip_network.h1
-rw-r--r--tools/virtio/Makefile1
-rw-r--r--tools/virtio/asm/barrier.h1
-rw-r--r--tools/virtio/linux/bug.h1
-rw-r--r--tools/virtio/linux/compiler.h1
-rw-r--r--tools/virtio/linux/dma-mapping.h1
-rw-r--r--tools/virtio/linux/err.h1
-rw-r--r--tools/virtio/linux/kernel.h1
-rw-r--r--tools/virtio/linux/module.h1
-rw-r--r--tools/virtio/linux/scatterlist.h1
-rw-r--r--tools/virtio/linux/slab.h1
-rw-r--r--tools/virtio/linux/uaccess.h1
-rw-r--r--tools/virtio/linux/virtio.h1
-rw-r--r--tools/virtio/linux/virtio_byteorder.h1
-rw-r--r--tools/virtio/linux/virtio_config.h1
-rw-r--r--tools/virtio/ringtest/Makefile1
-rw-r--r--tools/virtio/ringtest/main.h4
-rw-r--r--tools/virtio/ringtest/noring.c1
-rw-r--r--tools/virtio/ringtest/ptr_ring.c1
-rwxr-xr-xtools/virtio/ringtest/run-on-all.sh1
-rw-r--r--tools/virtio/uapi/linux/virtio_ring.h1
-rw-r--r--tools/virtio/virtio-trace/Makefile1
-rw-r--r--tools/virtio/virtio-trace/trace-agent.h1
-rw-r--r--tools/virtio/virtio_test.c1
-rw-r--r--tools/virtio/vringh_test.c1
-rw-r--r--tools/vm/Makefile1
-rw-r--r--tools/vm/page_owner_sort.c1
-rw-r--r--tools/vm/slabinfo.c12
-rw-r--r--tools/wmi/Makefile18
-rw-r--r--tools/wmi/dell-smbios-example.c210
1405 files changed, 54072 insertions, 11121 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 221e1ce78b06..be02c8b904db 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# Some of the tools (perf) use same make variables 2# Some of the tools (perf) use same make variables
2# as in kernel build. 3# as in kernel build.
3export srctree= 4export srctree=
@@ -18,9 +19,8 @@ help:
18 @echo ' iio - IIO tools' 19 @echo ' iio - IIO tools'
19 @echo ' kvm_stat - top-like utility for displaying kvm statistics' 20 @echo ' kvm_stat - top-like utility for displaying kvm statistics'
20 @echo ' leds - LEDs tools' 21 @echo ' leds - LEDs tools'
21 @echo ' lguest - a minimal 32-bit x86 hypervisor'
22 @echo ' liblockdep - user-space wrapper for kernel locking-validator' 22 @echo ' liblockdep - user-space wrapper for kernel locking-validator'
23 @echo ' net - misc networking tools' 23 @echo ' bpf - misc BPF tools'
24 @echo ' perf - Linux performance measurement and analysis tool' 24 @echo ' perf - Linux performance measurement and analysis tool'
25 @echo ' selftests - various kernel selftests' 25 @echo ' selftests - various kernel selftests'
26 @echo ' spi - spi tools' 26 @echo ' spi - spi tools'
@@ -30,6 +30,7 @@ help:
30 @echo ' usb - USB testing tools' 30 @echo ' usb - USB testing tools'
31 @echo ' virtio - vhost test module' 31 @echo ' virtio - vhost test module'
32 @echo ' vm - misc vm tools' 32 @echo ' vm - misc vm tools'
33 @echo ' wmi - WMI interface examples'
33 @echo ' x86_energy_perf_policy - Intel energy policy tool' 34 @echo ' x86_energy_perf_policy - Intel energy policy tool'
34 @echo '' 35 @echo ''
35 @echo 'You can do:' 36 @echo 'You can do:'
@@ -58,7 +59,7 @@ acpi: FORCE
58cpupower: FORCE 59cpupower: FORCE
59 $(call descend,power/$@) 60 $(call descend,power/$@)
60 61
61cgroup firewire hv guest spi usb virtio vm net iio gpio objtool leds: FORCE 62cgroup firewire hv guest spi usb virtio vm bpf iio gpio objtool leds wmi: FORCE
62 $(call descend,$@) 63 $(call descend,$@)
63 64
64liblockdep: FORCE 65liblockdep: FORCE
@@ -90,10 +91,10 @@ freefall: FORCE
90kvm_stat: FORCE 91kvm_stat: FORCE
91 $(call descend,kvm/$@) 92 $(call descend,kvm/$@)
92 93
93all: acpi cgroup cpupower gpio hv firewire lguest liblockdep \ 94all: acpi cgroup cpupower gpio hv firewire liblockdep \
94 perf selftests turbostat usb \ 95 perf selftests spi turbostat usb \
95 virtio vm net x86_energy_perf_policy \ 96 virtio vm bpf x86_energy_perf_policy \
96 tmon freefall objtool kvm_stat 97 tmon freefall iio objtool kvm_stat wmi
97 98
98acpi_install: 99acpi_install:
99 $(call descend,power/$(@:_install=),install) 100 $(call descend,power/$(@:_install=),install)
@@ -101,7 +102,7 @@ acpi_install:
101cpupower_install: 102cpupower_install:
102 $(call descend,power/$(@:_install=),install) 103 $(call descend,power/$(@:_install=),install)
103 104
104cgroup_install firewire_install gpio_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install objtool_install: 105cgroup_install firewire_install gpio_install hv_install iio_install perf_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install:
105 $(call descend,$(@:_install=),install) 106 $(call descend,$(@:_install=),install)
106 107
107liblockdep_install: 108liblockdep_install:
@@ -123,10 +124,11 @@ kvm_stat_install:
123 $(call descend,kvm/$(@:_install=),install) 124 $(call descend,kvm/$(@:_install=),install)
124 125
125install: acpi_install cgroup_install cpupower_install gpio_install \ 126install: acpi_install cgroup_install cpupower_install gpio_install \
126 hv_install firewire_install lguest_install liblockdep_install \ 127 hv_install firewire_install iio_install liblockdep_install \
127 perf_install selftests_install turbostat_install usb_install \ 128 perf_install selftests_install turbostat_install usb_install \
128 virtio_install vm_install net_install x86_energy_perf_policy_install \ 129 virtio_install vm_install bpf_install x86_energy_perf_policy_install \
129 tmon_install freefall_install objtool_install kvm_stat_install 130 tmon_install freefall_install objtool_install kvm_stat_install \
131 wmi_install
130 132
131acpi_clean: 133acpi_clean:
132 $(call descend,power/acpi,clean) 134 $(call descend,power/acpi,clean)
@@ -134,7 +136,7 @@ acpi_clean:
134cpupower_clean: 136cpupower_clean:
135 $(call descend,power/cpupower,clean) 137 $(call descend,power/cpupower,clean)
136 138
137cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean gpio_clean objtool_clean leds_clean: 139cgroup_clean hv_clean firewire_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean:
138 $(call descend,$(@:_clean=),clean) 140 $(call descend,$(@:_clean=),clean)
139 141
140liblockdep_clean: 142liblockdep_clean:
@@ -168,10 +170,10 @@ freefall_clean:
168build_clean: 170build_clean:
169 $(call descend,build,clean) 171 $(call descend,build,clean)
170 172
171clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_clean \ 173clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean \
172 perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \ 174 perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \
173 vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ 175 vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
174 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \ 176 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \
175 gpio_clean objtool_clean leds_clean 177 gpio_clean objtool_clean leds_clean wmi_clean
176 178
177.PHONY: FORCE 179.PHONY: FORCE
diff --git a/tools/accounting/Makefile b/tools/accounting/Makefile
index 647c94a219bf..03687f19cbb1 100644
--- a/tools/accounting/Makefile
+++ b/tools/accounting/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1CC := $(CROSS_COMPILE)gcc 2CC := $(CROSS_COMPILE)gcc
2CFLAGS := -I../../usr/include 3CFLAGS := -I../../usr/include
3 4
diff --git a/tools/accounting/getdelays.c b/tools/accounting/getdelays.c
index b5ca536e56a8..9f420d98b5fb 100644
--- a/tools/accounting/getdelays.c
+++ b/tools/accounting/getdelays.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* getdelays.c 2/* getdelays.c
2 * 3 *
3 * Utility to get per-pid and per-tgid delay accounting statistics 4 * Utility to get per-pid and per-tgid delay accounting statistics
diff --git a/tools/arch/alpha/include/asm/barrier.h b/tools/arch/alpha/include/asm/barrier.h
index 95df19c95482..da8d6457ed4f 100644
--- a/tools/arch/alpha/include/asm/barrier.h
+++ b/tools/arch/alpha/include/asm/barrier.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __TOOLS_LINUX_ASM_ALPHA_BARRIER_H 2#ifndef __TOOLS_LINUX_ASM_ALPHA_BARRIER_H
2#define __TOOLS_LINUX_ASM_ALPHA_BARRIER_H 3#define __TOOLS_LINUX_ASM_ALPHA_BARRIER_H
3 4
diff --git a/tools/arch/alpha/include/uapi/asm/bitsperlong.h b/tools/arch/alpha/include/uapi/asm/bitsperlong.h
index ad57f7868203..6c5bf7d03f4e 100644
--- a/tools/arch/alpha/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/alpha/include/uapi/asm/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef __ASM_ALPHA_BITSPERLONG_H 2#ifndef __ASM_ALPHA_BITSPERLONG_H
2#define __ASM_ALPHA_BITSPERLONG_H 3#define __ASM_ALPHA_BITSPERLONG_H
3 4
diff --git a/tools/arch/alpha/include/uapi/asm/mman.h b/tools/arch/alpha/include/uapi/asm/mman.h
index e38b64c82b97..c317d3e6867a 100644
--- a/tools/arch/alpha/include/uapi/asm/mman.h
+++ b/tools/arch/alpha/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_ALPHA_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_ALPHA_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_ALPHA_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_ALPHA_UAPI_ASM_MMAN_FIX_H
3#define MADV_DODUMP 17 4#define MADV_DODUMP 17
diff --git a/tools/arch/arc/include/uapi/asm/mman.h b/tools/arch/arc/include/uapi/asm/mman.h
index aa3acd2aa9af..81f0f9bf0c25 100644
--- a/tools/arch/arc/include/uapi/asm/mman.h
+++ b/tools/arch/arc/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_ARC_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_ARC_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_ARC_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_ARC_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h> 4#include <uapi/asm-generic/mman.h>
diff --git a/tools/arch/arm/include/uapi/asm/kvm.h b/tools/arch/arm/include/uapi/asm/kvm.h
index 5e3c673fa3f4..1f57bbe82b6f 100644
--- a/tools/arch/arm/include/uapi/asm/kvm.h
+++ b/tools/arch/arm/include/uapi/asm/kvm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1/* 2/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University 3 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com> 4 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
@@ -203,6 +204,14 @@ struct kvm_arch_memory_slot {
203#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff 204#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
204#define VGIC_LEVEL_INFO_LINE_LEVEL 0 205#define VGIC_LEVEL_INFO_LINE_LEVEL 0
205 206
207/* Device Control API on vcpu fd */
208#define KVM_ARM_VCPU_PMU_V3_CTRL 0
209#define KVM_ARM_VCPU_PMU_V3_IRQ 0
210#define KVM_ARM_VCPU_PMU_V3_INIT 1
211#define KVM_ARM_VCPU_TIMER_CTRL 1
212#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
213#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
214
206#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 215#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
207#define KVM_DEV_ARM_ITS_SAVE_TABLES 1 216#define KVM_DEV_ARM_ITS_SAVE_TABLES 1
208#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 217#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2
diff --git a/tools/arch/arm/include/uapi/asm/mman.h b/tools/arch/arm/include/uapi/asm/mman.h
index 478f699f56fd..a6d46321e330 100644
--- a/tools/arch/arm/include/uapi/asm/mman.h
+++ b/tools/arch/arm/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_ARM_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_ARM_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_ARM_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_ARM_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h> 4#include <uapi/asm-generic/mman.h>
diff --git a/tools/arch/arm/include/uapi/asm/perf_regs.h b/tools/arch/arm/include/uapi/asm/perf_regs.h
index ce59448458b2..a3c046174e6b 100644
--- a/tools/arch/arm/include/uapi/asm/perf_regs.h
+++ b/tools/arch/arm/include/uapi/asm/perf_regs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _ASM_ARM_PERF_REGS_H 2#ifndef _ASM_ARM_PERF_REGS_H
2#define _ASM_ARM_PERF_REGS_H 3#define _ASM_ARM_PERF_REGS_H
3 4
diff --git a/tools/arch/arm64/include/asm/barrier.h b/tools/arch/arm64/include/asm/barrier.h
index a0483c8e0142..40bde6b23501 100644
--- a/tools/arch/arm64/include/asm/barrier.h
+++ b/tools/arch/arm64/include/asm/barrier.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_ASM_AARCH64_BARRIER_H 2#ifndef _TOOLS_LINUX_ASM_AARCH64_BARRIER_H
2#define _TOOLS_LINUX_ASM_AARCH64_BARRIER_H 3#define _TOOLS_LINUX_ASM_AARCH64_BARRIER_H
3 4
diff --git a/tools/arch/arm64/include/uapi/asm/bitsperlong.h b/tools/arch/arm64/include/uapi/asm/bitsperlong.h
index fce9c2924fa3..485d60bee26c 100644
--- a/tools/arch/arm64/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/arm64/include/uapi/asm/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1/* 2/*
2 * Copyright (C) 2012 ARM Ltd. 3 * Copyright (C) 2012 ARM Ltd.
3 * 4 *
diff --git a/tools/arch/arm64/include/uapi/asm/kvm.h b/tools/arch/arm64/include/uapi/asm/kvm.h
index 70eea2ecc663..51149ec75fe4 100644
--- a/tools/arch/arm64/include/uapi/asm/kvm.h
+++ b/tools/arch/arm64/include/uapi/asm/kvm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1/* 2/*
2 * Copyright (C) 2012,2013 - ARM Ltd 3 * Copyright (C) 2012,2013 - ARM Ltd
3 * Author: Marc Zyngier <marc.zyngier@arm.com> 4 * Author: Marc Zyngier <marc.zyngier@arm.com>
@@ -232,6 +233,9 @@ struct kvm_arch_memory_slot {
232#define KVM_ARM_VCPU_PMU_V3_CTRL 0 233#define KVM_ARM_VCPU_PMU_V3_CTRL 0
233#define KVM_ARM_VCPU_PMU_V3_IRQ 0 234#define KVM_ARM_VCPU_PMU_V3_IRQ 0
234#define KVM_ARM_VCPU_PMU_V3_INIT 1 235#define KVM_ARM_VCPU_PMU_V3_INIT 1
236#define KVM_ARM_VCPU_TIMER_CTRL 1
237#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
238#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
235 239
236/* KVM_IRQ_LINE irq field index values */ 240/* KVM_IRQ_LINE irq field index values */
237#define KVM_ARM_IRQ_TYPE_SHIFT 24 241#define KVM_ARM_IRQ_TYPE_SHIFT 24
diff --git a/tools/arch/arm64/include/uapi/asm/mman.h b/tools/arch/arm64/include/uapi/asm/mman.h
index 70fd3113710a..2ee288e447ec 100644
--- a/tools/arch/arm64/include/uapi/asm/mman.h
+++ b/tools/arch/arm64/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_ARM64_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_ARM64_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_ARM64_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_ARM64_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h> 4#include <uapi/asm-generic/mman.h>
diff --git a/tools/arch/arm64/include/uapi/asm/perf_regs.h b/tools/arch/arm64/include/uapi/asm/perf_regs.h
index 172b8317ee49..d54daafa89e3 100644
--- a/tools/arch/arm64/include/uapi/asm/perf_regs.h
+++ b/tools/arch/arm64/include/uapi/asm/perf_regs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _ASM_ARM64_PERF_REGS_H 2#ifndef _ASM_ARM64_PERF_REGS_H
2#define _ASM_ARM64_PERF_REGS_H 3#define _ASM_ARM64_PERF_REGS_H
3 4
diff --git a/tools/arch/frv/include/uapi/asm/bitsperlong.h b/tools/arch/frv/include/uapi/asm/bitsperlong.h
index 6dc0bb0c13b2..76da34b10f59 100644
--- a/tools/arch/frv/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/frv/include/uapi/asm/bitsperlong.h
@@ -1 +1,2 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#include <asm-generic/bitsperlong.h> 2#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
index 5be78ac12464..5bc900b0bc78 100644
--- a/tools/arch/frv/include/uapi/asm/mman.h
+++ b/tools/arch/frv/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_FRV_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_FRV_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_FRV_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_FRV_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h> 4#include <uapi/asm-generic/mman.h>
diff --git a/tools/arch/h8300/include/asm/bitsperlong.h b/tools/arch/h8300/include/asm/bitsperlong.h
index e140e46729ac..fa1508337ffc 100644
--- a/tools/arch/h8300/include/asm/bitsperlong.h
+++ b/tools/arch/h8300/include/asm/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __ASM_H8300_BITS_PER_LONG 2#ifndef __ASM_H8300_BITS_PER_LONG
2#define __ASM_H8300_BITS_PER_LONG 3#define __ASM_H8300_BITS_PER_LONG
3 4
diff --git a/tools/arch/h8300/include/uapi/asm/mman.h b/tools/arch/h8300/include/uapi/asm/mman.h
index 9d9ac54d3c5a..be7bbe0528d1 100644
--- a/tools/arch/h8300/include/uapi/asm/mman.h
+++ b/tools/arch/h8300/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_H8300_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_H8300_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_H8300_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_H8300_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h> 4#include <uapi/asm-generic/mman.h>
diff --git a/tools/arch/hexagon/include/uapi/asm/bitsperlong.h b/tools/arch/hexagon/include/uapi/asm/bitsperlong.h
index 4a658151383d..5adca0d26913 100644
--- a/tools/arch/hexagon/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/hexagon/include/uapi/asm/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1/* 2/*
2 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
3 * 4 *
diff --git a/tools/arch/hexagon/include/uapi/asm/mman.h b/tools/arch/hexagon/include/uapi/asm/mman.h
index 102f3fae6085..cd59ba932b3a 100644
--- a/tools/arch/hexagon/include/uapi/asm/mman.h
+++ b/tools/arch/hexagon/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_HEXAGON_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_HEXAGON_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_HEXAGON_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_HEXAGON_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h> 4#include <uapi/asm-generic/mman.h>
diff --git a/tools/arch/ia64/include/asm/barrier.h b/tools/arch/ia64/include/asm/barrier.h
index e4422b4b634e..d808ee0e77b5 100644
--- a/tools/arch/ia64/include/asm/barrier.h
+++ b/tools/arch/ia64/include/asm/barrier.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Copied from the kernel sources to tools/: 3 * Copied from the kernel sources to tools/:
3 * 4 *
diff --git a/tools/arch/ia64/include/uapi/asm/bitsperlong.h b/tools/arch/ia64/include/uapi/asm/bitsperlong.h
index ec4db3c970b7..1146d55563db 100644
--- a/tools/arch/ia64/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/ia64/include/uapi/asm/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef __ASM_IA64_BITSPERLONG_H 2#ifndef __ASM_IA64_BITSPERLONG_H
2#define __ASM_IA64_BITSPERLONG_H 3#define __ASM_IA64_BITSPERLONG_H
3 4
diff --git a/tools/arch/ia64/include/uapi/asm/mman.h b/tools/arch/ia64/include/uapi/asm/mman.h
index 1d6e5ac6442d..2a19bb1db4ab 100644
--- a/tools/arch/ia64/include/uapi/asm/mman.h
+++ b/tools/arch/ia64/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_IA64_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_IA64_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_IA64_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_IA64_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h> 4#include <uapi/asm-generic/mman.h>
diff --git a/tools/arch/m32r/include/uapi/asm/bitsperlong.h b/tools/arch/m32r/include/uapi/asm/bitsperlong.h
index 6dc0bb0c13b2..76da34b10f59 100644
--- a/tools/arch/m32r/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/m32r/include/uapi/asm/bitsperlong.h
@@ -1 +1,2 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#include <asm-generic/bitsperlong.h> 2#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
index 1c29635bb73b..d19b82c9c290 100644
--- a/tools/arch/m32r/include/uapi/asm/mman.h
+++ b/tools/arch/m32r/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_M32R_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_M32R_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_M32R_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_M32R_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h> 4#include <uapi/asm-generic/mman.h>
diff --git a/tools/arch/microblaze/include/uapi/asm/bitsperlong.h b/tools/arch/microblaze/include/uapi/asm/bitsperlong.h
index 6dc0bb0c13b2..76da34b10f59 100644
--- a/tools/arch/microblaze/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/microblaze/include/uapi/asm/bitsperlong.h
@@ -1 +1,2 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#include <asm-generic/bitsperlong.h> 2#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
index 005cd50b50e1..f3f2103fd02c 100644
--- a/tools/arch/microblaze/include/uapi/asm/mman.h
+++ b/tools/arch/microblaze/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_MICROBLAZE_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_MICROBLAZE_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_MICROBLAZE_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_MICROBLAZE_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h> 4#include <uapi/asm-generic/mman.h>
diff --git a/tools/arch/mips/include/asm/barrier.h b/tools/arch/mips/include/asm/barrier.h
index 80f96f7556e3..0d1191523cd0 100644
--- a/tools/arch/mips/include/asm/barrier.h
+++ b/tools/arch/mips/include/asm/barrier.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_ASM_MIPS_BARRIER_H 2#ifndef _TOOLS_LINUX_ASM_MIPS_BARRIER_H
2#define _TOOLS_LINUX_ASM_MIPS_BARRIER_H 3#define _TOOLS_LINUX_ASM_MIPS_BARRIER_H
3/* 4/*
diff --git a/tools/arch/mips/include/uapi/asm/bitsperlong.h b/tools/arch/mips/include/uapi/asm/bitsperlong.h
index 3e4c10a8e787..7268380d8d28 100644
--- a/tools/arch/mips/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/mips/include/uapi/asm/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef __ASM_MIPS_BITSPERLONG_H 2#ifndef __ASM_MIPS_BITSPERLONG_H
2#define __ASM_MIPS_BITSPERLONG_H 3#define __ASM_MIPS_BITSPERLONG_H
3 4
diff --git a/tools/arch/mips/include/uapi/asm/kvm.h b/tools/arch/mips/include/uapi/asm/kvm.h
index 6985eb59b085..d2714cc1cd93 100644
--- a/tools/arch/mips/include/uapi/asm/kvm.h
+++ b/tools/arch/mips/include/uapi/asm/kvm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1/* 2/*
2 * This file is subject to the terms and conditions of the GNU General Public 3 * 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 * License. See the file "COPYING" in the main directory of this archive
diff --git a/tools/arch/mips/include/uapi/asm/mman.h b/tools/arch/mips/include/uapi/asm/mman.h
index c02052965d50..de2206883abc 100644
--- a/tools/arch/mips/include/uapi/asm/mman.h
+++ b/tools/arch/mips/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_MIPS_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_MIPS_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_MIPS_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_MIPS_UAPI_ASM_MMAN_FIX_H
3#define MADV_DODUMP 17 4#define MADV_DODUMP 17
diff --git a/tools/arch/mn10300/include/uapi/asm/mman.h b/tools/arch/mn10300/include/uapi/asm/mman.h
index c1ea36d83acc..b9360639974f 100644
--- a/tools/arch/mn10300/include/uapi/asm/mman.h
+++ b/tools/arch/mn10300/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_MN10300_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_MN10300_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_MN10300_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_MN10300_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h> 4#include <uapi/asm-generic/mman.h>
diff --git a/tools/arch/parisc/include/uapi/asm/bitsperlong.h b/tools/arch/parisc/include/uapi/asm/bitsperlong.h
index e0a23c7bdd43..23ac7562927a 100644
--- a/tools/arch/parisc/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/parisc/include/uapi/asm/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef __ASM_PARISC_BITSPERLONG_H 2#ifndef __ASM_PARISC_BITSPERLONG_H
2#define __ASM_PARISC_BITSPERLONG_H 3#define __ASM_PARISC_BITSPERLONG_H
3 4
diff --git a/tools/arch/parisc/include/uapi/asm/mman.h b/tools/arch/parisc/include/uapi/asm/mman.h
index 03d8d5b7ae7f..1bd78758bde9 100644
--- a/tools/arch/parisc/include/uapi/asm/mman.h
+++ b/tools/arch/parisc/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_PARISC_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_PARISC_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_PARISC_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_PARISC_UAPI_ASM_MMAN_FIX_H
3#define MADV_DODUMP 70 4#define MADV_DODUMP 70
@@ -36,9 +37,7 @@
36#define PROT_READ 0x1 37#define PROT_READ 0x1
37#define PROT_SEM 0x8 38#define PROT_SEM 0x8
38#define PROT_WRITE 0x2 39#define PROT_WRITE 0x2
39/* MADV_HWPOISON is undefined on parisc, fix it for perf */
40#define MADV_HWPOISON 100 40#define MADV_HWPOISON 100
41/* MADV_SOFT_OFFLINE is undefined on parisc, fix it for perf */
42#define MADV_SOFT_OFFLINE 101 41#define MADV_SOFT_OFFLINE 101
43/* MAP_32BIT is undefined on parisc, fix it for perf */ 42/* MAP_32BIT is undefined on parisc, fix it for perf */
44#define MAP_32BIT 0 43#define MAP_32BIT 0
diff --git a/tools/arch/powerpc/include/asm/barrier.h b/tools/arch/powerpc/include/asm/barrier.h
index b23aee8e6d90..a634da05bc97 100644
--- a/tools/arch/powerpc/include/asm/barrier.h
+++ b/tools/arch/powerpc/include/asm/barrier.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Copied from the kernel sources: 3 * Copied from the kernel sources:
3 * 4 *
diff --git a/tools/arch/powerpc/include/uapi/asm/bitsperlong.h b/tools/arch/powerpc/include/uapi/asm/bitsperlong.h
index 5f1659032c40..46ece3ecff31 100644
--- a/tools/arch/powerpc/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/powerpc/include/uapi/asm/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef __ASM_POWERPC_BITSPERLONG_H 2#ifndef __ASM_POWERPC_BITSPERLONG_H
2#define __ASM_POWERPC_BITSPERLONG_H 3#define __ASM_POWERPC_BITSPERLONG_H
3 4
diff --git a/tools/arch/powerpc/include/uapi/asm/kvm.h b/tools/arch/powerpc/include/uapi/asm/kvm.h
index 07fbeb927834..61d6049f4c1e 100644
--- a/tools/arch/powerpc/include/uapi/asm/kvm.h
+++ b/tools/arch/powerpc/include/uapi/asm/kvm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1/* 2/*
2 * This program is free software; you can redistribute it and/or modify 3 * 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 * it under the terms of the GNU General Public License, version 2, as
@@ -60,6 +61,12 @@ struct kvm_regs {
60 61
61#define KVM_SREGS_E_FSL_PIDn (1 << 0) /* PID1/PID2 */ 62#define KVM_SREGS_E_FSL_PIDn (1 << 0) /* PID1/PID2 */
62 63
64/* flags for kvm_run.flags */
65#define KVM_RUN_PPC_NMI_DISP_MASK (3 << 0)
66#define KVM_RUN_PPC_NMI_DISP_FULLY_RECOV (1 << 0)
67#define KVM_RUN_PPC_NMI_DISP_LIMITED_RECOV (2 << 0)
68#define KVM_RUN_PPC_NMI_DISP_NOT_RECOV (3 << 0)
69
63/* 70/*
64 * Feature bits indicate which sections of the sregs struct are valid, 71 * Feature bits indicate which sections of the sregs struct are valid,
65 * both in KVM_GET_SREGS and KVM_SET_SREGS. On KVM_SET_SREGS, registers 72 * both in KVM_GET_SREGS and KVM_SET_SREGS. On KVM_SET_SREGS, registers
diff --git a/tools/arch/powerpc/include/uapi/asm/mman.h b/tools/arch/powerpc/include/uapi/asm/mman.h
index 761db43172fe..f33105bc5ca6 100644
--- a/tools/arch/powerpc/include/uapi/asm/mman.h
+++ b/tools/arch/powerpc/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_POWERPC_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_POWERPC_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_POWERPC_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_POWERPC_UAPI_ASM_MMAN_FIX_H
3#define MAP_DENYWRITE 0x0800 4#define MAP_DENYWRITE 0x0800
diff --git a/tools/arch/powerpc/include/uapi/asm/perf_regs.h b/tools/arch/powerpc/include/uapi/asm/perf_regs.h
index 6a93209748a1..9e52c86ccbd3 100644
--- a/tools/arch/powerpc/include/uapi/asm/perf_regs.h
+++ b/tools/arch/powerpc/include/uapi/asm/perf_regs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _UAPI_ASM_POWERPC_PERF_REGS_H 2#ifndef _UAPI_ASM_POWERPC_PERF_REGS_H
2#define _UAPI_ASM_POWERPC_PERF_REGS_H 3#define _UAPI_ASM_POWERPC_PERF_REGS_H
3 4
diff --git a/tools/arch/s390/include/asm/barrier.h b/tools/arch/s390/include/asm/barrier.h
index f85141266b92..5030c99f47d2 100644
--- a/tools/arch/s390/include/asm/barrier.h
+++ b/tools/arch/s390/include/asm/barrier.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Copied from the kernel sources: 3 * Copied from the kernel sources:
3 * 4 *
diff --git a/tools/arch/s390/include/uapi/asm/bitsperlong.h b/tools/arch/s390/include/uapi/asm/bitsperlong.h
index e351ea2ad43e..d2bb620119bf 100644
--- a/tools/arch/s390/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/s390/include/uapi/asm/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef __ASM_S390_BITSPERLONG_H 2#ifndef __ASM_S390_BITSPERLONG_H
2#define __ASM_S390_BITSPERLONG_H 3#define __ASM_S390_BITSPERLONG_H
3 4
diff --git a/tools/arch/s390/include/uapi/asm/kvm.h b/tools/arch/s390/include/uapi/asm/kvm.h
index 3dd2a1d308dd..9ad172dcd912 100644
--- a/tools/arch/s390/include/uapi/asm/kvm.h
+++ b/tools/arch/s390/include/uapi/asm/kvm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef __LINUX_KVM_S390_H 2#ifndef __LINUX_KVM_S390_H
2#define __LINUX_KVM_S390_H 3#define __LINUX_KVM_S390_H
3/* 4/*
@@ -28,6 +29,7 @@
28#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8 29#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8
29#define KVM_DEV_FLIC_AISM 9 30#define KVM_DEV_FLIC_AISM 9
30#define KVM_DEV_FLIC_AIRQ_INJECT 10 31#define KVM_DEV_FLIC_AIRQ_INJECT 10
32#define KVM_DEV_FLIC_AISM_ALL 11
31/* 33/*
32 * We can have up to 4*64k pending subchannels + 8 adapter interrupts, 34 * We can have up to 4*64k pending subchannels + 8 adapter interrupts,
33 * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts. 35 * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
@@ -53,6 +55,11 @@ struct kvm_s390_ais_req {
53 __u16 mode; 55 __u16 mode;
54}; 56};
55 57
58struct kvm_s390_ais_all {
59 __u8 simm;
60 __u8 nimm;
61};
62
56#define KVM_S390_IO_ADAPTER_MASK 1 63#define KVM_S390_IO_ADAPTER_MASK 1
57#define KVM_S390_IO_ADAPTER_MAP 2 64#define KVM_S390_IO_ADAPTER_MAP 2
58#define KVM_S390_IO_ADAPTER_UNMAP 3 65#define KVM_S390_IO_ADAPTER_UNMAP 3
@@ -70,6 +77,7 @@ struct kvm_s390_io_adapter_req {
70#define KVM_S390_VM_TOD 1 77#define KVM_S390_VM_TOD 1
71#define KVM_S390_VM_CRYPTO 2 78#define KVM_S390_VM_CRYPTO 2
72#define KVM_S390_VM_CPU_MODEL 3 79#define KVM_S390_VM_CPU_MODEL 3
80#define KVM_S390_VM_MIGRATION 4
73 81
74/* kvm attributes for mem_ctrl */ 82/* kvm attributes for mem_ctrl */
75#define KVM_S390_VM_MEM_ENABLE_CMMA 0 83#define KVM_S390_VM_MEM_ENABLE_CMMA 0
@@ -81,6 +89,12 @@ struct kvm_s390_io_adapter_req {
81/* kvm attributes for KVM_S390_VM_TOD */ 89/* kvm attributes for KVM_S390_VM_TOD */
82#define KVM_S390_VM_TOD_LOW 0 90#define KVM_S390_VM_TOD_LOW 0
83#define KVM_S390_VM_TOD_HIGH 1 91#define KVM_S390_VM_TOD_HIGH 1
92#define KVM_S390_VM_TOD_EXT 2
93
94struct kvm_s390_vm_tod_clock {
95 __u8 epoch_idx;
96 __u64 tod;
97};
84 98
85/* kvm attributes for KVM_S390_VM_CPU_MODEL */ 99/* kvm attributes for KVM_S390_VM_CPU_MODEL */
86/* processor related attributes are r/w */ 100/* processor related attributes are r/w */
@@ -151,6 +165,11 @@ struct kvm_s390_vm_cpu_subfunc {
151#define KVM_S390_VM_CRYPTO_DISABLE_AES_KW 2 165#define KVM_S390_VM_CRYPTO_DISABLE_AES_KW 2
152#define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW 3 166#define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW 3
153 167
168/* kvm attributes for migration mode */
169#define KVM_S390_VM_MIGRATION_STOP 0
170#define KVM_S390_VM_MIGRATION_START 1
171#define KVM_S390_VM_MIGRATION_STATUS 2
172
154/* for KVM_GET_REGS and KVM_SET_REGS */ 173/* for KVM_GET_REGS and KVM_SET_REGS */
155struct kvm_regs { 174struct kvm_regs {
156 /* general purpose regs for s390 */ 175 /* general purpose regs for s390 */
diff --git a/tools/arch/s390/include/uapi/asm/kvm_perf.h b/tools/arch/s390/include/uapi/asm/kvm_perf.h
index 397282727e21..c36c97ffdc6f 100644
--- a/tools/arch/s390/include/uapi/asm/kvm_perf.h
+++ b/tools/arch/s390/include/uapi/asm/kvm_perf.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1/* 2/*
2 * Definitions for perf-kvm on s390 3 * Definitions for perf-kvm on s390
3 * 4 *
diff --git a/tools/arch/s390/include/uapi/asm/mman.h b/tools/arch/s390/include/uapi/asm/mman.h
index b03dea9e1f56..4ec32e4251a4 100644
--- a/tools/arch/s390/include/uapi/asm/mman.h
+++ b/tools/arch/s390/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_S390_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_S390_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_S390_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_S390_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h> 4#include <uapi/asm-generic/mman.h>
diff --git a/tools/arch/s390/include/uapi/asm/sie.h b/tools/arch/s390/include/uapi/asm/sie.h
index 3ac634368939..6ca1e68d7103 100644
--- a/tools/arch/s390/include/uapi/asm/sie.h
+++ b/tools/arch/s390/include/uapi/asm/sie.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _UAPI_ASM_S390_SIE_H 2#ifndef _UAPI_ASM_S390_SIE_H
2#define _UAPI_ASM_S390_SIE_H 3#define _UAPI_ASM_S390_SIE_H
3 4
diff --git a/tools/arch/score/include/uapi/asm/bitsperlong.h b/tools/arch/score/include/uapi/asm/bitsperlong.h
index 86ff337aa459..df48f2717da2 100644
--- a/tools/arch/score/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/score/include/uapi/asm/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _ASM_SCORE_BITSPERLONG_H 2#ifndef _ASM_SCORE_BITSPERLONG_H
2#define _ASM_SCORE_BITSPERLONG_H 3#define _ASM_SCORE_BITSPERLONG_H
3 4
diff --git a/tools/arch/score/include/uapi/asm/mman.h b/tools/arch/score/include/uapi/asm/mman.h
index 2f8fb89944fd..b4bd195a8586 100644
--- a/tools/arch/score/include/uapi/asm/mman.h
+++ b/tools/arch/score/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_SCORE_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_SCORE_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_SCORE_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_SCORE_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h> 4#include <uapi/asm-generic/mman.h>
diff --git a/tools/arch/sh/include/asm/barrier.h b/tools/arch/sh/include/asm/barrier.h
index c18fd7599b97..bde5221af282 100644
--- a/tools/arch/sh/include/asm/barrier.h
+++ b/tools/arch/sh/include/asm/barrier.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Copied from the kernel sources: 3 * Copied from the kernel sources:
3 * 4 *
diff --git a/tools/arch/sh/include/uapi/asm/mman.h b/tools/arch/sh/include/uapi/asm/mman.h
index 26504f6f060e..88c0e2930c47 100644
--- a/tools/arch/sh/include/uapi/asm/mman.h
+++ b/tools/arch/sh/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_SH_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_SH_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_SH_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_SH_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h> 4#include <uapi/asm-generic/mman.h>
diff --git a/tools/arch/sparc/include/asm/barrier.h b/tools/arch/sparc/include/asm/barrier.h
index 8c017b3b1391..95d1618465a6 100644
--- a/tools/arch/sparc/include/asm/barrier.h
+++ b/tools/arch/sparc/include/asm/barrier.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef ___TOOLS_LINUX_ASM_SPARC_BARRIER_H 2#ifndef ___TOOLS_LINUX_ASM_SPARC_BARRIER_H
2#define ___TOOLS_LINUX_ASM_SPARC_BARRIER_H 3#define ___TOOLS_LINUX_ASM_SPARC_BARRIER_H
3#if defined(__sparc__) && defined(__arch64__) 4#if defined(__sparc__) && defined(__arch64__)
diff --git a/tools/arch/sparc/include/asm/barrier_32.h b/tools/arch/sparc/include/asm/barrier_32.h
index c5eadd0a7233..cc19ed1dde0b 100644
--- a/tools/arch/sparc/include/asm/barrier_32.h
+++ b/tools/arch/sparc/include/asm/barrier_32.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __TOOLS_PERF_SPARC_BARRIER_H 2#ifndef __TOOLS_PERF_SPARC_BARRIER_H
2#define __TOOLS_PERF_SPARC_BARRIER_H 3#define __TOOLS_PERF_SPARC_BARRIER_H
3 4
diff --git a/tools/arch/sparc/include/asm/barrier_64.h b/tools/arch/sparc/include/asm/barrier_64.h
index 9a7d7322c3f7..ba61344287d5 100644
--- a/tools/arch/sparc/include/asm/barrier_64.h
+++ b/tools/arch/sparc/include/asm/barrier_64.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __TOOLS_LINUX_SPARC64_BARRIER_H 2#ifndef __TOOLS_LINUX_SPARC64_BARRIER_H
2#define __TOOLS_LINUX_SPARC64_BARRIER_H 3#define __TOOLS_LINUX_SPARC64_BARRIER_H
3 4
diff --git a/tools/arch/sparc/include/uapi/asm/bitsperlong.h b/tools/arch/sparc/include/uapi/asm/bitsperlong.h
index b62dd907d7c3..3b4e61740b75 100644
--- a/tools/arch/sparc/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/sparc/include/uapi/asm/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef __ASM_ALPHA_BITSPERLONG_H 2#ifndef __ASM_ALPHA_BITSPERLONG_H
2#define __ASM_ALPHA_BITSPERLONG_H 3#define __ASM_ALPHA_BITSPERLONG_H
3 4
diff --git a/tools/arch/sparc/include/uapi/asm/mman.h b/tools/arch/sparc/include/uapi/asm/mman.h
index 8640525de991..38920eed8cbf 100644
--- a/tools/arch/sparc/include/uapi/asm/mman.h
+++ b/tools/arch/sparc/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_SPARC_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_SPARC_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_SPARC_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_SPARC_UAPI_ASM_MMAN_FIX_H
3#define MAP_DENYWRITE 0x0800 4#define MAP_DENYWRITE 0x0800
diff --git a/tools/arch/tile/include/asm/barrier.h b/tools/arch/tile/include/asm/barrier.h
index 7d3692c3d4ac..7ad02a591b43 100644
--- a/tools/arch/tile/include/asm/barrier.h
+++ b/tools/arch/tile/include/asm/barrier.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_ASM_TILE_BARRIER_H 2#ifndef _TOOLS_LINUX_ASM_TILE_BARRIER_H
2#define _TOOLS_LINUX_ASM_TILE_BARRIER_H 3#define _TOOLS_LINUX_ASM_TILE_BARRIER_H
3/* 4/*
diff --git a/tools/arch/tile/include/uapi/asm/bitsperlong.h b/tools/arch/tile/include/uapi/asm/bitsperlong.h
index 58c771f2af2f..57cca78c0fbb 100644
--- a/tools/arch/tile/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/tile/include/uapi/asm/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1/* 2/*
2 * Copyright 2010 Tilera Corporation. All Rights Reserved. 3 * Copyright 2010 Tilera Corporation. All Rights Reserved.
3 * 4 *
diff --git a/tools/arch/tile/include/uapi/asm/mman.h b/tools/arch/tile/include/uapi/asm/mman.h
index 7116c4b928b3..65ec92925c6c 100644
--- a/tools/arch/tile/include/uapi/asm/mman.h
+++ b/tools/arch/tile/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_TILE_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_TILE_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_TILE_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_TILE_UAPI_ASM_MMAN_FIX_H
3#define MAP_DENYWRITE 0x0800 4#define MAP_DENYWRITE 0x0800
diff --git a/tools/arch/x86/include/asm/atomic.h b/tools/arch/x86/include/asm/atomic.h
index 328eeceec709..1f5e26aae9fc 100644
--- a/tools/arch/x86/include/asm/atomic.h
+++ b/tools/arch/x86/include/asm/atomic.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_ASM_X86_ATOMIC_H 2#ifndef _TOOLS_LINUX_ASM_X86_ATOMIC_H
2#define _TOOLS_LINUX_ASM_X86_ATOMIC_H 3#define _TOOLS_LINUX_ASM_X86_ATOMIC_H
3 4
@@ -24,7 +25,7 @@
24 */ 25 */
25static inline int atomic_read(const atomic_t *v) 26static inline int atomic_read(const atomic_t *v)
26{ 27{
27 return ACCESS_ONCE((v)->counter); 28 return READ_ONCE((v)->counter);
28} 29}
29 30
30/** 31/**
diff --git a/tools/arch/x86/include/asm/barrier.h b/tools/arch/x86/include/asm/barrier.h
index f366d8e550e4..8774dee27471 100644
--- a/tools/arch/x86/include/asm/barrier.h
+++ b/tools/arch/x86/include/asm/barrier.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_ASM_X86_BARRIER_H 2#ifndef _TOOLS_LINUX_ASM_X86_BARRIER_H
2#define _TOOLS_LINUX_ASM_X86_BARRIER_H 3#define _TOOLS_LINUX_ASM_X86_BARRIER_H
3 4
diff --git a/tools/arch/x86/include/asm/cmpxchg.h b/tools/arch/x86/include/asm/cmpxchg.h
index f5253260f3cc..0ed9ca2766ad 100644
--- a/tools/arch/x86/include/asm/cmpxchg.h
+++ b/tools/arch/x86/include/asm/cmpxchg.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef TOOLS_ASM_X86_CMPXCHG_H 2#ifndef TOOLS_ASM_X86_CMPXCHG_H
2#define TOOLS_ASM_X86_CMPXCHG_H 3#define TOOLS_ASM_X86_CMPXCHG_H
3 4
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index 2701e5f8145b..793690fbda36 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _ASM_X86_CPUFEATURES_H 2#ifndef _ASM_X86_CPUFEATURES_H
2#define _ASM_X86_CPUFEATURES_H 3#define _ASM_X86_CPUFEATURES_H
3 4
@@ -177,7 +178,7 @@
177#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */ 178#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */
178#define X86_FEATURE_BPEXT (6*32+26) /* data breakpoint extension */ 179#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_PTSC ( 6*32+27) /* performance time-stamp counter */
180#define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */ 181#define X86_FEATURE_PERFCTR_LLC ( 6*32+28) /* Last Level Cache performance counter extensions */
181#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */ 182#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */
182 183
183/* 184/*
@@ -196,6 +197,7 @@
196 197
197#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */ 198#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */
198#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ 199#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
200#define X86_FEATURE_SME ( 7*32+10) /* AMD Secure Memory Encryption */
199 201
200#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */ 202#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */
201#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */ 203#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */
@@ -286,6 +288,8 @@
286#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */ 288#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */
287#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */ 289#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */
288#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */ 290#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */
291#define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* Virtual VMSAVE VMLOAD */
292#define X86_FEATURE_VGIF (15*32+16) /* Virtual GIF */
289 293
290/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */ 294/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
291#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/ 295#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
diff --git a/tools/arch/x86/include/asm/disabled-features.h b/tools/arch/x86/include/asm/disabled-features.h
index 5dff775af7cd..c10c9128f54e 100644
--- a/tools/arch/x86/include/asm/disabled-features.h
+++ b/tools/arch/x86/include/asm/disabled-features.h
@@ -21,11 +21,13 @@
21# define DISABLE_K6_MTRR (1<<(X86_FEATURE_K6_MTRR & 31)) 21# define DISABLE_K6_MTRR (1<<(X86_FEATURE_K6_MTRR & 31))
22# define DISABLE_CYRIX_ARR (1<<(X86_FEATURE_CYRIX_ARR & 31)) 22# define DISABLE_CYRIX_ARR (1<<(X86_FEATURE_CYRIX_ARR & 31))
23# define DISABLE_CENTAUR_MCR (1<<(X86_FEATURE_CENTAUR_MCR & 31)) 23# define DISABLE_CENTAUR_MCR (1<<(X86_FEATURE_CENTAUR_MCR & 31))
24# define DISABLE_PCID 0
24#else 25#else
25# define DISABLE_VME 0 26# define DISABLE_VME 0
26# define DISABLE_K6_MTRR 0 27# define DISABLE_K6_MTRR 0
27# define DISABLE_CYRIX_ARR 0 28# define DISABLE_CYRIX_ARR 0
28# define DISABLE_CENTAUR_MCR 0 29# define DISABLE_CENTAUR_MCR 0
30# define DISABLE_PCID (1<<(X86_FEATURE_PCID & 31))
29#endif /* CONFIG_X86_64 */ 31#endif /* CONFIG_X86_64 */
30 32
31#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS 33#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
@@ -49,7 +51,7 @@
49#define DISABLED_MASK1 0 51#define DISABLED_MASK1 0
50#define DISABLED_MASK2 0 52#define DISABLED_MASK2 0
51#define DISABLED_MASK3 (DISABLE_CYRIX_ARR|DISABLE_CENTAUR_MCR|DISABLE_K6_MTRR) 53#define DISABLED_MASK3 (DISABLE_CYRIX_ARR|DISABLE_CENTAUR_MCR|DISABLE_K6_MTRR)
52#define DISABLED_MASK4 0 54#define DISABLED_MASK4 (DISABLE_PCID)
53#define DISABLED_MASK5 0 55#define DISABLED_MASK5 0
54#define DISABLED_MASK6 0 56#define DISABLED_MASK6 0
55#define DISABLED_MASK7 0 57#define DISABLED_MASK7 0
diff --git a/tools/arch/x86/include/asm/rmwcc.h b/tools/arch/x86/include/asm/rmwcc.h
index a6669bc06939..dc90c0c2fae3 100644
--- a/tools/arch/x86/include/asm/rmwcc.h
+++ b/tools/arch/x86/include/asm/rmwcc.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_ASM_X86_RMWcc 2#ifndef _TOOLS_LINUX_ASM_X86_RMWcc
2#define _TOOLS_LINUX_ASM_X86_RMWcc 3#define _TOOLS_LINUX_ASM_X86_RMWcc
3 4
diff --git a/tools/arch/x86/include/asm/unistd_32.h b/tools/arch/x86/include/asm/unistd_32.h
index 88b3f8c8920c..60a89dba01b6 100644
--- a/tools/arch/x86/include/asm/unistd_32.h
+++ b/tools/arch/x86/include/asm/unistd_32.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __NR_perf_event_open 2#ifndef __NR_perf_event_open
2# define __NR_perf_event_open 336 3# define __NR_perf_event_open 336
3#endif 4#endif
@@ -10,3 +11,6 @@
10#ifndef __NR_getcpu 11#ifndef __NR_getcpu
11# define __NR_getcpu 318 12# define __NR_getcpu 318
12#endif 13#endif
14#ifndef __NR_setns
15# define __NR_setns 346
16#endif
diff --git a/tools/arch/x86/include/asm/unistd_64.h b/tools/arch/x86/include/asm/unistd_64.h
index fbdb70ee8837..cb52a3a8b8fc 100644
--- a/tools/arch/x86/include/asm/unistd_64.h
+++ b/tools/arch/x86/include/asm/unistd_64.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __NR_perf_event_open 2#ifndef __NR_perf_event_open
2# define __NR_perf_event_open 298 3# define __NR_perf_event_open 298
3#endif 4#endif
@@ -10,3 +11,6 @@
10#ifndef __NR_getcpu 11#ifndef __NR_getcpu
11# define __NR_getcpu 309 12# define __NR_getcpu 309
12#endif 13#endif
14#ifndef __NR_setns
15#define __NR_setns 308
16#endif
diff --git a/tools/arch/x86/include/uapi/asm/bitsperlong.h b/tools/arch/x86/include/uapi/asm/bitsperlong.h
index 6e23c543cd80..f8a92e0009d6 100644
--- a/tools/arch/x86/include/uapi/asm/bitsperlong.h
+++ b/tools/arch/x86/include/uapi/asm/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef __ASM_X86_BITSPERLONG_H 2#ifndef __ASM_X86_BITSPERLONG_H
2#define __ASM_X86_BITSPERLONG_H 3#define __ASM_X86_BITSPERLONG_H
3 4
diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h
index c2824d02ba37..f3a960488eae 100644
--- a/tools/arch/x86/include/uapi/asm/kvm.h
+++ b/tools/arch/x86/include/uapi/asm/kvm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _ASM_X86_KVM_H 2#ifndef _ASM_X86_KVM_H
2#define _ASM_X86_KVM_H 3#define _ASM_X86_KVM_H
3 4
diff --git a/tools/arch/x86/include/uapi/asm/kvm_perf.h b/tools/arch/x86/include/uapi/asm/kvm_perf.h
index 3bb964f88aa1..125cf5cdf6c5 100644
--- a/tools/arch/x86/include/uapi/asm/kvm_perf.h
+++ b/tools/arch/x86/include/uapi/asm/kvm_perf.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _ASM_X86_KVM_PERF_H 2#ifndef _ASM_X86_KVM_PERF_H
2#define _ASM_X86_KVM_PERF_H 3#define _ASM_X86_KVM_PERF_H
3 4
diff --git a/tools/arch/x86/include/uapi/asm/mman.h b/tools/arch/x86/include/uapi/asm/mman.h
index b73c1af8b1dd..8449778de2ed 100644
--- a/tools/arch/x86/include/uapi/asm/mman.h
+++ b/tools/arch/x86/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_X86_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_X86_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_X86_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_X86_UAPI_ASM_MMAN_FIX_H
3#define MAP_32BIT 0x40 4#define MAP_32BIT 0x40
diff --git a/tools/arch/x86/include/uapi/asm/perf_regs.h b/tools/arch/x86/include/uapi/asm/perf_regs.h
index 3f2207bfd17b..f3329cabce5c 100644
--- a/tools/arch/x86/include/uapi/asm/perf_regs.h
+++ b/tools/arch/x86/include/uapi/asm/perf_regs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _ASM_X86_PERF_REGS_H 2#ifndef _ASM_X86_PERF_REGS_H
2#define _ASM_X86_PERF_REGS_H 3#define _ASM_X86_PERF_REGS_H
3 4
diff --git a/tools/arch/x86/include/uapi/asm/svm.h b/tools/arch/x86/include/uapi/asm/svm.h
index 3725e145aa58..a9731f8a480f 100644
--- a/tools/arch/x86/include/uapi/asm/svm.h
+++ b/tools/arch/x86/include/uapi/asm/svm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _UAPI__SVM_H 2#ifndef _UAPI__SVM_H
2#define _UAPI__SVM_H 3#define _UAPI__SVM_H
3 4
diff --git a/tools/arch/x86/include/uapi/asm/unistd.h b/tools/arch/x86/include/uapi/asm/unistd.h
new file mode 100644
index 000000000000..30d7d04d72d6
--- /dev/null
+++ b/tools/arch/x86/include/uapi/asm/unistd.h
@@ -0,0 +1,18 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef _UAPI_ASM_X86_UNISTD_H
3#define _UAPI_ASM_X86_UNISTD_H
4
5/* x32 syscall flag bit */
6#define __X32_SYSCALL_BIT 0x40000000
7
8#ifndef __KERNEL__
9# ifdef __i386__
10# include <asm/unistd_32.h>
11# elif defined(__ILP32__)
12# include <asm/unistd_x32.h>
13# else
14# include <asm/unistd_64.h>
15# endif
16#endif
17
18#endif /* _UAPI_ASM_X86_UNISTD_H */
diff --git a/tools/arch/x86/include/uapi/asm/vmx.h b/tools/arch/x86/include/uapi/asm/vmx.h
index 690a2dcf4078..f0b0c90dd398 100644
--- a/tools/arch/x86/include/uapi/asm/vmx.h
+++ b/tools/arch/x86/include/uapi/asm/vmx.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1/* 2/*
2 * vmx.h: VMX Architecture related definitions 3 * vmx.h: VMX Architecture related definitions
3 * Copyright (c) 2004, Intel Corporation. 4 * Copyright (c) 2004, Intel Corporation.
diff --git a/tools/arch/x86/lib/memcpy_64.S b/tools/arch/x86/lib/memcpy_64.S
index 98dcc112b363..9a53a06e5a3e 100644
--- a/tools/arch/x86/lib/memcpy_64.S
+++ b/tools/arch/x86/lib/memcpy_64.S
@@ -4,6 +4,7 @@
4#include <asm/errno.h> 4#include <asm/errno.h>
5#include <asm/cpufeatures.h> 5#include <asm/cpufeatures.h>
6#include <asm/alternative-asm.h> 6#include <asm/alternative-asm.h>
7#include <asm/export.h>
7 8
8/* 9/*
9 * We build a jump to memcpy_orig by default which gets NOPped out on 10 * We build a jump to memcpy_orig by default which gets NOPped out on
@@ -40,6 +41,8 @@ ENTRY(memcpy)
40 ret 41 ret
41ENDPROC(memcpy) 42ENDPROC(memcpy)
42ENDPROC(__memcpy) 43ENDPROC(__memcpy)
44EXPORT_SYMBOL(memcpy)
45EXPORT_SYMBOL(__memcpy)
43 46
44/* 47/*
45 * memcpy_erms() - enhanced fast string memcpy. This is faster and 48 * memcpy_erms() - enhanced fast string memcpy. This is faster and
@@ -274,6 +277,7 @@ ENTRY(memcpy_mcsafe_unrolled)
274 xorq %rax, %rax 277 xorq %rax, %rax
275 ret 278 ret
276ENDPROC(memcpy_mcsafe_unrolled) 279ENDPROC(memcpy_mcsafe_unrolled)
280EXPORT_SYMBOL_GPL(memcpy_mcsafe_unrolled)
277 281
278 .section .fixup, "ax" 282 .section .fixup, "ax"
279 /* Return -EFAULT for any failure */ 283 /* Return -EFAULT for any failure */
diff --git a/tools/arch/x86/lib/memset_64.S b/tools/arch/x86/lib/memset_64.S
index e1229ecd2a82..f8f3dc0a6690 100644
--- a/tools/arch/x86/lib/memset_64.S
+++ b/tools/arch/x86/lib/memset_64.S
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* Copyright 2002 Andi Kleen, SuSE Labs */ 2/* Copyright 2002 Andi Kleen, SuSE Labs */
2 3
3#include <linux/linkage.h> 4#include <linux/linkage.h>
diff --git a/tools/arch/xtensa/include/uapi/asm/mman.h b/tools/arch/xtensa/include/uapi/asm/mman.h
index 4453195c450c..34dde6f44dae 100644
--- a/tools/arch/xtensa/include/uapi/asm/mman.h
+++ b/tools/arch/xtensa/include/uapi/asm/mman.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef TOOLS_ARCH_XTENSA_UAPI_ASM_MMAN_FIX_H 2#ifndef TOOLS_ARCH_XTENSA_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_XTENSA_UAPI_ASM_MMAN_FIX_H 3#define TOOLS_ARCH_XTENSA_UAPI_ASM_MMAN_FIX_H
3#define MADV_DODUMP 17 4#define MADV_DODUMP 17
diff --git a/tools/net/Makefile b/tools/bpf/Makefile
index ddf888010652..07a6697466ef 100644
--- a/tools/net/Makefile
+++ b/tools/bpf/Makefile
@@ -1,8 +1,10 @@
1# SPDX-License-Identifier: GPL-2.0
1prefix = /usr 2prefix = /usr
2 3
3CC = gcc 4CC = gcc
4LEX = flex 5LEX = flex
5YACC = bison 6YACC = bison
7MAKE = make
6 8
7CFLAGS += -Wall -O2 9CFLAGS += -Wall -O2
8CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include 10CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
@@ -13,7 +15,7 @@ CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
13%.lex.c: %.l 15%.lex.c: %.l
14 $(LEX) -o $@ $< 16 $(LEX) -o $@ $<
15 17
16all : bpf_jit_disasm bpf_dbg bpf_asm 18all: bpf_jit_disasm bpf_dbg bpf_asm bpftool
17 19
18bpf_jit_disasm : CFLAGS += -DPACKAGE='bpf_jit_disasm' 20bpf_jit_disasm : CFLAGS += -DPACKAGE='bpf_jit_disasm'
19bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl 21bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl
@@ -26,10 +28,21 @@ bpf_asm : LDLIBS =
26bpf_asm : bpf_asm.o bpf_exp.yacc.o bpf_exp.lex.o 28bpf_asm : bpf_asm.o bpf_exp.yacc.o bpf_exp.lex.o
27bpf_exp.lex.o : bpf_exp.yacc.c 29bpf_exp.lex.o : bpf_exp.yacc.c
28 30
29clean : 31clean: bpftool_clean
30 rm -rf *.o bpf_jit_disasm bpf_dbg bpf_asm bpf_exp.yacc.* bpf_exp.lex.* 32 rm -rf *.o bpf_jit_disasm bpf_dbg bpf_asm bpf_exp.yacc.* bpf_exp.lex.*
31 33
32install : 34install: bpftool_install
33 install bpf_jit_disasm $(prefix)/bin/bpf_jit_disasm 35 install bpf_jit_disasm $(prefix)/bin/bpf_jit_disasm
34 install bpf_dbg $(prefix)/bin/bpf_dbg 36 install bpf_dbg $(prefix)/bin/bpf_dbg
35 install bpf_asm $(prefix)/bin/bpf_asm 37 install bpf_asm $(prefix)/bin/bpf_asm
38
39bpftool:
40 $(MAKE) -C bpftool
41
42bpftool_install:
43 $(MAKE) -C bpftool install
44
45bpftool_clean:
46 $(MAKE) -C bpftool clean
47
48.PHONY: bpftool FORCE
diff --git a/tools/net/bpf_asm.c b/tools/bpf/bpf_asm.c
index c15aef097b04..c15aef097b04 100644
--- a/tools/net/bpf_asm.c
+++ b/tools/bpf/bpf_asm.c
diff --git a/tools/net/bpf_dbg.c b/tools/bpf/bpf_dbg.c
index 4f254bcc4423..4f254bcc4423 100644
--- a/tools/net/bpf_dbg.c
+++ b/tools/bpf/bpf_dbg.c
diff --git a/tools/net/bpf_exp.l b/tools/bpf/bpf_exp.l
index bd83149e7be0..bd83149e7be0 100644
--- a/tools/net/bpf_exp.l
+++ b/tools/bpf/bpf_exp.l
diff --git a/tools/net/bpf_exp.y b/tools/bpf/bpf_exp.y
index 56ba1de50784..56ba1de50784 100644
--- a/tools/net/bpf_exp.y
+++ b/tools/bpf/bpf_exp.y
diff --git a/tools/net/bpf_jit_disasm.c b/tools/bpf/bpf_jit_disasm.c
index 422d9abd666a..75bf526a0168 100644
--- a/tools/net/bpf_jit_disasm.c
+++ b/tools/bpf/bpf_jit_disasm.c
@@ -27,6 +27,7 @@
27#include <sys/klog.h> 27#include <sys/klog.h>
28#include <sys/types.h> 28#include <sys/types.h>
29#include <sys/stat.h> 29#include <sys/stat.h>
30#include <limits.h>
30 31
31#define CMD_ACTION_SIZE_BUFFER 10 32#define CMD_ACTION_SIZE_BUFFER 10
32#define CMD_ACTION_READ_ALL 3 33#define CMD_ACTION_READ_ALL 3
@@ -51,7 +52,7 @@ static void get_exec_path(char *tpath, size_t size)
51static void get_asm_insns(uint8_t *image, size_t len, int opcodes) 52static void get_asm_insns(uint8_t *image, size_t len, int opcodes)
52{ 53{
53 int count, i, pc = 0; 54 int count, i, pc = 0;
54 char tpath[256]; 55 char tpath[PATH_MAX];
55 struct disassemble_info info; 56 struct disassemble_info info;
56 disassembler_ftype disassemble; 57 disassembler_ftype disassemble;
57 bfd *bfdf; 58 bfd *bfdf;
diff --git a/tools/bpf/bpftool/Documentation/Makefile b/tools/bpf/bpftool/Documentation/Makefile
new file mode 100644
index 000000000000..bde77d7c4390
--- /dev/null
+++ b/tools/bpf/bpftool/Documentation/Makefile
@@ -0,0 +1,34 @@
1include ../../../scripts/Makefile.include
2include ../../../scripts/utilities.mak
3
4INSTALL ?= install
5RM ?= rm -f
6
7# Make the path relative to DESTDIR, not prefix
8ifndef DESTDIR
9prefix?=$(HOME)
10endif
11mandir ?= $(prefix)/share/man
12man8dir = $(mandir)/man8
13
14MAN8_RST = $(wildcard *.rst)
15
16_DOC_MAN8 = $(patsubst %.rst,%.8,$(MAN8_RST))
17DOC_MAN8 = $(addprefix $(OUTPUT),$(_DOC_MAN8))
18
19man: man8
20man8: $(DOC_MAN8)
21
22$(OUTPUT)%.8: %.rst
23 rst2man $< > $@
24
25clean:
26 $(call QUIET_CLEAN, Documentation) $(RM) $(DOC_MAN8)
27
28install: man
29 $(call QUIET_INSTALL, Documentation-man) \
30 $(INSTALL) -d -m 755 $(DESTDIR)$(man8dir); \
31 $(INSTALL) -m 644 $(DOC_MAN8) $(DESTDIR)$(man8dir);
32
33.PHONY: man man8 clean install
34.DEFAULT_GOAL := man
diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst
new file mode 100644
index 000000000000..9f51a268eb06
--- /dev/null
+++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst
@@ -0,0 +1,131 @@
1================
2bpftool-map
3================
4-------------------------------------------------------------------------------
5tool for inspection and simple manipulation of eBPF maps
6-------------------------------------------------------------------------------
7
8:Manual section: 8
9
10SYNOPSIS
11========
12
13 **bpftool** [*OPTIONS*] **map** *COMMAND*
14
15 *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }
16
17 *COMMANDS* :=
18 { **show** | **dump** | **update** | **lookup** | **getnext** | **delete**
19 | **pin** | **help** }
20
21MAP COMMANDS
22=============
23
24| **bpftool** **map show** [*MAP*]
25| **bpftool** **map dump** *MAP*
26| **bpftool** **map update** *MAP* **key** *BYTES* **value** *VALUE* [*UPDATE_FLAGS*]
27| **bpftool** **map lookup** *MAP* **key** *BYTES*
28| **bpftool** **map getnext** *MAP* [**key** *BYTES*]
29| **bpftool** **map delete** *MAP* **key** *BYTES*
30| **bpftool** **map pin** *MAP* *FILE*
31| **bpftool** **map help**
32|
33| *MAP* := { **id** *MAP_ID* | **pinned** *FILE* }
34| *VALUE* := { *BYTES* | *MAP* | *PROGRAM* }
35| *UPDATE_FLAGS* := { **any** | **exist** | **noexist** }
36
37DESCRIPTION
38===========
39 **bpftool map show** [*MAP*]
40 Show information about loaded maps. If *MAP* is specified
41 show information only about given map, otherwise list all
42 maps currently loaded on the system.
43
44 Output will start with map ID followed by map type and
45 zero or more named attributes (depending on kernel version).
46
47 **bpftool map dump** *MAP*
48 Dump all entries in a given *MAP*.
49
50 **bpftool map update** *MAP* **key** *BYTES* **value** *VALUE* [*UPDATE_FLAGS*]
51 Update map entry for a given *KEY*.
52
53 *UPDATE_FLAGS* can be one of: **any** update existing entry
54 or add if doesn't exit; **exist** update only if entry already
55 exists; **noexist** update only if entry doesn't exist.
56
57 **bpftool map lookup** *MAP* **key** *BYTES*
58 Lookup **key** in the map.
59
60 **bpftool map getnext** *MAP* [**key** *BYTES*]
61 Get next key. If *key* is not specified, get first key.
62
63 **bpftool map delete** *MAP* **key** *BYTES*
64 Remove entry from the map.
65
66 **bpftool map pin** *MAP* *FILE*
67 Pin map *MAP* as *FILE*.
68
69 Note: *FILE* must be located in *bpffs* mount.
70
71 **bpftool map help**
72 Print short help message.
73
74OPTIONS
75=======
76 -h, --help
77 Print short generic help message (similar to **bpftool help**).
78
79 -v, --version
80 Print version number (similar to **bpftool version**).
81
82 -j, --json
83 Generate JSON output. For commands that cannot produce JSON, this
84 option has no effect.
85
86 -p, --pretty
87 Generate human-readable JSON output. Implies **-j**.
88
89 -f, --bpffs
90 Show file names of pinned maps.
91
92EXAMPLES
93========
94**# bpftool map show**
95::
96
97 10: hash name some_map flags 0x0
98 key 4B value 8B max_entries 2048 memlock 167936B
99
100**# bpftool map update id 10 key 13 00 07 00 value 02 00 00 00 01 02 03 04**
101
102**# bpftool map lookup id 10 key 0 1 2 3**
103
104::
105
106 key: 00 01 02 03 value: 00 01 02 03 04 05 06 07
107
108
109**# bpftool map dump id 10**
110::
111
112 key: 00 01 02 03 value: 00 01 02 03 04 05 06 07
113 key: 0d 00 07 00 value: 02 00 00 00 01 02 03 04
114 Found 2 elements
115
116**# bpftool map getnext id 10 key 0 1 2 3**
117::
118
119 key:
120 00 01 02 03
121 next key:
122 0d 00 07 00
123
124|
125| **# mount -t bpf none /sys/fs/bpf/**
126| **# bpftool map pin id 10 /sys/fs/bpf/map**
127| **# bpftool map del pinned /sys/fs/bpf/map key 13 00 07 00**
128
129SEE ALSO
130========
131 **bpftool**\ (8), **bpftool-prog**\ (8)
diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
new file mode 100644
index 000000000000..36e8d1c3c40d
--- /dev/null
+++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
@@ -0,0 +1,150 @@
1================
2bpftool-prog
3================
4-------------------------------------------------------------------------------
5tool for inspection and simple manipulation of eBPF progs
6-------------------------------------------------------------------------------
7
8:Manual section: 8
9
10SYNOPSIS
11========
12
13 **bpftool** [*OPTIONS*] **prog** *COMMAND*
14
15 *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }
16
17 *COMMANDS* :=
18 { **show** | **dump xlated** | **dump jited** | **pin** | **help** }
19
20MAP COMMANDS
21=============
22
23| **bpftool** **prog show** [*PROG*]
24| **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes**}]
25| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}]
26| **bpftool** **prog pin** *PROG* *FILE*
27| **bpftool** **prog help**
28|
29| *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
30
31DESCRIPTION
32===========
33 **bpftool prog show** [*PROG*]
34 Show information about loaded programs. If *PROG* is
35 specified show information only about given program, otherwise
36 list all programs currently loaded on the system.
37
38 Output will start with program ID followed by program type and
39 zero or more named attributes (depending on kernel version).
40
41 **bpftool prog dump xlated** *PROG* [{ **file** *FILE* | **opcodes** }]
42 Dump eBPF instructions of the program from the kernel.
43 If *FILE* is specified image will be written to a file,
44 otherwise it will be disassembled and printed to stdout.
45
46 **opcodes** controls if raw opcodes will be printed.
47
48 **bpftool prog dump jited** *PROG* [{ **file** *FILE* | **opcodes** }]
49 Dump jited image (host machine code) of the program.
50 If *FILE* is specified image will be written to a file,
51 otherwise it will be disassembled and printed to stdout.
52
53 **opcodes** controls if raw opcodes will be printed.
54
55 **bpftool prog pin** *PROG* *FILE*
56 Pin program *PROG* as *FILE*.
57
58 Note: *FILE* must be located in *bpffs* mount.
59
60 **bpftool prog help**
61 Print short help message.
62
63OPTIONS
64=======
65 -h, --help
66 Print short generic help message (similar to **bpftool help**).
67
68 -v, --version
69 Print version number (similar to **bpftool version**).
70
71 -j, --json
72 Generate JSON output. For commands that cannot produce JSON, this
73 option has no effect.
74
75 -p, --pretty
76 Generate human-readable JSON output. Implies **-j**.
77
78 -f, --bpffs
79 Show file names of pinned programs.
80
81EXAMPLES
82========
83**# bpftool prog show**
84::
85
86 10: xdp name some_prog tag 005a3d2123620c8b
87 loaded_at Sep 29/20:11 uid 0
88 xlated 528B jited 370B memlock 4096B map_ids 10
89
90**# bpftool --json --pretty prog show**
91
92::
93
94 {
95 "programs": [{
96 "id": 10,
97 "type": "xdp",
98 "tag": "005a3d2123620c8b",
99 "loaded_at": "Sep 29/20:11",
100 "uid": 0,
101 "bytes_xlated": 528,
102 "jited": true,
103 "bytes_jited": 370,
104 "bytes_memlock": 4096,
105 "map_ids": [10
106 ]
107 }
108 ]
109 }
110
111|
112| **# bpftool prog dump xlated id 10 file /tmp/t**
113| **# ls -l /tmp/t**
114| -rw------- 1 root root 560 Jul 22 01:42 /tmp/t
115
116**# bpftool prog dum jited tag 005a3d2123620c8b**
117
118::
119
120 push %rbp
121 mov %rsp,%rbp
122 sub $0x228,%rsp
123 sub $0x28,%rbp
124 mov %rbx,0x0(%rbp)
125
126|
127| **# mount -t bpf none /sys/fs/bpf/**
128| **# bpftool prog pin id 10 /sys/fs/bpf/prog**
129| **# ls -l /sys/fs/bpf/**
130| -rw------- 1 root root 0 Jul 22 01:43 prog
131
132**# bpftool prog dum jited pinned /sys/fs/bpf/prog opcodes**
133
134::
135
136 push %rbp
137 55
138 mov %rsp,%rbp
139 48 89 e5
140 sub $0x228,%rsp
141 48 81 ec 28 02 00 00
142 sub $0x28,%rbp
143 48 83 ed 28
144 mov %rbx,0x0(%rbp)
145 48 89 5d 00
146
147
148SEE ALSO
149========
150 **bpftool**\ (8), **bpftool-map**\ (8)
diff --git a/tools/bpf/bpftool/Documentation/bpftool.rst b/tools/bpf/bpftool/Documentation/bpftool.rst
new file mode 100644
index 000000000000..926c03d5a8da
--- /dev/null
+++ b/tools/bpf/bpftool/Documentation/bpftool.rst
@@ -0,0 +1,56 @@
1================
2BPFTOOL
3================
4-------------------------------------------------------------------------------
5tool for inspection and simple manipulation of eBPF programs and maps
6-------------------------------------------------------------------------------
7
8:Manual section: 8
9
10SYNOPSIS
11========
12
13 **bpftool** [*OPTIONS*] *OBJECT* { *COMMAND* | **help** }
14
15 **bpftool** **batch file** *FILE*
16
17 **bpftool** **version**
18
19 *OBJECT* := { **map** | **program** }
20
21 *OPTIONS* := { { **-V** | **--version** } | { **-h** | **--help** }
22 | { **-j** | **--json** } [{ **-p** | **--pretty** }] }
23
24 *MAP-COMMANDS* :=
25 { **show** | **dump** | **update** | **lookup** | **getnext** | **delete**
26 | **pin** | **help** }
27
28 *PROG-COMMANDS* := { **show** | **dump jited** | **dump xlated** | **pin**
29 | **help** }
30
31DESCRIPTION
32===========
33 *bpftool* allows for inspection and simple modification of BPF objects
34 on the system.
35
36 Note that format of the output of all tools is not guaranteed to be
37 stable and should not be depended upon.
38
39OPTIONS
40=======
41 -h, --help
42 Print short help message (similar to **bpftool help**).
43
44 -v, --version
45 Print version number (similar to **bpftool version**).
46
47 -j, --json
48 Generate JSON output. For commands that cannot produce JSON, this
49 option has no effect.
50
51 -p, --pretty
52 Generate human-readable JSON output. Implies **-j**.
53
54SEE ALSO
55========
56 **bpftool-map**\ (8), **bpftool-prog**\ (8)
diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
new file mode 100644
index 000000000000..813826c50936
--- /dev/null
+++ b/tools/bpf/bpftool/Makefile
@@ -0,0 +1,92 @@
1include ../../scripts/Makefile.include
2
3include ../../scripts/utilities.mak
4
5ifeq ($(srctree),)
6srctree := $(patsubst %/,%,$(dir $(CURDIR)))
7srctree := $(patsubst %/,%,$(dir $(srctree)))
8srctree := $(patsubst %/,%,$(dir $(srctree)))
9#$(info Determined 'srctree' to be $(srctree))
10endif
11
12ifneq ($(objtree),)
13#$(info Determined 'objtree' to be $(objtree))
14endif
15
16ifneq ($(OUTPUT),)
17#$(info Determined 'OUTPUT' to be $(OUTPUT))
18# Adding $(OUTPUT) as a directory to look for source files,
19# because use generated output files as sources dependency
20# for flex/bison parsers.
21VPATH += $(OUTPUT)
22export VPATH
23endif
24
25ifeq ($(V),1)
26 Q =
27else
28 Q = @
29endif
30
31BPF_DIR = $(srctree)/tools/lib/bpf/
32
33ifneq ($(OUTPUT),)
34 BPF_PATH=$(OUTPUT)
35else
36 BPF_PATH=$(BPF_DIR)
37endif
38
39LIBBPF = $(BPF_PATH)libbpf.a
40
41$(LIBBPF): FORCE
42 $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(OUTPUT) $(OUTPUT)libbpf.a FEATURES_DUMP=$(FEATURE_DUMP_EXPORT)
43
44$(LIBBPF)-clean:
45 $(call QUIET_CLEAN, libbpf)
46 $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(OUTPUT) clean >/dev/null
47
48prefix = /usr
49bash_compdir ?= $(prefix)/share/bash-completion/completions
50
51CC = gcc
52
53CFLAGS += -O2
54CFLAGS += -W -Wall -Wextra -Wno-unused-parameter -Wshadow
55CFLAGS += -D__EXPORTED_HEADERS__ -I$(srctree)/tools/include/uapi -I$(srctree)/tools/include -I$(srctree)/tools/lib/bpf -I$(srctree)/kernel/bpf/
56LIBS = -lelf -lbfd -lopcodes $(LIBBPF)
57
58include $(wildcard *.d)
59
60all: $(OUTPUT)bpftool
61
62SRCS=$(wildcard *.c)
63OBJS=$(patsubst %.c,$(OUTPUT)%.o,$(SRCS)) $(OUTPUT)disasm.o
64
65$(OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c
66 $(QUIET_CC)$(COMPILE.c) -MMD -o $@ $<
67
68$(OUTPUT)bpftool: $(OBJS) $(LIBBPF)
69 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
70
71$(OUTPUT)%.o: %.c
72 $(QUIET_CC)$(COMPILE.c) -MMD -o $@ $<
73
74clean: $(LIBBPF)-clean
75 $(call QUIET_CLEAN, bpftool)
76 $(Q)rm -rf $(OUTPUT)bpftool $(OUTPUT)*.o $(OUTPUT)*.d
77
78install:
79 install $(OUTPUT)bpftool $(prefix)/sbin/bpftool
80 install -m 0755 -d $(bash_compdir)
81 install -m 0644 bash-completion/bpftool $(bash_compdir)
82
83doc:
84 $(Q)$(MAKE) -C Documentation/
85
86doc-install:
87 $(Q)$(MAKE) -C Documentation/ install
88
89FORCE:
90
91.PHONY: all clean FORCE
92.DEFAULT_GOAL := all
diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
new file mode 100644
index 000000000000..7febee05c8e7
--- /dev/null
+++ b/tools/bpf/bpftool/bash-completion/bpftool
@@ -0,0 +1,354 @@
1# bpftool(8) bash completion -*- shell-script -*-
2#
3# Copyright (C) 2017 Netronome Systems, Inc.
4#
5# This software is dual licensed under the GNU General License
6# Version 2, June 1991 as shown in the file COPYING in the top-level
7# directory of this source tree or the BSD 2-Clause License provided
8# below. You have the option to license this software under the
9# complete terms of either license.
10#
11# The BSD 2-Clause License:
12#
13# Redistribution and use in source and binary forms, with or
14# without modification, are permitted provided that the following
15# conditions are met:
16#
17# 1. Redistributions of source code must retain the above
18# copyright notice, this list of conditions and the following
19# disclaimer.
20#
21# 2. Redistributions in binary form must reproduce the above
22# copyright notice, this list of conditions and the following
23# disclaimer in the documentation and/or other materials
24# provided with the distribution.
25#
26# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33# SOFTWARE.
34#
35# Author: Quentin Monnet <quentin.monnet@netronome.com>
36
37# Takes a list of words in argument; each one of them is added to COMPREPLY if
38# it is not already present on the command line. Returns no value.
39_bpftool_once_attr()
40{
41 local w idx found
42 for w in $*; do
43 found=0
44 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
45 if [[ $w == ${words[idx]} ]]; then
46 found=1
47 break
48 fi
49 done
50 [[ $found -eq 0 ]] && \
51 COMPREPLY+=( $( compgen -W "$w" -- "$cur" ) )
52 done
53}
54
55# Takes a list of words in argument; adds them all to COMPREPLY if none of them
56# is already present on the command line. Returns no value.
57_bpftool_one_of_list()
58{
59 local w idx
60 for w in $*; do
61 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
62 [[ $w == ${words[idx]} ]] && return 1
63 done
64 done
65 COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) )
66}
67
68_bpftool_get_map_ids()
69{
70 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \
71 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
72}
73
74_bpftool_get_prog_ids()
75{
76 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
77 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
78}
79
80_bpftool_get_prog_tags()
81{
82 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
83 command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) )
84}
85
86# For bpftool map update: retrieve type of the map to update.
87_bpftool_map_update_map_type()
88{
89 local keyword ref
90 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
91 if [[ ${words[$((idx-2))]} == "update" ]]; then
92 keyword=${words[$((idx-1))]}
93 ref=${words[$((idx))]}
94 fi
95 done
96 [[ -z $ref ]] && return 0
97
98 local type
99 type=$(bpftool -jp map show $keyword $ref | \
100 command sed -n 's/.*"type": "\(.*\)",$/\1/p')
101 printf $type
102}
103
104_bpftool_map_update_get_id()
105{
106 # Is it the map to update, or a map to insert into the map to update?
107 # Search for "value" keyword.
108 local idx value
109 for (( idx=7; idx < ${#words[@]}-1; idx++ )); do
110 if [[ ${words[idx]} == "value" ]]; then
111 value=1
112 break
113 fi
114 done
115 [[ $value -eq 0 ]] && _bpftool_get_map_ids && return 0
116
117 # Id to complete is for a value. It can be either prog id or map id. This
118 # depends on the type of the map to update.
119 local type=$(_bpftool_map_update_map_type)
120 case $type in
121 array_of_maps|hash_of_maps)
122 _bpftool_get_map_ids
123 return 0
124 ;;
125 prog_array)
126 _bpftool_get_prog_ids
127 return 0
128 ;;
129 *)
130 return 0
131 ;;
132 esac
133}
134
135_bpftool()
136{
137 local cur prev words objword
138 _init_completion || return
139
140 # Deal with simplest keywords
141 case $prev in
142 help|key|opcodes)
143 return 0
144 ;;
145 tag)
146 _bpftool_get_prog_tags
147 return 0
148 ;;
149 file|pinned)
150 _filedir
151 return 0
152 ;;
153 batch)
154 COMPREPLY=( $( compgen -W 'file' -- "$cur" ) )
155 return 0
156 ;;
157 esac
158
159 # Search for object and command
160 local object command cmdword
161 for (( cmdword=1; cmdword < ${#words[@]}-1; cmdword++ )); do
162 [[ -n $object ]] && command=${words[cmdword]} && break
163 [[ ${words[cmdword]} != -* ]] && object=${words[cmdword]}
164 done
165
166 if [[ -z $object ]]; then
167 case $cur in
168 -*)
169 local c='--version --json --pretty'
170 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
171 return 0
172 ;;
173 *)
174 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \
175 command sed \
176 -e '/OBJECT := /!d' \
177 -e 's/.*{//' \
178 -e 's/}.*//' \
179 -e 's/|//g' )" -- "$cur" ) )
180 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) )
181 return 0
182 ;;
183 esac
184 fi
185
186 [[ $command == help ]] && return 0
187
188 # Completion depends on object and command in use
189 case $object in
190 prog)
191 case $prev in
192 id)
193 _bpftool_get_prog_ids
194 return 0
195 ;;
196 esac
197
198 local PROG_TYPE='id pinned tag'
199 case $command in
200 show)
201 [[ $prev != "$command" ]] && return 0
202 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
203 return 0
204 ;;
205 dump)
206 case $prev in
207 $command)
208 COMPREPLY+=( $( compgen -W "xlated jited" -- \
209 "$cur" ) )
210 return 0
211 ;;
212 xlated|jited)
213 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
214 "$cur" ) )
215 return 0
216 ;;
217 *)
218 _bpftool_once_attr 'file'
219 COMPREPLY+=( $( compgen -W 'opcodes' -- \
220 "$cur" ) )
221 return 0
222 ;;
223 esac
224 ;;
225 pin)
226 if [[ $prev == "$command" ]]; then
227 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
228 else
229 _filedir
230 fi
231 return 0
232 ;;
233 *)
234 [[ $prev == $object ]] && \
235 COMPREPLY=( $( compgen -W 'dump help pin show' -- \
236 "$cur" ) )
237 ;;
238 esac
239 ;;
240 map)
241 local MAP_TYPE='id pinned'
242 case $command in
243 show|dump)
244 case $prev in
245 $command)
246 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
247 return 0
248 ;;
249 id)
250 _bpftool_get_map_ids
251 return 0
252 ;;
253 *)
254 return 0
255 ;;
256 esac
257 ;;
258 lookup|getnext|delete)
259 case $prev in
260 $command)
261 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
262 return 0
263 ;;
264 id)
265 _bpftool_get_map_ids
266 return 0
267 ;;
268 key)
269 return 0
270 ;;
271 *)
272 _bpftool_once_attr 'key'
273 return 0
274 ;;
275 esac
276 ;;
277 update)
278 case $prev in
279 $command)
280 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
281 return 0
282 ;;
283 id)
284 _bpftool_map_update_get_id
285 return 0
286 ;;
287 key)
288 return 0
289 ;;
290 value)
291 # We can have bytes, or references to a prog or a
292 # map, depending on the type of the map to update.
293 case $(_bpftool_map_update_map_type) in
294 array_of_maps|hash_of_maps)
295 local MAP_TYPE='id pinned'
296 COMPREPLY+=( $( compgen -W "$MAP_TYPE" \
297 -- "$cur" ) )
298 return 0
299 ;;
300 prog_array)
301 local PROG_TYPE='id pinned tag'
302 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \
303 -- "$cur" ) )
304 return 0
305 ;;
306 *)
307 return 0
308 ;;
309 esac
310 return 0
311 ;;
312 *)
313 _bpftool_once_attr 'key'
314 local UPDATE_FLAGS='any exist noexist'
315 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
316 if [[ ${words[idx]} == 'value' ]]; then
317 # 'value' is present, but is not the last
318 # word i.e. we can now have UPDATE_FLAGS.
319 _bpftool_one_of_list "$UPDATE_FLAGS"
320 return 0
321 fi
322 done
323 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
324 if [[ ${words[idx]} == 'key' ]]; then
325 # 'key' is present, but is not the last
326 # word i.e. we can now have 'value'.
327 _bpftool_once_attr 'value'
328 return 0
329 fi
330 done
331 return 0
332 ;;
333 esac
334 ;;
335 pin)
336 if [[ $prev == "$command" ]]; then
337 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
338 else
339 _filedir
340 fi
341 return 0
342 ;;
343 *)
344 [[ $prev == $object ]] && \
345 COMPREPLY=( $( compgen -W 'delete dump getnext help \
346 lookup pin show update' -- "$cur" ) )
347 ;;
348 esac
349 ;;
350 esac
351} &&
352complete -F _bpftool bpftool
353
354# ex: ts=4 sw=4 et filetype=sh
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
new file mode 100644
index 000000000000..2bd3b280e6dd
--- /dev/null
+++ b/tools/bpf/bpftool/common.c
@@ -0,0 +1,405 @@
1/*
2 * Copyright (C) 2017 Netronome Systems, Inc.
3 *
4 * This software is dual licensed under the GNU General License Version 2,
5 * June 1991 as shown in the file COPYING in the top-level directory of this
6 * source tree or the BSD 2-Clause License provided below. You have the
7 * option to license this software under the complete terms of either license.
8 *
9 * The BSD 2-Clause License:
10 *
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
13 * conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34/* Author: Jakub Kicinski <kubakici@wp.pl> */
35
36#include <errno.h>
37#include <fts.h>
38#include <libgen.h>
39#include <mntent.h>
40#include <stdbool.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <unistd.h>
45#include <linux/limits.h>
46#include <linux/magic.h>
47#include <sys/mount.h>
48#include <sys/types.h>
49#include <sys/vfs.h>
50
51#include <bpf.h>
52
53#include "main.h"
54
55void p_err(const char *fmt, ...)
56{
57 va_list ap;
58
59 va_start(ap, fmt);
60 if (json_output) {
61 jsonw_start_object(json_wtr);
62 jsonw_name(json_wtr, "error");
63 jsonw_vprintf_enquote(json_wtr, fmt, ap);
64 jsonw_end_object(json_wtr);
65 } else {
66 fprintf(stderr, "Error: ");
67 vfprintf(stderr, fmt, ap);
68 fprintf(stderr, "\n");
69 }
70 va_end(ap);
71}
72
73void p_info(const char *fmt, ...)
74{
75 va_list ap;
76
77 if (json_output)
78 return;
79
80 va_start(ap, fmt);
81 vfprintf(stderr, fmt, ap);
82 fprintf(stderr, "\n");
83 va_end(ap);
84}
85
86static bool is_bpffs(char *path)
87{
88 struct statfs st_fs;
89
90 if (statfs(path, &st_fs) < 0)
91 return false;
92
93 return (unsigned long)st_fs.f_type == BPF_FS_MAGIC;
94}
95
96static int mnt_bpffs(const char *target, char *buff, size_t bufflen)
97{
98 bool bind_done = false;
99
100 while (mount("", target, "none", MS_PRIVATE | MS_REC, NULL)) {
101 if (errno != EINVAL || bind_done) {
102 snprintf(buff, bufflen,
103 "mount --make-private %s failed: %s",
104 target, strerror(errno));
105 return -1;
106 }
107
108 if (mount(target, target, "none", MS_BIND, NULL)) {
109 snprintf(buff, bufflen,
110 "mount --bind %s %s failed: %s",
111 target, target, strerror(errno));
112 return -1;
113 }
114
115 bind_done = true;
116 }
117
118 if (mount("bpf", target, "bpf", 0, "mode=0700")) {
119 snprintf(buff, bufflen, "mount -t bpf bpf %s failed: %s",
120 target, strerror(errno));
121 return -1;
122 }
123
124 return 0;
125}
126
127int open_obj_pinned(char *path)
128{
129 int fd;
130
131 fd = bpf_obj_get(path);
132 if (fd < 0) {
133 p_err("bpf obj get (%s): %s", path,
134 errno == EACCES && !is_bpffs(dirname(path)) ?
135 "directory not in bpf file system (bpffs)" :
136 strerror(errno));
137 return -1;
138 }
139
140 return fd;
141}
142
143int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
144{
145 enum bpf_obj_type type;
146 int fd;
147
148 fd = open_obj_pinned(path);
149 if (fd < 0)
150 return -1;
151
152 type = get_fd_type(fd);
153 if (type < 0) {
154 close(fd);
155 return type;
156 }
157 if (type != exp_type) {
158 p_err("incorrect object type: %s", get_fd_type_name(type));
159 close(fd);
160 return -1;
161 }
162
163 return fd;
164}
165
166int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
167{
168 char err_str[ERR_MAX_LEN];
169 unsigned int id;
170 char *endptr;
171 char *file;
172 char *dir;
173 int err;
174 int fd;
175
176 if (!is_prefix(*argv, "id")) {
177 p_err("expected 'id' got %s", *argv);
178 return -1;
179 }
180 NEXT_ARG();
181
182 id = strtoul(*argv, &endptr, 0);
183 if (*endptr) {
184 p_err("can't parse %s as ID", *argv);
185 return -1;
186 }
187 NEXT_ARG();
188
189 if (argc != 1)
190 usage();
191
192 fd = get_fd_by_id(id);
193 if (fd < 0) {
194 p_err("can't get prog by id (%u): %s", id, strerror(errno));
195 return -1;
196 }
197
198 err = bpf_obj_pin(fd, *argv);
199 if (!err)
200 goto out_close;
201
202 file = malloc(strlen(*argv) + 1);
203 strcpy(file, *argv);
204 dir = dirname(file);
205
206 if (errno != EPERM || is_bpffs(dir)) {
207 p_err("can't pin the object (%s): %s", *argv, strerror(errno));
208 goto out_free;
209 }
210
211 /* Attempt to mount bpffs, then retry pinning. */
212 err = mnt_bpffs(dir, err_str, ERR_MAX_LEN);
213 if (!err) {
214 err = bpf_obj_pin(fd, *argv);
215 if (err)
216 p_err("can't pin the object (%s): %s", *argv,
217 strerror(errno));
218 } else {
219 err_str[ERR_MAX_LEN - 1] = '\0';
220 p_err("can't mount BPF file system to pin the object (%s): %s",
221 *argv, err_str);
222 }
223
224out_free:
225 free(file);
226out_close:
227 close(fd);
228 return err;
229}
230
231const char *get_fd_type_name(enum bpf_obj_type type)
232{
233 static const char * const names[] = {
234 [BPF_OBJ_UNKNOWN] = "unknown",
235 [BPF_OBJ_PROG] = "prog",
236 [BPF_OBJ_MAP] = "map",
237 };
238
239 if (type < 0 || type >= ARRAY_SIZE(names) || !names[type])
240 return names[BPF_OBJ_UNKNOWN];
241
242 return names[type];
243}
244
245int get_fd_type(int fd)
246{
247 char path[PATH_MAX];
248 char buf[512];
249 ssize_t n;
250
251 snprintf(path, sizeof(path), "/proc/%d/fd/%d", getpid(), fd);
252
253 n = readlink(path, buf, sizeof(buf));
254 if (n < 0) {
255 p_err("can't read link type: %s", strerror(errno));
256 return -1;
257 }
258 if (n == sizeof(path)) {
259 p_err("can't read link type: path too long!");
260 return -1;
261 }
262
263 if (strstr(buf, "bpf-map"))
264 return BPF_OBJ_MAP;
265 else if (strstr(buf, "bpf-prog"))
266 return BPF_OBJ_PROG;
267
268 return BPF_OBJ_UNKNOWN;
269}
270
271char *get_fdinfo(int fd, const char *key)
272{
273 char path[PATH_MAX];
274 char *line = NULL;
275 size_t line_n = 0;
276 ssize_t n;
277 FILE *fdi;
278
279 snprintf(path, sizeof(path), "/proc/%d/fdinfo/%d", getpid(), fd);
280
281 fdi = fopen(path, "r");
282 if (!fdi) {
283 p_err("can't open fdinfo: %s", strerror(errno));
284 return NULL;
285 }
286
287 while ((n = getline(&line, &line_n, fdi))) {
288 char *value;
289 int len;
290
291 if (!strstr(line, key))
292 continue;
293
294 fclose(fdi);
295
296 value = strchr(line, '\t');
297 if (!value || !value[1]) {
298 p_err("malformed fdinfo!?");
299 free(line);
300 return NULL;
301 }
302 value++;
303
304 len = strlen(value);
305 memmove(line, value, len);
306 line[len - 1] = '\0';
307
308 return line;
309 }
310
311 p_err("key '%s' not found in fdinfo", key);
312 free(line);
313 fclose(fdi);
314 return NULL;
315}
316
317void print_hex_data_json(uint8_t *data, size_t len)
318{
319 unsigned int i;
320
321 jsonw_start_array(json_wtr);
322 for (i = 0; i < len; i++)
323 jsonw_printf(json_wtr, "\"0x%02hhx\"", data[i]);
324 jsonw_end_array(json_wtr);
325}
326
327int build_pinned_obj_table(struct pinned_obj_table *tab,
328 enum bpf_obj_type type)
329{
330 struct bpf_prog_info pinned_info = {};
331 struct pinned_obj *obj_node = NULL;
332 __u32 len = sizeof(pinned_info);
333 struct mntent *mntent = NULL;
334 enum bpf_obj_type objtype;
335 FILE *mntfile = NULL;
336 FTSENT *ftse = NULL;
337 FTS *fts = NULL;
338 int fd, err;
339
340 mntfile = setmntent("/proc/mounts", "r");
341 if (!mntfile)
342 return -1;
343
344 while ((mntent = getmntent(mntfile))) {
345 char *path[] = { mntent->mnt_dir, NULL };
346
347 if (strncmp(mntent->mnt_type, "bpf", 3) != 0)
348 continue;
349
350 fts = fts_open(path, 0, NULL);
351 if (!fts)
352 continue;
353
354 while ((ftse = fts_read(fts))) {
355 if (!(ftse->fts_info & FTS_F))
356 continue;
357 fd = open_obj_pinned(ftse->fts_path);
358 if (fd < 0)
359 continue;
360
361 objtype = get_fd_type(fd);
362 if (objtype != type) {
363 close(fd);
364 continue;
365 }
366 memset(&pinned_info, 0, sizeof(pinned_info));
367 err = bpf_obj_get_info_by_fd(fd, &pinned_info, &len);
368 if (err) {
369 close(fd);
370 continue;
371 }
372
373 obj_node = malloc(sizeof(*obj_node));
374 if (!obj_node) {
375 close(fd);
376 fts_close(fts);
377 fclose(mntfile);
378 return -1;
379 }
380
381 memset(obj_node, 0, sizeof(*obj_node));
382 obj_node->id = pinned_info.id;
383 obj_node->path = strdup(ftse->fts_path);
384 hash_add(tab->table, &obj_node->hash, obj_node->id);
385
386 close(fd);
387 }
388 fts_close(fts);
389 }
390 fclose(mntfile);
391 return 0;
392}
393
394void delete_pinned_obj_table(struct pinned_obj_table *tab)
395{
396 struct pinned_obj *obj;
397 struct hlist_node *tmp;
398 unsigned int bkt;
399
400 hash_for_each_safe(tab->table, bkt, tmp, obj, hash) {
401 hash_del(&obj->hash);
402 free(obj->path);
403 free(obj);
404 }
405}
diff --git a/tools/bpf/bpftool/jit_disasm.c b/tools/bpf/bpftool/jit_disasm.c
new file mode 100644
index 000000000000..1551d3918d4c
--- /dev/null
+++ b/tools/bpf/bpftool/jit_disasm.c
@@ -0,0 +1,162 @@
1/*
2 * Based on:
3 *
4 * Minimal BPF JIT image disassembler
5 *
6 * Disassembles BPF JIT compiler emitted opcodes back to asm insn's for
7 * debugging or verification purposes.
8 *
9 * Copyright 2013 Daniel Borkmann <daniel@iogearbox.net>
10 * Licensed under the GNU General Public License, version 2.0 (GPLv2)
11 */
12
13#include <stdarg.h>
14#include <stdint.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <assert.h>
18#include <unistd.h>
19#include <string.h>
20#include <bfd.h>
21#include <dis-asm.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <limits.h>
25
26#include "json_writer.h"
27#include "main.h"
28
29static void get_exec_path(char *tpath, size_t size)
30{
31 ssize_t len;
32 char *path;
33
34 snprintf(tpath, size, "/proc/%d/exe", (int) getpid());
35 tpath[size - 1] = 0;
36
37 path = strdup(tpath);
38 assert(path);
39
40 len = readlink(path, tpath, size - 1);
41 assert(len > 0);
42 tpath[len] = 0;
43
44 free(path);
45}
46
47static int oper_count;
48static int fprintf_json(void *out, const char *fmt, ...)
49{
50 va_list ap;
51 char *s;
52
53 va_start(ap, fmt);
54 if (!oper_count) {
55 int i;
56
57 s = va_arg(ap, char *);
58
59 /* Strip trailing spaces */
60 i = strlen(s) - 1;
61 while (s[i] == ' ')
62 s[i--] = '\0';
63
64 jsonw_string_field(json_wtr, "operation", s);
65 jsonw_name(json_wtr, "operands");
66 jsonw_start_array(json_wtr);
67 oper_count++;
68 } else if (!strcmp(fmt, ",")) {
69 /* Skip */
70 } else {
71 s = va_arg(ap, char *);
72 jsonw_string(json_wtr, s);
73 oper_count++;
74 }
75 va_end(ap);
76 return 0;
77}
78
79void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes)
80{
81 disassembler_ftype disassemble;
82 struct disassemble_info info;
83 int count, i, pc = 0;
84 char tpath[PATH_MAX];
85 bfd *bfdf;
86
87 if (!len)
88 return;
89
90 memset(tpath, 0, sizeof(tpath));
91 get_exec_path(tpath, sizeof(tpath));
92
93 bfdf = bfd_openr(tpath, NULL);
94 assert(bfdf);
95 assert(bfd_check_format(bfdf, bfd_object));
96
97 if (json_output)
98 init_disassemble_info(&info, stdout,
99 (fprintf_ftype) fprintf_json);
100 else
101 init_disassemble_info(&info, stdout,
102 (fprintf_ftype) fprintf);
103 info.arch = bfd_get_arch(bfdf);
104 info.mach = bfd_get_mach(bfdf);
105 info.buffer = image;
106 info.buffer_length = len;
107
108 disassemble_init_for_target(&info);
109
110 disassemble = disassembler(bfdf);
111 assert(disassemble);
112
113 if (json_output)
114 jsonw_start_array(json_wtr);
115 do {
116 if (json_output) {
117 jsonw_start_object(json_wtr);
118 oper_count = 0;
119 jsonw_name(json_wtr, "pc");
120 jsonw_printf(json_wtr, "\"0x%x\"", pc);
121 } else {
122 printf("%4x:\t", pc);
123 }
124
125 count = disassemble(pc, &info);
126 if (json_output) {
127 /* Operand array, was started in fprintf_json. Before
128 * that, make sure we have a _null_ value if no operand
129 * other than operation code was present.
130 */
131 if (oper_count == 1)
132 jsonw_null(json_wtr);
133 jsonw_end_array(json_wtr);
134 }
135
136 if (opcodes) {
137 if (json_output) {
138 jsonw_name(json_wtr, "opcodes");
139 jsonw_start_array(json_wtr);
140 for (i = 0; i < count; ++i)
141 jsonw_printf(json_wtr, "\"0x%02hhx\"",
142 (uint8_t)image[pc + i]);
143 jsonw_end_array(json_wtr);
144 } else {
145 printf("\n\t");
146 for (i = 0; i < count; ++i)
147 printf("%02x ",
148 (uint8_t)image[pc + i]);
149 }
150 }
151 if (json_output)
152 jsonw_end_object(json_wtr);
153 else
154 printf("\n");
155
156 pc += count;
157 } while (count > 0 && pc < len);
158 if (json_output)
159 jsonw_end_array(json_wtr);
160
161 bfd_close(bfdf);
162}
diff --git a/tools/bpf/bpftool/json_writer.c b/tools/bpf/bpftool/json_writer.c
new file mode 100644
index 000000000000..c6eef76322ae
--- /dev/null
+++ b/tools/bpf/bpftool/json_writer.c
@@ -0,0 +1,356 @@
1/*
2 * Simple streaming JSON writer
3 *
4 * This takes care of the annoying bits of JSON syntax like the commas
5 * after elements
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 * Authors: Stephen Hemminger <stephen@networkplumber.org>
13 */
14
15#include <stdio.h>
16#include <stdbool.h>
17#include <stdarg.h>
18#include <assert.h>
19#include <malloc.h>
20#include <inttypes.h>
21#include <stdint.h>
22
23#include "json_writer.h"
24
25struct json_writer {
26 FILE *out; /* output file */
27 unsigned depth; /* nesting */
28 bool pretty; /* optional whitepace */
29 char sep; /* either nul or comma */
30};
31
32/* indentation for pretty print */
33static void jsonw_indent(json_writer_t *self)
34{
35 unsigned i;
36 for (i = 0; i < self->depth; ++i)
37 fputs(" ", self->out);
38}
39
40/* end current line and indent if pretty printing */
41static void jsonw_eol(json_writer_t *self)
42{
43 if (!self->pretty)
44 return;
45
46 putc('\n', self->out);
47 jsonw_indent(self);
48}
49
50/* If current object is not empty print a comma */
51static void jsonw_eor(json_writer_t *self)
52{
53 if (self->sep != '\0')
54 putc(self->sep, self->out);
55 self->sep = ',';
56}
57
58
59/* Output JSON encoded string */
60/* Handles C escapes, does not do Unicode */
61static void jsonw_puts(json_writer_t *self, const char *str)
62{
63 putc('"', self->out);
64 for (; *str; ++str)
65 switch (*str) {
66 case '\t':
67 fputs("\\t", self->out);
68 break;
69 case '\n':
70 fputs("\\n", self->out);
71 break;
72 case '\r':
73 fputs("\\r", self->out);
74 break;
75 case '\f':
76 fputs("\\f", self->out);
77 break;
78 case '\b':
79 fputs("\\b", self->out);
80 break;
81 case '\\':
82 fputs("\\n", self->out);
83 break;
84 case '"':
85 fputs("\\\"", self->out);
86 break;
87 case '\'':
88 fputs("\\\'", self->out);
89 break;
90 default:
91 putc(*str, self->out);
92 }
93 putc('"', self->out);
94}
95
96/* Create a new JSON stream */
97json_writer_t *jsonw_new(FILE *f)
98{
99 json_writer_t *self = malloc(sizeof(*self));
100 if (self) {
101 self->out = f;
102 self->depth = 0;
103 self->pretty = false;
104 self->sep = '\0';
105 }
106 return self;
107}
108
109/* End output to JSON stream */
110void jsonw_destroy(json_writer_t **self_p)
111{
112 json_writer_t *self = *self_p;
113
114 assert(self->depth == 0);
115 fputs("\n", self->out);
116 fflush(self->out);
117 free(self);
118 *self_p = NULL;
119}
120
121void jsonw_pretty(json_writer_t *self, bool on)
122{
123 self->pretty = on;
124}
125
126/* Basic blocks */
127static void jsonw_begin(json_writer_t *self, int c)
128{
129 jsonw_eor(self);
130 putc(c, self->out);
131 ++self->depth;
132 self->sep = '\0';
133}
134
135static void jsonw_end(json_writer_t *self, int c)
136{
137 assert(self->depth > 0);
138
139 --self->depth;
140 if (self->sep != '\0')
141 jsonw_eol(self);
142 putc(c, self->out);
143 self->sep = ',';
144}
145
146
147/* Add a JSON property name */
148void jsonw_name(json_writer_t *self, const char *name)
149{
150 jsonw_eor(self);
151 jsonw_eol(self);
152 self->sep = '\0';
153 jsonw_puts(self, name);
154 putc(':', self->out);
155 if (self->pretty)
156 putc(' ', self->out);
157}
158
159void jsonw_vprintf_enquote(json_writer_t *self, const char *fmt, va_list ap)
160{
161 jsonw_eor(self);
162 putc('"', self->out);
163 vfprintf(self->out, fmt, ap);
164 putc('"', self->out);
165}
166
167void jsonw_printf(json_writer_t *self, const char *fmt, ...)
168{
169 va_list ap;
170
171 va_start(ap, fmt);
172 jsonw_eor(self);
173 vfprintf(self->out, fmt, ap);
174 va_end(ap);
175}
176
177/* Collections */
178void jsonw_start_object(json_writer_t *self)
179{
180 jsonw_begin(self, '{');
181}
182
183void jsonw_end_object(json_writer_t *self)
184{
185 jsonw_end(self, '}');
186}
187
188void jsonw_start_array(json_writer_t *self)
189{
190 jsonw_begin(self, '[');
191}
192
193void jsonw_end_array(json_writer_t *self)
194{
195 jsonw_end(self, ']');
196}
197
198/* JSON value types */
199void jsonw_string(json_writer_t *self, const char *value)
200{
201 jsonw_eor(self);
202 jsonw_puts(self, value);
203}
204
205void jsonw_bool(json_writer_t *self, bool val)
206{
207 jsonw_printf(self, "%s", val ? "true" : "false");
208}
209
210void jsonw_null(json_writer_t *self)
211{
212 jsonw_printf(self, "null");
213}
214
215void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num)
216{
217 jsonw_printf(self, fmt, num);
218}
219
220#ifdef notused
221void jsonw_float(json_writer_t *self, double num)
222{
223 jsonw_printf(self, "%g", num);
224}
225#endif
226
227void jsonw_hu(json_writer_t *self, unsigned short num)
228{
229 jsonw_printf(self, "%hu", num);
230}
231
232void jsonw_uint(json_writer_t *self, uint64_t num)
233{
234 jsonw_printf(self, "%"PRIu64, num);
235}
236
237void jsonw_lluint(json_writer_t *self, unsigned long long int num)
238{
239 jsonw_printf(self, "%llu", num);
240}
241
242void jsonw_int(json_writer_t *self, int64_t num)
243{
244 jsonw_printf(self, "%"PRId64, num);
245}
246
247/* Basic name/value objects */
248void jsonw_string_field(json_writer_t *self, const char *prop, const char *val)
249{
250 jsonw_name(self, prop);
251 jsonw_string(self, val);
252}
253
254void jsonw_bool_field(json_writer_t *self, const char *prop, bool val)
255{
256 jsonw_name(self, prop);
257 jsonw_bool(self, val);
258}
259
260#ifdef notused
261void jsonw_float_field(json_writer_t *self, const char *prop, double val)
262{
263 jsonw_name(self, prop);
264 jsonw_float(self, val);
265}
266#endif
267
268void jsonw_float_field_fmt(json_writer_t *self,
269 const char *prop,
270 const char *fmt,
271 double val)
272{
273 jsonw_name(self, prop);
274 jsonw_float_fmt(self, fmt, val);
275}
276
277void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num)
278{
279 jsonw_name(self, prop);
280 jsonw_uint(self, num);
281}
282
283void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num)
284{
285 jsonw_name(self, prop);
286 jsonw_hu(self, num);
287}
288
289void jsonw_lluint_field(json_writer_t *self,
290 const char *prop,
291 unsigned long long int num)
292{
293 jsonw_name(self, prop);
294 jsonw_lluint(self, num);
295}
296
297void jsonw_int_field(json_writer_t *self, const char *prop, int64_t num)
298{
299 jsonw_name(self, prop);
300 jsonw_int(self, num);
301}
302
303void jsonw_null_field(json_writer_t *self, const char *prop)
304{
305 jsonw_name(self, prop);
306 jsonw_null(self);
307}
308
309#ifdef TEST
310int main(int argc, char **argv)
311{
312 json_writer_t *wr = jsonw_new(stdout);
313
314 jsonw_start_object(wr);
315 jsonw_pretty(wr, true);
316 jsonw_name(wr, "Vyatta");
317 jsonw_start_object(wr);
318 jsonw_string_field(wr, "url", "http://vyatta.com");
319 jsonw_uint_field(wr, "downloads", 2000000ul);
320 jsonw_float_field(wr, "stock", 8.16);
321
322 jsonw_name(wr, "ARGV");
323 jsonw_start_array(wr);
324 while (--argc)
325 jsonw_string(wr, *++argv);
326 jsonw_end_array(wr);
327
328 jsonw_name(wr, "empty");
329 jsonw_start_array(wr);
330 jsonw_end_array(wr);
331
332 jsonw_name(wr, "NIL");
333 jsonw_start_object(wr);
334 jsonw_end_object(wr);
335
336 jsonw_null_field(wr, "my_null");
337
338 jsonw_name(wr, "special chars");
339 jsonw_start_array(wr);
340 jsonw_string_field(wr, "slash", "/");
341 jsonw_string_field(wr, "newline", "\n");
342 jsonw_string_field(wr, "tab", "\t");
343 jsonw_string_field(wr, "ff", "\f");
344 jsonw_string_field(wr, "quote", "\"");
345 jsonw_string_field(wr, "tick", "\'");
346 jsonw_string_field(wr, "backslash", "\\");
347 jsonw_end_array(wr);
348
349 jsonw_end_object(wr);
350
351 jsonw_end_object(wr);
352 jsonw_destroy(&wr);
353 return 0;
354}
355
356#endif
diff --git a/tools/bpf/bpftool/json_writer.h b/tools/bpf/bpftool/json_writer.h
new file mode 100644
index 000000000000..0fa2fb1b6351
--- /dev/null
+++ b/tools/bpf/bpftool/json_writer.h
@@ -0,0 +1,72 @@
1/*
2 * Simple streaming JSON writer
3 *
4 * This takes care of the annoying bits of JSON syntax like the commas
5 * after elements
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 * Authors: Stephen Hemminger <stephen@networkplumber.org>
13 */
14
15#ifndef _JSON_WRITER_H_
16#define _JSON_WRITER_H_
17
18#include <stdbool.h>
19#include <stdint.h>
20#include <stdarg.h>
21
22/* Opaque class structure */
23typedef struct json_writer json_writer_t;
24
25/* Create a new JSON stream */
26json_writer_t *jsonw_new(FILE *f);
27/* End output to JSON stream */
28void jsonw_destroy(json_writer_t **self_p);
29
30/* Cause output to have pretty whitespace */
31void jsonw_pretty(json_writer_t *self, bool on);
32
33/* Add property name */
34void jsonw_name(json_writer_t *self, const char *name);
35
36/* Add value */
37void jsonw_vprintf_enquote(json_writer_t *self, const char *fmt, va_list ap);
38void jsonw_printf(json_writer_t *self, const char *fmt, ...);
39void jsonw_string(json_writer_t *self, const char *value);
40void jsonw_bool(json_writer_t *self, bool value);
41void jsonw_float(json_writer_t *self, double number);
42void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num);
43void jsonw_uint(json_writer_t *self, uint64_t number);
44void jsonw_hu(json_writer_t *self, unsigned short number);
45void jsonw_int(json_writer_t *self, int64_t number);
46void jsonw_null(json_writer_t *self);
47void jsonw_lluint(json_writer_t *self, unsigned long long int num);
48
49/* Useful Combinations of name and value */
50void jsonw_string_field(json_writer_t *self, const char *prop, const char *val);
51void jsonw_bool_field(json_writer_t *self, const char *prop, bool value);
52void jsonw_float_field(json_writer_t *self, const char *prop, double num);
53void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num);
54void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num);
55void jsonw_int_field(json_writer_t *self, const char *prop, int64_t num);
56void jsonw_null_field(json_writer_t *self, const char *prop);
57void jsonw_lluint_field(json_writer_t *self, const char *prop,
58 unsigned long long int num);
59void jsonw_float_field_fmt(json_writer_t *self, const char *prop,
60 const char *fmt, double val);
61
62/* Collections */
63void jsonw_start_object(json_writer_t *self);
64void jsonw_end_object(json_writer_t *self);
65
66void jsonw_start_array(json_writer_t *self);
67void jsonw_end_array(json_writer_t *self);
68
69/* Override default exception handling */
70typedef void (jsonw_err_handler_fn)(const char *);
71
72#endif /* _JSON_WRITER_H_ */
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
new file mode 100644
index 000000000000..d6e4762170a4
--- /dev/null
+++ b/tools/bpf/bpftool/main.c
@@ -0,0 +1,331 @@
1/*
2 * Copyright (C) 2017 Netronome Systems, Inc.
3 *
4 * This software is dual licensed under the GNU General License Version 2,
5 * June 1991 as shown in the file COPYING in the top-level directory of this
6 * source tree or the BSD 2-Clause License provided below. You have the
7 * option to license this software under the complete terms of either license.
8 *
9 * The BSD 2-Clause License:
10 *
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
13 * conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34/* Author: Jakub Kicinski <kubakici@wp.pl> */
35
36#include <bfd.h>
37#include <ctype.h>
38#include <errno.h>
39#include <getopt.h>
40#include <linux/bpf.h>
41#include <linux/version.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45
46#include <bpf.h>
47
48#include "main.h"
49
50const char *bin_name;
51static int last_argc;
52static char **last_argv;
53static int (*last_do_help)(int argc, char **argv);
54json_writer_t *json_wtr;
55bool pretty_output;
56bool json_output;
57bool show_pinned;
58struct pinned_obj_table prog_table;
59struct pinned_obj_table map_table;
60
61void usage(void)
62{
63 last_do_help(last_argc - 1, last_argv + 1);
64
65 exit(-1);
66}
67
68static int do_help(int argc, char **argv)
69{
70 if (json_output) {
71 jsonw_null(json_wtr);
72 return 0;
73 }
74
75 fprintf(stderr,
76 "Usage: %s [OPTIONS] OBJECT { COMMAND | help }\n"
77 " %s batch file FILE\n"
78 " %s version\n"
79 "\n"
80 " OBJECT := { prog | map }\n"
81 " " HELP_SPEC_OPTIONS "\n"
82 "",
83 bin_name, bin_name, bin_name);
84
85 return 0;
86}
87
88static int do_version(int argc, char **argv)
89{
90 unsigned int version[3];
91
92 version[0] = LINUX_VERSION_CODE >> 16;
93 version[1] = LINUX_VERSION_CODE >> 8 & 0xf;
94 version[2] = LINUX_VERSION_CODE & 0xf;
95
96 if (json_output) {
97 jsonw_start_object(json_wtr);
98 jsonw_name(json_wtr, "version");
99 jsonw_printf(json_wtr, "\"%u.%u.%u\"",
100 version[0], version[1], version[2]);
101 jsonw_end_object(json_wtr);
102 } else {
103 printf("%s v%u.%u.%u\n", bin_name,
104 version[0], version[1], version[2]);
105 }
106 return 0;
107}
108
109int cmd_select(const struct cmd *cmds, int argc, char **argv,
110 int (*help)(int argc, char **argv))
111{
112 unsigned int i;
113
114 last_argc = argc;
115 last_argv = argv;
116 last_do_help = help;
117
118 if (argc < 1 && cmds[0].func)
119 return cmds[0].func(argc, argv);
120
121 for (i = 0; cmds[i].func; i++)
122 if (is_prefix(*argv, cmds[i].cmd))
123 return cmds[i].func(argc - 1, argv + 1);
124
125 help(argc - 1, argv + 1);
126
127 return -1;
128}
129
130bool is_prefix(const char *pfx, const char *str)
131{
132 if (!pfx)
133 return false;
134 if (strlen(str) < strlen(pfx))
135 return false;
136
137 return !memcmp(str, pfx, strlen(pfx));
138}
139
140void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep)
141{
142 unsigned char *data = arg;
143 unsigned int i;
144
145 for (i = 0; i < n; i++) {
146 const char *pfx = "";
147
148 if (!i)
149 /* nothing */;
150 else if (!(i % 16))
151 fprintf(f, "\n");
152 else if (!(i % 8))
153 fprintf(f, " ");
154 else
155 pfx = sep;
156
157 fprintf(f, "%s%02hhx", i ? pfx : "", data[i]);
158 }
159}
160
161static int do_batch(int argc, char **argv);
162
163static const struct cmd cmds[] = {
164 { "help", do_help },
165 { "batch", do_batch },
166 { "prog", do_prog },
167 { "map", do_map },
168 { "version", do_version },
169 { 0 }
170};
171
172static int do_batch(int argc, char **argv)
173{
174 unsigned int lines = 0;
175 char *n_argv[4096];
176 char buf[65536];
177 int n_argc;
178 FILE *fp;
179 int err;
180 int i;
181
182 if (argc < 2) {
183 p_err("too few parameters for batch");
184 return -1;
185 } else if (!is_prefix(*argv, "file")) {
186 p_err("expected 'file', got: %s", *argv);
187 return -1;
188 } else if (argc > 2) {
189 p_err("too many parameters for batch");
190 return -1;
191 }
192 NEXT_ARG();
193
194 fp = fopen(*argv, "r");
195 if (!fp) {
196 p_err("Can't open file (%s): %s", *argv, strerror(errno));
197 return -1;
198 }
199
200 if (json_output)
201 jsonw_start_array(json_wtr);
202 while (fgets(buf, sizeof(buf), fp)) {
203 if (strlen(buf) == sizeof(buf) - 1) {
204 errno = E2BIG;
205 break;
206 }
207
208 n_argc = 0;
209 n_argv[n_argc] = strtok(buf, " \t\n");
210
211 while (n_argv[n_argc]) {
212 n_argc++;
213 if (n_argc == ARRAY_SIZE(n_argv)) {
214 p_err("line %d has too many arguments, skip",
215 lines);
216 n_argc = 0;
217 break;
218 }
219 n_argv[n_argc] = strtok(NULL, " \t\n");
220 }
221
222 if (!n_argc)
223 continue;
224
225 if (json_output) {
226 jsonw_start_object(json_wtr);
227 jsonw_name(json_wtr, "command");
228 jsonw_start_array(json_wtr);
229 for (i = 0; i < n_argc; i++)
230 jsonw_string(json_wtr, n_argv[i]);
231 jsonw_end_array(json_wtr);
232 jsonw_name(json_wtr, "output");
233 }
234
235 err = cmd_select(cmds, n_argc, n_argv, do_help);
236
237 if (json_output)
238 jsonw_end_object(json_wtr);
239
240 if (err)
241 goto err_close;
242
243 lines++;
244 }
245
246 if (errno && errno != ENOENT) {
247 perror("reading batch file failed");
248 err = -1;
249 } else {
250 p_info("processed %d lines", lines);
251 err = 0;
252 }
253err_close:
254 fclose(fp);
255
256 if (json_output)
257 jsonw_end_array(json_wtr);
258
259 return err;
260}
261
262int main(int argc, char **argv)
263{
264 static const struct option options[] = {
265 { "json", no_argument, NULL, 'j' },
266 { "help", no_argument, NULL, 'h' },
267 { "pretty", no_argument, NULL, 'p' },
268 { "version", no_argument, NULL, 'V' },
269 { "bpffs", no_argument, NULL, 'f' },
270 { 0 }
271 };
272 int opt, ret;
273
274 last_do_help = do_help;
275 pretty_output = false;
276 json_output = false;
277 show_pinned = false;
278 bin_name = argv[0];
279
280 hash_init(prog_table.table);
281 hash_init(map_table.table);
282
283 while ((opt = getopt_long(argc, argv, "Vhpjf",
284 options, NULL)) >= 0) {
285 switch (opt) {
286 case 'V':
287 return do_version(argc, argv);
288 case 'h':
289 return do_help(argc, argv);
290 case 'p':
291 pretty_output = true;
292 /* fall through */
293 case 'j':
294 json_output = true;
295 break;
296 case 'f':
297 show_pinned = true;
298 break;
299 default:
300 usage();
301 }
302 }
303
304 argc -= optind;
305 argv += optind;
306 if (argc < 0)
307 usage();
308
309 if (json_output) {
310 json_wtr = jsonw_new(stdout);
311 if (!json_wtr) {
312 p_err("failed to create JSON writer");
313 return -1;
314 }
315 jsonw_pretty(json_wtr, pretty_output);
316 }
317
318 bfd_init();
319
320 ret = cmd_select(cmds, argc, argv, do_help);
321
322 if (json_output)
323 jsonw_destroy(&json_wtr);
324
325 if (show_pinned) {
326 delete_pinned_obj_table(&prog_table);
327 delete_pinned_obj_table(&map_table);
328 }
329
330 return ret;
331}
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
new file mode 100644
index 000000000000..9c191e222d6f
--- /dev/null
+++ b/tools/bpf/bpftool/main.h
@@ -0,0 +1,122 @@
1/*
2 * Copyright (C) 2017 Netronome Systems, Inc.
3 *
4 * This software is dual licensed under the GNU General License Version 2,
5 * June 1991 as shown in the file COPYING in the top-level directory of this
6 * source tree or the BSD 2-Clause License provided below. You have the
7 * option to license this software under the complete terms of either license.
8 *
9 * The BSD 2-Clause License:
10 *
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
13 * conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34/* Author: Jakub Kicinski <kubakici@wp.pl> */
35
36#ifndef __BPF_TOOL_H
37#define __BPF_TOOL_H
38
39/* BFD and kernel.h both define GCC_VERSION, differently */
40#undef GCC_VERSION
41#include <stdbool.h>
42#include <stdio.h>
43#include <linux/bpf.h>
44#include <linux/kernel.h>
45#include <linux/hashtable.h>
46
47#include "json_writer.h"
48
49#define ptr_to_u64(ptr) ((__u64)(unsigned long)(ptr))
50
51#define NEXT_ARG() ({ argc--; argv++; if (argc < 0) usage(); })
52#define NEXT_ARGP() ({ (*argc)--; (*argv)++; if (*argc < 0) usage(); })
53#define BAD_ARG() ({ p_err("what is '%s'?\n", *argv); -1; })
54
55#define ERR_MAX_LEN 1024
56
57#define BPF_TAG_FMT "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
58
59#define HELP_SPEC_PROGRAM \
60 "PROG := { id PROG_ID | pinned FILE | tag PROG_TAG }"
61#define HELP_SPEC_OPTIONS \
62 "OPTIONS := { {-j|--json} [{-p|--pretty}] | {-f|--bpffs} }"
63
64enum bpf_obj_type {
65 BPF_OBJ_UNKNOWN,
66 BPF_OBJ_PROG,
67 BPF_OBJ_MAP,
68};
69
70extern const char *bin_name;
71
72extern json_writer_t *json_wtr;
73extern bool json_output;
74extern bool show_pinned;
75extern struct pinned_obj_table prog_table;
76extern struct pinned_obj_table map_table;
77
78void p_err(const char *fmt, ...);
79void p_info(const char *fmt, ...);
80
81bool is_prefix(const char *pfx, const char *str);
82void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep);
83void usage(void) __attribute__((noreturn));
84
85struct pinned_obj_table {
86 DECLARE_HASHTABLE(table, 16);
87};
88
89struct pinned_obj {
90 __u32 id;
91 char *path;
92 struct hlist_node hash;
93};
94
95int build_pinned_obj_table(struct pinned_obj_table *table,
96 enum bpf_obj_type type);
97void delete_pinned_obj_table(struct pinned_obj_table *tab);
98
99struct cmd {
100 const char *cmd;
101 int (*func)(int argc, char **argv);
102};
103
104int cmd_select(const struct cmd *cmds, int argc, char **argv,
105 int (*help)(int argc, char **argv));
106
107int get_fd_type(int fd);
108const char *get_fd_type_name(enum bpf_obj_type type);
109char *get_fdinfo(int fd, const char *key);
110int open_obj_pinned(char *path);
111int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type);
112int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32));
113
114int do_prog(int argc, char **arg);
115int do_map(int argc, char **arg);
116
117int prog_parse_fd(int *argc, char ***argv);
118
119void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes);
120void print_hex_data_json(uint8_t *data, size_t len);
121
122#endif
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
new file mode 100644
index 000000000000..e2450c8e88e6
--- /dev/null
+++ b/tools/bpf/bpftool/map.c
@@ -0,0 +1,899 @@
1/*
2 * Copyright (C) 2017 Netronome Systems, Inc.
3 *
4 * This software is dual licensed under the GNU General License Version 2,
5 * June 1991 as shown in the file COPYING in the top-level directory of this
6 * source tree or the BSD 2-Clause License provided below. You have the
7 * option to license this software under the complete terms of either license.
8 *
9 * The BSD 2-Clause License:
10 *
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
13 * conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34/* Author: Jakub Kicinski <kubakici@wp.pl> */
35
36#include <assert.h>
37#include <ctype.h>
38#include <errno.h>
39#include <fcntl.h>
40#include <stdbool.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <unistd.h>
45#include <sys/types.h>
46#include <sys/stat.h>
47
48#include <bpf.h>
49
50#include "main.h"
51
52static const char * const map_type_name[] = {
53 [BPF_MAP_TYPE_UNSPEC] = "unspec",
54 [BPF_MAP_TYPE_HASH] = "hash",
55 [BPF_MAP_TYPE_ARRAY] = "array",
56 [BPF_MAP_TYPE_PROG_ARRAY] = "prog_array",
57 [BPF_MAP_TYPE_PERF_EVENT_ARRAY] = "perf_event_array",
58 [BPF_MAP_TYPE_PERCPU_HASH] = "percpu_hash",
59 [BPF_MAP_TYPE_PERCPU_ARRAY] = "percpu_array",
60 [BPF_MAP_TYPE_STACK_TRACE] = "stack_trace",
61 [BPF_MAP_TYPE_CGROUP_ARRAY] = "cgroup_array",
62 [BPF_MAP_TYPE_LRU_HASH] = "lru_hash",
63 [BPF_MAP_TYPE_LRU_PERCPU_HASH] = "lru_percpu_hash",
64 [BPF_MAP_TYPE_LPM_TRIE] = "lpm_trie",
65 [BPF_MAP_TYPE_ARRAY_OF_MAPS] = "array_of_maps",
66 [BPF_MAP_TYPE_HASH_OF_MAPS] = "hash_of_maps",
67 [BPF_MAP_TYPE_DEVMAP] = "devmap",
68 [BPF_MAP_TYPE_SOCKMAP] = "sockmap",
69};
70
71static unsigned int get_possible_cpus(void)
72{
73 static unsigned int result;
74 char buf[128];
75 long int n;
76 char *ptr;
77 int fd;
78
79 if (result)
80 return result;
81
82 fd = open("/sys/devices/system/cpu/possible", O_RDONLY);
83 if (fd < 0) {
84 p_err("can't open sysfs possible cpus");
85 exit(-1);
86 }
87
88 n = read(fd, buf, sizeof(buf));
89 if (n < 2) {
90 p_err("can't read sysfs possible cpus");
91 exit(-1);
92 }
93 close(fd);
94
95 if (n == sizeof(buf)) {
96 p_err("read sysfs possible cpus overflow");
97 exit(-1);
98 }
99
100 ptr = buf;
101 n = 0;
102 while (*ptr && *ptr != '\n') {
103 unsigned int a, b;
104
105 if (sscanf(ptr, "%u-%u", &a, &b) == 2) {
106 n += b - a + 1;
107
108 ptr = strchr(ptr, '-') + 1;
109 } else if (sscanf(ptr, "%u", &a) == 1) {
110 n++;
111 } else {
112 assert(0);
113 }
114
115 while (isdigit(*ptr))
116 ptr++;
117 if (*ptr == ',')
118 ptr++;
119 }
120
121 result = n;
122
123 return result;
124}
125
126static bool map_is_per_cpu(__u32 type)
127{
128 return type == BPF_MAP_TYPE_PERCPU_HASH ||
129 type == BPF_MAP_TYPE_PERCPU_ARRAY ||
130 type == BPF_MAP_TYPE_LRU_PERCPU_HASH;
131}
132
133static bool map_is_map_of_maps(__u32 type)
134{
135 return type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
136 type == BPF_MAP_TYPE_HASH_OF_MAPS;
137}
138
139static bool map_is_map_of_progs(__u32 type)
140{
141 return type == BPF_MAP_TYPE_PROG_ARRAY;
142}
143
144static void *alloc_value(struct bpf_map_info *info)
145{
146 if (map_is_per_cpu(info->type))
147 return malloc(info->value_size * get_possible_cpus());
148 else
149 return malloc(info->value_size);
150}
151
152static int map_parse_fd(int *argc, char ***argv)
153{
154 int fd;
155
156 if (is_prefix(**argv, "id")) {
157 unsigned int id;
158 char *endptr;
159
160 NEXT_ARGP();
161
162 id = strtoul(**argv, &endptr, 0);
163 if (*endptr) {
164 p_err("can't parse %s as ID", **argv);
165 return -1;
166 }
167 NEXT_ARGP();
168
169 fd = bpf_map_get_fd_by_id(id);
170 if (fd < 0)
171 p_err("get map by id (%u): %s", id, strerror(errno));
172 return fd;
173 } else if (is_prefix(**argv, "pinned")) {
174 char *path;
175
176 NEXT_ARGP();
177
178 path = **argv;
179 NEXT_ARGP();
180
181 return open_obj_pinned_any(path, BPF_OBJ_MAP);
182 }
183
184 p_err("expected 'id' or 'pinned', got: '%s'?", **argv);
185 return -1;
186}
187
188static int
189map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len)
190{
191 int err;
192 int fd;
193
194 fd = map_parse_fd(argc, argv);
195 if (fd < 0)
196 return -1;
197
198 err = bpf_obj_get_info_by_fd(fd, info, info_len);
199 if (err) {
200 p_err("can't get map info: %s", strerror(errno));
201 close(fd);
202 return err;
203 }
204
205 return fd;
206}
207
208static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
209 unsigned char *value)
210{
211 jsonw_start_object(json_wtr);
212
213 if (!map_is_per_cpu(info->type)) {
214 jsonw_name(json_wtr, "key");
215 print_hex_data_json(key, info->key_size);
216 jsonw_name(json_wtr, "value");
217 print_hex_data_json(value, info->value_size);
218 } else {
219 unsigned int i, n;
220
221 n = get_possible_cpus();
222
223 jsonw_name(json_wtr, "key");
224 print_hex_data_json(key, info->key_size);
225
226 jsonw_name(json_wtr, "values");
227 jsonw_start_array(json_wtr);
228 for (i = 0; i < n; i++) {
229 jsonw_start_object(json_wtr);
230
231 jsonw_int_field(json_wtr, "cpu", i);
232
233 jsonw_name(json_wtr, "value");
234 print_hex_data_json(value + i * info->value_size,
235 info->value_size);
236
237 jsonw_end_object(json_wtr);
238 }
239 jsonw_end_array(json_wtr);
240 }
241
242 jsonw_end_object(json_wtr);
243}
244
245static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
246 unsigned char *value)
247{
248 if (!map_is_per_cpu(info->type)) {
249 bool single_line, break_names;
250
251 break_names = info->key_size > 16 || info->value_size > 16;
252 single_line = info->key_size + info->value_size <= 24 &&
253 !break_names;
254
255 printf("key:%c", break_names ? '\n' : ' ');
256 fprint_hex(stdout, key, info->key_size, " ");
257
258 printf(single_line ? " " : "\n");
259
260 printf("value:%c", break_names ? '\n' : ' ');
261 fprint_hex(stdout, value, info->value_size, " ");
262
263 printf("\n");
264 } else {
265 unsigned int i, n;
266
267 n = get_possible_cpus();
268
269 printf("key:\n");
270 fprint_hex(stdout, key, info->key_size, " ");
271 printf("\n");
272 for (i = 0; i < n; i++) {
273 printf("value (CPU %02d):%c",
274 i, info->value_size > 16 ? '\n' : ' ');
275 fprint_hex(stdout, value + i * info->value_size,
276 info->value_size, " ");
277 printf("\n");
278 }
279 }
280}
281
282static char **parse_bytes(char **argv, const char *name, unsigned char *val,
283 unsigned int n)
284{
285 unsigned int i = 0;
286 char *endptr;
287
288 while (i < n && argv[i]) {
289 val[i] = strtoul(argv[i], &endptr, 0);
290 if (*endptr) {
291 p_err("error parsing byte: %s", argv[i]);
292 return NULL;
293 }
294 i++;
295 }
296
297 if (i != n) {
298 p_err("%s expected %d bytes got %d", name, n, i);
299 return NULL;
300 }
301
302 return argv + i;
303}
304
305static int parse_elem(char **argv, struct bpf_map_info *info,
306 void *key, void *value, __u32 key_size, __u32 value_size,
307 __u32 *flags, __u32 **value_fd)
308{
309 if (!*argv) {
310 if (!key && !value)
311 return 0;
312 p_err("did not find %s", key ? "key" : "value");
313 return -1;
314 }
315
316 if (is_prefix(*argv, "key")) {
317 if (!key) {
318 if (key_size)
319 p_err("duplicate key");
320 else
321 p_err("unnecessary key");
322 return -1;
323 }
324
325 argv = parse_bytes(argv + 1, "key", key, key_size);
326 if (!argv)
327 return -1;
328
329 return parse_elem(argv, info, NULL, value, key_size, value_size,
330 flags, value_fd);
331 } else if (is_prefix(*argv, "value")) {
332 int fd;
333
334 if (!value) {
335 if (value_size)
336 p_err("duplicate value");
337 else
338 p_err("unnecessary value");
339 return -1;
340 }
341
342 argv++;
343
344 if (map_is_map_of_maps(info->type)) {
345 int argc = 2;
346
347 if (value_size != 4) {
348 p_err("value smaller than 4B for map in map?");
349 return -1;
350 }
351 if (!argv[0] || !argv[1]) {
352 p_err("not enough value arguments for map in map");
353 return -1;
354 }
355
356 fd = map_parse_fd(&argc, &argv);
357 if (fd < 0)
358 return -1;
359
360 *value_fd = value;
361 **value_fd = fd;
362 } else if (map_is_map_of_progs(info->type)) {
363 int argc = 2;
364
365 if (value_size != 4) {
366 p_err("value smaller than 4B for map of progs?");
367 return -1;
368 }
369 if (!argv[0] || !argv[1]) {
370 p_err("not enough value arguments for map of progs");
371 return -1;
372 }
373
374 fd = prog_parse_fd(&argc, &argv);
375 if (fd < 0)
376 return -1;
377
378 *value_fd = value;
379 **value_fd = fd;
380 } else {
381 argv = parse_bytes(argv, "value", value, value_size);
382 if (!argv)
383 return -1;
384 }
385
386 return parse_elem(argv, info, key, NULL, key_size, value_size,
387 flags, NULL);
388 } else if (is_prefix(*argv, "any") || is_prefix(*argv, "noexist") ||
389 is_prefix(*argv, "exist")) {
390 if (!flags) {
391 p_err("flags specified multiple times: %s", *argv);
392 return -1;
393 }
394
395 if (is_prefix(*argv, "any"))
396 *flags = BPF_ANY;
397 else if (is_prefix(*argv, "noexist"))
398 *flags = BPF_NOEXIST;
399 else if (is_prefix(*argv, "exist"))
400 *flags = BPF_EXIST;
401
402 return parse_elem(argv + 1, info, key, value, key_size,
403 value_size, NULL, value_fd);
404 }
405
406 p_err("expected key or value, got: %s", *argv);
407 return -1;
408}
409
410static int show_map_close_json(int fd, struct bpf_map_info *info)
411{
412 char *memlock;
413
414 memlock = get_fdinfo(fd, "memlock");
415 close(fd);
416
417 jsonw_start_object(json_wtr);
418
419 jsonw_uint_field(json_wtr, "id", info->id);
420 if (info->type < ARRAY_SIZE(map_type_name))
421 jsonw_string_field(json_wtr, "type",
422 map_type_name[info->type]);
423 else
424 jsonw_uint_field(json_wtr, "type", info->type);
425
426 if (*info->name)
427 jsonw_string_field(json_wtr, "name", info->name);
428
429 jsonw_name(json_wtr, "flags");
430 jsonw_printf(json_wtr, "%#x", info->map_flags);
431 jsonw_uint_field(json_wtr, "bytes_key", info->key_size);
432 jsonw_uint_field(json_wtr, "bytes_value", info->value_size);
433 jsonw_uint_field(json_wtr, "max_entries", info->max_entries);
434
435 if (memlock)
436 jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
437 free(memlock);
438
439 if (!hash_empty(map_table.table)) {
440 struct pinned_obj *obj;
441
442 jsonw_name(json_wtr, "pinned");
443 jsonw_start_array(json_wtr);
444 hash_for_each_possible(map_table.table, obj, hash, info->id) {
445 if (obj->id == info->id)
446 jsonw_string(json_wtr, obj->path);
447 }
448 jsonw_end_array(json_wtr);
449 }
450
451 jsonw_end_object(json_wtr);
452
453 return 0;
454}
455
456static int show_map_close_plain(int fd, struct bpf_map_info *info)
457{
458 char *memlock;
459
460 memlock = get_fdinfo(fd, "memlock");
461 close(fd);
462
463 printf("%u: ", info->id);
464 if (info->type < ARRAY_SIZE(map_type_name))
465 printf("%s ", map_type_name[info->type]);
466 else
467 printf("type %u ", info->type);
468
469 if (*info->name)
470 printf("name %s ", info->name);
471
472 printf("flags 0x%x\n", info->map_flags);
473 printf("\tkey %uB value %uB max_entries %u",
474 info->key_size, info->value_size, info->max_entries);
475
476 if (memlock)
477 printf(" memlock %sB", memlock);
478 free(memlock);
479
480 printf("\n");
481 if (!hash_empty(map_table.table)) {
482 struct pinned_obj *obj;
483
484 hash_for_each_possible(map_table.table, obj, hash, info->id) {
485 if (obj->id == info->id)
486 printf("\tpinned %s\n", obj->path);
487 }
488 }
489 return 0;
490}
491
492static int do_show(int argc, char **argv)
493{
494 struct bpf_map_info info = {};
495 __u32 len = sizeof(info);
496 __u32 id = 0;
497 int err;
498 int fd;
499
500 if (show_pinned)
501 build_pinned_obj_table(&map_table, BPF_OBJ_MAP);
502
503 if (argc == 2) {
504 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
505 if (fd < 0)
506 return -1;
507
508 if (json_output)
509 return show_map_close_json(fd, &info);
510 else
511 return show_map_close_plain(fd, &info);
512 }
513
514 if (argc)
515 return BAD_ARG();
516
517 if (json_output)
518 jsonw_start_array(json_wtr);
519 while (true) {
520 err = bpf_map_get_next_id(id, &id);
521 if (err) {
522 if (errno == ENOENT)
523 break;
524 p_err("can't get next map: %s%s", strerror(errno),
525 errno == EINVAL ? " -- kernel too old?" : "");
526 return -1;
527 }
528
529 fd = bpf_map_get_fd_by_id(id);
530 if (fd < 0) {
531 p_err("can't get map by id (%u): %s",
532 id, strerror(errno));
533 return -1;
534 }
535
536 err = bpf_obj_get_info_by_fd(fd, &info, &len);
537 if (err) {
538 p_err("can't get map info: %s", strerror(errno));
539 close(fd);
540 return -1;
541 }
542
543 if (json_output)
544 show_map_close_json(fd, &info);
545 else
546 show_map_close_plain(fd, &info);
547 }
548 if (json_output)
549 jsonw_end_array(json_wtr);
550
551 return errno == ENOENT ? 0 : -1;
552}
553
554static int do_dump(int argc, char **argv)
555{
556 void *key, *value, *prev_key;
557 unsigned int num_elems = 0;
558 struct bpf_map_info info = {};
559 __u32 len = sizeof(info);
560 int err;
561 int fd;
562
563 if (argc != 2)
564 usage();
565
566 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
567 if (fd < 0)
568 return -1;
569
570 if (map_is_map_of_maps(info.type) || map_is_map_of_progs(info.type)) {
571 p_err("Dumping maps of maps and program maps not supported");
572 close(fd);
573 return -1;
574 }
575
576 key = malloc(info.key_size);
577 value = alloc_value(&info);
578 if (!key || !value) {
579 p_err("mem alloc failed");
580 err = -1;
581 goto exit_free;
582 }
583
584 prev_key = NULL;
585 if (json_output)
586 jsonw_start_array(json_wtr);
587 while (true) {
588 err = bpf_map_get_next_key(fd, prev_key, key);
589 if (err) {
590 if (errno == ENOENT)
591 err = 0;
592 break;
593 }
594
595 if (!bpf_map_lookup_elem(fd, key, value)) {
596 if (json_output)
597 print_entry_json(&info, key, value);
598 else
599 print_entry_plain(&info, key, value);
600 } else {
601 if (json_output) {
602 jsonw_name(json_wtr, "key");
603 print_hex_data_json(key, info.key_size);
604 jsonw_name(json_wtr, "value");
605 jsonw_start_object(json_wtr);
606 jsonw_string_field(json_wtr, "error",
607 "can't lookup element");
608 jsonw_end_object(json_wtr);
609 } else {
610 p_info("can't lookup element with key: ");
611 fprint_hex(stderr, key, info.key_size, " ");
612 fprintf(stderr, "\n");
613 }
614 }
615
616 prev_key = key;
617 num_elems++;
618 }
619
620 if (json_output)
621 jsonw_end_array(json_wtr);
622 else
623 printf("Found %u element%s\n", num_elems,
624 num_elems != 1 ? "s" : "");
625
626exit_free:
627 free(key);
628 free(value);
629 close(fd);
630
631 return err;
632}
633
634static int do_update(int argc, char **argv)
635{
636 struct bpf_map_info info = {};
637 __u32 len = sizeof(info);
638 __u32 *value_fd = NULL;
639 __u32 flags = BPF_ANY;
640 void *key, *value;
641 int fd, err;
642
643 if (argc < 2)
644 usage();
645
646 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
647 if (fd < 0)
648 return -1;
649
650 key = malloc(info.key_size);
651 value = alloc_value(&info);
652 if (!key || !value) {
653 p_err("mem alloc failed");
654 err = -1;
655 goto exit_free;
656 }
657
658 err = parse_elem(argv, &info, key, value, info.key_size,
659 info.value_size, &flags, &value_fd);
660 if (err)
661 goto exit_free;
662
663 err = bpf_map_update_elem(fd, key, value, flags);
664 if (err) {
665 p_err("update failed: %s", strerror(errno));
666 goto exit_free;
667 }
668
669exit_free:
670 if (value_fd)
671 close(*value_fd);
672 free(key);
673 free(value);
674 close(fd);
675
676 if (!err && json_output)
677 jsonw_null(json_wtr);
678 return err;
679}
680
681static int do_lookup(int argc, char **argv)
682{
683 struct bpf_map_info info = {};
684 __u32 len = sizeof(info);
685 void *key, *value;
686 int err;
687 int fd;
688
689 if (argc < 2)
690 usage();
691
692 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
693 if (fd < 0)
694 return -1;
695
696 key = malloc(info.key_size);
697 value = alloc_value(&info);
698 if (!key || !value) {
699 p_err("mem alloc failed");
700 err = -1;
701 goto exit_free;
702 }
703
704 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
705 if (err)
706 goto exit_free;
707
708 err = bpf_map_lookup_elem(fd, key, value);
709 if (!err) {
710 if (json_output)
711 print_entry_json(&info, key, value);
712 else
713 print_entry_plain(&info, key, value);
714 } else if (errno == ENOENT) {
715 if (json_output) {
716 jsonw_null(json_wtr);
717 } else {
718 printf("key:\n");
719 fprint_hex(stdout, key, info.key_size, " ");
720 printf("\n\nNot found\n");
721 }
722 } else {
723 p_err("lookup failed: %s", strerror(errno));
724 }
725
726exit_free:
727 free(key);
728 free(value);
729 close(fd);
730
731 return err;
732}
733
734static int do_getnext(int argc, char **argv)
735{
736 struct bpf_map_info info = {};
737 __u32 len = sizeof(info);
738 void *key, *nextkey;
739 int err;
740 int fd;
741
742 if (argc < 2)
743 usage();
744
745 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
746 if (fd < 0)
747 return -1;
748
749 key = malloc(info.key_size);
750 nextkey = malloc(info.key_size);
751 if (!key || !nextkey) {
752 p_err("mem alloc failed");
753 err = -1;
754 goto exit_free;
755 }
756
757 if (argc) {
758 err = parse_elem(argv, &info, key, NULL, info.key_size, 0,
759 NULL, NULL);
760 if (err)
761 goto exit_free;
762 } else {
763 free(key);
764 key = NULL;
765 }
766
767 err = bpf_map_get_next_key(fd, key, nextkey);
768 if (err) {
769 p_err("can't get next key: %s", strerror(errno));
770 goto exit_free;
771 }
772
773 if (json_output) {
774 jsonw_start_object(json_wtr);
775 if (key) {
776 jsonw_name(json_wtr, "key");
777 print_hex_data_json(key, info.key_size);
778 } else {
779 jsonw_null_field(json_wtr, "key");
780 }
781 jsonw_name(json_wtr, "next_key");
782 print_hex_data_json(nextkey, info.key_size);
783 jsonw_end_object(json_wtr);
784 } else {
785 if (key) {
786 printf("key:\n");
787 fprint_hex(stdout, key, info.key_size, " ");
788 printf("\n");
789 } else {
790 printf("key: None\n");
791 }
792 printf("next key:\n");
793 fprint_hex(stdout, nextkey, info.key_size, " ");
794 printf("\n");
795 }
796
797exit_free:
798 free(nextkey);
799 free(key);
800 close(fd);
801
802 return err;
803}
804
805static int do_delete(int argc, char **argv)
806{
807 struct bpf_map_info info = {};
808 __u32 len = sizeof(info);
809 void *key;
810 int err;
811 int fd;
812
813 if (argc < 2)
814 usage();
815
816 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
817 if (fd < 0)
818 return -1;
819
820 key = malloc(info.key_size);
821 if (!key) {
822 p_err("mem alloc failed");
823 err = -1;
824 goto exit_free;
825 }
826
827 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
828 if (err)
829 goto exit_free;
830
831 err = bpf_map_delete_elem(fd, key);
832 if (err)
833 p_err("delete failed: %s", strerror(errno));
834
835exit_free:
836 free(key);
837 close(fd);
838
839 if (!err && json_output)
840 jsonw_null(json_wtr);
841 return err;
842}
843
844static int do_pin(int argc, char **argv)
845{
846 int err;
847
848 err = do_pin_any(argc, argv, bpf_map_get_fd_by_id);
849 if (!err && json_output)
850 jsonw_null(json_wtr);
851 return err;
852}
853
854static int do_help(int argc, char **argv)
855{
856 if (json_output) {
857 jsonw_null(json_wtr);
858 return 0;
859 }
860
861 fprintf(stderr,
862 "Usage: %s %s show [MAP]\n"
863 " %s %s dump MAP\n"
864 " %s %s update MAP key BYTES value VALUE [UPDATE_FLAGS]\n"
865 " %s %s lookup MAP key BYTES\n"
866 " %s %s getnext MAP [key BYTES]\n"
867 " %s %s delete MAP key BYTES\n"
868 " %s %s pin MAP FILE\n"
869 " %s %s help\n"
870 "\n"
871 " MAP := { id MAP_ID | pinned FILE }\n"
872 " " HELP_SPEC_PROGRAM "\n"
873 " VALUE := { BYTES | MAP | PROG }\n"
874 " UPDATE_FLAGS := { any | exist | noexist }\n"
875 " " HELP_SPEC_OPTIONS "\n"
876 "",
877 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
878 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
879 bin_name, argv[-2], bin_name, argv[-2]);
880
881 return 0;
882}
883
884static const struct cmd cmds[] = {
885 { "show", do_show },
886 { "help", do_help },
887 { "dump", do_dump },
888 { "update", do_update },
889 { "lookup", do_lookup },
890 { "getnext", do_getnext },
891 { "delete", do_delete },
892 { "pin", do_pin },
893 { 0 }
894};
895
896int do_map(int argc, char **argv)
897{
898 return cmd_select(cmds, argc, argv, do_help);
899}
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
new file mode 100644
index 000000000000..ad619b96c276
--- /dev/null
+++ b/tools/bpf/bpftool/prog.c
@@ -0,0 +1,672 @@
1/*
2 * Copyright (C) 2017 Netronome Systems, Inc.
3 *
4 * This software is dual licensed under the GNU General License Version 2,
5 * June 1991 as shown in the file COPYING in the top-level directory of this
6 * source tree or the BSD 2-Clause License provided below. You have the
7 * option to license this software under the complete terms of either license.
8 *
9 * The BSD 2-Clause License:
10 *
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
13 * conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34/* Author: Jakub Kicinski <kubakici@wp.pl> */
35
36#include <errno.h>
37#include <fcntl.h>
38#include <stdarg.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <time.h>
43#include <unistd.h>
44#include <sys/types.h>
45#include <sys/stat.h>
46
47#include <bpf.h>
48
49#include "main.h"
50#include "disasm.h"
51
52static const char * const prog_type_name[] = {
53 [BPF_PROG_TYPE_UNSPEC] = "unspec",
54 [BPF_PROG_TYPE_SOCKET_FILTER] = "socket_filter",
55 [BPF_PROG_TYPE_KPROBE] = "kprobe",
56 [BPF_PROG_TYPE_SCHED_CLS] = "sched_cls",
57 [BPF_PROG_TYPE_SCHED_ACT] = "sched_act",
58 [BPF_PROG_TYPE_TRACEPOINT] = "tracepoint",
59 [BPF_PROG_TYPE_XDP] = "xdp",
60 [BPF_PROG_TYPE_PERF_EVENT] = "perf_event",
61 [BPF_PROG_TYPE_CGROUP_SKB] = "cgroup_skb",
62 [BPF_PROG_TYPE_CGROUP_SOCK] = "cgroup_sock",
63 [BPF_PROG_TYPE_LWT_IN] = "lwt_in",
64 [BPF_PROG_TYPE_LWT_OUT] = "lwt_out",
65 [BPF_PROG_TYPE_LWT_XMIT] = "lwt_xmit",
66 [BPF_PROG_TYPE_SOCK_OPS] = "sock_ops",
67 [BPF_PROG_TYPE_SK_SKB] = "sk_skb",
68};
69
70static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
71{
72 struct timespec real_time_ts, boot_time_ts;
73 time_t wallclock_secs;
74 struct tm load_tm;
75
76 buf[--size] = '\0';
77
78 if (clock_gettime(CLOCK_REALTIME, &real_time_ts) ||
79 clock_gettime(CLOCK_BOOTTIME, &boot_time_ts)) {
80 perror("Can't read clocks");
81 snprintf(buf, size, "%llu", nsecs / 1000000000);
82 return;
83 }
84
85 wallclock_secs = (real_time_ts.tv_sec - boot_time_ts.tv_sec) +
86 nsecs / 1000000000;
87
88 if (!localtime_r(&wallclock_secs, &load_tm)) {
89 snprintf(buf, size, "%llu", nsecs / 1000000000);
90 return;
91 }
92
93 strftime(buf, size, "%b %d/%H:%M", &load_tm);
94}
95
96static int prog_fd_by_tag(unsigned char *tag)
97{
98 struct bpf_prog_info info = {};
99 __u32 len = sizeof(info);
100 unsigned int id = 0;
101 int err;
102 int fd;
103
104 while (true) {
105 err = bpf_prog_get_next_id(id, &id);
106 if (err) {
107 p_err("%s", strerror(errno));
108 return -1;
109 }
110
111 fd = bpf_prog_get_fd_by_id(id);
112 if (fd < 0) {
113 p_err("can't get prog by id (%u): %s",
114 id, strerror(errno));
115 return -1;
116 }
117
118 err = bpf_obj_get_info_by_fd(fd, &info, &len);
119 if (err) {
120 p_err("can't get prog info (%u): %s",
121 id, strerror(errno));
122 close(fd);
123 return -1;
124 }
125
126 if (!memcmp(tag, info.tag, BPF_TAG_SIZE))
127 return fd;
128
129 close(fd);
130 }
131}
132
133int prog_parse_fd(int *argc, char ***argv)
134{
135 int fd;
136
137 if (is_prefix(**argv, "id")) {
138 unsigned int id;
139 char *endptr;
140
141 NEXT_ARGP();
142
143 id = strtoul(**argv, &endptr, 0);
144 if (*endptr) {
145 p_err("can't parse %s as ID", **argv);
146 return -1;
147 }
148 NEXT_ARGP();
149
150 fd = bpf_prog_get_fd_by_id(id);
151 if (fd < 0)
152 p_err("get by id (%u): %s", id, strerror(errno));
153 return fd;
154 } else if (is_prefix(**argv, "tag")) {
155 unsigned char tag[BPF_TAG_SIZE];
156
157 NEXT_ARGP();
158
159 if (sscanf(**argv, BPF_TAG_FMT, tag, tag + 1, tag + 2,
160 tag + 3, tag + 4, tag + 5, tag + 6, tag + 7)
161 != BPF_TAG_SIZE) {
162 p_err("can't parse tag");
163 return -1;
164 }
165 NEXT_ARGP();
166
167 return prog_fd_by_tag(tag);
168 } else if (is_prefix(**argv, "pinned")) {
169 char *path;
170
171 NEXT_ARGP();
172
173 path = **argv;
174 NEXT_ARGP();
175
176 return open_obj_pinned_any(path, BPF_OBJ_PROG);
177 }
178
179 p_err("expected 'id', 'tag' or 'pinned', got: '%s'?", **argv);
180 return -1;
181}
182
183static void show_prog_maps(int fd, u32 num_maps)
184{
185 struct bpf_prog_info info = {};
186 __u32 len = sizeof(info);
187 __u32 map_ids[num_maps];
188 unsigned int i;
189 int err;
190
191 info.nr_map_ids = num_maps;
192 info.map_ids = ptr_to_u64(map_ids);
193
194 err = bpf_obj_get_info_by_fd(fd, &info, &len);
195 if (err || !info.nr_map_ids)
196 return;
197
198 if (json_output) {
199 jsonw_name(json_wtr, "map_ids");
200 jsonw_start_array(json_wtr);
201 for (i = 0; i < info.nr_map_ids; i++)
202 jsonw_uint(json_wtr, map_ids[i]);
203 jsonw_end_array(json_wtr);
204 } else {
205 printf(" map_ids ");
206 for (i = 0; i < info.nr_map_ids; i++)
207 printf("%u%s", map_ids[i],
208 i == info.nr_map_ids - 1 ? "" : ",");
209 }
210}
211
212static void print_prog_json(struct bpf_prog_info *info, int fd)
213{
214 char *memlock;
215
216 jsonw_start_object(json_wtr);
217 jsonw_uint_field(json_wtr, "id", info->id);
218 if (info->type < ARRAY_SIZE(prog_type_name))
219 jsonw_string_field(json_wtr, "type",
220 prog_type_name[info->type]);
221 else
222 jsonw_uint_field(json_wtr, "type", info->type);
223
224 if (*info->name)
225 jsonw_string_field(json_wtr, "name", info->name);
226
227 jsonw_name(json_wtr, "tag");
228 jsonw_printf(json_wtr, "\"" BPF_TAG_FMT "\"",
229 info->tag[0], info->tag[1], info->tag[2], info->tag[3],
230 info->tag[4], info->tag[5], info->tag[6], info->tag[7]);
231
232 if (info->load_time) {
233 char buf[32];
234
235 print_boot_time(info->load_time, buf, sizeof(buf));
236
237 /* Piggy back on load_time, since 0 uid is a valid one */
238 jsonw_string_field(json_wtr, "loaded_at", buf);
239 jsonw_uint_field(json_wtr, "uid", info->created_by_uid);
240 }
241
242 jsonw_uint_field(json_wtr, "bytes_xlated", info->xlated_prog_len);
243
244 if (info->jited_prog_len) {
245 jsonw_bool_field(json_wtr, "jited", true);
246 jsonw_uint_field(json_wtr, "bytes_jited", info->jited_prog_len);
247 } else {
248 jsonw_bool_field(json_wtr, "jited", false);
249 }
250
251 memlock = get_fdinfo(fd, "memlock");
252 if (memlock)
253 jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
254 free(memlock);
255
256 if (info->nr_map_ids)
257 show_prog_maps(fd, info->nr_map_ids);
258
259 if (!hash_empty(prog_table.table)) {
260 struct pinned_obj *obj;
261
262 jsonw_name(json_wtr, "pinned");
263 jsonw_start_array(json_wtr);
264 hash_for_each_possible(prog_table.table, obj, hash, info->id) {
265 if (obj->id == info->id)
266 jsonw_string(json_wtr, obj->path);
267 }
268 jsonw_end_array(json_wtr);
269 }
270
271 jsonw_end_object(json_wtr);
272}
273
274static void print_prog_plain(struct bpf_prog_info *info, int fd)
275{
276 char *memlock;
277
278 printf("%u: ", info->id);
279 if (info->type < ARRAY_SIZE(prog_type_name))
280 printf("%s ", prog_type_name[info->type]);
281 else
282 printf("type %u ", info->type);
283
284 if (*info->name)
285 printf("name %s ", info->name);
286
287 printf("tag ");
288 fprint_hex(stdout, info->tag, BPF_TAG_SIZE, "");
289 printf("\n");
290
291 if (info->load_time) {
292 char buf[32];
293
294 print_boot_time(info->load_time, buf, sizeof(buf));
295
296 /* Piggy back on load_time, since 0 uid is a valid one */
297 printf("\tloaded_at %s uid %u\n", buf, info->created_by_uid);
298 }
299
300 printf("\txlated %uB", info->xlated_prog_len);
301
302 if (info->jited_prog_len)
303 printf(" jited %uB", info->jited_prog_len);
304 else
305 printf(" not jited");
306
307 memlock = get_fdinfo(fd, "memlock");
308 if (memlock)
309 printf(" memlock %sB", memlock);
310 free(memlock);
311
312 if (info->nr_map_ids)
313 show_prog_maps(fd, info->nr_map_ids);
314
315 if (!hash_empty(prog_table.table)) {
316 struct pinned_obj *obj;
317
318 printf("\n");
319 hash_for_each_possible(prog_table.table, obj, hash, info->id) {
320 if (obj->id == info->id)
321 printf("\tpinned %s\n", obj->path);
322 }
323 }
324
325 printf("\n");
326}
327
328static int show_prog(int fd)
329{
330 struct bpf_prog_info info = {};
331 __u32 len = sizeof(info);
332 int err;
333
334 err = bpf_obj_get_info_by_fd(fd, &info, &len);
335 if (err) {
336 p_err("can't get prog info: %s", strerror(errno));
337 return -1;
338 }
339
340 if (json_output)
341 print_prog_json(&info, fd);
342 else
343 print_prog_plain(&info, fd);
344
345 return 0;
346}
347
348static int do_show(int argc, char **argv)
349{
350 __u32 id = 0;
351 int err;
352 int fd;
353
354 if (show_pinned)
355 build_pinned_obj_table(&prog_table, BPF_OBJ_PROG);
356
357 if (argc == 2) {
358 fd = prog_parse_fd(&argc, &argv);
359 if (fd < 0)
360 return -1;
361
362 return show_prog(fd);
363 }
364
365 if (argc)
366 return BAD_ARG();
367
368 if (json_output)
369 jsonw_start_array(json_wtr);
370 while (true) {
371 err = bpf_prog_get_next_id(id, &id);
372 if (err) {
373 if (errno == ENOENT) {
374 err = 0;
375 break;
376 }
377 p_err("can't get next program: %s%s", strerror(errno),
378 errno == EINVAL ? " -- kernel too old?" : "");
379 err = -1;
380 break;
381 }
382
383 fd = bpf_prog_get_fd_by_id(id);
384 if (fd < 0) {
385 p_err("can't get prog by id (%u): %s",
386 id, strerror(errno));
387 err = -1;
388 break;
389 }
390
391 err = show_prog(fd);
392 close(fd);
393 if (err)
394 break;
395 }
396
397 if (json_output)
398 jsonw_end_array(json_wtr);
399
400 return err;
401}
402
403static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...)
404{
405 va_list args;
406
407 va_start(args, fmt);
408 vprintf(fmt, args);
409 va_end(args);
410}
411
412static void dump_xlated_plain(void *buf, unsigned int len, bool opcodes)
413{
414 struct bpf_insn *insn = buf;
415 bool double_insn = false;
416 unsigned int i;
417
418 for (i = 0; i < len / sizeof(*insn); i++) {
419 if (double_insn) {
420 double_insn = false;
421 continue;
422 }
423
424 double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
425
426 printf("% 4d: ", i);
427 print_bpf_insn(print_insn, NULL, insn + i, true);
428
429 if (opcodes) {
430 printf(" ");
431 fprint_hex(stdout, insn + i, 8, " ");
432 if (double_insn && i < len - 1) {
433 printf(" ");
434 fprint_hex(stdout, insn + i + 1, 8, " ");
435 }
436 printf("\n");
437 }
438 }
439}
440
441static void print_insn_json(struct bpf_verifier_env *env, const char *fmt, ...)
442{
443 unsigned int l = strlen(fmt);
444 char chomped_fmt[l];
445 va_list args;
446
447 va_start(args, fmt);
448 if (l > 0) {
449 strncpy(chomped_fmt, fmt, l - 1);
450 chomped_fmt[l - 1] = '\0';
451 }
452 jsonw_vprintf_enquote(json_wtr, chomped_fmt, args);
453 va_end(args);
454}
455
456static void dump_xlated_json(void *buf, unsigned int len, bool opcodes)
457{
458 struct bpf_insn *insn = buf;
459 bool double_insn = false;
460 unsigned int i;
461
462 jsonw_start_array(json_wtr);
463 for (i = 0; i < len / sizeof(*insn); i++) {
464 if (double_insn) {
465 double_insn = false;
466 continue;
467 }
468 double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
469
470 jsonw_start_object(json_wtr);
471 jsonw_name(json_wtr, "disasm");
472 print_bpf_insn(print_insn_json, NULL, insn + i, true);
473
474 if (opcodes) {
475 jsonw_name(json_wtr, "opcodes");
476 jsonw_start_object(json_wtr);
477
478 jsonw_name(json_wtr, "code");
479 jsonw_printf(json_wtr, "\"0x%02hhx\"", insn[i].code);
480
481 jsonw_name(json_wtr, "src_reg");
482 jsonw_printf(json_wtr, "\"0x%hhx\"", insn[i].src_reg);
483
484 jsonw_name(json_wtr, "dst_reg");
485 jsonw_printf(json_wtr, "\"0x%hhx\"", insn[i].dst_reg);
486
487 jsonw_name(json_wtr, "off");
488 print_hex_data_json((uint8_t *)(&insn[i].off), 2);
489
490 jsonw_name(json_wtr, "imm");
491 if (double_insn && i < len - 1)
492 print_hex_data_json((uint8_t *)(&insn[i].imm),
493 12);
494 else
495 print_hex_data_json((uint8_t *)(&insn[i].imm),
496 4);
497 jsonw_end_object(json_wtr);
498 }
499 jsonw_end_object(json_wtr);
500 }
501 jsonw_end_array(json_wtr);
502}
503
504static int do_dump(int argc, char **argv)
505{
506 struct bpf_prog_info info = {};
507 __u32 len = sizeof(info);
508 unsigned int buf_size;
509 char *filepath = NULL;
510 bool opcodes = false;
511 unsigned char *buf;
512 __u32 *member_len;
513 __u64 *member_ptr;
514 ssize_t n;
515 int err;
516 int fd;
517
518 if (is_prefix(*argv, "jited")) {
519 member_len = &info.jited_prog_len;
520 member_ptr = &info.jited_prog_insns;
521 } else if (is_prefix(*argv, "xlated")) {
522 member_len = &info.xlated_prog_len;
523 member_ptr = &info.xlated_prog_insns;
524 } else {
525 p_err("expected 'xlated' or 'jited', got: %s", *argv);
526 return -1;
527 }
528 NEXT_ARG();
529
530 if (argc < 2)
531 usage();
532
533 fd = prog_parse_fd(&argc, &argv);
534 if (fd < 0)
535 return -1;
536
537 if (is_prefix(*argv, "file")) {
538 NEXT_ARG();
539 if (!argc) {
540 p_err("expected file path");
541 return -1;
542 }
543
544 filepath = *argv;
545 NEXT_ARG();
546 } else if (is_prefix(*argv, "opcodes")) {
547 opcodes = true;
548 NEXT_ARG();
549 }
550
551 if (argc) {
552 usage();
553 return -1;
554 }
555
556 err = bpf_obj_get_info_by_fd(fd, &info, &len);
557 if (err) {
558 p_err("can't get prog info: %s", strerror(errno));
559 return -1;
560 }
561
562 if (!*member_len) {
563 p_info("no instructions returned");
564 close(fd);
565 return 0;
566 }
567
568 buf_size = *member_len;
569
570 buf = malloc(buf_size);
571 if (!buf) {
572 p_err("mem alloc failed");
573 close(fd);
574 return -1;
575 }
576
577 memset(&info, 0, sizeof(info));
578
579 *member_ptr = ptr_to_u64(buf);
580 *member_len = buf_size;
581
582 err = bpf_obj_get_info_by_fd(fd, &info, &len);
583 close(fd);
584 if (err) {
585 p_err("can't get prog info: %s", strerror(errno));
586 goto err_free;
587 }
588
589 if (*member_len > buf_size) {
590 p_err("too many instructions returned");
591 goto err_free;
592 }
593
594 if (filepath) {
595 fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
596 if (fd < 0) {
597 p_err("can't open file %s: %s", filepath,
598 strerror(errno));
599 goto err_free;
600 }
601
602 n = write(fd, buf, *member_len);
603 close(fd);
604 if (n != *member_len) {
605 p_err("error writing output file: %s",
606 n < 0 ? strerror(errno) : "short write");
607 goto err_free;
608 }
609 } else {
610 if (member_len == &info.jited_prog_len)
611 disasm_print_insn(buf, *member_len, opcodes);
612 else
613 if (json_output)
614 dump_xlated_json(buf, *member_len, opcodes);
615 else
616 dump_xlated_plain(buf, *member_len, opcodes);
617 }
618
619 free(buf);
620
621 return 0;
622
623err_free:
624 free(buf);
625 return -1;
626}
627
628static int do_pin(int argc, char **argv)
629{
630 int err;
631
632 err = do_pin_any(argc, argv, bpf_prog_get_fd_by_id);
633 if (!err && json_output)
634 jsonw_null(json_wtr);
635 return err;
636}
637
638static int do_help(int argc, char **argv)
639{
640 if (json_output) {
641 jsonw_null(json_wtr);
642 return 0;
643 }
644
645 fprintf(stderr,
646 "Usage: %s %s show [PROG]\n"
647 " %s %s dump xlated PROG [{ file FILE | opcodes }]\n"
648 " %s %s dump jited PROG [{ file FILE | opcodes }]\n"
649 " %s %s pin PROG FILE\n"
650 " %s %s help\n"
651 "\n"
652 " " HELP_SPEC_PROGRAM "\n"
653 " " HELP_SPEC_OPTIONS "\n"
654 "",
655 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
656 bin_name, argv[-2], bin_name, argv[-2]);
657
658 return 0;
659}
660
661static const struct cmd cmds[] = {
662 { "show", do_show },
663 { "help", do_help },
664 { "dump", do_dump },
665 { "pin", do_pin },
666 { 0 }
667};
668
669int do_prog(int argc, char **argv)
670{
671 return cmd_select(cmds, argc, argv, do_help);
672}
diff --git a/tools/build/Makefile b/tools/build/Makefile
index 477f00eda591..5eb4b5ad79cb 100644
--- a/tools/build/Makefile
+++ b/tools/build/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1ifeq ($(srctree),) 2ifeq ($(srctree),)
2srctree := $(patsubst %/,%,$(dir $(CURDIR))) 3srctree := $(patsubst %/,%,$(dir $(CURDIR)))
3srctree := $(patsubst %/,%,$(dir $(srctree))) 4srctree := $(patsubst %/,%,$(dir $(srctree)))
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
index c46b20e4ad87..cd72016c3cfa 100644
--- a/tools/build/Makefile.build
+++ b/tools/build/Makefile.build
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1### 2###
2# Main build makefile. 3# Main build makefile.
3# 4#
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 523911f316ce..c71a05b9c984 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -64,7 +64,8 @@ FEATURE_TESTS_BASIC := \
64 get_cpuid \ 64 get_cpuid \
65 bpf \ 65 bpf \
66 sched_getcpu \ 66 sched_getcpu \
67 sdt 67 sdt \
68 setns
68 69
69# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list 70# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
70# of all feature tests 71# of all feature tests
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index e35e4e5ad192..96982640fbf8 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1FILES= \ 2FILES= \
2 test-all.bin \ 3 test-all.bin \
3 test-backtrace.bin \ 4 test-backtrace.bin \
@@ -49,7 +50,8 @@ FILES= \
49 test-sdt.bin \ 50 test-sdt.bin \
50 test-cxx.bin \ 51 test-cxx.bin \
51 test-jvmti.bin \ 52 test-jvmti.bin \
52 test-sched_getcpu.bin 53 test-sched_getcpu.bin \
54 test-setns.bin
53 55
54FILES := $(addprefix $(OUTPUT),$(FILES)) 56FILES := $(addprefix $(OUTPUT),$(FILES))
55 57
@@ -95,6 +97,9 @@ $(OUTPUT)test-glibc.bin:
95$(OUTPUT)test-sched_getcpu.bin: 97$(OUTPUT)test-sched_getcpu.bin:
96 $(BUILD) 98 $(BUILD)
97 99
100$(OUTPUT)test-setns.bin:
101 $(BUILD)
102
98DWARFLIBS := -ldw 103DWARFLIBS := -ldw
99ifeq ($(findstring -static,${LDFLAGS}),-static) 104ifeq ($(findstring -static,${LDFLAGS}),-static)
100DWARFLIBS += -lelf -lebl -lz -llzma -lbz2 105DWARFLIBS += -lelf -lebl -lz -llzma -lbz2
diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c
index cc6c7c01f4ca..4112702e4aed 100644
--- a/tools/build/feature/test-all.c
+++ b/tools/build/feature/test-all.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * test-all.c: Try to build all the main testcases at once. 3 * test-all.c: Try to build all the main testcases at once.
3 * 4 *
@@ -153,6 +154,10 @@
153# include "test-sdt.c" 154# include "test-sdt.c"
154#undef main 155#undef main
155 156
157#define main main_test_setns
158# include "test-setns.c"
159#undef main
160
156int main(int argc, char *argv[]) 161int main(int argc, char *argv[])
157{ 162{
158 main_test_libpython(); 163 main_test_libpython();
@@ -188,6 +193,7 @@ int main(int argc, char *argv[])
188 main_test_libcrypto(); 193 main_test_libcrypto();
189 main_test_sched_getcpu(); 194 main_test_sched_getcpu();
190 main_test_sdt(); 195 main_test_sdt();
196 main_test_setns();
191 197
192 return 0; 198 return 0;
193} 199}
diff --git a/tools/build/feature/test-backtrace.c b/tools/build/feature/test-backtrace.c
index 7124aa1dc8fb..e9ddd27c69c3 100644
--- a/tools/build/feature/test-backtrace.c
+++ b/tools/build/feature/test-backtrace.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <execinfo.h> 2#include <execinfo.h>
2#include <stdio.h> 3#include <stdio.h>
3 4
diff --git a/tools/build/feature/test-bionic.c b/tools/build/feature/test-bionic.c
index eac24e9513eb..4bcc9776504c 100644
--- a/tools/build/feature/test-bionic.c
+++ b/tools/build/feature/test-bionic.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <android/api-level.h> 2#include <android/api-level.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/build/feature/test-bpf.c b/tools/build/feature/test-bpf.c
index 7598361ef1f1..82070eadfc07 100644
--- a/tools/build/feature/test-bpf.c
+++ b/tools/build/feature/test-bpf.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <asm/unistd.h> 2#include <asm/unistd.h>
2#include <linux/bpf.h> 3#include <linux/bpf.h>
3#include <unistd.h> 4#include <unistd.h>
@@ -11,6 +12,8 @@
11# define __NR_bpf 280 12# define __NR_bpf 280
12# elif defined(__sparc__) 13# elif defined(__sparc__)
13# define __NR_bpf 349 14# define __NR_bpf 349
15# elif defined(__s390__)
16# define __NR_bpf 351
14# else 17# else
15# error __NR_bpf not defined. libbpf does not support your arch. 18# error __NR_bpf not defined. libbpf does not support your arch.
16# endif 19# endif
diff --git a/tools/build/feature/test-clang.cpp b/tools/build/feature/test-clang.cpp
index e23c1b1f1b91..a2b3f092d2f0 100644
--- a/tools/build/feature/test-clang.cpp
+++ b/tools/build/feature/test-clang.cpp
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "clang/Basic/VirtualFileSystem.h" 2#include "clang/Basic/VirtualFileSystem.h"
2#include "clang/Driver/Driver.h" 3#include "clang/Driver/Driver.h"
3#include "clang/Frontend/TextDiagnosticPrinter.h" 4#include "clang/Frontend/TextDiagnosticPrinter.h"
diff --git a/tools/build/feature/test-compile.c b/tools/build/feature/test-compile.c
index c54e6551ae4c..9821b8271dee 100644
--- a/tools/build/feature/test-compile.c
+++ b/tools/build/feature/test-compile.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2int main(void) 3int main(void)
3{ 4{
diff --git a/tools/build/feature/test-cplus-demangle.c b/tools/build/feature/test-cplus-demangle.c
index 610c686e0009..2ba56474ab71 100644
--- a/tools/build/feature/test-cplus-demangle.c
+++ b/tools/build/feature/test-cplus-demangle.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1extern int printf(const char *format, ...); 2extern int printf(const char *format, ...);
2extern char *cplus_demangle(const char *, int); 3extern char *cplus_demangle(const char *, int);
3 4
diff --git a/tools/build/feature/test-cxx.cpp b/tools/build/feature/test-cxx.cpp
index b1dee9a31d6c..396aaedd2418 100644
--- a/tools/build/feature/test-cxx.cpp
+++ b/tools/build/feature/test-cxx.cpp
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <iostream> 2#include <iostream>
2#include <memory> 3#include <memory>
3 4
diff --git a/tools/build/feature/test-dwarf.c b/tools/build/feature/test-dwarf.c
index 3fc1801ce4a9..8d474bd7371b 100644
--- a/tools/build/feature/test-dwarf.c
+++ b/tools/build/feature/test-dwarf.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <dwarf.h> 2#include <dwarf.h>
2#include <elfutils/libdw.h> 3#include <elfutils/libdw.h>
3#include <elfutils/version.h> 4#include <elfutils/version.h>
diff --git a/tools/build/feature/test-dwarf_getlocations.c b/tools/build/feature/test-dwarf_getlocations.c
index 70162699dd43..78fb4a1fa68c 100644
--- a/tools/build/feature/test-dwarf_getlocations.c
+++ b/tools/build/feature/test-dwarf_getlocations.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdlib.h> 2#include <stdlib.h>
2#include <elfutils/libdw.h> 3#include <elfutils/libdw.h>
3 4
diff --git a/tools/build/feature/test-get_cpuid.c b/tools/build/feature/test-get_cpuid.c
index d7a2c407130d..bb4f065f28a6 100644
--- a/tools/build/feature/test-get_cpuid.c
+++ b/tools/build/feature/test-get_cpuid.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <cpuid.h> 2#include <cpuid.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/build/feature/test-glibc.c b/tools/build/feature/test-glibc.c
index 9367f7586676..9ab8e90e7b88 100644
--- a/tools/build/feature/test-glibc.c
+++ b/tools/build/feature/test-glibc.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdlib.h> 2#include <stdlib.h>
2 3
3#if !defined(__UCLIBC__) 4#if !defined(__UCLIBC__)
diff --git a/tools/build/feature/test-gtk2-infobar.c b/tools/build/feature/test-gtk2-infobar.c
index 397b4646d066..b1b716dd5733 100644
--- a/tools/build/feature/test-gtk2-infobar.c
+++ b/tools/build/feature/test-gtk2-infobar.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#pragma GCC diagnostic ignored "-Wstrict-prototypes" 2#pragma GCC diagnostic ignored "-Wstrict-prototypes"
2#include <gtk/gtk.h> 3#include <gtk/gtk.h>
3#pragma GCC diagnostic error "-Wstrict-prototypes" 4#pragma GCC diagnostic error "-Wstrict-prototypes"
diff --git a/tools/build/feature/test-gtk2.c b/tools/build/feature/test-gtk2.c
index 6bd80e509439..2aaf4bfc2055 100644
--- a/tools/build/feature/test-gtk2.c
+++ b/tools/build/feature/test-gtk2.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#pragma GCC diagnostic ignored "-Wstrict-prototypes" 2#pragma GCC diagnostic ignored "-Wstrict-prototypes"
2#include <gtk/gtk.h> 3#include <gtk/gtk.h>
3#pragma GCC diagnostic error "-Wstrict-prototypes" 4#pragma GCC diagnostic error "-Wstrict-prototypes"
diff --git a/tools/build/feature/test-jvmti.c b/tools/build/feature/test-jvmti.c
index 1c665f09b9d6..5cf31192f204 100644
--- a/tools/build/feature/test-jvmti.c
+++ b/tools/build/feature/test-jvmti.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <jvmti.h> 2#include <jvmti.h>
2#include <jvmticmlr.h> 3#include <jvmticmlr.h>
3 4
diff --git a/tools/build/feature/test-libaudit.c b/tools/build/feature/test-libaudit.c
index afc019f08641..f5b0863fa1ec 100644
--- a/tools/build/feature/test-libaudit.c
+++ b/tools/build/feature/test-libaudit.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <libaudit.h> 2#include <libaudit.h>
2 3
3extern int printf(const char *format, ...); 4extern int printf(const char *format, ...);
diff --git a/tools/build/feature/test-libbabeltrace.c b/tools/build/feature/test-libbabeltrace.c
index 9cf802a04885..10bb69d55694 100644
--- a/tools/build/feature/test-libbabeltrace.c
+++ b/tools/build/feature/test-libbabeltrace.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1 2
2#include <babeltrace/ctf-writer/writer.h> 3#include <babeltrace/ctf-writer/writer.h>
3#include <babeltrace/ctf-ir/stream-class.h> 4#include <babeltrace/ctf-ir/stream-class.h>
diff --git a/tools/build/feature/test-libbfd.c b/tools/build/feature/test-libbfd.c
index 24059907e990..afa46b0465cd 100644
--- a/tools/build/feature/test-libbfd.c
+++ b/tools/build/feature/test-libbfd.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <bfd.h> 2#include <bfd.h>
2 3
3extern int printf(const char *format, ...); 4extern int printf(const char *format, ...);
diff --git a/tools/build/feature/test-libcrypto.c b/tools/build/feature/test-libcrypto.c
index bd79dc7f28d3..a98174e0569c 100644
--- a/tools/build/feature/test-libcrypto.c
+++ b/tools/build/feature/test-libcrypto.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <openssl/sha.h> 2#include <openssl/sha.h>
2#include <openssl/md5.h> 3#include <openssl/md5.h>
3 4
diff --git a/tools/build/feature/test-libdw-dwarf-unwind.c b/tools/build/feature/test-libdw-dwarf-unwind.c
index f676a3ff442a..ed03d9505609 100644
--- a/tools/build/feature/test-libdw-dwarf-unwind.c
+++ b/tools/build/feature/test-libdw-dwarf-unwind.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1 2
2#include <elfutils/libdwfl.h> 3#include <elfutils/libdwfl.h>
3 4
diff --git a/tools/build/feature/test-libelf-gelf_getnote.c b/tools/build/feature/test-libelf-gelf_getnote.c
index d78cf4d5271f..075d062fe841 100644
--- a/tools/build/feature/test-libelf-gelf_getnote.c
+++ b/tools/build/feature/test-libelf-gelf_getnote.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdlib.h> 2#include <stdlib.h>
2#include <gelf.h> 3#include <gelf.h>
3 4
diff --git a/tools/build/feature/test-libelf-getphdrnum.c b/tools/build/feature/test-libelf-getphdrnum.c
index d710459306c3..96a7f8d30a59 100644
--- a/tools/build/feature/test-libelf-getphdrnum.c
+++ b/tools/build/feature/test-libelf-getphdrnum.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <libelf.h> 2#include <libelf.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/build/feature/test-libelf-getshdrstrndx.c b/tools/build/feature/test-libelf-getshdrstrndx.c
index f0c3b47cce28..ae9f2fff5af0 100644
--- a/tools/build/feature/test-libelf-getshdrstrndx.c
+++ b/tools/build/feature/test-libelf-getshdrstrndx.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <libelf.h> 2#include <libelf.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/build/feature/test-libelf-mmap.c b/tools/build/feature/test-libelf-mmap.c
index 564427d7ef18..2c3ef81affe2 100644
--- a/tools/build/feature/test-libelf-mmap.c
+++ b/tools/build/feature/test-libelf-mmap.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <libelf.h> 2#include <libelf.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/build/feature/test-libelf.c b/tools/build/feature/test-libelf.c
index 08db322d8957..905044127d56 100644
--- a/tools/build/feature/test-libelf.c
+++ b/tools/build/feature/test-libelf.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <libelf.h> 2#include <libelf.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/build/feature/test-libnuma.c b/tools/build/feature/test-libnuma.c
index 4763d9cd587d..b3aa59f8b3cb 100644
--- a/tools/build/feature/test-libnuma.c
+++ b/tools/build/feature/test-libnuma.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <numa.h> 2#include <numa.h>
2#include <numaif.h> 3#include <numaif.h>
3 4
diff --git a/tools/build/feature/test-libperl.c b/tools/build/feature/test-libperl.c
index 8871f6a0fdb4..0415f437eb31 100644
--- a/tools/build/feature/test-libperl.c
+++ b/tools/build/feature/test-libperl.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <EXTERN.h> 2#include <EXTERN.h>
2#include <perl.h> 3#include <perl.h>
3 4
diff --git a/tools/build/feature/test-libpython-version.c b/tools/build/feature/test-libpython-version.c
index facea122d812..47714b942d4d 100644
--- a/tools/build/feature/test-libpython-version.c
+++ b/tools/build/feature/test-libpython-version.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <Python.h> 2#include <Python.h>
2 3
3#if PY_VERSION_HEX >= 0x03000000 4#if PY_VERSION_HEX >= 0x03000000
diff --git a/tools/build/feature/test-libpython.c b/tools/build/feature/test-libpython.c
index b24b28ad6324..0c1641b0d9a7 100644
--- a/tools/build/feature/test-libpython.c
+++ b/tools/build/feature/test-libpython.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <Python.h> 2#include <Python.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/build/feature/test-libslang.c b/tools/build/feature/test-libslang.c
index 22ff22ed94d1..9cbff8d1df53 100644
--- a/tools/build/feature/test-libslang.c
+++ b/tools/build/feature/test-libslang.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <slang.h> 2#include <slang.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/build/feature/test-libunwind-aarch64.c b/tools/build/feature/test-libunwind-aarch64.c
index fc03fb64e8c1..323803f49212 100644
--- a/tools/build/feature/test-libunwind-aarch64.c
+++ b/tools/build/feature/test-libunwind-aarch64.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <libunwind-aarch64.h> 2#include <libunwind-aarch64.h>
2#include <stdlib.h> 3#include <stdlib.h>
3 4
diff --git a/tools/build/feature/test-libunwind-arm.c b/tools/build/feature/test-libunwind-arm.c
index 632d95ec641f..cb378b7d6866 100644
--- a/tools/build/feature/test-libunwind-arm.c
+++ b/tools/build/feature/test-libunwind-arm.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <libunwind-arm.h> 2#include <libunwind-arm.h>
2#include <stdlib.h> 3#include <stdlib.h>
3 4
diff --git a/tools/build/feature/test-libunwind-debug-frame-aarch64.c b/tools/build/feature/test-libunwind-debug-frame-aarch64.c
index 22844673fc26..36d6646c185e 100644
--- a/tools/build/feature/test-libunwind-debug-frame-aarch64.c
+++ b/tools/build/feature/test-libunwind-debug-frame-aarch64.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <libunwind-aarch64.h> 2#include <libunwind-aarch64.h>
2#include <stdlib.h> 3#include <stdlib.h>
3 4
diff --git a/tools/build/feature/test-libunwind-debug-frame-arm.c b/tools/build/feature/test-libunwind-debug-frame-arm.c
index f98859684fee..8696e48e1268 100644
--- a/tools/build/feature/test-libunwind-debug-frame-arm.c
+++ b/tools/build/feature/test-libunwind-debug-frame-arm.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <libunwind-arm.h> 2#include <libunwind-arm.h>
2#include <stdlib.h> 3#include <stdlib.h>
3 4
diff --git a/tools/build/feature/test-libunwind-debug-frame.c b/tools/build/feature/test-libunwind-debug-frame.c
index 0ef8087a104a..efb55cdd8d01 100644
--- a/tools/build/feature/test-libunwind-debug-frame.c
+++ b/tools/build/feature/test-libunwind-debug-frame.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <libunwind.h> 2#include <libunwind.h>
2#include <stdlib.h> 3#include <stdlib.h>
3 4
diff --git a/tools/build/feature/test-libunwind-x86.c b/tools/build/feature/test-libunwind-x86.c
index 3561edce305e..e5e0f6c89637 100644
--- a/tools/build/feature/test-libunwind-x86.c
+++ b/tools/build/feature/test-libunwind-x86.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <libunwind-x86.h> 2#include <libunwind-x86.h>
2#include <stdlib.h> 3#include <stdlib.h>
3 4
diff --git a/tools/build/feature/test-libunwind-x86_64.c b/tools/build/feature/test-libunwind-x86_64.c
index 5add2517b2a1..62ae4db597dc 100644
--- a/tools/build/feature/test-libunwind-x86_64.c
+++ b/tools/build/feature/test-libunwind-x86_64.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <libunwind-x86_64.h> 2#include <libunwind-x86_64.h>
2#include <stdlib.h> 3#include <stdlib.h>
3 4
diff --git a/tools/build/feature/test-libunwind.c b/tools/build/feature/test-libunwind.c
index 43b9369bcab7..53fd26614ff0 100644
--- a/tools/build/feature/test-libunwind.c
+++ b/tools/build/feature/test-libunwind.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <libunwind.h> 2#include <libunwind.h>
2#include <stdlib.h> 3#include <stdlib.h>
3 4
diff --git a/tools/build/feature/test-llvm-version.cpp b/tools/build/feature/test-llvm-version.cpp
index 896d31724568..8a091625446a 100644
--- a/tools/build/feature/test-llvm-version.cpp
+++ b/tools/build/feature/test-llvm-version.cpp
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <cstdio> 2#include <cstdio>
2#include "llvm/Config/llvm-config.h" 3#include "llvm/Config/llvm-config.h"
3 4
diff --git a/tools/build/feature/test-llvm.cpp b/tools/build/feature/test-llvm.cpp
index 455a332dc8a8..88a3d1bdd9f6 100644
--- a/tools/build/feature/test-llvm.cpp
+++ b/tools/build/feature/test-llvm.cpp
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "llvm/Support/ManagedStatic.h" 2#include "llvm/Support/ManagedStatic.h"
2#include "llvm/Support/raw_ostream.h" 3#include "llvm/Support/raw_ostream.h"
3#define NUM_VERSION (((LLVM_VERSION_MAJOR) << 16) + (LLVM_VERSION_MINOR << 8) + LLVM_VERSION_PATCH) 4#define NUM_VERSION (((LLVM_VERSION_MAJOR) << 16) + (LLVM_VERSION_MINOR << 8) + LLVM_VERSION_PATCH)
diff --git a/tools/build/feature/test-lzma.c b/tools/build/feature/test-lzma.c
index 95adc8ced3dd..78682bb01d57 100644
--- a/tools/build/feature/test-lzma.c
+++ b/tools/build/feature/test-lzma.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <lzma.h> 2#include <lzma.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/build/feature/test-numa_num_possible_cpus.c b/tools/build/feature/test-numa_num_possible_cpus.c
index 2606e94b0659..573d07b9c570 100644
--- a/tools/build/feature/test-numa_num_possible_cpus.c
+++ b/tools/build/feature/test-numa_num_possible_cpus.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <numa.h> 2#include <numa.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/build/feature/test-pthread-attr-setaffinity-np.c b/tools/build/feature/test-pthread-attr-setaffinity-np.c
index fdada5e8d454..38c71131c452 100644
--- a/tools/build/feature/test-pthread-attr-setaffinity-np.c
+++ b/tools/build/feature/test-pthread-attr-setaffinity-np.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdint.h> 2#include <stdint.h>
2#include <pthread.h> 3#include <pthread.h>
3#include <sched.h> 4#include <sched.h>
diff --git a/tools/build/feature/test-sched_getcpu.c b/tools/build/feature/test-sched_getcpu.c
index 9c6b4cbffb1c..e448deb4124c 100644
--- a/tools/build/feature/test-sched_getcpu.c
+++ b/tools/build/feature/test-sched_getcpu.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#ifndef _GNU_SOURCE 2#ifndef _GNU_SOURCE
2#define _GNU_SOURCE 3#define _GNU_SOURCE
3#endif 4#endif
diff --git a/tools/build/feature/test-sdt.c b/tools/build/feature/test-sdt.c
index e4531a6e80ea..22737b0dadc8 100644
--- a/tools/build/feature/test-sdt.c
+++ b/tools/build/feature/test-sdt.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/sdt.h> 2#include <sys/sdt.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/build/feature/test-setns.c b/tools/build/feature/test-setns.c
new file mode 100644
index 000000000000..1f714d2a658b
--- /dev/null
+++ b/tools/build/feature/test-setns.c
@@ -0,0 +1,7 @@
1#define _GNU_SOURCE
2#include <sched.h>
3
4int main(void)
5{
6 return setns(0, 0);
7}
diff --git a/tools/build/feature/test-stackprotector-all.c b/tools/build/feature/test-stackprotector-all.c
index c9f398d87868..c8a57194f9f2 100644
--- a/tools/build/feature/test-stackprotector-all.c
+++ b/tools/build/feature/test-stackprotector-all.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/build/feature/test-sync-compare-and-swap.c b/tools/build/feature/test-sync-compare-and-swap.c
index c34d4ca4af56..1e38d1930a97 100644
--- a/tools/build/feature/test-sync-compare-and-swap.c
+++ b/tools/build/feature/test-sync-compare-and-swap.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdint.h> 2#include <stdint.h>
2 3
3volatile uint64_t x; 4volatile uint64_t x;
diff --git a/tools/build/feature/test-timerfd.c b/tools/build/feature/test-timerfd.c
index 8c5c083b4d3c..9c72c697a9df 100644
--- a/tools/build/feature/test-timerfd.c
+++ b/tools/build/feature/test-timerfd.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * test for timerfd functions used by perf-kvm-stat-live 3 * test for timerfd functions used by perf-kvm-stat-live
3 */ 4 */
diff --git a/tools/build/feature/test-zlib.c b/tools/build/feature/test-zlib.c
index e111fff6240e..da6c35794b93 100644
--- a/tools/build/feature/test-zlib.c
+++ b/tools/build/feature/test-zlib.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <zlib.h> 2#include <zlib.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/build/fixdep.c b/tools/build/fixdep.c
index 734d1547cbae..2501fea7aa3e 100644
--- a/tools/build/fixdep.c
+++ b/tools/build/fixdep.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * "Optimize" a list of dependencies as spit out by gcc -MD 3 * "Optimize" a list of dependencies as spit out by gcc -MD
3 * for the build framework. 4 * for the build framework.
diff --git a/tools/build/tests/ex/Makefile b/tools/build/tests/ex/Makefile
index c50d5782ad5a..fee032e06a85 100644
--- a/tools/build/tests/ex/Makefile
+++ b/tools/build/tests/ex/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1export srctree := $(abspath ../../../..) 2export srctree := $(abspath ../../../..)
2export CC := gcc 3export CC := gcc
3export LD := ld 4export LD := ld
@@ -8,7 +9,7 @@ ex:
8include $(srctree)/tools/build/Makefile.include 9include $(srctree)/tools/build/Makefile.include
9 10
10ex: ex-in.o libex-in.o 11ex: ex-in.o libex-in.o
11 gcc -o $@ $^ 12 $(CC) -o $@ $^
12 13
13ex.%: fixdep FORCE 14ex.%: fixdep FORCE
14 make -f $(srctree)/tools/build/Makefile.build dir=. $@ 15 make -f $(srctree)/tools/build/Makefile.build dir=. $@
diff --git a/tools/build/tests/ex/a.c b/tools/build/tests/ex/a.c
index 851762798c83..66017a9f40b6 100644
--- a/tools/build/tests/ex/a.c
+++ b/tools/build/tests/ex/a.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1 2
2int a(void) 3int a(void)
3{ 4{
diff --git a/tools/build/tests/ex/arch/e.c b/tools/build/tests/ex/arch/e.c
index beaa4a1d7ba8..f6ef585b570c 100644
--- a/tools/build/tests/ex/arch/e.c
+++ b/tools/build/tests/ex/arch/e.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1 2
2int e(void) 3int e(void)
3{ 4{
diff --git a/tools/build/tests/ex/arch/f.c b/tools/build/tests/ex/arch/f.c
index 7c3e9e9da5b7..bffd9c67e9af 100644
--- a/tools/build/tests/ex/arch/f.c
+++ b/tools/build/tests/ex/arch/f.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1 2
2int f(void) 3int f(void)
3{ 4{
diff --git a/tools/build/tests/ex/b.c b/tools/build/tests/ex/b.c
index c24ff9ca9a97..2b29fb4d3c20 100644
--- a/tools/build/tests/ex/b.c
+++ b/tools/build/tests/ex/b.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1 2
2int b(void) 3int b(void)
3{ 4{
diff --git a/tools/build/tests/ex/c.c b/tools/build/tests/ex/c.c
index e216d0217499..a63b20ab83d5 100644
--- a/tools/build/tests/ex/c.c
+++ b/tools/build/tests/ex/c.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1 2
2int c(void) 3int c(void)
3{ 4{
diff --git a/tools/build/tests/ex/d.c b/tools/build/tests/ex/d.c
index 80dc0f06151b..e114e8dca0b6 100644
--- a/tools/build/tests/ex/d.c
+++ b/tools/build/tests/ex/d.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1 2
2int d(void) 3int d(void)
3{ 4{
diff --git a/tools/build/tests/ex/ex.c b/tools/build/tests/ex/ex.c
index 57de6074d252..3c02756ef912 100644
--- a/tools/build/tests/ex/ex.c
+++ b/tools/build/tests/ex/ex.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1 2
2int a(void); 3int a(void);
3int b(void); 4int b(void);
diff --git a/tools/build/tests/ex/inc.c b/tools/build/tests/ex/inc.c
index c20f1e9033a3..3636ab5bf339 100644
--- a/tools/build/tests/ex/inc.c
+++ b/tools/build/tests/ex/inc.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#ifdef INCLUDE 2#ifdef INCLUDE
2#include "krava.h" 3#include "krava.h"
3#endif 4#endif
diff --git a/tools/build/tests/run.sh b/tools/build/tests/run.sh
index 44d2a0fade67..2c54e4d43546 100755
--- a/tools/build/tests/run.sh
+++ b/tools/build/tests/run.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2 3
3function test_ex { 4function test_ex {
4 make -C ex V=1 clean > ex.out 2>&1 5 make -C ex V=1 clean > ex.out 2>&1
diff --git a/tools/cgroup/Makefile b/tools/cgroup/Makefile
index b4286196b763..860fa151640a 100644
--- a/tools/cgroup/Makefile
+++ b/tools/cgroup/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# Makefile for cgroup tools 2# Makefile for cgroup tools
2 3
3CC = $(CROSS_COMPILE)gcc 4CC = $(CROSS_COMPILE)gcc
diff --git a/tools/cgroup/cgroup_event_listener.c b/tools/cgroup/cgroup_event_listener.c
index 4eb5507205c9..3d70dc831a76 100644
--- a/tools/cgroup/cgroup_event_listener.c
+++ b/tools/cgroup/cgroup_event_listener.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * cgroup_event_listener.c - Simple listener of cgroup events 3 * cgroup_event_listener.c - Simple listener of cgroup events
3 * 4 *
diff --git a/tools/firewire/Makefile b/tools/firewire/Makefile
index 81767adaae7d..67b6e9fca83c 100644
--- a/tools/firewire/Makefile
+++ b/tools/firewire/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1prefix = /usr 2prefix = /usr
2nosy-dump-version = 0.4 3nosy-dump-version = 0.4
3 4
diff --git a/tools/firewire/decode-fcp.c b/tools/firewire/decode-fcp.c
index e41223b6a4c8..b67ebc88434d 100644
--- a/tools/firewire/decode-fcp.c
+++ b/tools/firewire/decode-fcp.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/firewire-constants.h> 2#include <linux/firewire-constants.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <stdlib.h> 4#include <stdlib.h>
diff --git a/tools/firewire/list.h b/tools/firewire/list.h
index 41f4bdadf634..6278d08e99e3 100644
--- a/tools/firewire/list.h
+++ b/tools/firewire/list.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1struct list { 2struct list {
2 struct list *next, *prev; 3 struct list *next, *prev;
3}; 4};
diff --git a/tools/firewire/nosy-dump.h b/tools/firewire/nosy-dump.h
index 3a4b5b33ba5d..69e5e594f284 100644
--- a/tools/firewire/nosy-dump.h
+++ b/tools/firewire/nosy-dump.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __nosy_dump_h__ 2#ifndef __nosy_dump_h__
2#define __nosy_dump_h__ 3#define __nosy_dump_h__
3 4
diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile
index b4401536cfa9..805a2c0cf4cd 100644
--- a/tools/gpio/Makefile
+++ b/tools/gpio/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1include ../scripts/Makefile.include 2include ../scripts/Makefile.include
2 3
3bindir ?= /usr/bin 4bindir ?= /usr/bin
diff --git a/tools/gpio/gpio-utils.c b/tools/gpio/gpio-utils.c
index b86a32d90d88..cf7e2f3419ee 100644
--- a/tools/gpio/gpio-utils.c
+++ b/tools/gpio/gpio-utils.c
@@ -76,7 +76,8 @@ int gpiotools_request_linehandle(const char *device_name, unsigned int *lines,
76 fd = open(chrdev_name, 0); 76 fd = open(chrdev_name, 0);
77 if (fd == -1) { 77 if (fd == -1) {
78 ret = -errno; 78 ret = -errno;
79 fprintf(stderr, "Failed to open %s\n", chrdev_name); 79 fprintf(stderr, "Failed to open %s, %s\n",
80 chrdev_name, strerror(errno));
80 goto exit_close_error; 81 goto exit_close_error;
81 } 82 }
82 83
@@ -92,8 +93,8 @@ int gpiotools_request_linehandle(const char *device_name, unsigned int *lines,
92 ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); 93 ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
93 if (ret == -1) { 94 if (ret == -1) {
94 ret = -errno; 95 ret = -errno;
95 fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", 96 fprintf(stderr, "Failed to issue %s (%d), %s\n",
96 ret); 97 "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno));
97 } 98 }
98 99
99exit_close_error: 100exit_close_error:
@@ -118,8 +119,9 @@ int gpiotools_set_values(const int fd, struct gpiohandle_data *data)
118 ret = ioctl(fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, data); 119 ret = ioctl(fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, data);
119 if (ret == -1) { 120 if (ret == -1) {
120 ret = -errno; 121 ret = -errno;
121 fprintf(stderr, "Failed to issue %s (%d)\n", 122 fprintf(stderr, "Failed to issue %s (%d), %s\n",
122 "GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret); 123 "GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret,
124 strerror(errno));
123 } 125 }
124 126
125 return ret; 127 return ret;
@@ -141,8 +143,9 @@ int gpiotools_get_values(const int fd, struct gpiohandle_data *data)
141 ret = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, data); 143 ret = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, data);
142 if (ret == -1) { 144 if (ret == -1) {
143 ret = -errno; 145 ret = -errno;
144 fprintf(stderr, "Failed to issue %s (%d)\n", 146 fprintf(stderr, "Failed to issue %s (%d), %s\n",
145 "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret); 147 "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret,
148 strerror(errno));
146 } 149 }
147 150
148 return ret; 151 return ret;
diff --git a/tools/hv/Makefile b/tools/hv/Makefile
index 0d1e61b81844..31503819454d 100644
--- a/tools/hv/Makefile
+++ b/tools/hv/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# Makefile for Hyper-V tools 2# Makefile for Hyper-V tools
2 3
3CC = $(CROSS_COMPILE)gcc 4CC = $(CROSS_COMPILE)gcc
diff --git a/tools/hv/bondvf.sh b/tools/hv/bondvf.sh
deleted file mode 100755
index 89b25068cd98..000000000000
--- a/tools/hv/bondvf.sh
+++ /dev/null
@@ -1,232 +0,0 @@
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 UUID=`uuidgen` >>$fn
78 echo ONBOOT=yes >>$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 UUID=`uuidgen` >>$fn
97 echo ONBOOT=yes >>$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 del_eth_cfg_ubuntu {
105 local mainfn=$cfgdir/interfaces
106 local fnlist=( $mainfn )
107
108 local dirlist=(`awk '/^[ \t]*source/{print $2}' $mainfn`)
109
110 local i
111 for i in "${dirlist[@]}"
112 do
113 fnlist+=(`ls $i 2>/dev/null`)
114 done
115
116 local tmpfl=$(mktemp)
117
118 local nic_start='^[ \t]*(auto|iface|mapping|allow-.*)[ \t]+'$1
119 local nic_end='^[ \t]*(auto|iface|mapping|allow-.*|source)'
120
121 local fn
122 for fn in "${fnlist[@]}"
123 do
124 awk "/$nic_end/{x=0} x{next} /$nic_start/{x=1;next} 1" \
125 $fn >$tmpfl
126
127 cp $tmpfl $fn
128 done
129
130 rm $tmpfl
131}
132
133function create_eth_cfg_ubuntu {
134 local fn=$cfgdir/interfaces
135
136 del_eth_cfg_ubuntu $1
137 echo $'\n'auto $1 >>$fn
138 echo iface $1 inet manual >>$fn
139 echo bond-master $2 >>$fn
140}
141
142function create_eth_cfg_pri_ubuntu {
143 local fn=$cfgdir/interfaces
144
145 del_eth_cfg_ubuntu $1
146 echo $'\n'allow-hotplug $1 >>$fn
147 echo iface $1 inet manual >>$fn
148 echo bond-master $2 >>$fn
149 echo bond-primary $1 >>$fn
150}
151
152function create_bond_cfg_ubuntu {
153 local fn=$cfgdir/interfaces
154
155 del_eth_cfg_ubuntu $1
156
157 echo $'\n'auto $1 >>$fn
158 echo iface $1 inet dhcp >>$fn
159 echo bond-mode active-backup >>$fn
160 echo bond-miimon 100 >>$fn
161 echo bond-slaves none >>$fn
162}
163
164function create_eth_cfg_suse {
165 local fn=$cfgdir/ifcfg-$1
166
167 rm -f $fn
168 echo BOOTPROTO=none >>$fn
169 echo STARTMODE=auto >>$fn
170}
171
172function create_eth_cfg_pri_suse {
173 local fn=$cfgdir/ifcfg-$1
174
175 rm -f $fn
176 echo BOOTPROTO=none >>$fn
177 echo STARTMODE=hotplug >>$fn
178}
179
180function create_bond_cfg_suse {
181 local fn=$cfgdir/ifcfg-$1
182
183 rm -f $fn
184 echo BOOTPROTO=dhcp >>$fn
185 echo STARTMODE=auto >>$fn
186 echo BONDING_MASTER=yes >>$fn
187 echo BONDING_SLAVE_0=$2 >>$fn
188 echo BONDING_SLAVE_1=$3 >>$fn
189 echo BONDING_MODULE_OPTS=\'mode=active-backup miimon=100 primary=$2\' >>$fn
190}
191
192function create_bond {
193 local bondname=bond$bondcnt
194 local primary
195 local secondary
196
197 local class_id1=`cat $sysdir/$1/device/class_id 2>/dev/null`
198 local class_id2=`cat $sysdir/$2/device/class_id 2>/dev/null`
199
200 if [ "$class_id1" = "$netvsc_cls" ]
201 then
202 primary=$2
203 secondary=$1
204 elif [ "$class_id2" = "$netvsc_cls" ]
205 then
206 primary=$1
207 secondary=$2
208 else
209 return 0
210 fi
211
212 echo $'\nBond name:' $bondname
213
214 echo configuring $primary
215 create_eth_cfg_pri_$distro $primary $bondname
216
217 echo configuring $secondary
218 create_eth_cfg_$distro $secondary $bondname
219
220 echo creating: $bondname with primary slave: $primary
221 create_bond_cfg_$distro $bondname $primary $secondary
222
223 let bondcnt=bondcnt+1
224}
225
226for (( i=0; i < $eth_cnt-1; i++ ))
227do
228 if [ -n "${list_match[$i]}" ]
229 then
230 create_bond ${list_eth[$i]} ${list_match[$i]}
231 fi
232done
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c
index 26ae609a9448..457a1521f32f 100644
--- a/tools/hv/hv_fcopy_daemon.c
+++ b/tools/hv/hv_fcopy_daemon.c
@@ -138,14 +138,17 @@ void print_usage(char *argv[])
138 138
139int main(int argc, char *argv[]) 139int main(int argc, char *argv[])
140{ 140{
141 int fcopy_fd, len; 141 int fcopy_fd;
142 int error; 142 int error;
143 int daemonize = 1, long_index = 0, opt; 143 int daemonize = 1, long_index = 0, opt;
144 int version = FCOPY_CURRENT_VERSION; 144 int version = FCOPY_CURRENT_VERSION;
145 char *buffer[4096 * 2]; 145 union {
146 struct hv_fcopy_hdr *in_msg; 146 struct hv_fcopy_hdr hdr;
147 struct hv_start_fcopy start;
148 struct hv_do_fcopy copy;
149 __u32 kernel_modver;
150 } buffer = { };
147 int in_handshake = 1; 151 int in_handshake = 1;
148 __u32 kernel_modver;
149 152
150 static struct option long_options[] = { 153 static struct option long_options[] = {
151 {"help", no_argument, 0, 'h' }, 154 {"help", no_argument, 0, 'h' },
@@ -195,32 +198,31 @@ int main(int argc, char *argv[])
195 * In this loop we process fcopy messages after the 198 * In this loop we process fcopy messages after the
196 * handshake is complete. 199 * handshake is complete.
197 */ 200 */
198 len = pread(fcopy_fd, buffer, (4096 * 2), 0); 201 ssize_t len;
202
203 len = pread(fcopy_fd, &buffer, sizeof(buffer), 0);
199 if (len < 0) { 204 if (len < 0) {
200 syslog(LOG_ERR, "pread failed: %s", strerror(errno)); 205 syslog(LOG_ERR, "pread failed: %s", strerror(errno));
201 exit(EXIT_FAILURE); 206 exit(EXIT_FAILURE);
202 } 207 }
203 208
204 if (in_handshake) { 209 if (in_handshake) {
205 if (len != sizeof(kernel_modver)) { 210 if (len != sizeof(buffer.kernel_modver)) {
206 syslog(LOG_ERR, "invalid version negotiation"); 211 syslog(LOG_ERR, "invalid version negotiation");
207 exit(EXIT_FAILURE); 212 exit(EXIT_FAILURE);
208 } 213 }
209 kernel_modver = *(__u32 *)buffer;
210 in_handshake = 0; 214 in_handshake = 0;
211 syslog(LOG_INFO, "kernel module version: %d", 215 syslog(LOG_INFO, "kernel module version: %u",
212 kernel_modver); 216 buffer.kernel_modver);
213 continue; 217 continue;
214 } 218 }
215 219
216 in_msg = (struct hv_fcopy_hdr *)buffer; 220 switch (buffer.hdr.operation) {
217
218 switch (in_msg->operation) {
219 case START_FILE_COPY: 221 case START_FILE_COPY:
220 error = hv_start_fcopy((struct hv_start_fcopy *)in_msg); 222 error = hv_start_fcopy(&buffer.start);
221 break; 223 break;
222 case WRITE_TO_FILE: 224 case WRITE_TO_FILE:
223 error = hv_copy_data((struct hv_do_fcopy *)in_msg); 225 error = hv_copy_data(&buffer.copy);
224 break; 226 break;
225 case COMPLETE_FCOPY: 227 case COMPLETE_FCOPY:
226 error = hv_copy_finished(); 228 error = hv_copy_finished();
@@ -231,7 +233,7 @@ int main(int argc, char *argv[])
231 233
232 default: 234 default:
233 syslog(LOG_ERR, "Unknown operation: %d", 235 syslog(LOG_ERR, "Unknown operation: %d",
234 in_msg->operation); 236 buffer.hdr.operation);
235 237
236 } 238 }
237 239
diff --git a/tools/hv/hv_get_dhcp_info.sh b/tools/hv/hv_get_dhcp_info.sh
index ccd3e9532764..c38686c44656 100755
--- a/tools/hv/hv_get_dhcp_info.sh
+++ b/tools/hv/hv_get_dhcp_info.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2 3
3# This example script retrieves the DHCP state of a given interface. 4# This example script retrieves the DHCP state of a given interface.
4# In the interest of keeping the KVP daemon code free of distro specific 5# In the interest of keeping the KVP daemon code free of distro specific
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 88b20e007c05..eaa3bec273c8 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -1136,7 +1136,7 @@ static int process_ip_string(FILE *f, char *ip_string, int type)
1136 int i = 0; 1136 int i = 0;
1137 int j = 0; 1137 int j = 0;
1138 char str[256]; 1138 char str[256];
1139 char sub_str[10]; 1139 char sub_str[13];
1140 int offset = 0; 1140 int offset = 0;
1141 1141
1142 memset(addr, 0, sizeof(addr)); 1142 memset(addr, 0, sizeof(addr));
diff --git a/tools/hv/hv_set_ifconfig.sh b/tools/hv/hv_set_ifconfig.sh
index 735aafd64a3f..7ed9f85ef908 100755
--- a/tools/hv/hv_set_ifconfig.sh
+++ b/tools/hv/hv_set_ifconfig.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2 3
3# This example script activates an interface based on the specified 4# This example script activates an interface based on the specified
4# configuration. 5# configuration.
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index 7ba54195934c..b2b4ebffab8c 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -21,6 +21,7 @@
21#include <sys/types.h> 21#include <sys/types.h>
22#include <sys/poll.h> 22#include <sys/poll.h>
23#include <sys/ioctl.h> 23#include <sys/ioctl.h>
24#include <sys/stat.h>
24#include <fcntl.h> 25#include <fcntl.h>
25#include <stdio.h> 26#include <stdio.h>
26#include <mntent.h> 27#include <mntent.h>
@@ -30,6 +31,7 @@
30#include <ctype.h> 31#include <ctype.h>
31#include <errno.h> 32#include <errno.h>
32#include <linux/fs.h> 33#include <linux/fs.h>
34#include <linux/major.h>
33#include <linux/hyperv.h> 35#include <linux/hyperv.h>
34#include <syslog.h> 36#include <syslog.h>
35#include <getopt.h> 37#include <getopt.h>
@@ -70,6 +72,7 @@ static int vss_operate(int operation)
70 char match[] = "/dev/"; 72 char match[] = "/dev/";
71 FILE *mounts; 73 FILE *mounts;
72 struct mntent *ent; 74 struct mntent *ent;
75 struct stat sb;
73 char errdir[1024] = {0}; 76 char errdir[1024] = {0};
74 unsigned int cmd; 77 unsigned int cmd;
75 int error = 0, root_seen = 0, save_errno = 0; 78 int error = 0, root_seen = 0, save_errno = 0;
@@ -92,6 +95,10 @@ static int vss_operate(int operation)
92 while ((ent = getmntent(mounts))) { 95 while ((ent = getmntent(mounts))) {
93 if (strncmp(ent->mnt_fsname, match, strlen(match))) 96 if (strncmp(ent->mnt_fsname, match, strlen(match)))
94 continue; 97 continue;
98 if (stat(ent->mnt_fsname, &sb) == -1)
99 continue;
100 if (S_ISBLK(sb.st_mode) && major(sb.st_rdev) == LOOP_MAJOR)
101 continue;
95 if (hasmntopt(ent, MNTOPT_RO) != NULL) 102 if (hasmntopt(ent, MNTOPT_RO) != NULL)
96 continue; 103 continue;
97 if (strcmp(ent->mnt_type, "vfat") == 0) 104 if (strcmp(ent->mnt_type, "vfat") == 0)
diff --git a/tools/hv/lsvmbus b/tools/hv/lsvmbus
index e8fecd61871f..353e56768df8 100644
--- a/tools/hv/lsvmbus
+++ b/tools/hv/lsvmbus
@@ -1,4 +1,5 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2# SPDX-License-Identifier: GPL-2.0
2 3
3import os 4import os
4from optparse import OptionParser 5from optparse import OptionParser
diff --git a/tools/iio/Build b/tools/iio/Build
new file mode 100644
index 000000000000..f74cbda64710
--- /dev/null
+++ b/tools/iio/Build
@@ -0,0 +1,3 @@
1lsiio-y += lsiio.o iio_utils.o
2iio_event_monitor-y += iio_event_monitor.o iio_utils.o
3iio_generic_buffer-y += iio_generic_buffer.o iio_utils.o
diff --git a/tools/iio/Makefile b/tools/iio/Makefile
index 8f08e03a9a5e..a08e7a47d6a3 100644
--- a/tools/iio/Makefile
+++ b/tools/iio/Makefile
@@ -1,31 +1,68 @@
1# SPDX-License-Identifier: GPL-2.0
2include ../scripts/Makefile.include
3
4bindir ?= /usr/bin
5
6ifeq ($(srctree),)
7srctree := $(patsubst %/,%,$(dir $(CURDIR)))
8srctree := $(patsubst %/,%,$(dir $(srctree)))
9endif
10
11# Do not use make's built-in rules
12# (this improves performance and avoids hard-to-debug behaviour);
13MAKEFLAGS += -r
14
1CC = $(CROSS_COMPILE)gcc 15CC = $(CROSS_COMPILE)gcc
2CFLAGS += -Wall -g -D_GNU_SOURCE -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include 16LD = $(CROSS_COMPILE)ld
17CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
3 18
4BINDIR=usr/bin 19ALL_TARGETS := iio_event_monitor lsiio iio_generic_buffer
5INSTALL_PROGRAM=install -m 755 -p 20ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
6DEL_FILE=rm -f
7 21
8all: iio_event_monitor lsiio iio_generic_buffer 22all: $(ALL_PROGRAMS)
9 23
10iio_event_monitor: iio_event_monitor.o iio_utils.o 24export srctree OUTPUT CC LD CFLAGS
25include $(srctree)/tools/build/Makefile.include
11 26
12lsiio: lsiio.o iio_utils.o 27#
28# We need the following to be outside of kernel tree
29#
30$(OUTPUT)include/linux/iio: ../../include/uapi/linux/iio
31 mkdir -p $(OUTPUT)include/linux/iio 2>&1 || true
32 ln -sf $(CURDIR)/../../include/uapi/linux/iio/events.h $@
33 ln -sf $(CURDIR)/../../include/uapi/linux/iio/types.h $@
13 34
14iio_generic_buffer: iio_generic_buffer.o iio_utils.o 35prepare: $(OUTPUT)include/linux/iio
15 36
16%.o: %.c iio_utils.h 37LSIIO_IN := $(OUTPUT)lsiio-in.o
38$(LSIIO_IN): prepare FORCE
39 $(Q)$(MAKE) $(build)=lsiio
40$(OUTPUT)lsiio: $(LSIIO_IN)
41 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
17 42
18install: 43IIO_EVENT_MONITOR_IN := $(OUTPUT)iio_event_monitor-in.o
19 - mkdir -p $(INSTALL_ROOT)/$(BINDIR) 44$(IIO_EVENT_MONITOR_IN): prepare FORCE
20 - $(INSTALL_PROGRAM) "iio_event_monitor" "$(INSTALL_ROOT)/$(BINDIR)/iio_event_monitor" 45 $(Q)$(MAKE) $(build)=iio_event_monitor
21 - $(INSTALL_PROGRAM) "lsiio" "$(INSTALL_ROOT)/$(BINDIR)/lsiio" 46$(OUTPUT)iio_event_monitor: $(IIO_EVENT_MONITOR_IN)
22 - $(INSTALL_PROGRAM) "iio_generic_buffer" "$(INSTALL_ROOT)/$(BINDIR)/iio_generic_buffer" 47 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
23 48
24uninstall: 49IIO_GENERIC_BUFFER_IN := $(OUTPUT)iio_generic_buffer-in.o
25 $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/iio_event_monitor" 50$(IIO_GENERIC_BUFFER_IN): prepare FORCE
26 $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/lsiio" 51 $(Q)$(MAKE) $(build)=iio_generic_buffer
27 $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/iio_generic_buffer" 52$(OUTPUT)iio_generic_buffer: $(IIO_GENERIC_BUFFER_IN)
53 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
28 54
29.PHONY: clean
30clean: 55clean:
31 rm -f *.o iio_event_monitor lsiio iio_generic_buffer 56 rm -f $(ALL_PROGRAMS)
57 rm -rf $(OUTPUT)include/linux/iio
58 find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete
59
60install: $(ALL_PROGRAMS)
61 install -d -m 755 $(DESTDIR)$(bindir); \
62 for program in $(ALL_PROGRAMS); do \
63 install $$program $(DESTDIR)$(bindir); \
64 done
65
66FORCE:
67
68.PHONY: all install clean FORCE prepare
diff --git a/tools/include/asm-generic/atomic-gcc.h b/tools/include/asm-generic/atomic-gcc.h
index 5e9738f97bf3..4c1966f7c77a 100644
--- a/tools/include/asm-generic/atomic-gcc.h
+++ b/tools/include/asm-generic/atomic-gcc.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __TOOLS_ASM_GENERIC_ATOMIC_H 2#ifndef __TOOLS_ASM_GENERIC_ATOMIC_H
2#define __TOOLS_ASM_GENERIC_ATOMIC_H 3#define __TOOLS_ASM_GENERIC_ATOMIC_H
3 4
@@ -21,7 +22,7 @@
21 */ 22 */
22static inline int atomic_read(const atomic_t *v) 23static inline int atomic_read(const atomic_t *v)
23{ 24{
24 return ACCESS_ONCE((v)->counter); 25 return READ_ONCE((v)->counter);
25} 26}
26 27
27/** 28/**
diff --git a/tools/include/asm-generic/bitops.h b/tools/include/asm-generic/bitops.h
index 0304600121da..9bce3b56b5e7 100644
--- a/tools/include/asm-generic/bitops.h
+++ b/tools/include/asm-generic/bitops.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __TOOLS_ASM_GENERIC_BITOPS_H 2#ifndef __TOOLS_ASM_GENERIC_BITOPS_H
2#define __TOOLS_ASM_GENERIC_BITOPS_H 3#define __TOOLS_ASM_GENERIC_BITOPS_H
3 4
diff --git a/tools/include/asm-generic/bitops/__ffs.h b/tools/include/asm-generic/bitops/__ffs.h
index b3accfdf24b9..9d1310519497 100644
--- a/tools/include/asm-generic/bitops/__ffs.h
+++ b/tools/include/asm-generic/bitops/__ffs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_ 2#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_
2#define _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_ 3#define _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_
3 4
diff --git a/tools/include/asm-generic/bitops/__fls.h b/tools/include/asm-generic/bitops/__fls.h
index a60a7ccb6782..03f721a8a2b1 100644
--- a/tools/include/asm-generic/bitops/__fls.h
+++ b/tools/include/asm-generic/bitops/__fls.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _ASM_GENERIC_BITOPS___FLS_H_ 2#ifndef _ASM_GENERIC_BITOPS___FLS_H_
2#define _ASM_GENERIC_BITOPS___FLS_H_ 3#define _ASM_GENERIC_BITOPS___FLS_H_
3 4
diff --git a/tools/include/asm-generic/bitops/arch_hweight.h b/tools/include/asm-generic/bitops/arch_hweight.h
index 6a211f40665c..c2705e1d220d 100644
--- a/tools/include/asm-generic/bitops/arch_hweight.h
+++ b/tools/include/asm-generic/bitops/arch_hweight.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _ASM_GENERIC_BITOPS_ARCH_HWEIGHT_H_ 2#ifndef _ASM_GENERIC_BITOPS_ARCH_HWEIGHT_H_
2#define _ASM_GENERIC_BITOPS_ARCH_HWEIGHT_H_ 3#define _ASM_GENERIC_BITOPS_ARCH_HWEIGHT_H_
3 4
diff --git a/tools/include/asm-generic/bitops/atomic.h b/tools/include/asm-generic/bitops/atomic.h
index 68b8c1516c5a..21c41ccd1266 100644
--- a/tools/include/asm-generic/bitops/atomic.h
+++ b/tools/include/asm-generic/bitops/atomic.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_ 2#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_
2#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_ 3#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_
3 4
diff --git a/tools/include/asm-generic/bitops/const_hweight.h b/tools/include/asm-generic/bitops/const_hweight.h
index 0a7e06623470..149faeeeeaf2 100644
--- a/tools/include/asm-generic/bitops/const_hweight.h
+++ b/tools/include/asm-generic/bitops/const_hweight.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_ 2#ifndef _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_
2#define _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_ 3#define _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_
3 4
diff --git a/tools/include/asm-generic/bitops/find.h b/tools/include/asm-generic/bitops/find.h
index 5538ecdc964a..9311fadaaab2 100644
--- a/tools/include/asm-generic/bitops/find.h
+++ b/tools/include/asm-generic/bitops/find.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ 2#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_
2#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ 3#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_
3 4
diff --git a/tools/include/asm-generic/bitops/fls.h b/tools/include/asm-generic/bitops/fls.h
index 0576d1f42f43..753aecaab641 100644
--- a/tools/include/asm-generic/bitops/fls.h
+++ b/tools/include/asm-generic/bitops/fls.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _ASM_GENERIC_BITOPS_FLS_H_ 2#ifndef _ASM_GENERIC_BITOPS_FLS_H_
2#define _ASM_GENERIC_BITOPS_FLS_H_ 3#define _ASM_GENERIC_BITOPS_FLS_H_
3 4
diff --git a/tools/include/asm-generic/bitops/fls64.h b/tools/include/asm-generic/bitops/fls64.h
index b097cf8444e3..866f2b2304ff 100644
--- a/tools/include/asm-generic/bitops/fls64.h
+++ b/tools/include/asm-generic/bitops/fls64.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _ASM_GENERIC_BITOPS_FLS64_H_ 2#ifndef _ASM_GENERIC_BITOPS_FLS64_H_
2#define _ASM_GENERIC_BITOPS_FLS64_H_ 3#define _ASM_GENERIC_BITOPS_FLS64_H_
3 4
diff --git a/tools/include/asm-generic/bitops/hweight.h b/tools/include/asm-generic/bitops/hweight.h
index 290120c01a8e..3e681982bcd1 100644
--- a/tools/include/asm-generic/bitops/hweight.h
+++ b/tools/include/asm-generic/bitops/hweight.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_ 2#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_
2#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_ 3#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_
3 4
diff --git a/tools/include/asm-generic/bitsperlong.h b/tools/include/asm-generic/bitsperlong.h
index 45eca517efb3..8f2283052333 100644
--- a/tools/include/asm-generic/bitsperlong.h
+++ b/tools/include/asm-generic/bitsperlong.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __ASM_GENERIC_BITS_PER_LONG 2#ifndef __ASM_GENERIC_BITS_PER_LONG
2#define __ASM_GENERIC_BITS_PER_LONG 3#define __ASM_GENERIC_BITS_PER_LONG
3 4
diff --git a/tools/include/asm-generic/hugetlb_encode.h b/tools/include/asm-generic/hugetlb_encode.h
new file mode 100644
index 000000000000..e4732d3c2998
--- /dev/null
+++ b/tools/include/asm-generic/hugetlb_encode.h
@@ -0,0 +1,34 @@
1#ifndef _ASM_GENERIC_HUGETLB_ENCODE_H_
2#define _ASM_GENERIC_HUGETLB_ENCODE_H_
3
4/*
5 * Several system calls take a flag to request "hugetlb" huge pages.
6 * Without further specification, these system calls will use the
7 * system's default huge page size. If a system supports multiple
8 * huge page sizes, the desired huge page size can be specified in
9 * bits [26:31] of the flag arguments. The value in these 6 bits
10 * will encode the log2 of the huge page size.
11 *
12 * The following definitions are associated with this huge page size
13 * encoding in flag arguments. System call specific header files
14 * that use this encoding should include this file. They can then
15 * provide definitions based on these with their own specific prefix.
16 * for example:
17 * #define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
18 */
19
20#define HUGETLB_FLAG_ENCODE_SHIFT 26
21#define HUGETLB_FLAG_ENCODE_MASK 0x3f
22
23#define HUGETLB_FLAG_ENCODE_64KB (16 << HUGETLB_FLAG_ENCODE_SHIFT)
24#define HUGETLB_FLAG_ENCODE_512KB (19 << HUGETLB_FLAG_ENCODE_SHIFT)
25#define HUGETLB_FLAG_ENCODE_1MB (20 << HUGETLB_FLAG_ENCODE_SHIFT)
26#define HUGETLB_FLAG_ENCODE_2MB (21 << HUGETLB_FLAG_ENCODE_SHIFT)
27#define HUGETLB_FLAG_ENCODE_8MB (23 << HUGETLB_FLAG_ENCODE_SHIFT)
28#define HUGETLB_FLAG_ENCODE_16MB (24 << HUGETLB_FLAG_ENCODE_SHIFT)
29#define HUGETLB_FLAG_ENCODE_256MB (28 << HUGETLB_FLAG_ENCODE_SHIFT)
30#define HUGETLB_FLAG_ENCODE_1GB (30 << HUGETLB_FLAG_ENCODE_SHIFT)
31#define HUGETLB_FLAG_ENCODE_2GB (31 << HUGETLB_FLAG_ENCODE_SHIFT)
32#define HUGETLB_FLAG_ENCODE_16GB (34 << HUGETLB_FLAG_ENCODE_SHIFT)
33
34#endif /* _ASM_GENERIC_HUGETLB_ENCODE_H_ */
diff --git a/tools/include/asm/alternative-asm.h b/tools/include/asm/alternative-asm.h
index 2a4d1bfa2988..b54bd860dff6 100644
--- a/tools/include/asm/alternative-asm.h
+++ b/tools/include/asm/alternative-asm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_ASM_ALTERNATIVE_ASM_H 2#ifndef _TOOLS_ASM_ALTERNATIVE_ASM_H
2#define _TOOLS_ASM_ALTERNATIVE_ASM_H 3#define _TOOLS_ASM_ALTERNATIVE_ASM_H
3 4
diff --git a/tools/include/asm/atomic.h b/tools/include/asm/atomic.h
index 70794f538a86..8c9bfffd4191 100644
--- a/tools/include/asm/atomic.h
+++ b/tools/include/asm/atomic.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __TOOLS_LINUX_ASM_ATOMIC_H 2#ifndef __TOOLS_LINUX_ASM_ATOMIC_H
2#define __TOOLS_LINUX_ASM_ATOMIC_H 3#define __TOOLS_LINUX_ASM_ATOMIC_H
3 4
diff --git a/tools/include/asm/barrier.h b/tools/include/asm/barrier.h
index ac66ac594685..391d942536e5 100644
--- a/tools/include/asm/barrier.h
+++ b/tools/include/asm/barrier.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#if defined(__i386__) || defined(__x86_64__) 2#if defined(__i386__) || defined(__x86_64__)
2#include "../../arch/x86/include/asm/barrier.h" 3#include "../../arch/x86/include/asm/barrier.h"
3#elif defined(__arm__) 4#elif defined(__arm__)
diff --git a/tools/include/asm/bug.h b/tools/include/asm/bug.h
index 4790f047a89c..bbd75ac8b202 100644
--- a/tools/include/asm/bug.h
+++ b/tools/include/asm/bug.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_ASM_BUG_H 2#ifndef _TOOLS_ASM_BUG_H
2#define _TOOLS_ASM_BUG_H 3#define _TOOLS_ASM_BUG_H
3 4
diff --git a/tools/include/asm/export.h b/tools/include/asm/export.h
new file mode 100644
index 000000000000..2cb1a0d83035
--- /dev/null
+++ b/tools/include/asm/export.h
@@ -0,0 +1,7 @@
1#ifndef _TOOLS_ASM_EXPORT_H
2#define _TOOLS_ASM_EXPORT_H
3
4#define EXPORT_SYMBOL(x)
5#define EXPORT_SYMBOL_GPL(x)
6
7#endif /* _TOOLS_ASM_EXPORT_H */
diff --git a/tools/include/linux/atomic.h b/tools/include/linux/atomic.h
index 9f21fc2b092b..00a6c4ca562b 100644
--- a/tools/include/linux/atomic.h
+++ b/tools/include/linux/atomic.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __TOOLS_LINUX_ATOMIC_H 2#ifndef __TOOLS_LINUX_ATOMIC_H
2#define __TOOLS_LINUX_ATOMIC_H 3#define __TOOLS_LINUX_ATOMIC_H
3 4
diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index e8b9f518e36b..ca160270fdfa 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_BITOPS_H 2#ifndef _PERF_BITOPS_H
2#define _PERF_BITOPS_H 3#define _PERF_BITOPS_H
3 4
diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h
index 969db1981868..acc704bd3998 100644
--- a/tools/include/linux/bitops.h
+++ b/tools/include/linux/bitops.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_BITOPS_H_ 2#ifndef _TOOLS_LINUX_BITOPS_H_
2#define _TOOLS_LINUX_BITOPS_H_ 3#define _TOOLS_LINUX_BITOPS_H_
3 4
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
index 8e4a4f49135d..85f80258a15f 100644
--- a/tools/include/linux/bug.h
+++ b/tools/include/linux/bug.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_PERF_LINUX_BUG_H 2#ifndef _TOOLS_PERF_LINUX_BUG_H
2#define _TOOLS_PERF_LINUX_BUG_H 3#define _TOOLS_PERF_LINUX_BUG_H
3 4
diff --git a/tools/include/linux/compiler-gcc.h b/tools/include/linux/compiler-gcc.h
index bd39b2090ad1..a3a4427441bf 100644
--- a/tools/include/linux/compiler-gcc.h
+++ b/tools/include/linux/compiler-gcc.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_COMPILER_H_ 2#ifndef _TOOLS_LINUX_COMPILER_H_
2#error "Please don't include <linux/compiler-gcc.h> directly, include <linux/compiler.h> instead." 3#error "Please don't include <linux/compiler-gcc.h> directly, include <linux/compiler.h> instead."
3#endif 4#endif
@@ -21,11 +22,14 @@
21#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) 22#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
22 23
23#define noinline __attribute__((noinline)) 24#define noinline __attribute__((noinline))
24 25#ifndef __packed
25#define __packed __attribute__((packed)) 26#define __packed __attribute__((packed))
26 27#endif
28#ifndef __noreturn
27#define __noreturn __attribute__((noreturn)) 29#define __noreturn __attribute__((noreturn))
28 30#endif
31#ifndef __aligned
29#define __aligned(x) __attribute__((aligned(x))) 32#define __aligned(x) __attribute__((aligned(x)))
33#endif
30#define __printf(a, b) __attribute__((format(printf, a, b))) 34#define __printf(a, b) __attribute__((format(printf, a, b)))
31#define __scanf(a, b) __attribute__((format(scanf, a, b))) 35#define __scanf(a, b) __attribute__((format(scanf, a, b)))
diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index d7a5604c38d7..07fd03c74a77 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_COMPILER_H_ 2#ifndef _TOOLS_LINUX_COMPILER_H_
2#define _TOOLS_LINUX_COMPILER_H_ 3#define _TOOLS_LINUX_COMPILER_H_
3 4
diff --git a/tools/include/linux/coresight-pmu.h b/tools/include/linux/coresight-pmu.h
index 7d410260661b..edfeaba95429 100644
--- a/tools/include/linux/coresight-pmu.h
+++ b/tools/include/linux/coresight-pmu.h
@@ -24,6 +24,12 @@
24/* ETMv3.5/PTM's ETMCR config bit */ 24/* ETMv3.5/PTM's ETMCR config bit */
25#define ETM_OPT_CYCACC 12 25#define ETM_OPT_CYCACC 12
26#define ETM_OPT_TS 28 26#define ETM_OPT_TS 28
27#define ETM_OPT_RETSTK 29
28
29/* ETMv4 CONFIGR programming bits for the ETM OPTs */
30#define ETM4_CFG_BIT_CYCACC 4
31#define ETM4_CFG_BIT_TS 11
32#define ETM4_CFG_BIT_RETSTK 12
27 33
28static inline int coresight_get_trace_id(int cpu) 34static inline int coresight_get_trace_id(int cpu)
29{ 35{
diff --git a/tools/include/linux/debug_locks.h b/tools/include/linux/debug_locks.h
index 61cc7f501168..72d595ce764a 100644
--- a/tools/include/linux/debug_locks.h
+++ b/tools/include/linux/debug_locks.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LIBLOCKDEP_DEBUG_LOCKS_H_ 2#ifndef _LIBLOCKDEP_DEBUG_LOCKS_H_
2#define _LIBLOCKDEP_DEBUG_LOCKS_H_ 3#define _LIBLOCKDEP_DEBUG_LOCKS_H_
3 4
diff --git a/tools/include/linux/err.h b/tools/include/linux/err.h
index abf0478a8fb2..7a8b61ad44cb 100644
--- a/tools/include/linux/err.h
+++ b/tools/include/linux/err.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __TOOLS_LINUX_ERR_H 2#ifndef __TOOLS_LINUX_ERR_H
2#define __TOOLS_LINUX_ERR_H 3#define __TOOLS_LINUX_ERR_H
3 4
diff --git a/tools/include/linux/filter.h b/tools/include/linux/filter.h
index 4ce25d43e8e3..c5e512da8d8a 100644
--- a/tools/include/linux/filter.h
+++ b/tools/include/linux/filter.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Linux Socket Filter Data Structures 3 * Linux Socket Filter Data Structures
3 */ 4 */
diff --git a/tools/include/linux/hardirq.h b/tools/include/linux/hardirq.h
index c8f3f8f58729..b25580b6a9be 100644
--- a/tools/include/linux/hardirq.h
+++ b/tools/include/linux/hardirq.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LIBLOCKDEP_LINUX_HARDIRQ_H_ 2#ifndef _LIBLOCKDEP_LINUX_HARDIRQ_H_
2#define _LIBLOCKDEP_LINUX_HARDIRQ_H_ 3#define _LIBLOCKDEP_LINUX_HARDIRQ_H_
3 4
diff --git a/tools/include/linux/hashtable.h b/tools/include/linux/hashtable.h
index 251eabf2a05e..434dd5ac6d71 100644
--- a/tools/include/linux/hashtable.h
+++ b/tools/include/linux/hashtable.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Statically sized hash table implementation 3 * Statically sized hash table implementation
3 * (C) 2012 Sasha Levin <levinsasha928@gmail.com> 4 * (C) 2012 Sasha Levin <levinsasha928@gmail.com>
diff --git a/tools/include/linux/irqflags.h b/tools/include/linux/irqflags.h
index df77669cfe1c..e734da3e5b33 100644
--- a/tools/include/linux/irqflags.h
+++ b/tools/include/linux/irqflags.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_ 2#ifndef _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_
2#define _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_ 3#define _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_
3 4
diff --git a/tools/include/linux/kallsyms.h b/tools/include/linux/kallsyms.h
index 582cc1e5f3a4..89ca6fe257cc 100644
--- a/tools/include/linux/kallsyms.h
+++ b/tools/include/linux/kallsyms.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LIBLOCKDEP_LINUX_KALLSYMS_H_ 2#ifndef _LIBLOCKDEP_LINUX_KALLSYMS_H_
2#define _LIBLOCKDEP_LINUX_KALLSYMS_H_ 3#define _LIBLOCKDEP_LINUX_KALLSYMS_H_
3 4
diff --git a/tools/include/linux/kern_levels.h b/tools/include/linux/kern_levels.h
index 3b9bade28698..778ecb984480 100644
--- a/tools/include/linux/kern_levels.h
+++ b/tools/include/linux/kern_levels.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __KERN_LEVELS_H__ 2#ifndef __KERN_LEVELS_H__
2#define __KERN_LEVELS_H__ 3#define __KERN_LEVELS_H__
3 4
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 77d2e94ca5df..0ad884452c5c 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __TOOLS_LINUX_KERNEL_H 2#ifndef __TOOLS_LINUX_KERNEL_H
2#define __TOOLS_LINUX_KERNEL_H 3#define __TOOLS_LINUX_KERNEL_H
3 4
diff --git a/tools/include/linux/kmemcheck.h b/tools/include/linux/kmemcheck.h
index 94d598bc6abe..ea32a7d3cf1b 100644
--- a/tools/include/linux/kmemcheck.h
+++ b/tools/include/linux/kmemcheck.h
@@ -1,8 +1 @@
1#ifndef _LIBLOCKDEP_LINUX_KMEMCHECK_H_ /* SPDX-License-Identifier: GPL-2.0 */
2#define _LIBLOCKDEP_LINUX_KMEMCHECK_H_
3
4static inline void kmemcheck_mark_initialized(void *address, unsigned int n)
5{
6}
7
8#endif
diff --git a/tools/include/linux/list.h b/tools/include/linux/list.h
index 1da423820ad4..b2fc48d5478c 100644
--- a/tools/include/linux/list.h
+++ b/tools/include/linux/list.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __TOOLS_LINUX_LIST_H 2#ifndef __TOOLS_LINUX_LIST_H
2#define __TOOLS_LINUX_LIST_H 3#define __TOOLS_LINUX_LIST_H
3 4
diff --git a/tools/include/linux/lockdep.h b/tools/include/linux/lockdep.h
index 8da3e8effafa..940c1b075659 100644
--- a/tools/include/linux/lockdep.h
+++ b/tools/include/linux/lockdep.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LIBLOCKDEP_LOCKDEP_H_ 2#ifndef _LIBLOCKDEP_LOCKDEP_H_
2#define _LIBLOCKDEP_LOCKDEP_H_ 3#define _LIBLOCKDEP_LOCKDEP_H_
3 4
diff --git a/tools/include/linux/module.h b/tools/include/linux/module.h
index 07055db296f3..2c999abf68e7 100644
--- a/tools/include/linux/module.h
+++ b/tools/include/linux/module.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LIBLOCKDEP_LINUX_MODULE_H_ 2#ifndef _LIBLOCKDEP_LINUX_MODULE_H_
2#define _LIBLOCKDEP_LINUX_MODULE_H_ 3#define _LIBLOCKDEP_LINUX_MODULE_H_
3 4
diff --git a/tools/include/linux/poison.h b/tools/include/linux/poison.h
index 51334edec506..9fdcd3eaac3b 100644
--- a/tools/include/linux/poison.h
+++ b/tools/include/linux/poison.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LINUX_POISON_H 2#ifndef _LINUX_POISON_H
2#define _LINUX_POISON_H 3#define _LINUX_POISON_H
3 4
@@ -14,6 +15,10 @@
14# define POISON_POINTER_DELTA 0 15# define POISON_POINTER_DELTA 0
15#endif 16#endif
16 17
18#ifdef __cplusplus
19#define LIST_POISON1 NULL
20#define LIST_POISON2 NULL
21#else
17/* 22/*
18 * These are non-NULL pointers that will result in page faults 23 * These are non-NULL pointers that will result in page faults
19 * under normal circumstances, used to verify that nobody uses 24 * under normal circumstances, used to verify that nobody uses
@@ -21,6 +26,7 @@
21 */ 26 */
22#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA) 27#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA)
23#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA) 28#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA)
29#endif
24 30
25/********** include/linux/timer.h **********/ 31/********** include/linux/timer.h **********/
26/* 32/*
diff --git a/tools/include/linux/rcu.h b/tools/include/linux/rcu.h
index 5080649dad04..7d02527e5bce 100644
--- a/tools/include/linux/rcu.h
+++ b/tools/include/linux/rcu.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LIBLOCKDEP_RCU_H_ 2#ifndef _LIBLOCKDEP_RCU_H_
2#define _LIBLOCKDEP_RCU_H_ 3#define _LIBLOCKDEP_RCU_H_
3 4
diff --git a/tools/include/linux/refcount.h b/tools/include/linux/refcount.h
index a0177c1f55b1..36cb29bc57c2 100644
--- a/tools/include/linux/refcount.h
+++ b/tools/include/linux/refcount.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_REFCOUNT_H 2#ifndef _TOOLS_LINUX_REFCOUNT_H
2#define _TOOLS_LINUX_REFCOUNT_H 3#define _TOOLS_LINUX_REFCOUNT_H
3 4
diff --git a/tools/include/linux/spinlock.h b/tools/include/linux/spinlock.h
index 417cda4f793f..4ed569fcb139 100644
--- a/tools/include/linux/spinlock.h
+++ b/tools/include/linux/spinlock.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __LINUX_SPINLOCK_H_ 2#ifndef __LINUX_SPINLOCK_H_
2#define __LINUX_SPINLOCK_H_ 3#define __LINUX_SPINLOCK_H_
3 4
diff --git a/tools/include/linux/stacktrace.h b/tools/include/linux/stacktrace.h
index 39aecc6b19d1..ae343ac35bfa 100644
--- a/tools/include/linux/stacktrace.h
+++ b/tools/include/linux/stacktrace.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LIBLOCKDEP_LINUX_STACKTRACE_H_ 2#ifndef _LIBLOCKDEP_LINUX_STACKTRACE_H_
2#define _LIBLOCKDEP_LINUX_STACKTRACE_H_ 3#define _LIBLOCKDEP_LINUX_STACKTRACE_H_
3 4
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index d62b56cf8c12..6c3e2cc274c5 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -1,8 +1,9 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_STRING_H_ 2#ifndef _TOOLS_LINUX_STRING_H_
2#define _TOOLS_LINUX_STRING_H_ 3#define _TOOLS_LINUX_STRING_H_
3 4
4
5#include <linux/types.h> /* for size_t */ 5#include <linux/types.h> /* for size_t */
6#include <string.h>
6 7
7void *memdup(const void *src, size_t len); 8void *memdup(const void *src, size_t len);
8 9
@@ -18,6 +19,14 @@ extern size_t strlcpy(char *dest, const char *src, size_t size);
18 19
19char *str_error_r(int errnum, char *buf, size_t buflen); 20char *str_error_r(int errnum, char *buf, size_t buflen);
20 21
21int prefixcmp(const char *str, const char *prefix); 22/**
23 * strstarts - does @str start with @prefix?
24 * @str: string to examine
25 * @prefix: prefix to look for.
26 */
27static inline bool strstarts(const char *str, const char *prefix)
28{
29 return strncmp(str, prefix, strlen(prefix)) == 0;
30}
22 31
23#endif /* _LINUX_STRING_H_ */ 32#endif /* _LINUX_STRING_H_ */
diff --git a/tools/include/linux/stringify.h b/tools/include/linux/stringify.h
index 841cec8ed525..60e2c187da2c 100644
--- a/tools/include/linux/stringify.h
+++ b/tools/include/linux/stringify.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __LINUX_STRINGIFY_H 2#ifndef __LINUX_STRINGIFY_H
2#define __LINUX_STRINGIFY_H 3#define __LINUX_STRINGIFY_H
3 4
diff --git a/tools/include/linux/time64.h b/tools/include/linux/time64.h
index df9265483d65..55fa644b95fd 100644
--- a/tools/include/linux/time64.h
+++ b/tools/include/linux/time64.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_TIME64_H 2#ifndef _TOOLS_LINUX_TIME64_H
2#define _TOOLS_LINUX_TIME64_H 3#define _TOOLS_LINUX_TIME64_H
3 4
diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h
index 77a28a26a670..154eb4e3ca7c 100644
--- a/tools/include/linux/types.h
+++ b/tools/include/linux/types.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LINUX_TYPES_H_ 2#ifndef _TOOLS_LINUX_TYPES_H_
2#define _TOOLS_LINUX_TYPES_H_ 3#define _TOOLS_LINUX_TYPES_H_
3 4
diff --git a/tools/include/linux/unaligned/packed_struct.h b/tools/include/linux/unaligned/packed_struct.h
index c0d817de4df2..dbd93c7df2e1 100644
--- a/tools/include/linux/unaligned/packed_struct.h
+++ b/tools/include/linux/unaligned/packed_struct.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LINUX_UNALIGNED_PACKED_STRUCT_H 2#ifndef _LINUX_UNALIGNED_PACKED_STRUCT_H
2#define _LINUX_UNALIGNED_PACKED_STRUCT_H 3#define _LINUX_UNALIGNED_PACKED_STRUCT_H
3 4
diff --git a/tools/include/tools/be_byteshift.h b/tools/include/tools/be_byteshift.h
index 84c17d836578..f7d1d1698938 100644
--- a/tools/include/tools/be_byteshift.h
+++ b/tools/include/tools/be_byteshift.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_BE_BYTESHIFT_H 2#ifndef _TOOLS_BE_BYTESHIFT_H
2#define _TOOLS_BE_BYTESHIFT_H 3#define _TOOLS_BE_BYTESHIFT_H
3 4
diff --git a/tools/include/tools/endian.h b/tools/include/tools/endian.h
index 8001194008da..c67888fd427e 100644
--- a/tools/include/tools/endian.h
+++ b/tools/include/tools/endian.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_ENDIAN_H 2#ifndef _TOOLS_ENDIAN_H
2#define _TOOLS_ENDIAN_H 3#define _TOOLS_ENDIAN_H
3 4
diff --git a/tools/include/tools/le_byteshift.h b/tools/include/tools/le_byteshift.h
index 8fe9f2488ec7..dc8565f39717 100644
--- a/tools/include/tools/le_byteshift.h
+++ b/tools/include/tools/le_byteshift.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TOOLS_LE_BYTESHIFT_H 2#ifndef _TOOLS_LE_BYTESHIFT_H
2#define _TOOLS_LE_BYTESHIFT_H 3#define _TOOLS_LE_BYTESHIFT_H
3 4
diff --git a/tools/include/uapi/asm-generic/fcntl.h b/tools/include/uapi/asm-generic/fcntl.h
new file mode 100644
index 000000000000..ac190958c981
--- /dev/null
+++ b/tools/include/uapi/asm-generic/fcntl.h
@@ -0,0 +1,220 @@
1#ifndef _ASM_GENERIC_FCNTL_H
2#define _ASM_GENERIC_FCNTL_H
3
4#include <linux/types.h>
5
6/*
7 * FMODE_EXEC is 0x20
8 * FMODE_NONOTIFY is 0x4000000
9 * These cannot be used by userspace O_* until internal and external open
10 * flags are split.
11 * -Eric Paris
12 */
13
14/*
15 * When introducing new O_* bits, please check its uniqueness in fcntl_init().
16 */
17
18#define O_ACCMODE 00000003
19#define O_RDONLY 00000000
20#define O_WRONLY 00000001
21#define O_RDWR 00000002
22#ifndef O_CREAT
23#define O_CREAT 00000100 /* not fcntl */
24#endif
25#ifndef O_EXCL
26#define O_EXCL 00000200 /* not fcntl */
27#endif
28#ifndef O_NOCTTY
29#define O_NOCTTY 00000400 /* not fcntl */
30#endif
31#ifndef O_TRUNC
32#define O_TRUNC 00001000 /* not fcntl */
33#endif
34#ifndef O_APPEND
35#define O_APPEND 00002000
36#endif
37#ifndef O_NONBLOCK
38#define O_NONBLOCK 00004000
39#endif
40#ifndef O_DSYNC
41#define O_DSYNC 00010000 /* used to be O_SYNC, see below */
42#endif
43#ifndef FASYNC
44#define FASYNC 00020000 /* fcntl, for BSD compatibility */
45#endif
46#ifndef O_DIRECT
47#define O_DIRECT 00040000 /* direct disk access hint */
48#endif
49#ifndef O_LARGEFILE
50#define O_LARGEFILE 00100000
51#endif
52#ifndef O_DIRECTORY
53#define O_DIRECTORY 00200000 /* must be a directory */
54#endif
55#ifndef O_NOFOLLOW
56#define O_NOFOLLOW 00400000 /* don't follow links */
57#endif
58#ifndef O_NOATIME
59#define O_NOATIME 01000000
60#endif
61#ifndef O_CLOEXEC
62#define O_CLOEXEC 02000000 /* set close_on_exec */
63#endif
64
65/*
66 * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
67 * the O_SYNC flag. We continue to use the existing numerical value
68 * for O_DSYNC semantics now, but using the correct symbolic name for it.
69 * This new value is used to request true Posix O_SYNC semantics. It is
70 * defined in this strange way to make sure applications compiled against
71 * new headers get at least O_DSYNC semantics on older kernels.
72 *
73 * This has the nice side-effect that we can simply test for O_DSYNC
74 * wherever we do not care if O_DSYNC or O_SYNC is used.
75 *
76 * Note: __O_SYNC must never be used directly.
77 */
78#ifndef O_SYNC
79#define __O_SYNC 04000000
80#define O_SYNC (__O_SYNC|O_DSYNC)
81#endif
82
83#ifndef O_PATH
84#define O_PATH 010000000
85#endif
86
87#ifndef __O_TMPFILE
88#define __O_TMPFILE 020000000
89#endif
90
91/* a horrid kludge trying to make sure that this will fail on old kernels */
92#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
93#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT)
94
95#ifndef O_NDELAY
96#define O_NDELAY O_NONBLOCK
97#endif
98
99#define F_DUPFD 0 /* dup */
100#define F_GETFD 1 /* get close_on_exec */
101#define F_SETFD 2 /* set/clear close_on_exec */
102#define F_GETFL 3 /* get file->f_flags */
103#define F_SETFL 4 /* set file->f_flags */
104#ifndef F_GETLK
105#define F_GETLK 5
106#define F_SETLK 6
107#define F_SETLKW 7
108#endif
109#ifndef F_SETOWN
110#define F_SETOWN 8 /* for sockets. */
111#define F_GETOWN 9 /* for sockets. */
112#endif
113#ifndef F_SETSIG
114#define F_SETSIG 10 /* for sockets. */
115#define F_GETSIG 11 /* for sockets. */
116#endif
117
118#ifndef CONFIG_64BIT
119#ifndef F_GETLK64
120#define F_GETLK64 12 /* using 'struct flock64' */
121#define F_SETLK64 13
122#define F_SETLKW64 14
123#endif
124#endif
125
126#ifndef F_SETOWN_EX
127#define F_SETOWN_EX 15
128#define F_GETOWN_EX 16
129#endif
130
131#ifndef F_GETOWNER_UIDS
132#define F_GETOWNER_UIDS 17
133#endif
134
135/*
136 * Open File Description Locks
137 *
138 * Usually record locks held by a process are released on *any* close and are
139 * not inherited across a fork().
140 *
141 * These cmd values will set locks that conflict with process-associated
142 * record locks, but are "owned" by the open file description, not the
143 * process. This means that they are inherited across fork() like BSD (flock)
144 * locks, and they are only released automatically when the last reference to
145 * the the open file against which they were acquired is put.
146 */
147#define F_OFD_GETLK 36
148#define F_OFD_SETLK 37
149#define F_OFD_SETLKW 38
150
151#define F_OWNER_TID 0
152#define F_OWNER_PID 1
153#define F_OWNER_PGRP 2
154
155struct f_owner_ex {
156 int type;
157 __kernel_pid_t pid;
158};
159
160/* for F_[GET|SET]FL */
161#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
162
163/* for posix fcntl() and lockf() */
164#ifndef F_RDLCK
165#define F_RDLCK 0
166#define F_WRLCK 1
167#define F_UNLCK 2
168#endif
169
170/* for old implementation of bsd flock () */
171#ifndef F_EXLCK
172#define F_EXLCK 4 /* or 3 */
173#define F_SHLCK 8 /* or 4 */
174#endif
175
176/* operations for bsd flock(), also used by the kernel implementation */
177#define LOCK_SH 1 /* shared lock */
178#define LOCK_EX 2 /* exclusive lock */
179#define LOCK_NB 4 /* or'd with one of the above to prevent
180 blocking */
181#define LOCK_UN 8 /* remove lock */
182
183#define LOCK_MAND 32 /* This is a mandatory flock ... */
184#define LOCK_READ 64 /* which allows concurrent read operations */
185#define LOCK_WRITE 128 /* which allows concurrent write operations */
186#define LOCK_RW 192 /* which allows concurrent read & write ops */
187
188#define F_LINUX_SPECIFIC_BASE 1024
189
190#ifndef HAVE_ARCH_STRUCT_FLOCK
191#ifndef __ARCH_FLOCK_PAD
192#define __ARCH_FLOCK_PAD
193#endif
194
195struct flock {
196 short l_type;
197 short l_whence;
198 __kernel_off_t l_start;
199 __kernel_off_t l_len;
200 __kernel_pid_t l_pid;
201 __ARCH_FLOCK_PAD
202};
203#endif
204
205#ifndef HAVE_ARCH_STRUCT_FLOCK64
206#ifndef __ARCH_FLOCK64_PAD
207#define __ARCH_FLOCK64_PAD
208#endif
209
210struct flock64 {
211 short l_type;
212 short l_whence;
213 __kernel_loff_t l_start;
214 __kernel_loff_t l_len;
215 __kernel_pid_t l_pid;
216 __ARCH_FLOCK64_PAD
217};
218#endif
219
220#endif /* _ASM_GENERIC_FCNTL_H */
diff --git a/tools/include/uapi/asm-generic/ioctls.h b/tools/include/uapi/asm-generic/ioctls.h
new file mode 100644
index 000000000000..040651735662
--- /dev/null
+++ b/tools/include/uapi/asm-generic/ioctls.h
@@ -0,0 +1,119 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef __ASM_GENERIC_IOCTLS_H
3#define __ASM_GENERIC_IOCTLS_H
4
5#include <linux/ioctl.h>
6
7/*
8 * These are the most common definitions for tty ioctl numbers.
9 * Most of them do not use the recommended _IOC(), but there is
10 * probably some source code out there hardcoding the number,
11 * so we might as well use them for all new platforms.
12 *
13 * The architectures that use different values here typically
14 * try to be compatible with some Unix variants for the same
15 * architecture.
16 */
17
18/* 0x54 is just a magic number to make these relatively unique ('T') */
19
20#define TCGETS 0x5401
21#define TCSETS 0x5402
22#define TCSETSW 0x5403
23#define TCSETSF 0x5404
24#define TCGETA 0x5405
25#define TCSETA 0x5406
26#define TCSETAW 0x5407
27#define TCSETAF 0x5408
28#define TCSBRK 0x5409
29#define TCXONC 0x540A
30#define TCFLSH 0x540B
31#define TIOCEXCL 0x540C
32#define TIOCNXCL 0x540D
33#define TIOCSCTTY 0x540E
34#define TIOCGPGRP 0x540F
35#define TIOCSPGRP 0x5410
36#define TIOCOUTQ 0x5411
37#define TIOCSTI 0x5412
38#define TIOCGWINSZ 0x5413
39#define TIOCSWINSZ 0x5414
40#define TIOCMGET 0x5415
41#define TIOCMBIS 0x5416
42#define TIOCMBIC 0x5417
43#define TIOCMSET 0x5418
44#define TIOCGSOFTCAR 0x5419
45#define TIOCSSOFTCAR 0x541A
46#define FIONREAD 0x541B
47#define TIOCINQ FIONREAD
48#define TIOCLINUX 0x541C
49#define TIOCCONS 0x541D
50#define TIOCGSERIAL 0x541E
51#define TIOCSSERIAL 0x541F
52#define TIOCPKT 0x5420
53#define FIONBIO 0x5421
54#define TIOCNOTTY 0x5422
55#define TIOCSETD 0x5423
56#define TIOCGETD 0x5424
57#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
58#define TIOCSBRK 0x5427 /* BSD compatibility */
59#define TIOCCBRK 0x5428 /* BSD compatibility */
60#define TIOCGSID 0x5429 /* Return the session ID of FD */
61#define TCGETS2 _IOR('T', 0x2A, struct termios2)
62#define TCSETS2 _IOW('T', 0x2B, struct termios2)
63#define TCSETSW2 _IOW('T', 0x2C, struct termios2)
64#define TCSETSF2 _IOW('T', 0x2D, struct termios2)
65#define TIOCGRS485 0x542E
66#ifndef TIOCSRS485
67#define TIOCSRS485 0x542F
68#endif
69#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
70#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
71#define TIOCGDEV _IOR('T', 0x32, unsigned int) /* Get primary device node of /dev/console */
72#define TCGETX 0x5432 /* SYS5 TCGETX compatibility */
73#define TCSETX 0x5433
74#define TCSETXF 0x5434
75#define TCSETXW 0x5435
76#define TIOCSIG _IOW('T', 0x36, int) /* pty: generate signal */
77#define TIOCVHANGUP 0x5437
78#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */
79#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */
80#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */
81#define TIOCGPTPEER _IO('T', 0x41) /* Safely open the slave */
82
83#define FIONCLEX 0x5450
84#define FIOCLEX 0x5451
85#define FIOASYNC 0x5452
86#define TIOCSERCONFIG 0x5453
87#define TIOCSERGWILD 0x5454
88#define TIOCSERSWILD 0x5455
89#define TIOCGLCKTRMIOS 0x5456
90#define TIOCSLCKTRMIOS 0x5457
91#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
92#define TIOCSERGETLSR 0x5459 /* Get line status register */
93#define TIOCSERGETMULTI 0x545A /* Get multiport config */
94#define TIOCSERSETMULTI 0x545B /* Set multiport config */
95
96#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
97#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
98
99/*
100 * Some arches already define FIOQSIZE due to a historical
101 * conflict with a Hayes modem-specific ioctl value.
102 */
103#ifndef FIOQSIZE
104# define FIOQSIZE 0x5460
105#endif
106
107/* Used for packet mode */
108#define TIOCPKT_DATA 0
109#define TIOCPKT_FLUSHREAD 1
110#define TIOCPKT_FLUSHWRITE 2
111#define TIOCPKT_STOP 4
112#define TIOCPKT_START 8
113#define TIOCPKT_NOSTOP 16
114#define TIOCPKT_DOSTOP 32
115#define TIOCPKT_IOCTL 64
116
117#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
118
119#endif /* __ASM_GENERIC_IOCTLS_H */
diff --git a/tools/include/uapi/asm-generic/mman-common.h b/tools/include/uapi/asm-generic/mman-common.h
index 8c27db0c5c08..f8b134f5608f 100644
--- a/tools/include/uapi/asm-generic/mman-common.h
+++ b/tools/include/uapi/asm-generic/mman-common.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef __ASM_GENERIC_MMAN_COMMON_H 2#ifndef __ASM_GENERIC_MMAN_COMMON_H
2#define __ASM_GENERIC_MMAN_COMMON_H 3#define __ASM_GENERIC_MMAN_COMMON_H
3 4
@@ -16,6 +17,7 @@
16 17
17#define MAP_SHARED 0x01 /* Share changes */ 18#define MAP_SHARED 0x01 /* Share changes */
18#define MAP_PRIVATE 0x02 /* Changes are private */ 19#define MAP_PRIVATE 0x02 /* Changes are private */
20#define MAP_SHARED_VALIDATE 0x03 /* share + validate extension flags */
19#define MAP_TYPE 0x0f /* Mask for type of mapping */ 21#define MAP_TYPE 0x0f /* Mask for type of mapping */
20#define MAP_FIXED 0x10 /* Interpret addr exactly */ 22#define MAP_FIXED 0x10 /* Interpret addr exactly */
21#define MAP_ANONYMOUS 0x20 /* don't use a file */ 23#define MAP_ANONYMOUS 0x20 /* don't use a file */
@@ -58,20 +60,12 @@
58 overrides the coredump filter bits */ 60 overrides the coredump filter bits */
59#define MADV_DODUMP 17 /* Clear the MADV_DONTDUMP flag */ 61#define MADV_DODUMP 17 /* Clear the MADV_DONTDUMP flag */
60 62
63#define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */
64#define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */
65
61/* compatibility flags */ 66/* compatibility flags */
62#define MAP_FILE 0 67#define MAP_FILE 0
63 68
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#define PKEY_DISABLE_ACCESS 0x1 69#define PKEY_DISABLE_ACCESS 0x1
76#define PKEY_DISABLE_WRITE 0x2 70#define PKEY_DISABLE_WRITE 0x2
77#define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS |\ 71#define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS |\
diff --git a/tools/include/uapi/asm-generic/mman.h b/tools/include/uapi/asm-generic/mman.h
index 10fa7857777f..2dffcbf705b3 100644
--- a/tools/include/uapi/asm-generic/mman.h
+++ b/tools/include/uapi/asm-generic/mman.h
@@ -1,7 +1,8 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef __ASM_GENERIC_MMAN_H 2#ifndef __ASM_GENERIC_MMAN_H
2#define __ASM_GENERIC_MMAN_H 3#define __ASM_GENERIC_MMAN_H
3 4
4#include <uapi/asm-generic/mman-common.h> 5#include <asm-generic/mman-common.h>
5 6
6#define MAP_GROWSDOWN 0x0100 /* stack-like segment */ 7#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
7#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ 8#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
diff --git a/tools/include/uapi/drm/drm.h b/tools/include/uapi/drm/drm.h
new file mode 100644
index 000000000000..97677cd6964d
--- /dev/null
+++ b/tools/include/uapi/drm/drm.h
@@ -0,0 +1,955 @@
1/**
2 * \file drm.h
3 * Header for the Direct Rendering Manager
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 *
7 * \par Acknowledgments:
8 * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic \c cmpxchg.
9 */
10
11/*
12 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All rights reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36#ifndef _DRM_H_
37#define _DRM_H_
38
39#if defined(__KERNEL__)
40
41#include <linux/types.h>
42#include <asm/ioctl.h>
43typedef unsigned int drm_handle_t;
44
45#elif defined(__linux__)
46
47#include <linux/types.h>
48#include <asm/ioctl.h>
49typedef unsigned int drm_handle_t;
50
51#else /* One of the BSDs */
52
53#include <sys/ioccom.h>
54#include <sys/types.h>
55typedef int8_t __s8;
56typedef uint8_t __u8;
57typedef int16_t __s16;
58typedef uint16_t __u16;
59typedef int32_t __s32;
60typedef uint32_t __u32;
61typedef int64_t __s64;
62typedef uint64_t __u64;
63typedef size_t __kernel_size_t;
64typedef unsigned long drm_handle_t;
65
66#endif
67
68#if defined(__cplusplus)
69extern "C" {
70#endif
71
72#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */
73#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */
74#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */
75#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */
76
77#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */
78#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */
79#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD)
80#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)
81#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
82
83typedef unsigned int drm_context_t;
84typedef unsigned int drm_drawable_t;
85typedef unsigned int drm_magic_t;
86
87/**
88 * Cliprect.
89 *
90 * \warning: If you change this structure, make sure you change
91 * XF86DRIClipRectRec in the server as well
92 *
93 * \note KW: Actually it's illegal to change either for
94 * backwards-compatibility reasons.
95 */
96struct drm_clip_rect {
97 unsigned short x1;
98 unsigned short y1;
99 unsigned short x2;
100 unsigned short y2;
101};
102
103/**
104 * Drawable information.
105 */
106struct drm_drawable_info {
107 unsigned int num_rects;
108 struct drm_clip_rect *rects;
109};
110
111/**
112 * Texture region,
113 */
114struct drm_tex_region {
115 unsigned char next;
116 unsigned char prev;
117 unsigned char in_use;
118 unsigned char padding;
119 unsigned int age;
120};
121
122/**
123 * Hardware lock.
124 *
125 * The lock structure is a simple cache-line aligned integer. To avoid
126 * processor bus contention on a multiprocessor system, there should not be any
127 * other data stored in the same cache line.
128 */
129struct drm_hw_lock {
130 __volatile__ unsigned int lock; /**< lock variable */
131 char padding[60]; /**< Pad to cache line */
132};
133
134/**
135 * DRM_IOCTL_VERSION ioctl argument type.
136 *
137 * \sa drmGetVersion().
138 */
139struct drm_version {
140 int version_major; /**< Major version */
141 int version_minor; /**< Minor version */
142 int version_patchlevel; /**< Patch level */
143 __kernel_size_t name_len; /**< Length of name buffer */
144 char __user *name; /**< Name of driver */
145 __kernel_size_t date_len; /**< Length of date buffer */
146 char __user *date; /**< User-space buffer to hold date */
147 __kernel_size_t desc_len; /**< Length of desc buffer */
148 char __user *desc; /**< User-space buffer to hold desc */
149};
150
151/**
152 * DRM_IOCTL_GET_UNIQUE ioctl argument type.
153 *
154 * \sa drmGetBusid() and drmSetBusId().
155 */
156struct drm_unique {
157 __kernel_size_t unique_len; /**< Length of unique */
158 char __user *unique; /**< Unique name for driver instantiation */
159};
160
161struct drm_list {
162 int count; /**< Length of user-space structures */
163 struct drm_version __user *version;
164};
165
166struct drm_block {
167 int unused;
168};
169
170/**
171 * DRM_IOCTL_CONTROL ioctl argument type.
172 *
173 * \sa drmCtlInstHandler() and drmCtlUninstHandler().
174 */
175struct drm_control {
176 enum {
177 DRM_ADD_COMMAND,
178 DRM_RM_COMMAND,
179 DRM_INST_HANDLER,
180 DRM_UNINST_HANDLER
181 } func;
182 int irq;
183};
184
185/**
186 * Type of memory to map.
187 */
188enum drm_map_type {
189 _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
190 _DRM_REGISTERS = 1, /**< no caching, no core dump */
191 _DRM_SHM = 2, /**< shared, cached */
192 _DRM_AGP = 3, /**< AGP/GART */
193 _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */
194 _DRM_CONSISTENT = 5 /**< Consistent memory for PCI DMA */
195};
196
197/**
198 * Memory mapping flags.
199 */
200enum drm_map_flags {
201 _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
202 _DRM_READ_ONLY = 0x02,
203 _DRM_LOCKED = 0x04, /**< shared, cached, locked */
204 _DRM_KERNEL = 0x08, /**< kernel requires access */
205 _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
206 _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
207 _DRM_REMOVABLE = 0x40, /**< Removable mapping */
208 _DRM_DRIVER = 0x80 /**< Managed by driver */
209};
210
211struct drm_ctx_priv_map {
212 unsigned int ctx_id; /**< Context requesting private mapping */
213 void *handle; /**< Handle of map */
214};
215
216/**
217 * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
218 * argument type.
219 *
220 * \sa drmAddMap().
221 */
222struct drm_map {
223 unsigned long offset; /**< Requested physical address (0 for SAREA)*/
224 unsigned long size; /**< Requested physical size (bytes) */
225 enum drm_map_type type; /**< Type of memory to map */
226 enum drm_map_flags flags; /**< Flags */
227 void *handle; /**< User-space: "Handle" to pass to mmap() */
228 /**< Kernel-space: kernel-virtual address */
229 int mtrr; /**< MTRR slot used */
230 /* Private data */
231};
232
233/**
234 * DRM_IOCTL_GET_CLIENT ioctl argument type.
235 */
236struct drm_client {
237 int idx; /**< Which client desired? */
238 int auth; /**< Is client authenticated? */
239 unsigned long pid; /**< Process ID */
240 unsigned long uid; /**< User ID */
241 unsigned long magic; /**< Magic */
242 unsigned long iocs; /**< Ioctl count */
243};
244
245enum drm_stat_type {
246 _DRM_STAT_LOCK,
247 _DRM_STAT_OPENS,
248 _DRM_STAT_CLOSES,
249 _DRM_STAT_IOCTLS,
250 _DRM_STAT_LOCKS,
251 _DRM_STAT_UNLOCKS,
252 _DRM_STAT_VALUE, /**< Generic value */
253 _DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */
254 _DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */
255
256 _DRM_STAT_IRQ, /**< IRQ */
257 _DRM_STAT_PRIMARY, /**< Primary DMA bytes */
258 _DRM_STAT_SECONDARY, /**< Secondary DMA bytes */
259 _DRM_STAT_DMA, /**< DMA */
260 _DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */
261 _DRM_STAT_MISSED /**< Missed DMA opportunity */
262 /* Add to the *END* of the list */
263};
264
265/**
266 * DRM_IOCTL_GET_STATS ioctl argument type.
267 */
268struct drm_stats {
269 unsigned long count;
270 struct {
271 unsigned long value;
272 enum drm_stat_type type;
273 } data[15];
274};
275
276/**
277 * Hardware locking flags.
278 */
279enum drm_lock_flags {
280 _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
281 _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
282 _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
283 _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
284 /* These *HALT* flags aren't supported yet
285 -- they will be used to support the
286 full-screen DGA-like mode. */
287 _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
288 _DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
289};
290
291/**
292 * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
293 *
294 * \sa drmGetLock() and drmUnlock().
295 */
296struct drm_lock {
297 int context;
298 enum drm_lock_flags flags;
299};
300
301/**
302 * DMA flags
303 *
304 * \warning
305 * These values \e must match xf86drm.h.
306 *
307 * \sa drm_dma.
308 */
309enum drm_dma_flags {
310 /* Flags for DMA buffer dispatch */
311 _DRM_DMA_BLOCK = 0x01, /**<
312 * Block until buffer dispatched.
313 *
314 * \note The buffer may not yet have
315 * been processed by the hardware --
316 * getting a hardware lock with the
317 * hardware quiescent will ensure
318 * that the buffer has been
319 * processed.
320 */
321 _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
322 _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
323
324 /* Flags for DMA buffer request */
325 _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
326 _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
327 _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
328};
329
330/**
331 * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
332 *
333 * \sa drmAddBufs().
334 */
335struct drm_buf_desc {
336 int count; /**< Number of buffers of this size */
337 int size; /**< Size in bytes */
338 int low_mark; /**< Low water mark */
339 int high_mark; /**< High water mark */
340 enum {
341 _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
342 _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
343 _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */
344 _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */
345 _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */
346 } flags;
347 unsigned long agp_start; /**<
348 * Start address of where the AGP buffers are
349 * in the AGP aperture
350 */
351};
352
353/**
354 * DRM_IOCTL_INFO_BUFS ioctl argument type.
355 */
356struct drm_buf_info {
357 int count; /**< Entries in list */
358 struct drm_buf_desc __user *list;
359};
360
361/**
362 * DRM_IOCTL_FREE_BUFS ioctl argument type.
363 */
364struct drm_buf_free {
365 int count;
366 int __user *list;
367};
368
369/**
370 * Buffer information
371 *
372 * \sa drm_buf_map.
373 */
374struct drm_buf_pub {
375 int idx; /**< Index into the master buffer list */
376 int total; /**< Buffer size */
377 int used; /**< Amount of buffer in use (for DMA) */
378 void __user *address; /**< Address of buffer */
379};
380
381/**
382 * DRM_IOCTL_MAP_BUFS ioctl argument type.
383 */
384struct drm_buf_map {
385 int count; /**< Length of the buffer list */
386#ifdef __cplusplus
387 void __user *virt;
388#else
389 void __user *virtual; /**< Mmap'd area in user-virtual */
390#endif
391 struct drm_buf_pub __user *list; /**< Buffer information */
392};
393
394/**
395 * DRM_IOCTL_DMA ioctl argument type.
396 *
397 * Indices here refer to the offset into the buffer list in drm_buf_get.
398 *
399 * \sa drmDMA().
400 */
401struct drm_dma {
402 int context; /**< Context handle */
403 int send_count; /**< Number of buffers to send */
404 int __user *send_indices; /**< List of handles to buffers */
405 int __user *send_sizes; /**< Lengths of data to send */
406 enum drm_dma_flags flags; /**< Flags */
407 int request_count; /**< Number of buffers requested */
408 int request_size; /**< Desired size for buffers */
409 int __user *request_indices; /**< Buffer information */
410 int __user *request_sizes;
411 int granted_count; /**< Number of buffers granted */
412};
413
414enum drm_ctx_flags {
415 _DRM_CONTEXT_PRESERVED = 0x01,
416 _DRM_CONTEXT_2DONLY = 0x02
417};
418
419/**
420 * DRM_IOCTL_ADD_CTX ioctl argument type.
421 *
422 * \sa drmCreateContext() and drmDestroyContext().
423 */
424struct drm_ctx {
425 drm_context_t handle;
426 enum drm_ctx_flags flags;
427};
428
429/**
430 * DRM_IOCTL_RES_CTX ioctl argument type.
431 */
432struct drm_ctx_res {
433 int count;
434 struct drm_ctx __user *contexts;
435};
436
437/**
438 * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
439 */
440struct drm_draw {
441 drm_drawable_t handle;
442};
443
444/**
445 * DRM_IOCTL_UPDATE_DRAW ioctl argument type.
446 */
447typedef enum {
448 DRM_DRAWABLE_CLIPRECTS
449} drm_drawable_info_type_t;
450
451struct drm_update_draw {
452 drm_drawable_t handle;
453 unsigned int type;
454 unsigned int num;
455 unsigned long long data;
456};
457
458/**
459 * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
460 */
461struct drm_auth {
462 drm_magic_t magic;
463};
464
465/**
466 * DRM_IOCTL_IRQ_BUSID ioctl argument type.
467 *
468 * \sa drmGetInterruptFromBusID().
469 */
470struct drm_irq_busid {
471 int irq; /**< IRQ number */
472 int busnum; /**< bus number */
473 int devnum; /**< device number */
474 int funcnum; /**< function number */
475};
476
477enum drm_vblank_seq_type {
478 _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
479 _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
480 /* bits 1-6 are reserved for high crtcs */
481 _DRM_VBLANK_HIGH_CRTC_MASK = 0x0000003e,
482 _DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */
483 _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */
484 _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */
485 _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
486 _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking, unsupported */
487};
488#define _DRM_VBLANK_HIGH_CRTC_SHIFT 1
489
490#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
491#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \
492 _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)
493
494struct drm_wait_vblank_request {
495 enum drm_vblank_seq_type type;
496 unsigned int sequence;
497 unsigned long signal;
498};
499
500struct drm_wait_vblank_reply {
501 enum drm_vblank_seq_type type;
502 unsigned int sequence;
503 long tval_sec;
504 long tval_usec;
505};
506
507/**
508 * DRM_IOCTL_WAIT_VBLANK ioctl argument type.
509 *
510 * \sa drmWaitVBlank().
511 */
512union drm_wait_vblank {
513 struct drm_wait_vblank_request request;
514 struct drm_wait_vblank_reply reply;
515};
516
517#define _DRM_PRE_MODESET 1
518#define _DRM_POST_MODESET 2
519
520/**
521 * DRM_IOCTL_MODESET_CTL ioctl argument type
522 *
523 * \sa drmModesetCtl().
524 */
525struct drm_modeset_ctl {
526 __u32 crtc;
527 __u32 cmd;
528};
529
530/**
531 * DRM_IOCTL_AGP_ENABLE ioctl argument type.
532 *
533 * \sa drmAgpEnable().
534 */
535struct drm_agp_mode {
536 unsigned long mode; /**< AGP mode */
537};
538
539/**
540 * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
541 *
542 * \sa drmAgpAlloc() and drmAgpFree().
543 */
544struct drm_agp_buffer {
545 unsigned long size; /**< In bytes -- will round to page boundary */
546 unsigned long handle; /**< Used for binding / unbinding */
547 unsigned long type; /**< Type of memory to allocate */
548 unsigned long physical; /**< Physical used by i810 */
549};
550
551/**
552 * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
553 *
554 * \sa drmAgpBind() and drmAgpUnbind().
555 */
556struct drm_agp_binding {
557 unsigned long handle; /**< From drm_agp_buffer */
558 unsigned long offset; /**< In bytes -- will round to page boundary */
559};
560
561/**
562 * DRM_IOCTL_AGP_INFO ioctl argument type.
563 *
564 * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(),
565 * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
566 * drmAgpVendorId() and drmAgpDeviceId().
567 */
568struct drm_agp_info {
569 int agp_version_major;
570 int agp_version_minor;
571 unsigned long mode;
572 unsigned long aperture_base; /* physical address */
573 unsigned long aperture_size; /* bytes */
574 unsigned long memory_allowed; /* bytes */
575 unsigned long memory_used;
576
577 /* PCI information */
578 unsigned short id_vendor;
579 unsigned short id_device;
580};
581
582/**
583 * DRM_IOCTL_SG_ALLOC ioctl argument type.
584 */
585struct drm_scatter_gather {
586 unsigned long size; /**< In bytes -- will round to page boundary */
587 unsigned long handle; /**< Used for mapping / unmapping */
588};
589
590/**
591 * DRM_IOCTL_SET_VERSION ioctl argument type.
592 */
593struct drm_set_version {
594 int drm_di_major;
595 int drm_di_minor;
596 int drm_dd_major;
597 int drm_dd_minor;
598};
599
600/** DRM_IOCTL_GEM_CLOSE ioctl argument type */
601struct drm_gem_close {
602 /** Handle of the object to be closed. */
603 __u32 handle;
604 __u32 pad;
605};
606
607/** DRM_IOCTL_GEM_FLINK ioctl argument type */
608struct drm_gem_flink {
609 /** Handle for the object being named */
610 __u32 handle;
611
612 /** Returned global name */
613 __u32 name;
614};
615
616/** DRM_IOCTL_GEM_OPEN ioctl argument type */
617struct drm_gem_open {
618 /** Name of object being opened */
619 __u32 name;
620
621 /** Returned handle for the object */
622 __u32 handle;
623
624 /** Returned size of the object */
625 __u64 size;
626};
627
628#define DRM_CAP_DUMB_BUFFER 0x1
629#define DRM_CAP_VBLANK_HIGH_CRTC 0x2
630#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
631#define DRM_CAP_DUMB_PREFER_SHADOW 0x4
632#define DRM_CAP_PRIME 0x5
633#define DRM_PRIME_CAP_IMPORT 0x1
634#define DRM_PRIME_CAP_EXPORT 0x2
635#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
636#define DRM_CAP_ASYNC_PAGE_FLIP 0x7
637/*
638 * The CURSOR_WIDTH and CURSOR_HEIGHT capabilities return a valid widthxheight
639 * combination for the hardware cursor. The intention is that a hardware
640 * agnostic userspace can query a cursor plane size to use.
641 *
642 * Note that the cross-driver contract is to merely return a valid size;
643 * drivers are free to attach another meaning on top, eg. i915 returns the
644 * maximum plane size.
645 */
646#define DRM_CAP_CURSOR_WIDTH 0x8
647#define DRM_CAP_CURSOR_HEIGHT 0x9
648#define DRM_CAP_ADDFB2_MODIFIERS 0x10
649#define DRM_CAP_PAGE_FLIP_TARGET 0x11
650#define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12
651#define DRM_CAP_SYNCOBJ 0x13
652
653/** DRM_IOCTL_GET_CAP ioctl argument type */
654struct drm_get_cap {
655 __u64 capability;
656 __u64 value;
657};
658
659/**
660 * DRM_CLIENT_CAP_STEREO_3D
661 *
662 * if set to 1, the DRM core will expose the stereo 3D capabilities of the
663 * monitor by advertising the supported 3D layouts in the flags of struct
664 * drm_mode_modeinfo.
665 */
666#define DRM_CLIENT_CAP_STEREO_3D 1
667
668/**
669 * DRM_CLIENT_CAP_UNIVERSAL_PLANES
670 *
671 * If set to 1, the DRM core will expose all planes (overlay, primary, and
672 * cursor) to userspace.
673 */
674#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
675
676/**
677 * DRM_CLIENT_CAP_ATOMIC
678 *
679 * If set to 1, the DRM core will expose atomic properties to userspace
680 */
681#define DRM_CLIENT_CAP_ATOMIC 3
682
683/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
684struct drm_set_client_cap {
685 __u64 capability;
686 __u64 value;
687};
688
689#define DRM_RDWR O_RDWR
690#define DRM_CLOEXEC O_CLOEXEC
691struct drm_prime_handle {
692 __u32 handle;
693
694 /** Flags.. only applicable for handle->fd */
695 __u32 flags;
696
697 /** Returned dmabuf file descriptor */
698 __s32 fd;
699};
700
701struct drm_syncobj_create {
702 __u32 handle;
703#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0)
704 __u32 flags;
705};
706
707struct drm_syncobj_destroy {
708 __u32 handle;
709 __u32 pad;
710};
711
712#define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE (1 << 0)
713#define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE (1 << 0)
714struct drm_syncobj_handle {
715 __u32 handle;
716 __u32 flags;
717
718 __s32 fd;
719 __u32 pad;
720};
721
722#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
723#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
724struct drm_syncobj_wait {
725 __u64 handles;
726 /* absolute timeout */
727 __s64 timeout_nsec;
728 __u32 count_handles;
729 __u32 flags;
730 __u32 first_signaled; /* only valid when not waiting all */
731 __u32 pad;
732};
733
734struct drm_syncobj_array {
735 __u64 handles;
736 __u32 count_handles;
737 __u32 pad;
738};
739
740#if defined(__cplusplus)
741}
742#endif
743
744#include "drm_mode.h"
745
746#if defined(__cplusplus)
747extern "C" {
748#endif
749
750#define DRM_IOCTL_BASE 'd'
751#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
752#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
753#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type)
754#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type)
755
756#define DRM_IOCTL_VERSION DRM_IOWR(0x00, struct drm_version)
757#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, struct drm_unique)
758#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, struct drm_auth)
759#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, struct drm_irq_busid)
760#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, struct drm_map)
761#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client)
762#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats)
763#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version)
764#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl)
765#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close)
766#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink)
767#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open)
768#define DRM_IOCTL_GET_CAP DRM_IOWR(0x0c, struct drm_get_cap)
769#define DRM_IOCTL_SET_CLIENT_CAP DRM_IOW( 0x0d, struct drm_set_client_cap)
770
771#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique)
772#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth)
773#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, struct drm_block)
774#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, struct drm_block)
775#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, struct drm_control)
776#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, struct drm_map)
777#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, struct drm_buf_desc)
778#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, struct drm_buf_desc)
779#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, struct drm_buf_info)
780#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, struct drm_buf_map)
781#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, struct drm_buf_free)
782
783#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, struct drm_map)
784
785#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map)
786#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map)
787
788#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e)
789#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f)
790
791#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx)
792#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx)
793#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx)
794#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, struct drm_ctx)
795#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, struct drm_ctx)
796#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, struct drm_ctx)
797#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, struct drm_ctx_res)
798#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, struct drm_draw)
799#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, struct drm_draw)
800#define DRM_IOCTL_DMA DRM_IOWR(0x29, struct drm_dma)
801#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, struct drm_lock)
802#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock)
803#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock)
804
805#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle)
806#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle)
807
808#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)
809#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31)
810#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, struct drm_agp_mode)
811#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, struct drm_agp_info)
812#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, struct drm_agp_buffer)
813#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, struct drm_agp_buffer)
814#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, struct drm_agp_binding)
815#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, struct drm_agp_binding)
816
817#define DRM_IOCTL_SG_ALLOC DRM_IOWR(0x38, struct drm_scatter_gather)
818#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, struct drm_scatter_gather)
819
820#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank)
821
822#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw)
823
824#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res)
825#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc)
826#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc)
827#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor)
828#define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut)
829#define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut)
830#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder)
831#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector)
832#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd) /* deprecated (never worked) */
833#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) /* deprecated (never worked) */
834
835#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property)
836#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property)
837#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob)
838#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
839#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
840#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int)
841#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)
842#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd)
843
844#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb)
845#define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB3, struct drm_mode_map_dumb)
846#define DRM_IOCTL_MODE_DESTROY_DUMB DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
847#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
848#define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane)
849#define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane)
850#define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
851#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
852#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property)
853#define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2)
854#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic)
855#define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct drm_mode_create_blob)
856#define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct drm_mode_destroy_blob)
857
858#define DRM_IOCTL_SYNCOBJ_CREATE DRM_IOWR(0xBF, struct drm_syncobj_create)
859#define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy)
860#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle)
861#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle)
862#define DRM_IOCTL_SYNCOBJ_WAIT DRM_IOWR(0xC3, struct drm_syncobj_wait)
863#define DRM_IOCTL_SYNCOBJ_RESET DRM_IOWR(0xC4, struct drm_syncobj_array)
864#define DRM_IOCTL_SYNCOBJ_SIGNAL DRM_IOWR(0xC5, struct drm_syncobj_array)
865
866/**
867 * Device specific ioctls should only be in their respective headers
868 * The device specific ioctl range is from 0x40 to 0x9f.
869 * Generic IOCTLS restart at 0xA0.
870 *
871 * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
872 * drmCommandReadWrite().
873 */
874#define DRM_COMMAND_BASE 0x40
875#define DRM_COMMAND_END 0xA0
876
877/**
878 * Header for events written back to userspace on the drm fd. The
879 * type defines the type of event, the length specifies the total
880 * length of the event (including the header), and user_data is
881 * typically a 64 bit value passed with the ioctl that triggered the
882 * event. A read on the drm fd will always only return complete
883 * events, that is, if for example the read buffer is 100 bytes, and
884 * there are two 64 byte events pending, only one will be returned.
885 *
886 * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and
887 * up are chipset specific.
888 */
889struct drm_event {
890 __u32 type;
891 __u32 length;
892};
893
894#define DRM_EVENT_VBLANK 0x01
895#define DRM_EVENT_FLIP_COMPLETE 0x02
896
897struct drm_event_vblank {
898 struct drm_event base;
899 __u64 user_data;
900 __u32 tv_sec;
901 __u32 tv_usec;
902 __u32 sequence;
903 __u32 crtc_id; /* 0 on older kernels that do not support this */
904};
905
906/* typedef area */
907#ifndef __KERNEL__
908typedef struct drm_clip_rect drm_clip_rect_t;
909typedef struct drm_drawable_info drm_drawable_info_t;
910typedef struct drm_tex_region drm_tex_region_t;
911typedef struct drm_hw_lock drm_hw_lock_t;
912typedef struct drm_version drm_version_t;
913typedef struct drm_unique drm_unique_t;
914typedef struct drm_list drm_list_t;
915typedef struct drm_block drm_block_t;
916typedef struct drm_control drm_control_t;
917typedef enum drm_map_type drm_map_type_t;
918typedef enum drm_map_flags drm_map_flags_t;
919typedef struct drm_ctx_priv_map drm_ctx_priv_map_t;
920typedef struct drm_map drm_map_t;
921typedef struct drm_client drm_client_t;
922typedef enum drm_stat_type drm_stat_type_t;
923typedef struct drm_stats drm_stats_t;
924typedef enum drm_lock_flags drm_lock_flags_t;
925typedef struct drm_lock drm_lock_t;
926typedef enum drm_dma_flags drm_dma_flags_t;
927typedef struct drm_buf_desc drm_buf_desc_t;
928typedef struct drm_buf_info drm_buf_info_t;
929typedef struct drm_buf_free drm_buf_free_t;
930typedef struct drm_buf_pub drm_buf_pub_t;
931typedef struct drm_buf_map drm_buf_map_t;
932typedef struct drm_dma drm_dma_t;
933typedef union drm_wait_vblank drm_wait_vblank_t;
934typedef struct drm_agp_mode drm_agp_mode_t;
935typedef enum drm_ctx_flags drm_ctx_flags_t;
936typedef struct drm_ctx drm_ctx_t;
937typedef struct drm_ctx_res drm_ctx_res_t;
938typedef struct drm_draw drm_draw_t;
939typedef struct drm_update_draw drm_update_draw_t;
940typedef struct drm_auth drm_auth_t;
941typedef struct drm_irq_busid drm_irq_busid_t;
942typedef enum drm_vblank_seq_type drm_vblank_seq_type_t;
943
944typedef struct drm_agp_buffer drm_agp_buffer_t;
945typedef struct drm_agp_binding drm_agp_binding_t;
946typedef struct drm_agp_info drm_agp_info_t;
947typedef struct drm_scatter_gather drm_scatter_gather_t;
948typedef struct drm_set_version drm_set_version_t;
949#endif
950
951#if defined(__cplusplus)
952}
953#endif
954
955#endif
diff --git a/tools/include/uapi/drm/i915_drm.h b/tools/include/uapi/drm/i915_drm.h
new file mode 100644
index 000000000000..9816590d3ad2
--- /dev/null
+++ b/tools/include/uapi/drm/i915_drm.h
@@ -0,0 +1,1522 @@
1/*
2 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#ifndef _UAPI_I915_DRM_H_
28#define _UAPI_I915_DRM_H_
29
30#include "drm.h"
31
32#if defined(__cplusplus)
33extern "C" {
34#endif
35
36/* Please note that modifications to all structs defined here are
37 * subject to backwards-compatibility constraints.
38 */
39
40/**
41 * DOC: uevents generated by i915 on it's device node
42 *
43 * I915_L3_PARITY_UEVENT - Generated when the driver receives a parity mismatch
44 * event from the gpu l3 cache. Additional information supplied is ROW,
45 * BANK, SUBBANK, SLICE of the affected cacheline. Userspace should keep
46 * track of these events and if a specific cache-line seems to have a
47 * persistent error remap it with the l3 remapping tool supplied in
48 * intel-gpu-tools. The value supplied with the event is always 1.
49 *
50 * I915_ERROR_UEVENT - Generated upon error detection, currently only via
51 * hangcheck. The error detection event is a good indicator of when things
52 * began to go badly. The value supplied with the event is a 1 upon error
53 * detection, and a 0 upon reset completion, signifying no more error
54 * exists. NOTE: Disabling hangcheck or reset via module parameter will
55 * cause the related events to not be seen.
56 *
57 * I915_RESET_UEVENT - Event is generated just before an attempt to reset the
58 * the GPU. The value supplied with the event is always 1. NOTE: Disable
59 * reset via module parameter will cause this event to not be seen.
60 */
61#define I915_L3_PARITY_UEVENT "L3_PARITY_ERROR"
62#define I915_ERROR_UEVENT "ERROR"
63#define I915_RESET_UEVENT "RESET"
64
65/*
66 * MOCS indexes used for GPU surfaces, defining the cacheability of the
67 * surface data and the coherency for this data wrt. CPU vs. GPU accesses.
68 */
69enum i915_mocs_table_index {
70 /*
71 * Not cached anywhere, coherency between CPU and GPU accesses is
72 * guaranteed.
73 */
74 I915_MOCS_UNCACHED,
75 /*
76 * Cacheability and coherency controlled by the kernel automatically
77 * based on the DRM_I915_GEM_SET_CACHING IOCTL setting and the current
78 * usage of the surface (used for display scanout or not).
79 */
80 I915_MOCS_PTE,
81 /*
82 * Cached in all GPU caches available on the platform.
83 * Coherency between CPU and GPU accesses to the surface is not
84 * guaranteed without extra synchronization.
85 */
86 I915_MOCS_CACHED,
87};
88
89/* Each region is a minimum of 16k, and there are at most 255 of them.
90 */
91#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use
92 * of chars for next/prev indices */
93#define I915_LOG_MIN_TEX_REGION_SIZE 14
94
95typedef struct _drm_i915_init {
96 enum {
97 I915_INIT_DMA = 0x01,
98 I915_CLEANUP_DMA = 0x02,
99 I915_RESUME_DMA = 0x03
100 } func;
101 unsigned int mmio_offset;
102 int sarea_priv_offset;
103 unsigned int ring_start;
104 unsigned int ring_end;
105 unsigned int ring_size;
106 unsigned int front_offset;
107 unsigned int back_offset;
108 unsigned int depth_offset;
109 unsigned int w;
110 unsigned int h;
111 unsigned int pitch;
112 unsigned int pitch_bits;
113 unsigned int back_pitch;
114 unsigned int depth_pitch;
115 unsigned int cpp;
116 unsigned int chipset;
117} drm_i915_init_t;
118
119typedef struct _drm_i915_sarea {
120 struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1];
121 int last_upload; /* last time texture was uploaded */
122 int last_enqueue; /* last time a buffer was enqueued */
123 int last_dispatch; /* age of the most recently dispatched buffer */
124 int ctxOwner; /* last context to upload state */
125 int texAge;
126 int pf_enabled; /* is pageflipping allowed? */
127 int pf_active;
128 int pf_current_page; /* which buffer is being displayed? */
129 int perf_boxes; /* performance boxes to be displayed */
130 int width, height; /* screen size in pixels */
131
132 drm_handle_t front_handle;
133 int front_offset;
134 int front_size;
135
136 drm_handle_t back_handle;
137 int back_offset;
138 int back_size;
139
140 drm_handle_t depth_handle;
141 int depth_offset;
142 int depth_size;
143
144 drm_handle_t tex_handle;
145 int tex_offset;
146 int tex_size;
147 int log_tex_granularity;
148 int pitch;
149 int rotation; /* 0, 90, 180 or 270 */
150 int rotated_offset;
151 int rotated_size;
152 int rotated_pitch;
153 int virtualX, virtualY;
154
155 unsigned int front_tiled;
156 unsigned int back_tiled;
157 unsigned int depth_tiled;
158 unsigned int rotated_tiled;
159 unsigned int rotated2_tiled;
160
161 int pipeA_x;
162 int pipeA_y;
163 int pipeA_w;
164 int pipeA_h;
165 int pipeB_x;
166 int pipeB_y;
167 int pipeB_w;
168 int pipeB_h;
169
170 /* fill out some space for old userspace triple buffer */
171 drm_handle_t unused_handle;
172 __u32 unused1, unused2, unused3;
173
174 /* buffer object handles for static buffers. May change
175 * over the lifetime of the client.
176 */
177 __u32 front_bo_handle;
178 __u32 back_bo_handle;
179 __u32 unused_bo_handle;
180 __u32 depth_bo_handle;
181
182} drm_i915_sarea_t;
183
184/* due to userspace building against these headers we need some compat here */
185#define planeA_x pipeA_x
186#define planeA_y pipeA_y
187#define planeA_w pipeA_w
188#define planeA_h pipeA_h
189#define planeB_x pipeB_x
190#define planeB_y pipeB_y
191#define planeB_w pipeB_w
192#define planeB_h pipeB_h
193
194/* Flags for perf_boxes
195 */
196#define I915_BOX_RING_EMPTY 0x1
197#define I915_BOX_FLIP 0x2
198#define I915_BOX_WAIT 0x4
199#define I915_BOX_TEXTURE_LOAD 0x8
200#define I915_BOX_LOST_CONTEXT 0x10
201
202/*
203 * i915 specific ioctls.
204 *
205 * The device specific ioctl range is [DRM_COMMAND_BASE, DRM_COMMAND_END) ie
206 * [0x40, 0xa0) (a0 is excluded). The numbers below are defined as offset
207 * against DRM_COMMAND_BASE and should be between [0x0, 0x60).
208 */
209#define DRM_I915_INIT 0x00
210#define DRM_I915_FLUSH 0x01
211#define DRM_I915_FLIP 0x02
212#define DRM_I915_BATCHBUFFER 0x03
213#define DRM_I915_IRQ_EMIT 0x04
214#define DRM_I915_IRQ_WAIT 0x05
215#define DRM_I915_GETPARAM 0x06
216#define DRM_I915_SETPARAM 0x07
217#define DRM_I915_ALLOC 0x08
218#define DRM_I915_FREE 0x09
219#define DRM_I915_INIT_HEAP 0x0a
220#define DRM_I915_CMDBUFFER 0x0b
221#define DRM_I915_DESTROY_HEAP 0x0c
222#define DRM_I915_SET_VBLANK_PIPE 0x0d
223#define DRM_I915_GET_VBLANK_PIPE 0x0e
224#define DRM_I915_VBLANK_SWAP 0x0f
225#define DRM_I915_HWS_ADDR 0x11
226#define DRM_I915_GEM_INIT 0x13
227#define DRM_I915_GEM_EXECBUFFER 0x14
228#define DRM_I915_GEM_PIN 0x15
229#define DRM_I915_GEM_UNPIN 0x16
230#define DRM_I915_GEM_BUSY 0x17
231#define DRM_I915_GEM_THROTTLE 0x18
232#define DRM_I915_GEM_ENTERVT 0x19
233#define DRM_I915_GEM_LEAVEVT 0x1a
234#define DRM_I915_GEM_CREATE 0x1b
235#define DRM_I915_GEM_PREAD 0x1c
236#define DRM_I915_GEM_PWRITE 0x1d
237#define DRM_I915_GEM_MMAP 0x1e
238#define DRM_I915_GEM_SET_DOMAIN 0x1f
239#define DRM_I915_GEM_SW_FINISH 0x20
240#define DRM_I915_GEM_SET_TILING 0x21
241#define DRM_I915_GEM_GET_TILING 0x22
242#define DRM_I915_GEM_GET_APERTURE 0x23
243#define DRM_I915_GEM_MMAP_GTT 0x24
244#define DRM_I915_GET_PIPE_FROM_CRTC_ID 0x25
245#define DRM_I915_GEM_MADVISE 0x26
246#define DRM_I915_OVERLAY_PUT_IMAGE 0x27
247#define DRM_I915_OVERLAY_ATTRS 0x28
248#define DRM_I915_GEM_EXECBUFFER2 0x29
249#define DRM_I915_GEM_EXECBUFFER2_WR DRM_I915_GEM_EXECBUFFER2
250#define DRM_I915_GET_SPRITE_COLORKEY 0x2a
251#define DRM_I915_SET_SPRITE_COLORKEY 0x2b
252#define DRM_I915_GEM_WAIT 0x2c
253#define DRM_I915_GEM_CONTEXT_CREATE 0x2d
254#define DRM_I915_GEM_CONTEXT_DESTROY 0x2e
255#define DRM_I915_GEM_SET_CACHING 0x2f
256#define DRM_I915_GEM_GET_CACHING 0x30
257#define DRM_I915_REG_READ 0x31
258#define DRM_I915_GET_RESET_STATS 0x32
259#define DRM_I915_GEM_USERPTR 0x33
260#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34
261#define DRM_I915_GEM_CONTEXT_SETPARAM 0x35
262#define DRM_I915_PERF_OPEN 0x36
263#define DRM_I915_PERF_ADD_CONFIG 0x37
264#define DRM_I915_PERF_REMOVE_CONFIG 0x38
265
266#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
267#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
268#define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
269#define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
270#define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
271#define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
272#define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t)
273#define DRM_IOCTL_I915_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SETPARAM, drm_i915_setparam_t)
274#define DRM_IOCTL_I915_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_ALLOC, drm_i915_mem_alloc_t)
275#define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t)
276#define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t)
277#define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t)
278#define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
279#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
280#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
281#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
282#define DRM_IOCTL_I915_HWS_ADDR DRM_IOW(DRM_COMMAND_BASE + DRM_I915_HWS_ADDR, struct drm_i915_gem_init)
283#define DRM_IOCTL_I915_GEM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init)
284#define DRM_IOCTL_I915_GEM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer)
285#define DRM_IOCTL_I915_GEM_EXECBUFFER2 DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2)
286#define DRM_IOCTL_I915_GEM_EXECBUFFER2_WR DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2_WR, struct drm_i915_gem_execbuffer2)
287#define DRM_IOCTL_I915_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
288#define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
289#define DRM_IOCTL_I915_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
290#define DRM_IOCTL_I915_GEM_SET_CACHING DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_SET_CACHING, struct drm_i915_gem_caching)
291#define DRM_IOCTL_I915_GEM_GET_CACHING DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_GET_CACHING, struct drm_i915_gem_caching)
292#define DRM_IOCTL_I915_GEM_THROTTLE DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE)
293#define DRM_IOCTL_I915_GEM_ENTERVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT)
294#define DRM_IOCTL_I915_GEM_LEAVEVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT)
295#define DRM_IOCTL_I915_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create)
296#define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread)
297#define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite)
298#define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap)
299#define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt)
300#define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain)
301#define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish)
302#define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
303#define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling)
304#define DRM_IOCTL_I915_GEM_GET_APERTURE DRM_IOR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
305#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_i915_get_pipe_from_crtc_id)
306#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
307#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image)
308#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
309#define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
310#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
311#define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait)
312#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
313#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
314#define DRM_IOCTL_I915_REG_READ DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
315#define DRM_IOCTL_I915_GET_RESET_STATS DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats)
316#define DRM_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_USERPTR, struct drm_i915_gem_userptr)
317#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
318#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
319#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
320#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
321#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
322
323/* Allow drivers to submit batchbuffers directly to hardware, relying
324 * on the security mechanisms provided by hardware.
325 */
326typedef struct drm_i915_batchbuffer {
327 int start; /* agp offset */
328 int used; /* nr bytes in use */
329 int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
330 int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
331 int num_cliprects; /* mulitpass with multiple cliprects? */
332 struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
333} drm_i915_batchbuffer_t;
334
335/* As above, but pass a pointer to userspace buffer which can be
336 * validated by the kernel prior to sending to hardware.
337 */
338typedef struct _drm_i915_cmdbuffer {
339 char __user *buf; /* pointer to userspace command buffer */
340 int sz; /* nr bytes in buf */
341 int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
342 int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
343 int num_cliprects; /* mulitpass with multiple cliprects? */
344 struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
345} drm_i915_cmdbuffer_t;
346
347/* Userspace can request & wait on irq's:
348 */
349typedef struct drm_i915_irq_emit {
350 int __user *irq_seq;
351} drm_i915_irq_emit_t;
352
353typedef struct drm_i915_irq_wait {
354 int irq_seq;
355} drm_i915_irq_wait_t;
356
357/* Ioctl to query kernel params:
358 */
359#define I915_PARAM_IRQ_ACTIVE 1
360#define I915_PARAM_ALLOW_BATCHBUFFER 2
361#define I915_PARAM_LAST_DISPATCH 3
362#define I915_PARAM_CHIPSET_ID 4
363#define I915_PARAM_HAS_GEM 5
364#define I915_PARAM_NUM_FENCES_AVAIL 6
365#define I915_PARAM_HAS_OVERLAY 7
366#define I915_PARAM_HAS_PAGEFLIPPING 8
367#define I915_PARAM_HAS_EXECBUF2 9
368#define I915_PARAM_HAS_BSD 10
369#define I915_PARAM_HAS_BLT 11
370#define I915_PARAM_HAS_RELAXED_FENCING 12
371#define I915_PARAM_HAS_COHERENT_RINGS 13
372#define I915_PARAM_HAS_EXEC_CONSTANTS 14
373#define I915_PARAM_HAS_RELAXED_DELTA 15
374#define I915_PARAM_HAS_GEN7_SOL_RESET 16
375#define I915_PARAM_HAS_LLC 17
376#define I915_PARAM_HAS_ALIASING_PPGTT 18
377#define I915_PARAM_HAS_WAIT_TIMEOUT 19
378#define I915_PARAM_HAS_SEMAPHORES 20
379#define I915_PARAM_HAS_PRIME_VMAP_FLUSH 21
380#define I915_PARAM_HAS_VEBOX 22
381#define I915_PARAM_HAS_SECURE_BATCHES 23
382#define I915_PARAM_HAS_PINNED_BATCHES 24
383#define I915_PARAM_HAS_EXEC_NO_RELOC 25
384#define I915_PARAM_HAS_EXEC_HANDLE_LUT 26
385#define I915_PARAM_HAS_WT 27
386#define I915_PARAM_CMD_PARSER_VERSION 28
387#define I915_PARAM_HAS_COHERENT_PHYS_GTT 29
388#define I915_PARAM_MMAP_VERSION 30
389#define I915_PARAM_HAS_BSD2 31
390#define I915_PARAM_REVISION 32
391#define I915_PARAM_SUBSLICE_TOTAL 33
392#define I915_PARAM_EU_TOTAL 34
393#define I915_PARAM_HAS_GPU_RESET 35
394#define I915_PARAM_HAS_RESOURCE_STREAMER 36
395#define I915_PARAM_HAS_EXEC_SOFTPIN 37
396#define I915_PARAM_HAS_POOLED_EU 38
397#define I915_PARAM_MIN_EU_IN_POOL 39
398#define I915_PARAM_MMAP_GTT_VERSION 40
399
400/* Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution
401 * priorities and the driver will attempt to execute batches in priority order.
402 */
403#define I915_PARAM_HAS_SCHEDULER 41
404#define I915_PARAM_HUC_STATUS 42
405
406/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to opt-out of
407 * synchronisation with implicit fencing on individual objects.
408 * See EXEC_OBJECT_ASYNC.
409 */
410#define I915_PARAM_HAS_EXEC_ASYNC 43
411
412/* Query whether DRM_I915_GEM_EXECBUFFER2 supports explicit fence support -
413 * both being able to pass in a sync_file fd to wait upon before executing,
414 * and being able to return a new sync_file fd that is signaled when the
415 * current request is complete. See I915_EXEC_FENCE_IN and I915_EXEC_FENCE_OUT.
416 */
417#define I915_PARAM_HAS_EXEC_FENCE 44
418
419/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to capture
420 * user specified bufffers for post-mortem debugging of GPU hangs. See
421 * EXEC_OBJECT_CAPTURE.
422 */
423#define I915_PARAM_HAS_EXEC_CAPTURE 45
424
425#define I915_PARAM_SLICE_MASK 46
426
427/* Assuming it's uniform for each slice, this queries the mask of subslices
428 * per-slice for this system.
429 */
430#define I915_PARAM_SUBSLICE_MASK 47
431
432/*
433 * Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying the batch buffer
434 * as the first execobject as opposed to the last. See I915_EXEC_BATCH_FIRST.
435 */
436#define I915_PARAM_HAS_EXEC_BATCH_FIRST 48
437
438/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of
439 * drm_i915_gem_exec_fence structures. See I915_EXEC_FENCE_ARRAY.
440 */
441#define I915_PARAM_HAS_EXEC_FENCE_ARRAY 49
442
443typedef struct drm_i915_getparam {
444 __s32 param;
445 /*
446 * WARNING: Using pointers instead of fixed-size u64 means we need to write
447 * compat32 code. Don't repeat this mistake.
448 */
449 int __user *value;
450} drm_i915_getparam_t;
451
452/* Ioctl to set kernel params:
453 */
454#define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1
455#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2
456#define I915_SETPARAM_ALLOW_BATCHBUFFER 3
457#define I915_SETPARAM_NUM_USED_FENCES 4
458
459typedef struct drm_i915_setparam {
460 int param;
461 int value;
462} drm_i915_setparam_t;
463
464/* A memory manager for regions of shared memory:
465 */
466#define I915_MEM_REGION_AGP 1
467
468typedef struct drm_i915_mem_alloc {
469 int region;
470 int alignment;
471 int size;
472 int __user *region_offset; /* offset from start of fb or agp */
473} drm_i915_mem_alloc_t;
474
475typedef struct drm_i915_mem_free {
476 int region;
477 int region_offset;
478} drm_i915_mem_free_t;
479
480typedef struct drm_i915_mem_init_heap {
481 int region;
482 int size;
483 int start;
484} drm_i915_mem_init_heap_t;
485
486/* Allow memory manager to be torn down and re-initialized (eg on
487 * rotate):
488 */
489typedef struct drm_i915_mem_destroy_heap {
490 int region;
491} drm_i915_mem_destroy_heap_t;
492
493/* Allow X server to configure which pipes to monitor for vblank signals
494 */
495#define DRM_I915_VBLANK_PIPE_A 1
496#define DRM_I915_VBLANK_PIPE_B 2
497
498typedef struct drm_i915_vblank_pipe {
499 int pipe;
500} drm_i915_vblank_pipe_t;
501
502/* Schedule buffer swap at given vertical blank:
503 */
504typedef struct drm_i915_vblank_swap {
505 drm_drawable_t drawable;
506 enum drm_vblank_seq_type seqtype;
507 unsigned int sequence;
508} drm_i915_vblank_swap_t;
509
510typedef struct drm_i915_hws_addr {
511 __u64 addr;
512} drm_i915_hws_addr_t;
513
514struct drm_i915_gem_init {
515 /**
516 * Beginning offset in the GTT to be managed by the DRM memory
517 * manager.
518 */
519 __u64 gtt_start;
520 /**
521 * Ending offset in the GTT to be managed by the DRM memory
522 * manager.
523 */
524 __u64 gtt_end;
525};
526
527struct drm_i915_gem_create {
528 /**
529 * Requested size for the object.
530 *
531 * The (page-aligned) allocated size for the object will be returned.
532 */
533 __u64 size;
534 /**
535 * Returned handle for the object.
536 *
537 * Object handles are nonzero.
538 */
539 __u32 handle;
540 __u32 pad;
541};
542
543struct drm_i915_gem_pread {
544 /** Handle for the object being read. */
545 __u32 handle;
546 __u32 pad;
547 /** Offset into the object to read from */
548 __u64 offset;
549 /** Length of data to read */
550 __u64 size;
551 /**
552 * Pointer to write the data into.
553 *
554 * This is a fixed-size type for 32/64 compatibility.
555 */
556 __u64 data_ptr;
557};
558
559struct drm_i915_gem_pwrite {
560 /** Handle for the object being written to. */
561 __u32 handle;
562 __u32 pad;
563 /** Offset into the object to write to */
564 __u64 offset;
565 /** Length of data to write */
566 __u64 size;
567 /**
568 * Pointer to read the data from.
569 *
570 * This is a fixed-size type for 32/64 compatibility.
571 */
572 __u64 data_ptr;
573};
574
575struct drm_i915_gem_mmap {
576 /** Handle for the object being mapped. */
577 __u32 handle;
578 __u32 pad;
579 /** Offset in the object to map. */
580 __u64 offset;
581 /**
582 * Length of data to map.
583 *
584 * The value will be page-aligned.
585 */
586 __u64 size;
587 /**
588 * Returned pointer the data was mapped at.
589 *
590 * This is a fixed-size type for 32/64 compatibility.
591 */
592 __u64 addr_ptr;
593
594 /**
595 * Flags for extended behaviour.
596 *
597 * Added in version 2.
598 */
599 __u64 flags;
600#define I915_MMAP_WC 0x1
601};
602
603struct drm_i915_gem_mmap_gtt {
604 /** Handle for the object being mapped. */
605 __u32 handle;
606 __u32 pad;
607 /**
608 * Fake offset to use for subsequent mmap call
609 *
610 * This is a fixed-size type for 32/64 compatibility.
611 */
612 __u64 offset;
613};
614
615struct drm_i915_gem_set_domain {
616 /** Handle for the object */
617 __u32 handle;
618
619 /** New read domains */
620 __u32 read_domains;
621
622 /** New write domain */
623 __u32 write_domain;
624};
625
626struct drm_i915_gem_sw_finish {
627 /** Handle for the object */
628 __u32 handle;
629};
630
631struct drm_i915_gem_relocation_entry {
632 /**
633 * Handle of the buffer being pointed to by this relocation entry.
634 *
635 * It's appealing to make this be an index into the mm_validate_entry
636 * list to refer to the buffer, but this allows the driver to create
637 * a relocation list for state buffers and not re-write it per
638 * exec using the buffer.
639 */
640 __u32 target_handle;
641
642 /**
643 * Value to be added to the offset of the target buffer to make up
644 * the relocation entry.
645 */
646 __u32 delta;
647
648 /** Offset in the buffer the relocation entry will be written into */
649 __u64 offset;
650
651 /**
652 * Offset value of the target buffer that the relocation entry was last
653 * written as.
654 *
655 * If the buffer has the same offset as last time, we can skip syncing
656 * and writing the relocation. This value is written back out by
657 * the execbuffer ioctl when the relocation is written.
658 */
659 __u64 presumed_offset;
660
661 /**
662 * Target memory domains read by this operation.
663 */
664 __u32 read_domains;
665
666 /**
667 * Target memory domains written by this operation.
668 *
669 * Note that only one domain may be written by the whole
670 * execbuffer operation, so that where there are conflicts,
671 * the application will get -EINVAL back.
672 */
673 __u32 write_domain;
674};
675
676/** @{
677 * Intel memory domains
678 *
679 * Most of these just align with the various caches in
680 * the system and are used to flush and invalidate as
681 * objects end up cached in different domains.
682 */
683/** CPU cache */
684#define I915_GEM_DOMAIN_CPU 0x00000001
685/** Render cache, used by 2D and 3D drawing */
686#define I915_GEM_DOMAIN_RENDER 0x00000002
687/** Sampler cache, used by texture engine */
688#define I915_GEM_DOMAIN_SAMPLER 0x00000004
689/** Command queue, used to load batch buffers */
690#define I915_GEM_DOMAIN_COMMAND 0x00000008
691/** Instruction cache, used by shader programs */
692#define I915_GEM_DOMAIN_INSTRUCTION 0x00000010
693/** Vertex address cache */
694#define I915_GEM_DOMAIN_VERTEX 0x00000020
695/** GTT domain - aperture and scanout */
696#define I915_GEM_DOMAIN_GTT 0x00000040
697/** WC domain - uncached access */
698#define I915_GEM_DOMAIN_WC 0x00000080
699/** @} */
700
701struct drm_i915_gem_exec_object {
702 /**
703 * User's handle for a buffer to be bound into the GTT for this
704 * operation.
705 */
706 __u32 handle;
707
708 /** Number of relocations to be performed on this buffer */
709 __u32 relocation_count;
710 /**
711 * Pointer to array of struct drm_i915_gem_relocation_entry containing
712 * the relocations to be performed in this buffer.
713 */
714 __u64 relocs_ptr;
715
716 /** Required alignment in graphics aperture */
717 __u64 alignment;
718
719 /**
720 * Returned value of the updated offset of the object, for future
721 * presumed_offset writes.
722 */
723 __u64 offset;
724};
725
726struct drm_i915_gem_execbuffer {
727 /**
728 * List of buffers to be validated with their relocations to be
729 * performend on them.
730 *
731 * This is a pointer to an array of struct drm_i915_gem_validate_entry.
732 *
733 * These buffers must be listed in an order such that all relocations
734 * a buffer is performing refer to buffers that have already appeared
735 * in the validate list.
736 */
737 __u64 buffers_ptr;
738 __u32 buffer_count;
739
740 /** Offset in the batchbuffer to start execution from. */
741 __u32 batch_start_offset;
742 /** Bytes used in batchbuffer from batch_start_offset */
743 __u32 batch_len;
744 __u32 DR1;
745 __u32 DR4;
746 __u32 num_cliprects;
747 /** This is a struct drm_clip_rect *cliprects */
748 __u64 cliprects_ptr;
749};
750
751struct drm_i915_gem_exec_object2 {
752 /**
753 * User's handle for a buffer to be bound into the GTT for this
754 * operation.
755 */
756 __u32 handle;
757
758 /** Number of relocations to be performed on this buffer */
759 __u32 relocation_count;
760 /**
761 * Pointer to array of struct drm_i915_gem_relocation_entry containing
762 * the relocations to be performed in this buffer.
763 */
764 __u64 relocs_ptr;
765
766 /** Required alignment in graphics aperture */
767 __u64 alignment;
768
769 /**
770 * When the EXEC_OBJECT_PINNED flag is specified this is populated by
771 * the user with the GTT offset at which this object will be pinned.
772 * When the I915_EXEC_NO_RELOC flag is specified this must contain the
773 * presumed_offset of the object.
774 * During execbuffer2 the kernel populates it with the value of the
775 * current GTT offset of the object, for future presumed_offset writes.
776 */
777 __u64 offset;
778
779#define EXEC_OBJECT_NEEDS_FENCE (1<<0)
780#define EXEC_OBJECT_NEEDS_GTT (1<<1)
781#define EXEC_OBJECT_WRITE (1<<2)
782#define EXEC_OBJECT_SUPPORTS_48B_ADDRESS (1<<3)
783#define EXEC_OBJECT_PINNED (1<<4)
784#define EXEC_OBJECT_PAD_TO_SIZE (1<<5)
785/* The kernel implicitly tracks GPU activity on all GEM objects, and
786 * synchronises operations with outstanding rendering. This includes
787 * rendering on other devices if exported via dma-buf. However, sometimes
788 * this tracking is too coarse and the user knows better. For example,
789 * if the object is split into non-overlapping ranges shared between different
790 * clients or engines (i.e. suballocating objects), the implicit tracking
791 * by kernel assumes that each operation affects the whole object rather
792 * than an individual range, causing needless synchronisation between clients.
793 * The kernel will also forgo any CPU cache flushes prior to rendering from
794 * the object as the client is expected to be also handling such domain
795 * tracking.
796 *
797 * The kernel maintains the implicit tracking in order to manage resources
798 * used by the GPU - this flag only disables the synchronisation prior to
799 * rendering with this object in this execbuf.
800 *
801 * Opting out of implicit synhronisation requires the user to do its own
802 * explicit tracking to avoid rendering corruption. See, for example,
803 * I915_PARAM_HAS_EXEC_FENCE to order execbufs and execute them asynchronously.
804 */
805#define EXEC_OBJECT_ASYNC (1<<6)
806/* Request that the contents of this execobject be copied into the error
807 * state upon a GPU hang involving this batch for post-mortem debugging.
808 * These buffers are recorded in no particular order as "user" in
809 * /sys/class/drm/cardN/error. Query I915_PARAM_HAS_EXEC_CAPTURE to see
810 * if the kernel supports this flag.
811 */
812#define EXEC_OBJECT_CAPTURE (1<<7)
813/* All remaining bits are MBZ and RESERVED FOR FUTURE USE */
814#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_CAPTURE<<1)
815 __u64 flags;
816
817 union {
818 __u64 rsvd1;
819 __u64 pad_to_size;
820 };
821 __u64 rsvd2;
822};
823
824struct drm_i915_gem_exec_fence {
825 /**
826 * User's handle for a drm_syncobj to wait on or signal.
827 */
828 __u32 handle;
829
830#define I915_EXEC_FENCE_WAIT (1<<0)
831#define I915_EXEC_FENCE_SIGNAL (1<<1)
832#define __I915_EXEC_FENCE_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SIGNAL << 1))
833 __u32 flags;
834};
835
836struct drm_i915_gem_execbuffer2 {
837 /**
838 * List of gem_exec_object2 structs
839 */
840 __u64 buffers_ptr;
841 __u32 buffer_count;
842
843 /** Offset in the batchbuffer to start execution from. */
844 __u32 batch_start_offset;
845 /** Bytes used in batchbuffer from batch_start_offset */
846 __u32 batch_len;
847 __u32 DR1;
848 __u32 DR4;
849 __u32 num_cliprects;
850 /**
851 * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY
852 * is not set. If I915_EXEC_FENCE_ARRAY is set, then this is a
853 * struct drm_i915_gem_exec_fence *fences.
854 */
855 __u64 cliprects_ptr;
856#define I915_EXEC_RING_MASK (7<<0)
857#define I915_EXEC_DEFAULT (0<<0)
858#define I915_EXEC_RENDER (1<<0)
859#define I915_EXEC_BSD (2<<0)
860#define I915_EXEC_BLT (3<<0)
861#define I915_EXEC_VEBOX (4<<0)
862
863/* Used for switching the constants addressing mode on gen4+ RENDER ring.
864 * Gen6+ only supports relative addressing to dynamic state (default) and
865 * absolute addressing.
866 *
867 * These flags are ignored for the BSD and BLT rings.
868 */
869#define I915_EXEC_CONSTANTS_MASK (3<<6)
870#define I915_EXEC_CONSTANTS_REL_GENERAL (0<<6) /* default */
871#define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6)
872#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */
873 __u64 flags;
874 __u64 rsvd1; /* now used for context info */
875 __u64 rsvd2;
876};
877
878/** Resets the SO write offset registers for transform feedback on gen7. */
879#define I915_EXEC_GEN7_SOL_RESET (1<<8)
880
881/** Request a privileged ("secure") batch buffer. Note only available for
882 * DRM_ROOT_ONLY | DRM_MASTER processes.
883 */
884#define I915_EXEC_SECURE (1<<9)
885
886/** Inform the kernel that the batch is and will always be pinned. This
887 * negates the requirement for a workaround to be performed to avoid
888 * an incoherent CS (such as can be found on 830/845). If this flag is
889 * not passed, the kernel will endeavour to make sure the batch is
890 * coherent with the CS before execution. If this flag is passed,
891 * userspace assumes the responsibility for ensuring the same.
892 */
893#define I915_EXEC_IS_PINNED (1<<10)
894
895/** Provide a hint to the kernel that the command stream and auxiliary
896 * state buffers already holds the correct presumed addresses and so the
897 * relocation process may be skipped if no buffers need to be moved in
898 * preparation for the execbuffer.
899 */
900#define I915_EXEC_NO_RELOC (1<<11)
901
902/** Use the reloc.handle as an index into the exec object array rather
903 * than as the per-file handle.
904 */
905#define I915_EXEC_HANDLE_LUT (1<<12)
906
907/** Used for switching BSD rings on the platforms with two BSD rings */
908#define I915_EXEC_BSD_SHIFT (13)
909#define I915_EXEC_BSD_MASK (3 << I915_EXEC_BSD_SHIFT)
910/* default ping-pong mode */
911#define I915_EXEC_BSD_DEFAULT (0 << I915_EXEC_BSD_SHIFT)
912#define I915_EXEC_BSD_RING1 (1 << I915_EXEC_BSD_SHIFT)
913#define I915_EXEC_BSD_RING2 (2 << I915_EXEC_BSD_SHIFT)
914
915/** Tell the kernel that the batchbuffer is processed by
916 * the resource streamer.
917 */
918#define I915_EXEC_RESOURCE_STREAMER (1<<15)
919
920/* Setting I915_EXEC_FENCE_IN implies that lower_32_bits(rsvd2) represent
921 * a sync_file fd to wait upon (in a nonblocking manner) prior to executing
922 * the batch.
923 *
924 * Returns -EINVAL if the sync_file fd cannot be found.
925 */
926#define I915_EXEC_FENCE_IN (1<<16)
927
928/* Setting I915_EXEC_FENCE_OUT causes the ioctl to return a sync_file fd
929 * in the upper_32_bits(rsvd2) upon success. Ownership of the fd is given
930 * to the caller, and it should be close() after use. (The fd is a regular
931 * file descriptor and will be cleaned up on process termination. It holds
932 * a reference to the request, but nothing else.)
933 *
934 * The sync_file fd can be combined with other sync_file and passed either
935 * to execbuf using I915_EXEC_FENCE_IN, to atomic KMS ioctls (so that a flip
936 * will only occur after this request completes), or to other devices.
937 *
938 * Using I915_EXEC_FENCE_OUT requires use of
939 * DRM_IOCTL_I915_GEM_EXECBUFFER2_WR ioctl so that the result is written
940 * back to userspace. Failure to do so will cause the out-fence to always
941 * be reported as zero, and the real fence fd to be leaked.
942 */
943#define I915_EXEC_FENCE_OUT (1<<17)
944
945/*
946 * Traditionally the execbuf ioctl has only considered the final element in
947 * the execobject[] to be the executable batch. Often though, the client
948 * will known the batch object prior to construction and being able to place
949 * it into the execobject[] array first can simplify the relocation tracking.
950 * Setting I915_EXEC_BATCH_FIRST tells execbuf to use element 0 of the
951 * execobject[] as the * batch instead (the default is to use the last
952 * element).
953 */
954#define I915_EXEC_BATCH_FIRST (1<<18)
955
956/* Setting I915_FENCE_ARRAY implies that num_cliprects and cliprects_ptr
957 * define an array of i915_gem_exec_fence structures which specify a set of
958 * dma fences to wait upon or signal.
959 */
960#define I915_EXEC_FENCE_ARRAY (1<<19)
961
962#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1))
963
964#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
965#define i915_execbuffer2_set_context_id(eb2, context) \
966 (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK
967#define i915_execbuffer2_get_context_id(eb2) \
968 ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK)
969
970struct drm_i915_gem_pin {
971 /** Handle of the buffer to be pinned. */
972 __u32 handle;
973 __u32 pad;
974
975 /** alignment required within the aperture */
976 __u64 alignment;
977
978 /** Returned GTT offset of the buffer. */
979 __u64 offset;
980};
981
982struct drm_i915_gem_unpin {
983 /** Handle of the buffer to be unpinned. */
984 __u32 handle;
985 __u32 pad;
986};
987
988struct drm_i915_gem_busy {
989 /** Handle of the buffer to check for busy */
990 __u32 handle;
991
992 /** Return busy status
993 *
994 * A return of 0 implies that the object is idle (after
995 * having flushed any pending activity), and a non-zero return that
996 * the object is still in-flight on the GPU. (The GPU has not yet
997 * signaled completion for all pending requests that reference the
998 * object.) An object is guaranteed to become idle eventually (so
999 * long as no new GPU commands are executed upon it). Due to the
1000 * asynchronous nature of the hardware, an object reported
1001 * as busy may become idle before the ioctl is completed.
1002 *
1003 * Furthermore, if the object is busy, which engine is busy is only
1004 * provided as a guide. There are race conditions which prevent the
1005 * report of which engines are busy from being always accurate.
1006 * However, the converse is not true. If the object is idle, the
1007 * result of the ioctl, that all engines are idle, is accurate.
1008 *
1009 * The returned dword is split into two fields to indicate both
1010 * the engines on which the object is being read, and the
1011 * engine on which it is currently being written (if any).
1012 *
1013 * The low word (bits 0:15) indicate if the object is being written
1014 * to by any engine (there can only be one, as the GEM implicit
1015 * synchronisation rules force writes to be serialised). Only the
1016 * engine for the last write is reported.
1017 *
1018 * The high word (bits 16:31) are a bitmask of which engines are
1019 * currently reading from the object. Multiple engines may be
1020 * reading from the object simultaneously.
1021 *
1022 * The value of each engine is the same as specified in the
1023 * EXECBUFFER2 ioctl, i.e. I915_EXEC_RENDER, I915_EXEC_BSD etc.
1024 * Note I915_EXEC_DEFAULT is a symbolic value and is mapped to
1025 * the I915_EXEC_RENDER engine for execution, and so it is never
1026 * reported as active itself. Some hardware may have parallel
1027 * execution engines, e.g. multiple media engines, which are
1028 * mapped to the same identifier in the EXECBUFFER2 ioctl and
1029 * so are not separately reported for busyness.
1030 *
1031 * Caveat emptor:
1032 * Only the boolean result of this query is reliable; that is whether
1033 * the object is idle or busy. The report of which engines are busy
1034 * should be only used as a heuristic.
1035 */
1036 __u32 busy;
1037};
1038
1039/**
1040 * I915_CACHING_NONE
1041 *
1042 * GPU access is not coherent with cpu caches. Default for machines without an
1043 * LLC.
1044 */
1045#define I915_CACHING_NONE 0
1046/**
1047 * I915_CACHING_CACHED
1048 *
1049 * GPU access is coherent with cpu caches and furthermore the data is cached in
1050 * last-level caches shared between cpu cores and the gpu GT. Default on
1051 * machines with HAS_LLC.
1052 */
1053#define I915_CACHING_CACHED 1
1054/**
1055 * I915_CACHING_DISPLAY
1056 *
1057 * Special GPU caching mode which is coherent with the scanout engines.
1058 * Transparently falls back to I915_CACHING_NONE on platforms where no special
1059 * cache mode (like write-through or gfdt flushing) is available. The kernel
1060 * automatically sets this mode when using a buffer as a scanout target.
1061 * Userspace can manually set this mode to avoid a costly stall and clflush in
1062 * the hotpath of drawing the first frame.
1063 */
1064#define I915_CACHING_DISPLAY 2
1065
1066struct drm_i915_gem_caching {
1067 /**
1068 * Handle of the buffer to set/get the caching level of. */
1069 __u32 handle;
1070
1071 /**
1072 * Cacheing level to apply or return value
1073 *
1074 * bits0-15 are for generic caching control (i.e. the above defined
1075 * values). bits16-31 are reserved for platform-specific variations
1076 * (e.g. l3$ caching on gen7). */
1077 __u32 caching;
1078};
1079
1080#define I915_TILING_NONE 0
1081#define I915_TILING_X 1
1082#define I915_TILING_Y 2
1083#define I915_TILING_LAST I915_TILING_Y
1084
1085#define I915_BIT_6_SWIZZLE_NONE 0
1086#define I915_BIT_6_SWIZZLE_9 1
1087#define I915_BIT_6_SWIZZLE_9_10 2
1088#define I915_BIT_6_SWIZZLE_9_11 3
1089#define I915_BIT_6_SWIZZLE_9_10_11 4
1090/* Not seen by userland */
1091#define I915_BIT_6_SWIZZLE_UNKNOWN 5
1092/* Seen by userland. */
1093#define I915_BIT_6_SWIZZLE_9_17 6
1094#define I915_BIT_6_SWIZZLE_9_10_17 7
1095
1096struct drm_i915_gem_set_tiling {
1097 /** Handle of the buffer to have its tiling state updated */
1098 __u32 handle;
1099
1100 /**
1101 * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
1102 * I915_TILING_Y).
1103 *
1104 * This value is to be set on request, and will be updated by the
1105 * kernel on successful return with the actual chosen tiling layout.
1106 *
1107 * The tiling mode may be demoted to I915_TILING_NONE when the system
1108 * has bit 6 swizzling that can't be managed correctly by GEM.
1109 *
1110 * Buffer contents become undefined when changing tiling_mode.
1111 */
1112 __u32 tiling_mode;
1113
1114 /**
1115 * Stride in bytes for the object when in I915_TILING_X or
1116 * I915_TILING_Y.
1117 */
1118 __u32 stride;
1119
1120 /**
1121 * Returned address bit 6 swizzling required for CPU access through
1122 * mmap mapping.
1123 */
1124 __u32 swizzle_mode;
1125};
1126
1127struct drm_i915_gem_get_tiling {
1128 /** Handle of the buffer to get tiling state for. */
1129 __u32 handle;
1130
1131 /**
1132 * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
1133 * I915_TILING_Y).
1134 */
1135 __u32 tiling_mode;
1136
1137 /**
1138 * Returned address bit 6 swizzling required for CPU access through
1139 * mmap mapping.
1140 */
1141 __u32 swizzle_mode;
1142
1143 /**
1144 * Returned address bit 6 swizzling required for CPU access through
1145 * mmap mapping whilst bound.
1146 */
1147 __u32 phys_swizzle_mode;
1148};
1149
1150struct drm_i915_gem_get_aperture {
1151 /** Total size of the aperture used by i915_gem_execbuffer, in bytes */
1152 __u64 aper_size;
1153
1154 /**
1155 * Available space in the aperture used by i915_gem_execbuffer, in
1156 * bytes
1157 */
1158 __u64 aper_available_size;
1159};
1160
1161struct drm_i915_get_pipe_from_crtc_id {
1162 /** ID of CRTC being requested **/
1163 __u32 crtc_id;
1164
1165 /** pipe of requested CRTC **/
1166 __u32 pipe;
1167};
1168
1169#define I915_MADV_WILLNEED 0
1170#define I915_MADV_DONTNEED 1
1171#define __I915_MADV_PURGED 2 /* internal state */
1172
1173struct drm_i915_gem_madvise {
1174 /** Handle of the buffer to change the backing store advice */
1175 __u32 handle;
1176
1177 /* Advice: either the buffer will be needed again in the near future,
1178 * or wont be and could be discarded under memory pressure.
1179 */
1180 __u32 madv;
1181
1182 /** Whether the backing store still exists. */
1183 __u32 retained;
1184};
1185
1186/* flags */
1187#define I915_OVERLAY_TYPE_MASK 0xff
1188#define I915_OVERLAY_YUV_PLANAR 0x01
1189#define I915_OVERLAY_YUV_PACKED 0x02
1190#define I915_OVERLAY_RGB 0x03
1191
1192#define I915_OVERLAY_DEPTH_MASK 0xff00
1193#define I915_OVERLAY_RGB24 0x1000
1194#define I915_OVERLAY_RGB16 0x2000
1195#define I915_OVERLAY_RGB15 0x3000
1196#define I915_OVERLAY_YUV422 0x0100
1197#define I915_OVERLAY_YUV411 0x0200
1198#define I915_OVERLAY_YUV420 0x0300
1199#define I915_OVERLAY_YUV410 0x0400
1200
1201#define I915_OVERLAY_SWAP_MASK 0xff0000
1202#define I915_OVERLAY_NO_SWAP 0x000000
1203#define I915_OVERLAY_UV_SWAP 0x010000
1204#define I915_OVERLAY_Y_SWAP 0x020000
1205#define I915_OVERLAY_Y_AND_UV_SWAP 0x030000
1206
1207#define I915_OVERLAY_FLAGS_MASK 0xff000000
1208#define I915_OVERLAY_ENABLE 0x01000000
1209
1210struct drm_intel_overlay_put_image {
1211 /* various flags and src format description */
1212 __u32 flags;
1213 /* source picture description */
1214 __u32 bo_handle;
1215 /* stride values and offsets are in bytes, buffer relative */
1216 __u16 stride_Y; /* stride for packed formats */
1217 __u16 stride_UV;
1218 __u32 offset_Y; /* offset for packet formats */
1219 __u32 offset_U;
1220 __u32 offset_V;
1221 /* in pixels */
1222 __u16 src_width;
1223 __u16 src_height;
1224 /* to compensate the scaling factors for partially covered surfaces */
1225 __u16 src_scan_width;
1226 __u16 src_scan_height;
1227 /* output crtc description */
1228 __u32 crtc_id;
1229 __u16 dst_x;
1230 __u16 dst_y;
1231 __u16 dst_width;
1232 __u16 dst_height;
1233};
1234
1235/* flags */
1236#define I915_OVERLAY_UPDATE_ATTRS (1<<0)
1237#define I915_OVERLAY_UPDATE_GAMMA (1<<1)
1238#define I915_OVERLAY_DISABLE_DEST_COLORKEY (1<<2)
1239struct drm_intel_overlay_attrs {
1240 __u32 flags;
1241 __u32 color_key;
1242 __s32 brightness;
1243 __u32 contrast;
1244 __u32 saturation;
1245 __u32 gamma0;
1246 __u32 gamma1;
1247 __u32 gamma2;
1248 __u32 gamma3;
1249 __u32 gamma4;
1250 __u32 gamma5;
1251};
1252
1253/*
1254 * Intel sprite handling
1255 *
1256 * Color keying works with a min/mask/max tuple. Both source and destination
1257 * color keying is allowed.
1258 *
1259 * Source keying:
1260 * Sprite pixels within the min & max values, masked against the color channels
1261 * specified in the mask field, will be transparent. All other pixels will
1262 * be displayed on top of the primary plane. For RGB surfaces, only the min
1263 * and mask fields will be used; ranged compares are not allowed.
1264 *
1265 * Destination keying:
1266 * Primary plane pixels that match the min value, masked against the color
1267 * channels specified in the mask field, will be replaced by corresponding
1268 * pixels from the sprite plane.
1269 *
1270 * Note that source & destination keying are exclusive; only one can be
1271 * active on a given plane.
1272 */
1273
1274#define I915_SET_COLORKEY_NONE (1<<0) /* disable color key matching */
1275#define I915_SET_COLORKEY_DESTINATION (1<<1)
1276#define I915_SET_COLORKEY_SOURCE (1<<2)
1277struct drm_intel_sprite_colorkey {
1278 __u32 plane_id;
1279 __u32 min_value;
1280 __u32 channel_mask;
1281 __u32 max_value;
1282 __u32 flags;
1283};
1284
1285struct drm_i915_gem_wait {
1286 /** Handle of BO we shall wait on */
1287 __u32 bo_handle;
1288 __u32 flags;
1289 /** Number of nanoseconds to wait, Returns time remaining. */
1290 __s64 timeout_ns;
1291};
1292
1293struct drm_i915_gem_context_create {
1294 /* output: id of new context*/
1295 __u32 ctx_id;
1296 __u32 pad;
1297};
1298
1299struct drm_i915_gem_context_destroy {
1300 __u32 ctx_id;
1301 __u32 pad;
1302};
1303
1304struct drm_i915_reg_read {
1305 /*
1306 * Register offset.
1307 * For 64bit wide registers where the upper 32bits don't immediately
1308 * follow the lower 32bits, the offset of the lower 32bits must
1309 * be specified
1310 */
1311 __u64 offset;
1312 __u64 val; /* Return value */
1313};
1314/* Known registers:
1315 *
1316 * Render engine timestamp - 0x2358 + 64bit - gen7+
1317 * - Note this register returns an invalid value if using the default
1318 * single instruction 8byte read, in order to workaround that use
1319 * offset (0x2538 | 1) instead.
1320 *
1321 */
1322
1323struct drm_i915_reset_stats {
1324 __u32 ctx_id;
1325 __u32 flags;
1326
1327 /* All resets since boot/module reload, for all contexts */
1328 __u32 reset_count;
1329
1330 /* Number of batches lost when active in GPU, for this context */
1331 __u32 batch_active;
1332
1333 /* Number of batches lost pending for execution, for this context */
1334 __u32 batch_pending;
1335
1336 __u32 pad;
1337};
1338
1339struct drm_i915_gem_userptr {
1340 __u64 user_ptr;
1341 __u64 user_size;
1342 __u32 flags;
1343#define I915_USERPTR_READ_ONLY 0x1
1344#define I915_USERPTR_UNSYNCHRONIZED 0x80000000
1345 /**
1346 * Returned handle for the object.
1347 *
1348 * Object handles are nonzero.
1349 */
1350 __u32 handle;
1351};
1352
1353struct drm_i915_gem_context_param {
1354 __u32 ctx_id;
1355 __u32 size;
1356 __u64 param;
1357#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1
1358#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2
1359#define I915_CONTEXT_PARAM_GTT_SIZE 0x3
1360#define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE 0x4
1361#define I915_CONTEXT_PARAM_BANNABLE 0x5
1362 __u64 value;
1363};
1364
1365enum drm_i915_oa_format {
1366 I915_OA_FORMAT_A13 = 1, /* HSW only */
1367 I915_OA_FORMAT_A29, /* HSW only */
1368 I915_OA_FORMAT_A13_B8_C8, /* HSW only */
1369 I915_OA_FORMAT_B4_C8, /* HSW only */
1370 I915_OA_FORMAT_A45_B8_C8, /* HSW only */
1371 I915_OA_FORMAT_B4_C8_A16, /* HSW only */
1372 I915_OA_FORMAT_C4_B8, /* HSW+ */
1373
1374 /* Gen8+ */
1375 I915_OA_FORMAT_A12,
1376 I915_OA_FORMAT_A12_B8_C8,
1377 I915_OA_FORMAT_A32u40_A4u32_B8_C8,
1378
1379 I915_OA_FORMAT_MAX /* non-ABI */
1380};
1381
1382enum drm_i915_perf_property_id {
1383 /**
1384 * Open the stream for a specific context handle (as used with
1385 * execbuffer2). A stream opened for a specific context this way
1386 * won't typically require root privileges.
1387 */
1388 DRM_I915_PERF_PROP_CTX_HANDLE = 1,
1389
1390 /**
1391 * A value of 1 requests the inclusion of raw OA unit reports as
1392 * part of stream samples.
1393 */
1394 DRM_I915_PERF_PROP_SAMPLE_OA,
1395
1396 /**
1397 * The value specifies which set of OA unit metrics should be
1398 * be configured, defining the contents of any OA unit reports.
1399 */
1400 DRM_I915_PERF_PROP_OA_METRICS_SET,
1401
1402 /**
1403 * The value specifies the size and layout of OA unit reports.
1404 */
1405 DRM_I915_PERF_PROP_OA_FORMAT,
1406
1407 /**
1408 * Specifying this property implicitly requests periodic OA unit
1409 * sampling and (at least on Haswell) the sampling frequency is derived
1410 * from this exponent as follows:
1411 *
1412 * 80ns * 2^(period_exponent + 1)
1413 */
1414 DRM_I915_PERF_PROP_OA_EXPONENT,
1415
1416 DRM_I915_PERF_PROP_MAX /* non-ABI */
1417};
1418
1419struct drm_i915_perf_open_param {
1420 __u32 flags;
1421#define I915_PERF_FLAG_FD_CLOEXEC (1<<0)
1422#define I915_PERF_FLAG_FD_NONBLOCK (1<<1)
1423#define I915_PERF_FLAG_DISABLED (1<<2)
1424
1425 /** The number of u64 (id, value) pairs */
1426 __u32 num_properties;
1427
1428 /**
1429 * Pointer to array of u64 (id, value) pairs configuring the stream
1430 * to open.
1431 */
1432 __u64 properties_ptr;
1433};
1434
1435/**
1436 * Enable data capture for a stream that was either opened in a disabled state
1437 * via I915_PERF_FLAG_DISABLED or was later disabled via
1438 * I915_PERF_IOCTL_DISABLE.
1439 *
1440 * It is intended to be cheaper to disable and enable a stream than it may be
1441 * to close and re-open a stream with the same configuration.
1442 *
1443 * It's undefined whether any pending data for the stream will be lost.
1444 */
1445#define I915_PERF_IOCTL_ENABLE _IO('i', 0x0)
1446
1447/**
1448 * Disable data capture for a stream.
1449 *
1450 * It is an error to try and read a stream that is disabled.
1451 */
1452#define I915_PERF_IOCTL_DISABLE _IO('i', 0x1)
1453
1454/**
1455 * Common to all i915 perf records
1456 */
1457struct drm_i915_perf_record_header {
1458 __u32 type;
1459 __u16 pad;
1460 __u16 size;
1461};
1462
1463enum drm_i915_perf_record_type {
1464
1465 /**
1466 * Samples are the work horse record type whose contents are extensible
1467 * and defined when opening an i915 perf stream based on the given
1468 * properties.
1469 *
1470 * Boolean properties following the naming convention
1471 * DRM_I915_PERF_SAMPLE_xyz_PROP request the inclusion of 'xyz' data in
1472 * every sample.
1473 *
1474 * The order of these sample properties given by userspace has no
1475 * affect on the ordering of data within a sample. The order is
1476 * documented here.
1477 *
1478 * struct {
1479 * struct drm_i915_perf_record_header header;
1480 *
1481 * { u32 oa_report[]; } && DRM_I915_PERF_PROP_SAMPLE_OA
1482 * };
1483 */
1484 DRM_I915_PERF_RECORD_SAMPLE = 1,
1485
1486 /*
1487 * Indicates that one or more OA reports were not written by the
1488 * hardware. This can happen for example if an MI_REPORT_PERF_COUNT
1489 * command collides with periodic sampling - which would be more likely
1490 * at higher sampling frequencies.
1491 */
1492 DRM_I915_PERF_RECORD_OA_REPORT_LOST = 2,
1493
1494 /**
1495 * An error occurred that resulted in all pending OA reports being lost.
1496 */
1497 DRM_I915_PERF_RECORD_OA_BUFFER_LOST = 3,
1498
1499 DRM_I915_PERF_RECORD_MAX /* non-ABI */
1500};
1501
1502/**
1503 * Structure to upload perf dynamic configuration into the kernel.
1504 */
1505struct drm_i915_perf_oa_config {
1506 /** String formatted like "%08x-%04x-%04x-%04x-%012x" */
1507 char uuid[36];
1508
1509 __u32 n_mux_regs;
1510 __u32 n_boolean_regs;
1511 __u32 n_flex_regs;
1512
1513 __u64 __user mux_regs_ptr;
1514 __u64 __user boolean_regs_ptr;
1515 __u64 __user flex_regs_ptr;
1516};
1517
1518#if defined(__cplusplus)
1519}
1520#endif
1521
1522#endif /* _UAPI_I915_DRM_H_ */
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index ce2988be4f0e..4c223ab30293 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com 2/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com
2 * 3 *
3 * This program is free software; you can redistribute it and/or 4 * This program is free software; you can redistribute it and/or
@@ -30,9 +31,14 @@
30#define BPF_FROM_LE BPF_TO_LE 31#define BPF_FROM_LE BPF_TO_LE
31#define BPF_FROM_BE BPF_TO_BE 32#define BPF_FROM_BE BPF_TO_BE
32 33
34/* jmp encodings */
33#define BPF_JNE 0x50 /* jump != */ 35#define BPF_JNE 0x50 /* jump != */
36#define BPF_JLT 0xa0 /* LT is unsigned, '<' */
37#define BPF_JLE 0xb0 /* LE is unsigned, '<=' */
34#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */ 38#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */
35#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */ 39#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */
40#define BPF_JSLT 0xc0 /* SLT is signed, '<' */
41#define BPF_JSLE 0xd0 /* SLE is signed, '<=' */
36#define BPF_CALL 0x80 /* function call */ 42#define BPF_CALL 0x80 /* function call */
37#define BPF_EXIT 0x90 /* function return */ 43#define BPF_EXIT 0x90 /* function return */
38 44
@@ -87,6 +93,7 @@ enum bpf_cmd {
87 BPF_PROG_GET_FD_BY_ID, 93 BPF_PROG_GET_FD_BY_ID,
88 BPF_MAP_GET_FD_BY_ID, 94 BPF_MAP_GET_FD_BY_ID,
89 BPF_OBJ_GET_INFO_BY_FD, 95 BPF_OBJ_GET_INFO_BY_FD,
96 BPF_PROG_QUERY,
90}; 97};
91 98
92enum bpf_map_type { 99enum bpf_map_type {
@@ -104,6 +111,9 @@ enum bpf_map_type {
104 BPF_MAP_TYPE_LPM_TRIE, 111 BPF_MAP_TYPE_LPM_TRIE,
105 BPF_MAP_TYPE_ARRAY_OF_MAPS, 112 BPF_MAP_TYPE_ARRAY_OF_MAPS,
106 BPF_MAP_TYPE_HASH_OF_MAPS, 113 BPF_MAP_TYPE_HASH_OF_MAPS,
114 BPF_MAP_TYPE_DEVMAP,
115 BPF_MAP_TYPE_SOCKMAP,
116 BPF_MAP_TYPE_CPUMAP,
107}; 117};
108 118
109enum bpf_prog_type { 119enum bpf_prog_type {
@@ -121,6 +131,8 @@ enum bpf_prog_type {
121 BPF_PROG_TYPE_LWT_OUT, 131 BPF_PROG_TYPE_LWT_OUT,
122 BPF_PROG_TYPE_LWT_XMIT, 132 BPF_PROG_TYPE_LWT_XMIT,
123 BPF_PROG_TYPE_SOCK_OPS, 133 BPF_PROG_TYPE_SOCK_OPS,
134 BPF_PROG_TYPE_SK_SKB,
135 BPF_PROG_TYPE_CGROUP_DEVICE,
124}; 136};
125 137
126enum bpf_attach_type { 138enum bpf_attach_type {
@@ -128,16 +140,55 @@ enum bpf_attach_type {
128 BPF_CGROUP_INET_EGRESS, 140 BPF_CGROUP_INET_EGRESS,
129 BPF_CGROUP_INET_SOCK_CREATE, 141 BPF_CGROUP_INET_SOCK_CREATE,
130 BPF_CGROUP_SOCK_OPS, 142 BPF_CGROUP_SOCK_OPS,
143 BPF_SK_SKB_STREAM_PARSER,
144 BPF_SK_SKB_STREAM_VERDICT,
145 BPF_CGROUP_DEVICE,
131 __MAX_BPF_ATTACH_TYPE 146 __MAX_BPF_ATTACH_TYPE
132}; 147};
133 148
134#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE 149#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
135 150
136/* If BPF_F_ALLOW_OVERRIDE flag is used in BPF_PROG_ATTACH command 151/* cgroup-bpf attach flags used in BPF_PROG_ATTACH command
137 * to the given target_fd cgroup the descendent cgroup will be able to 152 *
138 * override effective bpf program that was inherited from this cgroup 153 * NONE(default): No further bpf programs allowed in the subtree.
154 *
155 * BPF_F_ALLOW_OVERRIDE: If a sub-cgroup installs some bpf program,
156 * the program in this cgroup yields to sub-cgroup program.
157 *
158 * BPF_F_ALLOW_MULTI: If a sub-cgroup installs some bpf program,
159 * that cgroup program gets run in addition to the program in this cgroup.
160 *
161 * Only one program is allowed to be attached to a cgroup with
162 * NONE or BPF_F_ALLOW_OVERRIDE flag.
163 * Attaching another program on top of NONE or BPF_F_ALLOW_OVERRIDE will
164 * release old program and attach the new one. Attach flags has to match.
165 *
166 * Multiple programs are allowed to be attached to a cgroup with
167 * BPF_F_ALLOW_MULTI flag. They are executed in FIFO order
168 * (those that were attached first, run first)
169 * The programs of sub-cgroup are executed first, then programs of
170 * this cgroup and then programs of parent cgroup.
171 * When children program makes decision (like picking TCP CA or sock bind)
172 * parent program has a chance to override it.
173 *
174 * A cgroup with MULTI or OVERRIDE flag allows any attach flags in sub-cgroups.
175 * A cgroup with NONE doesn't allow any programs in sub-cgroups.
176 * Ex1:
177 * cgrp1 (MULTI progs A, B) ->
178 * cgrp2 (OVERRIDE prog C) ->
179 * cgrp3 (MULTI prog D) ->
180 * cgrp4 (OVERRIDE prog E) ->
181 * cgrp5 (NONE prog F)
182 * the event in cgrp5 triggers execution of F,D,A,B in that order.
183 * if prog F is detached, the execution is E,D,A,B
184 * if prog F and D are detached, the execution is E,A,B
185 * if prog F, E and D are detached, the execution is C,A,B
186 *
187 * All eligible programs are executed regardless of return code from
188 * earlier programs.
139 */ 189 */
140#define BPF_F_ALLOW_OVERRIDE (1U << 0) 190#define BPF_F_ALLOW_OVERRIDE (1U << 0)
191#define BPF_F_ALLOW_MULTI (1U << 1)
141 192
142/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the 193/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
143 * verifier will perform strict alignment checking as if the kernel 194 * verifier will perform strict alignment checking as if the kernel
@@ -153,6 +204,7 @@ enum bpf_attach_type {
153#define BPF_NOEXIST 1 /* create new element if it didn't exist */ 204#define BPF_NOEXIST 1 /* create new element if it didn't exist */
154#define BPF_EXIST 2 /* update existing element */ 205#define BPF_EXIST 2 /* update existing element */
155 206
207/* flags for BPF_MAP_CREATE command */
156#define BPF_F_NO_PREALLOC (1U << 0) 208#define BPF_F_NO_PREALLOC (1U << 0)
157/* Instead of having one common LRU list in the 209/* Instead of having one common LRU list in the
158 * BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list 210 * BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list
@@ -161,6 +213,17 @@ enum bpf_attach_type {
161 * across different LRU lists. 213 * across different LRU lists.
162 */ 214 */
163#define BPF_F_NO_COMMON_LRU (1U << 1) 215#define BPF_F_NO_COMMON_LRU (1U << 1)
216/* Specify numa node during map creation */
217#define BPF_F_NUMA_NODE (1U << 2)
218
219/* flags for BPF_PROG_QUERY */
220#define BPF_F_QUERY_EFFECTIVE (1U << 0)
221
222#define BPF_OBJ_NAME_LEN 16U
223
224/* Flags for accessing BPF object */
225#define BPF_F_RDONLY (1U << 3)
226#define BPF_F_WRONLY (1U << 4)
164 227
165union bpf_attr { 228union bpf_attr {
166 struct { /* anonymous struct used by BPF_MAP_CREATE command */ 229 struct { /* anonymous struct used by BPF_MAP_CREATE command */
@@ -168,8 +231,14 @@ union bpf_attr {
168 __u32 key_size; /* size of key in bytes */ 231 __u32 key_size; /* size of key in bytes */
169 __u32 value_size; /* size of value in bytes */ 232 __u32 value_size; /* size of value in bytes */
170 __u32 max_entries; /* max number of entries in a map */ 233 __u32 max_entries; /* max number of entries in a map */
171 __u32 map_flags; /* prealloc or not */ 234 __u32 map_flags; /* BPF_MAP_CREATE related
235 * flags defined above.
236 */
172 __u32 inner_map_fd; /* fd pointing to the inner map */ 237 __u32 inner_map_fd; /* fd pointing to the inner map */
238 __u32 numa_node; /* numa node (effective only if
239 * BPF_F_NUMA_NODE is set).
240 */
241 char map_name[BPF_OBJ_NAME_LEN];
173 }; 242 };
174 243
175 struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */ 244 struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */
@@ -192,11 +261,14 @@ union bpf_attr {
192 __aligned_u64 log_buf; /* user supplied buffer */ 261 __aligned_u64 log_buf; /* user supplied buffer */
193 __u32 kern_version; /* checked when prog_type=kprobe */ 262 __u32 kern_version; /* checked when prog_type=kprobe */
194 __u32 prog_flags; 263 __u32 prog_flags;
264 char prog_name[BPF_OBJ_NAME_LEN];
265 __u32 prog_ifindex; /* ifindex of netdev to prep for */
195 }; 266 };
196 267
197 struct { /* anonymous struct used by BPF_OBJ_* commands */ 268 struct { /* anonymous struct used by BPF_OBJ_* commands */
198 __aligned_u64 pathname; 269 __aligned_u64 pathname;
199 __u32 bpf_fd; 270 __u32 bpf_fd;
271 __u32 file_flags;
200 }; 272 };
201 273
202 struct { /* anonymous struct used by BPF_PROG_ATTACH/DETACH commands */ 274 struct { /* anonymous struct used by BPF_PROG_ATTACH/DETACH commands */
@@ -224,6 +296,7 @@ union bpf_attr {
224 __u32 map_id; 296 __u32 map_id;
225 }; 297 };
226 __u32 next_id; 298 __u32 next_id;
299 __u32 open_flags;
227 }; 300 };
228 301
229 struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */ 302 struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */
@@ -231,6 +304,15 @@ union bpf_attr {
231 __u32 info_len; 304 __u32 info_len;
232 __aligned_u64 info; 305 __aligned_u64 info;
233 } info; 306 } info;
307
308 struct { /* anonymous struct used by BPF_PROG_QUERY command */
309 __u32 target_fd; /* container object to query */
310 __u32 attach_type;
311 __u32 query_flags;
312 __u32 attach_flags;
313 __aligned_u64 prog_ids;
314 __u32 prog_cnt;
315 } query;
234} __attribute__((aligned(8))); 316} __attribute__((aligned(8)));
235 317
236/* BPF helper function descriptions: 318/* BPF helper function descriptions:
@@ -294,7 +376,7 @@ union bpf_attr {
294 * jump into another BPF program 376 * jump into another BPF program
295 * @ctx: context pointer passed to next program 377 * @ctx: context pointer passed to next program
296 * @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY 378 * @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY
297 * @index: index inside array that selects specific program to run 379 * @index: 32-bit index inside array that selects specific program to run
298 * Return: 0 on success or negative error 380 * Return: 0 on success or negative error
299 * 381 *
300 * int bpf_clone_redirect(skb, ifindex, flags) 382 * int bpf_clone_redirect(skb, ifindex, flags)
@@ -344,9 +426,20 @@ union bpf_attr {
344 * int bpf_redirect(ifindex, flags) 426 * int bpf_redirect(ifindex, flags)
345 * redirect to another netdev 427 * redirect to another netdev
346 * @ifindex: ifindex of the net device 428 * @ifindex: ifindex of the net device
347 * @flags: bit 0 - if set, redirect to ingress instead of egress 429 * @flags:
348 * other bits - reserved 430 * cls_bpf:
349 * Return: TC_ACT_REDIRECT 431 * bit 0 - if set, redirect to ingress instead of egress
432 * other bits - reserved
433 * xdp_bpf:
434 * all bits - reserved
435 * Return: cls_bpf: TC_ACT_REDIRECT on success or TC_ACT_SHOT on error
436 * xdp_bfp: XDP_REDIRECT on success or XDP_ABORT on error
437 * int bpf_redirect_map(map, key, flags)
438 * redirect to endpoint in map
439 * @map: pointer to dev map
440 * @key: index in map to lookup
441 * @flags: --
442 * Return: XDP_REDIRECT on success or XDP_ABORT on error
350 * 443 *
351 * u32 bpf_get_route_realm(skb) 444 * u32 bpf_get_route_realm(skb)
352 * retrieve a dst's tclassid 445 * retrieve a dst's tclassid
@@ -524,12 +617,22 @@ union bpf_attr {
524 * int bpf_setsockopt(bpf_socket, level, optname, optval, optlen) 617 * int bpf_setsockopt(bpf_socket, level, optname, optval, optlen)
525 * Calls setsockopt. Not all opts are available, only those with 618 * Calls setsockopt. Not all opts are available, only those with
526 * integer optvals plus TCP_CONGESTION. 619 * integer optvals plus TCP_CONGESTION.
527 * Supported levels: SOL_SOCKET and IPROTO_TCP 620 * Supported levels: SOL_SOCKET and IPPROTO_TCP
528 * @bpf_socket: pointer to bpf_socket 621 * @bpf_socket: pointer to bpf_socket
529 * @level: SOL_SOCKET or IPROTO_TCP 622 * @level: SOL_SOCKET or IPPROTO_TCP
530 * @optname: option name 623 * @optname: option name
531 * @optval: pointer to option value 624 * @optval: pointer to option value
532 * @optlen: length of optval in byes 625 * @optlen: length of optval in bytes
626 * Return: 0 or negative error
627 *
628 * int bpf_getsockopt(bpf_socket, level, optname, optval, optlen)
629 * Calls getsockopt. Not all opts are available.
630 * Supported levels: IPPROTO_TCP
631 * @bpf_socket: pointer to bpf_socket
632 * @level: IPPROTO_TCP
633 * @optname: option name
634 * @optval: pointer to option value
635 * @optlen: length of optval in bytes
533 * Return: 0 or negative error 636 * Return: 0 or negative error
534 * 637 *
535 * int bpf_skb_adjust_room(skb, len_diff, mode, flags) 638 * int bpf_skb_adjust_room(skb, len_diff, mode, flags)
@@ -539,6 +642,41 @@ union bpf_attr {
539 * @mode: operation mode (enum bpf_adj_room_mode) 642 * @mode: operation mode (enum bpf_adj_room_mode)
540 * @flags: reserved for future use 643 * @flags: reserved for future use
541 * Return: 0 on success or negative error code 644 * Return: 0 on success or negative error code
645 *
646 * int bpf_sk_redirect_map(map, key, flags)
647 * Redirect skb to a sock in map using key as a lookup key for the
648 * sock in map.
649 * @map: pointer to sockmap
650 * @key: key to lookup sock in map
651 * @flags: reserved for future use
652 * Return: SK_PASS
653 *
654 * int bpf_sock_map_update(skops, map, key, flags)
655 * @skops: pointer to bpf_sock_ops
656 * @map: pointer to sockmap to update
657 * @key: key to insert/update sock in map
658 * @flags: same flags as map update elem
659 *
660 * int bpf_xdp_adjust_meta(xdp_md, delta)
661 * Adjust the xdp_md.data_meta by delta
662 * @xdp_md: pointer to xdp_md
663 * @delta: An positive/negative integer to be added to xdp_md.data_meta
664 * Return: 0 on success or negative on error
665 *
666 * int bpf_perf_event_read_value(map, flags, buf, buf_size)
667 * read perf event counter value and perf event enabled/running time
668 * @map: pointer to perf_event_array map
669 * @flags: index of event in the map or bitmask flags
670 * @buf: buf to fill
671 * @buf_size: size of the buf
672 * Return: 0 on success or negative error code
673 *
674 * int bpf_perf_prog_read_value(ctx, buf, buf_size)
675 * read perf prog attached perf event counter and enabled/running time
676 * @ctx: pointer to ctx
677 * @buf: buf to fill
678 * @buf_size: size of the buf
679 * Return : 0 on success or negative error code
542 */ 680 */
543#define __BPF_FUNC_MAPPER(FN) \ 681#define __BPF_FUNC_MAPPER(FN) \
544 FN(unspec), \ 682 FN(unspec), \
@@ -591,7 +729,14 @@ union bpf_attr {
591 FN(get_socket_uid), \ 729 FN(get_socket_uid), \
592 FN(set_hash), \ 730 FN(set_hash), \
593 FN(setsockopt), \ 731 FN(setsockopt), \
594 FN(skb_adjust_room), 732 FN(skb_adjust_room), \
733 FN(redirect_map), \
734 FN(sk_redirect_map), \
735 FN(sock_map_update), \
736 FN(xdp_adjust_meta), \
737 FN(perf_event_read_value), \
738 FN(perf_prog_read_value), \
739 FN(getsockopt),
595 740
596/* integer value in 'imm' field of BPF_CALL instruction selects which helper 741/* integer value in 'imm' field of BPF_CALL instruction selects which helper
597 * function eBPF program intends to call 742 * function eBPF program intends to call
@@ -635,7 +780,9 @@ enum bpf_func_id {
635#define BPF_F_ZERO_CSUM_TX (1ULL << 1) 780#define BPF_F_ZERO_CSUM_TX (1ULL << 1)
636#define BPF_F_DONT_FRAGMENT (1ULL << 2) 781#define BPF_F_DONT_FRAGMENT (1ULL << 2)
637 782
638/* BPF_FUNC_perf_event_output and BPF_FUNC_perf_event_read flags. */ 783/* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and
784 * BPF_FUNC_perf_event_read_value flags.
785 */
639#define BPF_F_INDEX_MASK 0xffffffffULL 786#define BPF_F_INDEX_MASK 0xffffffffULL
640#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK 787#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK
641/* BPF_FUNC_perf_event_output for sk_buff input context. */ 788/* BPF_FUNC_perf_event_output for sk_buff input context. */
@@ -643,7 +790,7 @@ enum bpf_func_id {
643 790
644/* Mode for BPF_FUNC_skb_adjust_room helper. */ 791/* Mode for BPF_FUNC_skb_adjust_room helper. */
645enum bpf_adj_room_mode { 792enum bpf_adj_room_mode {
646 BPF_ADJ_ROOM_NET_OPTS, 793 BPF_ADJ_ROOM_NET,
647}; 794};
648 795
649/* user accessible mirror of in-kernel sk_buff. 796/* user accessible mirror of in-kernel sk_buff.
@@ -668,6 +815,18 @@ struct __sk_buff {
668 __u32 data; 815 __u32 data;
669 __u32 data_end; 816 __u32 data_end;
670 __u32 napi_id; 817 __u32 napi_id;
818
819 /* Accessed by BPF_PROG_TYPE_sk_skb types from here to ... */
820 __u32 family;
821 __u32 remote_ip4; /* Stored in network byte order */
822 __u32 local_ip4; /* Stored in network byte order */
823 __u32 remote_ip6[4]; /* Stored in network byte order */
824 __u32 local_ip6[4]; /* Stored in network byte order */
825 __u32 remote_port; /* Stored in network byte order */
826 __u32 local_port; /* stored in host byte order */
827 /* ... here. */
828
829 __u32 data_meta;
671}; 830};
672 831
673struct bpf_tunnel_key { 832struct bpf_tunnel_key {
@@ -703,20 +862,23 @@ struct bpf_sock {
703 __u32 family; 862 __u32 family;
704 __u32 type; 863 __u32 type;
705 __u32 protocol; 864 __u32 protocol;
865 __u32 mark;
866 __u32 priority;
706}; 867};
707 868
708#define XDP_PACKET_HEADROOM 256 869#define XDP_PACKET_HEADROOM 256
709 870
710/* User return codes for XDP prog type. 871/* User return codes for XDP prog type.
711 * A valid XDP program must return one of these defined values. All other 872 * A valid XDP program must return one of these defined values. All other
712 * return codes are reserved for future use. Unknown return codes will result 873 * return codes are reserved for future use. Unknown return codes will
713 * in packet drop. 874 * result in packet drops and a warning via bpf_warn_invalid_xdp_action().
714 */ 875 */
715enum xdp_action { 876enum xdp_action {
716 XDP_ABORTED = 0, 877 XDP_ABORTED = 0,
717 XDP_DROP, 878 XDP_DROP,
718 XDP_PASS, 879 XDP_PASS,
719 XDP_TX, 880 XDP_TX,
881 XDP_REDIRECT,
720}; 882};
721 883
722/* user accessible metadata for XDP packet hook 884/* user accessible metadata for XDP packet hook
@@ -725,6 +887,12 @@ enum xdp_action {
725struct xdp_md { 887struct xdp_md {
726 __u32 data; 888 __u32 data;
727 __u32 data_end; 889 __u32 data_end;
890 __u32 data_meta;
891};
892
893enum sk_action {
894 SK_DROP = 0,
895 SK_PASS,
728}; 896};
729 897
730#define BPF_TAG_SIZE 8 898#define BPF_TAG_SIZE 8
@@ -737,6 +905,11 @@ struct bpf_prog_info {
737 __u32 xlated_prog_len; 905 __u32 xlated_prog_len;
738 __aligned_u64 jited_prog_insns; 906 __aligned_u64 jited_prog_insns;
739 __aligned_u64 xlated_prog_insns; 907 __aligned_u64 xlated_prog_insns;
908 __u64 load_time; /* ns since boottime */
909 __u32 created_by_uid;
910 __u32 nr_map_ids;
911 __aligned_u64 map_ids;
912 char name[BPF_OBJ_NAME_LEN];
740} __attribute__((aligned(8))); 913} __attribute__((aligned(8)));
741 914
742struct bpf_map_info { 915struct bpf_map_info {
@@ -746,10 +919,13 @@ struct bpf_map_info {
746 __u32 value_size; 919 __u32 value_size;
747 __u32 max_entries; 920 __u32 max_entries;
748 __u32 map_flags; 921 __u32 map_flags;
922 char name[BPF_OBJ_NAME_LEN];
749} __attribute__((aligned(8))); 923} __attribute__((aligned(8)));
750 924
751/* User bpf_sock_ops struct to access socket values and specify request ops 925/* User bpf_sock_ops struct to access socket values and specify request ops
752 * and their replies. 926 * and their replies.
927 * Some of this fields are in network (bigendian) byte order and may need
928 * to be converted before use (bpf_ntohl() defined in samples/bpf/bpf_endian.h).
753 * New fields can only be added at the end of this structure 929 * New fields can only be added at the end of this structure
754 */ 930 */
755struct bpf_sock_ops { 931struct bpf_sock_ops {
@@ -759,12 +935,12 @@ struct bpf_sock_ops {
759 __u32 replylong[4]; 935 __u32 replylong[4];
760 }; 936 };
761 __u32 family; 937 __u32 family;
762 __u32 remote_ip4; 938 __u32 remote_ip4; /* Stored in network byte order */
763 __u32 local_ip4; 939 __u32 local_ip4; /* Stored in network byte order */
764 __u32 remote_ip6[4]; 940 __u32 remote_ip6[4]; /* Stored in network byte order */
765 __u32 local_ip6[4]; 941 __u32 local_ip6[4]; /* Stored in network byte order */
766 __u32 remote_port; 942 __u32 remote_port; /* Stored in network byte order */
767 __u32 local_port; 943 __u32 local_port; /* stored in host byte order */
768}; 944};
769 945
770/* List of known BPF sock_ops operators. 946/* List of known BPF sock_ops operators.
@@ -793,9 +969,35 @@ enum {
793 BPF_SOCK_OPS_NEEDS_ECN, /* If connection's congestion control 969 BPF_SOCK_OPS_NEEDS_ECN, /* If connection's congestion control
794 * needs ECN 970 * needs ECN
795 */ 971 */
972 BPF_SOCK_OPS_BASE_RTT, /* Get base RTT. The correct value is
973 * based on the path and may be
974 * dependent on the congestion control
975 * algorithm. In general it indicates
976 * a congestion threshold. RTTs above
977 * this indicate congestion
978 */
796}; 979};
797 980
798#define TCP_BPF_IW 1001 /* Set TCP initial congestion window */ 981#define TCP_BPF_IW 1001 /* Set TCP initial congestion window */
799#define TCP_BPF_SNDCWND_CLAMP 1002 /* Set sndcwnd_clamp */ 982#define TCP_BPF_SNDCWND_CLAMP 1002 /* Set sndcwnd_clamp */
800 983
984struct bpf_perf_event_value {
985 __u64 counter;
986 __u64 enabled;
987 __u64 running;
988};
989
990#define BPF_DEVCG_ACC_MKNOD (1ULL << 0)
991#define BPF_DEVCG_ACC_READ (1ULL << 1)
992#define BPF_DEVCG_ACC_WRITE (1ULL << 2)
993
994#define BPF_DEVCG_DEV_BLOCK (1ULL << 0)
995#define BPF_DEVCG_DEV_CHAR (1ULL << 1)
996
997struct bpf_cgroup_dev_ctx {
998 __u32 access_type; /* (access << 16) | type */
999 __u32 major;
1000 __u32 minor;
1001};
1002
801#endif /* _UAPI__LINUX_BPF_H__ */ 1003#endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/tools/include/uapi/linux/bpf_common.h b/tools/include/uapi/linux/bpf_common.h
index a5c220e0828f..18be90725ab0 100644
--- a/tools/include/uapi/linux/bpf_common.h
+++ b/tools/include/uapi/linux/bpf_common.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _UAPI__LINUX_BPF_COMMON_H__ 2#ifndef _UAPI__LINUX_BPF_COMMON_H__
2#define _UAPI__LINUX_BPF_COMMON_H__ 3#define _UAPI__LINUX_BPF_COMMON_H__
3 4
diff --git a/tools/include/uapi/linux/fcntl.h b/tools/include/uapi/linux/fcntl.h
index 813afd6eee71..6448cdd9a350 100644
--- a/tools/include/uapi/linux/fcntl.h
+++ b/tools/include/uapi/linux/fcntl.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _UAPI_LINUX_FCNTL_H 2#ifndef _UAPI_LINUX_FCNTL_H
2#define _UAPI_LINUX_FCNTL_H 3#define _UAPI_LINUX_FCNTL_H
3 4
@@ -43,6 +44,27 @@
43/* (1U << 31) is reserved for signed error codes */ 44/* (1U << 31) is reserved for signed error codes */
44 45
45/* 46/*
47 * Set/Get write life time hints. {GET,SET}_RW_HINT operate on the
48 * underlying inode, while {GET,SET}_FILE_RW_HINT operate only on
49 * the specific file.
50 */
51#define F_GET_RW_HINT (F_LINUX_SPECIFIC_BASE + 11)
52#define F_SET_RW_HINT (F_LINUX_SPECIFIC_BASE + 12)
53#define F_GET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 13)
54#define F_SET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 14)
55
56/*
57 * Valid hint values for F_{GET,SET}_RW_HINT. 0 is "not set", or can be
58 * used to clear any hints previously set.
59 */
60#define RWF_WRITE_LIFE_NOT_SET 0
61#define RWH_WRITE_LIFE_NONE 1
62#define RWH_WRITE_LIFE_SHORT 2
63#define RWH_WRITE_LIFE_MEDIUM 3
64#define RWH_WRITE_LIFE_LONG 4
65#define RWH_WRITE_LIFE_EXTREME 5
66
67/*
46 * Types of directory notifications that may be requested. 68 * Types of directory notifications that may be requested.
47 */ 69 */
48#define DN_ACCESS 0x00000001 /* File accessed */ 70#define DN_ACCESS 0x00000001 /* File accessed */
diff --git a/tools/include/uapi/linux/hw_breakpoint.h b/tools/include/uapi/linux/hw_breakpoint.h
index 2b65efd19a46..965e4d8606d8 100644
--- a/tools/include/uapi/linux/hw_breakpoint.h
+++ b/tools/include/uapi/linux/hw_breakpoint.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _UAPI_LINUX_HW_BREAKPOINT_H 2#ifndef _UAPI_LINUX_HW_BREAKPOINT_H
2#define _UAPI_LINUX_HW_BREAKPOINT_H 3#define _UAPI_LINUX_HW_BREAKPOINT_H
3 4
diff --git a/tools/include/uapi/linux/kcmp.h b/tools/include/uapi/linux/kcmp.h
new file mode 100644
index 000000000000..481e103da78e
--- /dev/null
+++ b/tools/include/uapi/linux/kcmp.h
@@ -0,0 +1,27 @@
1#ifndef _UAPI_LINUX_KCMP_H
2#define _UAPI_LINUX_KCMP_H
3
4#include <linux/types.h>
5
6/* Comparison type */
7enum kcmp_type {
8 KCMP_FILE,
9 KCMP_VM,
10 KCMP_FILES,
11 KCMP_FS,
12 KCMP_SIGHAND,
13 KCMP_IO,
14 KCMP_SYSVSEM,
15 KCMP_EPOLL_TFD,
16
17 KCMP_TYPES,
18};
19
20/* Slot for KCMP_EPOLL_TFD */
21struct kcmp_epoll_slot {
22 __u32 efd; /* epoll file descriptor */
23 __u32 tfd; /* target file number */
24 __u32 toff; /* target offset within same numbered sequence */
25};
26
27#endif /* _UAPI_LINUX_KCMP_H */
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
new file mode 100644
index 000000000000..7e99999d6236
--- /dev/null
+++ b/tools/include/uapi/linux/kvm.h
@@ -0,0 +1,1421 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef __LINUX_KVM_H
3#define __LINUX_KVM_H
4
5/*
6 * Userspace interface for /dev/kvm - kernel based virtual machine
7 *
8 * Note: you must update KVM_API_VERSION if you change this interface.
9 */
10
11#include <linux/types.h>
12#include <linux/compiler.h>
13#include <linux/ioctl.h>
14#include <asm/kvm.h>
15
16#define KVM_API_VERSION 12
17
18/* *** Deprecated interfaces *** */
19
20#define KVM_TRC_SHIFT 16
21
22#define KVM_TRC_ENTRYEXIT (1 << KVM_TRC_SHIFT)
23#define KVM_TRC_HANDLER (1 << (KVM_TRC_SHIFT + 1))
24
25#define KVM_TRC_VMENTRY (KVM_TRC_ENTRYEXIT + 0x01)
26#define KVM_TRC_VMEXIT (KVM_TRC_ENTRYEXIT + 0x02)
27#define KVM_TRC_PAGE_FAULT (KVM_TRC_HANDLER + 0x01)
28
29#define KVM_TRC_HEAD_SIZE 12
30#define KVM_TRC_CYCLE_SIZE 8
31#define KVM_TRC_EXTRA_MAX 7
32
33#define KVM_TRC_INJ_VIRQ (KVM_TRC_HANDLER + 0x02)
34#define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03)
35#define KVM_TRC_PEND_INTR (KVM_TRC_HANDLER + 0x04)
36#define KVM_TRC_IO_READ (KVM_TRC_HANDLER + 0x05)
37#define KVM_TRC_IO_WRITE (KVM_TRC_HANDLER + 0x06)
38#define KVM_TRC_CR_READ (KVM_TRC_HANDLER + 0x07)
39#define KVM_TRC_CR_WRITE (KVM_TRC_HANDLER + 0x08)
40#define KVM_TRC_DR_READ (KVM_TRC_HANDLER + 0x09)
41#define KVM_TRC_DR_WRITE (KVM_TRC_HANDLER + 0x0A)
42#define KVM_TRC_MSR_READ (KVM_TRC_HANDLER + 0x0B)
43#define KVM_TRC_MSR_WRITE (KVM_TRC_HANDLER + 0x0C)
44#define KVM_TRC_CPUID (KVM_TRC_HANDLER + 0x0D)
45#define KVM_TRC_INTR (KVM_TRC_HANDLER + 0x0E)
46#define KVM_TRC_NMI (KVM_TRC_HANDLER + 0x0F)
47#define KVM_TRC_VMMCALL (KVM_TRC_HANDLER + 0x10)
48#define KVM_TRC_HLT (KVM_TRC_HANDLER + 0x11)
49#define KVM_TRC_CLTS (KVM_TRC_HANDLER + 0x12)
50#define KVM_TRC_LMSW (KVM_TRC_HANDLER + 0x13)
51#define KVM_TRC_APIC_ACCESS (KVM_TRC_HANDLER + 0x14)
52#define KVM_TRC_TDP_FAULT (KVM_TRC_HANDLER + 0x15)
53#define KVM_TRC_GTLB_WRITE (KVM_TRC_HANDLER + 0x16)
54#define KVM_TRC_STLB_WRITE (KVM_TRC_HANDLER + 0x17)
55#define KVM_TRC_STLB_INVAL (KVM_TRC_HANDLER + 0x18)
56#define KVM_TRC_PPC_INSTR (KVM_TRC_HANDLER + 0x19)
57
58struct kvm_user_trace_setup {
59 __u32 buf_size;
60 __u32 buf_nr;
61};
62
63#define __KVM_DEPRECATED_MAIN_W_0x06 \
64 _IOW(KVMIO, 0x06, struct kvm_user_trace_setup)
65#define __KVM_DEPRECATED_MAIN_0x07 _IO(KVMIO, 0x07)
66#define __KVM_DEPRECATED_MAIN_0x08 _IO(KVMIO, 0x08)
67
68#define __KVM_DEPRECATED_VM_R_0x70 _IOR(KVMIO, 0x70, struct kvm_assigned_irq)
69
70struct kvm_breakpoint {
71 __u32 enabled;
72 __u32 padding;
73 __u64 address;
74};
75
76struct kvm_debug_guest {
77 __u32 enabled;
78 __u32 pad;
79 struct kvm_breakpoint breakpoints[4];
80 __u32 singlestep;
81};
82
83#define __KVM_DEPRECATED_VCPU_W_0x87 _IOW(KVMIO, 0x87, struct kvm_debug_guest)
84
85/* *** End of deprecated interfaces *** */
86
87
88/* for KVM_CREATE_MEMORY_REGION */
89struct kvm_memory_region {
90 __u32 slot;
91 __u32 flags;
92 __u64 guest_phys_addr;
93 __u64 memory_size; /* bytes */
94};
95
96/* for KVM_SET_USER_MEMORY_REGION */
97struct kvm_userspace_memory_region {
98 __u32 slot;
99 __u32 flags;
100 __u64 guest_phys_addr;
101 __u64 memory_size; /* bytes */
102 __u64 userspace_addr; /* start of the userspace allocated memory */
103};
104
105/*
106 * The bit 0 ~ bit 15 of kvm_memory_region::flags are visible for userspace,
107 * other bits are reserved for kvm internal use which are defined in
108 * include/linux/kvm_host.h.
109 */
110#define KVM_MEM_LOG_DIRTY_PAGES (1UL << 0)
111#define KVM_MEM_READONLY (1UL << 1)
112
113/* for KVM_IRQ_LINE */
114struct kvm_irq_level {
115 /*
116 * ACPI gsi notion of irq.
117 * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
118 * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
119 * For ARM: See Documentation/virtual/kvm/api.txt
120 */
121 union {
122 __u32 irq;
123 __s32 status;
124 };
125 __u32 level;
126};
127
128
129struct kvm_irqchip {
130 __u32 chip_id;
131 __u32 pad;
132 union {
133 char dummy[512]; /* reserving space */
134#ifdef __KVM_HAVE_PIT
135 struct kvm_pic_state pic;
136#endif
137#ifdef __KVM_HAVE_IOAPIC
138 struct kvm_ioapic_state ioapic;
139#endif
140 } chip;
141};
142
143/* for KVM_CREATE_PIT2 */
144struct kvm_pit_config {
145 __u32 flags;
146 __u32 pad[15];
147};
148
149#define KVM_PIT_SPEAKER_DUMMY 1
150
151struct kvm_s390_skeys {
152 __u64 start_gfn;
153 __u64 count;
154 __u64 skeydata_addr;
155 __u32 flags;
156 __u32 reserved[9];
157};
158
159#define KVM_S390_CMMA_PEEK (1 << 0)
160
161/**
162 * kvm_s390_cmma_log - Used for CMMA migration.
163 *
164 * Used both for input and output.
165 *
166 * @start_gfn: Guest page number to start from.
167 * @count: Size of the result buffer.
168 * @flags: Control operation mode via KVM_S390_CMMA_* flags
169 * @remaining: Used with KVM_S390_GET_CMMA_BITS. Indicates how many dirty
170 * pages are still remaining.
171 * @mask: Used with KVM_S390_SET_CMMA_BITS. Bitmap of bits to actually set
172 * in the PGSTE.
173 * @values: Pointer to the values buffer.
174 *
175 * Used in KVM_S390_{G,S}ET_CMMA_BITS ioctls.
176 */
177struct kvm_s390_cmma_log {
178 __u64 start_gfn;
179 __u32 count;
180 __u32 flags;
181 union {
182 __u64 remaining;
183 __u64 mask;
184 };
185 __u64 values;
186};
187
188struct kvm_hyperv_exit {
189#define KVM_EXIT_HYPERV_SYNIC 1
190#define KVM_EXIT_HYPERV_HCALL 2
191 __u32 type;
192 union {
193 struct {
194 __u32 msr;
195 __u64 control;
196 __u64 evt_page;
197 __u64 msg_page;
198 } synic;
199 struct {
200 __u64 input;
201 __u64 result;
202 __u64 params[2];
203 } hcall;
204 } u;
205};
206
207#define KVM_S390_GET_SKEYS_NONE 1
208#define KVM_S390_SKEYS_MAX 1048576
209
210#define KVM_EXIT_UNKNOWN 0
211#define KVM_EXIT_EXCEPTION 1
212#define KVM_EXIT_IO 2
213#define KVM_EXIT_HYPERCALL 3
214#define KVM_EXIT_DEBUG 4
215#define KVM_EXIT_HLT 5
216#define KVM_EXIT_MMIO 6
217#define KVM_EXIT_IRQ_WINDOW_OPEN 7
218#define KVM_EXIT_SHUTDOWN 8
219#define KVM_EXIT_FAIL_ENTRY 9
220#define KVM_EXIT_INTR 10
221#define KVM_EXIT_SET_TPR 11
222#define KVM_EXIT_TPR_ACCESS 12
223#define KVM_EXIT_S390_SIEIC 13
224#define KVM_EXIT_S390_RESET 14
225#define KVM_EXIT_DCR 15 /* deprecated */
226#define KVM_EXIT_NMI 16
227#define KVM_EXIT_INTERNAL_ERROR 17
228#define KVM_EXIT_OSI 18
229#define KVM_EXIT_PAPR_HCALL 19
230#define KVM_EXIT_S390_UCONTROL 20
231#define KVM_EXIT_WATCHDOG 21
232#define KVM_EXIT_S390_TSCH 22
233#define KVM_EXIT_EPR 23
234#define KVM_EXIT_SYSTEM_EVENT 24
235#define KVM_EXIT_S390_STSI 25
236#define KVM_EXIT_IOAPIC_EOI 26
237#define KVM_EXIT_HYPERV 27
238
239/* For KVM_EXIT_INTERNAL_ERROR */
240/* Emulate instruction failed. */
241#define KVM_INTERNAL_ERROR_EMULATION 1
242/* Encounter unexpected simultaneous exceptions. */
243#define KVM_INTERNAL_ERROR_SIMUL_EX 2
244/* Encounter unexpected vm-exit due to delivery event. */
245#define KVM_INTERNAL_ERROR_DELIVERY_EV 3
246
247/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
248struct kvm_run {
249 /* in */
250 __u8 request_interrupt_window;
251 __u8 immediate_exit;
252 __u8 padding1[6];
253
254 /* out */
255 __u32 exit_reason;
256 __u8 ready_for_interrupt_injection;
257 __u8 if_flag;
258 __u16 flags;
259
260 /* in (pre_kvm_run), out (post_kvm_run) */
261 __u64 cr8;
262 __u64 apic_base;
263
264#ifdef __KVM_S390
265 /* the processor status word for s390 */
266 __u64 psw_mask; /* psw upper half */
267 __u64 psw_addr; /* psw lower half */
268#endif
269 union {
270 /* KVM_EXIT_UNKNOWN */
271 struct {
272 __u64 hardware_exit_reason;
273 } hw;
274 /* KVM_EXIT_FAIL_ENTRY */
275 struct {
276 __u64 hardware_entry_failure_reason;
277 } fail_entry;
278 /* KVM_EXIT_EXCEPTION */
279 struct {
280 __u32 exception;
281 __u32 error_code;
282 } ex;
283 /* KVM_EXIT_IO */
284 struct {
285#define KVM_EXIT_IO_IN 0
286#define KVM_EXIT_IO_OUT 1
287 __u8 direction;
288 __u8 size; /* bytes */
289 __u16 port;
290 __u32 count;
291 __u64 data_offset; /* relative to kvm_run start */
292 } io;
293 /* KVM_EXIT_DEBUG */
294 struct {
295 struct kvm_debug_exit_arch arch;
296 } debug;
297 /* KVM_EXIT_MMIO */
298 struct {
299 __u64 phys_addr;
300 __u8 data[8];
301 __u32 len;
302 __u8 is_write;
303 } mmio;
304 /* KVM_EXIT_HYPERCALL */
305 struct {
306 __u64 nr;
307 __u64 args[6];
308 __u64 ret;
309 __u32 longmode;
310 __u32 pad;
311 } hypercall;
312 /* KVM_EXIT_TPR_ACCESS */
313 struct {
314 __u64 rip;
315 __u32 is_write;
316 __u32 pad;
317 } tpr_access;
318 /* KVM_EXIT_S390_SIEIC */
319 struct {
320 __u8 icptcode;
321 __u16 ipa;
322 __u32 ipb;
323 } s390_sieic;
324 /* KVM_EXIT_S390_RESET */
325#define KVM_S390_RESET_POR 1
326#define KVM_S390_RESET_CLEAR 2
327#define KVM_S390_RESET_SUBSYSTEM 4
328#define KVM_S390_RESET_CPU_INIT 8
329#define KVM_S390_RESET_IPL 16
330 __u64 s390_reset_flags;
331 /* KVM_EXIT_S390_UCONTROL */
332 struct {
333 __u64 trans_exc_code;
334 __u32 pgm_code;
335 } s390_ucontrol;
336 /* KVM_EXIT_DCR (deprecated) */
337 struct {
338 __u32 dcrn;
339 __u32 data;
340 __u8 is_write;
341 } dcr;
342 /* KVM_EXIT_INTERNAL_ERROR */
343 struct {
344 __u32 suberror;
345 /* Available with KVM_CAP_INTERNAL_ERROR_DATA: */
346 __u32 ndata;
347 __u64 data[16];
348 } internal;
349 /* KVM_EXIT_OSI */
350 struct {
351 __u64 gprs[32];
352 } osi;
353 /* KVM_EXIT_PAPR_HCALL */
354 struct {
355 __u64 nr;
356 __u64 ret;
357 __u64 args[9];
358 } papr_hcall;
359 /* KVM_EXIT_S390_TSCH */
360 struct {
361 __u16 subchannel_id;
362 __u16 subchannel_nr;
363 __u32 io_int_parm;
364 __u32 io_int_word;
365 __u32 ipb;
366 __u8 dequeued;
367 } s390_tsch;
368 /* KVM_EXIT_EPR */
369 struct {
370 __u32 epr;
371 } epr;
372 /* KVM_EXIT_SYSTEM_EVENT */
373 struct {
374#define KVM_SYSTEM_EVENT_SHUTDOWN 1
375#define KVM_SYSTEM_EVENT_RESET 2
376#define KVM_SYSTEM_EVENT_CRASH 3
377 __u32 type;
378 __u64 flags;
379 } system_event;
380 /* KVM_EXIT_S390_STSI */
381 struct {
382 __u64 addr;
383 __u8 ar;
384 __u8 reserved;
385 __u8 fc;
386 __u8 sel1;
387 __u16 sel2;
388 } s390_stsi;
389 /* KVM_EXIT_IOAPIC_EOI */
390 struct {
391 __u8 vector;
392 } eoi;
393 /* KVM_EXIT_HYPERV */
394 struct kvm_hyperv_exit hyperv;
395 /* Fix the size of the union. */
396 char padding[256];
397 };
398
399 /*
400 * shared registers between kvm and userspace.
401 * kvm_valid_regs specifies the register classes set by the host
402 * kvm_dirty_regs specified the register classes dirtied by userspace
403 * struct kvm_sync_regs is architecture specific, as well as the
404 * bits for kvm_valid_regs and kvm_dirty_regs
405 */
406 __u64 kvm_valid_regs;
407 __u64 kvm_dirty_regs;
408 union {
409 struct kvm_sync_regs regs;
410 char padding[2048];
411 } s;
412};
413
414/* for KVM_REGISTER_COALESCED_MMIO / KVM_UNREGISTER_COALESCED_MMIO */
415
416struct kvm_coalesced_mmio_zone {
417 __u64 addr;
418 __u32 size;
419 __u32 pad;
420};
421
422struct kvm_coalesced_mmio {
423 __u64 phys_addr;
424 __u32 len;
425 __u32 pad;
426 __u8 data[8];
427};
428
429struct kvm_coalesced_mmio_ring {
430 __u32 first, last;
431 struct kvm_coalesced_mmio coalesced_mmio[0];
432};
433
434#define KVM_COALESCED_MMIO_MAX \
435 ((PAGE_SIZE - sizeof(struct kvm_coalesced_mmio_ring)) / \
436 sizeof(struct kvm_coalesced_mmio))
437
438/* for KVM_TRANSLATE */
439struct kvm_translation {
440 /* in */
441 __u64 linear_address;
442
443 /* out */
444 __u64 physical_address;
445 __u8 valid;
446 __u8 writeable;
447 __u8 usermode;
448 __u8 pad[5];
449};
450
451/* for KVM_S390_MEM_OP */
452struct kvm_s390_mem_op {
453 /* in */
454 __u64 gaddr; /* the guest address */
455 __u64 flags; /* flags */
456 __u32 size; /* amount of bytes */
457 __u32 op; /* type of operation */
458 __u64 buf; /* buffer in userspace */
459 __u8 ar; /* the access register number */
460 __u8 reserved[31]; /* should be set to 0 */
461};
462/* types for kvm_s390_mem_op->op */
463#define KVM_S390_MEMOP_LOGICAL_READ 0
464#define KVM_S390_MEMOP_LOGICAL_WRITE 1
465/* flags for kvm_s390_mem_op->flags */
466#define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0)
467#define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1)
468
469/* for KVM_INTERRUPT */
470struct kvm_interrupt {
471 /* in */
472 __u32 irq;
473};
474
475/* for KVM_GET_DIRTY_LOG */
476struct kvm_dirty_log {
477 __u32 slot;
478 __u32 padding1;
479 union {
480 void __user *dirty_bitmap; /* one bit per page */
481 __u64 padding2;
482 };
483};
484
485/* for KVM_SET_SIGNAL_MASK */
486struct kvm_signal_mask {
487 __u32 len;
488 __u8 sigset[0];
489};
490
491/* for KVM_TPR_ACCESS_REPORTING */
492struct kvm_tpr_access_ctl {
493 __u32 enabled;
494 __u32 flags;
495 __u32 reserved[8];
496};
497
498/* for KVM_SET_VAPIC_ADDR */
499struct kvm_vapic_addr {
500 __u64 vapic_addr;
501};
502
503/* for KVM_SET_MP_STATE */
504
505/* not all states are valid on all architectures */
506#define KVM_MP_STATE_RUNNABLE 0
507#define KVM_MP_STATE_UNINITIALIZED 1
508#define KVM_MP_STATE_INIT_RECEIVED 2
509#define KVM_MP_STATE_HALTED 3
510#define KVM_MP_STATE_SIPI_RECEIVED 4
511#define KVM_MP_STATE_STOPPED 5
512#define KVM_MP_STATE_CHECK_STOP 6
513#define KVM_MP_STATE_OPERATING 7
514#define KVM_MP_STATE_LOAD 8
515
516struct kvm_mp_state {
517 __u32 mp_state;
518};
519
520struct kvm_s390_psw {
521 __u64 mask;
522 __u64 addr;
523};
524
525/* valid values for type in kvm_s390_interrupt */
526#define KVM_S390_SIGP_STOP 0xfffe0000u
527#define KVM_S390_PROGRAM_INT 0xfffe0001u
528#define KVM_S390_SIGP_SET_PREFIX 0xfffe0002u
529#define KVM_S390_RESTART 0xfffe0003u
530#define KVM_S390_INT_PFAULT_INIT 0xfffe0004u
531#define KVM_S390_INT_PFAULT_DONE 0xfffe0005u
532#define KVM_S390_MCHK 0xfffe1000u
533#define KVM_S390_INT_CLOCK_COMP 0xffff1004u
534#define KVM_S390_INT_CPU_TIMER 0xffff1005u
535#define KVM_S390_INT_VIRTIO 0xffff2603u
536#define KVM_S390_INT_SERVICE 0xffff2401u
537#define KVM_S390_INT_EMERGENCY 0xffff1201u
538#define KVM_S390_INT_EXTERNAL_CALL 0xffff1202u
539/* Anything below 0xfffe0000u is taken by INT_IO */
540#define KVM_S390_INT_IO(ai,cssid,ssid,schid) \
541 (((schid)) | \
542 ((ssid) << 16) | \
543 ((cssid) << 18) | \
544 ((ai) << 26))
545#define KVM_S390_INT_IO_MIN 0x00000000u
546#define KVM_S390_INT_IO_MAX 0xfffdffffu
547#define KVM_S390_INT_IO_AI_MASK 0x04000000u
548
549
550struct kvm_s390_interrupt {
551 __u32 type;
552 __u32 parm;
553 __u64 parm64;
554};
555
556struct kvm_s390_io_info {
557 __u16 subchannel_id;
558 __u16 subchannel_nr;
559 __u32 io_int_parm;
560 __u32 io_int_word;
561};
562
563struct kvm_s390_ext_info {
564 __u32 ext_params;
565 __u32 pad;
566 __u64 ext_params2;
567};
568
569struct kvm_s390_pgm_info {
570 __u64 trans_exc_code;
571 __u64 mon_code;
572 __u64 per_address;
573 __u32 data_exc_code;
574 __u16 code;
575 __u16 mon_class_nr;
576 __u8 per_code;
577 __u8 per_atmid;
578 __u8 exc_access_id;
579 __u8 per_access_id;
580 __u8 op_access_id;
581#define KVM_S390_PGM_FLAGS_ILC_VALID 0x01
582#define KVM_S390_PGM_FLAGS_ILC_0 0x02
583#define KVM_S390_PGM_FLAGS_ILC_1 0x04
584#define KVM_S390_PGM_FLAGS_ILC_MASK 0x06
585#define KVM_S390_PGM_FLAGS_NO_REWIND 0x08
586 __u8 flags;
587 __u8 pad[2];
588};
589
590struct kvm_s390_prefix_info {
591 __u32 address;
592};
593
594struct kvm_s390_extcall_info {
595 __u16 code;
596};
597
598struct kvm_s390_emerg_info {
599 __u16 code;
600};
601
602#define KVM_S390_STOP_FLAG_STORE_STATUS 0x01
603struct kvm_s390_stop_info {
604 __u32 flags;
605};
606
607struct kvm_s390_mchk_info {
608 __u64 cr14;
609 __u64 mcic;
610 __u64 failing_storage_address;
611 __u32 ext_damage_code;
612 __u32 pad;
613 __u8 fixed_logout[16];
614};
615
616struct kvm_s390_irq {
617 __u64 type;
618 union {
619 struct kvm_s390_io_info io;
620 struct kvm_s390_ext_info ext;
621 struct kvm_s390_pgm_info pgm;
622 struct kvm_s390_emerg_info emerg;
623 struct kvm_s390_extcall_info extcall;
624 struct kvm_s390_prefix_info prefix;
625 struct kvm_s390_stop_info stop;
626 struct kvm_s390_mchk_info mchk;
627 char reserved[64];
628 } u;
629};
630
631struct kvm_s390_irq_state {
632 __u64 buf;
633 __u32 flags;
634 __u32 len;
635 __u32 reserved[4];
636};
637
638/* for KVM_SET_GUEST_DEBUG */
639
640#define KVM_GUESTDBG_ENABLE 0x00000001
641#define KVM_GUESTDBG_SINGLESTEP 0x00000002
642
643struct kvm_guest_debug {
644 __u32 control;
645 __u32 pad;
646 struct kvm_guest_debug_arch arch;
647};
648
649enum {
650 kvm_ioeventfd_flag_nr_datamatch,
651 kvm_ioeventfd_flag_nr_pio,
652 kvm_ioeventfd_flag_nr_deassign,
653 kvm_ioeventfd_flag_nr_virtio_ccw_notify,
654 kvm_ioeventfd_flag_nr_fast_mmio,
655 kvm_ioeventfd_flag_nr_max,
656};
657
658#define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
659#define KVM_IOEVENTFD_FLAG_PIO (1 << kvm_ioeventfd_flag_nr_pio)
660#define KVM_IOEVENTFD_FLAG_DEASSIGN (1 << kvm_ioeventfd_flag_nr_deassign)
661#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \
662 (1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify)
663
664#define KVM_IOEVENTFD_VALID_FLAG_MASK ((1 << kvm_ioeventfd_flag_nr_max) - 1)
665
666struct kvm_ioeventfd {
667 __u64 datamatch;
668 __u64 addr; /* legal pio/mmio address */
669 __u32 len; /* 1, 2, 4, or 8 bytes; or 0 to ignore length */
670 __s32 fd;
671 __u32 flags;
672 __u8 pad[36];
673};
674
675/* for KVM_ENABLE_CAP */
676struct kvm_enable_cap {
677 /* in */
678 __u32 cap;
679 __u32 flags;
680 __u64 args[4];
681 __u8 pad[64];
682};
683
684/* for KVM_PPC_GET_PVINFO */
685
686#define KVM_PPC_PVINFO_FLAGS_EV_IDLE (1<<0)
687
688struct kvm_ppc_pvinfo {
689 /* out */
690 __u32 flags;
691 __u32 hcall[4];
692 __u8 pad[108];
693};
694
695/* for KVM_PPC_GET_SMMU_INFO */
696#define KVM_PPC_PAGE_SIZES_MAX_SZ 8
697
698struct kvm_ppc_one_page_size {
699 __u32 page_shift; /* Page shift (or 0) */
700 __u32 pte_enc; /* Encoding in the HPTE (>>12) */
701};
702
703struct kvm_ppc_one_seg_page_size {
704 __u32 page_shift; /* Base page shift of segment (or 0) */
705 __u32 slb_enc; /* SLB encoding for BookS */
706 struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ];
707};
708
709#define KVM_PPC_PAGE_SIZES_REAL 0x00000001
710#define KVM_PPC_1T_SEGMENTS 0x00000002
711
712struct kvm_ppc_smmu_info {
713 __u64 flags;
714 __u32 slb_size;
715 __u16 data_keys; /* # storage keys supported for data */
716 __u16 instr_keys; /* # storage keys supported for instructions */
717 struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
718};
719
720/* for KVM_PPC_RESIZE_HPT_{PREPARE,COMMIT} */
721struct kvm_ppc_resize_hpt {
722 __u64 flags;
723 __u32 shift;
724 __u32 pad;
725};
726
727#define KVMIO 0xAE
728
729/* machine type bits, to be used as argument to KVM_CREATE_VM */
730#define KVM_VM_S390_UCONTROL 1
731
732/* on ppc, 0 indicate default, 1 should force HV and 2 PR */
733#define KVM_VM_PPC_HV 1
734#define KVM_VM_PPC_PR 2
735
736/* on MIPS, 0 forces trap & emulate, 1 forces VZ ASE */
737#define KVM_VM_MIPS_TE 0
738#define KVM_VM_MIPS_VZ 1
739
740#define KVM_S390_SIE_PAGE_OFFSET 1
741
742/*
743 * ioctls for /dev/kvm fds:
744 */
745#define KVM_GET_API_VERSION _IO(KVMIO, 0x00)
746#define KVM_CREATE_VM _IO(KVMIO, 0x01) /* returns a VM fd */
747#define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 0x02, struct kvm_msr_list)
748
749#define KVM_S390_ENABLE_SIE _IO(KVMIO, 0x06)
750/*
751 * Check if a kvm extension is available. Argument is extension number,
752 * return is 1 (yes) or 0 (no, sorry).
753 */
754#define KVM_CHECK_EXTENSION _IO(KVMIO, 0x03)
755/*
756 * Get size for mmap(vcpu_fd)
757 */
758#define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04) /* in bytes */
759#define KVM_GET_SUPPORTED_CPUID _IOWR(KVMIO, 0x05, struct kvm_cpuid2)
760#define KVM_TRACE_ENABLE __KVM_DEPRECATED_MAIN_W_0x06
761#define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07
762#define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08
763#define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2)
764
765/*
766 * Extension capability list.
767 */
768#define KVM_CAP_IRQCHIP 0
769#define KVM_CAP_HLT 1
770#define KVM_CAP_MMU_SHADOW_CACHE_CONTROL 2
771#define KVM_CAP_USER_MEMORY 3
772#define KVM_CAP_SET_TSS_ADDR 4
773#define KVM_CAP_VAPIC 6
774#define KVM_CAP_EXT_CPUID 7
775#define KVM_CAP_CLOCKSOURCE 8
776#define KVM_CAP_NR_VCPUS 9 /* returns recommended max vcpus per vm */
777#define KVM_CAP_NR_MEMSLOTS 10 /* returns max memory slots per vm */
778#define KVM_CAP_PIT 11
779#define KVM_CAP_NOP_IO_DELAY 12
780#define KVM_CAP_PV_MMU 13
781#define KVM_CAP_MP_STATE 14
782#define KVM_CAP_COALESCED_MMIO 15
783#define KVM_CAP_SYNC_MMU 16 /* Changes to host mmap are reflected in guest */
784#define KVM_CAP_IOMMU 18
785/* Bug in KVM_SET_USER_MEMORY_REGION fixed: */
786#define KVM_CAP_DESTROY_MEMORY_REGION_WORKS 21
787#define KVM_CAP_USER_NMI 22
788#ifdef __KVM_HAVE_GUEST_DEBUG
789#define KVM_CAP_SET_GUEST_DEBUG 23
790#endif
791#ifdef __KVM_HAVE_PIT
792#define KVM_CAP_REINJECT_CONTROL 24
793#endif
794#define KVM_CAP_IRQ_ROUTING 25
795#define KVM_CAP_IRQ_INJECT_STATUS 26
796#define KVM_CAP_ASSIGN_DEV_IRQ 29
797/* Another bug in KVM_SET_USER_MEMORY_REGION fixed: */
798#define KVM_CAP_JOIN_MEMORY_REGIONS_WORKS 30
799#ifdef __KVM_HAVE_MCE
800#define KVM_CAP_MCE 31
801#endif
802#define KVM_CAP_IRQFD 32
803#ifdef __KVM_HAVE_PIT
804#define KVM_CAP_PIT2 33
805#endif
806#define KVM_CAP_SET_BOOT_CPU_ID 34
807#ifdef __KVM_HAVE_PIT_STATE2
808#define KVM_CAP_PIT_STATE2 35
809#endif
810#define KVM_CAP_IOEVENTFD 36
811#define KVM_CAP_SET_IDENTITY_MAP_ADDR 37
812#ifdef __KVM_HAVE_XEN_HVM
813#define KVM_CAP_XEN_HVM 38
814#endif
815#define KVM_CAP_ADJUST_CLOCK 39
816#define KVM_CAP_INTERNAL_ERROR_DATA 40
817#ifdef __KVM_HAVE_VCPU_EVENTS
818#define KVM_CAP_VCPU_EVENTS 41
819#endif
820#define KVM_CAP_S390_PSW 42
821#define KVM_CAP_PPC_SEGSTATE 43
822#define KVM_CAP_HYPERV 44
823#define KVM_CAP_HYPERV_VAPIC 45
824#define KVM_CAP_HYPERV_SPIN 46
825#define KVM_CAP_PCI_SEGMENT 47
826#define KVM_CAP_PPC_PAIRED_SINGLES 48
827#define KVM_CAP_INTR_SHADOW 49
828#ifdef __KVM_HAVE_DEBUGREGS
829#define KVM_CAP_DEBUGREGS 50
830#endif
831#define KVM_CAP_X86_ROBUST_SINGLESTEP 51
832#define KVM_CAP_PPC_OSI 52
833#define KVM_CAP_PPC_UNSET_IRQ 53
834#define KVM_CAP_ENABLE_CAP 54
835#ifdef __KVM_HAVE_XSAVE
836#define KVM_CAP_XSAVE 55
837#endif
838#ifdef __KVM_HAVE_XCRS
839#define KVM_CAP_XCRS 56
840#endif
841#define KVM_CAP_PPC_GET_PVINFO 57
842#define KVM_CAP_PPC_IRQ_LEVEL 58
843#define KVM_CAP_ASYNC_PF 59
844#define KVM_CAP_TSC_CONTROL 60
845#define KVM_CAP_GET_TSC_KHZ 61
846#define KVM_CAP_PPC_BOOKE_SREGS 62
847#define KVM_CAP_SPAPR_TCE 63
848#define KVM_CAP_PPC_SMT 64
849#define KVM_CAP_PPC_RMA 65
850#define KVM_CAP_MAX_VCPUS 66 /* returns max vcpus per vm */
851#define KVM_CAP_PPC_HIOR 67
852#define KVM_CAP_PPC_PAPR 68
853#define KVM_CAP_SW_TLB 69
854#define KVM_CAP_ONE_REG 70
855#define KVM_CAP_S390_GMAP 71
856#define KVM_CAP_TSC_DEADLINE_TIMER 72
857#define KVM_CAP_S390_UCONTROL 73
858#define KVM_CAP_SYNC_REGS 74
859#define KVM_CAP_PCI_2_3 75
860#define KVM_CAP_KVMCLOCK_CTRL 76
861#define KVM_CAP_SIGNAL_MSI 77
862#define KVM_CAP_PPC_GET_SMMU_INFO 78
863#define KVM_CAP_S390_COW 79
864#define KVM_CAP_PPC_ALLOC_HTAB 80
865#define KVM_CAP_READONLY_MEM 81
866#define KVM_CAP_IRQFD_RESAMPLE 82
867#define KVM_CAP_PPC_BOOKE_WATCHDOG 83
868#define KVM_CAP_PPC_HTAB_FD 84
869#define KVM_CAP_S390_CSS_SUPPORT 85
870#define KVM_CAP_PPC_EPR 86
871#define KVM_CAP_ARM_PSCI 87
872#define KVM_CAP_ARM_SET_DEVICE_ADDR 88
873#define KVM_CAP_DEVICE_CTRL 89
874#define KVM_CAP_IRQ_MPIC 90
875#define KVM_CAP_PPC_RTAS 91
876#define KVM_CAP_IRQ_XICS 92
877#define KVM_CAP_ARM_EL1_32BIT 93
878#define KVM_CAP_SPAPR_MULTITCE 94
879#define KVM_CAP_EXT_EMUL_CPUID 95
880#define KVM_CAP_HYPERV_TIME 96
881#define KVM_CAP_IOAPIC_POLARITY_IGNORED 97
882#define KVM_CAP_ENABLE_CAP_VM 98
883#define KVM_CAP_S390_IRQCHIP 99
884#define KVM_CAP_IOEVENTFD_NO_LENGTH 100
885#define KVM_CAP_VM_ATTRIBUTES 101
886#define KVM_CAP_ARM_PSCI_0_2 102
887#define KVM_CAP_PPC_FIXUP_HCALL 103
888#define KVM_CAP_PPC_ENABLE_HCALL 104
889#define KVM_CAP_CHECK_EXTENSION_VM 105
890#define KVM_CAP_S390_USER_SIGP 106
891#define KVM_CAP_S390_VECTOR_REGISTERS 107
892#define KVM_CAP_S390_MEM_OP 108
893#define KVM_CAP_S390_USER_STSI 109
894#define KVM_CAP_S390_SKEYS 110
895#define KVM_CAP_MIPS_FPU 111
896#define KVM_CAP_MIPS_MSA 112
897#define KVM_CAP_S390_INJECT_IRQ 113
898#define KVM_CAP_S390_IRQ_STATE 114
899#define KVM_CAP_PPC_HWRNG 115
900#define KVM_CAP_DISABLE_QUIRKS 116
901#define KVM_CAP_X86_SMM 117
902#define KVM_CAP_MULTI_ADDRESS_SPACE 118
903#define KVM_CAP_GUEST_DEBUG_HW_BPS 119
904#define KVM_CAP_GUEST_DEBUG_HW_WPS 120
905#define KVM_CAP_SPLIT_IRQCHIP 121
906#define KVM_CAP_IOEVENTFD_ANY_LENGTH 122
907#define KVM_CAP_HYPERV_SYNIC 123
908#define KVM_CAP_S390_RI 124
909#define KVM_CAP_SPAPR_TCE_64 125
910#define KVM_CAP_ARM_PMU_V3 126
911#define KVM_CAP_VCPU_ATTRIBUTES 127
912#define KVM_CAP_MAX_VCPU_ID 128
913#define KVM_CAP_X2APIC_API 129
914#define KVM_CAP_S390_USER_INSTR0 130
915#define KVM_CAP_MSI_DEVID 131
916#define KVM_CAP_PPC_HTM 132
917#define KVM_CAP_SPAPR_RESIZE_HPT 133
918#define KVM_CAP_PPC_MMU_RADIX 134
919#define KVM_CAP_PPC_MMU_HASH_V3 135
920#define KVM_CAP_IMMEDIATE_EXIT 136
921#define KVM_CAP_MIPS_VZ 137
922#define KVM_CAP_MIPS_TE 138
923#define KVM_CAP_MIPS_64BIT 139
924#define KVM_CAP_S390_GS 140
925#define KVM_CAP_S390_AIS 141
926#define KVM_CAP_SPAPR_TCE_VFIO 142
927#define KVM_CAP_X86_GUEST_MWAIT 143
928#define KVM_CAP_ARM_USER_IRQ 144
929#define KVM_CAP_S390_CMMA_MIGRATION 145
930#define KVM_CAP_PPC_FWNMI 146
931#define KVM_CAP_PPC_SMT_POSSIBLE 147
932#define KVM_CAP_HYPERV_SYNIC2 148
933#define KVM_CAP_HYPERV_VP_INDEX 149
934
935#ifdef KVM_CAP_IRQ_ROUTING
936
937struct kvm_irq_routing_irqchip {
938 __u32 irqchip;
939 __u32 pin;
940};
941
942struct kvm_irq_routing_msi {
943 __u32 address_lo;
944 __u32 address_hi;
945 __u32 data;
946 union {
947 __u32 pad;
948 __u32 devid;
949 };
950};
951
952struct kvm_irq_routing_s390_adapter {
953 __u64 ind_addr;
954 __u64 summary_addr;
955 __u64 ind_offset;
956 __u32 summary_offset;
957 __u32 adapter_id;
958};
959
960struct kvm_irq_routing_hv_sint {
961 __u32 vcpu;
962 __u32 sint;
963};
964
965/* gsi routing entry types */
966#define KVM_IRQ_ROUTING_IRQCHIP 1
967#define KVM_IRQ_ROUTING_MSI 2
968#define KVM_IRQ_ROUTING_S390_ADAPTER 3
969#define KVM_IRQ_ROUTING_HV_SINT 4
970
971struct kvm_irq_routing_entry {
972 __u32 gsi;
973 __u32 type;
974 __u32 flags;
975 __u32 pad;
976 union {
977 struct kvm_irq_routing_irqchip irqchip;
978 struct kvm_irq_routing_msi msi;
979 struct kvm_irq_routing_s390_adapter adapter;
980 struct kvm_irq_routing_hv_sint hv_sint;
981 __u32 pad[8];
982 } u;
983};
984
985struct kvm_irq_routing {
986 __u32 nr;
987 __u32 flags;
988 struct kvm_irq_routing_entry entries[0];
989};
990
991#endif
992
993#ifdef KVM_CAP_MCE
994/* x86 MCE */
995struct kvm_x86_mce {
996 __u64 status;
997 __u64 addr;
998 __u64 misc;
999 __u64 mcg_status;
1000 __u8 bank;
1001 __u8 pad1[7];
1002 __u64 pad2[3];
1003};
1004#endif
1005
1006#ifdef KVM_CAP_XEN_HVM
1007struct kvm_xen_hvm_config {
1008 __u32 flags;
1009 __u32 msr;
1010 __u64 blob_addr_32;
1011 __u64 blob_addr_64;
1012 __u8 blob_size_32;
1013 __u8 blob_size_64;
1014 __u8 pad2[30];
1015};
1016#endif
1017
1018#define KVM_IRQFD_FLAG_DEASSIGN (1 << 0)
1019/*
1020 * Available with KVM_CAP_IRQFD_RESAMPLE
1021 *
1022 * KVM_IRQFD_FLAG_RESAMPLE indicates resamplefd is valid and specifies
1023 * the irqfd to operate in resampling mode for level triggered interrupt
1024 * emulation. See Documentation/virtual/kvm/api.txt.
1025 */
1026#define KVM_IRQFD_FLAG_RESAMPLE (1 << 1)
1027
1028struct kvm_irqfd {
1029 __u32 fd;
1030 __u32 gsi;
1031 __u32 flags;
1032 __u32 resamplefd;
1033 __u8 pad[16];
1034};
1035
1036/* For KVM_CAP_ADJUST_CLOCK */
1037
1038/* Do not use 1, KVM_CHECK_EXTENSION returned it before we had flags. */
1039#define KVM_CLOCK_TSC_STABLE 2
1040
1041struct kvm_clock_data {
1042 __u64 clock;
1043 __u32 flags;
1044 __u32 pad[9];
1045};
1046
1047/* For KVM_CAP_SW_TLB */
1048
1049#define KVM_MMU_FSL_BOOKE_NOHV 0
1050#define KVM_MMU_FSL_BOOKE_HV 1
1051
1052struct kvm_config_tlb {
1053 __u64 params;
1054 __u64 array;
1055 __u32 mmu_type;
1056 __u32 array_len;
1057};
1058
1059struct kvm_dirty_tlb {
1060 __u64 bitmap;
1061 __u32 num_dirty;
1062};
1063
1064/* Available with KVM_CAP_ONE_REG */
1065
1066#define KVM_REG_ARCH_MASK 0xff00000000000000ULL
1067#define KVM_REG_GENERIC 0x0000000000000000ULL
1068
1069/*
1070 * Architecture specific registers are to be defined in arch headers and
1071 * ORed with the arch identifier.
1072 */
1073#define KVM_REG_PPC 0x1000000000000000ULL
1074#define KVM_REG_X86 0x2000000000000000ULL
1075#define KVM_REG_IA64 0x3000000000000000ULL
1076#define KVM_REG_ARM 0x4000000000000000ULL
1077#define KVM_REG_S390 0x5000000000000000ULL
1078#define KVM_REG_ARM64 0x6000000000000000ULL
1079#define KVM_REG_MIPS 0x7000000000000000ULL
1080
1081#define KVM_REG_SIZE_SHIFT 52
1082#define KVM_REG_SIZE_MASK 0x00f0000000000000ULL
1083#define KVM_REG_SIZE_U8 0x0000000000000000ULL
1084#define KVM_REG_SIZE_U16 0x0010000000000000ULL
1085#define KVM_REG_SIZE_U32 0x0020000000000000ULL
1086#define KVM_REG_SIZE_U64 0x0030000000000000ULL
1087#define KVM_REG_SIZE_U128 0x0040000000000000ULL
1088#define KVM_REG_SIZE_U256 0x0050000000000000ULL
1089#define KVM_REG_SIZE_U512 0x0060000000000000ULL
1090#define KVM_REG_SIZE_U1024 0x0070000000000000ULL
1091
1092struct kvm_reg_list {
1093 __u64 n; /* number of regs */
1094 __u64 reg[0];
1095};
1096
1097struct kvm_one_reg {
1098 __u64 id;
1099 __u64 addr;
1100};
1101
1102#define KVM_MSI_VALID_DEVID (1U << 0)
1103struct kvm_msi {
1104 __u32 address_lo;
1105 __u32 address_hi;
1106 __u32 data;
1107 __u32 flags;
1108 __u32 devid;
1109 __u8 pad[12];
1110};
1111
1112struct kvm_arm_device_addr {
1113 __u64 id;
1114 __u64 addr;
1115};
1116
1117/*
1118 * Device control API, available with KVM_CAP_DEVICE_CTRL
1119 */
1120#define KVM_CREATE_DEVICE_TEST 1
1121
1122struct kvm_create_device {
1123 __u32 type; /* in: KVM_DEV_TYPE_xxx */
1124 __u32 fd; /* out: device handle */
1125 __u32 flags; /* in: KVM_CREATE_DEVICE_xxx */
1126};
1127
1128struct kvm_device_attr {
1129 __u32 flags; /* no flags currently defined */
1130 __u32 group; /* device-defined */
1131 __u64 attr; /* group-defined */
1132 __u64 addr; /* userspace address of attr data */
1133};
1134
1135#define KVM_DEV_VFIO_GROUP 1
1136#define KVM_DEV_VFIO_GROUP_ADD 1
1137#define KVM_DEV_VFIO_GROUP_DEL 2
1138#define KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE 3
1139
1140enum kvm_device_type {
1141 KVM_DEV_TYPE_FSL_MPIC_20 = 1,
1142#define KVM_DEV_TYPE_FSL_MPIC_20 KVM_DEV_TYPE_FSL_MPIC_20
1143 KVM_DEV_TYPE_FSL_MPIC_42,
1144#define KVM_DEV_TYPE_FSL_MPIC_42 KVM_DEV_TYPE_FSL_MPIC_42
1145 KVM_DEV_TYPE_XICS,
1146#define KVM_DEV_TYPE_XICS KVM_DEV_TYPE_XICS
1147 KVM_DEV_TYPE_VFIO,
1148#define KVM_DEV_TYPE_VFIO KVM_DEV_TYPE_VFIO
1149 KVM_DEV_TYPE_ARM_VGIC_V2,
1150#define KVM_DEV_TYPE_ARM_VGIC_V2 KVM_DEV_TYPE_ARM_VGIC_V2
1151 KVM_DEV_TYPE_FLIC,
1152#define KVM_DEV_TYPE_FLIC KVM_DEV_TYPE_FLIC
1153 KVM_DEV_TYPE_ARM_VGIC_V3,
1154#define KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_V3
1155 KVM_DEV_TYPE_ARM_VGIC_ITS,
1156#define KVM_DEV_TYPE_ARM_VGIC_ITS KVM_DEV_TYPE_ARM_VGIC_ITS
1157 KVM_DEV_TYPE_MAX,
1158};
1159
1160struct kvm_vfio_spapr_tce {
1161 __s32 groupfd;
1162 __s32 tablefd;
1163};
1164
1165/*
1166 * ioctls for VM fds
1167 */
1168#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 0x40, struct kvm_memory_region)
1169/*
1170 * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns
1171 * a vcpu fd.
1172 */
1173#define KVM_CREATE_VCPU _IO(KVMIO, 0x41)
1174#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log)
1175/* KVM_SET_MEMORY_ALIAS is obsolete: */
1176#define KVM_SET_MEMORY_ALIAS _IOW(KVMIO, 0x43, struct kvm_memory_alias)
1177#define KVM_SET_NR_MMU_PAGES _IO(KVMIO, 0x44)
1178#define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45)
1179#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46, \
1180 struct kvm_userspace_memory_region)
1181#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)
1182#define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64)
1183
1184/* enable ucontrol for s390 */
1185struct kvm_s390_ucas_mapping {
1186 __u64 user_addr;
1187 __u64 vcpu_addr;
1188 __u64 length;
1189};
1190#define KVM_S390_UCAS_MAP _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping)
1191#define KVM_S390_UCAS_UNMAP _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping)
1192#define KVM_S390_VCPU_FAULT _IOW(KVMIO, 0x52, unsigned long)
1193
1194/* Device model IOC */
1195#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)
1196#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
1197#define KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip)
1198#define KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip)
1199#define KVM_CREATE_PIT _IO(KVMIO, 0x64)
1200#define KVM_GET_PIT _IOWR(KVMIO, 0x65, struct kvm_pit_state)
1201#define KVM_SET_PIT _IOR(KVMIO, 0x66, struct kvm_pit_state)
1202#define KVM_IRQ_LINE_STATUS _IOWR(KVMIO, 0x67, struct kvm_irq_level)
1203#define KVM_REGISTER_COALESCED_MMIO \
1204 _IOW(KVMIO, 0x67, struct kvm_coalesced_mmio_zone)
1205#define KVM_UNREGISTER_COALESCED_MMIO \
1206 _IOW(KVMIO, 0x68, struct kvm_coalesced_mmio_zone)
1207#define KVM_ASSIGN_PCI_DEVICE _IOR(KVMIO, 0x69, \
1208 struct kvm_assigned_pci_dev)
1209#define KVM_SET_GSI_ROUTING _IOW(KVMIO, 0x6a, struct kvm_irq_routing)
1210/* deprecated, replaced by KVM_ASSIGN_DEV_IRQ */
1211#define KVM_ASSIGN_IRQ __KVM_DEPRECATED_VM_R_0x70
1212#define KVM_ASSIGN_DEV_IRQ _IOW(KVMIO, 0x70, struct kvm_assigned_irq)
1213#define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71)
1214#define KVM_DEASSIGN_PCI_DEVICE _IOW(KVMIO, 0x72, \
1215 struct kvm_assigned_pci_dev)
1216#define KVM_ASSIGN_SET_MSIX_NR _IOW(KVMIO, 0x73, \
1217 struct kvm_assigned_msix_nr)
1218#define KVM_ASSIGN_SET_MSIX_ENTRY _IOW(KVMIO, 0x74, \
1219 struct kvm_assigned_msix_entry)
1220#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq)
1221#define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd)
1222#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config)
1223#define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78)
1224#define KVM_IOEVENTFD _IOW(KVMIO, 0x79, struct kvm_ioeventfd)
1225#define KVM_XEN_HVM_CONFIG _IOW(KVMIO, 0x7a, struct kvm_xen_hvm_config)
1226#define KVM_SET_CLOCK _IOW(KVMIO, 0x7b, struct kvm_clock_data)
1227#define KVM_GET_CLOCK _IOR(KVMIO, 0x7c, struct kvm_clock_data)
1228/* Available with KVM_CAP_PIT_STATE2 */
1229#define KVM_GET_PIT2 _IOR(KVMIO, 0x9f, struct kvm_pit_state2)
1230#define KVM_SET_PIT2 _IOW(KVMIO, 0xa0, struct kvm_pit_state2)
1231/* Available with KVM_CAP_PPC_GET_PVINFO */
1232#define KVM_PPC_GET_PVINFO _IOW(KVMIO, 0xa1, struct kvm_ppc_pvinfo)
1233/* Available with KVM_CAP_TSC_CONTROL */
1234#define KVM_SET_TSC_KHZ _IO(KVMIO, 0xa2)
1235#define KVM_GET_TSC_KHZ _IO(KVMIO, 0xa3)
1236/* Available with KVM_CAP_PCI_2_3 */
1237#define KVM_ASSIGN_SET_INTX_MASK _IOW(KVMIO, 0xa4, \
1238 struct kvm_assigned_pci_dev)
1239/* Available with KVM_CAP_SIGNAL_MSI */
1240#define KVM_SIGNAL_MSI _IOW(KVMIO, 0xa5, struct kvm_msi)
1241/* Available with KVM_CAP_PPC_GET_SMMU_INFO */
1242#define KVM_PPC_GET_SMMU_INFO _IOR(KVMIO, 0xa6, struct kvm_ppc_smmu_info)
1243/* Available with KVM_CAP_PPC_ALLOC_HTAB */
1244#define KVM_PPC_ALLOCATE_HTAB _IOWR(KVMIO, 0xa7, __u32)
1245#define KVM_CREATE_SPAPR_TCE _IOW(KVMIO, 0xa8, struct kvm_create_spapr_tce)
1246#define KVM_CREATE_SPAPR_TCE_64 _IOW(KVMIO, 0xa8, \
1247 struct kvm_create_spapr_tce_64)
1248/* Available with KVM_CAP_RMA */
1249#define KVM_ALLOCATE_RMA _IOR(KVMIO, 0xa9, struct kvm_allocate_rma)
1250/* Available with KVM_CAP_PPC_HTAB_FD */
1251#define KVM_PPC_GET_HTAB_FD _IOW(KVMIO, 0xaa, struct kvm_get_htab_fd)
1252/* Available with KVM_CAP_ARM_SET_DEVICE_ADDR */
1253#define KVM_ARM_SET_DEVICE_ADDR _IOW(KVMIO, 0xab, struct kvm_arm_device_addr)
1254/* Available with KVM_CAP_PPC_RTAS */
1255#define KVM_PPC_RTAS_DEFINE_TOKEN _IOW(KVMIO, 0xac, struct kvm_rtas_token_args)
1256/* Available with KVM_CAP_SPAPR_RESIZE_HPT */
1257#define KVM_PPC_RESIZE_HPT_PREPARE _IOR(KVMIO, 0xad, struct kvm_ppc_resize_hpt)
1258#define KVM_PPC_RESIZE_HPT_COMMIT _IOR(KVMIO, 0xae, struct kvm_ppc_resize_hpt)
1259/* Available with KVM_CAP_PPC_RADIX_MMU or KVM_CAP_PPC_HASH_MMU_V3 */
1260#define KVM_PPC_CONFIGURE_V3_MMU _IOW(KVMIO, 0xaf, struct kvm_ppc_mmuv3_cfg)
1261/* Available with KVM_CAP_PPC_RADIX_MMU */
1262#define KVM_PPC_GET_RMMU_INFO _IOW(KVMIO, 0xb0, struct kvm_ppc_rmmu_info)
1263
1264/* ioctl for vm fd */
1265#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)
1266
1267/* ioctls for fds returned by KVM_CREATE_DEVICE */
1268#define KVM_SET_DEVICE_ATTR _IOW(KVMIO, 0xe1, struct kvm_device_attr)
1269#define KVM_GET_DEVICE_ATTR _IOW(KVMIO, 0xe2, struct kvm_device_attr)
1270#define KVM_HAS_DEVICE_ATTR _IOW(KVMIO, 0xe3, struct kvm_device_attr)
1271
1272/*
1273 * ioctls for vcpu fds
1274 */
1275#define KVM_RUN _IO(KVMIO, 0x80)
1276#define KVM_GET_REGS _IOR(KVMIO, 0x81, struct kvm_regs)
1277#define KVM_SET_REGS _IOW(KVMIO, 0x82, struct kvm_regs)
1278#define KVM_GET_SREGS _IOR(KVMIO, 0x83, struct kvm_sregs)
1279#define KVM_SET_SREGS _IOW(KVMIO, 0x84, struct kvm_sregs)
1280#define KVM_TRANSLATE _IOWR(KVMIO, 0x85, struct kvm_translation)
1281#define KVM_INTERRUPT _IOW(KVMIO, 0x86, struct kvm_interrupt)
1282/* KVM_DEBUG_GUEST is no longer supported, use KVM_SET_GUEST_DEBUG instead */
1283#define KVM_DEBUG_GUEST __KVM_DEPRECATED_VCPU_W_0x87
1284#define KVM_GET_MSRS _IOWR(KVMIO, 0x88, struct kvm_msrs)
1285#define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs)
1286#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid)
1287#define KVM_SET_SIGNAL_MASK _IOW(KVMIO, 0x8b, struct kvm_signal_mask)
1288#define KVM_GET_FPU _IOR(KVMIO, 0x8c, struct kvm_fpu)
1289#define KVM_SET_FPU _IOW(KVMIO, 0x8d, struct kvm_fpu)
1290#define KVM_GET_LAPIC _IOR(KVMIO, 0x8e, struct kvm_lapic_state)
1291#define KVM_SET_LAPIC _IOW(KVMIO, 0x8f, struct kvm_lapic_state)
1292#define KVM_SET_CPUID2 _IOW(KVMIO, 0x90, struct kvm_cpuid2)
1293#define KVM_GET_CPUID2 _IOWR(KVMIO, 0x91, struct kvm_cpuid2)
1294/* Available with KVM_CAP_VAPIC */
1295#define KVM_TPR_ACCESS_REPORTING _IOWR(KVMIO, 0x92, struct kvm_tpr_access_ctl)
1296/* Available with KVM_CAP_VAPIC */
1297#define KVM_SET_VAPIC_ADDR _IOW(KVMIO, 0x93, struct kvm_vapic_addr)
1298/* valid for virtual machine (for floating interrupt)_and_ vcpu */
1299#define KVM_S390_INTERRUPT _IOW(KVMIO, 0x94, struct kvm_s390_interrupt)
1300/* store status for s390 */
1301#define KVM_S390_STORE_STATUS_NOADDR (-1ul)
1302#define KVM_S390_STORE_STATUS_PREFIXED (-2ul)
1303#define KVM_S390_STORE_STATUS _IOW(KVMIO, 0x95, unsigned long)
1304/* initial ipl psw for s390 */
1305#define KVM_S390_SET_INITIAL_PSW _IOW(KVMIO, 0x96, struct kvm_s390_psw)
1306/* initial reset for s390 */
1307#define KVM_S390_INITIAL_RESET _IO(KVMIO, 0x97)
1308#define KVM_GET_MP_STATE _IOR(KVMIO, 0x98, struct kvm_mp_state)
1309#define KVM_SET_MP_STATE _IOW(KVMIO, 0x99, struct kvm_mp_state)
1310/* Available with KVM_CAP_USER_NMI */
1311#define KVM_NMI _IO(KVMIO, 0x9a)
1312/* Available with KVM_CAP_SET_GUEST_DEBUG */
1313#define KVM_SET_GUEST_DEBUG _IOW(KVMIO, 0x9b, struct kvm_guest_debug)
1314/* MCE for x86 */
1315#define KVM_X86_SETUP_MCE _IOW(KVMIO, 0x9c, __u64)
1316#define KVM_X86_GET_MCE_CAP_SUPPORTED _IOR(KVMIO, 0x9d, __u64)
1317#define KVM_X86_SET_MCE _IOW(KVMIO, 0x9e, struct kvm_x86_mce)
1318/* Available with KVM_CAP_VCPU_EVENTS */
1319#define KVM_GET_VCPU_EVENTS _IOR(KVMIO, 0x9f, struct kvm_vcpu_events)
1320#define KVM_SET_VCPU_EVENTS _IOW(KVMIO, 0xa0, struct kvm_vcpu_events)
1321/* Available with KVM_CAP_DEBUGREGS */
1322#define KVM_GET_DEBUGREGS _IOR(KVMIO, 0xa1, struct kvm_debugregs)
1323#define KVM_SET_DEBUGREGS _IOW(KVMIO, 0xa2, struct kvm_debugregs)
1324/*
1325 * vcpu version available with KVM_ENABLE_CAP
1326 * vm version available with KVM_CAP_ENABLE_CAP_VM
1327 */
1328#define KVM_ENABLE_CAP _IOW(KVMIO, 0xa3, struct kvm_enable_cap)
1329/* Available with KVM_CAP_XSAVE */
1330#define KVM_GET_XSAVE _IOR(KVMIO, 0xa4, struct kvm_xsave)
1331#define KVM_SET_XSAVE _IOW(KVMIO, 0xa5, struct kvm_xsave)
1332/* Available with KVM_CAP_XCRS */
1333#define KVM_GET_XCRS _IOR(KVMIO, 0xa6, struct kvm_xcrs)
1334#define KVM_SET_XCRS _IOW(KVMIO, 0xa7, struct kvm_xcrs)
1335/* Available with KVM_CAP_SW_TLB */
1336#define KVM_DIRTY_TLB _IOW(KVMIO, 0xaa, struct kvm_dirty_tlb)
1337/* Available with KVM_CAP_ONE_REG */
1338#define KVM_GET_ONE_REG _IOW(KVMIO, 0xab, struct kvm_one_reg)
1339#define KVM_SET_ONE_REG _IOW(KVMIO, 0xac, struct kvm_one_reg)
1340/* VM is being stopped by host */
1341#define KVM_KVMCLOCK_CTRL _IO(KVMIO, 0xad)
1342#define KVM_ARM_VCPU_INIT _IOW(KVMIO, 0xae, struct kvm_vcpu_init)
1343#define KVM_ARM_PREFERRED_TARGET _IOR(KVMIO, 0xaf, struct kvm_vcpu_init)
1344#define KVM_GET_REG_LIST _IOWR(KVMIO, 0xb0, struct kvm_reg_list)
1345/* Available with KVM_CAP_S390_MEM_OP */
1346#define KVM_S390_MEM_OP _IOW(KVMIO, 0xb1, struct kvm_s390_mem_op)
1347/* Available with KVM_CAP_S390_SKEYS */
1348#define KVM_S390_GET_SKEYS _IOW(KVMIO, 0xb2, struct kvm_s390_skeys)
1349#define KVM_S390_SET_SKEYS _IOW(KVMIO, 0xb3, struct kvm_s390_skeys)
1350/* Available with KVM_CAP_S390_INJECT_IRQ */
1351#define KVM_S390_IRQ _IOW(KVMIO, 0xb4, struct kvm_s390_irq)
1352/* Available with KVM_CAP_S390_IRQ_STATE */
1353#define KVM_S390_SET_IRQ_STATE _IOW(KVMIO, 0xb5, struct kvm_s390_irq_state)
1354#define KVM_S390_GET_IRQ_STATE _IOW(KVMIO, 0xb6, struct kvm_s390_irq_state)
1355/* Available with KVM_CAP_X86_SMM */
1356#define KVM_SMI _IO(KVMIO, 0xb7)
1357/* Available with KVM_CAP_S390_CMMA_MIGRATION */
1358#define KVM_S390_GET_CMMA_BITS _IOWR(KVMIO, 0xb8, struct kvm_s390_cmma_log)
1359#define KVM_S390_SET_CMMA_BITS _IOW(KVMIO, 0xb9, struct kvm_s390_cmma_log)
1360
1361#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
1362#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
1363#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
1364
1365struct kvm_assigned_pci_dev {
1366 __u32 assigned_dev_id;
1367 __u32 busnr;
1368 __u32 devfn;
1369 __u32 flags;
1370 __u32 segnr;
1371 union {
1372 __u32 reserved[11];
1373 };
1374};
1375
1376#define KVM_DEV_IRQ_HOST_INTX (1 << 0)
1377#define KVM_DEV_IRQ_HOST_MSI (1 << 1)
1378#define KVM_DEV_IRQ_HOST_MSIX (1 << 2)
1379
1380#define KVM_DEV_IRQ_GUEST_INTX (1 << 8)
1381#define KVM_DEV_IRQ_GUEST_MSI (1 << 9)
1382#define KVM_DEV_IRQ_GUEST_MSIX (1 << 10)
1383
1384#define KVM_DEV_IRQ_HOST_MASK 0x00ff
1385#define KVM_DEV_IRQ_GUEST_MASK 0xff00
1386
1387struct kvm_assigned_irq {
1388 __u32 assigned_dev_id;
1389 __u32 host_irq; /* ignored (legacy field) */
1390 __u32 guest_irq;
1391 __u32 flags;
1392 union {
1393 __u32 reserved[12];
1394 };
1395};
1396
1397struct kvm_assigned_msix_nr {
1398 __u32 assigned_dev_id;
1399 __u16 entry_nr;
1400 __u16 padding;
1401};
1402
1403#define KVM_MAX_MSIX_PER_DEV 256
1404struct kvm_assigned_msix_entry {
1405 __u32 assigned_dev_id;
1406 __u32 gsi;
1407 __u16 entry; /* The index of entry in the MSI-X table */
1408 __u16 padding[3];
1409};
1410
1411#define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0)
1412#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1)
1413
1414/* Available with KVM_CAP_ARM_USER_IRQ */
1415
1416/* Bits for run->s.regs.device_irq_level */
1417#define KVM_ARM_DEV_EL1_VTIMER (1 << 0)
1418#define KVM_ARM_DEV_EL1_PTIMER (1 << 1)
1419#define KVM_ARM_DEV_PMU (1 << 2)
1420
1421#endif /* __LINUX_KVM_H */
diff --git a/tools/include/uapi/linux/mman.h b/tools/include/uapi/linux/mman.h
index 81d8edf11789..bfd5938fede6 100644
--- a/tools/include/uapi/linux/mman.h
+++ b/tools/include/uapi/linux/mman.h
@@ -1,7 +1,9 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _UAPI_LINUX_MMAN_H 2#ifndef _UAPI_LINUX_MMAN_H
2#define _UAPI_LINUX_MMAN_H 3#define _UAPI_LINUX_MMAN_H
3 4
4#include <uapi/asm/mman.h> 5#include <asm/mman.h>
6#include <asm-generic/hugetlb_encode.h>
5 7
6#define MREMAP_MAYMOVE 1 8#define MREMAP_MAYMOVE 1
7#define MREMAP_FIXED 2 9#define MREMAP_FIXED 2
@@ -10,4 +12,25 @@
10#define OVERCOMMIT_ALWAYS 1 12#define OVERCOMMIT_ALWAYS 1
11#define OVERCOMMIT_NEVER 2 13#define OVERCOMMIT_NEVER 2
12 14
15/*
16 * Huge page size encoding when MAP_HUGETLB is specified, and a huge page
17 * size other than the default is desired. See hugetlb_encode.h.
18 * All known huge page size encodings are provided here. It is the
19 * responsibility of the application to know which sizes are supported on
20 * the running system. See mmap(2) man page for details.
21 */
22#define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
23#define MAP_HUGE_MASK HUGETLB_FLAG_ENCODE_MASK
24
25#define MAP_HUGE_64KB HUGETLB_FLAG_ENCODE_64KB
26#define MAP_HUGE_512KB HUGETLB_FLAG_ENCODE_512KB
27#define MAP_HUGE_1MB HUGETLB_FLAG_ENCODE_1MB
28#define MAP_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB
29#define MAP_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB
30#define MAP_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB
31#define MAP_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB
32#define MAP_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB
33#define MAP_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB
34#define MAP_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB
35
13#endif /* _UAPI_LINUX_MMAN_H */ 36#endif /* _UAPI_LINUX_MMAN_H */
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index b1c0b187acfe..362493a2f950 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1/* 2/*
2 * Performance events: 3 * Performance events:
3 * 4 *
@@ -139,8 +140,9 @@ enum perf_event_sample_format {
139 PERF_SAMPLE_IDENTIFIER = 1U << 16, 140 PERF_SAMPLE_IDENTIFIER = 1U << 16,
140 PERF_SAMPLE_TRANSACTION = 1U << 17, 141 PERF_SAMPLE_TRANSACTION = 1U << 17,
141 PERF_SAMPLE_REGS_INTR = 1U << 18, 142 PERF_SAMPLE_REGS_INTR = 1U << 18,
143 PERF_SAMPLE_PHYS_ADDR = 1U << 19,
142 144
143 PERF_SAMPLE_MAX = 1U << 19, /* non-ABI */ 145 PERF_SAMPLE_MAX = 1U << 20, /* non-ABI */
144}; 146};
145 147
146/* 148/*
@@ -174,6 +176,8 @@ enum perf_branch_sample_type_shift {
174 PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 14, /* no flags */ 176 PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 14, /* no flags */
175 PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 15, /* no cycles */ 177 PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 15, /* no cycles */
176 178
179 PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 16, /* save branch type */
180
177 PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */ 181 PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */
178}; 182};
179 183
@@ -198,9 +202,30 @@ enum perf_branch_sample_type {
198 PERF_SAMPLE_BRANCH_NO_FLAGS = 1U << PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT, 202 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, 203 PERF_SAMPLE_BRANCH_NO_CYCLES = 1U << PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT,
200 204
205 PERF_SAMPLE_BRANCH_TYPE_SAVE =
206 1U << PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT,
207
201 PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT, 208 PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT,
202}; 209};
203 210
211/*
212 * Common flow change classification
213 */
214enum {
215 PERF_BR_UNKNOWN = 0, /* unknown */
216 PERF_BR_COND = 1, /* conditional */
217 PERF_BR_UNCOND = 2, /* unconditional */
218 PERF_BR_IND = 3, /* indirect */
219 PERF_BR_CALL = 4, /* function call */
220 PERF_BR_IND_CALL = 5, /* indirect function call */
221 PERF_BR_RET = 6, /* function return */
222 PERF_BR_SYSCALL = 7, /* syscall */
223 PERF_BR_SYSRET = 8, /* syscall return */
224 PERF_BR_COND_CALL = 9, /* conditional function call */
225 PERF_BR_COND_RET = 10, /* conditional function return */
226 PERF_BR_MAX,
227};
228
204#define PERF_SAMPLE_BRANCH_PLM_ALL \ 229#define PERF_SAMPLE_BRANCH_PLM_ALL \
205 (PERF_SAMPLE_BRANCH_USER|\ 230 (PERF_SAMPLE_BRANCH_USER|\
206 PERF_SAMPLE_BRANCH_KERNEL|\ 231 PERF_SAMPLE_BRANCH_KERNEL|\
@@ -791,6 +816,7 @@ enum perf_event_type {
791 * { u64 transaction; } && PERF_SAMPLE_TRANSACTION 816 * { u64 transaction; } && PERF_SAMPLE_TRANSACTION
792 * { u64 abi; # enum perf_sample_regs_abi 817 * { u64 abi; # enum perf_sample_regs_abi
793 * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR 818 * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR
819 * { u64 phys_addr;} && PERF_SAMPLE_PHYS_ADDR
794 * }; 820 * };
795 */ 821 */
796 PERF_RECORD_SAMPLE = 9, 822 PERF_RECORD_SAMPLE = 9,
@@ -931,14 +957,20 @@ union perf_mem_data_src {
931 mem_snoop:5, /* snoop mode */ 957 mem_snoop:5, /* snoop mode */
932 mem_lock:2, /* lock instr */ 958 mem_lock:2, /* lock instr */
933 mem_dtlb:7, /* tlb access */ 959 mem_dtlb:7, /* tlb access */
934 mem_rsvd:31; 960 mem_lvl_num:4, /* memory hierarchy level number */
961 mem_remote:1, /* remote */
962 mem_snoopx:2, /* snoop mode, ext */
963 mem_rsvd:24;
935 }; 964 };
936}; 965};
937#elif defined(__BIG_ENDIAN_BITFIELD) 966#elif defined(__BIG_ENDIAN_BITFIELD)
938union perf_mem_data_src { 967union perf_mem_data_src {
939 __u64 val; 968 __u64 val;
940 struct { 969 struct {
941 __u64 mem_rsvd:31, 970 __u64 mem_rsvd:24,
971 mem_snoopx:2, /* snoop mode, ext */
972 mem_remote:1, /* remote */
973 mem_lvl_num:4, /* memory hierarchy level number */
942 mem_dtlb:7, /* tlb access */ 974 mem_dtlb:7, /* tlb access */
943 mem_lock:2, /* lock instr */ 975 mem_lock:2, /* lock instr */
944 mem_snoop:5, /* snoop mode */ 976 mem_snoop:5, /* snoop mode */
@@ -975,6 +1007,22 @@ union perf_mem_data_src {
975#define PERF_MEM_LVL_UNC 0x2000 /* Uncached memory */ 1007#define PERF_MEM_LVL_UNC 0x2000 /* Uncached memory */
976#define PERF_MEM_LVL_SHIFT 5 1008#define PERF_MEM_LVL_SHIFT 5
977 1009
1010#define PERF_MEM_REMOTE_REMOTE 0x01 /* Remote */
1011#define PERF_MEM_REMOTE_SHIFT 37
1012
1013#define PERF_MEM_LVLNUM_L1 0x01 /* L1 */
1014#define PERF_MEM_LVLNUM_L2 0x02 /* L2 */
1015#define PERF_MEM_LVLNUM_L3 0x03 /* L3 */
1016#define PERF_MEM_LVLNUM_L4 0x04 /* L4 */
1017/* 5-0xa available */
1018#define PERF_MEM_LVLNUM_ANY_CACHE 0x0b /* Any cache */
1019#define PERF_MEM_LVLNUM_LFB 0x0c /* LFB */
1020#define PERF_MEM_LVLNUM_RAM 0x0d /* RAM */
1021#define PERF_MEM_LVLNUM_PMEM 0x0e /* PMEM */
1022#define PERF_MEM_LVLNUM_NA 0x0f /* N/A */
1023
1024#define PERF_MEM_LVLNUM_SHIFT 33
1025
978/* snoop mode */ 1026/* snoop mode */
979#define PERF_MEM_SNOOP_NA 0x01 /* not available */ 1027#define PERF_MEM_SNOOP_NA 0x01 /* not available */
980#define PERF_MEM_SNOOP_NONE 0x02 /* no snoop */ 1028#define PERF_MEM_SNOOP_NONE 0x02 /* no snoop */
@@ -983,6 +1031,10 @@ union perf_mem_data_src {
983#define PERF_MEM_SNOOP_HITM 0x10 /* snoop hit modified */ 1031#define PERF_MEM_SNOOP_HITM 0x10 /* snoop hit modified */
984#define PERF_MEM_SNOOP_SHIFT 19 1032#define PERF_MEM_SNOOP_SHIFT 19
985 1033
1034#define PERF_MEM_SNOOPX_FWD 0x01 /* forward */
1035/* 1 free */
1036#define PERF_MEM_SNOOPX_SHIFT 37
1037
986/* locked instruction */ 1038/* locked instruction */
987#define PERF_MEM_LOCK_NA 0x01 /* not available */ 1039#define PERF_MEM_LOCK_NA 0x01 /* not available */
988#define PERF_MEM_LOCK_LOCKED 0x02 /* locked transaction */ 1040#define PERF_MEM_LOCK_LOCKED 0x02 /* locked transaction */
@@ -1015,6 +1067,7 @@ union perf_mem_data_src {
1015 * in_tx: running in a hardware transaction 1067 * in_tx: running in a hardware transaction
1016 * abort: aborting a hardware transaction 1068 * abort: aborting a hardware transaction
1017 * cycles: cycles from last branch (or 0 if not supported) 1069 * cycles: cycles from last branch (or 0 if not supported)
1070 * type: branch type
1018 */ 1071 */
1019struct perf_branch_entry { 1072struct perf_branch_entry {
1020 __u64 from; 1073 __u64 from;
@@ -1024,7 +1077,8 @@ struct perf_branch_entry {
1024 in_tx:1, /* in transaction */ 1077 in_tx:1, /* in transaction */
1025 abort:1, /* transaction abort */ 1078 abort:1, /* transaction abort */
1026 cycles:16, /* cycle count to last branch */ 1079 cycles:16, /* cycle count to last branch */
1027 reserved:44; 1080 type:4, /* branch type */
1081 reserved:40;
1028}; 1082};
1029 1083
1030#endif /* _UAPI_LINUX_PERF_EVENT_H */ 1084#endif /* _UAPI_LINUX_PERF_EVENT_H */
diff --git a/tools/include/uapi/linux/prctl.h b/tools/include/uapi/linux/prctl.h
new file mode 100644
index 000000000000..a8d0759a9e40
--- /dev/null
+++ b/tools/include/uapi/linux/prctl.h
@@ -0,0 +1,200 @@
1#ifndef _LINUX_PRCTL_H
2#define _LINUX_PRCTL_H
3
4#include <linux/types.h>
5
6/* Values to pass as first argument to prctl() */
7
8#define PR_SET_PDEATHSIG 1 /* Second arg is a signal */
9#define PR_GET_PDEATHSIG 2 /* Second arg is a ptr to return the signal */
10
11/* Get/set current->mm->dumpable */
12#define PR_GET_DUMPABLE 3
13#define PR_SET_DUMPABLE 4
14
15/* Get/set unaligned access control bits (if meaningful) */
16#define PR_GET_UNALIGN 5
17#define PR_SET_UNALIGN 6
18# define PR_UNALIGN_NOPRINT 1 /* silently fix up unaligned user accesses */
19# define PR_UNALIGN_SIGBUS 2 /* generate SIGBUS on unaligned user access */
20
21/* Get/set whether or not to drop capabilities on setuid() away from
22 * uid 0 (as per security/commoncap.c) */
23#define PR_GET_KEEPCAPS 7
24#define PR_SET_KEEPCAPS 8
25
26/* Get/set floating-point emulation control bits (if meaningful) */
27#define PR_GET_FPEMU 9
28#define PR_SET_FPEMU 10
29# define PR_FPEMU_NOPRINT 1 /* silently emulate fp operations accesses */
30# define PR_FPEMU_SIGFPE 2 /* don't emulate fp operations, send SIGFPE instead */
31
32/* Get/set floating-point exception mode (if meaningful) */
33#define PR_GET_FPEXC 11
34#define PR_SET_FPEXC 12
35# define PR_FP_EXC_SW_ENABLE 0x80 /* Use FPEXC for FP exception enables */
36# define PR_FP_EXC_DIV 0x010000 /* floating point divide by zero */
37# define PR_FP_EXC_OVF 0x020000 /* floating point overflow */
38# define PR_FP_EXC_UND 0x040000 /* floating point underflow */
39# define PR_FP_EXC_RES 0x080000 /* floating point inexact result */
40# define PR_FP_EXC_INV 0x100000 /* floating point invalid operation */
41# define PR_FP_EXC_DISABLED 0 /* FP exceptions disabled */
42# define PR_FP_EXC_NONRECOV 1 /* async non-recoverable exc. mode */
43# define PR_FP_EXC_ASYNC 2 /* async recoverable exception mode */
44# define PR_FP_EXC_PRECISE 3 /* precise exception mode */
45
46/* Get/set whether we use statistical process timing or accurate timestamp
47 * based process timing */
48#define PR_GET_TIMING 13
49#define PR_SET_TIMING 14
50# define PR_TIMING_STATISTICAL 0 /* Normal, traditional,
51 statistical process timing */
52# define PR_TIMING_TIMESTAMP 1 /* Accurate timestamp based
53 process timing */
54
55#define PR_SET_NAME 15 /* Set process name */
56#define PR_GET_NAME 16 /* Get process name */
57
58/* Get/set process endian */
59#define PR_GET_ENDIAN 19
60#define PR_SET_ENDIAN 20
61# define PR_ENDIAN_BIG 0
62# define PR_ENDIAN_LITTLE 1 /* True little endian mode */
63# define PR_ENDIAN_PPC_LITTLE 2 /* "PowerPC" pseudo little endian */
64
65/* Get/set process seccomp mode */
66#define PR_GET_SECCOMP 21
67#define PR_SET_SECCOMP 22
68
69/* Get/set the capability bounding set (as per security/commoncap.c) */
70#define PR_CAPBSET_READ 23
71#define PR_CAPBSET_DROP 24
72
73/* Get/set the process' ability to use the timestamp counter instruction */
74#define PR_GET_TSC 25
75#define PR_SET_TSC 26
76# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
77# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
78
79/* Get/set securebits (as per security/commoncap.c) */
80#define PR_GET_SECUREBITS 27
81#define PR_SET_SECUREBITS 28
82
83/*
84 * Get/set the timerslack as used by poll/select/nanosleep
85 * A value of 0 means "use default"
86 */
87#define PR_SET_TIMERSLACK 29
88#define PR_GET_TIMERSLACK 30
89
90#define PR_TASK_PERF_EVENTS_DISABLE 31
91#define PR_TASK_PERF_EVENTS_ENABLE 32
92
93/*
94 * Set early/late kill mode for hwpoison memory corruption.
95 * This influences when the process gets killed on a memory corruption.
96 */
97#define PR_MCE_KILL 33
98# define PR_MCE_KILL_CLEAR 0
99# define PR_MCE_KILL_SET 1
100
101# define PR_MCE_KILL_LATE 0
102# define PR_MCE_KILL_EARLY 1
103# define PR_MCE_KILL_DEFAULT 2
104
105#define PR_MCE_KILL_GET 34
106
107/*
108 * Tune up process memory map specifics.
109 */
110#define PR_SET_MM 35
111# define PR_SET_MM_START_CODE 1
112# define PR_SET_MM_END_CODE 2
113# define PR_SET_MM_START_DATA 3
114# define PR_SET_MM_END_DATA 4
115# define PR_SET_MM_START_STACK 5
116# define PR_SET_MM_START_BRK 6
117# define PR_SET_MM_BRK 7
118# define PR_SET_MM_ARG_START 8
119# define PR_SET_MM_ARG_END 9
120# define PR_SET_MM_ENV_START 10
121# define PR_SET_MM_ENV_END 11
122# define PR_SET_MM_AUXV 12
123# define PR_SET_MM_EXE_FILE 13
124# define PR_SET_MM_MAP 14
125# define PR_SET_MM_MAP_SIZE 15
126
127/*
128 * This structure provides new memory descriptor
129 * map which mostly modifies /proc/pid/stat[m]
130 * output for a task. This mostly done in a
131 * sake of checkpoint/restore functionality.
132 */
133struct prctl_mm_map {
134 __u64 start_code; /* code section bounds */
135 __u64 end_code;
136 __u64 start_data; /* data section bounds */
137 __u64 end_data;
138 __u64 start_brk; /* heap for brk() syscall */
139 __u64 brk;
140 __u64 start_stack; /* stack starts at */
141 __u64 arg_start; /* command line arguments bounds */
142 __u64 arg_end;
143 __u64 env_start; /* environment variables bounds */
144 __u64 env_end;
145 __u64 *auxv; /* auxiliary vector */
146 __u32 auxv_size; /* vector size */
147 __u32 exe_fd; /* /proc/$pid/exe link file */
148};
149
150/*
151 * Set specific pid that is allowed to ptrace the current task.
152 * A value of 0 mean "no process".
153 */
154#define PR_SET_PTRACER 0x59616d61
155# define PR_SET_PTRACER_ANY ((unsigned long)-1)
156
157#define PR_SET_CHILD_SUBREAPER 36
158#define PR_GET_CHILD_SUBREAPER 37
159
160/*
161 * If no_new_privs is set, then operations that grant new privileges (i.e.
162 * execve) will either fail or not grant them. This affects suid/sgid,
163 * file capabilities, and LSMs.
164 *
165 * Operations that merely manipulate or drop existing privileges (setresuid,
166 * capset, etc.) will still work. Drop those privileges if you want them gone.
167 *
168 * Changing LSM security domain is considered a new privilege. So, for example,
169 * asking selinux for a specific new context (e.g. with runcon) will result
170 * in execve returning -EPERM.
171 *
172 * See Documentation/prctl/no_new_privs.txt for more details.
173 */
174#define PR_SET_NO_NEW_PRIVS 38
175#define PR_GET_NO_NEW_PRIVS 39
176
177#define PR_GET_TID_ADDRESS 40
178
179#define PR_SET_THP_DISABLE 41
180#define PR_GET_THP_DISABLE 42
181
182/*
183 * Tell the kernel to start/stop helping userspace manage bounds tables.
184 */
185#define PR_MPX_ENABLE_MANAGEMENT 43
186#define PR_MPX_DISABLE_MANAGEMENT 44
187
188#define PR_SET_FP_MODE 45
189#define PR_GET_FP_MODE 46
190# define PR_FP_MODE_FR (1 << 0) /* 64b FP registers */
191# define PR_FP_MODE_FRE (1 << 1) /* 32b compatibility */
192
193/* Control the ambient capability set */
194#define PR_CAP_AMBIENT 47
195# define PR_CAP_AMBIENT_IS_SET 1
196# define PR_CAP_AMBIENT_RAISE 2
197# define PR_CAP_AMBIENT_LOWER 3
198# define PR_CAP_AMBIENT_CLEAR_ALL 4
199
200#endif /* _LINUX_PRCTL_H */
diff --git a/tools/include/uapi/linux/sched.h b/tools/include/uapi/linux/sched.h
new file mode 100644
index 000000000000..30a9e51bbb1e
--- /dev/null
+++ b/tools/include/uapi/linux/sched.h
@@ -0,0 +1,53 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef _UAPI_LINUX_SCHED_H
3#define _UAPI_LINUX_SCHED_H
4
5/*
6 * cloning flags:
7 */
8#define CSIGNAL 0x000000ff /* signal mask to be sent at exit */
9#define CLONE_VM 0x00000100 /* set if VM shared between processes */
10#define CLONE_FS 0x00000200 /* set if fs info shared between processes */
11#define CLONE_FILES 0x00000400 /* set if open files shared between processes */
12#define CLONE_SIGHAND 0x00000800 /* set if signal handlers and blocked signals shared */
13#define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */
14#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
15#define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */
16#define CLONE_THREAD 0x00010000 /* Same thread group? */
17#define CLONE_NEWNS 0x00020000 /* New mount namespace group */
18#define CLONE_SYSVSEM 0x00040000 /* share system V SEM_UNDO semantics */
19#define CLONE_SETTLS 0x00080000 /* create a new TLS for the child */
20#define CLONE_PARENT_SETTID 0x00100000 /* set the TID in the parent */
21#define CLONE_CHILD_CLEARTID 0x00200000 /* clear the TID in the child */
22#define CLONE_DETACHED 0x00400000 /* Unused, ignored */
23#define CLONE_UNTRACED 0x00800000 /* set if the tracing process can't force CLONE_PTRACE on this clone */
24#define CLONE_CHILD_SETTID 0x01000000 /* set the TID in the child */
25#define CLONE_NEWCGROUP 0x02000000 /* New cgroup namespace */
26#define CLONE_NEWUTS 0x04000000 /* New utsname namespace */
27#define CLONE_NEWIPC 0x08000000 /* New ipc namespace */
28#define CLONE_NEWUSER 0x10000000 /* New user namespace */
29#define CLONE_NEWPID 0x20000000 /* New pid namespace */
30#define CLONE_NEWNET 0x40000000 /* New network namespace */
31#define CLONE_IO 0x80000000 /* Clone io context */
32
33/*
34 * Scheduling policies
35 */
36#define SCHED_NORMAL 0
37#define SCHED_FIFO 1
38#define SCHED_RR 2
39#define SCHED_BATCH 3
40/* SCHED_ISO: reserved but not implemented yet */
41#define SCHED_IDLE 5
42#define SCHED_DEADLINE 6
43
44/* Can be ORed in to make sure the process is reverted back to SCHED_NORMAL on fork */
45#define SCHED_RESET_ON_FORK 0x40000000
46
47/*
48 * For the sched_{set,get}attr() calls
49 */
50#define SCHED_FLAG_RESET_ON_FORK 0x01
51#define SCHED_FLAG_RECLAIM 0x02
52
53#endif /* _UAPI_LINUX_SCHED_H */
diff --git a/tools/include/uapi/linux/stat.h b/tools/include/uapi/linux/stat.h
index 17b10304c393..7b35e98d3c58 100644
--- a/tools/include/uapi/linux/stat.h
+++ b/tools/include/uapi/linux/stat.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
1#ifndef _UAPI_LINUX_STAT_H 2#ifndef _UAPI_LINUX_STAT_H
2#define _UAPI_LINUX_STAT_H 3#define _UAPI_LINUX_STAT_H
3 4
diff --git a/tools/include/uapi/linux/vhost.h b/tools/include/uapi/linux/vhost.h
new file mode 100644
index 000000000000..c51f8e5cc608
--- /dev/null
+++ b/tools/include/uapi/linux/vhost.h
@@ -0,0 +1,210 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef _LINUX_VHOST_H
3#define _LINUX_VHOST_H
4/* Userspace interface for in-kernel virtio accelerators. */
5
6/* vhost is used to reduce the number of system calls involved in virtio.
7 *
8 * Existing virtio net code is used in the guest without modification.
9 *
10 * This header includes interface used by userspace hypervisor for
11 * device configuration.
12 */
13
14#include <linux/types.h>
15#include <linux/compiler.h>
16#include <linux/ioctl.h>
17#include <linux/virtio_config.h>
18#include <linux/virtio_ring.h>
19
20struct vhost_vring_state {
21 unsigned int index;
22 unsigned int num;
23};
24
25struct vhost_vring_file {
26 unsigned int index;
27 int fd; /* Pass -1 to unbind from file. */
28
29};
30
31struct vhost_vring_addr {
32 unsigned int index;
33 /* Option flags. */
34 unsigned int flags;
35 /* Flag values: */
36 /* Whether log address is valid. If set enables logging. */
37#define VHOST_VRING_F_LOG 0
38
39 /* Start of array of descriptors (virtually contiguous) */
40 __u64 desc_user_addr;
41 /* Used structure address. Must be 32 bit aligned */
42 __u64 used_user_addr;
43 /* Available structure address. Must be 16 bit aligned */
44 __u64 avail_user_addr;
45 /* Logging support. */
46 /* Log writes to used structure, at offset calculated from specified
47 * address. Address must be 32 bit aligned. */
48 __u64 log_guest_addr;
49};
50
51/* no alignment requirement */
52struct vhost_iotlb_msg {
53 __u64 iova;
54 __u64 size;
55 __u64 uaddr;
56#define VHOST_ACCESS_RO 0x1
57#define VHOST_ACCESS_WO 0x2
58#define VHOST_ACCESS_RW 0x3
59 __u8 perm;
60#define VHOST_IOTLB_MISS 1
61#define VHOST_IOTLB_UPDATE 2
62#define VHOST_IOTLB_INVALIDATE 3
63#define VHOST_IOTLB_ACCESS_FAIL 4
64 __u8 type;
65};
66
67#define VHOST_IOTLB_MSG 0x1
68
69struct vhost_msg {
70 int type;
71 union {
72 struct vhost_iotlb_msg iotlb;
73 __u8 padding[64];
74 };
75};
76
77struct vhost_memory_region {
78 __u64 guest_phys_addr;
79 __u64 memory_size; /* bytes */
80 __u64 userspace_addr;
81 __u64 flags_padding; /* No flags are currently specified. */
82};
83
84/* All region addresses and sizes must be 4K aligned. */
85#define VHOST_PAGE_SIZE 0x1000
86
87struct vhost_memory {
88 __u32 nregions;
89 __u32 padding;
90 struct vhost_memory_region regions[0];
91};
92
93/* ioctls */
94
95#define VHOST_VIRTIO 0xAF
96
97/* Features bitmask for forward compatibility. Transport bits are used for
98 * vhost specific features. */
99#define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64)
100#define VHOST_SET_FEATURES _IOW(VHOST_VIRTIO, 0x00, __u64)
101
102/* Set current process as the (exclusive) owner of this file descriptor. This
103 * must be called before any other vhost command. Further calls to
104 * VHOST_OWNER_SET fail until VHOST_OWNER_RESET is called. */
105#define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01)
106/* Give up ownership, and reset the device to default values.
107 * Allows subsequent call to VHOST_OWNER_SET to succeed. */
108#define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
109
110/* Set up/modify memory layout */
111#define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
112
113/* Write logging setup. */
114/* Memory writes can optionally be logged by setting bit at an offset
115 * (calculated from the physical address) from specified log base.
116 * The bit is set using an atomic 32 bit operation. */
117/* Set base address for logging. */
118#define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64)
119/* Specify an eventfd file descriptor to signal on log write. */
120#define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int)
121
122/* Ring setup. */
123/* Set number of descriptors in ring. This parameter can not
124 * be modified while ring is running (bound to a device). */
125#define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state)
126/* Set addresses for the ring. */
127#define VHOST_SET_VRING_ADDR _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr)
128/* Base value where queue looks for available descriptors */
129#define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
130/* Get accessor: reads index, writes value in num */
131#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
132
133/* Set the vring byte order in num. Valid values are VHOST_VRING_LITTLE_ENDIAN
134 * or VHOST_VRING_BIG_ENDIAN (other values return -EINVAL).
135 * The byte order cannot be changed while the device is active: trying to do so
136 * returns -EBUSY.
137 * This is a legacy only API that is simply ignored when VIRTIO_F_VERSION_1 is
138 * set.
139 * Not all kernel configurations support this ioctl, but all configurations that
140 * support SET also support GET.
141 */
142#define VHOST_VRING_LITTLE_ENDIAN 0
143#define VHOST_VRING_BIG_ENDIAN 1
144#define VHOST_SET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x13, struct vhost_vring_state)
145#define VHOST_GET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x14, struct vhost_vring_state)
146
147/* The following ioctls use eventfd file descriptors to signal and poll
148 * for events. */
149
150/* Set eventfd to poll for added buffers */
151#define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file)
152/* Set eventfd to signal when buffers have beed used */
153#define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file)
154/* Set eventfd to signal an error */
155#define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
156/* Set busy loop timeout (in us) */
157#define VHOST_SET_VRING_BUSYLOOP_TIMEOUT _IOW(VHOST_VIRTIO, 0x23, \
158 struct vhost_vring_state)
159/* Get busy loop timeout (in us) */
160#define VHOST_GET_VRING_BUSYLOOP_TIMEOUT _IOW(VHOST_VIRTIO, 0x24, \
161 struct vhost_vring_state)
162
163/* VHOST_NET specific defines */
164
165/* Attach virtio net ring to a raw socket, or tap device.
166 * The socket must be already bound to an ethernet device, this device will be
167 * used for transmit. Pass fd -1 to unbind from the socket and the transmit
168 * device. This can be used to stop the ring (e.g. for migration). */
169#define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
170
171/* Feature bits */
172/* Log all write descriptors. Can be changed while device is active. */
173#define VHOST_F_LOG_ALL 26
174/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
175#define VHOST_NET_F_VIRTIO_NET_HDR 27
176
177/* VHOST_SCSI specific definitions */
178
179/*
180 * Used by QEMU userspace to ensure a consistent vhost-scsi ABI.
181 *
182 * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate +
183 * RFC-v2 vhost-scsi userspace. Add GET_ABI_VERSION ioctl usage
184 * ABI Rev 1: January 2013. Ignore vhost_tpgt filed in struct vhost_scsi_target.
185 * All the targets under vhost_wwpn can be seen and used by guset.
186 */
187
188#define VHOST_SCSI_ABI_VERSION 1
189
190struct vhost_scsi_target {
191 int abi_version;
192 char vhost_wwpn[224]; /* TRANSPORT_IQN_LEN */
193 unsigned short vhost_tpgt;
194 unsigned short reserved;
195};
196
197#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
198#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
199/* Changing this breaks userspace. */
200#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int)
201/* Set and get the events missed flag */
202#define VHOST_SCSI_SET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x43, __u32)
203#define VHOST_SCSI_GET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x44, __u32)
204
205/* VHOST_VSOCK specific defines */
206
207#define VHOST_VSOCK_SET_GUEST_CID _IOW(VHOST_VIRTIO, 0x60, __u64)
208#define VHOST_VSOCK_SET_RUNNING _IOW(VHOST_VIRTIO, 0x61, int)
209
210#endif
diff --git a/tools/include/uapi/sound/asound.h b/tools/include/uapi/sound/asound.h
new file mode 100644
index 000000000000..c227ccba60ae
--- /dev/null
+++ b/tools/include/uapi/sound/asound.h
@@ -0,0 +1,1027 @@
1/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
2/*
3 * Advanced Linux Sound Architecture - ALSA - Driver
4 * Copyright (c) 1994-2003 by Jaroslav Kysela <perex@perex.cz>,
5 * Abramo Bagnara <abramo@alsa-project.org>
6 *
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 as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
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, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#ifndef _UAPI__SOUND_ASOUND_H
25#define _UAPI__SOUND_ASOUND_H
26
27#if defined(__KERNEL__) || defined(__linux__)
28#include <linux/types.h>
29#else
30#include <sys/ioctl.h>
31#endif
32
33#ifndef __KERNEL__
34#include <stdlib.h>
35#endif
36
37/*
38 * protocol version
39 */
40
41#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
42#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
43#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
44#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
45#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \
46 (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \
47 (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \
48 SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
49
50/****************************************************************************
51 * *
52 * Digital audio interface *
53 * *
54 ****************************************************************************/
55
56struct snd_aes_iec958 {
57 unsigned char status[24]; /* AES/IEC958 channel status bits */
58 unsigned char subcode[147]; /* AES/IEC958 subcode bits */
59 unsigned char pad; /* nothing */
60 unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */
61};
62
63/****************************************************************************
64 * *
65 * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort *
66 * *
67 ****************************************************************************/
68
69struct snd_cea_861_aud_if {
70 unsigned char db1_ct_cc; /* coding type and channel count */
71 unsigned char db2_sf_ss; /* sample frequency and size */
72 unsigned char db3; /* not used, all zeros */
73 unsigned char db4_ca; /* channel allocation code */
74 unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
75};
76
77/****************************************************************************
78 * *
79 * Section for driver hardware dependent interface - /dev/snd/hw? *
80 * *
81 ****************************************************************************/
82
83#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
84
85enum {
86 SNDRV_HWDEP_IFACE_OPL2 = 0,
87 SNDRV_HWDEP_IFACE_OPL3,
88 SNDRV_HWDEP_IFACE_OPL4,
89 SNDRV_HWDEP_IFACE_SB16CSP, /* Creative Signal Processor */
90 SNDRV_HWDEP_IFACE_EMU10K1, /* FX8010 processor in EMU10K1 chip */
91 SNDRV_HWDEP_IFACE_YSS225, /* Yamaha FX processor */
92 SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */
93 SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */
94 SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */
95 SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */
96 SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */
97 SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */
98 SNDRV_HWDEP_IFACE_BLUETOOTH, /* Bluetooth audio */
99 SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */
100 SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */
101 SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */
102 SNDRV_HWDEP_IFACE_HDA, /* HD-audio */
103 SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */
104 SNDRV_HWDEP_IFACE_FW_DICE, /* TC DICE FireWire device */
105 SNDRV_HWDEP_IFACE_FW_FIREWORKS, /* Echo Audio Fireworks based device */
106 SNDRV_HWDEP_IFACE_FW_BEBOB, /* BridgeCo BeBoB based device */
107 SNDRV_HWDEP_IFACE_FW_OXFW, /* Oxford OXFW970/971 based device */
108 SNDRV_HWDEP_IFACE_FW_DIGI00X, /* Digidesign Digi 002/003 family */
109 SNDRV_HWDEP_IFACE_FW_TASCAM, /* TASCAM FireWire series */
110 SNDRV_HWDEP_IFACE_LINE6, /* Line6 USB processors */
111 SNDRV_HWDEP_IFACE_FW_MOTU, /* MOTU FireWire series */
112 SNDRV_HWDEP_IFACE_FW_FIREFACE, /* RME Fireface series */
113
114 /* Don't forget to change the following: */
115 SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_FIREFACE
116};
117
118struct snd_hwdep_info {
119 unsigned int device; /* WR: device number */
120 int card; /* R: card number */
121 unsigned char id[64]; /* ID (user selectable) */
122 unsigned char name[80]; /* hwdep name */
123 int iface; /* hwdep interface */
124 unsigned char reserved[64]; /* reserved for future */
125};
126
127/* generic DSP loader */
128struct snd_hwdep_dsp_status {
129 unsigned int version; /* R: driver-specific version */
130 unsigned char id[32]; /* R: driver-specific ID string */
131 unsigned int num_dsps; /* R: number of DSP images to transfer */
132 unsigned int dsp_loaded; /* R: bit flags indicating the loaded DSPs */
133 unsigned int chip_ready; /* R: 1 = initialization finished */
134 unsigned char reserved[16]; /* reserved for future use */
135};
136
137struct snd_hwdep_dsp_image {
138 unsigned int index; /* W: DSP index */
139 unsigned char name[64]; /* W: ID (e.g. file name) */
140 unsigned char __user *image; /* W: binary image */
141 size_t length; /* W: size of image in bytes */
142 unsigned long driver_data; /* W: driver-specific data */
143};
144
145#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int)
146#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info)
147#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
148#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
149
150/*****************************************************************************
151 * *
152 * Digital Audio (PCM) interface - /dev/snd/pcm?? *
153 * *
154 *****************************************************************************/
155
156#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 14)
157
158typedef unsigned long snd_pcm_uframes_t;
159typedef signed long snd_pcm_sframes_t;
160
161enum {
162 SNDRV_PCM_CLASS_GENERIC = 0, /* standard mono or stereo device */
163 SNDRV_PCM_CLASS_MULTI, /* multichannel device */
164 SNDRV_PCM_CLASS_MODEM, /* software modem class */
165 SNDRV_PCM_CLASS_DIGITIZER, /* digitizer class */
166 /* Don't forget to change the following: */
167 SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
168};
169
170enum {
171 SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */
172 SNDRV_PCM_SUBCLASS_MULTI_MIX, /* multichannel subdevices are mixed together */
173 /* Don't forget to change the following: */
174 SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
175};
176
177enum {
178 SNDRV_PCM_STREAM_PLAYBACK = 0,
179 SNDRV_PCM_STREAM_CAPTURE,
180 SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
181};
182
183typedef int __bitwise snd_pcm_access_t;
184#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0) /* interleaved mmap */
185#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
186#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2) /* complex mmap */
187#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3) /* readi/writei */
188#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4) /* readn/writen */
189#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
190
191typedef int __bitwise snd_pcm_format_t;
192#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
193#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
194#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
195#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
196#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
197#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
198#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */
199#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */
200#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */
201#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */
202#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
203#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
204#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
205#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
206#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
207#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
208#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
209#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
210#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
211#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
212#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
213#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
214#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
215#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
216#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
217#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
218#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */
219#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */
220#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34) /* in three bytes */
221#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35) /* in three bytes */
222#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36) /* in three bytes */
223#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37) /* in three bytes */
224#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38) /* in three bytes */
225#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39) /* in three bytes */
226#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40) /* in three bytes */
227#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41) /* in three bytes */
228#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42) /* in three bytes */
229#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43) /* in three bytes */
230#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
231#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
232#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
233#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
234#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */
235#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */
236#define SNDRV_PCM_FORMAT_DSD_U32_LE ((__force snd_pcm_format_t) 50) /* DSD, 4-byte samples DSD (x32), little endian */
237#define SNDRV_PCM_FORMAT_DSD_U16_BE ((__force snd_pcm_format_t) 51) /* DSD, 2-byte samples DSD (x16), big endian */
238#define SNDRV_PCM_FORMAT_DSD_U32_BE ((__force snd_pcm_format_t) 52) /* DSD, 4-byte samples DSD (x32), big endian */
239#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U32_BE
240
241#ifdef SNDRV_LITTLE_ENDIAN
242#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
243#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE
244#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE
245#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE
246#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE
247#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE
248#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
249#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
250#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
251#endif
252#ifdef SNDRV_BIG_ENDIAN
253#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
254#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE
255#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE
256#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE
257#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE
258#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE
259#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
260#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
261#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
262#endif
263
264typedef int __bitwise snd_pcm_subformat_t;
265#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
266#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD
267
268#define SNDRV_PCM_INFO_MMAP 0x00000001 /* hardware supports mmap */
269#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */
270#define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */
271#define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */
272#define SNDRV_PCM_INFO_SYNC_APPLPTR 0x00000020 /* need the explicit sync of appl_ptr update */
273#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */
274#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */
275#define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */
276#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000 /* hardware transfer block of samples */
277#define SNDRV_PCM_INFO_OVERRANGE 0x00020000 /* hardware supports ADC (capture) overrange detection */
278#define SNDRV_PCM_INFO_RESUME 0x00040000 /* hardware supports stream resume after suspend */
279#define SNDRV_PCM_INFO_PAUSE 0x00080000 /* pause ioctl is supported */
280#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */
281#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
282#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */
283#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */
284#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* (Deprecated)has audio wall clock for audio/system time sync */
285#define SNDRV_PCM_INFO_HAS_LINK_ATIME 0x01000000 /* report hardware link audio time, reset on startup */
286#define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */
287#define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */
288#define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */
289
290#define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */
291#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */
292
293
294
295typedef int __bitwise snd_pcm_state_t;
296#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */
297#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */
298#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2) /* stream is ready to start */
299#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3) /* stream is running */
300#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4) /* stream reached an xrun */
301#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5) /* stream is draining */
302#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6) /* stream is paused */
303#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7) /* hardware is suspended */
304#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8) /* hardware is disconnected */
305#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
306
307enum {
308 SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
309 SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
310 SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
311};
312
313union snd_pcm_sync_id {
314 unsigned char id[16];
315 unsigned short id16[8];
316 unsigned int id32[4];
317};
318
319struct snd_pcm_info {
320 unsigned int device; /* RO/WR (control): device number */
321 unsigned int subdevice; /* RO/WR (control): subdevice number */
322 int stream; /* RO/WR (control): stream direction */
323 int card; /* R: card number */
324 unsigned char id[64]; /* ID (user selectable) */
325 unsigned char name[80]; /* name of this device */
326 unsigned char subname[32]; /* subdevice name */
327 int dev_class; /* SNDRV_PCM_CLASS_* */
328 int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */
329 unsigned int subdevices_count;
330 unsigned int subdevices_avail;
331 union snd_pcm_sync_id sync; /* hardware synchronization ID */
332 unsigned char reserved[64]; /* reserved for future... */
333};
334
335typedef int snd_pcm_hw_param_t;
336#define SNDRV_PCM_HW_PARAM_ACCESS 0 /* Access type */
337#define SNDRV_PCM_HW_PARAM_FORMAT 1 /* Format */
338#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2 /* Subformat */
339#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
340#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
341
342#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8 /* Bits per sample */
343#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9 /* Bits per frame */
344#define SNDRV_PCM_HW_PARAM_CHANNELS 10 /* Channels */
345#define SNDRV_PCM_HW_PARAM_RATE 11 /* Approx rate */
346#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12 /* Approx distance between
347 * interrupts in us
348 */
349#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13 /* Approx frames between
350 * interrupts
351 */
352#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14 /* Approx bytes between
353 * interrupts
354 */
355#define SNDRV_PCM_HW_PARAM_PERIODS 15 /* Approx interrupts per
356 * buffer
357 */
358#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16 /* Approx duration of buffer
359 * in us
360 */
361#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17 /* Size of buffer in frames */
362#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18 /* Size of buffer in bytes */
363#define SNDRV_PCM_HW_PARAM_TICK_TIME 19 /* Approx tick duration in us */
364#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
365#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
366
367#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */
368#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1) /* export buffer */
369#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) /* disable period wakeups */
370
371struct snd_interval {
372 unsigned int min, max;
373 unsigned int openmin:1,
374 openmax:1,
375 integer:1,
376 empty:1;
377};
378
379#define SNDRV_MASK_MAX 256
380
381struct snd_mask {
382 __u32 bits[(SNDRV_MASK_MAX+31)/32];
383};
384
385struct snd_pcm_hw_params {
386 unsigned int flags;
387 struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
388 SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
389 struct snd_mask mres[5]; /* reserved masks */
390 struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
391 SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
392 struct snd_interval ires[9]; /* reserved intervals */
393 unsigned int rmask; /* W: requested masks */
394 unsigned int cmask; /* R: changed masks */
395 unsigned int info; /* R: Info flags for returned setup */
396 unsigned int msbits; /* R: used most significant bits */
397 unsigned int rate_num; /* R: rate numerator */
398 unsigned int rate_den; /* R: rate denominator */
399 snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */
400 unsigned char reserved[64]; /* reserved for future */
401};
402
403enum {
404 SNDRV_PCM_TSTAMP_NONE = 0,
405 SNDRV_PCM_TSTAMP_ENABLE,
406 SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
407};
408
409struct snd_pcm_sw_params {
410 int tstamp_mode; /* timestamp mode */
411 unsigned int period_step;
412 unsigned int sleep_min; /* min ticks to sleep */
413 snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */
414 snd_pcm_uframes_t xfer_align; /* obsolete: xfer size need to be a multiple */
415 snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */
416 snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */
417 snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */
418 snd_pcm_uframes_t silence_size; /* silence block size */
419 snd_pcm_uframes_t boundary; /* pointers wrap point */
420 unsigned int proto; /* protocol version */
421 unsigned int tstamp_type; /* timestamp type (req. proto >= 2.0.12) */
422 unsigned char reserved[56]; /* reserved for future */
423};
424
425struct snd_pcm_channel_info {
426 unsigned int channel;
427 __kernel_off_t offset; /* mmap offset */
428 unsigned int first; /* offset to first sample in bits */
429 unsigned int step; /* samples distance in bits */
430};
431
432enum {
433 /*
434 * first definition for backwards compatibility only,
435 * maps to wallclock/link time for HDAudio playback and DEFAULT/DMA time for everything else
436 */
437 SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT = 0,
438
439 /* timestamp definitions */
440 SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT = 1, /* DMA time, reported as per hw_ptr */
441 SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK = 2, /* link time reported by sample or wallclock counter, reset on startup */
442 SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE = 3, /* link time reported by sample or wallclock counter, not reset on startup */
443 SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED = 4, /* link time estimated indirectly */
444 SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED = 5, /* link time synchronized with system time */
445 SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED
446};
447
448struct snd_pcm_status {
449 snd_pcm_state_t state; /* stream state */
450 struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
451 struct timespec tstamp; /* reference timestamp */
452 snd_pcm_uframes_t appl_ptr; /* appl ptr */
453 snd_pcm_uframes_t hw_ptr; /* hw ptr */
454 snd_pcm_sframes_t delay; /* current delay in frames */
455 snd_pcm_uframes_t avail; /* number of frames available */
456 snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */
457 snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
458 snd_pcm_state_t suspended_state; /* suspended stream state */
459 __u32 audio_tstamp_data; /* needed for 64-bit alignment, used for configs/report to/from userspace */
460 struct timespec audio_tstamp; /* sample counter, wall clock, PHC or on-demand sync'ed */
461 struct timespec driver_tstamp; /* useful in case reference system tstamp is reported with delay */
462 __u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */
463 unsigned char reserved[52-2*sizeof(struct timespec)]; /* must be filled with zero */
464};
465
466struct snd_pcm_mmap_status {
467 snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */
468 int pad1; /* Needed for 64 bit alignment */
469 snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
470 struct timespec tstamp; /* Timestamp */
471 snd_pcm_state_t suspended_state; /* RO: suspended stream state */
472 struct timespec audio_tstamp; /* from sample counter or wall clock */
473};
474
475struct snd_pcm_mmap_control {
476 snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */
477 snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */
478};
479
480#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0) /* execute hwsync */
481#define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */
482#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */
483
484struct snd_pcm_sync_ptr {
485 unsigned int flags;
486 union {
487 struct snd_pcm_mmap_status status;
488 unsigned char reserved[64];
489 } s;
490 union {
491 struct snd_pcm_mmap_control control;
492 unsigned char reserved[64];
493 } c;
494};
495
496struct snd_xferi {
497 snd_pcm_sframes_t result;
498 void __user *buf;
499 snd_pcm_uframes_t frames;
500};
501
502struct snd_xfern {
503 snd_pcm_sframes_t result;
504 void __user * __user *bufs;
505 snd_pcm_uframes_t frames;
506};
507
508enum {
509 SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
510 SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */
511 SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /* monotonic_raw (no NTP) */
512 SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW,
513};
514
515/* channel positions */
516enum {
517 SNDRV_CHMAP_UNKNOWN = 0,
518 SNDRV_CHMAP_NA, /* N/A, silent */
519 SNDRV_CHMAP_MONO, /* mono stream */
520 /* this follows the alsa-lib mixer channel value + 3 */
521 SNDRV_CHMAP_FL, /* front left */
522 SNDRV_CHMAP_FR, /* front right */
523 SNDRV_CHMAP_RL, /* rear left */
524 SNDRV_CHMAP_RR, /* rear right */
525 SNDRV_CHMAP_FC, /* front center */
526 SNDRV_CHMAP_LFE, /* LFE */
527 SNDRV_CHMAP_SL, /* side left */
528 SNDRV_CHMAP_SR, /* side right */
529 SNDRV_CHMAP_RC, /* rear center */
530 /* new definitions */
531 SNDRV_CHMAP_FLC, /* front left center */
532 SNDRV_CHMAP_FRC, /* front right center */
533 SNDRV_CHMAP_RLC, /* rear left center */
534 SNDRV_CHMAP_RRC, /* rear right center */
535 SNDRV_CHMAP_FLW, /* front left wide */
536 SNDRV_CHMAP_FRW, /* front right wide */
537 SNDRV_CHMAP_FLH, /* front left high */
538 SNDRV_CHMAP_FCH, /* front center high */
539 SNDRV_CHMAP_FRH, /* front right high */
540 SNDRV_CHMAP_TC, /* top center */
541 SNDRV_CHMAP_TFL, /* top front left */
542 SNDRV_CHMAP_TFR, /* top front right */
543 SNDRV_CHMAP_TFC, /* top front center */
544 SNDRV_CHMAP_TRL, /* top rear left */
545 SNDRV_CHMAP_TRR, /* top rear right */
546 SNDRV_CHMAP_TRC, /* top rear center */
547 /* new definitions for UAC2 */
548 SNDRV_CHMAP_TFLC, /* top front left center */
549 SNDRV_CHMAP_TFRC, /* top front right center */
550 SNDRV_CHMAP_TSL, /* top side left */
551 SNDRV_CHMAP_TSR, /* top side right */
552 SNDRV_CHMAP_LLFE, /* left LFE */
553 SNDRV_CHMAP_RLFE, /* right LFE */
554 SNDRV_CHMAP_BC, /* bottom center */
555 SNDRV_CHMAP_BLC, /* bottom left center */
556 SNDRV_CHMAP_BRC, /* bottom right center */
557 SNDRV_CHMAP_LAST = SNDRV_CHMAP_BRC,
558};
559
560#define SNDRV_CHMAP_POSITION_MASK 0xffff
561#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16)
562#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
563
564#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int)
565#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
566#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
567#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
568#define SNDRV_PCM_IOCTL_USER_PVERSION _IOW('A', 0x04, int)
569#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
570#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
571#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
572#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params)
573#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
574#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
575#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
576#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
577#define SNDRV_PCM_IOCTL_STATUS_EXT _IOWR('A', 0x24, struct snd_pcm_status)
578#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
579#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
580#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
581#define SNDRV_PCM_IOCTL_START _IO('A', 0x42)
582#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43)
583#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44)
584#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int)
585#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t)
586#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47)
587#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48)
588#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t)
589#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi)
590#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi)
591#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern)
592#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern)
593#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
594#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
595
596/*****************************************************************************
597 * *
598 * MIDI v1.0 interface *
599 * *
600 *****************************************************************************/
601
602/*
603 * Raw MIDI section - /dev/snd/midi??
604 */
605
606#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
607
608enum {
609 SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
610 SNDRV_RAWMIDI_STREAM_INPUT,
611 SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
612};
613
614#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001
615#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002
616#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004
617
618struct snd_rawmidi_info {
619 unsigned int device; /* RO/WR (control): device number */
620 unsigned int subdevice; /* RO/WR (control): subdevice number */
621 int stream; /* WR: stream */
622 int card; /* R: card number */
623 unsigned int flags; /* SNDRV_RAWMIDI_INFO_XXXX */
624 unsigned char id[64]; /* ID (user selectable) */
625 unsigned char name[80]; /* name of device */
626 unsigned char subname[32]; /* name of active or selected subdevice */
627 unsigned int subdevices_count;
628 unsigned int subdevices_avail;
629 unsigned char reserved[64]; /* reserved for future use */
630};
631
632struct snd_rawmidi_params {
633 int stream;
634 size_t buffer_size; /* queue size in bytes */
635 size_t avail_min; /* minimum avail bytes for wakeup */
636 unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
637 unsigned char reserved[16]; /* reserved for future use */
638};
639
640struct snd_rawmidi_status {
641 int stream;
642 struct timespec tstamp; /* Timestamp */
643 size_t avail; /* available bytes */
644 size_t xruns; /* count of overruns since last status (in bytes) */
645 unsigned char reserved[16]; /* reserved for future use */
646};
647
648#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
649#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info)
650#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params)
651#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status)
652#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int)
653#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int)
654
655/*
656 * Timer section - /dev/snd/timer
657 */
658
659#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
660
661enum {
662 SNDRV_TIMER_CLASS_NONE = -1,
663 SNDRV_TIMER_CLASS_SLAVE = 0,
664 SNDRV_TIMER_CLASS_GLOBAL,
665 SNDRV_TIMER_CLASS_CARD,
666 SNDRV_TIMER_CLASS_PCM,
667 SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
668};
669
670/* slave timer classes */
671enum {
672 SNDRV_TIMER_SCLASS_NONE = 0,
673 SNDRV_TIMER_SCLASS_APPLICATION,
674 SNDRV_TIMER_SCLASS_SEQUENCER, /* alias */
675 SNDRV_TIMER_SCLASS_OSS_SEQUENCER, /* alias */
676 SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
677};
678
679/* global timers (device member) */
680#define SNDRV_TIMER_GLOBAL_SYSTEM 0
681#define SNDRV_TIMER_GLOBAL_RTC 1 /* unused */
682#define SNDRV_TIMER_GLOBAL_HPET 2
683#define SNDRV_TIMER_GLOBAL_HRTIMER 3
684
685/* info flags */
686#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
687
688struct snd_timer_id {
689 int dev_class;
690 int dev_sclass;
691 int card;
692 int device;
693 int subdevice;
694};
695
696struct snd_timer_ginfo {
697 struct snd_timer_id tid; /* requested timer ID */
698 unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
699 int card; /* card number */
700 unsigned char id[64]; /* timer identification */
701 unsigned char name[80]; /* timer name */
702 unsigned long reserved0; /* reserved for future use */
703 unsigned long resolution; /* average period resolution in ns */
704 unsigned long resolution_min; /* minimal period resolution in ns */
705 unsigned long resolution_max; /* maximal period resolution in ns */
706 unsigned int clients; /* active timer clients */
707 unsigned char reserved[32];
708};
709
710struct snd_timer_gparams {
711 struct snd_timer_id tid; /* requested timer ID */
712 unsigned long period_num; /* requested precise period duration (in seconds) - numerator */
713 unsigned long period_den; /* requested precise period duration (in seconds) - denominator */
714 unsigned char reserved[32];
715};
716
717struct snd_timer_gstatus {
718 struct snd_timer_id tid; /* requested timer ID */
719 unsigned long resolution; /* current period resolution in ns */
720 unsigned long resolution_num; /* precise current period resolution (in seconds) - numerator */
721 unsigned long resolution_den; /* precise current period resolution (in seconds) - denominator */
722 unsigned char reserved[32];
723};
724
725struct snd_timer_select {
726 struct snd_timer_id id; /* bind to timer ID */
727 unsigned char reserved[32]; /* reserved */
728};
729
730struct snd_timer_info {
731 unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
732 int card; /* card number */
733 unsigned char id[64]; /* timer identificator */
734 unsigned char name[80]; /* timer name */
735 unsigned long reserved0; /* reserved for future use */
736 unsigned long resolution; /* average period resolution in ns */
737 unsigned char reserved[64]; /* reserved */
738};
739
740#define SNDRV_TIMER_PSFLG_AUTO (1<<0) /* auto start, otherwise one-shot */
741#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1) /* exclusive use, precise start/stop/pause/continue */
742#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */
743
744struct snd_timer_params {
745 unsigned int flags; /* flags - SNDRV_MIXER_PSFLG_* */
746 unsigned int ticks; /* requested resolution in ticks */
747 unsigned int queue_size; /* total size of queue (32-1024) */
748 unsigned int reserved0; /* reserved, was: failure locations */
749 unsigned int filter; /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */
750 unsigned char reserved[60]; /* reserved */
751};
752
753struct snd_timer_status {
754 struct timespec tstamp; /* Timestamp - last update */
755 unsigned int resolution; /* current period resolution in ns */
756 unsigned int lost; /* counter of master tick lost */
757 unsigned int overrun; /* count of read queue overruns */
758 unsigned int queue; /* used queue size */
759 unsigned char reserved[64]; /* reserved */
760};
761
762#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
763#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
764#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
765#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo)
766#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams)
767#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus)
768#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select)
769#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info)
770#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params)
771#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status)
772/* The following four ioctls are changed since 1.0.9 due to confliction */
773#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0)
774#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
775#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
776#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
777
778struct snd_timer_read {
779 unsigned int resolution;
780 unsigned int ticks;
781};
782
783enum {
784 SNDRV_TIMER_EVENT_RESOLUTION = 0, /* val = resolution in ns */
785 SNDRV_TIMER_EVENT_TICK, /* val = ticks */
786 SNDRV_TIMER_EVENT_START, /* val = resolution in ns */
787 SNDRV_TIMER_EVENT_STOP, /* val = 0 */
788 SNDRV_TIMER_EVENT_CONTINUE, /* val = resolution in ns */
789 SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */
790 SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */
791 SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */
792 SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */
793 /* master timer events for slave timer instances */
794 SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
795 SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
796 SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
797 SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
798 SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
799 SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
800};
801
802struct snd_timer_tread {
803 int event;
804 struct timespec tstamp;
805 unsigned int val;
806};
807
808/****************************************************************************
809 * *
810 * Section for driver control interface - /dev/snd/control? *
811 * *
812 ****************************************************************************/
813
814#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7)
815
816struct snd_ctl_card_info {
817 int card; /* card number */
818 int pad; /* reserved for future (was type) */
819 unsigned char id[16]; /* ID of card (user selectable) */
820 unsigned char driver[16]; /* Driver name */
821 unsigned char name[32]; /* Short name of soundcard */
822 unsigned char longname[80]; /* name + info text about soundcard */
823 unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */
824 unsigned char mixername[80]; /* visual mixer identification */
825 unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */
826};
827
828typedef int __bitwise snd_ctl_elem_type_t;
829#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */
830#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */
831#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2) /* integer type */
832#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3) /* enumerated type */
833#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4) /* byte array */
834#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
835#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
836#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
837
838typedef int __bitwise snd_ctl_elem_iface_t;
839#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0) /* global control */
840#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
841#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
842#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3) /* PCM device */
843#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
844#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5) /* timer device */
845#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
846#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
847
848#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
849#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
850#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
851#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */
852#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3) /* when was control changed */
853#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */
854#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */
855#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
856#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6) /* TLV command is possible */
857#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8) /* control does actually nothing, but may be updated */
858#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9) /* write lock */
859#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */
860#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */
861#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */
862/* bits 30 and 31 are obsoleted (for indirect access) */
863
864/* for further details see the ACPI and PCI power management specification */
865#define SNDRV_CTL_POWER_D0 0x0000 /* full On */
866#define SNDRV_CTL_POWER_D1 0x0100 /* partial On */
867#define SNDRV_CTL_POWER_D2 0x0200 /* partial On */
868#define SNDRV_CTL_POWER_D3 0x0300 /* Off */
869#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */
870#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */
871
872#define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44
873
874struct snd_ctl_elem_id {
875 unsigned int numid; /* numeric identifier, zero = invalid */
876 snd_ctl_elem_iface_t iface; /* interface identifier */
877 unsigned int device; /* device/client number */
878 unsigned int subdevice; /* subdevice (substream) number */
879 unsigned char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* ASCII name of item */
880 unsigned int index; /* index of item */
881};
882
883struct snd_ctl_elem_list {
884 unsigned int offset; /* W: first element ID to get */
885 unsigned int space; /* W: count of element IDs to get */
886 unsigned int used; /* R: count of element IDs set */
887 unsigned int count; /* R: count of all elements */
888 struct snd_ctl_elem_id __user *pids; /* R: IDs */
889 unsigned char reserved[50];
890};
891
892struct snd_ctl_elem_info {
893 struct snd_ctl_elem_id id; /* W: element ID */
894 snd_ctl_elem_type_t type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */
895 unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
896 unsigned int count; /* count of values */
897 __kernel_pid_t owner; /* owner's PID of this control */
898 union {
899 struct {
900 long min; /* R: minimum value */
901 long max; /* R: maximum value */
902 long step; /* R: step (0 variable) */
903 } integer;
904 struct {
905 long long min; /* R: minimum value */
906 long long max; /* R: maximum value */
907 long long step; /* R: step (0 variable) */
908 } integer64;
909 struct {
910 unsigned int items; /* R: number of items */
911 unsigned int item; /* W: item number */
912 char name[64]; /* R: value name */
913 __u64 names_ptr; /* W: names list (ELEM_ADD only) */
914 unsigned int names_length;
915 } enumerated;
916 unsigned char reserved[128];
917 } value;
918 union {
919 unsigned short d[4]; /* dimensions */
920 unsigned short *d_ptr; /* indirect - obsoleted */
921 } dimen;
922 unsigned char reserved[64-4*sizeof(unsigned short)];
923};
924
925struct snd_ctl_elem_value {
926 struct snd_ctl_elem_id id; /* W: element ID */
927 unsigned int indirect: 1; /* W: indirect access - obsoleted */
928 union {
929 union {
930 long value[128];
931 long *value_ptr; /* obsoleted */
932 } integer;
933 union {
934 long long value[64];
935 long long *value_ptr; /* obsoleted */
936 } integer64;
937 union {
938 unsigned int item[128];
939 unsigned int *item_ptr; /* obsoleted */
940 } enumerated;
941 union {
942 unsigned char data[512];
943 unsigned char *data_ptr; /* obsoleted */
944 } bytes;
945 struct snd_aes_iec958 iec958;
946 } value; /* RO */
947 struct timespec tstamp;
948 unsigned char reserved[128-sizeof(struct timespec)];
949};
950
951struct snd_ctl_tlv {
952 unsigned int numid; /* control element numeric identification */
953 unsigned int length; /* in bytes aligned to 4 */
954 unsigned int tlv[0]; /* first TLV */
955};
956
957#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
958#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
959#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
960#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
961#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
962#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value)
963#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id)
964#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id)
965#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
966#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info)
967#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info)
968#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id)
969#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv)
970#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv)
971#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv)
972#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
973#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info)
974#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int)
975#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info)
976#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
977#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
978#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info)
979#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
980#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int)
981#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int)
982
983/*
984 * Read interface.
985 */
986
987enum sndrv_ctl_event_type {
988 SNDRV_CTL_EVENT_ELEM = 0,
989 SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
990};
991
992#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0) /* element value was changed */
993#define SNDRV_CTL_EVENT_MASK_INFO (1<<1) /* element info was changed */
994#define SNDRV_CTL_EVENT_MASK_ADD (1<<2) /* element was added */
995#define SNDRV_CTL_EVENT_MASK_TLV (1<<3) /* element TLV tree was changed */
996#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U) /* element was removed */
997
998struct snd_ctl_event {
999 int type; /* event type - SNDRV_CTL_EVENT_* */
1000 union {
1001 struct {
1002 unsigned int mask;
1003 struct snd_ctl_elem_id id;
1004 } elem;
1005 unsigned char data8[60];
1006 } data;
1007};
1008
1009/*
1010 * Control names
1011 */
1012
1013#define SNDRV_CTL_NAME_NONE ""
1014#define SNDRV_CTL_NAME_PLAYBACK "Playback "
1015#define SNDRV_CTL_NAME_CAPTURE "Capture "
1016
1017#define SNDRV_CTL_NAME_IEC958_NONE ""
1018#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch"
1019#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume"
1020#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default"
1021#define SNDRV_CTL_NAME_IEC958_MASK "Mask"
1022#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask"
1023#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask"
1024#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream"
1025#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
1026
1027#endif /* _UAPI__SOUND_ASOUND_H */
diff --git a/tools/kvm/kvm_stat/Makefile b/tools/kvm/kvm_stat/Makefile
index 5b1cba57e3b3..c3e36c60d477 100644
--- a/tools/kvm/kvm_stat/Makefile
+++ b/tools/kvm/kvm_stat/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1include ../../scripts/Makefile.include 2include ../../scripts/Makefile.include
2include ../../scripts/utilities.mak 3include ../../scripts/utilities.mak
3BINDIR=usr/bin 4BINDIR=usr/bin
diff --git a/tools/kvm/kvm_stat/kvm_stat b/tools/kvm/kvm_stat/kvm_stat
index dd8f00cfb8b4..217cf6f95c36 100755
--- a/tools/kvm/kvm_stat/kvm_stat
+++ b/tools/kvm/kvm_stat/kvm_stat
@@ -19,9 +19,11 @@ Three different ways of output formatting are available:
19 19
20The data is sampled from the KVM's debugfs entries and its perf events. 20The data is sampled from the KVM's debugfs entries and its perf events.
21""" 21"""
22from __future__ import print_function
22 23
23import curses 24import curses
24import sys 25import sys
26import locale
25import os 27import os
26import time 28import time
27import optparse 29import optparse
@@ -225,6 +227,8 @@ IOCTL_NUMBERS = {
225 'RESET': 0x00002403, 227 'RESET': 0x00002403,
226} 228}
227 229
230ENCODING = locale.getpreferredencoding(False)
231
228 232
229class Arch(object): 233class Arch(object):
230 """Encapsulates global architecture specific data. 234 """Encapsulates global architecture specific data.
@@ -474,7 +478,7 @@ class Provider(object):
474 @staticmethod 478 @staticmethod
475 def is_field_wanted(fields_filter, field): 479 def is_field_wanted(fields_filter, field):
476 """Indicate whether field is valid according to fields_filter.""" 480 """Indicate whether field is valid according to fields_filter."""
477 if not fields_filter: 481 if not fields_filter or fields_filter == "help":
478 return True 482 return True
479 return re.match(fields_filter, field) is not None 483 return re.match(fields_filter, field) is not None
480 484
@@ -666,7 +670,7 @@ class TracepointProvider(Provider):
666 """Returns 'event name: current value' for all enabled events.""" 670 """Returns 'event name: current value' for all enabled events."""
667 ret = defaultdict(int) 671 ret = defaultdict(int)
668 for group in self.group_leaders: 672 for group in self.group_leaders:
669 for name, val in group.read().iteritems(): 673 for name, val in group.read().items():
670 if name in self._fields: 674 if name in self._fields:
671 ret[name] += val 675 ret[name] += val
672 return ret 676 return ret
@@ -955,7 +959,7 @@ class Tui(object):
955 except: 959 except:
956 raise Exception 960 raise Exception
957 for line in child.stdout: 961 for line in child.stdout:
958 line = line.lstrip().split(' ', 1) 962 line = line.decode(ENCODING).lstrip().split(' ', 1)
959 # perform a sanity check before calling the more expensive 963 # perform a sanity check before calling the more expensive
960 # function to possibly extract the guest name 964 # function to possibly extract the guest name
961 if ' -name ' in line[1]: 965 if ' -name ' in line[1]:
@@ -1005,7 +1009,7 @@ class Tui(object):
1005 name = '' 1009 name = ''
1006 try: 1010 try:
1007 line = open('/proc/{}/cmdline' 1011 line = open('/proc/{}/cmdline'
1008 .format(pid), 'rb').read().split('\0') 1012 .format(pid), 'r').read().split('\0')
1009 parms = line[line.index('-name') + 1].split(',') 1013 parms = line[line.index('-name') + 1].split(',')
1010 while '' in parms: 1014 while '' in parms:
1011 # commas are escaped (i.e. ',,'), hence e.g. 'foo,bar' results 1015 # commas are escaped (i.e. ',,'), hence e.g. 'foo,bar' results
@@ -1170,7 +1174,7 @@ class Tui(object):
1170 .format(self.stats.fields_filter)) 1174 .format(self.stats.fields_filter))
1171 self.screen.addstr(3, 0, "New regex: ") 1175 self.screen.addstr(3, 0, "New regex: ")
1172 curses.echo() 1176 curses.echo()
1173 regex = self.screen.getstr() 1177 regex = self.screen.getstr().decode(ENCODING)
1174 curses.noecho() 1178 curses.noecho()
1175 if len(regex) == 0: 1179 if len(regex) == 0:
1176 self.stats.fields_filter = DEFAULT_REGEX 1180 self.stats.fields_filter = DEFAULT_REGEX
@@ -1204,7 +1208,7 @@ class Tui(object):
1204 1208
1205 curses.echo() 1209 curses.echo()
1206 self.screen.addstr(3, 0, "Pid [0 or pid]: ") 1210 self.screen.addstr(3, 0, "Pid [0 or pid]: ")
1207 pid = self.screen.getstr() 1211 pid = self.screen.getstr().decode(ENCODING)
1208 curses.noecho() 1212 curses.noecho()
1209 1213
1210 try: 1214 try:
@@ -1233,7 +1237,7 @@ class Tui(object):
1233 self.screen.addstr(2, 0, 'Change delay from %.1fs to ' % 1237 self.screen.addstr(2, 0, 'Change delay from %.1fs to ' %
1234 self._delay_regular) 1238 self._delay_regular)
1235 curses.echo() 1239 curses.echo()
1236 val = self.screen.getstr() 1240 val = self.screen.getstr().decode(ENCODING)
1237 curses.noecho() 1241 curses.noecho()
1238 1242
1239 try: 1243 try:
@@ -1273,7 +1277,7 @@ class Tui(object):
1273 self.print_all_gnames(7) 1277 self.print_all_gnames(7)
1274 curses.echo() 1278 curses.echo()
1275 self.screen.addstr(3, 0, "Guest [ENTER or guest]: ") 1279 self.screen.addstr(3, 0, "Guest [ENTER or guest]: ")
1276 gname = self.screen.getstr() 1280 gname = self.screen.getstr().decode(ENCODING)
1277 curses.noecho() 1281 curses.noecho()
1278 1282
1279 if not gname: 1283 if not gname:
@@ -1369,25 +1373,25 @@ def batch(stats):
1369 s = stats.get() 1373 s = stats.get()
1370 for key in sorted(s.keys()): 1374 for key in sorted(s.keys()):
1371 values = s[key] 1375 values = s[key]
1372 print '%-42s%10d%10d' % (key, values[0], values[1]) 1376 print('%-42s%10d%10d' % (key, values[0], values[1]))
1373 except KeyboardInterrupt: 1377 except KeyboardInterrupt:
1374 pass 1378 pass
1375 1379
1376 1380
1377def log(stats): 1381def log(stats):
1378 """Prints statistics as reiterating key block, multiple value blocks.""" 1382 """Prints statistics as reiterating key block, multiple value blocks."""
1379 keys = sorted(stats.get().iterkeys()) 1383 keys = sorted(stats.get().keys())
1380 1384
1381 def banner(): 1385 def banner():
1382 for k in keys: 1386 for k in keys:
1383 print '%s' % k, 1387 print(k, end=' ')
1384 print 1388 print()
1385 1389
1386 def statline(): 1390 def statline():
1387 s = stats.get() 1391 s = stats.get()
1388 for k in keys: 1392 for k in keys:
1389 print ' %9d' % s[k][1], 1393 print(' %9d' % s[k][1], end=' ')
1390 print 1394 print()
1391 line = 0 1395 line = 0
1392 banner_repeat = 20 1396 banner_repeat = 20
1393 while True: 1397 while True:
@@ -1413,8 +1417,8 @@ performance.
1413 1417
1414Requirements: 1418Requirements:
1415- Access to: 1419- Access to:
1416 /sys/kernel/debug/kvm 1420 %s
1417 /sys/kernel/debug/trace/events/* 1421 %s/events/*
1418 /proc/pid/task 1422 /proc/pid/task
1419- /proc/sys/kernel/perf_event_paranoid < 1 if user has no 1423- /proc/sys/kernel/perf_event_paranoid < 1 if user has no
1420 CAP_SYS_ADMIN and perf events are used. 1424 CAP_SYS_ADMIN and perf events are used.
@@ -1434,7 +1438,7 @@ Interactive Commands:
1434 s set update interval 1438 s set update interval
1435 x toggle reporting of stats for individual child trace events 1439 x toggle reporting of stats for individual child trace events
1436Press any other key to refresh statistics immediately. 1440Press any other key to refresh statistics immediately.
1437""" 1441""" % (PATH_DEBUGFS_KVM, PATH_DEBUGFS_TRACING)
1438 1442
1439 class PlainHelpFormatter(optparse.IndentedHelpFormatter): 1443 class PlainHelpFormatter(optparse.IndentedHelpFormatter):
1440 def format_description(self, description): 1444 def format_description(self, description):
@@ -1496,7 +1500,8 @@ Press any other key to refresh statistics immediately.
1496 action='store', 1500 action='store',
1497 default=DEFAULT_REGEX, 1501 default=DEFAULT_REGEX,
1498 dest='fields', 1502 dest='fields',
1499 help='fields to display (regex)', 1503 help='''fields to display (regex)
1504 "-f help" for a list of available events''',
1500 ) 1505 )
1501 optparser.add_option('-p', '--pid', 1506 optparser.add_option('-p', '--pid',
1502 action='store', 1507 action='store',
@@ -1559,6 +1564,17 @@ def main():
1559 1564
1560 stats = Stats(options) 1565 stats = Stats(options)
1561 1566
1567 if options.fields == "help":
1568 event_list = "\n"
1569 s = stats.get()
1570 for key in s.keys():
1571 if key.find('(') != -1:
1572 key = key[0:key.find('(')]
1573 if event_list.find('\n' + key + '\n') == -1:
1574 event_list += key + '\n'
1575 sys.stdout.write(event_list)
1576 return ""
1577
1562 if options.log: 1578 if options.log:
1563 log(stats) 1579 log(stats)
1564 elif not options.once: 1580 elif not options.once:
diff --git a/tools/laptop/dslm/Makefile b/tools/laptop/dslm/Makefile
index ff613b31730b..90f512c4e2bb 100644
--- a/tools/laptop/dslm/Makefile
+++ b/tools/laptop/dslm/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1CC := $(CROSS_COMPILE)gcc 2CC := $(CROSS_COMPILE)gcc
2CFLAGS := -I../../usr/include 3CFLAGS := -I../../usr/include
3 4
diff --git a/tools/laptop/freefall/Makefile b/tools/laptop/freefall/Makefile
index 48c6c9328419..5f758c489a20 100644
--- a/tools/laptop/freefall/Makefile
+++ b/tools/laptop/freefall/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1PREFIX ?= /usr 2PREFIX ?= /usr
2SBINDIR ?= sbin 3SBINDIR ?= sbin
3INSTALL ?= install 4INSTALL ?= install
diff --git a/tools/leds/Makefile b/tools/leds/Makefile
index 078b666fd78b..c379af003807 100644
--- a/tools/leds/Makefile
+++ b/tools/leds/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# Makefile for LEDs tools 2# Makefile for LEDs tools
2 3
3CC = $(CROSS_COMPILE)gcc 4CC = $(CROSS_COMPILE)gcc
diff --git a/tools/leds/led_hw_brightness_mon.c b/tools/leds/led_hw_brightness_mon.c
index 64642ccfe442..eb65ae988839 100644
--- a/tools/leds/led_hw_brightness_mon.c
+++ b/tools/leds/led_hw_brightness_mon.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * led_hw_brightness_mon.c 3 * led_hw_brightness_mon.c
3 * 4 *
diff --git a/tools/leds/uledmon.c b/tools/leds/uledmon.c
index 25cbc7acf50a..c15a39c1f271 100644
--- a/tools/leds/uledmon.c
+++ b/tools/leds/uledmon.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * uledmon.c 3 * uledmon.c
3 * 4 *
diff --git a/tools/lguest/.gitignore b/tools/lguest/.gitignore
deleted file mode 100644
index 8d9a8383a52e..000000000000
--- a/tools/lguest/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
1lguest
2include
diff --git a/tools/lguest/Makefile b/tools/lguest/Makefile
deleted file mode 100644
index d04599a79802..000000000000
--- a/tools/lguest/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
1# This creates the demonstration utility "lguest" which runs a Linux guest.
2CFLAGS:=-m32 -Wall -Wmissing-declarations -Wmissing-prototypes -O3 -U_FORTIFY_SOURCE -Iinclude
3
4all: lguest
5
6include/linux/virtio_types.h: ../../include/uapi/linux/virtio_types.h
7 mkdir -p include/linux 2>&1 || true
8 ln -sf ../../../../include/uapi/linux/virtio_types.h $@
9
10lguest: include/linux/virtio_types.h
11
12clean:
13 rm -f lguest
14 rm -rf include
diff --git a/tools/lguest/extract b/tools/lguest/extract
deleted file mode 100644
index 7730bb6e4b94..000000000000
--- a/tools/lguest/extract
+++ /dev/null
@@ -1,58 +0,0 @@
1#! /bin/sh
2
3set -e
4
5PREFIX=$1
6shift
7
8trap 'rm -r $TMPDIR' 0
9TMPDIR=`mktemp -d`
10
11exec 3>/dev/null
12for f; do
13 while IFS="
14" read -r LINE; do
15 case "$LINE" in
16 *$PREFIX:[0-9]*:\**)
17 NUM=`echo "$LINE" | sed "s/.*$PREFIX:\([0-9]*\).*/\1/"`
18 if [ -f $TMPDIR/$NUM ]; then
19 echo "$TMPDIR/$NUM already exits prior to $f"
20 exit 1
21 fi
22 exec 3>>$TMPDIR/$NUM
23 echo $f | sed 's,\.\./,,g' > $TMPDIR/.$NUM
24 /bin/echo "$LINE" | sed -e "s/$PREFIX:[0-9]*//" -e "s/:\*/*/" >&3
25 ;;
26 *$PREFIX:[0-9]*)
27 NUM=`echo "$LINE" | sed "s/.*$PREFIX:\([0-9]*\).*/\1/"`
28 if [ -f $TMPDIR/$NUM ]; then
29 echo "$TMPDIR/$NUM already exits prior to $f"
30 exit 1
31 fi
32 exec 3>>$TMPDIR/$NUM
33 echo $f | sed 's,\.\./,,g' > $TMPDIR/.$NUM
34 /bin/echo "$LINE" | sed "s/$PREFIX:[0-9]*//" >&3
35 ;;
36 *:\**)
37 /bin/echo "$LINE" | sed -e "s/:\*/*/" -e "s,/\*\*/,," >&3
38 echo >&3
39 exec 3>/dev/null
40 ;;
41 *)
42 /bin/echo "$LINE" >&3
43 ;;
44 esac
45 done < $f
46 echo >&3
47 exec 3>/dev/null
48done
49
50LASTFILE=""
51for f in $TMPDIR/*; do
52 if [ "$LASTFILE" != $(cat $TMPDIR/.$(basename $f) ) ]; then
53 LASTFILE=$(cat $TMPDIR/.$(basename $f) )
54 echo "[ $LASTFILE ]"
55 fi
56 cat $f
57done
58
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c
deleted file mode 100644
index 897cd6f3f687..000000000000
--- a/tools/lguest/lguest.c
+++ /dev/null
@@ -1,3420 +0,0 @@
1/*P:100
2 * This is the Launcher code, a simple program which lays out the "physical"
3 * memory for the new Guest by mapping the kernel image and the virtual
4 * devices, then opens /dev/lguest to tell the kernel about the Guest and
5 * control it.
6:*/
7#define _LARGEFILE64_SOURCE
8#define _GNU_SOURCE
9#include <stdio.h>
10#include <string.h>
11#include <unistd.h>
12#include <err.h>
13#include <stdint.h>
14#include <stdlib.h>
15#include <elf.h>
16#include <sys/mman.h>
17#include <sys/param.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <sys/wait.h>
21#include <sys/eventfd.h>
22#include <fcntl.h>
23#include <stdbool.h>
24#include <errno.h>
25#include <ctype.h>
26#include <sys/socket.h>
27#include <sys/ioctl.h>
28#include <sys/time.h>
29#include <time.h>
30#include <netinet/in.h>
31#include <net/if.h>
32#include <linux/sockios.h>
33#include <linux/if_tun.h>
34#include <sys/uio.h>
35#include <termios.h>
36#include <getopt.h>
37#include <assert.h>
38#include <sched.h>
39#include <limits.h>
40#include <stddef.h>
41#include <signal.h>
42#include <pwd.h>
43#include <grp.h>
44#include <sys/user.h>
45#include <linux/pci_regs.h>
46
47#ifndef VIRTIO_F_ANY_LAYOUT
48#define VIRTIO_F_ANY_LAYOUT 27
49#endif
50
51/*L:110
52 * We can ignore the 43 include files we need for this program, but I do want
53 * to draw attention to the use of kernel-style types.
54 *
55 * As Linus said, "C is a Spartan language, and so should your naming be." I
56 * like these abbreviations, so we define them here. Note that u64 is always
57 * unsigned long long, which works on all Linux systems: this means that we can
58 * use %llu in printf for any u64.
59 */
60typedef unsigned long long u64;
61typedef uint32_t u32;
62typedef uint16_t u16;
63typedef uint8_t u8;
64/*:*/
65
66#define VIRTIO_CONFIG_NO_LEGACY
67#define VIRTIO_PCI_NO_LEGACY
68#define VIRTIO_BLK_NO_LEGACY
69#define VIRTIO_NET_NO_LEGACY
70
71/* Use in-kernel ones, which defines VIRTIO_F_VERSION_1 */
72#include "../../include/uapi/linux/virtio_config.h"
73#include "../../include/uapi/linux/virtio_net.h"
74#include "../../include/uapi/linux/virtio_blk.h"
75#include "../../include/uapi/linux/virtio_console.h"
76#include "../../include/uapi/linux/virtio_rng.h"
77#include <linux/virtio_ring.h>
78#include "../../include/uapi/linux/virtio_pci.h"
79#include <asm/bootparam.h>
80#include "../../include/linux/lguest_launcher.h"
81
82#define BRIDGE_PFX "bridge:"
83#ifndef SIOCBRADDIF
84#define SIOCBRADDIF 0x89a2 /* add interface to bridge */
85#endif
86/* We can have up to 256 pages for devices. */
87#define DEVICE_PAGES 256
88/* This will occupy 3 pages: it must be a power of 2. */
89#define VIRTQUEUE_NUM 256
90
91/*L:120
92 * verbose is both a global flag and a macro. The C preprocessor allows
93 * this, and although I wouldn't recommend it, it works quite nicely here.
94 */
95static bool verbose;
96#define verbose(args...) \
97 do { if (verbose) printf(args); } while(0)
98/*:*/
99
100/* The pointer to the start of guest memory. */
101static void *guest_base;
102/* The maximum guest physical address allowed, and maximum possible. */
103static unsigned long guest_limit, guest_max, guest_mmio;
104/* The /dev/lguest file descriptor. */
105static int lguest_fd;
106
107/* a per-cpu variable indicating whose vcpu is currently running */
108static unsigned int __thread cpu_id;
109
110/* 5 bit device number in the PCI_CONFIG_ADDR => 32 only */
111#define MAX_PCI_DEVICES 32
112
113/* This is our list of devices. */
114struct device_list {
115 /* Counter to assign interrupt numbers. */
116 unsigned int next_irq;
117
118 /* Counter to print out convenient device numbers. */
119 unsigned int device_num;
120
121 /* PCI devices. */
122 struct device *pci[MAX_PCI_DEVICES];
123};
124
125/* The list of Guest devices, based on command line arguments. */
126static struct device_list devices;
127
128/*
129 * Just like struct virtio_pci_cfg_cap in uapi/linux/virtio_pci.h,
130 * but uses a u32 explicitly for the data.
131 */
132struct virtio_pci_cfg_cap_u32 {
133 struct virtio_pci_cap cap;
134 u32 pci_cfg_data; /* Data for BAR access. */
135};
136
137struct virtio_pci_mmio {
138 struct virtio_pci_common_cfg cfg;
139 u16 notify;
140 u8 isr;
141 u8 padding;
142 /* Device-specific configuration follows this. */
143};
144
145/* This is the layout (little-endian) of the PCI config space. */
146struct pci_config {
147 u16 vendor_id, device_id;
148 u16 command, status;
149 u8 revid, prog_if, subclass, class;
150 u8 cacheline_size, lat_timer, header_type, bist;
151 u32 bar[6];
152 u32 cardbus_cis_ptr;
153 u16 subsystem_vendor_id, subsystem_device_id;
154 u32 expansion_rom_addr;
155 u8 capabilities, reserved1[3];
156 u32 reserved2;
157 u8 irq_line, irq_pin, min_grant, max_latency;
158
159 /* Now, this is the linked capability list. */
160 struct virtio_pci_cap common;
161 struct virtio_pci_notify_cap notify;
162 struct virtio_pci_cap isr;
163 struct virtio_pci_cap device;
164 struct virtio_pci_cfg_cap_u32 cfg_access;
165};
166
167/* The device structure describes a single device. */
168struct device {
169 /* The name of this device, for --verbose. */
170 const char *name;
171
172 /* Any queues attached to this device */
173 struct virtqueue *vq;
174
175 /* Is it operational */
176 bool running;
177
178 /* Has it written FEATURES_OK but not re-checked it? */
179 bool wrote_features_ok;
180
181 /* PCI configuration */
182 union {
183 struct pci_config config;
184 u32 config_words[sizeof(struct pci_config) / sizeof(u32)];
185 };
186
187 /* Features we offer, and those accepted. */
188 u64 features, features_accepted;
189
190 /* Device-specific config hangs off the end of this. */
191 struct virtio_pci_mmio *mmio;
192
193 /* PCI MMIO resources (all in BAR0) */
194 size_t mmio_size;
195 u32 mmio_addr;
196
197 /* Device-specific data. */
198 void *priv;
199};
200
201/* The virtqueue structure describes a queue attached to a device. */
202struct virtqueue {
203 struct virtqueue *next;
204
205 /* Which device owns me. */
206 struct device *dev;
207
208 /* Name for printing errors. */
209 const char *name;
210
211 /* The actual ring of buffers. */
212 struct vring vring;
213
214 /* The information about this virtqueue (we only use queue_size on) */
215 struct virtio_pci_common_cfg pci_config;
216
217 /* Last available index we saw. */
218 u16 last_avail_idx;
219
220 /* How many are used since we sent last irq? */
221 unsigned int pending_used;
222
223 /* Eventfd where Guest notifications arrive. */
224 int eventfd;
225
226 /* Function for the thread which is servicing this virtqueue. */
227 void (*service)(struct virtqueue *vq);
228 pid_t thread;
229};
230
231/* Remember the arguments to the program so we can "reboot" */
232static char **main_args;
233
234/* The original tty settings to restore on exit. */
235static struct termios orig_term;
236
237/*
238 * We have to be careful with barriers: our devices are all run in separate
239 * threads and so we need to make sure that changes visible to the Guest happen
240 * in precise order.
241 */
242#define wmb() __asm__ __volatile__("" : : : "memory")
243#define rmb() __asm__ __volatile__("lock; addl $0,0(%%esp)" : : : "memory")
244#define mb() __asm__ __volatile__("lock; addl $0,0(%%esp)" : : : "memory")
245
246/* Wrapper for the last available index. Makes it easier to change. */
247#define lg_last_avail(vq) ((vq)->last_avail_idx)
248
249/*
250 * The virtio configuration space is defined to be little-endian. x86 is
251 * little-endian too, but it's nice to be explicit so we have these helpers.
252 */
253#define cpu_to_le16(v16) (v16)
254#define cpu_to_le32(v32) (v32)
255#define cpu_to_le64(v64) (v64)
256#define le16_to_cpu(v16) (v16)
257#define le32_to_cpu(v32) (v32)
258#define le64_to_cpu(v64) (v64)
259
260/*
261 * A real device would ignore weird/non-compliant driver behaviour. We
262 * stop and flag it, to help debugging Linux problems.
263 */
264#define bad_driver(d, fmt, ...) \
265 errx(1, "%s: bad driver: " fmt, (d)->name, ## __VA_ARGS__)
266#define bad_driver_vq(vq, fmt, ...) \
267 errx(1, "%s vq %s: bad driver: " fmt, (vq)->dev->name, \
268 vq->name, ## __VA_ARGS__)
269
270/* Is this iovec empty? */
271static bool iov_empty(const struct iovec iov[], unsigned int num_iov)
272{
273 unsigned int i;
274
275 for (i = 0; i < num_iov; i++)
276 if (iov[i].iov_len)
277 return false;
278 return true;
279}
280
281/* Take len bytes from the front of this iovec. */
282static void iov_consume(struct device *d,
283 struct iovec iov[], unsigned num_iov,
284 void *dest, unsigned len)
285{
286 unsigned int i;
287
288 for (i = 0; i < num_iov; i++) {
289 unsigned int used;
290
291 used = iov[i].iov_len < len ? iov[i].iov_len : len;
292 if (dest) {
293 memcpy(dest, iov[i].iov_base, used);
294 dest += used;
295 }
296 iov[i].iov_base += used;
297 iov[i].iov_len -= used;
298 len -= used;
299 }
300 if (len != 0)
301 bad_driver(d, "iovec too short!");
302}
303
304/*L:100
305 * The Launcher code itself takes us out into userspace, that scary place where
306 * pointers run wild and free! Unfortunately, like most userspace programs,
307 * it's quite boring (which is why everyone likes to hack on the kernel!).
308 * Perhaps if you make up an Lguest Drinking Game at this point, it will get
309 * you through this section. Or, maybe not.
310 *
311 * The Launcher sets up a big chunk of memory to be the Guest's "physical"
312 * memory and stores it in "guest_base". In other words, Guest physical ==
313 * Launcher virtual with an offset.
314 *
315 * This can be tough to get your head around, but usually it just means that we
316 * use these trivial conversion functions when the Guest gives us its
317 * "physical" addresses:
318 */
319static void *from_guest_phys(unsigned long addr)
320{
321 return guest_base + addr;
322}
323
324static unsigned long to_guest_phys(const void *addr)
325{
326 return (addr - guest_base);
327}
328
329/*L:130
330 * Loading the Kernel.
331 *
332 * We start with couple of simple helper routines. open_or_die() avoids
333 * error-checking code cluttering the callers:
334 */
335static int open_or_die(const char *name, int flags)
336{
337 int fd = open(name, flags);
338 if (fd < 0)
339 err(1, "Failed to open %s", name);
340 return fd;
341}
342
343/* map_zeroed_pages() takes a number of pages. */
344static void *map_zeroed_pages(unsigned int num)
345{
346 int fd = open_or_die("/dev/zero", O_RDONLY);
347 void *addr;
348
349 /*
350 * We use a private mapping (ie. if we write to the page, it will be
351 * copied). We allocate an extra two pages PROT_NONE to act as guard
352 * pages against read/write attempts that exceed allocated space.
353 */
354 addr = mmap(NULL, getpagesize() * (num+2),
355 PROT_NONE, MAP_PRIVATE, fd, 0);
356
357 if (addr == MAP_FAILED)
358 err(1, "Mmapping %u pages of /dev/zero", num);
359
360 if (mprotect(addr + getpagesize(), getpagesize() * num,
361 PROT_READ|PROT_WRITE) == -1)
362 err(1, "mprotect rw %u pages failed", num);
363
364 /*
365 * One neat mmap feature is that you can close the fd, and it
366 * stays mapped.
367 */
368 close(fd);
369
370 /* Return address after PROT_NONE page */
371 return addr + getpagesize();
372}
373
374/* Get some bytes which won't be mapped into the guest. */
375static unsigned long get_mmio_region(size_t size)
376{
377 unsigned long addr = guest_mmio;
378 size_t i;
379
380 if (!size)
381 return addr;
382
383 /* Size has to be a power of 2 (and multiple of 16) */
384 for (i = 1; i < size; i <<= 1);
385
386 guest_mmio += i;
387
388 return addr;
389}
390
391/*
392 * This routine is used to load the kernel or initrd. It tries mmap, but if
393 * that fails (Plan 9's kernel file isn't nicely aligned on page boundaries),
394 * it falls back to reading the memory in.
395 */
396static void map_at(int fd, void *addr, unsigned long offset, unsigned long len)
397{
398 ssize_t r;
399
400 /*
401 * We map writable even though for some segments are marked read-only.
402 * The kernel really wants to be writable: it patches its own
403 * instructions.
404 *
405 * MAP_PRIVATE means that the page won't be copied until a write is
406 * done to it. This allows us to share untouched memory between
407 * Guests.
408 */
409 if (mmap(addr, len, PROT_READ|PROT_WRITE,
410 MAP_FIXED|MAP_PRIVATE, fd, offset) != MAP_FAILED)
411 return;
412
413 /* pread does a seek and a read in one shot: saves a few lines. */
414 r = pread(fd, addr, len, offset);
415 if (r != len)
416 err(1, "Reading offset %lu len %lu gave %zi", offset, len, r);
417}
418
419/*
420 * This routine takes an open vmlinux image, which is in ELF, and maps it into
421 * the Guest memory. ELF = Embedded Linking Format, which is the format used
422 * by all modern binaries on Linux including the kernel.
423 *
424 * The ELF headers give *two* addresses: a physical address, and a virtual
425 * address. We use the physical address; the Guest will map itself to the
426 * virtual address.
427 *
428 * We return the starting address.
429 */
430static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr)
431{
432 Elf32_Phdr phdr[ehdr->e_phnum];
433 unsigned int i;
434
435 /*
436 * Sanity checks on the main ELF header: an x86 executable with a
437 * reasonable number of correctly-sized program headers.
438 */
439 if (ehdr->e_type != ET_EXEC
440 || ehdr->e_machine != EM_386
441 || ehdr->e_phentsize != sizeof(Elf32_Phdr)
442 || ehdr->e_phnum < 1 || ehdr->e_phnum > 65536U/sizeof(Elf32_Phdr))
443 errx(1, "Malformed elf header");
444
445 /*
446 * An ELF executable contains an ELF header and a number of "program"
447 * headers which indicate which parts ("segments") of the program to
448 * load where.
449 */
450
451 /* We read in all the program headers at once: */
452 if (lseek(elf_fd, ehdr->e_phoff, SEEK_SET) < 0)
453 err(1, "Seeking to program headers");
454 if (read(elf_fd, phdr, sizeof(phdr)) != sizeof(phdr))
455 err(1, "Reading program headers");
456
457 /*
458 * Try all the headers: there are usually only three. A read-only one,
459 * a read-write one, and a "note" section which we don't load.
460 */
461 for (i = 0; i < ehdr->e_phnum; i++) {
462 /* If this isn't a loadable segment, we ignore it */
463 if (phdr[i].p_type != PT_LOAD)
464 continue;
465
466 verbose("Section %i: size %i addr %p\n",
467 i, phdr[i].p_memsz, (void *)phdr[i].p_paddr);
468
469 /* We map this section of the file at its physical address. */
470 map_at(elf_fd, from_guest_phys(phdr[i].p_paddr),
471 phdr[i].p_offset, phdr[i].p_filesz);
472 }
473
474 /* The entry point is given in the ELF header. */
475 return ehdr->e_entry;
476}
477
478/*L:150
479 * A bzImage, unlike an ELF file, is not meant to be loaded. You're supposed
480 * to jump into it and it will unpack itself. We used to have to perform some
481 * hairy magic because the unpacking code scared me.
482 *
483 * Fortunately, Jeremy Fitzhardinge convinced me it wasn't that hard and wrote
484 * a small patch to jump over the tricky bits in the Guest, so now we just read
485 * the funky header so we know where in the file to load, and away we go!
486 */
487static unsigned long load_bzimage(int fd)
488{
489 struct boot_params boot;
490 int r;
491 /* Modern bzImages get loaded at 1M. */
492 void *p = from_guest_phys(0x100000);
493
494 /*
495 * Go back to the start of the file and read the header. It should be
496 * a Linux boot header (see Documentation/x86/boot.txt)
497 */
498 lseek(fd, 0, SEEK_SET);
499 read(fd, &boot, sizeof(boot));
500
501 /* Inside the setup_hdr, we expect the magic "HdrS" */
502 if (memcmp(&boot.hdr.header, "HdrS", 4) != 0)
503 errx(1, "This doesn't look like a bzImage to me");
504
505 /* Skip over the extra sectors of the header. */
506 lseek(fd, (boot.hdr.setup_sects+1) * 512, SEEK_SET);
507
508 /* Now read everything into memory. in nice big chunks. */
509 while ((r = read(fd, p, 65536)) > 0)
510 p += r;
511
512 /* Finally, code32_start tells us where to enter the kernel. */
513 return boot.hdr.code32_start;
514}
515
516/*L:140
517 * Loading the kernel is easy when it's a "vmlinux", but most kernels
518 * come wrapped up in the self-decompressing "bzImage" format. With a little
519 * work, we can load those, too.
520 */
521static unsigned long load_kernel(int fd)
522{
523 Elf32_Ehdr hdr;
524
525 /* Read in the first few bytes. */
526 if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
527 err(1, "Reading kernel");
528
529 /* If it's an ELF file, it starts with "\177ELF" */
530 if (memcmp(hdr.e_ident, ELFMAG, SELFMAG) == 0)
531 return map_elf(fd, &hdr);
532
533 /* Otherwise we assume it's a bzImage, and try to load it. */
534 return load_bzimage(fd);
535}
536
537/*
538 * This is a trivial little helper to align pages. Andi Kleen hated it because
539 * it calls getpagesize() twice: "it's dumb code."
540 *
541 * Kernel guys get really het up about optimization, even when it's not
542 * necessary. I leave this code as a reaction against that.
543 */
544static inline unsigned long page_align(unsigned long addr)
545{
546 /* Add upwards and truncate downwards. */
547 return ((addr + getpagesize()-1) & ~(getpagesize()-1));
548}
549
550/*L:180
551 * An "initial ram disk" is a disk image loaded into memory along with the
552 * kernel which the kernel can use to boot from without needing any drivers.
553 * Most distributions now use this as standard: the initrd contains the code to
554 * load the appropriate driver modules for the current machine.
555 *
556 * Importantly, James Morris works for RedHat, and Fedora uses initrds for its
557 * kernels. He sent me this (and tells me when I break it).
558 */
559static unsigned long load_initrd(const char *name, unsigned long mem)
560{
561 int ifd;
562 struct stat st;
563 unsigned long len;
564
565 ifd = open_or_die(name, O_RDONLY);
566 /* fstat() is needed to get the file size. */
567 if (fstat(ifd, &st) < 0)
568 err(1, "fstat() on initrd '%s'", name);
569
570 /*
571 * We map the initrd at the top of memory, but mmap wants it to be
572 * page-aligned, so we round the size up for that.
573 */
574 len = page_align(st.st_size);
575 map_at(ifd, from_guest_phys(mem - len), 0, st.st_size);
576 /*
577 * Once a file is mapped, you can close the file descriptor. It's a
578 * little odd, but quite useful.
579 */
580 close(ifd);
581 verbose("mapped initrd %s size=%lu @ %p\n", name, len, (void*)mem-len);
582
583 /* We return the initrd size. */
584 return len;
585}
586/*:*/
587
588/*
589 * Simple routine to roll all the commandline arguments together with spaces
590 * between them.
591 */
592static void concat(char *dst, char *args[])
593{
594 unsigned int i, len = 0;
595
596 for (i = 0; args[i]; i++) {
597 if (i) {
598 strcat(dst+len, " ");
599 len++;
600 }
601 strcpy(dst+len, args[i]);
602 len += strlen(args[i]);
603 }
604 /* In case it's empty. */
605 dst[len] = '\0';
606}
607
608/*L:185
609 * This is where we actually tell the kernel to initialize the Guest. We
610 * saw the arguments it expects when we looked at initialize() in lguest_user.c:
611 * the base of Guest "physical" memory, the top physical page to allow and the
612 * entry point for the Guest.
613 */
614static void tell_kernel(unsigned long start)
615{
616 unsigned long args[] = { LHREQ_INITIALIZE,
617 (unsigned long)guest_base,
618 guest_limit / getpagesize(), start,
619 (guest_mmio+getpagesize()-1) / getpagesize() };
620 verbose("Guest: %p - %p (%#lx, MMIO %#lx)\n",
621 guest_base, guest_base + guest_limit,
622 guest_limit, guest_mmio);
623 lguest_fd = open_or_die("/dev/lguest", O_RDWR);
624 if (write(lguest_fd, args, sizeof(args)) < 0)
625 err(1, "Writing to /dev/lguest");
626}
627/*:*/
628
629/*L:200
630 * Device Handling.
631 *
632 * When the Guest gives us a buffer, it sends an array of addresses and sizes.
633 * We need to make sure it's not trying to reach into the Launcher itself, so
634 * we have a convenient routine which checks it and exits with an error message
635 * if something funny is going on:
636 */
637static void *_check_pointer(struct device *d,
638 unsigned long addr, unsigned int size,
639 unsigned int line)
640{
641 /*
642 * Check if the requested address and size exceeds the allocated memory,
643 * or addr + size wraps around.
644 */
645 if ((addr + size) > guest_limit || (addr + size) < addr)
646 bad_driver(d, "%s:%i: Invalid address %#lx",
647 __FILE__, line, addr);
648 /*
649 * We return a pointer for the caller's convenience, now we know it's
650 * safe to use.
651 */
652 return from_guest_phys(addr);
653}
654/* A macro which transparently hands the line number to the real function. */
655#define check_pointer(d,addr,size) _check_pointer(d, addr, size, __LINE__)
656
657/*
658 * Each buffer in the virtqueues is actually a chain of descriptors. This
659 * function returns the next descriptor in the chain, or vq->vring.num if we're
660 * at the end.
661 */
662static unsigned next_desc(struct device *d, struct vring_desc *desc,
663 unsigned int i, unsigned int max)
664{
665 unsigned int next;
666
667 /* If this descriptor says it doesn't chain, we're done. */
668 if (!(desc[i].flags & VRING_DESC_F_NEXT))
669 return max;
670
671 /* Check they're not leading us off end of descriptors. */
672 next = desc[i].next;
673 /* Make sure compiler knows to grab that: we don't want it changing! */
674 wmb();
675
676 if (next >= max)
677 bad_driver(d, "Desc next is %u", next);
678
679 return next;
680}
681
682/*
683 * This actually sends the interrupt for this virtqueue, if we've used a
684 * buffer.
685 */
686static void trigger_irq(struct virtqueue *vq)
687{
688 unsigned long buf[] = { LHREQ_IRQ, vq->dev->config.irq_line };
689
690 /* Don't inform them if nothing used. */
691 if (!vq->pending_used)
692 return;
693 vq->pending_used = 0;
694
695 /*
696 * 2.4.7.1:
697 *
698 * If the VIRTIO_F_EVENT_IDX feature bit is not negotiated:
699 * The driver MUST set flags to 0 or 1.
700 */
701 if (vq->vring.avail->flags > 1)
702 bad_driver_vq(vq, "avail->flags = %u\n", vq->vring.avail->flags);
703
704 /*
705 * 2.4.7.2:
706 *
707 * If the VIRTIO_F_EVENT_IDX feature bit is not negotiated:
708 *
709 * - The device MUST ignore the used_event value.
710 * - After the device writes a descriptor index into the used ring:
711 * - If flags is 1, the device SHOULD NOT send an interrupt.
712 * - If flags is 0, the device MUST send an interrupt.
713 */
714 if (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT) {
715 return;
716 }
717
718 /*
719 * 4.1.4.5.1:
720 *
721 * If MSI-X capability is disabled, the device MUST set the Queue
722 * Interrupt bit in ISR status before sending a virtqueue notification
723 * to the driver.
724 */
725 vq->dev->mmio->isr = 0x1;
726
727 /* Send the Guest an interrupt tell them we used something up. */
728 if (write(lguest_fd, buf, sizeof(buf)) != 0)
729 err(1, "Triggering irq %i", vq->dev->config.irq_line);
730}
731
732/*
733 * This looks in the virtqueue for the first available buffer, and converts
734 * it to an iovec for convenient access. Since descriptors consist of some
735 * number of output then some number of input descriptors, it's actually two
736 * iovecs, but we pack them into one and note how many of each there were.
737 *
738 * This function waits if necessary, and returns the descriptor number found.
739 */
740static unsigned wait_for_vq_desc(struct virtqueue *vq,
741 struct iovec iov[],
742 unsigned int *out_num, unsigned int *in_num)
743{
744 unsigned int i, head, max;
745 struct vring_desc *desc;
746 u16 last_avail = lg_last_avail(vq);
747
748 /*
749 * 2.4.7.1:
750 *
751 * The driver MUST handle spurious interrupts from the device.
752 *
753 * That's why this is a while loop.
754 */
755
756 /* There's nothing available? */
757 while (last_avail == vq->vring.avail->idx) {
758 u64 event;
759
760 /*
761 * Since we're about to sleep, now is a good time to tell the
762 * Guest about what we've used up to now.
763 */
764 trigger_irq(vq);
765
766 /* OK, now we need to know about added descriptors. */
767 vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
768
769 /*
770 * They could have slipped one in as we were doing that: make
771 * sure it's written, then check again.
772 */
773 mb();
774 if (last_avail != vq->vring.avail->idx) {
775 vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
776 break;
777 }
778
779 /* Nothing new? Wait for eventfd to tell us they refilled. */
780 if (read(vq->eventfd, &event, sizeof(event)) != sizeof(event))
781 errx(1, "Event read failed?");
782
783 /* We don't need to be notified again. */
784 vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
785 }
786
787 /* Check it isn't doing very strange things with descriptor numbers. */
788 if ((u16)(vq->vring.avail->idx - last_avail) > vq->vring.num)
789 bad_driver_vq(vq, "Guest moved used index from %u to %u",
790 last_avail, vq->vring.avail->idx);
791
792 /*
793 * Make sure we read the descriptor number *after* we read the ring
794 * update; don't let the cpu or compiler change the order.
795 */
796 rmb();
797
798 /*
799 * Grab the next descriptor number they're advertising, and increment
800 * the index we've seen.
801 */
802 head = vq->vring.avail->ring[last_avail % vq->vring.num];
803 lg_last_avail(vq)++;
804
805 /* If their number is silly, that's a fatal mistake. */
806 if (head >= vq->vring.num)
807 bad_driver_vq(vq, "Guest says index %u is available", head);
808
809 /* When we start there are none of either input nor output. */
810 *out_num = *in_num = 0;
811
812 max = vq->vring.num;
813 desc = vq->vring.desc;
814 i = head;
815
816 /*
817 * We have to read the descriptor after we read the descriptor number,
818 * but there's a data dependency there so the CPU shouldn't reorder
819 * that: no rmb() required.
820 */
821
822 do {
823 /*
824 * If this is an indirect entry, then this buffer contains a
825 * descriptor table which we handle as if it's any normal
826 * descriptor chain.
827 */
828 if (desc[i].flags & VRING_DESC_F_INDIRECT) {
829 /* 2.4.5.3.1:
830 *
831 * The driver MUST NOT set the VIRTQ_DESC_F_INDIRECT
832 * flag unless the VIRTIO_F_INDIRECT_DESC feature was
833 * negotiated.
834 */
835 if (!(vq->dev->features_accepted &
836 (1<<VIRTIO_RING_F_INDIRECT_DESC)))
837 bad_driver_vq(vq, "vq indirect not negotiated");
838
839 /*
840 * 2.4.5.3.1:
841 *
842 * The driver MUST NOT set the VIRTQ_DESC_F_INDIRECT
843 * flag within an indirect descriptor (ie. only one
844 * table per descriptor).
845 */
846 if (desc != vq->vring.desc)
847 bad_driver_vq(vq, "Indirect within indirect");
848
849 /*
850 * Proposed update VIRTIO-134 spells this out:
851 *
852 * A driver MUST NOT set both VIRTQ_DESC_F_INDIRECT
853 * and VIRTQ_DESC_F_NEXT in flags.
854 */
855 if (desc[i].flags & VRING_DESC_F_NEXT)
856 bad_driver_vq(vq, "indirect and next together");
857
858 if (desc[i].len % sizeof(struct vring_desc))
859 bad_driver_vq(vq,
860 "Invalid size for indirect table");
861 /*
862 * 2.4.5.3.2:
863 *
864 * The device MUST ignore the write-only flag
865 * (flags&VIRTQ_DESC_F_WRITE) in the descriptor that
866 * refers to an indirect table.
867 *
868 * We ignore it here: :)
869 */
870
871 max = desc[i].len / sizeof(struct vring_desc);
872 desc = check_pointer(vq->dev, desc[i].addr, desc[i].len);
873 i = 0;
874
875 /* 2.4.5.3.1:
876 *
877 * A driver MUST NOT create a descriptor chain longer
878 * than the Queue Size of the device.
879 */
880 if (max > vq->pci_config.queue_size)
881 bad_driver_vq(vq,
882 "indirect has too many entries");
883 }
884
885 /* Grab the first descriptor, and check it's OK. */
886 iov[*out_num + *in_num].iov_len = desc[i].len;
887 iov[*out_num + *in_num].iov_base
888 = check_pointer(vq->dev, desc[i].addr, desc[i].len);
889 /* If this is an input descriptor, increment that count. */
890 if (desc[i].flags & VRING_DESC_F_WRITE)
891 (*in_num)++;
892 else {
893 /*
894 * If it's an output descriptor, they're all supposed
895 * to come before any input descriptors.
896 */
897 if (*in_num)
898 bad_driver_vq(vq,
899 "Descriptor has out after in");
900 (*out_num)++;
901 }
902
903 /* If we've got too many, that implies a descriptor loop. */
904 if (*out_num + *in_num > max)
905 bad_driver_vq(vq, "Looped descriptor");
906 } while ((i = next_desc(vq->dev, desc, i, max)) != max);
907
908 return head;
909}
910
911/*
912 * After we've used one of their buffers, we tell the Guest about it. Sometime
913 * later we'll want to send them an interrupt using trigger_irq(); note that
914 * wait_for_vq_desc() does that for us if it has to wait.
915 */
916static void add_used(struct virtqueue *vq, unsigned int head, int len)
917{
918 struct vring_used_elem *used;
919
920 /*
921 * The virtqueue contains a ring of used buffers. Get a pointer to the
922 * next entry in that used ring.
923 */
924 used = &vq->vring.used->ring[vq->vring.used->idx % vq->vring.num];
925 used->id = head;
926 used->len = len;
927 /* Make sure buffer is written before we update index. */
928 wmb();
929 vq->vring.used->idx++;
930 vq->pending_used++;
931}
932
933/* And here's the combo meal deal. Supersize me! */
934static void add_used_and_trigger(struct virtqueue *vq, unsigned head, int len)
935{
936 add_used(vq, head, len);
937 trigger_irq(vq);
938}
939
940/*
941 * The Console
942 *
943 * We associate some data with the console for our exit hack.
944 */
945struct console_abort {
946 /* How many times have they hit ^C? */
947 int count;
948 /* When did they start? */
949 struct timeval start;
950};
951
952/* This is the routine which handles console input (ie. stdin). */
953static void console_input(struct virtqueue *vq)
954{
955 int len;
956 unsigned int head, in_num, out_num;
957 struct console_abort *abort = vq->dev->priv;
958 struct iovec iov[vq->vring.num];
959
960 /* Make sure there's a descriptor available. */
961 head = wait_for_vq_desc(vq, iov, &out_num, &in_num);
962 if (out_num)
963 bad_driver_vq(vq, "Output buffers in console in queue?");
964
965 /* Read into it. This is where we usually wait. */
966 len = readv(STDIN_FILENO, iov, in_num);
967 if (len <= 0) {
968 /* Ran out of input? */
969 warnx("Failed to get console input, ignoring console.");
970 /*
971 * For simplicity, dying threads kill the whole Launcher. So
972 * just nap here.
973 */
974 for (;;)
975 pause();
976 }
977
978 /* Tell the Guest we used a buffer. */
979 add_used_and_trigger(vq, head, len);
980
981 /*
982 * Three ^C within one second? Exit.
983 *
984 * This is such a hack, but works surprisingly well. Each ^C has to
985 * be in a buffer by itself, so they can't be too fast. But we check
986 * that we get three within about a second, so they can't be too
987 * slow.
988 */
989 if (len != 1 || ((char *)iov[0].iov_base)[0] != 3) {
990 abort->count = 0;
991 return;
992 }
993
994 abort->count++;
995 if (abort->count == 1)
996 gettimeofday(&abort->start, NULL);
997 else if (abort->count == 3) {
998 struct timeval now;
999 gettimeofday(&now, NULL);
1000 /* Kill all Launcher processes with SIGINT, like normal ^C */
1001 if (now.tv_sec <= abort->start.tv_sec+1)
1002 kill(0, SIGINT);
1003 abort->count = 0;
1004 }
1005}
1006
1007/* This is the routine which handles console output (ie. stdout). */
1008static void console_output(struct virtqueue *vq)
1009{
1010 unsigned int head, out, in;
1011 struct iovec iov[vq->vring.num];
1012
1013 /* We usually wait in here, for the Guest to give us something. */
1014 head = wait_for_vq_desc(vq, iov, &out, &in);
1015 if (in)
1016 bad_driver_vq(vq, "Input buffers in console output queue?");
1017
1018 /* writev can return a partial write, so we loop here. */
1019 while (!iov_empty(iov, out)) {
1020 int len = writev(STDOUT_FILENO, iov, out);
1021 if (len <= 0) {
1022 warn("Write to stdout gave %i (%d)", len, errno);
1023 break;
1024 }
1025 iov_consume(vq->dev, iov, out, NULL, len);
1026 }
1027
1028 /*
1029 * We're finished with that buffer: if we're going to sleep,
1030 * wait_for_vq_desc() will prod the Guest with an interrupt.
1031 */
1032 add_used(vq, head, 0);
1033}
1034
1035/*
1036 * The Network
1037 *
1038 * Handling output for network is also simple: we get all the output buffers
1039 * and write them to /dev/net/tun.
1040 */
1041struct net_info {
1042 int tunfd;
1043};
1044
1045static void net_output(struct virtqueue *vq)
1046{
1047 struct net_info *net_info = vq->dev->priv;
1048 unsigned int head, out, in;
1049 struct iovec iov[vq->vring.num];
1050
1051 /* We usually wait in here for the Guest to give us a packet. */
1052 head = wait_for_vq_desc(vq, iov, &out, &in);
1053 if (in)
1054 bad_driver_vq(vq, "Input buffers in net output queue?");
1055 /*
1056 * Send the whole thing through to /dev/net/tun. It expects the exact
1057 * same format: what a coincidence!
1058 */
1059 if (writev(net_info->tunfd, iov, out) < 0)
1060 warnx("Write to tun failed (%d)?", errno);
1061
1062 /*
1063 * Done with that one; wait_for_vq_desc() will send the interrupt if
1064 * all packets are processed.
1065 */
1066 add_used(vq, head, 0);
1067}
1068
1069/*
1070 * Handling network input is a bit trickier, because I've tried to optimize it.
1071 *
1072 * First we have a helper routine which tells is if from this file descriptor
1073 * (ie. the /dev/net/tun device) will block:
1074 */
1075static bool will_block(int fd)
1076{
1077 fd_set fdset;
1078 struct timeval zero = { 0, 0 };
1079 FD_ZERO(&fdset);
1080 FD_SET(fd, &fdset);
1081 return select(fd+1, &fdset, NULL, NULL, &zero) != 1;
1082}
1083
1084/*
1085 * This handles packets coming in from the tun device to our Guest. Like all
1086 * service routines, it gets called again as soon as it returns, so you don't
1087 * see a while(1) loop here.
1088 */
1089static void net_input(struct virtqueue *vq)
1090{
1091 int len;
1092 unsigned int head, out, in;
1093 struct iovec iov[vq->vring.num];
1094 struct net_info *net_info = vq->dev->priv;
1095
1096 /*
1097 * Get a descriptor to write an incoming packet into. This will also
1098 * send an interrupt if they're out of descriptors.
1099 */
1100 head = wait_for_vq_desc(vq, iov, &out, &in);
1101 if (out)
1102 bad_driver_vq(vq, "Output buffers in net input queue?");
1103
1104 /*
1105 * If it looks like we'll block reading from the tun device, send them
1106 * an interrupt.
1107 */
1108 if (vq->pending_used && will_block(net_info->tunfd))
1109 trigger_irq(vq);
1110
1111 /*
1112 * Read in the packet. This is where we normally wait (when there's no
1113 * incoming network traffic).
1114 */
1115 len = readv(net_info->tunfd, iov, in);
1116 if (len <= 0)
1117 warn("Failed to read from tun (%d).", errno);
1118
1119 /*
1120 * Mark that packet buffer as used, but don't interrupt here. We want
1121 * to wait until we've done as much work as we can.
1122 */
1123 add_used(vq, head, len);
1124}
1125/*:*/
1126
1127/* This is the helper to create threads: run the service routine in a loop. */
1128static int do_thread(void *_vq)
1129{
1130 struct virtqueue *vq = _vq;
1131
1132 for (;;)
1133 vq->service(vq);
1134 return 0;
1135}
1136
1137/*
1138 * When a child dies, we kill our entire process group with SIGTERM. This
1139 * also has the side effect that the shell restores the console for us!
1140 */
1141static void kill_launcher(int signal)
1142{
1143 kill(0, SIGTERM);
1144}
1145
1146static void reset_vq_pci_config(struct virtqueue *vq)
1147{
1148 vq->pci_config.queue_size = VIRTQUEUE_NUM;
1149 vq->pci_config.queue_enable = 0;
1150}
1151
1152static void reset_device(struct device *dev)
1153{
1154 struct virtqueue *vq;
1155
1156 verbose("Resetting device %s\n", dev->name);
1157
1158 /* Clear any features they've acked. */
1159 dev->features_accepted = 0;
1160
1161 /* We're going to be explicitly killing threads, so ignore them. */
1162 signal(SIGCHLD, SIG_IGN);
1163
1164 /*
1165 * 4.1.4.3.1:
1166 *
1167 * The device MUST present a 0 in queue_enable on reset.
1168 *
1169 * This means we set it here, and reset the saved ones in every vq.
1170 */
1171 dev->mmio->cfg.queue_enable = 0;
1172
1173 /* Get rid of the virtqueue threads */
1174 for (vq = dev->vq; vq; vq = vq->next) {
1175 vq->last_avail_idx = 0;
1176 reset_vq_pci_config(vq);
1177 if (vq->thread != (pid_t)-1) {
1178 kill(vq->thread, SIGTERM);
1179 waitpid(vq->thread, NULL, 0);
1180 vq->thread = (pid_t)-1;
1181 }
1182 }
1183 dev->running = false;
1184 dev->wrote_features_ok = false;
1185
1186 /* Now we care if threads die. */
1187 signal(SIGCHLD, (void *)kill_launcher);
1188}
1189
1190static void cleanup_devices(void)
1191{
1192 unsigned int i;
1193
1194 for (i = 1; i < MAX_PCI_DEVICES; i++) {
1195 struct device *d = devices.pci[i];
1196 if (!d)
1197 continue;
1198 reset_device(d);
1199 }
1200
1201 /* If we saved off the original terminal settings, restore them now. */
1202 if (orig_term.c_lflag & (ISIG|ICANON|ECHO))
1203 tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
1204}
1205
1206/*L:217
1207 * We do PCI. This is mainly done to let us test the kernel virtio PCI
1208 * code.
1209 */
1210
1211/* Linux expects a PCI host bridge: ours is a dummy, and first on the bus. */
1212static struct device pci_host_bridge;
1213
1214static void init_pci_host_bridge(void)
1215{
1216 pci_host_bridge.name = "PCI Host Bridge";
1217 pci_host_bridge.config.class = 0x06; /* bridge */
1218 pci_host_bridge.config.subclass = 0; /* host bridge */
1219 devices.pci[0] = &pci_host_bridge;
1220}
1221
1222/* The IO ports used to read the PCI config space. */
1223#define PCI_CONFIG_ADDR 0xCF8
1224#define PCI_CONFIG_DATA 0xCFC
1225
1226/*
1227 * Not really portable, but does help readability: this is what the Guest
1228 * writes to the PCI_CONFIG_ADDR IO port.
1229 */
1230union pci_config_addr {
1231 struct {
1232 unsigned mbz: 2;
1233 unsigned offset: 6;
1234 unsigned funcnum: 3;
1235 unsigned devnum: 5;
1236 unsigned busnum: 8;
1237 unsigned reserved: 7;
1238 unsigned enabled : 1;
1239 } bits;
1240 u32 val;
1241};
1242
1243/*
1244 * We cache what they wrote to the address port, so we know what they're
1245 * talking about when they access the data port.
1246 */
1247static union pci_config_addr pci_config_addr;
1248
1249static struct device *find_pci_device(unsigned int index)
1250{
1251 return devices.pci[index];
1252}
1253
1254/* PCI can do 1, 2 and 4 byte reads; we handle that here. */
1255static void ioread(u16 off, u32 v, u32 mask, u32 *val)
1256{
1257 assert(off < 4);
1258 assert(mask == 0xFF || mask == 0xFFFF || mask == 0xFFFFFFFF);
1259 *val = (v >> (off * 8)) & mask;
1260}
1261
1262/* PCI can do 1, 2 and 4 byte writes; we handle that here. */
1263static void iowrite(u16 off, u32 v, u32 mask, u32 *dst)
1264{
1265 assert(off < 4);
1266 assert(mask == 0xFF || mask == 0xFFFF || mask == 0xFFFFFFFF);
1267 *dst &= ~(mask << (off * 8));
1268 *dst |= (v & mask) << (off * 8);
1269}
1270
1271/*
1272 * Where PCI_CONFIG_DATA accesses depends on the previous write to
1273 * PCI_CONFIG_ADDR.
1274 */
1275static struct device *dev_and_reg(u32 *reg)
1276{
1277 if (!pci_config_addr.bits.enabled)
1278 return NULL;
1279
1280 if (pci_config_addr.bits.funcnum != 0)
1281 return NULL;
1282
1283 if (pci_config_addr.bits.busnum != 0)
1284 return NULL;
1285
1286 if (pci_config_addr.bits.offset * 4 >= sizeof(struct pci_config))
1287 return NULL;
1288
1289 *reg = pci_config_addr.bits.offset;
1290 return find_pci_device(pci_config_addr.bits.devnum);
1291}
1292
1293/*
1294 * We can get invalid combinations of values while they're writing, so we
1295 * only fault if they try to write with some invalid bar/offset/length.
1296 */
1297static bool valid_bar_access(struct device *d,
1298 struct virtio_pci_cfg_cap_u32 *cfg_access)
1299{
1300 /* We only have 1 bar (BAR0) */
1301 if (cfg_access->cap.bar != 0)
1302 return false;
1303
1304 /* Check it's within BAR0. */
1305 if (cfg_access->cap.offset >= d->mmio_size
1306 || cfg_access->cap.offset + cfg_access->cap.length > d->mmio_size)
1307 return false;
1308
1309 /* Check length is 1, 2 or 4. */
1310 if (cfg_access->cap.length != 1
1311 && cfg_access->cap.length != 2
1312 && cfg_access->cap.length != 4)
1313 return false;
1314
1315 /*
1316 * 4.1.4.7.2:
1317 *
1318 * The driver MUST NOT write a cap.offset which is not a multiple of
1319 * cap.length (ie. all accesses MUST be aligned).
1320 */
1321 if (cfg_access->cap.offset % cfg_access->cap.length != 0)
1322 return false;
1323
1324 /* Return pointer into word in BAR0. */
1325 return true;
1326}
1327
1328/* Is this accessing the PCI config address port?. */
1329static bool is_pci_addr_port(u16 port)
1330{
1331 return port >= PCI_CONFIG_ADDR && port < PCI_CONFIG_ADDR + 4;
1332}
1333
1334static bool pci_addr_iowrite(u16 port, u32 mask, u32 val)
1335{
1336 iowrite(port - PCI_CONFIG_ADDR, val, mask,
1337 &pci_config_addr.val);
1338 verbose("PCI%s: %#x/%x: bus %u dev %u func %u reg %u\n",
1339 pci_config_addr.bits.enabled ? "" : " DISABLED",
1340 val, mask,
1341 pci_config_addr.bits.busnum,
1342 pci_config_addr.bits.devnum,
1343 pci_config_addr.bits.funcnum,
1344 pci_config_addr.bits.offset);
1345 return true;
1346}
1347
1348static void pci_addr_ioread(u16 port, u32 mask, u32 *val)
1349{
1350 ioread(port - PCI_CONFIG_ADDR, pci_config_addr.val, mask, val);
1351}
1352
1353/* Is this accessing the PCI config data port?. */
1354static bool is_pci_data_port(u16 port)
1355{
1356 return port >= PCI_CONFIG_DATA && port < PCI_CONFIG_DATA + 4;
1357}
1358
1359static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask);
1360
1361static bool pci_data_iowrite(u16 port, u32 mask, u32 val)
1362{
1363 u32 reg, portoff;
1364 struct device *d = dev_and_reg(&reg);
1365
1366 /* Complain if they don't belong to a device. */
1367 if (!d)
1368 return false;
1369
1370 /* They can do 1 byte writes, etc. */
1371 portoff = port - PCI_CONFIG_DATA;
1372
1373 /*
1374 * PCI uses a weird way to determine the BAR size: the OS
1375 * writes all 1's, and sees which ones stick.
1376 */
1377 if (&d->config_words[reg] == &d->config.bar[0]) {
1378 int i;
1379
1380 iowrite(portoff, val, mask, &d->config.bar[0]);
1381 for (i = 0; (1 << i) < d->mmio_size; i++)
1382 d->config.bar[0] &= ~(1 << i);
1383 return true;
1384 } else if ((&d->config_words[reg] > &d->config.bar[0]
1385 && &d->config_words[reg] <= &d->config.bar[6])
1386 || &d->config_words[reg] == &d->config.expansion_rom_addr) {
1387 /* Allow writing to any other BAR, or expansion ROM */
1388 iowrite(portoff, val, mask, &d->config_words[reg]);
1389 return true;
1390 /* We let them override latency timer and cacheline size */
1391 } else if (&d->config_words[reg] == (void *)&d->config.cacheline_size) {
1392 /* Only let them change the first two fields. */
1393 if (mask == 0xFFFFFFFF)
1394 mask = 0xFFFF;
1395 iowrite(portoff, val, mask, &d->config_words[reg]);
1396 return true;
1397 } else if (&d->config_words[reg] == (void *)&d->config.command
1398 && mask == 0xFFFF) {
1399 /* Ignore command writes. */
1400 return true;
1401 } else if (&d->config_words[reg]
1402 == (void *)&d->config.cfg_access.cap.bar
1403 || &d->config_words[reg]
1404 == &d->config.cfg_access.cap.length
1405 || &d->config_words[reg]
1406 == &d->config.cfg_access.cap.offset) {
1407
1408 /*
1409 * The VIRTIO_PCI_CAP_PCI_CFG capability
1410 * provides a backdoor to access the MMIO
1411 * regions without mapping them. Weird, but
1412 * useful.
1413 */
1414 iowrite(portoff, val, mask, &d->config_words[reg]);
1415 return true;
1416 } else if (&d->config_words[reg] == &d->config.cfg_access.pci_cfg_data) {
1417 u32 write_mask;
1418
1419 /*
1420 * 4.1.4.7.1:
1421 *
1422 * Upon detecting driver write access to pci_cfg_data, the
1423 * device MUST execute a write access at offset cap.offset at
1424 * BAR selected by cap.bar using the first cap.length bytes
1425 * from pci_cfg_data.
1426 */
1427
1428 /* Must be bar 0 */
1429 if (!valid_bar_access(d, &d->config.cfg_access))
1430 return false;
1431
1432 iowrite(portoff, val, mask, &d->config.cfg_access.pci_cfg_data);
1433
1434 /*
1435 * Now emulate a write. The mask we use is set by
1436 * len, *not* this write!
1437 */
1438 write_mask = (1ULL<<(8*d->config.cfg_access.cap.length)) - 1;
1439 verbose("Window writing %#x/%#x to bar %u, offset %u len %u\n",
1440 d->config.cfg_access.pci_cfg_data, write_mask,
1441 d->config.cfg_access.cap.bar,
1442 d->config.cfg_access.cap.offset,
1443 d->config.cfg_access.cap.length);
1444
1445 emulate_mmio_write(d, d->config.cfg_access.cap.offset,
1446 d->config.cfg_access.pci_cfg_data,
1447 write_mask);
1448 return true;
1449 }
1450
1451 /*
1452 * 4.1.4.1:
1453 *
1454 * The driver MUST NOT write into any field of the capability
1455 * structure, with the exception of those with cap_type
1456 * VIRTIO_PCI_CAP_PCI_CFG...
1457 */
1458 return false;
1459}
1460
1461static u32 emulate_mmio_read(struct device *d, u32 off, u32 mask);
1462
1463static void pci_data_ioread(u16 port, u32 mask, u32 *val)
1464{
1465 u32 reg;
1466 struct device *d = dev_and_reg(&reg);
1467
1468 if (!d)
1469 return;
1470
1471 /* Read through the PCI MMIO access window is special */
1472 if (&d->config_words[reg] == &d->config.cfg_access.pci_cfg_data) {
1473 u32 read_mask;
1474
1475 /*
1476 * 4.1.4.7.1:
1477 *
1478 * Upon detecting driver read access to pci_cfg_data, the
1479 * device MUST execute a read access of length cap.length at
1480 * offset cap.offset at BAR selected by cap.bar and store the
1481 * first cap.length bytes in pci_cfg_data.
1482 */
1483 /* Must be bar 0 */
1484 if (!valid_bar_access(d, &d->config.cfg_access))
1485 bad_driver(d,
1486 "Invalid cfg_access to bar%u, offset %u len %u",
1487 d->config.cfg_access.cap.bar,
1488 d->config.cfg_access.cap.offset,
1489 d->config.cfg_access.cap.length);
1490
1491 /*
1492 * Read into the window. The mask we use is set by
1493 * len, *not* this read!
1494 */
1495 read_mask = (1ULL<<(8*d->config.cfg_access.cap.length))-1;
1496 d->config.cfg_access.pci_cfg_data
1497 = emulate_mmio_read(d,
1498 d->config.cfg_access.cap.offset,
1499 read_mask);
1500 verbose("Window read %#x/%#x from bar %u, offset %u len %u\n",
1501 d->config.cfg_access.pci_cfg_data, read_mask,
1502 d->config.cfg_access.cap.bar,
1503 d->config.cfg_access.cap.offset,
1504 d->config.cfg_access.cap.length);
1505 }
1506 ioread(port - PCI_CONFIG_DATA, d->config_words[reg], mask, val);
1507}
1508
1509/*L:216
1510 * This is where we emulate a handful of Guest instructions. It's ugly
1511 * and we used to do it in the kernel but it grew over time.
1512 */
1513
1514/*
1515 * We use the ptrace syscall's pt_regs struct to talk about registers
1516 * to lguest: these macros convert the names to the offsets.
1517 */
1518#define getreg(name) getreg_off(offsetof(struct user_regs_struct, name))
1519#define setreg(name, val) \
1520 setreg_off(offsetof(struct user_regs_struct, name), (val))
1521
1522static u32 getreg_off(size_t offset)
1523{
1524 u32 r;
1525 unsigned long args[] = { LHREQ_GETREG, offset };
1526
1527 if (pwrite(lguest_fd, args, sizeof(args), cpu_id) < 0)
1528 err(1, "Getting register %u", offset);
1529 if (pread(lguest_fd, &r, sizeof(r), cpu_id) != sizeof(r))
1530 err(1, "Reading register %u", offset);
1531
1532 return r;
1533}
1534
1535static void setreg_off(size_t offset, u32 val)
1536{
1537 unsigned long args[] = { LHREQ_SETREG, offset, val };
1538
1539 if (pwrite(lguest_fd, args, sizeof(args), cpu_id) < 0)
1540 err(1, "Setting register %u", offset);
1541}
1542
1543/* Get register by instruction encoding */
1544static u32 getreg_num(unsigned regnum, u32 mask)
1545{
1546 /* 8 bit ops use regnums 4-7 for high parts of word */
1547 if (mask == 0xFF && (regnum & 0x4))
1548 return getreg_num(regnum & 0x3, 0xFFFF) >> 8;
1549
1550 switch (regnum) {
1551 case 0: return getreg(eax) & mask;
1552 case 1: return getreg(ecx) & mask;
1553 case 2: return getreg(edx) & mask;
1554 case 3: return getreg(ebx) & mask;
1555 case 4: return getreg(esp) & mask;
1556 case 5: return getreg(ebp) & mask;
1557 case 6: return getreg(esi) & mask;
1558 case 7: return getreg(edi) & mask;
1559 }
1560 abort();
1561}
1562
1563/* Set register by instruction encoding */
1564static void setreg_num(unsigned regnum, u32 val, u32 mask)
1565{
1566 /* Don't try to set bits out of range */
1567 assert(~(val & ~mask));
1568
1569 /* 8 bit ops use regnums 4-7 for high parts of word */
1570 if (mask == 0xFF && (regnum & 0x4)) {
1571 /* Construct the 16 bits we want. */
1572 val = (val << 8) | getreg_num(regnum & 0x3, 0xFF);
1573 setreg_num(regnum & 0x3, val, 0xFFFF);
1574 return;
1575 }
1576
1577 switch (regnum) {
1578 case 0: setreg(eax, val | (getreg(eax) & ~mask)); return;
1579 case 1: setreg(ecx, val | (getreg(ecx) & ~mask)); return;
1580 case 2: setreg(edx, val | (getreg(edx) & ~mask)); return;
1581 case 3: setreg(ebx, val | (getreg(ebx) & ~mask)); return;
1582 case 4: setreg(esp, val | (getreg(esp) & ~mask)); return;
1583 case 5: setreg(ebp, val | (getreg(ebp) & ~mask)); return;
1584 case 6: setreg(esi, val | (getreg(esi) & ~mask)); return;
1585 case 7: setreg(edi, val | (getreg(edi) & ~mask)); return;
1586 }
1587 abort();
1588}
1589
1590/* Get bytes of displacement appended to instruction, from r/m encoding */
1591static u32 insn_displacement_len(u8 mod_reg_rm)
1592{
1593 /* Switch on the mod bits */
1594 switch (mod_reg_rm >> 6) {
1595 case 0:
1596 /* If mod == 0, and r/m == 101, 16-bit displacement follows */
1597 if ((mod_reg_rm & 0x7) == 0x5)
1598 return 2;
1599 /* Normally, mod == 0 means no literal displacement */
1600 return 0;
1601 case 1:
1602 /* One byte displacement */
1603 return 1;
1604 case 2:
1605 /* Four byte displacement */
1606 return 4;
1607 case 3:
1608 /* Register mode */
1609 return 0;
1610 }
1611 abort();
1612}
1613
1614static void emulate_insn(const u8 insn[])
1615{
1616 unsigned long args[] = { LHREQ_TRAP, 13 };
1617 unsigned int insnlen = 0, in = 0, small_operand = 0, byte_access;
1618 unsigned int eax, port, mask;
1619 /*
1620 * Default is to return all-ones on IO port reads, which traditionally
1621 * means "there's nothing there".
1622 */
1623 u32 val = 0xFFFFFFFF;
1624
1625 /*
1626 * This must be the Guest kernel trying to do something, not userspace!
1627 * The bottom two bits of the CS segment register are the privilege
1628 * level.
1629 */
1630 if ((getreg(xcs) & 3) != 0x1)
1631 goto no_emulate;
1632
1633 /* Decoding x86 instructions is icky. */
1634
1635 /*
1636 * Around 2.6.33, the kernel started using an emulation for the
1637 * cmpxchg8b instruction in early boot on many configurations. This
1638 * code isn't paravirtualized, and it tries to disable interrupts.
1639 * Ignore it, which will Mostly Work.
1640 */
1641 if (insn[insnlen] == 0xfa) {
1642 /* "cli", or Clear Interrupt Enable instruction. Skip it. */
1643 insnlen = 1;
1644 goto skip_insn;
1645 }
1646
1647 /*
1648 * 0x66 is an "operand prefix". It means a 16, not 32 bit in/out.
1649 */
1650 if (insn[insnlen] == 0x66) {
1651 small_operand = 1;
1652 /* The instruction is 1 byte so far, read the next byte. */
1653 insnlen = 1;
1654 }
1655
1656 /* If the lower bit isn't set, it's a single byte access */
1657 byte_access = !(insn[insnlen] & 1);
1658
1659 /*
1660 * Now we can ignore the lower bit and decode the 4 opcodes
1661 * we need to emulate.
1662 */
1663 switch (insn[insnlen] & 0xFE) {
1664 case 0xE4: /* in <next byte>,%al */
1665 port = insn[insnlen+1];
1666 insnlen += 2;
1667 in = 1;
1668 break;
1669 case 0xEC: /* in (%dx),%al */
1670 port = getreg(edx) & 0xFFFF;
1671 insnlen += 1;
1672 in = 1;
1673 break;
1674 case 0xE6: /* out %al,<next byte> */
1675 port = insn[insnlen+1];
1676 insnlen += 2;
1677 break;
1678 case 0xEE: /* out %al,(%dx) */
1679 port = getreg(edx) & 0xFFFF;
1680 insnlen += 1;
1681 break;
1682 default:
1683 /* OK, we don't know what this is, can't emulate. */
1684 goto no_emulate;
1685 }
1686
1687 /* Set a mask of the 1, 2 or 4 bytes, depending on size of IO */
1688 if (byte_access)
1689 mask = 0xFF;
1690 else if (small_operand)
1691 mask = 0xFFFF;
1692 else
1693 mask = 0xFFFFFFFF;
1694
1695 /*
1696 * If it was an "IN" instruction, they expect the result to be read
1697 * into %eax, so we change %eax.
1698 */
1699 eax = getreg(eax);
1700
1701 if (in) {
1702 /* This is the PS/2 keyboard status; 1 means ready for output */
1703 if (port == 0x64)
1704 val = 1;
1705 else if (is_pci_addr_port(port))
1706 pci_addr_ioread(port, mask, &val);
1707 else if (is_pci_data_port(port))
1708 pci_data_ioread(port, mask, &val);
1709
1710 /* Clear the bits we're about to read */
1711 eax &= ~mask;
1712 /* Copy bits in from val. */
1713 eax |= val & mask;
1714 /* Now update the register. */
1715 setreg(eax, eax);
1716 } else {
1717 if (is_pci_addr_port(port)) {
1718 if (!pci_addr_iowrite(port, mask, eax))
1719 goto bad_io;
1720 } else if (is_pci_data_port(port)) {
1721 if (!pci_data_iowrite(port, mask, eax))
1722 goto bad_io;
1723 }
1724 /* There are many other ports, eg. CMOS clock, serial
1725 * and parallel ports, so we ignore them all. */
1726 }
1727
1728 verbose("IO %s of %x to %u: %#08x\n",
1729 in ? "IN" : "OUT", mask, port, eax);
1730skip_insn:
1731 /* Finally, we've "done" the instruction, so move past it. */
1732 setreg(eip, getreg(eip) + insnlen);
1733 return;
1734
1735bad_io:
1736 warnx("Attempt to %s port %u (%#x mask)",
1737 in ? "read from" : "write to", port, mask);
1738
1739no_emulate:
1740 /* Inject trap into Guest. */
1741 if (write(lguest_fd, args, sizeof(args)) < 0)
1742 err(1, "Reinjecting trap 13 for fault at %#x", getreg(eip));
1743}
1744
1745static struct device *find_mmio_region(unsigned long paddr, u32 *off)
1746{
1747 unsigned int i;
1748
1749 for (i = 1; i < MAX_PCI_DEVICES; i++) {
1750 struct device *d = devices.pci[i];
1751
1752 if (!d)
1753 continue;
1754 if (paddr < d->mmio_addr)
1755 continue;
1756 if (paddr >= d->mmio_addr + d->mmio_size)
1757 continue;
1758 *off = paddr - d->mmio_addr;
1759 return d;
1760 }
1761 return NULL;
1762}
1763
1764/* FIXME: Use vq array. */
1765static struct virtqueue *vq_by_num(struct device *d, u32 num)
1766{
1767 struct virtqueue *vq = d->vq;
1768
1769 while (num-- && vq)
1770 vq = vq->next;
1771
1772 return vq;
1773}
1774
1775static void save_vq_config(const struct virtio_pci_common_cfg *cfg,
1776 struct virtqueue *vq)
1777{
1778 vq->pci_config = *cfg;
1779}
1780
1781static void restore_vq_config(struct virtio_pci_common_cfg *cfg,
1782 struct virtqueue *vq)
1783{
1784 /* Only restore the per-vq part */
1785 size_t off = offsetof(struct virtio_pci_common_cfg, queue_size);
1786
1787 memcpy((void *)cfg + off, (void *)&vq->pci_config + off,
1788 sizeof(*cfg) - off);
1789}
1790
1791/*
1792 * 4.1.4.3.2:
1793 *
1794 * The driver MUST configure the other virtqueue fields before
1795 * enabling the virtqueue with queue_enable.
1796 *
1797 * When they enable the virtqueue, we check that their setup is valid.
1798 */
1799static void check_virtqueue(struct device *d, struct virtqueue *vq)
1800{
1801 /* Because lguest is 32 bit, all the descriptor high bits must be 0 */
1802 if (vq->pci_config.queue_desc_hi
1803 || vq->pci_config.queue_avail_hi
1804 || vq->pci_config.queue_used_hi)
1805 bad_driver_vq(vq, "invalid 64-bit queue address");
1806
1807 /*
1808 * 2.4.1:
1809 *
1810 * The driver MUST ensure that the physical address of the first byte
1811 * of each virtqueue part is a multiple of the specified alignment
1812 * value in the above table.
1813 */
1814 if (vq->pci_config.queue_desc_lo % 16
1815 || vq->pci_config.queue_avail_lo % 2
1816 || vq->pci_config.queue_used_lo % 4)
1817 bad_driver_vq(vq, "invalid alignment in queue addresses");
1818
1819 /* Initialize the virtqueue and check they're all in range. */
1820 vq->vring.num = vq->pci_config.queue_size;
1821 vq->vring.desc = check_pointer(vq->dev,
1822 vq->pci_config.queue_desc_lo,
1823 sizeof(*vq->vring.desc) * vq->vring.num);
1824 vq->vring.avail = check_pointer(vq->dev,
1825 vq->pci_config.queue_avail_lo,
1826 sizeof(*vq->vring.avail)
1827 + (sizeof(vq->vring.avail->ring[0])
1828 * vq->vring.num));
1829 vq->vring.used = check_pointer(vq->dev,
1830 vq->pci_config.queue_used_lo,
1831 sizeof(*vq->vring.used)
1832 + (sizeof(vq->vring.used->ring[0])
1833 * vq->vring.num));
1834
1835 /*
1836 * 2.4.9.1:
1837 *
1838 * The driver MUST initialize flags in the used ring to 0
1839 * when allocating the used ring.
1840 */
1841 if (vq->vring.used->flags != 0)
1842 bad_driver_vq(vq, "invalid initial used.flags %#x",
1843 vq->vring.used->flags);
1844}
1845
1846static void start_virtqueue(struct virtqueue *vq)
1847{
1848 /*
1849 * Create stack for thread. Since the stack grows upwards, we point
1850 * the stack pointer to the end of this region.
1851 */
1852 char *stack = malloc(32768);
1853
1854 /* Create a zero-initialized eventfd. */
1855 vq->eventfd = eventfd(0, 0);
1856 if (vq->eventfd < 0)
1857 err(1, "Creating eventfd");
1858
1859 /*
1860 * CLONE_VM: because it has to access the Guest memory, and SIGCHLD so
1861 * we get a signal if it dies.
1862 */
1863 vq->thread = clone(do_thread, stack + 32768, CLONE_VM | SIGCHLD, vq);
1864 if (vq->thread == (pid_t)-1)
1865 err(1, "Creating clone");
1866}
1867
1868static void start_virtqueues(struct device *d)
1869{
1870 struct virtqueue *vq;
1871
1872 for (vq = d->vq; vq; vq = vq->next) {
1873 if (vq->pci_config.queue_enable)
1874 start_virtqueue(vq);
1875 }
1876}
1877
1878static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask)
1879{
1880 struct virtqueue *vq;
1881
1882 switch (off) {
1883 case offsetof(struct virtio_pci_mmio, cfg.device_feature_select):
1884 /*
1885 * 4.1.4.3.1:
1886 *
1887 * The device MUST present the feature bits it is offering in
1888 * device_feature, starting at bit device_feature_select ∗ 32
1889 * for any device_feature_select written by the driver
1890 */
1891 if (val == 0)
1892 d->mmio->cfg.device_feature = d->features;
1893 else if (val == 1)
1894 d->mmio->cfg.device_feature = (d->features >> 32);
1895 else
1896 d->mmio->cfg.device_feature = 0;
1897 goto feature_write_through32;
1898 case offsetof(struct virtio_pci_mmio, cfg.guest_feature_select):
1899 if (val > 1)
1900 bad_driver(d, "Unexpected driver select %u", val);
1901 goto feature_write_through32;
1902 case offsetof(struct virtio_pci_mmio, cfg.guest_feature):
1903 if (d->mmio->cfg.guest_feature_select == 0) {
1904 d->features_accepted &= ~((u64)0xFFFFFFFF);
1905 d->features_accepted |= val;
1906 } else {
1907 assert(d->mmio->cfg.guest_feature_select == 1);
1908 d->features_accepted &= 0xFFFFFFFF;
1909 d->features_accepted |= ((u64)val) << 32;
1910 }
1911 /*
1912 * 2.2.1:
1913 *
1914 * The driver MUST NOT accept a feature which the device did
1915 * not offer
1916 */
1917 if (d->features_accepted & ~d->features)
1918 bad_driver(d, "over-accepted features %#llx of %#llx",
1919 d->features_accepted, d->features);
1920 goto feature_write_through32;
1921 case offsetof(struct virtio_pci_mmio, cfg.device_status): {
1922 u8 prev;
1923
1924 verbose("%s: device status -> %#x\n", d->name, val);
1925 /*
1926 * 4.1.4.3.1:
1927 *
1928 * The device MUST reset when 0 is written to device_status,
1929 * and present a 0 in device_status once that is done.
1930 */
1931 if (val == 0) {
1932 reset_device(d);
1933 goto write_through8;
1934 }
1935
1936 /* 2.1.1: The driver MUST NOT clear a device status bit. */
1937 if (d->mmio->cfg.device_status & ~val)
1938 bad_driver(d, "unset of device status bit %#x -> %#x",
1939 d->mmio->cfg.device_status, val);
1940
1941 /*
1942 * 2.1.2:
1943 *
1944 * The device MUST NOT consume buffers or notify the driver
1945 * before DRIVER_OK.
1946 */
1947 if (val & VIRTIO_CONFIG_S_DRIVER_OK
1948 && !(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER_OK))
1949 start_virtqueues(d);
1950
1951 /*
1952 * 3.1.1:
1953 *
1954 * The driver MUST follow this sequence to initialize a device:
1955 * - Reset the device.
1956 * - Set the ACKNOWLEDGE status bit: the guest OS has
1957 * notice the device.
1958 * - Set the DRIVER status bit: the guest OS knows how
1959 * to drive the device.
1960 * - Read device feature bits, and write the subset
1961 * of feature bits understood by the OS and driver
1962 * to the device. During this step the driver MAY
1963 * read (but MUST NOT write) the device-specific
1964 * configuration fields to check that it can
1965 * support the device before accepting it.
1966 * - Set the FEATURES_OK status bit. The driver
1967 * MUST not accept new feature bits after this
1968 * step.
1969 * - Re-read device status to ensure the FEATURES_OK
1970 * bit is still set: otherwise, the device does
1971 * not support our subset of features and the
1972 * device is unusable.
1973 * - Perform device-specific setup, including
1974 * discovery of virtqueues for the device,
1975 * optional per-bus setup, reading and possibly
1976 * writing the device’s virtio configuration
1977 * space, and population of virtqueues.
1978 * - Set the DRIVER_OK status bit. At this point the
1979 * device is “live”.
1980 */
1981 prev = 0;
1982 switch (val & ~d->mmio->cfg.device_status) {
1983 case VIRTIO_CONFIG_S_DRIVER_OK:
1984 prev |= VIRTIO_CONFIG_S_FEATURES_OK; /* fall thru */
1985 case VIRTIO_CONFIG_S_FEATURES_OK:
1986 prev |= VIRTIO_CONFIG_S_DRIVER; /* fall thru */
1987 case VIRTIO_CONFIG_S_DRIVER:
1988 prev |= VIRTIO_CONFIG_S_ACKNOWLEDGE; /* fall thru */
1989 case VIRTIO_CONFIG_S_ACKNOWLEDGE:
1990 break;
1991 default:
1992 bad_driver(d, "unknown device status bit %#x -> %#x",
1993 d->mmio->cfg.device_status, val);
1994 }
1995 if (d->mmio->cfg.device_status != prev)
1996 bad_driver(d, "unexpected status transition %#x -> %#x",
1997 d->mmio->cfg.device_status, val);
1998
1999 /* If they just wrote FEATURES_OK, we make sure they read */
2000 switch (val & ~d->mmio->cfg.device_status) {
2001 case VIRTIO_CONFIG_S_FEATURES_OK:
2002 d->wrote_features_ok = true;
2003 break;
2004 case VIRTIO_CONFIG_S_DRIVER_OK:
2005 if (d->wrote_features_ok)
2006 bad_driver(d, "did not re-read FEATURES_OK");
2007 break;
2008 }
2009 goto write_through8;
2010 }
2011 case offsetof(struct virtio_pci_mmio, cfg.queue_select):
2012 vq = vq_by_num(d, val);
2013 /*
2014 * 4.1.4.3.1:
2015 *
2016 * The device MUST present a 0 in queue_size if the virtqueue
2017 * corresponding to the current queue_select is unavailable.
2018 */
2019 if (!vq) {
2020 d->mmio->cfg.queue_size = 0;
2021 goto write_through16;
2022 }
2023 /* Save registers for old vq, if it was a valid vq */
2024 if (d->mmio->cfg.queue_size)
2025 save_vq_config(&d->mmio->cfg,
2026 vq_by_num(d, d->mmio->cfg.queue_select));
2027 /* Restore the registers for the queue they asked for */
2028 restore_vq_config(&d->mmio->cfg, vq);
2029 goto write_through16;
2030 case offsetof(struct virtio_pci_mmio, cfg.queue_size):
2031 /*
2032 * 4.1.4.3.2:
2033 *
2034 * The driver MUST NOT write a value which is not a power of 2
2035 * to queue_size.
2036 */
2037 if (val & (val-1))
2038 bad_driver(d, "invalid queue size %u", val);
2039 if (d->mmio->cfg.queue_enable)
2040 bad_driver(d, "changing queue size on live device");
2041 goto write_through16;
2042 case offsetof(struct virtio_pci_mmio, cfg.queue_msix_vector):
2043 bad_driver(d, "attempt to set MSIX vector to %u", val);
2044 case offsetof(struct virtio_pci_mmio, cfg.queue_enable): {
2045 struct virtqueue *vq = vq_by_num(d, d->mmio->cfg.queue_select);
2046
2047 /*
2048 * 4.1.4.3.2:
2049 *
2050 * The driver MUST NOT write a 0 to queue_enable.
2051 */
2052 if (val != 1)
2053 bad_driver(d, "setting queue_enable to %u", val);
2054
2055 /*
2056 * 3.1.1:
2057 *
2058 * 7. Perform device-specific setup, including discovery of
2059 * virtqueues for the device, optional per-bus setup,
2060 * reading and possibly writing the device’s virtio
2061 * configuration space, and population of virtqueues.
2062 * 8. Set the DRIVER_OK status bit.
2063 *
2064 * All our devices require all virtqueues to be enabled, so
2065 * they should have done that before setting DRIVER_OK.
2066 */
2067 if (d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER_OK)
2068 bad_driver(d, "enabling vq after DRIVER_OK");
2069
2070 d->mmio->cfg.queue_enable = val;
2071 save_vq_config(&d->mmio->cfg, vq);
2072 check_virtqueue(d, vq);
2073 goto write_through16;
2074 }
2075 case offsetof(struct virtio_pci_mmio, cfg.queue_notify_off):
2076 bad_driver(d, "attempt to write to queue_notify_off");
2077 case offsetof(struct virtio_pci_mmio, cfg.queue_desc_lo):
2078 case offsetof(struct virtio_pci_mmio, cfg.queue_desc_hi):
2079 case offsetof(struct virtio_pci_mmio, cfg.queue_avail_lo):
2080 case offsetof(struct virtio_pci_mmio, cfg.queue_avail_hi):
2081 case offsetof(struct virtio_pci_mmio, cfg.queue_used_lo):
2082 case offsetof(struct virtio_pci_mmio, cfg.queue_used_hi):
2083 /*
2084 * 4.1.4.3.2:
2085 *
2086 * The driver MUST configure the other virtqueue fields before
2087 * enabling the virtqueue with queue_enable.
2088 */
2089 if (d->mmio->cfg.queue_enable)
2090 bad_driver(d, "changing queue on live device");
2091
2092 /*
2093 * 3.1.1:
2094 *
2095 * The driver MUST follow this sequence to initialize a device:
2096 *...
2097 * 5. Set the FEATURES_OK status bit. The driver MUST not
2098 * accept new feature bits after this step.
2099 */
2100 if (!(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_FEATURES_OK))
2101 bad_driver(d, "setting up vq before FEATURES_OK");
2102
2103 /*
2104 * 6. Re-read device status to ensure the FEATURES_OK bit is
2105 * still set...
2106 */
2107 if (d->wrote_features_ok)
2108 bad_driver(d, "didn't re-read FEATURES_OK before setup");
2109
2110 goto write_through32;
2111 case offsetof(struct virtio_pci_mmio, notify):
2112 vq = vq_by_num(d, val);
2113 if (!vq)
2114 bad_driver(d, "Invalid vq notification on %u", val);
2115 /* Notify the process handling this vq by adding 1 to eventfd */
2116 write(vq->eventfd, "\1\0\0\0\0\0\0\0", 8);
2117 goto write_through16;
2118 case offsetof(struct virtio_pci_mmio, isr):
2119 bad_driver(d, "Unexpected write to isr");
2120 /* Weird corner case: write to emerg_wr of console */
2121 case sizeof(struct virtio_pci_mmio)
2122 + offsetof(struct virtio_console_config, emerg_wr):
2123 if (strcmp(d->name, "console") == 0) {
2124 char c = val;
2125 write(STDOUT_FILENO, &c, 1);
2126 goto write_through32;
2127 }
2128 /* Fall through... */
2129 default:
2130 /*
2131 * 4.1.4.3.2:
2132 *
2133 * The driver MUST NOT write to device_feature, num_queues,
2134 * config_generation or queue_notify_off.
2135 */
2136 bad_driver(d, "Unexpected write to offset %u", off);
2137 }
2138
2139feature_write_through32:
2140 /*
2141 * 3.1.1:
2142 *
2143 * The driver MUST follow this sequence to initialize a device:
2144 *...
2145 * - Set the DRIVER status bit: the guest OS knows how
2146 * to drive the device.
2147 * - Read device feature bits, and write the subset
2148 * of feature bits understood by the OS and driver
2149 * to the device.
2150 *...
2151 * - Set the FEATURES_OK status bit. The driver MUST not
2152 * accept new feature bits after this step.
2153 */
2154 if (!(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER))
2155 bad_driver(d, "feature write before VIRTIO_CONFIG_S_DRIVER");
2156 if (d->mmio->cfg.device_status & VIRTIO_CONFIG_S_FEATURES_OK)
2157 bad_driver(d, "feature write after VIRTIO_CONFIG_S_FEATURES_OK");
2158
2159 /*
2160 * 4.1.3.1:
2161 *
2162 * The driver MUST access each field using the “natural” access
2163 * method, i.e. 32-bit accesses for 32-bit fields, 16-bit accesses for
2164 * 16-bit fields and 8-bit accesses for 8-bit fields.
2165 */
2166write_through32:
2167 if (mask != 0xFFFFFFFF) {
2168 bad_driver(d, "non-32-bit write to offset %u (%#x)",
2169 off, getreg(eip));
2170 return;
2171 }
2172 memcpy((char *)d->mmio + off, &val, 4);
2173 return;
2174
2175write_through16:
2176 if (mask != 0xFFFF)
2177 bad_driver(d, "non-16-bit write to offset %u (%#x)",
2178 off, getreg(eip));
2179 memcpy((char *)d->mmio + off, &val, 2);
2180 return;
2181
2182write_through8:
2183 if (mask != 0xFF)
2184 bad_driver(d, "non-8-bit write to offset %u (%#x)",
2185 off, getreg(eip));
2186 memcpy((char *)d->mmio + off, &val, 1);
2187 return;
2188}
2189
2190static u32 emulate_mmio_read(struct device *d, u32 off, u32 mask)
2191{
2192 u8 isr;
2193 u32 val = 0;
2194
2195 switch (off) {
2196 case offsetof(struct virtio_pci_mmio, cfg.device_feature_select):
2197 case offsetof(struct virtio_pci_mmio, cfg.device_feature):
2198 case offsetof(struct virtio_pci_mmio, cfg.guest_feature_select):
2199 case offsetof(struct virtio_pci_mmio, cfg.guest_feature):
2200 /*
2201 * 3.1.1:
2202 *
2203 * The driver MUST follow this sequence to initialize a device:
2204 *...
2205 * - Set the DRIVER status bit: the guest OS knows how
2206 * to drive the device.
2207 * - Read device feature bits, and write the subset
2208 * of feature bits understood by the OS and driver
2209 * to the device.
2210 */
2211 if (!(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER))
2212 bad_driver(d,
2213 "feature read before VIRTIO_CONFIG_S_DRIVER");
2214 goto read_through32;
2215 case offsetof(struct virtio_pci_mmio, cfg.msix_config):
2216 bad_driver(d, "read of msix_config");
2217 case offsetof(struct virtio_pci_mmio, cfg.num_queues):
2218 goto read_through16;
2219 case offsetof(struct virtio_pci_mmio, cfg.device_status):
2220 /* As they did read, any write of FEATURES_OK is now fine. */
2221 d->wrote_features_ok = false;
2222 goto read_through8;
2223 case offsetof(struct virtio_pci_mmio, cfg.config_generation):
2224 /*
2225 * 4.1.4.3.1:
2226 *
2227 * The device MUST present a changed config_generation after
2228 * the driver has read a device-specific configuration value
2229 * which has changed since any part of the device-specific
2230 * configuration was last read.
2231 *
2232 * This is simple: none of our devices change config, so this
2233 * is always 0.
2234 */
2235 goto read_through8;
2236 case offsetof(struct virtio_pci_mmio, notify):
2237 /*
2238 * 3.1.1:
2239 *
2240 * The driver MUST NOT notify the device before setting
2241 * DRIVER_OK.
2242 */
2243 if (!(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER_OK))
2244 bad_driver(d, "notify before VIRTIO_CONFIG_S_DRIVER_OK");
2245 goto read_through16;
2246 case offsetof(struct virtio_pci_mmio, isr):
2247 if (mask != 0xFF)
2248 bad_driver(d, "non-8-bit read from offset %u (%#x)",
2249 off, getreg(eip));
2250 isr = d->mmio->isr;
2251 /*
2252 * 4.1.4.5.1:
2253 *
2254 * The device MUST reset ISR status to 0 on driver read.
2255 */
2256 d->mmio->isr = 0;
2257 return isr;
2258 case offsetof(struct virtio_pci_mmio, padding):
2259 bad_driver(d, "read from padding (%#x)", getreg(eip));
2260 default:
2261 /* Read from device config space, beware unaligned overflow */
2262 if (off > d->mmio_size - 4)
2263 bad_driver(d, "read past end (%#x)", getreg(eip));
2264
2265 /*
2266 * 3.1.1:
2267 * The driver MUST follow this sequence to initialize a device:
2268 *...
2269 * 3. Set the DRIVER status bit: the guest OS knows how to
2270 * drive the device.
2271 * 4. Read device feature bits, and write the subset of
2272 * feature bits understood by the OS and driver to the
2273 * device. During this step the driver MAY read (but MUST NOT
2274 * write) the device-specific configuration fields to check
2275 * that it can support the device before accepting it.
2276 */
2277 if (!(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER))
2278 bad_driver(d,
2279 "config read before VIRTIO_CONFIG_S_DRIVER");
2280
2281 if (mask == 0xFFFFFFFF)
2282 goto read_through32;
2283 else if (mask == 0xFFFF)
2284 goto read_through16;
2285 else
2286 goto read_through8;
2287 }
2288
2289 /*
2290 * 4.1.3.1:
2291 *
2292 * The driver MUST access each field using the “natural” access
2293 * method, i.e. 32-bit accesses for 32-bit fields, 16-bit accesses for
2294 * 16-bit fields and 8-bit accesses for 8-bit fields.
2295 */
2296read_through32:
2297 if (mask != 0xFFFFFFFF)
2298 bad_driver(d, "non-32-bit read to offset %u (%#x)",
2299 off, getreg(eip));
2300 memcpy(&val, (char *)d->mmio + off, 4);
2301 return val;
2302
2303read_through16:
2304 if (mask != 0xFFFF)
2305 bad_driver(d, "non-16-bit read to offset %u (%#x)",
2306 off, getreg(eip));
2307 memcpy(&val, (char *)d->mmio + off, 2);
2308 return val;
2309
2310read_through8:
2311 if (mask != 0xFF)
2312 bad_driver(d, "non-8-bit read to offset %u (%#x)",
2313 off, getreg(eip));
2314 memcpy(&val, (char *)d->mmio + off, 1);
2315 return val;
2316}
2317
2318static void emulate_mmio(unsigned long paddr, const u8 *insn)
2319{
2320 u32 val, off, mask = 0xFFFFFFFF, insnlen = 0;
2321 struct device *d = find_mmio_region(paddr, &off);
2322 unsigned long args[] = { LHREQ_TRAP, 14 };
2323
2324 if (!d) {
2325 warnx("MMIO touching %#08lx (not a device)", paddr);
2326 goto reinject;
2327 }
2328
2329 /* Prefix makes it a 16 bit op */
2330 if (insn[0] == 0x66) {
2331 mask = 0xFFFF;
2332 insnlen++;
2333 }
2334
2335 /* iowrite */
2336 if (insn[insnlen] == 0x89) {
2337 /* Next byte is r/m byte: bits 3-5 are register. */
2338 val = getreg_num((insn[insnlen+1] >> 3) & 0x7, mask);
2339 emulate_mmio_write(d, off, val, mask);
2340 insnlen += 2 + insn_displacement_len(insn[insnlen+1]);
2341 } else if (insn[insnlen] == 0x8b) { /* ioread */
2342 /* Next byte is r/m byte: bits 3-5 are register. */
2343 val = emulate_mmio_read(d, off, mask);
2344 setreg_num((insn[insnlen+1] >> 3) & 0x7, val, mask);
2345 insnlen += 2 + insn_displacement_len(insn[insnlen+1]);
2346 } else if (insn[0] == 0x88) { /* 8-bit iowrite */
2347 mask = 0xff;
2348 /* Next byte is r/m byte: bits 3-5 are register. */
2349 val = getreg_num((insn[1] >> 3) & 0x7, mask);
2350 emulate_mmio_write(d, off, val, mask);
2351 insnlen = 2 + insn_displacement_len(insn[1]);
2352 } else if (insn[0] == 0x8a) { /* 8-bit ioread */
2353 mask = 0xff;
2354 val = emulate_mmio_read(d, off, mask);
2355 setreg_num((insn[1] >> 3) & 0x7, val, mask);
2356 insnlen = 2 + insn_displacement_len(insn[1]);
2357 } else {
2358 warnx("Unknown MMIO instruction touching %#08lx:"
2359 " %02x %02x %02x %02x at %u",
2360 paddr, insn[0], insn[1], insn[2], insn[3], getreg(eip));
2361 reinject:
2362 /* Inject trap into Guest. */
2363 if (write(lguest_fd, args, sizeof(args)) < 0)
2364 err(1, "Reinjecting trap 14 for fault at %#x",
2365 getreg(eip));
2366 return;
2367 }
2368
2369 /* Finally, we've "done" the instruction, so move past it. */
2370 setreg(eip, getreg(eip) + insnlen);
2371}
2372
2373/*L:190
2374 * Device Setup
2375 *
2376 * All devices need a descriptor so the Guest knows it exists, and a "struct
2377 * device" so the Launcher can keep track of it. We have common helper
2378 * routines to allocate and manage them.
2379 */
2380static void add_pci_virtqueue(struct device *dev,
2381 void (*service)(struct virtqueue *),
2382 const char *name)
2383{
2384 struct virtqueue **i, *vq = malloc(sizeof(*vq));
2385
2386 /* Initialize the virtqueue */
2387 vq->next = NULL;
2388 vq->last_avail_idx = 0;
2389 vq->dev = dev;
2390 vq->name = name;
2391
2392 /*
2393 * This is the routine the service thread will run, and its Process ID
2394 * once it's running.
2395 */
2396 vq->service = service;
2397 vq->thread = (pid_t)-1;
2398
2399 /* Initialize the configuration. */
2400 reset_vq_pci_config(vq);
2401 vq->pci_config.queue_notify_off = 0;
2402
2403 /* Add one to the number of queues */
2404 vq->dev->mmio->cfg.num_queues++;
2405
2406 /*
2407 * Add to tail of list, so dev->vq is first vq, dev->vq->next is
2408 * second.
2409 */
2410 for (i = &dev->vq; *i; i = &(*i)->next);
2411 *i = vq;
2412}
2413
2414/* The Guest accesses the feature bits via the PCI common config MMIO region */
2415static void add_pci_feature(struct device *dev, unsigned bit)
2416{
2417 dev->features |= (1ULL << bit);
2418}
2419
2420/* For devices with no config. */
2421static void no_device_config(struct device *dev)
2422{
2423 dev->mmio_addr = get_mmio_region(dev->mmio_size);
2424
2425 dev->config.bar[0] = dev->mmio_addr;
2426 /* Bottom 4 bits must be zero */
2427 assert(~(dev->config.bar[0] & 0xF));
2428}
2429
2430/* This puts the device config into BAR0 */
2431static void set_device_config(struct device *dev, const void *conf, size_t len)
2432{
2433 /* Set up BAR 0 */
2434 dev->mmio_size += len;
2435 dev->mmio = realloc(dev->mmio, dev->mmio_size);
2436 memcpy(dev->mmio + 1, conf, len);
2437
2438 /*
2439 * 4.1.4.6:
2440 *
2441 * The device MUST present at least one VIRTIO_PCI_CAP_DEVICE_CFG
2442 * capability for any device type which has a device-specific
2443 * configuration.
2444 */
2445 /* Hook up device cfg */
2446 dev->config.cfg_access.cap.cap_next
2447 = offsetof(struct pci_config, device);
2448
2449 /*
2450 * 4.1.4.6.1:
2451 *
2452 * The offset for the device-specific configuration MUST be 4-byte
2453 * aligned.
2454 */
2455 assert(dev->config.cfg_access.cap.cap_next % 4 == 0);
2456
2457 /* Fix up device cfg field length. */
2458 dev->config.device.length = len;
2459
2460 /* The rest is the same as the no-config case */
2461 no_device_config(dev);
2462}
2463
2464static void init_cap(struct virtio_pci_cap *cap, size_t caplen, int type,
2465 size_t bar_offset, size_t bar_bytes, u8 next)
2466{
2467 cap->cap_vndr = PCI_CAP_ID_VNDR;
2468 cap->cap_next = next;
2469 cap->cap_len = caplen;
2470 cap->cfg_type = type;
2471 cap->bar = 0;
2472 memset(cap->padding, 0, sizeof(cap->padding));
2473 cap->offset = bar_offset;
2474 cap->length = bar_bytes;
2475}
2476
2477/*
2478 * This sets up the pci_config structure, as defined in the virtio 1.0
2479 * standard (and PCI standard).
2480 */
2481static void init_pci_config(struct pci_config *pci, u16 type,
2482 u8 class, u8 subclass)
2483{
2484 size_t bar_offset, bar_len;
2485
2486 /*
2487 * 4.1.4.4.1:
2488 *
2489 * The device MUST either present notify_off_multiplier as an even
2490 * power of 2, or present notify_off_multiplier as 0.
2491 *
2492 * 2.1.2:
2493 *
2494 * The device MUST initialize device status to 0 upon reset.
2495 */
2496 memset(pci, 0, sizeof(*pci));
2497
2498 /* 4.1.2.1: Devices MUST have the PCI Vendor ID 0x1AF4 */
2499 pci->vendor_id = 0x1AF4;
2500 /* 4.1.2.1: ... PCI Device ID calculated by adding 0x1040 ... */
2501 pci->device_id = 0x1040 + type;
2502
2503 /*
2504 * PCI have specific codes for different types of devices.
2505 * Linux doesn't care, but it's a good clue for people looking
2506 * at the device.
2507 */
2508 pci->class = class;
2509 pci->subclass = subclass;
2510
2511 /*
2512 * 4.1.2.1:
2513 *
2514 * Non-transitional devices SHOULD have a PCI Revision ID of 1 or
2515 * higher
2516 */
2517 pci->revid = 1;
2518
2519 /*
2520 * 4.1.2.1:
2521 *
2522 * Non-transitional devices SHOULD have a PCI Subsystem Device ID of
2523 * 0x40 or higher.
2524 */
2525 pci->subsystem_device_id = 0x40;
2526
2527 /* We use our dummy interrupt controller, and irq_line is the irq */
2528 pci->irq_line = devices.next_irq++;
2529 pci->irq_pin = 0;
2530
2531 /* Support for extended capabilities. */
2532 pci->status = (1 << 4);
2533
2534 /* Link them in. */
2535 /*
2536 * 4.1.4.3.1:
2537 *
2538 * The device MUST present at least one common configuration
2539 * capability.
2540 */
2541 pci->capabilities = offsetof(struct pci_config, common);
2542
2543 /* 4.1.4.3.1 ... offset MUST be 4-byte aligned. */
2544 assert(pci->capabilities % 4 == 0);
2545
2546 bar_offset = offsetof(struct virtio_pci_mmio, cfg);
2547 bar_len = sizeof(((struct virtio_pci_mmio *)0)->cfg);
2548 init_cap(&pci->common, sizeof(pci->common), VIRTIO_PCI_CAP_COMMON_CFG,
2549 bar_offset, bar_len,
2550 offsetof(struct pci_config, notify));
2551
2552 /*
2553 * 4.1.4.4.1:
2554 *
2555 * The device MUST present at least one notification capability.
2556 */
2557 bar_offset += bar_len;
2558 bar_len = sizeof(((struct virtio_pci_mmio *)0)->notify);
2559
2560 /*
2561 * 4.1.4.4.1:
2562 *
2563 * The cap.offset MUST be 2-byte aligned.
2564 */
2565 assert(pci->common.cap_next % 2 == 0);
2566
2567 /* FIXME: Use a non-zero notify_off, for per-queue notification? */
2568 /*
2569 * 4.1.4.4.1:
2570 *
2571 * The value cap.length presented by the device MUST be at least 2 and
2572 * MUST be large enough to support queue notification offsets for all
2573 * supported queues in all possible configurations.
2574 */
2575 assert(bar_len >= 2);
2576
2577 init_cap(&pci->notify.cap, sizeof(pci->notify),
2578 VIRTIO_PCI_CAP_NOTIFY_CFG,
2579 bar_offset, bar_len,
2580 offsetof(struct pci_config, isr));
2581
2582 bar_offset += bar_len;
2583 bar_len = sizeof(((struct virtio_pci_mmio *)0)->isr);
2584 /*
2585 * 4.1.4.5.1:
2586 *
2587 * The device MUST present at least one VIRTIO_PCI_CAP_ISR_CFG
2588 * capability.
2589 */
2590 init_cap(&pci->isr, sizeof(pci->isr),
2591 VIRTIO_PCI_CAP_ISR_CFG,
2592 bar_offset, bar_len,
2593 offsetof(struct pci_config, cfg_access));
2594
2595 /*
2596 * 4.1.4.7.1:
2597 *
2598 * The device MUST present at least one VIRTIO_PCI_CAP_PCI_CFG
2599 * capability.
2600 */
2601 /* This doesn't have any presence in the BAR */
2602 init_cap(&pci->cfg_access.cap, sizeof(pci->cfg_access),
2603 VIRTIO_PCI_CAP_PCI_CFG,
2604 0, 0, 0);
2605
2606 bar_offset += bar_len + sizeof(((struct virtio_pci_mmio *)0)->padding);
2607 assert(bar_offset == sizeof(struct virtio_pci_mmio));
2608
2609 /*
2610 * This gets sewn in and length set in set_device_config().
2611 * Some devices don't have a device configuration interface, so
2612 * we never expose this if we don't call set_device_config().
2613 */
2614 init_cap(&pci->device, sizeof(pci->device), VIRTIO_PCI_CAP_DEVICE_CFG,
2615 bar_offset, 0, 0);
2616}
2617
2618/*
2619 * This routine does all the creation and setup of a new device, but we don't
2620 * actually place the MMIO region until we know the size (if any) of the
2621 * device-specific config. And we don't actually start the service threads
2622 * until later.
2623 *
2624 * See what I mean about userspace being boring?
2625 */
2626static struct device *new_pci_device(const char *name, u16 type,
2627 u8 class, u8 subclass)
2628{
2629 struct device *dev = malloc(sizeof(*dev));
2630
2631 /* Now we populate the fields one at a time. */
2632 dev->name = name;
2633 dev->vq = NULL;
2634 dev->running = false;
2635 dev->wrote_features_ok = false;
2636 dev->mmio_size = sizeof(struct virtio_pci_mmio);
2637 dev->mmio = calloc(1, dev->mmio_size);
2638 dev->features = (u64)1 << VIRTIO_F_VERSION_1;
2639 dev->features_accepted = 0;
2640
2641 if (devices.device_num + 1 >= MAX_PCI_DEVICES)
2642 errx(1, "Can only handle 31 PCI devices");
2643
2644 init_pci_config(&dev->config, type, class, subclass);
2645 assert(!devices.pci[devices.device_num+1]);
2646 devices.pci[++devices.device_num] = dev;
2647
2648 return dev;
2649}
2650
2651/*
2652 * Our first setup routine is the console. It's a fairly simple device, but
2653 * UNIX tty handling makes it uglier than it could be.
2654 */
2655static void setup_console(void)
2656{
2657 struct device *dev;
2658 struct virtio_console_config conf;
2659
2660 /* If we can save the initial standard input settings... */
2661 if (tcgetattr(STDIN_FILENO, &orig_term) == 0) {
2662 struct termios term = orig_term;
2663 /*
2664 * Then we turn off echo, line buffering and ^C etc: We want a
2665 * raw input stream to the Guest.
2666 */
2667 term.c_lflag &= ~(ISIG|ICANON|ECHO);
2668 tcsetattr(STDIN_FILENO, TCSANOW, &term);
2669 }
2670
2671 dev = new_pci_device("console", VIRTIO_ID_CONSOLE, 0x07, 0x00);
2672
2673 /* We store the console state in dev->priv, and initialize it. */
2674 dev->priv = malloc(sizeof(struct console_abort));
2675 ((struct console_abort *)dev->priv)->count = 0;
2676
2677 /*
2678 * The console needs two virtqueues: the input then the output. When
2679 * they put something the input queue, we make sure we're listening to
2680 * stdin. When they put something in the output queue, we write it to
2681 * stdout.
2682 */
2683 add_pci_virtqueue(dev, console_input, "input");
2684 add_pci_virtqueue(dev, console_output, "output");
2685
2686 /* We need a configuration area for the emerg_wr early writes. */
2687 add_pci_feature(dev, VIRTIO_CONSOLE_F_EMERG_WRITE);
2688 set_device_config(dev, &conf, sizeof(conf));
2689
2690 verbose("device %u: console\n", devices.device_num);
2691}
2692/*:*/
2693
2694/*M:010
2695 * Inter-guest networking is an interesting area. Simplest is to have a
2696 * --sharenet=<name> option which opens or creates a named pipe. This can be
2697 * used to send packets to another guest in a 1:1 manner.
2698 *
2699 * More sophisticated is to use one of the tools developed for project like UML
2700 * to do networking.
2701 *
2702 * Faster is to do virtio bonding in kernel. Doing this 1:1 would be
2703 * completely generic ("here's my vring, attach to your vring") and would work
2704 * for any traffic. Of course, namespace and permissions issues need to be
2705 * dealt with. A more sophisticated "multi-channel" virtio_net.c could hide
2706 * multiple inter-guest channels behind one interface, although it would
2707 * require some manner of hotplugging new virtio channels.
2708 *
2709 * Finally, we could use a virtio network switch in the kernel, ie. vhost.
2710:*/
2711
2712static u32 str2ip(const char *ipaddr)
2713{
2714 unsigned int b[4];
2715
2716 if (sscanf(ipaddr, "%u.%u.%u.%u", &b[0], &b[1], &b[2], &b[3]) != 4)
2717 errx(1, "Failed to parse IP address '%s'", ipaddr);
2718 return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
2719}
2720
2721static void str2mac(const char *macaddr, unsigned char mac[6])
2722{
2723 unsigned int m[6];
2724 if (sscanf(macaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
2725 &m[0], &m[1], &m[2], &m[3], &m[4], &m[5]) != 6)
2726 errx(1, "Failed to parse mac address '%s'", macaddr);
2727 mac[0] = m[0];
2728 mac[1] = m[1];
2729 mac[2] = m[2];
2730 mac[3] = m[3];
2731 mac[4] = m[4];
2732 mac[5] = m[5];
2733}
2734
2735/*
2736 * This code is "adapted" from libbridge: it attaches the Host end of the
2737 * network device to the bridge device specified by the command line.
2738 *
2739 * This is yet another James Morris contribution (I'm an IP-level guy, so I
2740 * dislike bridging), and I just try not to break it.
2741 */
2742static void add_to_bridge(int fd, const char *if_name, const char *br_name)
2743{
2744 int ifidx;
2745 struct ifreq ifr;
2746
2747 if (!*br_name)
2748 errx(1, "must specify bridge name");
2749
2750 ifidx = if_nametoindex(if_name);
2751 if (!ifidx)
2752 errx(1, "interface %s does not exist!", if_name);
2753
2754 strncpy(ifr.ifr_name, br_name, IFNAMSIZ);
2755 ifr.ifr_name[IFNAMSIZ-1] = '\0';
2756 ifr.ifr_ifindex = ifidx;
2757 if (ioctl(fd, SIOCBRADDIF, &ifr) < 0)
2758 err(1, "can't add %s to bridge %s", if_name, br_name);
2759}
2760
2761/*
2762 * This sets up the Host end of the network device with an IP address, brings
2763 * it up so packets will flow, the copies the MAC address into the hwaddr
2764 * pointer.
2765 */
2766static void configure_device(int fd, const char *tapif, u32 ipaddr)
2767{
2768 struct ifreq ifr;
2769 struct sockaddr_in sin;
2770
2771 memset(&ifr, 0, sizeof(ifr));
2772 strcpy(ifr.ifr_name, tapif);
2773
2774 /* Don't read these incantations. Just cut & paste them like I did! */
2775 sin.sin_family = AF_INET;
2776 sin.sin_addr.s_addr = htonl(ipaddr);
2777 memcpy(&ifr.ifr_addr, &sin, sizeof(sin));
2778 if (ioctl(fd, SIOCSIFADDR, &ifr) != 0)
2779 err(1, "Setting %s interface address", tapif);
2780 ifr.ifr_flags = IFF_UP;
2781 if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0)
2782 err(1, "Bringing interface %s up", tapif);
2783}
2784
2785static int get_tun_device(char tapif[IFNAMSIZ])
2786{
2787 struct ifreq ifr;
2788 int vnet_hdr_sz;
2789 int netfd;
2790
2791 /* Start with this zeroed. Messy but sure. */
2792 memset(&ifr, 0, sizeof(ifr));
2793
2794 /*
2795 * We open the /dev/net/tun device and tell it we want a tap device. A
2796 * tap device is like a tun device, only somehow different. To tell
2797 * the truth, I completely blundered my way through this code, but it
2798 * works now!
2799 */
2800 netfd = open_or_die("/dev/net/tun", O_RDWR);
2801 ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
2802 strcpy(ifr.ifr_name, "tap%d");
2803 if (ioctl(netfd, TUNSETIFF, &ifr) != 0)
2804 err(1, "configuring /dev/net/tun");
2805
2806 if (ioctl(netfd, TUNSETOFFLOAD,
2807 TUN_F_CSUM|TUN_F_TSO4|TUN_F_TSO6|TUN_F_TSO_ECN) != 0)
2808 err(1, "Could not set features for tun device");
2809
2810 /*
2811 * We don't need checksums calculated for packets coming in this
2812 * device: trust us!
2813 */
2814 ioctl(netfd, TUNSETNOCSUM, 1);
2815
2816 /*
2817 * In virtio before 1.0 (aka legacy virtio), we added a 16-bit
2818 * field at the end of the network header iff
2819 * VIRTIO_NET_F_MRG_RXBUF was negotiated. For virtio 1.0,
2820 * that became the norm, but we need to tell the tun device
2821 * about our expanded header (which is called
2822 * virtio_net_hdr_mrg_rxbuf in the legacy system).
2823 */
2824 vnet_hdr_sz = sizeof(struct virtio_net_hdr_v1);
2825 if (ioctl(netfd, TUNSETVNETHDRSZ, &vnet_hdr_sz) != 0)
2826 err(1, "Setting tun header size to %u", vnet_hdr_sz);
2827
2828 memcpy(tapif, ifr.ifr_name, IFNAMSIZ);
2829 return netfd;
2830}
2831
2832/*L:195
2833 * Our network is a Host<->Guest network. This can either use bridging or
2834 * routing, but the principle is the same: it uses the "tun" device to inject
2835 * packets into the Host as if they came in from a normal network card. We
2836 * just shunt packets between the Guest and the tun device.
2837 */
2838static void setup_tun_net(char *arg)
2839{
2840 struct device *dev;
2841 struct net_info *net_info = malloc(sizeof(*net_info));
2842 int ipfd;
2843 u32 ip = INADDR_ANY;
2844 bool bridging = false;
2845 char tapif[IFNAMSIZ], *p;
2846 struct virtio_net_config conf;
2847
2848 net_info->tunfd = get_tun_device(tapif);
2849
2850 /* First we create a new network device. */
2851 dev = new_pci_device("net", VIRTIO_ID_NET, 0x02, 0x00);
2852 dev->priv = net_info;
2853
2854 /* Network devices need a recv and a send queue, just like console. */
2855 add_pci_virtqueue(dev, net_input, "rx");
2856 add_pci_virtqueue(dev, net_output, "tx");
2857
2858 /*
2859 * We need a socket to perform the magic network ioctls to bring up the
2860 * tap interface, connect to the bridge etc. Any socket will do!
2861 */
2862 ipfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
2863 if (ipfd < 0)
2864 err(1, "opening IP socket");
2865
2866 /* If the command line was --tunnet=bridge:<name> do bridging. */
2867 if (!strncmp(BRIDGE_PFX, arg, strlen(BRIDGE_PFX))) {
2868 arg += strlen(BRIDGE_PFX);
2869 bridging = true;
2870 }
2871
2872 /* A mac address may follow the bridge name or IP address */
2873 p = strchr(arg, ':');
2874 if (p) {
2875 str2mac(p+1, conf.mac);
2876 add_pci_feature(dev, VIRTIO_NET_F_MAC);
2877 *p = '\0';
2878 }
2879
2880 /* arg is now either an IP address or a bridge name */
2881 if (bridging)
2882 add_to_bridge(ipfd, tapif, arg);
2883 else
2884 ip = str2ip(arg);
2885
2886 /* Set up the tun device. */
2887 configure_device(ipfd, tapif, ip);
2888
2889 /* Expect Guest to handle everything except UFO */
2890 add_pci_feature(dev, VIRTIO_NET_F_CSUM);
2891 add_pci_feature(dev, VIRTIO_NET_F_GUEST_CSUM);
2892 add_pci_feature(dev, VIRTIO_NET_F_GUEST_TSO4);
2893 add_pci_feature(dev, VIRTIO_NET_F_GUEST_TSO6);
2894 add_pci_feature(dev, VIRTIO_NET_F_GUEST_ECN);
2895 add_pci_feature(dev, VIRTIO_NET_F_HOST_TSO4);
2896 add_pci_feature(dev, VIRTIO_NET_F_HOST_TSO6);
2897 add_pci_feature(dev, VIRTIO_NET_F_HOST_ECN);
2898 /* We handle indirect ring entries */
2899 add_pci_feature(dev, VIRTIO_RING_F_INDIRECT_DESC);
2900 set_device_config(dev, &conf, sizeof(conf));
2901
2902 /* We don't need the socket any more; setup is done. */
2903 close(ipfd);
2904
2905 if (bridging)
2906 verbose("device %u: tun %s attached to bridge: %s\n",
2907 devices.device_num, tapif, arg);
2908 else
2909 verbose("device %u: tun %s: %s\n",
2910 devices.device_num, tapif, arg);
2911}
2912/*:*/
2913
2914/* This hangs off device->priv. */
2915struct vblk_info {
2916 /* The size of the file. */
2917 off64_t len;
2918
2919 /* The file descriptor for the file. */
2920 int fd;
2921
2922};
2923
2924/*L:210
2925 * The Disk
2926 *
2927 * The disk only has one virtqueue, so it only has one thread. It is really
2928 * simple: the Guest asks for a block number and we read or write that position
2929 * in the file.
2930 *
2931 * Before we serviced each virtqueue in a separate thread, that was unacceptably
2932 * slow: the Guest waits until the read is finished before running anything
2933 * else, even if it could have been doing useful work.
2934 *
2935 * We could have used async I/O, except it's reputed to suck so hard that
2936 * characters actually go missing from your code when you try to use it.
2937 */
2938static void blk_request(struct virtqueue *vq)
2939{
2940 struct vblk_info *vblk = vq->dev->priv;
2941 unsigned int head, out_num, in_num, wlen;
2942 int ret, i;
2943 u8 *in;
2944 struct virtio_blk_outhdr out;
2945 struct iovec iov[vq->vring.num];
2946 off64_t off;
2947
2948 /*
2949 * Get the next request, where we normally wait. It triggers the
2950 * interrupt to acknowledge previously serviced requests (if any).
2951 */
2952 head = wait_for_vq_desc(vq, iov, &out_num, &in_num);
2953
2954 /* Copy the output header from the front of the iov (adjusts iov) */
2955 iov_consume(vq->dev, iov, out_num, &out, sizeof(out));
2956
2957 /* Find and trim end of iov input array, for our status byte. */
2958 in = NULL;
2959 for (i = out_num + in_num - 1; i >= out_num; i--) {
2960 if (iov[i].iov_len > 0) {
2961 in = iov[i].iov_base + iov[i].iov_len - 1;
2962 iov[i].iov_len--;
2963 break;
2964 }
2965 }
2966 if (!in)
2967 bad_driver_vq(vq, "Bad virtblk cmd with no room for status");
2968
2969 /*
2970 * For historical reasons, block operations are expressed in 512 byte
2971 * "sectors".
2972 */
2973 off = out.sector * 512;
2974
2975 if (out.type & VIRTIO_BLK_T_OUT) {
2976 /*
2977 * Write
2978 *
2979 * Move to the right location in the block file. This can fail
2980 * if they try to write past end.
2981 */
2982 if (lseek64(vblk->fd, off, SEEK_SET) != off)
2983 err(1, "Bad seek to sector %llu", out.sector);
2984
2985 ret = writev(vblk->fd, iov, out_num);
2986 verbose("WRITE to sector %llu: %i\n", out.sector, ret);
2987
2988 /*
2989 * Grr... Now we know how long the descriptor they sent was, we
2990 * make sure they didn't try to write over the end of the block
2991 * file (possibly extending it).
2992 */
2993 if (ret > 0 && off + ret > vblk->len) {
2994 /* Trim it back to the correct length */
2995 ftruncate64(vblk->fd, vblk->len);
2996 /* Die, bad Guest, die. */
2997 bad_driver_vq(vq, "Write past end %llu+%u", off, ret);
2998 }
2999
3000 wlen = sizeof(*in);
3001 *in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
3002 } else if (out.type & VIRTIO_BLK_T_FLUSH) {
3003 /* Flush */
3004 ret = fdatasync(vblk->fd);
3005 verbose("FLUSH fdatasync: %i\n", ret);
3006 wlen = sizeof(*in);
3007 *in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
3008 } else {
3009 /*
3010 * Read
3011 *
3012 * Move to the right location in the block file. This can fail
3013 * if they try to read past end.
3014 */
3015 if (lseek64(vblk->fd, off, SEEK_SET) != off)
3016 err(1, "Bad seek to sector %llu", out.sector);
3017
3018 ret = readv(vblk->fd, iov + out_num, in_num);
3019 if (ret >= 0) {
3020 wlen = sizeof(*in) + ret;
3021 *in = VIRTIO_BLK_S_OK;
3022 } else {
3023 wlen = sizeof(*in);
3024 *in = VIRTIO_BLK_S_IOERR;
3025 }
3026 }
3027
3028 /* Finished that request. */
3029 add_used(vq, head, wlen);
3030}
3031
3032/*L:198 This actually sets up a virtual block device. */
3033static void setup_block_file(const char *filename)
3034{
3035 struct device *dev;
3036 struct vblk_info *vblk;
3037 struct virtio_blk_config conf;
3038
3039 /* Create the device. */
3040 dev = new_pci_device("block", VIRTIO_ID_BLOCK, 0x01, 0x80);
3041
3042 /* The device has one virtqueue, where the Guest places requests. */
3043 add_pci_virtqueue(dev, blk_request, "request");
3044
3045 /* Allocate the room for our own bookkeeping */
3046 vblk = dev->priv = malloc(sizeof(*vblk));
3047
3048 /* First we open the file and store the length. */
3049 vblk->fd = open_or_die(filename, O_RDWR|O_LARGEFILE);
3050 vblk->len = lseek64(vblk->fd, 0, SEEK_END);
3051
3052 /* Tell Guest how many sectors this device has. */
3053 conf.capacity = cpu_to_le64(vblk->len / 512);
3054
3055 /*
3056 * Tell Guest not to put in too many descriptors at once: two are used
3057 * for the in and out elements.
3058 */
3059 add_pci_feature(dev, VIRTIO_BLK_F_SEG_MAX);
3060 conf.seg_max = cpu_to_le32(VIRTQUEUE_NUM - 2);
3061
3062 set_device_config(dev, &conf, sizeof(struct virtio_blk_config));
3063
3064 verbose("device %u: virtblock %llu sectors\n",
3065 devices.device_num, le64_to_cpu(conf.capacity));
3066}
3067
3068/*L:211
3069 * Our random number generator device reads from /dev/urandom into the Guest's
3070 * input buffers. The usual case is that the Guest doesn't want random numbers
3071 * and so has no buffers although /dev/urandom is still readable, whereas
3072 * console is the reverse.
3073 *
3074 * The same logic applies, however.
3075 */
3076struct rng_info {
3077 int rfd;
3078};
3079
3080static void rng_input(struct virtqueue *vq)
3081{
3082 int len;
3083 unsigned int head, in_num, out_num, totlen = 0;
3084 struct rng_info *rng_info = vq->dev->priv;
3085 struct iovec iov[vq->vring.num];
3086
3087 /* First we need a buffer from the Guests's virtqueue. */
3088 head = wait_for_vq_desc(vq, iov, &out_num, &in_num);
3089 if (out_num)
3090 bad_driver_vq(vq, "Output buffers in rng?");
3091
3092 /*
3093 * Just like the console write, we loop to cover the whole iovec.
3094 * In this case, short reads actually happen quite a bit.
3095 */
3096 while (!iov_empty(iov, in_num)) {
3097 len = readv(rng_info->rfd, iov, in_num);
3098 if (len <= 0)
3099 err(1, "Read from /dev/urandom gave %i", len);
3100 iov_consume(vq->dev, iov, in_num, NULL, len);
3101 totlen += len;
3102 }
3103
3104 /* Tell the Guest about the new input. */
3105 add_used(vq, head, totlen);
3106}
3107
3108/*L:199
3109 * This creates a "hardware" random number device for the Guest.
3110 */
3111static void setup_rng(void)
3112{
3113 struct device *dev;
3114 struct rng_info *rng_info = malloc(sizeof(*rng_info));
3115
3116 /* Our device's private info simply contains the /dev/urandom fd. */
3117 rng_info->rfd = open_or_die("/dev/urandom", O_RDONLY);
3118
3119 /* Create the new device. */
3120 dev = new_pci_device("rng", VIRTIO_ID_RNG, 0xff, 0);
3121 dev->priv = rng_info;
3122
3123 /* The device has one virtqueue, where the Guest places inbufs. */
3124 add_pci_virtqueue(dev, rng_input, "input");
3125
3126 /* We don't have any configuration space */
3127 no_device_config(dev);
3128
3129 verbose("device %u: rng\n", devices.device_num);
3130}
3131/* That's the end of device setup. */
3132
3133/*L:230 Reboot is pretty easy: clean up and exec() the Launcher afresh. */
3134static void __attribute__((noreturn)) restart_guest(void)
3135{
3136 unsigned int i;
3137
3138 /*
3139 * Since we don't track all open fds, we simply close everything beyond
3140 * stderr.
3141 */
3142 for (i = 3; i < FD_SETSIZE; i++)
3143 close(i);
3144
3145 /* Reset all the devices (kills all threads). */
3146 cleanup_devices();
3147
3148 execv(main_args[0], main_args);
3149 err(1, "Could not exec %s", main_args[0]);
3150}
3151
3152/*L:220
3153 * Finally we reach the core of the Launcher which runs the Guest, serves
3154 * its input and output, and finally, lays it to rest.
3155 */
3156static void __attribute__((noreturn)) run_guest(void)
3157{
3158 for (;;) {
3159 struct lguest_pending notify;
3160 int readval;
3161
3162 /* We read from the /dev/lguest device to run the Guest. */
3163 readval = pread(lguest_fd, &notify, sizeof(notify), cpu_id);
3164 if (readval == sizeof(notify)) {
3165 if (notify.trap == 13) {
3166 verbose("Emulating instruction at %#x\n",
3167 getreg(eip));
3168 emulate_insn(notify.insn);
3169 } else if (notify.trap == 14) {
3170 verbose("Emulating MMIO at %#x\n",
3171 getreg(eip));
3172 emulate_mmio(notify.addr, notify.insn);
3173 } else
3174 errx(1, "Unknown trap %i addr %#08x\n",
3175 notify.trap, notify.addr);
3176 /* ENOENT means the Guest died. Reading tells us why. */
3177 } else if (errno == ENOENT) {
3178 char reason[1024] = { 0 };
3179 pread(lguest_fd, reason, sizeof(reason)-1, cpu_id);
3180 errx(1, "%s", reason);
3181 /* ERESTART means that we need to reboot the guest */
3182 } else if (errno == ERESTART) {
3183 restart_guest();
3184 /* Anything else means a bug or incompatible change. */
3185 } else
3186 err(1, "Running guest failed");
3187 }
3188}
3189/*L:240
3190 * This is the end of the Launcher. The good news: we are over halfway
3191 * through! The bad news: the most fiendish part of the code still lies ahead
3192 * of us.
3193 *
3194 * Are you ready? Take a deep breath and join me in the core of the Host, in
3195 * "make Host".
3196:*/
3197
3198static struct option opts[] = {
3199 { "verbose", 0, NULL, 'v' },
3200 { "tunnet", 1, NULL, 't' },
3201 { "block", 1, NULL, 'b' },
3202 { "rng", 0, NULL, 'r' },
3203 { "initrd", 1, NULL, 'i' },
3204 { "username", 1, NULL, 'u' },
3205 { "chroot", 1, NULL, 'c' },
3206 { NULL },
3207};
3208static void usage(void)
3209{
3210 errx(1, "Usage: lguest [--verbose] "
3211 "[--tunnet=(<ipaddr>:<macaddr>|bridge:<bridgename>:<macaddr>)\n"
3212 "|--block=<filename>|--initrd=<filename>]...\n"
3213 "<mem-in-mb> vmlinux [args...]");
3214}
3215
3216/*L:105 The main routine is where the real work begins: */
3217int main(int argc, char *argv[])
3218{
3219 /* Memory, code startpoint and size of the (optional) initrd. */
3220 unsigned long mem = 0, start, initrd_size = 0;
3221 /* Two temporaries. */
3222 int i, c;
3223 /* The boot information for the Guest. */
3224 struct boot_params *boot;
3225 /* If they specify an initrd file to load. */
3226 const char *initrd_name = NULL;
3227
3228 /* Password structure for initgroups/setres[gu]id */
3229 struct passwd *user_details = NULL;
3230
3231 /* Directory to chroot to */
3232 char *chroot_path = NULL;
3233
3234 /* Save the args: we "reboot" by execing ourselves again. */
3235 main_args = argv;
3236
3237 /*
3238 * First we initialize the device list. We remember next interrupt
3239 * number to use for devices (1: remember that 0 is used by the timer).
3240 */
3241 devices.next_irq = 1;
3242
3243 /* We're CPU 0. In fact, that's the only CPU possible right now. */
3244 cpu_id = 0;
3245
3246 /*
3247 * We need to know how much memory so we can set up the device
3248 * descriptor and memory pages for the devices as we parse the command
3249 * line. So we quickly look through the arguments to find the amount
3250 * of memory now.
3251 */
3252 for (i = 1; i < argc; i++) {
3253 if (argv[i][0] != '-') {
3254 mem = atoi(argv[i]) * 1024 * 1024;
3255 /*
3256 * We start by mapping anonymous pages over all of
3257 * guest-physical memory range. This fills it with 0,
3258 * and ensures that the Guest won't be killed when it
3259 * tries to access it.
3260 */
3261 guest_base = map_zeroed_pages(mem / getpagesize()
3262 + DEVICE_PAGES);
3263 guest_limit = mem;
3264 guest_max = guest_mmio = mem + DEVICE_PAGES*getpagesize();
3265 break;
3266 }
3267 }
3268
3269 /* If we exit via err(), this kills all the threads, restores tty. */
3270 atexit(cleanup_devices);
3271
3272 /* We always have a console device, and it's always device 1. */
3273 setup_console();
3274
3275 /* The options are fairly straight-forward */
3276 while ((c = getopt_long(argc, argv, "v", opts, NULL)) != EOF) {
3277 switch (c) {
3278 case 'v':
3279 verbose = true;
3280 break;
3281 case 't':
3282 setup_tun_net(optarg);
3283 break;
3284 case 'b':
3285 setup_block_file(optarg);
3286 break;
3287 case 'r':
3288 setup_rng();
3289 break;
3290 case 'i':
3291 initrd_name = optarg;
3292 break;
3293 case 'u':
3294 user_details = getpwnam(optarg);
3295 if (!user_details)
3296 err(1, "getpwnam failed, incorrect username?");
3297 break;
3298 case 'c':
3299 chroot_path = optarg;
3300 break;
3301 default:
3302 warnx("Unknown argument %s", argv[optind]);
3303 usage();
3304 }
3305 }
3306 /*
3307 * After the other arguments we expect memory and kernel image name,
3308 * followed by command line arguments for the kernel.
3309 */
3310 if (optind + 2 > argc)
3311 usage();
3312
3313 verbose("Guest base is at %p\n", guest_base);
3314
3315 /* Initialize the (fake) PCI host bridge device. */
3316 init_pci_host_bridge();
3317
3318 /* Now we load the kernel */
3319 start = load_kernel(open_or_die(argv[optind+1], O_RDONLY));
3320
3321 /* Boot information is stashed at physical address 0 */
3322 boot = from_guest_phys(0);
3323
3324 /* Map the initrd image if requested (at top of physical memory) */
3325 if (initrd_name) {
3326 initrd_size = load_initrd(initrd_name, mem);
3327 /*
3328 * These are the location in the Linux boot header where the
3329 * start and size of the initrd are expected to be found.
3330 */
3331 boot->hdr.ramdisk_image = mem - initrd_size;
3332 boot->hdr.ramdisk_size = initrd_size;
3333 /* The bootloader type 0xFF means "unknown"; that's OK. */
3334 boot->hdr.type_of_loader = 0xFF;
3335 }
3336
3337 /*
3338 * The Linux boot header contains an "E820" memory map: ours is a
3339 * simple, single region.
3340 */
3341 boot->e820_entries = 1;
3342 boot->e820_table[0] = ((struct e820_entry) { 0, mem, E820_TYPE_RAM });
3343 /*
3344 * The boot header contains a command line pointer: we put the command
3345 * line after the boot header.
3346 */
3347 boot->hdr.cmd_line_ptr = to_guest_phys(boot + 1);
3348 /* We use a simple helper to copy the arguments separated by spaces. */
3349 concat((char *)(boot + 1), argv+optind+2);
3350
3351 /* Set kernel alignment to 16M (CONFIG_PHYSICAL_ALIGN) */
3352 boot->hdr.kernel_alignment = 0x1000000;
3353
3354 /* Boot protocol version: 2.07 supports the fields for lguest. */
3355 boot->hdr.version = 0x207;
3356
3357 /* X86_SUBARCH_LGUEST tells the Guest it's an lguest. */
3358 boot->hdr.hardware_subarch = X86_SUBARCH_LGUEST;
3359
3360 /* Tell the entry path not to try to reload segment registers. */
3361 boot->hdr.loadflags |= KEEP_SEGMENTS;
3362
3363 /* We don't support tboot: */
3364 boot->tboot_addr = 0;
3365
3366 /* Ensure this is 0 to prevent APM from loading: */
3367 boot->apm_bios_info.version = 0;
3368
3369 /* We tell the kernel to initialize the Guest. */
3370 tell_kernel(start);
3371
3372 /* Ensure that we terminate if a device-servicing child dies. */
3373 signal(SIGCHLD, kill_launcher);
3374
3375 /* If requested, chroot to a directory */
3376 if (chroot_path) {
3377 if (chroot(chroot_path) != 0)
3378 err(1, "chroot(\"%s\") failed", chroot_path);
3379
3380 if (chdir("/") != 0)
3381 err(1, "chdir(\"/\") failed");
3382
3383 verbose("chroot done\n");
3384 }
3385
3386 /* If requested, drop privileges */
3387 if (user_details) {
3388 uid_t u;
3389 gid_t g;
3390
3391 u = user_details->pw_uid;
3392 g = user_details->pw_gid;
3393
3394 if (initgroups(user_details->pw_name, g) != 0)
3395 err(1, "initgroups failed");
3396
3397 if (setresgid(g, g, g) != 0)
3398 err(1, "setresgid failed");
3399
3400 if (setresuid(u, u, u) != 0)
3401 err(1, "setresuid failed");
3402
3403 verbose("Dropping privileges completed\n");
3404 }
3405
3406 /* Finally, run the Guest. This doesn't return. */
3407 run_guest();
3408}
3409/*:*/
3410
3411/*M:999
3412 * Mastery is done: you now know everything I do.
3413 *
3414 * But surely you have seen code, features and bugs in your wanderings which
3415 * you now yearn to attack? That is the real game, and I look forward to you
3416 * patching and forking lguest into the Your-Name-Here-visor.
3417 *
3418 * Farewell, and good coding!
3419 * Rusty Russell.
3420 */
diff --git a/tools/lguest/lguest.txt b/tools/lguest/lguest.txt
deleted file mode 100644
index 06e1f4649511..000000000000
--- a/tools/lguest/lguest.txt
+++ /dev/null
@@ -1,125 +0,0 @@
1 __
2 (___()'`; Rusty's Remarkably Unreliable Guide to Lguest
3 /, /` - or, A Young Coder's Illustrated Hypervisor
4 \\"--\\ http://lguest.ozlabs.org
5
6Lguest is designed to be a minimal 32-bit x86 hypervisor for the Linux kernel,
7for Linux developers and users to experiment with virtualization with the
8minimum of complexity. Nonetheless, it should have sufficient features to
9make it useful for specific tasks, and, of course, you are encouraged to fork
10and enhance it (see drivers/lguest/README).
11
12Features:
13
14- Kernel module which runs in a normal kernel.
15- Simple I/O model for communication.
16- Simple program to create new guests.
17- Logo contains cute puppies: http://lguest.ozlabs.org
18
19Developer features:
20
21- Fun to hack on.
22- No ABI: being tied to a specific kernel anyway, you can change anything.
23- Many opportunities for improvement or feature implementation.
24
25Running Lguest:
26
27- The easiest way to run lguest is to use same kernel as guest and host.
28 You can configure them differently, but usually it's easiest not to.
29
30 You will need to configure your kernel with the following options:
31
32 "Processor type and features":
33 "Paravirtualized guest support" = Y
34 "Lguest guest support" = Y
35 "High Memory Support" = off/4GB
36 "Alignment value to which kernel should be aligned" = 0x100000
37 (CONFIG_PARAVIRT=y, CONFIG_LGUEST_GUEST=y, CONFIG_HIGHMEM64G=n and
38 CONFIG_PHYSICAL_ALIGN=0x100000)
39
40 "Device Drivers":
41 "Block devices"
42 "Virtio block driver" = M/Y
43 "Network device support"
44 "Universal TUN/TAP device driver support" = M/Y
45 "Virtio network driver" = M/Y
46 (CONFIG_VIRTIO_BLK=m, CONFIG_VIRTIO_NET=m and CONFIG_TUN=m)
47
48 "Virtualization"
49 "Linux hypervisor example code" = M/Y
50 (CONFIG_LGUEST=m)
51
52- A tool called "lguest" is available in this directory: type "make"
53 to build it. If you didn't build your kernel in-tree, use "make
54 O=<builddir>".
55
56- Create or find a root disk image. There are several useful ones
57 around, such as the xm-test tiny root image at
58 http://xm-test.xensource.com/ramdisks/initrd-1.1-i386.img
59
60 For more serious work, I usually use a distribution ISO image and
61 install it under qemu, then make multiple copies:
62
63 dd if=/dev/zero of=rootfile bs=1M count=2048
64 qemu -cdrom image.iso -hda rootfile -net user -net nic -boot d
65
66 Make sure that you install a getty on /dev/hvc0 if you want to log in on the
67 console!
68
69- "modprobe lg" if you built it as a module.
70
71- Run an lguest as root:
72
73 tools/lguest/lguest 64 vmlinux --tunnet=192.168.19.1 \
74 --block=rootfile root=/dev/vda
75
76 Explanation:
77 64: the amount of memory to use, in MB.
78
79 vmlinux: the kernel image found in the top of your build directory. You
80 can also use a standard bzImage.
81
82 --tunnet=192.168.19.1: configures a "tap" device for networking with this
83 IP address.
84
85 --block=rootfile: a file or block device which becomes /dev/vda
86 inside the guest.
87
88 root=/dev/vda: this (and anything else on the command line) are
89 kernel boot parameters.
90
91- Configuring networking. I usually have the host masquerade, using
92 "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE" and "echo 1 >
93 /proc/sys/net/ipv4/ip_forward". In this example, I would configure
94 eth0 inside the guest at 192.168.19.2.
95
96 Another method is to bridge the tap device to an external interface
97 using --tunnet=bridge:<bridgename>, and perhaps run dhcp on the guest
98 to obtain an IP address. The bridge needs to be configured first:
99 this option simply adds the tap interface to it.
100
101 A simple example on my system:
102
103 ifconfig eth0 0.0.0.0
104 brctl addbr lg0
105 ifconfig lg0 up
106 brctl addif lg0 eth0
107 dhclient lg0
108
109 Then use --tunnet=bridge:lg0 when launching the guest.
110
111 See:
112
113 http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge
114
115 for general information on how to get bridging to work.
116
117- Random number generation. Using the --rng option will provide a
118 /dev/hwrng in the guest that will read from the host's /dev/random.
119 Use this option in conjunction with rng-tools (see ../hw_random.txt)
120 to provide entropy to the guest kernel's /dev/random.
121
122There is a helpful mailing list at http://ozlabs.org/mailman/listinfo/lguest
123
124Good luck!
125Rusty Russell rusty@rustcorp.com.au.
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index eb6e0b36bfc1..a13e9c7f1fc5 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1include ../../scripts/Makefile.include 2include ../../scripts/Makefile.include
2include ../../scripts/utilities.mak # QUIET_CLEAN 3include ../../scripts/utilities.mak # QUIET_CLEAN
3 4
@@ -8,22 +9,28 @@ srctree := $(patsubst %/,%,$(dir $(srctree)))
8#$(info Determined 'srctree' to be $(srctree)) 9#$(info Determined 'srctree' to be $(srctree))
9endif 10endif
10 11
11CC = $(CROSS_COMPILE)gcc 12CC ?= $(CROSS_COMPILE)gcc
12AR = $(CROSS_COMPILE)ar 13AR ?= $(CROSS_COMPILE)ar
13LD = $(CROSS_COMPILE)ld 14LD ?= $(CROSS_COMPILE)ld
14 15
15MAKEFLAGS += --no-print-directory 16MAKEFLAGS += --no-print-directory
16 17
17LIBFILE = $(OUTPUT)libapi.a 18LIBFILE = $(OUTPUT)libapi.a
18 19
19CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 20CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
20CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC 21CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -fPIC
21 22
22ifeq ($(CC), clang) 23ifeq ($(DEBUG),0)
24ifeq ($(CC_NO_CLANG), 0)
23 CFLAGS += -O3 25 CFLAGS += -O3
24else 26else
25 CFLAGS += -O6 27 CFLAGS += -O6
26endif 28endif
29endif
30
31ifeq ($(DEBUG),0)
32 CFLAGS += -D_FORTIFY_SOURCE
33endif
27 34
28# Treat warnings as errors unless directed not to 35# Treat warnings as errors unless directed not to
29ifneq ($(WERROR),0) 36ifneq ($(WERROR),0)
diff --git a/tools/lib/api/cpu.c b/tools/lib/api/cpu.c
index 8c6489356e3a..4af6d4b7aa07 100644
--- a/tools/lib/api/cpu.c
+++ b/tools/lib/api/cpu.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2 3
3#include "cpu.h" 4#include "cpu.h"
diff --git a/tools/lib/api/cpu.h b/tools/lib/api/cpu.h
index 81e9d3955961..90a102fb20de 100644
--- a/tools/lib/api/cpu.h
+++ b/tools/lib/api/cpu.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __API_CPU__ 2#ifndef __API_CPU__
2#define __API_CPU__ 3#define __API_CPU__
3 4
diff --git a/tools/lib/api/debug-internal.h b/tools/lib/api/debug-internal.h
index 188f7880eafe..80c783497d25 100644
--- a/tools/lib/api/debug-internal.h
+++ b/tools/lib/api/debug-internal.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __API_DEBUG_INTERNAL_H__ 2#ifndef __API_DEBUG_INTERNAL_H__
2#define __API_DEBUG_INTERNAL_H__ 3#define __API_DEBUG_INTERNAL_H__
3 4
diff --git a/tools/lib/api/debug.c b/tools/lib/api/debug.c
index 5fa5cf500a1f..69b1ba3d1ee3 100644
--- a/tools/lib/api/debug.c
+++ b/tools/lib/api/debug.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <stdarg.h> 3#include <stdarg.h>
3#include "debug.h" 4#include "debug.h"
diff --git a/tools/lib/api/debug.h b/tools/lib/api/debug.h
index a0872f68fc56..3684dd6e0c02 100644
--- a/tools/lib/api/debug.h
+++ b/tools/lib/api/debug.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __API_DEBUG_H__ 2#ifndef __API_DEBUG_H__
2#define __API_DEBUG_H__ 3#define __API_DEBUG_H__
3 4
diff --git a/tools/lib/api/fd/array.h b/tools/lib/api/fd/array.h
index 71287dddc05f..b39557d1a88f 100644
--- a/tools/lib/api/fd/array.h
+++ b/tools/lib/api/fd/array.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __API_FD_ARRAY__ 2#ifndef __API_FD_ARRAY__
2#define __API_FD_ARRAY__ 3#define __API_FD_ARRAY__
3 4
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
index a7ecf8f469f4..b24afc0e6e81 100644
--- a/tools/lib/api/fs/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <ctype.h> 2#include <ctype.h>
2#include <errno.h> 3#include <errno.h>
3#include <limits.h> 4#include <limits.h>
diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h
index 45605348461e..dda49deefb52 100644
--- a/tools/lib/api/fs/fs.h
+++ b/tools/lib/api/fs/fs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __API_FS__ 2#ifndef __API_FS__
2#define __API_FS__ 3#define __API_FS__
3 4
diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c
index 3e606b9c443e..7b7fd0b18551 100644
--- a/tools/lib/api/fs/tracing_path.c
+++ b/tools/lib/api/fs/tracing_path.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#ifndef _GNU_SOURCE 2#ifndef _GNU_SOURCE
2# define _GNU_SOURCE 3# define _GNU_SOURCE
3#endif 4#endif
diff --git a/tools/lib/api/fs/tracing_path.h b/tools/lib/api/fs/tracing_path.h
index 3f233ac70b6f..0066f06cc381 100644
--- a/tools/lib/api/fs/tracing_path.h
+++ b/tools/lib/api/fs/tracing_path.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __API_FS_TRACING_PATH_H 2#ifndef __API_FS_TRACING_PATH_H
2#define __API_FS_TRACING_PATH_H 3#define __API_FS_TRACING_PATH_H
3 4
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index 1f5300e56b44..4555304dc18e 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# Most of this file is copied from tools/lib/traceevent/Makefile 2# Most of this file is copied from tools/lib/traceevent/Makefile
2 3
3BPF_VERSION = 0 4BPF_VERSION = 0
@@ -154,12 +155,12 @@ all: fixdep $(VERSION_FILES) all_cmd
154all_cmd: $(CMD_TARGETS) 155all_cmd: $(CMD_TARGETS)
155 156
156$(BPF_IN): force elfdep bpfdep 157$(BPF_IN): force elfdep bpfdep
157 @(test -f ../../../include/uapi/linux/bpf.h -a -f ../../../include/uapi/linux/bpf.h && ( \ 158 @(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 (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 echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/bpf.h' differs from latest version at 'include/uapi/linux/bpf.h'" >&2 )) || true
160 @(test -f ../../../include/uapi/linux/bpf_common.h -a -f ../../../include/uapi/linux/bpf_common.h && ( \ 161 @(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 (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 163 echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/bpf_common.h' differs from latest version at 'include/uapi/linux/bpf_common.h'" >&2 )) || true
163 $(Q)$(MAKE) $(build)=libbpf 164 $(Q)$(MAKE) $(build)=libbpf
164 165
165$(OUTPUT)libbpf.so: $(BPF_IN) 166$(OUTPUT)libbpf.so: $(BPF_IN)
@@ -189,6 +190,10 @@ install_lib: all_cmd
189 $(call QUIET_INSTALL, $(LIB_FILE)) \ 190 $(call QUIET_INSTALL, $(LIB_FILE)) \
190 $(call do_install,$(LIB_FILE),$(libdir_SQ)) 191 $(call do_install,$(LIB_FILE),$(libdir_SQ))
191 192
193install_headers:
194 $(call QUIET_INSTALL, headers) \
195 $(call do_install,bpf.h,$(prefix)/include/bpf,644)
196
192install: install_lib 197install: install_lib
193 198
194### Cleaning rules 199### Cleaning rules
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 412a7c82995a..5128677e4117 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -39,11 +39,15 @@
39# define __NR_bpf 280 39# define __NR_bpf 280
40# elif defined(__sparc__) 40# elif defined(__sparc__)
41# define __NR_bpf 349 41# define __NR_bpf 349
42# elif defined(__s390__)
43# define __NR_bpf 351
42# else 44# else
43# error __NR_bpf not defined. libbpf does not support your arch. 45# error __NR_bpf not defined. libbpf does not support your arch.
44# endif 46# endif
45#endif 47#endif
46 48
49#define min(x, y) ((x) < (y) ? (x) : (y))
50
47static inline __u64 ptr_to_u64(const void *ptr) 51static inline __u64 ptr_to_u64(const void *ptr)
48{ 52{
49 return (__u64) (unsigned long) ptr; 53 return (__u64) (unsigned long) ptr;
@@ -55,9 +59,11 @@ static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
55 return syscall(__NR_bpf, cmd, attr, size); 59 return syscall(__NR_bpf, cmd, attr, size);
56} 60}
57 61
58int bpf_create_map(enum bpf_map_type map_type, int key_size, 62int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
59 int value_size, int max_entries, __u32 map_flags) 63 int key_size, int value_size, int max_entries,
64 __u32 map_flags, int node)
60{ 65{
66 __u32 name_len = name ? strlen(name) : 0;
61 union bpf_attr attr; 67 union bpf_attr attr;
62 68
63 memset(&attr, '\0', sizeof(attr)); 69 memset(&attr, '\0', sizeof(attr));
@@ -67,13 +73,36 @@ int bpf_create_map(enum bpf_map_type map_type, int key_size,
67 attr.value_size = value_size; 73 attr.value_size = value_size;
68 attr.max_entries = max_entries; 74 attr.max_entries = max_entries;
69 attr.map_flags = map_flags; 75 attr.map_flags = map_flags;
76 memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));
77
78 if (node >= 0) {
79 attr.map_flags |= BPF_F_NUMA_NODE;
80 attr.numa_node = node;
81 }
70 82
71 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 83 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
72} 84}
73 85
74int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size, 86int bpf_create_map(enum bpf_map_type map_type, int key_size,
75 int inner_map_fd, int max_entries, __u32 map_flags) 87 int value_size, int max_entries, __u32 map_flags)
76{ 88{
89 return bpf_create_map_node(map_type, NULL, key_size, value_size,
90 max_entries, map_flags, -1);
91}
92
93int bpf_create_map_name(enum bpf_map_type map_type, const char *name,
94 int key_size, int value_size, int max_entries,
95 __u32 map_flags)
96{
97 return bpf_create_map_node(map_type, name, key_size, value_size,
98 max_entries, map_flags, -1);
99}
100
101int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name,
102 int key_size, int inner_map_fd, int max_entries,
103 __u32 map_flags, int node)
104{
105 __u32 name_len = name ? strlen(name) : 0;
77 union bpf_attr attr; 106 union bpf_attr attr;
78 107
79 memset(&attr, '\0', sizeof(attr)); 108 memset(&attr, '\0', sizeof(attr));
@@ -84,16 +113,34 @@ int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size,
84 attr.inner_map_fd = inner_map_fd; 113 attr.inner_map_fd = inner_map_fd;
85 attr.max_entries = max_entries; 114 attr.max_entries = max_entries;
86 attr.map_flags = map_flags; 115 attr.map_flags = map_flags;
116 memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));
117
118 if (node >= 0) {
119 attr.map_flags |= BPF_F_NUMA_NODE;
120 attr.numa_node = node;
121 }
87 122
88 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 123 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
89} 124}
90 125
91int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, 126int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
92 size_t insns_cnt, const char *license, 127 int key_size, int inner_map_fd, int max_entries,
93 __u32 kern_version, char *log_buf, size_t log_buf_sz) 128 __u32 map_flags)
129{
130 return bpf_create_map_in_map_node(map_type, name, key_size,
131 inner_map_fd, max_entries, map_flags,
132 -1);
133}
134
135int bpf_load_program_name(enum bpf_prog_type type, const char *name,
136 const struct bpf_insn *insns,
137 size_t insns_cnt, const char *license,
138 __u32 kern_version, char *log_buf,
139 size_t log_buf_sz)
94{ 140{
95 int fd; 141 int fd;
96 union bpf_attr attr; 142 union bpf_attr attr;
143 __u32 name_len = name ? strlen(name) : 0;
97 144
98 bzero(&attr, sizeof(attr)); 145 bzero(&attr, sizeof(attr));
99 attr.prog_type = type; 146 attr.prog_type = type;
@@ -104,6 +151,7 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
104 attr.log_size = 0; 151 attr.log_size = 0;
105 attr.log_level = 0; 152 attr.log_level = 0;
106 attr.kern_version = kern_version; 153 attr.kern_version = kern_version;
154 memcpy(attr.prog_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));
107 155
108 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 156 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
109 if (fd >= 0 || !log_buf || !log_buf_sz) 157 if (fd >= 0 || !log_buf || !log_buf_sz)
@@ -117,6 +165,15 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
117 return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 165 return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
118} 166}
119 167
168int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
169 size_t insns_cnt, const char *license,
170 __u32 kern_version, char *log_buf,
171 size_t log_buf_sz)
172{
173 return bpf_load_program_name(type, NULL, insns, insns_cnt, license,
174 kern_version, log_buf, log_buf_sz);
175}
176
120int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, 177int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
121 size_t insns_cnt, int strict_alignment, 178 size_t insns_cnt, int strict_alignment,
122 const char *license, __u32 kern_version, 179 const char *license, __u32 kern_version,
@@ -234,6 +291,38 @@ int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
234 return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr)); 291 return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
235} 292}
236 293
294int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type)
295{
296 union bpf_attr attr;
297
298 bzero(&attr, sizeof(attr));
299 attr.target_fd = target_fd;
300 attr.attach_bpf_fd = prog_fd;
301 attr.attach_type = type;
302
303 return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
304}
305
306int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
307 __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt)
308{
309 union bpf_attr attr;
310 int ret;
311
312 bzero(&attr, sizeof(attr));
313 attr.query.target_fd = target_fd;
314 attr.query.attach_type = type;
315 attr.query.query_flags = query_flags;
316 attr.query.prog_cnt = *prog_cnt;
317 attr.query.prog_ids = ptr_to_u64(prog_ids);
318
319 ret = sys_bpf(BPF_PROG_QUERY, &attr, sizeof(attr));
320 if (attach_flags)
321 *attach_flags = attr.query.attach_flags;
322 *prog_cnt = attr.query.prog_cnt;
323 return ret;
324}
325
237int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size, 326int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size,
238 void *data_out, __u32 *size_out, __u32 *retval, 327 void *data_out, __u32 *size_out, __u32 *retval,
239 __u32 *duration) 328 __u32 *duration)
@@ -314,7 +403,6 @@ int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len)
314 int err; 403 int err;
315 404
316 bzero(&attr, sizeof(attr)); 405 bzero(&attr, sizeof(attr));
317 bzero(info, *info_len);
318 attr.info.bpf_fd = prog_fd; 406 attr.info.bpf_fd = prog_fd;
319 attr.info.info_len = *info_len; 407 attr.info.info_len = *info_len;
320 attr.info.info = ptr_to_u64(info); 408 attr.info.info = ptr_to_u64(info);
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 418c86e69bcb..6534889e2b2f 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -24,13 +24,28 @@
24#include <linux/bpf.h> 24#include <linux/bpf.h>
25#include <stddef.h> 25#include <stddef.h>
26 26
27int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
28 int key_size, int value_size, int max_entries,
29 __u32 map_flags, int node);
30int bpf_create_map_name(enum bpf_map_type map_type, const char *name,
31 int key_size, int value_size, int max_entries,
32 __u32 map_flags);
27int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, 33int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
28 int max_entries, __u32 map_flags); 34 int max_entries, __u32 map_flags);
29int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size, 35int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name,
30 int inner_map_fd, int max_entries, __u32 map_flags); 36 int key_size, int inner_map_fd, int max_entries,
37 __u32 map_flags, int node);
38int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
39 int key_size, int inner_map_fd, int max_entries,
40 __u32 map_flags);
31 41
32/* Recommend log buffer size */ 42/* Recommend log buffer size */
33#define BPF_LOG_BUF_SIZE 65536 43#define BPF_LOG_BUF_SIZE 65536
44int bpf_load_program_name(enum bpf_prog_type type, const char *name,
45 const struct bpf_insn *insns,
46 size_t insns_cnt, const char *license,
47 __u32 kern_version, char *log_buf,
48 size_t log_buf_sz);
34int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, 49int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
35 size_t insns_cnt, const char *license, 50 size_t insns_cnt, const char *license,
36 __u32 kern_version, char *log_buf, 51 __u32 kern_version, char *log_buf,
@@ -51,6 +66,7 @@ int bpf_obj_get(const char *pathname);
51int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type, 66int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type,
52 unsigned int flags); 67 unsigned int flags);
53int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type); 68int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
69int bpf_prog_detach2(int prog_fd, int attachable_fd, enum bpf_attach_type type);
54int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size, 70int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size,
55 void *data_out, __u32 *size_out, __u32 *retval, 71 void *data_out, __u32 *size_out, __u32 *retval,
56 __u32 *duration); 72 __u32 *duration);
@@ -59,5 +75,6 @@ int bpf_map_get_next_id(__u32 start_id, __u32 *next_id);
59int bpf_prog_get_fd_by_id(__u32 id); 75int bpf_prog_get_fd_by_id(__u32 id);
60int bpf_map_get_fd_by_id(__u32 id); 76int bpf_map_get_fd_by_id(__u32 id);
61int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len); 77int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len);
62 78int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
79 __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt);
63#endif 80#endif
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 1a2c07eb7795..5aa45f89da93 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -171,6 +171,7 @@ int libbpf_strerror(int err, char *buf, size_t size)
171struct bpf_program { 171struct bpf_program {
172 /* Index in elf obj file, for relocation use. */ 172 /* Index in elf obj file, for relocation use. */
173 int idx; 173 int idx;
174 char *name;
174 char *section_name; 175 char *section_name;
175 struct bpf_insn *insns; 176 struct bpf_insn *insns;
176 size_t insns_cnt; 177 size_t insns_cnt;
@@ -283,6 +284,7 @@ static void bpf_program__exit(struct bpf_program *prog)
283 prog->clear_priv = NULL; 284 prog->clear_priv = NULL;
284 285
285 bpf_program__unload(prog); 286 bpf_program__unload(prog);
287 zfree(&prog->name);
286 zfree(&prog->section_name); 288 zfree(&prog->section_name);
287 zfree(&prog->insns); 289 zfree(&prog->insns);
288 zfree(&prog->reloc_desc); 290 zfree(&prog->reloc_desc);
@@ -293,26 +295,27 @@ static void bpf_program__exit(struct bpf_program *prog)
293} 295}
294 296
295static int 297static int
296bpf_program__init(void *data, size_t size, char *name, int idx, 298bpf_program__init(void *data, size_t size, char *section_name, int idx,
297 struct bpf_program *prog) 299 struct bpf_program *prog)
298{ 300{
299 if (size < sizeof(struct bpf_insn)) { 301 if (size < sizeof(struct bpf_insn)) {
300 pr_warning("corrupted section '%s'\n", name); 302 pr_warning("corrupted section '%s'\n", section_name);
301 return -EINVAL; 303 return -EINVAL;
302 } 304 }
303 305
304 bzero(prog, sizeof(*prog)); 306 bzero(prog, sizeof(*prog));
305 307
306 prog->section_name = strdup(name); 308 prog->section_name = strdup(section_name);
307 if (!prog->section_name) { 309 if (!prog->section_name) {
308 pr_warning("failed to alloc name for prog %s\n", 310 pr_warning("failed to alloc name for prog under section %s\n",
309 name); 311 section_name);
310 goto errout; 312 goto errout;
311 } 313 }
312 314
313 prog->insns = malloc(size); 315 prog->insns = malloc(size);
314 if (!prog->insns) { 316 if (!prog->insns) {
315 pr_warning("failed to alloc insns for %s\n", name); 317 pr_warning("failed to alloc insns for prog under section %s\n",
318 section_name);
316 goto errout; 319 goto errout;
317 } 320 }
318 prog->insns_cnt = size / sizeof(struct bpf_insn); 321 prog->insns_cnt = size / sizeof(struct bpf_insn);
@@ -331,12 +334,12 @@ errout:
331 334
332static int 335static int
333bpf_object__add_program(struct bpf_object *obj, void *data, size_t size, 336bpf_object__add_program(struct bpf_object *obj, void *data, size_t size,
334 char *name, int idx) 337 char *section_name, int idx)
335{ 338{
336 struct bpf_program prog, *progs; 339 struct bpf_program prog, *progs;
337 int nr_progs, err; 340 int nr_progs, err;
338 341
339 err = bpf_program__init(data, size, name, idx, &prog); 342 err = bpf_program__init(data, size, section_name, idx, &prog);
340 if (err) 343 if (err)
341 return err; 344 return err;
342 345
@@ -350,8 +353,8 @@ bpf_object__add_program(struct bpf_object *obj, void *data, size_t size,
350 * is still valid, so don't need special treat for 353 * is still valid, so don't need special treat for
351 * bpf_close_object(). 354 * bpf_close_object().
352 */ 355 */
353 pr_warning("failed to alloc a new program '%s'\n", 356 pr_warning("failed to alloc a new program under section '%s'\n",
354 name); 357 section_name);
355 bpf_program__exit(&prog); 358 bpf_program__exit(&prog);
356 return -ENOMEM; 359 return -ENOMEM;
357 } 360 }
@@ -364,6 +367,54 @@ bpf_object__add_program(struct bpf_object *obj, void *data, size_t size,
364 return 0; 367 return 0;
365} 368}
366 369
370static int
371bpf_object__init_prog_names(struct bpf_object *obj)
372{
373 Elf_Data *symbols = obj->efile.symbols;
374 struct bpf_program *prog;
375 size_t pi, si;
376
377 for (pi = 0; pi < obj->nr_programs; pi++) {
378 char *name = NULL;
379
380 prog = &obj->programs[pi];
381
382 for (si = 0; si < symbols->d_size / sizeof(GElf_Sym) && !name;
383 si++) {
384 GElf_Sym sym;
385
386 if (!gelf_getsym(symbols, si, &sym))
387 continue;
388 if (sym.st_shndx != prog->idx)
389 continue;
390
391 name = elf_strptr(obj->efile.elf,
392 obj->efile.strtabidx,
393 sym.st_name);
394 if (!name) {
395 pr_warning("failed to get sym name string for prog %s\n",
396 prog->section_name);
397 return -LIBBPF_ERRNO__LIBELF;
398 }
399 }
400
401 if (!name) {
402 pr_warning("failed to find sym for prog %s\n",
403 prog->section_name);
404 return -EINVAL;
405 }
406
407 prog->name = strdup(name);
408 if (!prog->name) {
409 pr_warning("failed to allocate memory for prog sym %s\n",
410 name);
411 return -ENOMEM;
412 }
413 }
414
415 return 0;
416}
417
367static struct bpf_object *bpf_object__new(const char *path, 418static struct bpf_object *bpf_object__new(const char *path,
368 void *obj_buf, 419 void *obj_buf,
369 size_t obj_buf_sz) 420 size_t obj_buf_sz)
@@ -528,31 +579,6 @@ bpf_object__init_kversion(struct bpf_object *obj,
528 return 0; 579 return 0;
529} 580}
530 581
531static int
532bpf_object__validate_maps(struct bpf_object *obj)
533{
534 int i;
535
536 /*
537 * If there's only 1 map, the only error case should have been
538 * catched in bpf_object__init_maps().
539 */
540 if (!obj->maps || !obj->nr_maps || (obj->nr_maps == 1))
541 return 0;
542
543 for (i = 1; i < obj->nr_maps; i++) {
544 const struct bpf_map *a = &obj->maps[i - 1];
545 const struct bpf_map *b = &obj->maps[i];
546
547 if (b->offset - a->offset < sizeof(struct bpf_map_def)) {
548 pr_warning("corrupted map section in %s: map \"%s\" too small\n",
549 obj->path, a->name);
550 return -EINVAL;
551 }
552 }
553 return 0;
554}
555
556static int compare_bpf_map(const void *_a, const void *_b) 582static int compare_bpf_map(const void *_a, const void *_b)
557{ 583{
558 const struct bpf_map *a = _a; 584 const struct bpf_map *a = _a;
@@ -564,7 +590,7 @@ static int compare_bpf_map(const void *_a, const void *_b)
564static int 590static int
565bpf_object__init_maps(struct bpf_object *obj) 591bpf_object__init_maps(struct bpf_object *obj)
566{ 592{
567 int i, map_idx, nr_maps = 0; 593 int i, map_idx, map_def_sz, nr_maps = 0;
568 Elf_Scn *scn; 594 Elf_Scn *scn;
569 Elf_Data *data; 595 Elf_Data *data;
570 Elf_Data *symbols = obj->efile.symbols; 596 Elf_Data *symbols = obj->efile.symbols;
@@ -607,6 +633,15 @@ bpf_object__init_maps(struct bpf_object *obj)
607 if (!nr_maps) 633 if (!nr_maps)
608 return 0; 634 return 0;
609 635
636 /* Assume equally sized map definitions */
637 map_def_sz = data->d_size / nr_maps;
638 if (!data->d_size || (data->d_size % nr_maps) != 0) {
639 pr_warning("unable to determine map definition size "
640 "section %s, %d maps in %zd bytes\n",
641 obj->path, nr_maps, data->d_size);
642 return -EINVAL;
643 }
644
610 obj->maps = calloc(nr_maps, sizeof(obj->maps[0])); 645 obj->maps = calloc(nr_maps, sizeof(obj->maps[0]));
611 if (!obj->maps) { 646 if (!obj->maps) {
612 pr_warning("alloc maps for object failed\n"); 647 pr_warning("alloc maps for object failed\n");
@@ -639,7 +674,7 @@ bpf_object__init_maps(struct bpf_object *obj)
639 obj->efile.strtabidx, 674 obj->efile.strtabidx,
640 sym.st_name); 675 sym.st_name);
641 obj->maps[map_idx].offset = sym.st_value; 676 obj->maps[map_idx].offset = sym.st_value;
642 if (sym.st_value + sizeof(struct bpf_map_def) > data->d_size) { 677 if (sym.st_value + map_def_sz > data->d_size) {
643 pr_warning("corrupted maps section in %s: last map \"%s\" too small\n", 678 pr_warning("corrupted maps section in %s: last map \"%s\" too small\n",
644 obj->path, map_name); 679 obj->path, map_name);
645 return -EINVAL; 680 return -EINVAL;
@@ -653,12 +688,40 @@ bpf_object__init_maps(struct bpf_object *obj)
653 pr_debug("map %d is \"%s\"\n", map_idx, 688 pr_debug("map %d is \"%s\"\n", map_idx,
654 obj->maps[map_idx].name); 689 obj->maps[map_idx].name);
655 def = (struct bpf_map_def *)(data->d_buf + sym.st_value); 690 def = (struct bpf_map_def *)(data->d_buf + sym.st_value);
656 obj->maps[map_idx].def = *def; 691 /*
692 * If the definition of the map in the object file fits in
693 * bpf_map_def, copy it. Any extra fields in our version
694 * of bpf_map_def will default to zero as a result of the
695 * calloc above.
696 */
697 if (map_def_sz <= sizeof(struct bpf_map_def)) {
698 memcpy(&obj->maps[map_idx].def, def, map_def_sz);
699 } else {
700 /*
701 * Here the map structure being read is bigger than what
702 * we expect, truncate if the excess bits are all zero.
703 * If they are not zero, reject this map as
704 * incompatible.
705 */
706 char *b;
707 for (b = ((char *)def) + sizeof(struct bpf_map_def);
708 b < ((char *)def) + map_def_sz; b++) {
709 if (*b != 0) {
710 pr_warning("maps section in %s: \"%s\" "
711 "has unrecognized, non-zero "
712 "options\n",
713 obj->path, map_name);
714 return -EINVAL;
715 }
716 }
717 memcpy(&obj->maps[map_idx].def, def,
718 sizeof(struct bpf_map_def));
719 }
657 map_idx++; 720 map_idx++;
658 } 721 }
659 722
660 qsort(obj->maps, obj->nr_maps, sizeof(obj->maps[0]), compare_bpf_map); 723 qsort(obj->maps, obj->nr_maps, sizeof(obj->maps[0]), compare_bpf_map);
661 return bpf_object__validate_maps(obj); 724 return 0;
662} 725}
663 726
664static int bpf_object__elf_collect(struct bpf_object *obj) 727static int bpf_object__elf_collect(struct bpf_object *obj)
@@ -766,8 +829,12 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
766 pr_warning("Corrupted ELF file: index of strtab invalid\n"); 829 pr_warning("Corrupted ELF file: index of strtab invalid\n");
767 return LIBBPF_ERRNO__FORMAT; 830 return LIBBPF_ERRNO__FORMAT;
768 } 831 }
769 if (obj->efile.maps_shndx >= 0) 832 if (obj->efile.maps_shndx >= 0) {
770 err = bpf_object__init_maps(obj); 833 err = bpf_object__init_maps(obj);
834 if (err)
835 goto out;
836 }
837 err = bpf_object__init_prog_names(obj);
771out: 838out:
772 return err; 839 return err;
773} 840}
@@ -870,16 +937,18 @@ bpf_object__create_maps(struct bpf_object *obj)
870 struct bpf_map_def *def = &obj->maps[i].def; 937 struct bpf_map_def *def = &obj->maps[i].def;
871 int *pfd = &obj->maps[i].fd; 938 int *pfd = &obj->maps[i].fd;
872 939
873 *pfd = bpf_create_map(def->type, 940 *pfd = bpf_create_map_name(def->type,
874 def->key_size, 941 obj->maps[i].name,
875 def->value_size, 942 def->key_size,
876 def->max_entries, 943 def->value_size,
877 0); 944 def->max_entries,
945 def->map_flags);
878 if (*pfd < 0) { 946 if (*pfd < 0) {
879 size_t j; 947 size_t j;
880 int err = *pfd; 948 int err = *pfd;
881 949
882 pr_warning("failed to create map: %s\n", 950 pr_warning("failed to create map (name: '%s'): %s\n",
951 obj->maps[i].name,
883 strerror(errno)); 952 strerror(errno));
884 for (j = 0; j < i; j++) 953 for (j = 0; j < i; j++)
885 zclose(obj->maps[j].fd); 954 zclose(obj->maps[j].fd);
@@ -981,7 +1050,7 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
981} 1050}
982 1051
983static int 1052static int
984load_program(enum bpf_prog_type type, struct bpf_insn *insns, 1053load_program(enum bpf_prog_type type, const char *name, struct bpf_insn *insns,
985 int insns_cnt, char *license, u32 kern_version, int *pfd) 1054 int insns_cnt, char *license, u32 kern_version, int *pfd)
986{ 1055{
987 int ret; 1056 int ret;
@@ -994,8 +1063,8 @@ load_program(enum bpf_prog_type type, struct bpf_insn *insns,
994 if (!log_buf) 1063 if (!log_buf)
995 pr_warning("Alloc log buffer for bpf loader error, continue without log\n"); 1064 pr_warning("Alloc log buffer for bpf loader error, continue without log\n");
996 1065
997 ret = bpf_load_program(type, insns, insns_cnt, license, 1066 ret = bpf_load_program_name(type, name, insns, insns_cnt, license,
998 kern_version, log_buf, BPF_LOG_BUF_SIZE); 1067 kern_version, log_buf, BPF_LOG_BUF_SIZE);
999 1068
1000 if (ret >= 0) { 1069 if (ret >= 0) {
1001 *pfd = ret; 1070 *pfd = ret;
@@ -1020,9 +1089,9 @@ load_program(enum bpf_prog_type type, struct bpf_insn *insns,
1020 if (type != BPF_PROG_TYPE_KPROBE) { 1089 if (type != BPF_PROG_TYPE_KPROBE) {
1021 int fd; 1090 int fd;
1022 1091
1023 fd = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns, 1092 fd = bpf_load_program_name(BPF_PROG_TYPE_KPROBE, name,
1024 insns_cnt, license, kern_version, 1093 insns, insns_cnt, license,
1025 NULL, 0); 1094 kern_version, NULL, 0);
1026 if (fd >= 0) { 1095 if (fd >= 0) {
1027 close(fd); 1096 close(fd);
1028 ret = -LIBBPF_ERRNO__PROGTYPE; 1097 ret = -LIBBPF_ERRNO__PROGTYPE;
@@ -1066,8 +1135,8 @@ bpf_program__load(struct bpf_program *prog,
1066 pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n", 1135 pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n",
1067 prog->section_name, prog->instances.nr); 1136 prog->section_name, prog->instances.nr);
1068 } 1137 }
1069 err = load_program(prog->type, prog->insns, prog->insns_cnt, 1138 err = load_program(prog->type, prog->name, prog->insns,
1070 license, kern_version, &fd); 1139 prog->insns_cnt, license, kern_version, &fd);
1071 if (!err) 1140 if (!err)
1072 prog->instances.fds[0] = fd; 1141 prog->instances.fds[0] = fd;
1073 goto out; 1142 goto out;
@@ -1095,7 +1164,8 @@ bpf_program__load(struct bpf_program *prog,
1095 continue; 1164 continue;
1096 } 1165 }
1097 1166
1098 err = load_program(prog->type, result.new_insn_ptr, 1167 err = load_program(prog->type, prog->name,
1168 result.new_insn_ptr,
1099 result.new_insn_cnt, 1169 result.new_insn_cnt,
1100 license, kern_version, &fd); 1170 license, kern_version, &fd);
1101 1171
@@ -1744,3 +1814,32 @@ long libbpf_get_error(const void *ptr)
1744 return PTR_ERR(ptr); 1814 return PTR_ERR(ptr);
1745 return 0; 1815 return 0;
1746} 1816}
1817
1818int bpf_prog_load(const char *file, enum bpf_prog_type type,
1819 struct bpf_object **pobj, int *prog_fd)
1820{
1821 struct bpf_program *prog;
1822 struct bpf_object *obj;
1823 int err;
1824
1825 obj = bpf_object__open(file);
1826 if (IS_ERR(obj))
1827 return -ENOENT;
1828
1829 prog = bpf_program__next(NULL, obj);
1830 if (!prog) {
1831 bpf_object__close(obj);
1832 return -ENOENT;
1833 }
1834
1835 bpf_program__set_type(prog, type);
1836 err = bpf_object__load(obj);
1837 if (err) {
1838 bpf_object__close(obj);
1839 return -EINVAL;
1840 }
1841
1842 *pobj = obj;
1843 *prog_fd = bpf_program__fd(prog);
1844 return 0;
1845}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 32c7252f734e..6e20003109e0 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -207,6 +207,7 @@ struct bpf_map_def {
207 unsigned int key_size; 207 unsigned int key_size;
208 unsigned int value_size; 208 unsigned int value_size;
209 unsigned int max_entries; 209 unsigned int max_entries;
210 unsigned int map_flags;
210}; 211};
211 212
212/* 213/*
@@ -243,4 +244,6 @@ int bpf_map__pin(struct bpf_map *map, const char *path);
243 244
244long libbpf_get_error(const void *ptr); 245long libbpf_get_error(const void *ptr);
245 246
247int bpf_prog_load(const char *file, enum bpf_prog_type type,
248 struct bpf_object **pobj, int *prog_fd);
246#endif 249#endif
diff --git a/tools/lib/hweight.c b/tools/lib/hweight.c
index 0b859b884339..a16ebf515417 100644
--- a/tools/lib/hweight.c
+++ b/tools/lib/hweight.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/bitops.h> 2#include <linux/bitops.h>
2#include <asm/types.h> 3#include <asm/types.h>
3 4
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
index ed9ace59d112..9b0ca3ad1ef3 100644
--- a/tools/lib/lockdep/Makefile
+++ b/tools/lib/lockdep/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# file format version 2# file format version
2FILE_VERSION = 1 3FILE_VERSION = 1
3 4
diff --git a/tools/lib/lockdep/common.c b/tools/lib/lockdep/common.c
index d1c89cc06f5f..5c3b58cce8a9 100644
--- a/tools/lib/lockdep/common.c
+++ b/tools/lib/lockdep/common.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stddef.h> 2#include <stddef.h>
2#include <stdbool.h> 3#include <stdbool.h>
3#include <linux/compiler.h> 4#include <linux/compiler.h>
diff --git a/tools/lib/lockdep/include/liblockdep/common.h b/tools/lib/lockdep/include/liblockdep/common.h
index 6e66277ec437..8862da80995a 100644
--- a/tools/lib/lockdep/include/liblockdep/common.h
+++ b/tools/lib/lockdep/include/liblockdep/common.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LIBLOCKDEP_COMMON_H 2#ifndef _LIBLOCKDEP_COMMON_H
2#define _LIBLOCKDEP_COMMON_H 3#define _LIBLOCKDEP_COMMON_H
3 4
diff --git a/tools/lib/lockdep/include/liblockdep/mutex.h b/tools/lib/lockdep/include/liblockdep/mutex.h
index ee53a42818ca..a80ac39f966e 100644
--- a/tools/lib/lockdep/include/liblockdep/mutex.h
+++ b/tools/lib/lockdep/include/liblockdep/mutex.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LIBLOCKDEP_MUTEX_H 2#ifndef _LIBLOCKDEP_MUTEX_H
2#define _LIBLOCKDEP_MUTEX_H 3#define _LIBLOCKDEP_MUTEX_H
3 4
diff --git a/tools/lib/lockdep/include/liblockdep/rwlock.h b/tools/lib/lockdep/include/liblockdep/rwlock.h
index 4ec03f861551..a96c3bf0fef1 100644
--- a/tools/lib/lockdep/include/liblockdep/rwlock.h
+++ b/tools/lib/lockdep/include/liblockdep/rwlock.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LIBLOCKDEP_RWLOCK_H 2#ifndef _LIBLOCKDEP_RWLOCK_H
2#define _LIBLOCKDEP_RWLOCK_H 3#define _LIBLOCKDEP_RWLOCK_H
3 4
diff --git a/tools/lib/lockdep/lockdep.c b/tools/lib/lockdep/lockdep.c
index ced6d7443cea..6002fcf2f9bc 100644
--- a/tools/lib/lockdep/lockdep.c
+++ b/tools/lib/lockdep/lockdep.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/lockdep.h> 2#include <linux/lockdep.h>
2#include <stdlib.h> 3#include <stdlib.h>
3 4
diff --git a/tools/lib/lockdep/preload.c b/tools/lib/lockdep/preload.c
index 6a2d3c5d4e92..76245d16196d 100644
--- a/tools/lib/lockdep/preload.c
+++ b/tools/lib/lockdep/preload.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2#include <pthread.h> 3#include <pthread.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/lib/lockdep/run_tests.sh b/tools/lib/lockdep/run_tests.sh
index f9b94098fc98..2e570a188f16 100755
--- a/tools/lib/lockdep/run_tests.sh
+++ b/tools/lib/lockdep/run_tests.sh
@@ -1,4 +1,5 @@
1#! /bin/bash 1#! /bin/bash
2# SPDX-License-Identifier: GPL-2.0
2 3
3make &> /dev/null 4make &> /dev/null
4 5
diff --git a/tools/lib/lockdep/tests/AA.c b/tools/lib/lockdep/tests/AA.c
index 18211a5f354f..63c7ce97bda3 100644
--- a/tools/lib/lockdep/tests/AA.c
+++ b/tools/lib/lockdep/tests/AA.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <liblockdep/mutex.h> 2#include <liblockdep/mutex.h>
2 3
3int main(void) 4int main(void)
diff --git a/tools/lib/lockdep/tests/ABA.c b/tools/lib/lockdep/tests/ABA.c
index 0f782ff404ac..efa39b23f05d 100644
--- a/tools/lib/lockdep/tests/ABA.c
+++ b/tools/lib/lockdep/tests/ABA.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <liblockdep/mutex.h> 2#include <liblockdep/mutex.h>
2 3
3void main(void) 4void main(void)
diff --git a/tools/lib/lockdep/tests/ABBA.c b/tools/lib/lockdep/tests/ABBA.c
index 07f0e29d5485..1460afd33d71 100644
--- a/tools/lib/lockdep/tests/ABBA.c
+++ b/tools/lib/lockdep/tests/ABBA.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <liblockdep/mutex.h> 2#include <liblockdep/mutex.h>
2#include "common.h" 3#include "common.h"
3 4
diff --git a/tools/lib/lockdep/tests/ABBA_2threads.c b/tools/lib/lockdep/tests/ABBA_2threads.c
index cd807d736361..39325ef8a2ac 100644
--- a/tools/lib/lockdep/tests/ABBA_2threads.c
+++ b/tools/lib/lockdep/tests/ABBA_2threads.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <pthread.h> 3#include <pthread.h>
3 4
diff --git a/tools/lib/lockdep/tests/ABBCCA.c b/tools/lib/lockdep/tests/ABBCCA.c
index 843db09ac666..a54c1b2af118 100644
--- a/tools/lib/lockdep/tests/ABBCCA.c
+++ b/tools/lib/lockdep/tests/ABBCCA.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <liblockdep/mutex.h> 2#include <liblockdep/mutex.h>
2#include "common.h" 3#include "common.h"
3 4
diff --git a/tools/lib/lockdep/tests/ABBCCDDA.c b/tools/lib/lockdep/tests/ABBCCDDA.c
index 33620e268f85..aa5d194e8869 100644
--- a/tools/lib/lockdep/tests/ABBCCDDA.c
+++ b/tools/lib/lockdep/tests/ABBCCDDA.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <liblockdep/mutex.h> 2#include <liblockdep/mutex.h>
2#include "common.h" 3#include "common.h"
3 4
diff --git a/tools/lib/lockdep/tests/ABCABC.c b/tools/lib/lockdep/tests/ABCABC.c
index 3fee51e3a68a..b54a08e60416 100644
--- a/tools/lib/lockdep/tests/ABCABC.c
+++ b/tools/lib/lockdep/tests/ABCABC.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <liblockdep/mutex.h> 2#include <liblockdep/mutex.h>
2#include "common.h" 3#include "common.h"
3 4
diff --git a/tools/lib/lockdep/tests/ABCDBCDA.c b/tools/lib/lockdep/tests/ABCDBCDA.c
index 427ba562c75b..a56742250d86 100644
--- a/tools/lib/lockdep/tests/ABCDBCDA.c
+++ b/tools/lib/lockdep/tests/ABCDBCDA.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <liblockdep/mutex.h> 2#include <liblockdep/mutex.h>
2#include "common.h" 3#include "common.h"
3 4
diff --git a/tools/lib/lockdep/tests/ABCDBDDA.c b/tools/lib/lockdep/tests/ABCDBDDA.c
index 680c6cf3e919..238a3353f3c3 100644
--- a/tools/lib/lockdep/tests/ABCDBDDA.c
+++ b/tools/lib/lockdep/tests/ABCDBDDA.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <liblockdep/mutex.h> 2#include <liblockdep/mutex.h>
2#include "common.h" 3#include "common.h"
3 4
diff --git a/tools/lib/lockdep/tests/WW.c b/tools/lib/lockdep/tests/WW.c
index d44f77d71029..eee88df7fc41 100644
--- a/tools/lib/lockdep/tests/WW.c
+++ b/tools/lib/lockdep/tests/WW.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <liblockdep/rwlock.h> 2#include <liblockdep/rwlock.h>
2 3
3void main(void) 4void main(void)
diff --git a/tools/lib/lockdep/tests/common.h b/tools/lib/lockdep/tests/common.h
index d89e94d47d86..3026c29ccb5c 100644
--- a/tools/lib/lockdep/tests/common.h
+++ b/tools/lib/lockdep/tests/common.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LIBLOCKDEP_TEST_COMMON_H 2#ifndef _LIBLOCKDEP_TEST_COMMON_H
2#define _LIBLOCKDEP_TEST_COMMON_H 3#define _LIBLOCKDEP_TEST_COMMON_H
3 4
diff --git a/tools/lib/lockdep/tests/unlock_balance.c b/tools/lib/lockdep/tests/unlock_balance.c
index 0bc62de686f7..34cf32f689de 100644
--- a/tools/lib/lockdep/tests/unlock_balance.c
+++ b/tools/lib/lockdep/tests/unlock_balance.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <liblockdep/mutex.h> 2#include <liblockdep/mutex.h>
2 3
3void main(void) 4void main(void)
diff --git a/tools/lib/str_error_r.c b/tools/lib/str_error_r.c
index 503ae072244c..d6d65537b0d9 100644
--- a/tools/lib/str_error_r.c
+++ b/tools/lib/str_error_r.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#undef _GNU_SOURCE 2#undef _GNU_SOURCE
2#include <string.h> 3#include <string.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/lib/string.c b/tools/lib/string.c
index 8e678af1c6ee..93b3d4b6feac 100644
--- a/tools/lib/string.c
+++ b/tools/lib/string.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * linux/tools/lib/string.c 3 * linux/tools/lib/string.c
3 * 4 *
@@ -39,27 +40,45 @@ void *memdup(const void *src, size_t len)
39 * @s: input string 40 * @s: input string
40 * @res: result 41 * @res: result
41 * 42 *
42 * This routine returns 0 iff the first character is one of 'Yy1Nn0'. 43 * This routine returns 0 iff the first character is one of 'Yy1Nn0', or
43 * Otherwise it will return -EINVAL. Value pointed to by res is 44 * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value
44 * updated upon finding a match. 45 * pointed to by res is updated upon finding a match.
45 */ 46 */
46int strtobool(const char *s, bool *res) 47int strtobool(const char *s, bool *res)
47{ 48{
49 if (!s)
50 return -EINVAL;
51
48 switch (s[0]) { 52 switch (s[0]) {
49 case 'y': 53 case 'y':
50 case 'Y': 54 case 'Y':
51 case '1': 55 case '1':
52 *res = true; 56 *res = true;
53 break; 57 return 0;
54 case 'n': 58 case 'n':
55 case 'N': 59 case 'N':
56 case '0': 60 case '0':
57 *res = false; 61 *res = false;
58 break; 62 return 0;
63 case 'o':
64 case 'O':
65 switch (s[1]) {
66 case 'n':
67 case 'N':
68 *res = true;
69 return 0;
70 case 'f':
71 case 'F':
72 *res = false;
73 return 0;
74 default:
75 break;
76 }
59 default: 77 default:
60 return -EINVAL; 78 break;
61 } 79 }
62 return 0; 80
81 return -EINVAL;
63} 82}
64 83
65/** 84/**
@@ -87,12 +106,3 @@ size_t __weak strlcpy(char *dest, const char *src, size_t size)
87 } 106 }
88 return ret; 107 return ret;
89} 108}
90
91int prefixcmp(const char *str, const char *prefix)
92{
93 for (; ; str++, prefix++)
94 if (!*prefix)
95 return 0;
96 else if (*str != *prefix)
97 return (unsigned char)*prefix - (unsigned char)*str;
98}
diff --git a/tools/lib/subcmd/Makefile b/tools/lib/subcmd/Makefile
index 3d1c3b5b5150..95563b8e1ad7 100644
--- a/tools/lib/subcmd/Makefile
+++ b/tools/lib/subcmd/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1include ../../scripts/Makefile.include 2include ../../scripts/Makefile.include
2include ../../scripts/utilities.mak # QUIET_CLEAN 3include ../../scripts/utilities.mak # QUIET_CLEAN
3 4
@@ -21,7 +22,7 @@ LIBFILE = $(OUTPUT)libsubcmd.a
21CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 22CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
22CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC 23CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
23 24
24ifeq ($(CC), clang) 25ifeq ($(CC_NO_CLANG), 0)
25 CFLAGS += -O3 26 CFLAGS += -O3
26else 27else
27 CFLAGS += -O6 28 CFLAGS += -O6
diff --git a/tools/lib/subcmd/exec-cmd.c b/tools/lib/subcmd/exec-cmd.c
index 1ae833af1a4a..33e94fb83986 100644
--- a/tools/lib/subcmd/exec-cmd.c
+++ b/tools/lib/subcmd/exec-cmd.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include <linux/string.h> 3#include <linux/string.h>
3#include <sys/types.h> 4#include <sys/types.h>
diff --git a/tools/lib/subcmd/exec-cmd.h b/tools/lib/subcmd/exec-cmd.h
index 5d08bda31d90..aba591b8d254 100644
--- a/tools/lib/subcmd/exec-cmd.h
+++ b/tools/lib/subcmd/exec-cmd.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __SUBCMD_EXEC_CMD_H 2#ifndef __SUBCMD_EXEC_CMD_H
2#define __SUBCMD_EXEC_CMD_H 3#define __SUBCMD_EXEC_CMD_H
3 4
diff --git a/tools/lib/subcmd/help.c b/tools/lib/subcmd/help.c
index ba970a73d053..2859f107abc8 100644
--- a/tools/lib/subcmd/help.c
+++ b/tools/lib/subcmd/help.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <string.h> 4#include <string.h>
@@ -171,7 +172,7 @@ static void list_commands_in_dir(struct cmdnames *cmds,
171 while ((de = readdir(dir)) != NULL) { 172 while ((de = readdir(dir)) != NULL) {
172 int entlen; 173 int entlen;
173 174
174 if (prefixcmp(de->d_name, prefix)) 175 if (!strstarts(de->d_name, prefix))
175 continue; 176 continue;
176 177
177 astrcat(&buf, de->d_name); 178 astrcat(&buf, de->d_name);
diff --git a/tools/lib/subcmd/help.h b/tools/lib/subcmd/help.h
index 9bd4223dc722..355c066c8d49 100644
--- a/tools/lib/subcmd/help.h
+++ b/tools/lib/subcmd/help.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __SUBCMD_HELP_H 2#ifndef __SUBCMD_HELP_H
2#define __SUBCMD_HELP_H 3#define __SUBCMD_HELP_H
3 4
diff --git a/tools/lib/subcmd/pager.c b/tools/lib/subcmd/pager.c
index 6518bea926d6..5ba754d17952 100644
--- a/tools/lib/subcmd/pager.c
+++ b/tools/lib/subcmd/pager.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/select.h> 2#include <sys/select.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/lib/subcmd/pager.h b/tools/lib/subcmd/pager.h
index 623f5542d05d..f1a53cf29880 100644
--- a/tools/lib/subcmd/pager.h
+++ b/tools/lib/subcmd/pager.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __SUBCMD_PAGER_H 2#ifndef __SUBCMD_PAGER_H
2#define __SUBCMD_PAGER_H 3#define __SUBCMD_PAGER_H
3 4
diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c
index 359bfa77f39c..f6a1babcbac4 100644
--- a/tools/lib/subcmd/parse-options.c
+++ b/tools/lib/subcmd/parse-options.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include <linux/string.h> 3#include <linux/string.h>
3#include <linux/types.h> 4#include <linux/types.h>
@@ -368,7 +369,7 @@ retry:
368 return 0; 369 return 0;
369 } 370 }
370 if (!rest) { 371 if (!rest) {
371 if (!prefixcmp(options->long_name, "no-")) { 372 if (strstarts(options->long_name, "no-")) {
372 /* 373 /*
373 * The long name itself starts with "no-", so 374 * The long name itself starts with "no-", so
374 * accept the option without "no-" so that users 375 * accept the option without "no-" so that users
@@ -381,7 +382,7 @@ retry:
381 goto match; 382 goto match;
382 } 383 }
383 /* Abbreviated case */ 384 /* Abbreviated case */
384 if (!prefixcmp(options->long_name + 3, arg)) { 385 if (strstarts(options->long_name + 3, arg)) {
385 flags |= OPT_UNSET; 386 flags |= OPT_UNSET;
386 goto is_abbreviated; 387 goto is_abbreviated;
387 } 388 }
@@ -406,7 +407,7 @@ is_abbreviated:
406 continue; 407 continue;
407 } 408 }
408 /* negated and abbreviated very much? */ 409 /* negated and abbreviated very much? */
409 if (!prefixcmp("no-", arg)) { 410 if (strstarts("no-", arg)) {
410 flags |= OPT_UNSET; 411 flags |= OPT_UNSET;
411 goto is_abbreviated; 412 goto is_abbreviated;
412 } 413 }
@@ -416,7 +417,7 @@ is_abbreviated:
416 flags |= OPT_UNSET; 417 flags |= OPT_UNSET;
417 rest = skip_prefix(arg + 3, options->long_name); 418 rest = skip_prefix(arg + 3, options->long_name);
418 /* abbreviated and negated? */ 419 /* abbreviated and negated? */
419 if (!rest && !prefixcmp(options->long_name, arg + 3)) 420 if (!rest && strstarts(options->long_name, arg + 3))
420 goto is_abbreviated; 421 goto is_abbreviated;
421 if (!rest) 422 if (!rest)
422 continue; 423 continue;
@@ -456,7 +457,7 @@ static void check_typos(const char *arg, const struct option *options)
456 if (strlen(arg) < 3) 457 if (strlen(arg) < 3)
457 return; 458 return;
458 459
459 if (!prefixcmp(arg, "no-")) { 460 if (strstarts(arg, "no-")) {
460 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg); 461 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
461 exit(129); 462 exit(129);
462 } 463 }
@@ -464,7 +465,7 @@ static void check_typos(const char *arg, const struct option *options)
464 for (; options->type != OPTION_END; options++) { 465 for (; options->type != OPTION_END; options++) {
465 if (!options->long_name) 466 if (!options->long_name)
466 continue; 467 continue;
467 if (!prefixcmp(options->long_name, arg)) { 468 if (strstarts(options->long_name, arg)) {
468 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg); 469 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
469 exit(129); 470 exit(129);
470 } 471 }
@@ -933,10 +934,10 @@ opt:
933 if (opts->long_name == NULL) 934 if (opts->long_name == NULL)
934 continue; 935 continue;
935 936
936 if (!prefixcmp(opts->long_name, optstr)) 937 if (strstarts(opts->long_name, optstr))
937 print_option_help(opts, 0); 938 print_option_help(opts, 0);
938 if (!prefixcmp("no-", optstr) && 939 if (strstarts("no-", optstr) &&
939 !prefixcmp(opts->long_name, optstr + 3)) 940 strstarts(opts->long_name, optstr + 3))
940 print_option_help(opts, 0); 941 print_option_help(opts, 0);
941 } 942 }
942 943
diff --git a/tools/lib/subcmd/parse-options.h b/tools/lib/subcmd/parse-options.h
index f054ca1b899d..92fdbe1519f6 100644
--- a/tools/lib/subcmd/parse-options.h
+++ b/tools/lib/subcmd/parse-options.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __SUBCMD_PARSE_OPTIONS_H 2#ifndef __SUBCMD_PARSE_OPTIONS_H
2#define __SUBCMD_PARSE_OPTIONS_H 3#define __SUBCMD_PARSE_OPTIONS_H
3 4
diff --git a/tools/lib/subcmd/run-command.c b/tools/lib/subcmd/run-command.c
index 911f83942723..5cdac2162532 100644
--- a/tools/lib/subcmd/run-command.c
+++ b/tools/lib/subcmd/run-command.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <unistd.h> 2#include <unistd.h>
2#include <sys/types.h> 3#include <sys/types.h>
3#include <sys/stat.h> 4#include <sys/stat.h>
diff --git a/tools/lib/subcmd/run-command.h b/tools/lib/subcmd/run-command.h
index fe2befea1e73..17d969c6add3 100644
--- a/tools/lib/subcmd/run-command.h
+++ b/tools/lib/subcmd/run-command.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __SUBCMD_RUN_COMMAND_H 2#ifndef __SUBCMD_RUN_COMMAND_H
2#define __SUBCMD_RUN_COMMAND_H 3#define __SUBCMD_RUN_COMMAND_H
3 4
diff --git a/tools/lib/subcmd/sigchain.c b/tools/lib/subcmd/sigchain.c
index 3537c348a18e..f0fe3dbef7f7 100644
--- a/tools/lib/subcmd/sigchain.c
+++ b/tools/lib/subcmd/sigchain.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <signal.h> 2#include <signal.h>
2#include "subcmd-util.h" 3#include "subcmd-util.h"
3#include "sigchain.h" 4#include "sigchain.h"
diff --git a/tools/lib/subcmd/sigchain.h b/tools/lib/subcmd/sigchain.h
index 0c919f2874ca..1ec663af43ea 100644
--- a/tools/lib/subcmd/sigchain.h
+++ b/tools/lib/subcmd/sigchain.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __SUBCMD_SIGCHAIN_H 2#ifndef __SUBCMD_SIGCHAIN_H
2#define __SUBCMD_SIGCHAIN_H 3#define __SUBCMD_SIGCHAIN_H
3 4
diff --git a/tools/lib/subcmd/subcmd-config.c b/tools/lib/subcmd/subcmd-config.c
index d017c728bd1b..84a7cf6c7878 100644
--- a/tools/lib/subcmd/subcmd-config.c
+++ b/tools/lib/subcmd/subcmd-config.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "subcmd-config.h" 2#include "subcmd-config.h"
2 3
3#define UNDEFINED "SUBCMD_HAS_NOT_BEEN_INITIALIZED" 4#define UNDEFINED "SUBCMD_HAS_NOT_BEEN_INITIALIZED"
diff --git a/tools/lib/subcmd/subcmd-config.h b/tools/lib/subcmd/subcmd-config.h
index cc8514030b5c..9024dc17d100 100644
--- a/tools/lib/subcmd/subcmd-config.h
+++ b/tools/lib/subcmd/subcmd-config.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_SUBCMD_CONFIG_H 2#ifndef __PERF_SUBCMD_CONFIG_H
2#define __PERF_SUBCMD_CONFIG_H 3#define __PERF_SUBCMD_CONFIG_H
3 4
diff --git a/tools/lib/subcmd/subcmd-util.h b/tools/lib/subcmd/subcmd-util.h
index 8fa5f036eff0..794a375dad36 100644
--- a/tools/lib/subcmd/subcmd-util.h
+++ b/tools/lib/subcmd/subcmd-util.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __SUBCMD_UTIL_H 2#ifndef __SUBCMD_UTIL_H
2#define __SUBCMD_UTIL_H 3#define __SUBCMD_UTIL_H
3 4
diff --git a/tools/lib/symbol/kallsyms.c b/tools/lib/symbol/kallsyms.c
index d270ac00613d..914cb8e3d40b 100644
--- a/tools/lib/symbol/kallsyms.c
+++ b/tools/lib/symbol/kallsyms.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <ctype.h> 2#include <ctype.h>
2#include "symbol/kallsyms.h" 3#include "symbol/kallsyms.h"
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h
index 4071316a766e..bc40101d72c1 100644
--- a/tools/lib/symbol/kallsyms.h
+++ b/tools/lib/symbol/kallsyms.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __TOOLS_KALLSYMS_H_ 2#ifndef __TOOLS_KALLSYMS_H_
2#define __TOOLS_KALLSYMS_H_ 1 3#define __TOOLS_KALLSYMS_H_ 1
3 4
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 9b8555ea3459..46cd5f871ad7 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# trace-cmd version 2# trace-cmd version
2EP_VERSION = 1 3EP_VERSION = 1
3EP_PATCHLEVEL = 1 4EP_PATCHLEVEL = 1
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index 7c214ceb9386..315df0a70265 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -436,13 +436,13 @@ create_arg_exp(enum filter_exp_type etype)
436 return NULL; 436 return NULL;
437 437
438 arg->type = FILTER_ARG_EXP; 438 arg->type = FILTER_ARG_EXP;
439 arg->op.type = etype; 439 arg->exp.type = etype;
440 440
441 return arg; 441 return arg;
442} 442}
443 443
444static struct filter_arg * 444static struct filter_arg *
445create_arg_cmp(enum filter_exp_type etype) 445create_arg_cmp(enum filter_cmp_type ctype)
446{ 446{
447 struct filter_arg *arg; 447 struct filter_arg *arg;
448 448
@@ -452,7 +452,7 @@ create_arg_cmp(enum filter_exp_type etype)
452 452
453 /* Use NUM and change if necessary */ 453 /* Use NUM and change if necessary */
454 arg->type = FILTER_ARG_NUM; 454 arg->type = FILTER_ARG_NUM;
455 arg->op.type = etype; 455 arg->num.type = ctype;
456 456
457 return arg; 457 return arg;
458} 458}
diff --git a/tools/lib/traceevent/plugin_cfg80211.c b/tools/lib/traceevent/plugin_cfg80211.c
index ec57d0c1fbc2..8f8586912da7 100644
--- a/tools/lib/traceevent/plugin_cfg80211.c
+++ b/tools/lib/traceevent/plugin_cfg80211.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <string.h> 3#include <string.h>
3#include <inttypes.h> 4#include <inttypes.h>
diff --git a/tools/lib/traceevent/plugin_scsi.c b/tools/lib/traceevent/plugin_scsi.c
index 3727de48c8d5..5e750af2b461 100644
--- a/tools/lib/traceevent/plugin_scsi.c
+++ b/tools/lib/traceevent/plugin_scsi.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <string.h> 3#include <string.h>
3#include <inttypes.h> 4#include <inttypes.h>
diff --git a/tools/lib/traceevent/plugin_xen.c b/tools/lib/traceevent/plugin_xen.c
index 3a413eaada68..690173bfa13e 100644
--- a/tools/lib/traceevent/plugin_xen.c
+++ b/tools/lib/traceevent/plugin_xen.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <string.h> 4#include <string.h>
diff --git a/tools/lib/vsprintf.c b/tools/lib/vsprintf.c
index 45f9a06daa56..e08ee147eab4 100644
--- a/tools/lib/vsprintf.c
+++ b/tools/lib/vsprintf.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/types.h> 2#include <sys/types.h>
2#include <linux/kernel.h> 3#include <linux/kernel.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/nfsd/inject_fault.sh b/tools/nfsd/inject_fault.sh
index 06a399ac8b2f..10ceee64a09a 100755
--- a/tools/nfsd/inject_fault.sh
+++ b/tools/nfsd/inject_fault.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2# 3#
3# Copyright (c) 2011 Bryan Schumaker <bjschuma@netapp.com> 4# Copyright (c) 2011 Bryan Schumaker <bjschuma@netapp.com>
4# 5#
diff --git a/tools/objtool/.gitignore b/tools/objtool/.gitignore
index d3102c865a95..914cff12899b 100644
--- a/tools/objtool/.gitignore
+++ b/tools/objtool/.gitignore
@@ -1,3 +1,3 @@
1arch/x86/insn/inat-tables.c 1arch/x86/lib/inat-tables.c
2objtool 2objtool
3fixdep 3fixdep
diff --git a/tools/objtool/Build b/tools/objtool/Build
index 6f2e1987c4d9..749becdf5b90 100644
--- a/tools/objtool/Build
+++ b/tools/objtool/Build
@@ -1,6 +1,9 @@
1objtool-y += arch/$(SRCARCH)/ 1objtool-y += arch/$(SRCARCH)/
2objtool-y += builtin-check.o 2objtool-y += builtin-check.o
3objtool-y += builtin-orc.o
3objtool-y += check.o 4objtool-y += check.o
5objtool-y += orc_gen.o
6objtool-y += orc_dump.o
4objtool-y += elf.o 7objtool-y += elf.o
5objtool-y += special.o 8objtool-y += special.o
6objtool-y += objtool.o 9objtool-y += objtool.o
diff --git a/tools/objtool/Documentation/stack-validation.txt b/tools/objtool/Documentation/stack-validation.txt
index 17c1195f11f4..3995735a878f 100644
--- a/tools/objtool/Documentation/stack-validation.txt
+++ b/tools/objtool/Documentation/stack-validation.txt
@@ -11,9 +11,6 @@ analyzes every .o file and ensures the validity of its stack metadata.
11It enforces a set of rules on asm code and C inline assembly code so 11It enforces a set of rules on asm code and C inline assembly code so
12that stack traces can be reliable. 12that stack traces can be reliable.
13 13
14Currently it only checks frame pointer usage, but there are plans to add
15CFI validation for C files and CFI generation for asm files.
16
17For each function, it recursively follows all possible code paths and 14For each function, it recursively follows all possible code paths and
18validates the correct frame pointer state at each instruction. 15validates the correct frame pointer state at each instruction.
19 16
@@ -23,6 +20,10 @@ alternative execution paths to a given instruction (or set of
23instructions). Similarly, it knows how to follow switch statements, for 20instructions). Similarly, it knows how to follow switch statements, for
24which gcc sometimes uses jump tables. 21which gcc sometimes uses jump tables.
25 22
23(Objtool also has an 'orc generate' subcommand which generates debuginfo
24for the ORC unwinder. See Documentation/x86/orc-unwinder.txt in the
25kernel tree for more details.)
26
26 27
27Why do we need stack metadata validation? 28Why do we need stack metadata validation?
28----------------------------------------- 29-----------------------------------------
@@ -93,37 +94,14 @@ a) More reliable stack traces for frame pointer enabled kernels
93 or at the very end of the function after the stack frame has been 94 or at the very end of the function after the stack frame has been
94 destroyed. This is an inherent limitation of frame pointers. 95 destroyed. This is an inherent limitation of frame pointers.
95 96
96b) 100% reliable stack traces for DWARF enabled kernels 97b) ORC (Oops Rewind Capability) unwind table generation
97
98 (NOTE: This is not yet implemented)
99
100 As an alternative to frame pointers, DWARF Call Frame Information
101 (CFI) metadata can be used to walk the stack. Unlike frame pointers,
102 CFI metadata is out of band. So it doesn't affect runtime
103 performance and it can be reliable even when interrupts or exceptions
104 are involved.
105
106 For C code, gcc automatically generates DWARF CFI metadata. But for
107 asm code, generating CFI is a tedious manual approach which requires
108 manually placed .cfi assembler macros to be scattered throughout the
109 code. It's clumsy and very easy to get wrong, and it makes the real
110 code harder to read.
111
112 Stacktool will improve this situation in several ways. For code
113 which already has CFI annotations, it will validate them. For code
114 which doesn't have CFI annotations, it will generate them. So an
115 architecture can opt to strip out all the manual .cfi annotations
116 from their asm code and have objtool generate them instead.
117 98
118 We might also add a runtime stack validation debug option where we 99 An alternative to frame pointers and DWARF, ORC unwind data can be
119 periodically walk the stack from schedule() and/or an NMI to ensure 100 used to walk the stack. Unlike frame pointers, ORC data is out of
120 that the stack metadata is sane and that we reach the bottom of the 101 band. So it doesn't affect runtime performance and it can be
121 stack. 102 reliable even when interrupts or exceptions are involved.
122 103
123 So the benefit of objtool here will be that external tooling should 104 For more details, see Documentation/x86/orc-unwinder.txt.
124 always show perfect stack traces. And the same will be true for
125 kernel warning/oops traces if the architecture has a runtime DWARF
126 unwinder.
127 105
128c) Higher live patching compatibility rate 106c) Higher live patching compatibility rate
129 107
@@ -211,15 +189,15 @@ they mean, and suggestions for how to fix them.
211 function, add proper frame pointer logic using the FRAME_BEGIN and 189 function, add proper frame pointer logic using the FRAME_BEGIN and
212 FRAME_END macros. Otherwise, if it's not a callable function, remove 190 FRAME_END macros. Otherwise, if it's not a callable function, remove
213 its ELF function annotation by changing ENDPROC to END, and instead 191 its ELF function annotation by changing ENDPROC to END, and instead
214 use the manual CFI hint macros in asm/undwarf.h. 192 use the manual unwind hint macros in asm/unwind_hints.h.
215 193
216 If it's a GCC-compiled .c file, the error may be because the function 194 If it's a GCC-compiled .c file, the error may be because the function
217 uses an inline asm() statement which has a "call" instruction. An 195 uses an inline asm() statement which has a "call" instruction. An
218 asm() statement with a call instruction must declare the use of the 196 asm() statement with a call instruction must declare the use of the
219 stack pointer in its output operand. For example, on x86_64: 197 stack pointer in its output operand. On x86_64, this means adding
198 the ASM_CALL_CONSTRAINT as an output constraint:
220 199
221 register void *__sp asm("rsp"); 200 asm volatile("call func" : ASM_CALL_CONSTRAINT);
222 asm volatile("call func" : "+r" (__sp));
223 201
224 Otherwise the stack frame may not get created before the call. 202 Otherwise the stack frame may not get created before the call.
225 203
@@ -231,8 +209,8 @@ they mean, and suggestions for how to fix them.
231 If the error is for an asm file, and the instruction is inside (or 209 If the error is for an asm file, and the instruction is inside (or
232 reachable from) a callable function, the function should be annotated 210 reachable from) a callable function, the function should be annotated
233 with the ENTRY/ENDPROC macros (ENDPROC is the important one). 211 with the ENTRY/ENDPROC macros (ENDPROC is the important one).
234 Otherwise, the code should probably be annotated with the CFI hint 212 Otherwise, the code should probably be annotated with the unwind hint
235 macros in asm/undwarf.h so objtool and the unwinder can know the 213 macros in asm/unwind_hints.h so objtool and the unwinder can know the
236 stack state associated with the code. 214 stack state associated with the code.
237 215
238 If you're 100% sure the code won't affect stack traces, or if you're 216 If you're 100% sure the code won't affect stack traces, or if you're
@@ -258,7 +236,7 @@ they mean, and suggestions for how to fix them.
258 instructions aren't allowed in a callable function, and are most 236 instructions aren't allowed in a callable function, and are most
259 likely part of the kernel entry code. They should usually not have 237 likely part of the kernel entry code. They should usually not have
260 the callable function annotation (ENDPROC) and should always be 238 the callable function annotation (ENDPROC) and should always be
261 annotated with the CFI hint macros in asm/undwarf.h. 239 annotated with the unwind hint macros in asm/unwind_hints.h.
262 240
263 241
2646. file.o: warning: objtool: func()+0x26: sibling call from callable instruction with modified stack frame 2426. file.o: warning: objtool: func()+0x26: sibling call from callable instruction with modified stack frame
@@ -272,7 +250,7 @@ they mean, and suggestions for how to fix them.
272 250
273 If the instruction is not actually in a callable function (e.g. 251 If the instruction is not actually in a callable function (e.g.
274 kernel entry code), change ENDPROC to END and annotate manually with 252 kernel entry code), change ENDPROC to END and annotate manually with
275 the CFI hint macros in asm/undwarf.h. 253 the unwind hint macros in asm/unwind_hints.h.
276 254
277 255
2787. file: warning: objtool: func()+0x5c: stack state mismatch 2567. file: warning: objtool: func()+0x5c: stack state mismatch
@@ -288,8 +266,8 @@ they mean, and suggestions for how to fix them.
288 266
289 Another possibility is that the code has some asm or inline asm which 267 Another possibility is that the code has some asm or inline asm which
290 does some unusual things to the stack or the frame pointer. In such 268 does some unusual things to the stack or the frame pointer. In such
291 cases it's probably appropriate to use the CFI hint macros in 269 cases it's probably appropriate to use the unwind hint macros in
292 asm/undwarf.h. 270 asm/unwind_hints.h.
293 271
294 272
2958. file.o: warning: objtool: funcA() falls through to next function funcB() 2738. file.o: warning: objtool: funcA() falls through to next function funcB()
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 0e2765e243c0..0f94af3ccaaa 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1include ../scripts/Makefile.include 2include ../scripts/Makefile.include
2include ../scripts/Makefile.arch 3include ../scripts/Makefile.arch
3 4
@@ -24,8 +25,11 @@ OBJTOOL_IN := $(OBJTOOL)-in.o
24 25
25all: $(OBJTOOL) 26all: $(OBJTOOL)
26 27
27INCLUDES := -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi 28INCLUDES := -I$(srctree)/tools/include \
28CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -Wno-switch-default -Wno-switch-enum -fomit-frame-pointer -O2 -g $(INCLUDES) 29 -I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi \
30 -I$(srctree)/tools/objtool/arch/$(ARCH)/include
31WARNINGS := $(EXTRA_WARNINGS) -Wno-switch-default -Wno-switch-enum -Wno-packed
32CFLAGS += -Wall -Werror $(WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES)
29LDFLAGS += -lelf $(LIBSUBCMD) 33LDFLAGS += -lelf $(LIBSUBCMD)
30 34
31# Allow old libelf to be used: 35# Allow old libelf to be used:
@@ -39,19 +43,8 @@ include $(srctree)/tools/build/Makefile.include
39$(OBJTOOL_IN): fixdep FORCE 43$(OBJTOOL_IN): fixdep FORCE
40 @$(MAKE) $(build)=objtool 44 @$(MAKE) $(build)=objtool
41 45
42# Busybox's diff doesn't have -I, avoid warning in that case
43#
44$(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN) 46$(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN)
45 @(diff -I 2>&1 | grep -q 'option requires an argument' && \ 47 @./sync-check.sh
46 test -d ../../kernel -a -d ../../tools -a -d ../objtool && (( \
47 diff -I'^#include' arch/x86/insn/insn.c ../../arch/x86/lib/insn.c >/dev/null && \
48 diff -I'^#include' arch/x86/insn/inat.c ../../arch/x86/lib/inat.c >/dev/null && \
49 diff arch/x86/insn/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null && \
50 diff arch/x86/insn/gen-insn-attr-x86.awk ../../arch/x86/tools/gen-insn-attr-x86.awk >/dev/null && \
51 diff -I'^#include' arch/x86/insn/insn.h ../../arch/x86/include/asm/insn.h >/dev/null && \
52 diff -I'^#include' arch/x86/insn/inat.h ../../arch/x86/include/asm/inat.h >/dev/null && \
53 diff -I'^#include' arch/x86/insn/inat_types.h ../../arch/x86/include/asm/inat_types.h >/dev/null) \
54 || echo "warning: objtool: x86 instruction decoder differs from kernel" >&2 )) || true
55 $(QUIET_LINK)$(CC) $(OBJTOOL_IN) $(LDFLAGS) -o $@ 48 $(QUIET_LINK)$(CC) $(OBJTOOL_IN) $(LDFLAGS) -o $@
56 49
57 50
@@ -61,7 +54,7 @@ $(LIBSUBCMD): fixdep FORCE
61clean: 54clean:
62 $(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL) 55 $(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL)
63 $(Q)find $(OUTPUT) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 56 $(Q)find $(OUTPUT) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
64 $(Q)$(RM) $(OUTPUT)arch/x86/insn/inat-tables.c $(OUTPUT)fixdep 57 $(Q)$(RM) $(OUTPUT)arch/x86/lib/inat-tables.c $(OUTPUT)fixdep
65 58
66FORCE: 59FORCE:
67 60
diff --git a/tools/objtool/arch.h b/tools/objtool/arch.h
index 21aeca874edb..b0d7dc3d71b5 100644
--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@ -31,8 +31,9 @@
31#define INSN_RETURN 6 31#define INSN_RETURN 6
32#define INSN_CONTEXT_SWITCH 7 32#define INSN_CONTEXT_SWITCH 7
33#define INSN_STACK 8 33#define INSN_STACK 8
34#define INSN_NOP 9 34#define INSN_BUG 9
35#define INSN_OTHER 10 35#define INSN_NOP 10
36#define INSN_OTHER 11
36#define INSN_LAST INSN_OTHER 37#define INSN_LAST INSN_OTHER
37 38
38enum op_dest_type { 39enum op_dest_type {
diff --git a/tools/objtool/arch/x86/Build b/tools/objtool/arch/x86/Build
index debbdb0b5c43..b998412c017d 100644
--- a/tools/objtool/arch/x86/Build
+++ b/tools/objtool/arch/x86/Build
@@ -1,12 +1,12 @@
1objtool-y += decode.o 1objtool-y += decode.o
2 2
3inat_tables_script = arch/x86/insn/gen-insn-attr-x86.awk 3inat_tables_script = arch/x86/tools/gen-insn-attr-x86.awk
4inat_tables_maps = arch/x86/insn/x86-opcode-map.txt 4inat_tables_maps = arch/x86/lib/x86-opcode-map.txt
5 5
6$(OUTPUT)arch/x86/insn/inat-tables.c: $(inat_tables_script) $(inat_tables_maps) 6$(OUTPUT)arch/x86/lib/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
7 $(call rule_mkdir) 7 $(call rule_mkdir)
8 $(Q)$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ 8 $(Q)$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@
9 9
10$(OUTPUT)arch/x86/decode.o: $(OUTPUT)arch/x86/insn/inat-tables.c 10$(OUTPUT)arch/x86/decode.o: $(OUTPUT)arch/x86/lib/inat-tables.c
11 11
12CFLAGS_decode.o += -I$(OUTPUT)arch/x86/insn 12CFLAGS_decode.o += -I$(OUTPUT)arch/x86/lib
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index a36c2eba64e7..8acfc47af70e 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -19,9 +19,9 @@
19#include <stdlib.h> 19#include <stdlib.h>
20 20
21#define unlikely(cond) (cond) 21#define unlikely(cond) (cond)
22#include "insn/insn.h" 22#include <asm/insn.h>
23#include "insn/inat.c" 23#include "lib/inat.c"
24#include "insn/insn.c" 24#include "lib/insn.c"
25 25
26#include "../../elf.h" 26#include "../../elf.h"
27#include "../../arch.h" 27#include "../../arch.h"
@@ -86,8 +86,8 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
86 struct insn insn; 86 struct insn insn;
87 int x86_64, sign; 87 int x86_64, sign;
88 unsigned char op1, op2, rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, 88 unsigned char op1, op2, rex = 0, rex_b = 0, rex_r = 0, rex_w = 0,
89 modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0, 89 rex_x = 0, modrm = 0, modrm_mod = 0, modrm_rm = 0,
90 sib = 0; 90 modrm_reg = 0, sib = 0;
91 91
92 x86_64 = is_x86_64(elf); 92 x86_64 = is_x86_64(elf);
93 if (x86_64 == -1) 93 if (x86_64 == -1)
@@ -114,6 +114,7 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
114 rex = insn.rex_prefix.bytes[0]; 114 rex = insn.rex_prefix.bytes[0];
115 rex_w = X86_REX_W(rex) >> 3; 115 rex_w = X86_REX_W(rex) >> 3;
116 rex_r = X86_REX_R(rex) >> 2; 116 rex_r = X86_REX_R(rex) >> 2;
117 rex_x = X86_REX_X(rex) >> 1;
117 rex_b = X86_REX_B(rex); 118 rex_b = X86_REX_B(rex);
118 } 119 }
119 120
@@ -207,16 +208,28 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
207 break; 208 break;
208 209
209 case 0x89: 210 case 0x89:
210 if (rex == 0x48 && modrm == 0xe5) { 211 if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) {
211 212
212 /* mov %rsp, %rbp */ 213 /* mov %rsp, reg */
213 *type = INSN_STACK; 214 *type = INSN_STACK;
214 op->src.type = OP_SRC_REG; 215 op->src.type = OP_SRC_REG;
215 op->src.reg = CFI_SP; 216 op->src.reg = CFI_SP;
216 op->dest.type = OP_DEST_REG; 217 op->dest.type = OP_DEST_REG;
217 op->dest.reg = CFI_BP; 218 op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
219 break;
220 }
221
222 if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
223
224 /* mov reg, %rsp */
225 *type = INSN_STACK;
226 op->src.type = OP_SRC_REG;
227 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
228 op->dest.type = OP_DEST_REG;
229 op->dest.reg = CFI_SP;
218 break; 230 break;
219 } 231 }
232
220 /* fallthrough */ 233 /* fallthrough */
221 case 0x88: 234 case 0x88:
222 if (!rex_b && 235 if (!rex_b &&
@@ -269,56 +282,33 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
269 break; 282 break;
270 283
271 case 0x8d: 284 case 0x8d:
272 if (rex == 0x48 && modrm == 0x65) { 285 if (sib == 0x24 && rex_w && !rex_b && !rex_x) {
273 286
274 /* lea -disp(%rbp), %rsp */
275 *type = INSN_STACK; 287 *type = INSN_STACK;
276 op->src.type = OP_SRC_ADD; 288 if (!insn.displacement.value) {
277 op->src.reg = CFI_BP; 289 /* lea (%rsp), reg */
278 op->src.offset = insn.displacement.value; 290 op->src.type = OP_SRC_REG;
279 op->dest.type = OP_DEST_REG; 291 } else {
280 op->dest.reg = CFI_SP; 292 /* lea disp(%rsp), reg */
281 break; 293 op->src.type = OP_SRC_ADD;
282 } 294 op->src.offset = insn.displacement.value;
283 295 }
284 if (rex == 0x4c && modrm == 0x54 && sib == 0x24 &&
285 insn.displacement.value == 8) {
286
287 /*
288 * lea 0x8(%rsp), %r10
289 *
290 * Here r10 is the "drap" pointer, used as a stack
291 * pointer helper when the stack gets realigned.
292 */
293 *type = INSN_STACK;
294 op->src.type = OP_SRC_ADD;
295 op->src.reg = CFI_SP; 296 op->src.reg = CFI_SP;
296 op->src.offset = 8;
297 op->dest.type = OP_DEST_REG; 297 op->dest.type = OP_DEST_REG;
298 op->dest.reg = CFI_R10; 298 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
299 break;
300 }
301 299
302 if (rex == 0x4c && modrm == 0x6c && sib == 0x24 && 300 } else if (rex == 0x48 && modrm == 0x65) {
303 insn.displacement.value == 16) {
304 301
305 /* 302 /* lea disp(%rbp), %rsp */
306 * lea 0x10(%rsp), %r13
307 *
308 * Here r13 is the "drap" pointer, used as a stack
309 * pointer helper when the stack gets realigned.
310 */
311 *type = INSN_STACK; 303 *type = INSN_STACK;
312 op->src.type = OP_SRC_ADD; 304 op->src.type = OP_SRC_ADD;
313 op->src.reg = CFI_SP; 305 op->src.reg = CFI_BP;
314 op->src.offset = 16; 306 op->src.offset = insn.displacement.value;
315 op->dest.type = OP_DEST_REG; 307 op->dest.type = OP_DEST_REG;
316 op->dest.reg = CFI_R13; 308 op->dest.reg = CFI_SP;
317 break;
318 }
319 309
320 if (rex == 0x49 && modrm == 0x62 && 310 } else if (rex == 0x49 && modrm == 0x62 &&
321 insn.displacement.value == -8) { 311 insn.displacement.value == -8) {
322 312
323 /* 313 /*
324 * lea -0x8(%r10), %rsp 314 * lea -0x8(%r10), %rsp
@@ -332,11 +322,9 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
332 op->src.offset = -8; 322 op->src.offset = -8;
333 op->dest.type = OP_DEST_REG; 323 op->dest.type = OP_DEST_REG;
334 op->dest.reg = CFI_SP; 324 op->dest.reg = CFI_SP;
335 break;
336 }
337 325
338 if (rex == 0x49 && modrm == 0x65 && 326 } else if (rex == 0x49 && modrm == 0x65 &&
339 insn.displacement.value == -16) { 327 insn.displacement.value == -16) {
340 328
341 /* 329 /*
342 * lea -0x10(%r13), %rsp 330 * lea -0x10(%r13), %rsp
@@ -350,7 +338,6 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
350 op->src.offset = -16; 338 op->src.offset = -16;
351 op->dest.type = OP_DEST_REG; 339 op->dest.type = OP_DEST_REG;
352 op->dest.reg = CFI_SP; 340 op->dest.reg = CFI_SP;
353 break;
354 } 341 }
355 342
356 break; 343 break;
@@ -382,20 +369,27 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
382 369
383 case 0x0f: 370 case 0x0f:
384 371
385 if (op2 >= 0x80 && op2 <= 0x8f) 372 if (op2 >= 0x80 && op2 <= 0x8f) {
373
386 *type = INSN_JUMP_CONDITIONAL; 374 *type = INSN_JUMP_CONDITIONAL;
387 else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 || 375
388 op2 == 0x35) 376 } else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 ||
377 op2 == 0x35) {
389 378
390 /* sysenter, sysret */ 379 /* sysenter, sysret */
391 *type = INSN_CONTEXT_SWITCH; 380 *type = INSN_CONTEXT_SWITCH;
392 381
393 else if (op2 == 0x0d || op2 == 0x1f) 382 } else if (op2 == 0x0b || op2 == 0xb9) {
383
384 /* ud2 */
385 *type = INSN_BUG;
386
387 } else if (op2 == 0x0d || op2 == 0x1f) {
394 388
395 /* nopl/nopw */ 389 /* nopl/nopw */
396 *type = INSN_NOP; 390 *type = INSN_NOP;
397 391
398 else if (op2 == 0xa0 || op2 == 0xa8) { 392 } else if (op2 == 0xa0 || op2 == 0xa8) {
399 393
400 /* push fs/gs */ 394 /* push fs/gs */
401 *type = INSN_STACK; 395 *type = INSN_STACK;
diff --git a/tools/objtool/arch/x86/insn/inat.h b/tools/objtool/arch/x86/include/asm/inat.h
index 125ecd2a300d..1c78580e58be 100644
--- a/tools/objtool/arch/x86/insn/inat.h
+++ b/tools/objtool/arch/x86/include/asm/inat.h
@@ -20,7 +20,7 @@
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * 21 *
22 */ 22 */
23#include "inat_types.h" 23#include <asm/inat_types.h>
24 24
25/* 25/*
26 * Internal bits. Don't use bitmasks directly, because these bits are 26 * Internal bits. Don't use bitmasks directly, because these bits are
@@ -97,6 +97,16 @@
97#define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM) 97#define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM)
98#define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS) 98#define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS)
99 99
100/* Identifiers for segment registers */
101#define INAT_SEG_REG_IGNORE 0
102#define INAT_SEG_REG_DEFAULT 1
103#define INAT_SEG_REG_CS 2
104#define INAT_SEG_REG_SS 3
105#define INAT_SEG_REG_DS 4
106#define INAT_SEG_REG_ES 5
107#define INAT_SEG_REG_FS 6
108#define INAT_SEG_REG_GS 7
109
100/* Attribute search APIs */ 110/* Attribute search APIs */
101extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode); 111extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode);
102extern int inat_get_last_prefix_id(insn_byte_t last_pfx); 112extern int inat_get_last_prefix_id(insn_byte_t last_pfx);
diff --git a/tools/objtool/arch/x86/insn/inat_types.h b/tools/objtool/arch/x86/include/asm/inat_types.h
index cb3c20ce39cf..cb3c20ce39cf 100644
--- a/tools/objtool/arch/x86/insn/inat_types.h
+++ b/tools/objtool/arch/x86/include/asm/inat_types.h
diff --git a/tools/objtool/arch/x86/insn/insn.h b/tools/objtool/arch/x86/include/asm/insn.h
index e23578c7b1be..b3e32b010ab1 100644
--- a/tools/objtool/arch/x86/insn/insn.h
+++ b/tools/objtool/arch/x86/include/asm/insn.h
@@ -21,7 +21,7 @@
21 */ 21 */
22 22
23/* insn_attr_t is defined in inat.h */ 23/* insn_attr_t is defined in inat.h */
24#include "inat.h" 24#include <asm/inat.h>
25 25
26struct insn_field { 26struct insn_field {
27 union { 27 union {
diff --git a/tools/objtool/arch/x86/include/asm/orc_types.h b/tools/objtool/arch/x86/include/asm/orc_types.h
new file mode 100644
index 000000000000..9c9dc579bd7d
--- /dev/null
+++ b/tools/objtool/arch/x86/include/asm/orc_types.h
@@ -0,0 +1,107 @@
1/*
2 * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
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 2
7 * of the License, or (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef _ORC_TYPES_H
19#define _ORC_TYPES_H
20
21#include <linux/types.h>
22#include <linux/compiler.h>
23
24/*
25 * The ORC_REG_* registers are base registers which are used to find other
26 * registers on the stack.
27 *
28 * ORC_REG_PREV_SP, also known as DWARF Call Frame Address (CFA), is the
29 * address of the previous frame: the caller's SP before it called the current
30 * function.
31 *
32 * ORC_REG_UNDEFINED means the corresponding register's value didn't change in
33 * the current frame.
34 *
35 * The most commonly used base registers are SP and BP -- which the previous SP
36 * is usually based on -- and PREV_SP and UNDEFINED -- which the previous BP is
37 * usually based on.
38 *
39 * The rest of the base registers are needed for special cases like entry code
40 * and GCC realigned stacks.
41 */
42#define ORC_REG_UNDEFINED 0
43#define ORC_REG_PREV_SP 1
44#define ORC_REG_DX 2
45#define ORC_REG_DI 3
46#define ORC_REG_BP 4
47#define ORC_REG_SP 5
48#define ORC_REG_R10 6
49#define ORC_REG_R13 7
50#define ORC_REG_BP_INDIRECT 8
51#define ORC_REG_SP_INDIRECT 9
52#define ORC_REG_MAX 15
53
54/*
55 * ORC_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP (the
56 * caller's SP right before it made the call). Used for all callable
57 * functions, i.e. all C code and all callable asm functions.
58 *
59 * ORC_TYPE_REGS: Used in entry code to indicate that sp_reg+sp_offset points
60 * to a fully populated pt_regs from a syscall, interrupt, or exception.
61 *
62 * ORC_TYPE_REGS_IRET: Used in entry code to indicate that sp_reg+sp_offset
63 * points to the iret return frame.
64 *
65 * The UNWIND_HINT macros are used only for the unwind_hint struct. They
66 * aren't used in struct orc_entry due to size and complexity constraints.
67 * Objtool converts them to real types when it converts the hints to orc
68 * entries.
69 */
70#define ORC_TYPE_CALL 0
71#define ORC_TYPE_REGS 1
72#define ORC_TYPE_REGS_IRET 2
73#define UNWIND_HINT_TYPE_SAVE 3
74#define UNWIND_HINT_TYPE_RESTORE 4
75
76#ifndef __ASSEMBLY__
77/*
78 * This struct is more or less a vastly simplified version of the DWARF Call
79 * Frame Information standard. It contains only the necessary parts of DWARF
80 * CFI, simplified for ease of access by the in-kernel unwinder. It tells the
81 * unwinder how to find the previous SP and BP (and sometimes entry regs) on
82 * the stack for a given code address. Each instance of the struct corresponds
83 * to one or more code locations.
84 */
85struct orc_entry {
86 s16 sp_offset;
87 s16 bp_offset;
88 unsigned sp_reg:4;
89 unsigned bp_reg:4;
90 unsigned type:2;
91} __packed;
92
93/*
94 * This struct is used by asm and inline asm code to manually annotate the
95 * location of registers on the stack for the ORC unwinder.
96 *
97 * Type can be either ORC_TYPE_* or UNWIND_HINT_TYPE_*.
98 */
99struct unwind_hint {
100 u32 ip;
101 s16 sp_offset;
102 u8 sp_reg;
103 u8 type;
104};
105#endif /* __ASSEMBLY__ */
106
107#endif /* _ORC_TYPES_H */
diff --git a/tools/objtool/arch/x86/insn/inat.c b/tools/objtool/arch/x86/lib/inat.c
index e4bf28e6f4c7..c1f01a8e9f65 100644
--- a/tools/objtool/arch/x86/insn/inat.c
+++ b/tools/objtool/arch/x86/lib/inat.c
@@ -18,7 +18,7 @@
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * 19 *
20 */ 20 */
21#include "insn.h" 21#include <asm/insn.h>
22 22
23/* Attribute tables are generated from opcode map */ 23/* Attribute tables are generated from opcode map */
24#include "inat-tables.c" 24#include "inat-tables.c"
diff --git a/tools/objtool/arch/x86/insn/insn.c b/tools/objtool/arch/x86/lib/insn.c
index ca983e2bea8b..1088eb8f3a5f 100644
--- a/tools/objtool/arch/x86/insn/insn.c
+++ b/tools/objtool/arch/x86/lib/insn.c
@@ -23,8 +23,8 @@
23#else 23#else
24#include <string.h> 24#include <string.h>
25#endif 25#endif
26#include "inat.h" 26#include <asm/inat.h>
27#include "insn.h" 27#include <asm/insn.h>
28 28
29/* Verify next sizeof(t) bytes can be on the same instruction */ 29/* Verify next sizeof(t) bytes can be on the same instruction */
30#define validate_next(t, insn, n) \ 30#define validate_next(t, insn, n) \
diff --git a/tools/objtool/arch/x86/insn/x86-opcode-map.txt b/tools/objtool/arch/x86/lib/x86-opcode-map.txt
index 12e377184ee4..12e377184ee4 100644
--- a/tools/objtool/arch/x86/insn/x86-opcode-map.txt
+++ b/tools/objtool/arch/x86/lib/x86-opcode-map.txt
diff --git a/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk b/tools/objtool/arch/x86/tools/gen-insn-attr-x86.awk
index a3d2c62fd805..b02a36b2c14f 100644
--- a/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk
+++ b/tools/objtool/arch/x86/tools/gen-insn-attr-x86.awk
@@ -1,4 +1,5 @@
1#!/bin/awk -f 1#!/bin/awk -f
2# SPDX-License-Identifier: GPL-2.0
2# gen-insn-attr-x86.awk: Instruction attribute table generator 3# gen-insn-attr-x86.awk: Instruction attribute table generator
3# Written by Masami Hiramatsu <mhiramat@redhat.com> 4# Written by Masami Hiramatsu <mhiramat@redhat.com>
4# 5#
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index 365c34ecab26..57254f5b2779 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -29,7 +29,7 @@
29#include "builtin.h" 29#include "builtin.h"
30#include "check.h" 30#include "check.h"
31 31
32bool nofp; 32bool no_fp, no_unreachable;
33 33
34static const char * const check_usage[] = { 34static const char * const check_usage[] = {
35 "objtool check [<options>] file.o", 35 "objtool check [<options>] file.o",
@@ -37,7 +37,8 @@ static const char * const check_usage[] = {
37}; 37};
38 38
39const struct option check_options[] = { 39const struct option check_options[] = {
40 OPT_BOOLEAN('f', "no-fp", &nofp, "Skip frame pointer validation"), 40 OPT_BOOLEAN('f', "no-fp", &no_fp, "Skip frame pointer validation"),
41 OPT_BOOLEAN('u', "no-unreachable", &no_unreachable, "Skip 'unreachable instruction' warnings"),
41 OPT_END(), 42 OPT_END(),
42}; 43};
43 44
@@ -52,5 +53,5 @@ int cmd_check(int argc, const char **argv)
52 53
53 objname = argv[0]; 54 objname = argv[0];
54 55
55 return check(objname, nofp); 56 return check(objname, no_fp, no_unreachable, false);
56} 57}
diff --git a/tools/objtool/builtin-orc.c b/tools/objtool/builtin-orc.c
new file mode 100644
index 000000000000..4c6b5c9ef073
--- /dev/null
+++ b/tools/objtool/builtin-orc.c
@@ -0,0 +1,70 @@
1/*
2 * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
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 2
7 * of the License, or (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * objtool orc:
20 *
21 * This command analyzes a .o file and adds .orc_unwind and .orc_unwind_ip
22 * sections to it, which is used by the in-kernel ORC unwinder.
23 *
24 * This command is a superset of "objtool check".
25 */
26
27#include <string.h>
28#include <subcmd/parse-options.h>
29#include "builtin.h"
30#include "check.h"
31
32
33static const char *orc_usage[] = {
34 "objtool orc generate [<options>] file.o",
35 "objtool orc dump file.o",
36 NULL,
37};
38
39extern const struct option check_options[];
40extern bool no_fp, no_unreachable;
41
42int cmd_orc(int argc, const char **argv)
43{
44 const char *objname;
45
46 argc--; argv++;
47 if (!strncmp(argv[0], "gen", 3)) {
48 argc = parse_options(argc, argv, check_options, orc_usage, 0);
49 if (argc != 1)
50 usage_with_options(orc_usage, check_options);
51
52 objname = argv[0];
53
54 return check(objname, no_fp, no_unreachable, true);
55
56 }
57
58 if (!strcmp(argv[0], "dump")) {
59 if (argc != 2)
60 usage_with_options(orc_usage, check_options);
61
62 objname = argv[1];
63
64 return orc_dump(objname);
65 }
66
67 usage_with_options(orc_usage, check_options);
68
69 return 0;
70}
diff --git a/tools/objtool/builtin.h b/tools/objtool/builtin.h
index 34d2ba78a616..dd526067fed5 100644
--- a/tools/objtool/builtin.h
+++ b/tools/objtool/builtin.h
@@ -18,5 +18,6 @@
18#define _BUILTIN_H 18#define _BUILTIN_H
19 19
20extern int cmd_check(int argc, const char **argv); 20extern int cmd_check(int argc, const char **argv);
21extern int cmd_orc(int argc, const char **argv);
21 22
22#endif /* _BUILTIN_H */ 23#endif /* _BUILTIN_H */
diff --git a/tools/objtool/cfi.h b/tools/objtool/cfi.h
index 443ab2c69992..2fe883c665c7 100644
--- a/tools/objtool/cfi.h
+++ b/tools/objtool/cfi.h
@@ -40,7 +40,7 @@
40#define CFI_R14 14 40#define CFI_R14 14
41#define CFI_R15 15 41#define CFI_R15 15
42#define CFI_RA 16 42#define CFI_RA 16
43#define CFI_NUM_REGS 17 43#define CFI_NUM_REGS 17
44 44
45struct cfi_reg { 45struct cfi_reg {
46 int base; 46 int base;
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 2c6d74880403..9b341584eb1b 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -33,11 +33,11 @@ struct alternative {
33}; 33};
34 34
35const char *objname; 35const char *objname;
36static bool nofp; 36static bool no_fp;
37struct cfi_state initial_func_cfi; 37struct cfi_state initial_func_cfi;
38 38
39static struct instruction *find_insn(struct objtool_file *file, 39struct instruction *find_insn(struct objtool_file *file,
40 struct section *sec, unsigned long offset) 40 struct section *sec, unsigned long offset)
41{ 41{
42 struct instruction *insn; 42 struct instruction *insn;
43 43
@@ -59,19 +59,6 @@ static struct instruction *next_insn_same_sec(struct objtool_file *file,
59 return next; 59 return next;
60} 60}
61 61
62static bool gcov_enabled(struct objtool_file *file)
63{
64 struct section *sec;
65 struct symbol *sym;
66
67 for_each_sec(file, sec)
68 list_for_each_entry(sym, &sec->symbol_list, list)
69 if (!strncmp(sym->name, "__gcov_.", 8))
70 return true;
71
72 return false;
73}
74
75#define func_for_each_insn(file, func, insn) \ 62#define func_for_each_insn(file, func, insn) \
76 for (insn = find_insn(file, func->sec, func->offset); \ 63 for (insn = find_insn(file, func->sec, func->offset); \
77 insn && &insn->list != &file->insn_list && \ 64 insn && &insn->list != &file->insn_list && \
@@ -100,7 +87,6 @@ static bool gcov_enabled(struct objtool_file *file)
100static bool ignore_func(struct objtool_file *file, struct symbol *func) 87static bool ignore_func(struct objtool_file *file, struct symbol *func)
101{ 88{
102 struct rela *rela; 89 struct rela *rela;
103 struct instruction *insn;
104 90
105 /* check for STACK_FRAME_NON_STANDARD */ 91 /* check for STACK_FRAME_NON_STANDARD */
106 if (file->whitelist && file->whitelist->rela) 92 if (file->whitelist && file->whitelist->rela)
@@ -113,11 +99,6 @@ static bool ignore_func(struct objtool_file *file, struct symbol *func)
113 return true; 99 return true;
114 } 100 }
115 101
116 /* check if it has a context switching instruction */
117 func_for_each_insn(file, func, insn)
118 if (insn->type == INSN_CONTEXT_SWITCH)
119 return true;
120
121 return false; 102 return false;
122} 103}
123 104
@@ -237,9 +218,12 @@ static void clear_insn_state(struct insn_state *state)
237 218
238 memset(state, 0, sizeof(*state)); 219 memset(state, 0, sizeof(*state));
239 state->cfa.base = CFI_UNDEFINED; 220 state->cfa.base = CFI_UNDEFINED;
240 for (i = 0; i < CFI_NUM_REGS; i++) 221 for (i = 0; i < CFI_NUM_REGS; i++) {
241 state->regs[i].base = CFI_UNDEFINED; 222 state->regs[i].base = CFI_UNDEFINED;
223 state->vals[i].base = CFI_UNDEFINED;
224 }
242 state->drap_reg = CFI_UNDEFINED; 225 state->drap_reg = CFI_UNDEFINED;
226 state->drap_offset = -1;
243} 227}
244 228
245/* 229/*
@@ -259,6 +243,11 @@ static int decode_instructions(struct objtool_file *file)
259 if (!(sec->sh.sh_flags & SHF_EXECINSTR)) 243 if (!(sec->sh.sh_flags & SHF_EXECINSTR))
260 continue; 244 continue;
261 245
246 if (strcmp(sec->name, ".altinstr_replacement") &&
247 strcmp(sec->name, ".altinstr_aux") &&
248 strncmp(sec->name, ".discard.", 9))
249 sec->text = true;
250
262 for (offset = 0; offset < sec->len; offset += insn->len) { 251 for (offset = 0; offset < sec->len; offset += insn->len) {
263 insn = malloc(sizeof(*insn)); 252 insn = malloc(sizeof(*insn));
264 if (!insn) { 253 if (!insn) {
@@ -278,12 +267,13 @@ static int decode_instructions(struct objtool_file *file)
278 &insn->immediate, 267 &insn->immediate,
279 &insn->stack_op); 268 &insn->stack_op);
280 if (ret) 269 if (ret)
281 return ret; 270 goto err;
282 271
283 if (!insn->type || insn->type > INSN_LAST) { 272 if (!insn->type || insn->type > INSN_LAST) {
284 WARN_FUNC("invalid instruction type %d", 273 WARN_FUNC("invalid instruction type %d",
285 insn->sec, insn->offset, insn->type); 274 insn->sec, insn->offset, insn->type);
286 return -1; 275 ret = -1;
276 goto err;
287 } 277 }
288 278
289 hash_add(file->insn_hash, &insn->hash, insn->offset); 279 hash_add(file->insn_hash, &insn->hash, insn->offset);
@@ -307,10 +297,14 @@ static int decode_instructions(struct objtool_file *file)
307 } 297 }
308 298
309 return 0; 299 return 0;
300
301err:
302 free(insn);
303 return ret;
310} 304}
311 305
312/* 306/*
313 * Find all uses of the unreachable() macro, which are code path dead ends. 307 * Mark "ud2" instructions and manually annotated dead ends.
314 */ 308 */
315static int add_dead_ends(struct objtool_file *file) 309static int add_dead_ends(struct objtool_file *file)
316{ 310{
@@ -319,9 +313,20 @@ static int add_dead_ends(struct objtool_file *file)
319 struct instruction *insn; 313 struct instruction *insn;
320 bool found; 314 bool found;
321 315
316 /*
317 * By default, "ud2" is a dead end unless otherwise annotated, because
318 * GCC 7 inserts it for certain divide-by-zero cases.
319 */
320 for_each_insn(file, insn)
321 if (insn->type == INSN_BUG)
322 insn->dead_end = true;
323
324 /*
325 * Check for manually annotated dead ends.
326 */
322 sec = find_section_by_name(file->elf, ".rela.discard.unreachable"); 327 sec = find_section_by_name(file->elf, ".rela.discard.unreachable");
323 if (!sec) 328 if (!sec)
324 return 0; 329 goto reachable;
325 330
326 list_for_each_entry(rela, &sec->rela_list, list) { 331 list_for_each_entry(rela, &sec->rela_list, list) {
327 if (rela->sym->type != STT_SECTION) { 332 if (rela->sym->type != STT_SECTION) {
@@ -354,6 +359,48 @@ static int add_dead_ends(struct objtool_file *file)
354 insn->dead_end = true; 359 insn->dead_end = true;
355 } 360 }
356 361
362reachable:
363 /*
364 * These manually annotated reachable checks are needed for GCC 4.4,
365 * where the Linux unreachable() macro isn't supported. In that case
366 * GCC doesn't know the "ud2" is fatal, so it generates code as if it's
367 * not a dead end.
368 */
369 sec = find_section_by_name(file->elf, ".rela.discard.reachable");
370 if (!sec)
371 return 0;
372
373 list_for_each_entry(rela, &sec->rela_list, list) {
374 if (rela->sym->type != STT_SECTION) {
375 WARN("unexpected relocation symbol type in %s", sec->name);
376 return -1;
377 }
378 insn = find_insn(file, rela->sym->sec, rela->addend);
379 if (insn)
380 insn = list_prev_entry(insn, list);
381 else if (rela->addend == rela->sym->sec->len) {
382 found = false;
383 list_for_each_entry_reverse(insn, &file->insn_list, list) {
384 if (insn->sec == rela->sym->sec) {
385 found = true;
386 break;
387 }
388 }
389
390 if (!found) {
391 WARN("can't find reachable insn at %s+0x%x",
392 rela->sym->sec->name, rela->addend);
393 return -1;
394 }
395 } else {
396 WARN("can't find reachable insn at %s+0x%x",
397 rela->sym->sec->name, rela->addend);
398 return -1;
399 }
400
401 insn->dead_end = false;
402 }
403
357 return 0; 404 return 0;
358} 405}
359 406
@@ -874,6 +921,99 @@ static int add_switch_table_alts(struct objtool_file *file)
874 return 0; 921 return 0;
875} 922}
876 923
924static int read_unwind_hints(struct objtool_file *file)
925{
926 struct section *sec, *relasec;
927 struct rela *rela;
928 struct unwind_hint *hint;
929 struct instruction *insn;
930 struct cfi_reg *cfa;
931 int i;
932
933 sec = find_section_by_name(file->elf, ".discard.unwind_hints");
934 if (!sec)
935 return 0;
936
937 relasec = sec->rela;
938 if (!relasec) {
939 WARN("missing .rela.discard.unwind_hints section");
940 return -1;
941 }
942
943 if (sec->len % sizeof(struct unwind_hint)) {
944 WARN("struct unwind_hint size mismatch");
945 return -1;
946 }
947
948 file->hints = true;
949
950 for (i = 0; i < sec->len / sizeof(struct unwind_hint); i++) {
951 hint = (struct unwind_hint *)sec->data->d_buf + i;
952
953 rela = find_rela_by_dest(sec, i * sizeof(*hint));
954 if (!rela) {
955 WARN("can't find rela for unwind_hints[%d]", i);
956 return -1;
957 }
958
959 insn = find_insn(file, rela->sym->sec, rela->addend);
960 if (!insn) {
961 WARN("can't find insn for unwind_hints[%d]", i);
962 return -1;
963 }
964
965 cfa = &insn->state.cfa;
966
967 if (hint->type == UNWIND_HINT_TYPE_SAVE) {
968 insn->save = true;
969 continue;
970
971 } else if (hint->type == UNWIND_HINT_TYPE_RESTORE) {
972 insn->restore = true;
973 insn->hint = true;
974 continue;
975 }
976
977 insn->hint = true;
978
979 switch (hint->sp_reg) {
980 case ORC_REG_UNDEFINED:
981 cfa->base = CFI_UNDEFINED;
982 break;
983 case ORC_REG_SP:
984 cfa->base = CFI_SP;
985 break;
986 case ORC_REG_BP:
987 cfa->base = CFI_BP;
988 break;
989 case ORC_REG_SP_INDIRECT:
990 cfa->base = CFI_SP_INDIRECT;
991 break;
992 case ORC_REG_R10:
993 cfa->base = CFI_R10;
994 break;
995 case ORC_REG_R13:
996 cfa->base = CFI_R13;
997 break;
998 case ORC_REG_DI:
999 cfa->base = CFI_DI;
1000 break;
1001 case ORC_REG_DX:
1002 cfa->base = CFI_DX;
1003 break;
1004 default:
1005 WARN_FUNC("unsupported unwind_hint sp base reg %d",
1006 insn->sec, insn->offset, hint->sp_reg);
1007 return -1;
1008 }
1009
1010 cfa->offset = hint->sp_offset;
1011 insn->state.type = hint->type;
1012 }
1013
1014 return 0;
1015}
1016
877static int decode_sections(struct objtool_file *file) 1017static int decode_sections(struct objtool_file *file)
878{ 1018{
879 int ret; 1019 int ret;
@@ -904,6 +1044,10 @@ static int decode_sections(struct objtool_file *file)
904 if (ret) 1044 if (ret)
905 return ret; 1045 return ret;
906 1046
1047 ret = read_unwind_hints(file);
1048 if (ret)
1049 return ret;
1050
907 return 0; 1051 return 0;
908} 1052}
909 1053
@@ -947,11 +1091,34 @@ static bool has_valid_stack_frame(struct insn_state *state)
947 return false; 1091 return false;
948} 1092}
949 1093
1094static int update_insn_state_regs(struct instruction *insn, struct insn_state *state)
1095{
1096 struct cfi_reg *cfa = &state->cfa;
1097 struct stack_op *op = &insn->stack_op;
1098
1099 if (cfa->base != CFI_SP)
1100 return 0;
1101
1102 /* push */
1103 if (op->dest.type == OP_DEST_PUSH)
1104 cfa->offset += 8;
1105
1106 /* pop */
1107 if (op->src.type == OP_SRC_POP)
1108 cfa->offset -= 8;
1109
1110 /* add immediate to sp */
1111 if (op->dest.type == OP_DEST_REG && op->src.type == OP_SRC_ADD &&
1112 op->dest.reg == CFI_SP && op->src.reg == CFI_SP)
1113 cfa->offset -= op->src.offset;
1114
1115 return 0;
1116}
1117
950static void save_reg(struct insn_state *state, unsigned char reg, int base, 1118static void save_reg(struct insn_state *state, unsigned char reg, int base,
951 int offset) 1119 int offset)
952{ 1120{
953 if ((arch_callee_saved_reg(reg) || 1121 if (arch_callee_saved_reg(reg) &&
954 (state->drap && reg == state->drap_reg)) &&
955 state->regs[reg].base == CFI_UNDEFINED) { 1122 state->regs[reg].base == CFI_UNDEFINED) {
956 state->regs[reg].base = base; 1123 state->regs[reg].base = base;
957 state->regs[reg].offset = offset; 1124 state->regs[reg].offset = offset;
@@ -1032,30 +1199,71 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1032 return 0; 1199 return 0;
1033 } 1200 }
1034 1201
1202 if (state->type == ORC_TYPE_REGS || state->type == ORC_TYPE_REGS_IRET)
1203 return update_insn_state_regs(insn, state);
1204
1035 switch (op->dest.type) { 1205 switch (op->dest.type) {
1036 1206
1037 case OP_DEST_REG: 1207 case OP_DEST_REG:
1038 switch (op->src.type) { 1208 switch (op->src.type) {
1039 1209
1040 case OP_SRC_REG: 1210 case OP_SRC_REG:
1041 if (cfa->base == op->src.reg && cfa->base == CFI_SP && 1211 if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP &&
1042 op->dest.reg == CFI_BP && regs[CFI_BP].base == CFI_CFA && 1212 cfa->base == CFI_SP &&
1213 regs[CFI_BP].base == CFI_CFA &&
1043 regs[CFI_BP].offset == -cfa->offset) { 1214 regs[CFI_BP].offset == -cfa->offset) {
1044 1215
1045 /* mov %rsp, %rbp */ 1216 /* mov %rsp, %rbp */
1046 cfa->base = op->dest.reg; 1217 cfa->base = op->dest.reg;
1047 state->bp_scratch = false; 1218 state->bp_scratch = false;
1048 } else if (state->drap) { 1219 }
1220
1221 else if (op->src.reg == CFI_SP &&
1222 op->dest.reg == CFI_BP && state->drap) {
1049 1223
1050 /* drap: mov %rsp, %rbp */ 1224 /* drap: mov %rsp, %rbp */
1051 regs[CFI_BP].base = CFI_BP; 1225 regs[CFI_BP].base = CFI_BP;
1052 regs[CFI_BP].offset = -state->stack_size; 1226 regs[CFI_BP].offset = -state->stack_size;
1053 state->bp_scratch = false; 1227 state->bp_scratch = false;
1054 } else if (!nofp) { 1228 }
1055 1229
1056 WARN_FUNC("unknown stack-related register move", 1230 else if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
1057 insn->sec, insn->offset); 1231
1058 return -1; 1232 /*
1233 * mov %rsp, %reg
1234 *
1235 * This is needed for the rare case where GCC
1236 * does:
1237 *
1238 * mov %rsp, %rax
1239 * ...
1240 * mov %rax, %rsp
1241 */
1242 state->vals[op->dest.reg].base = CFI_CFA;
1243 state->vals[op->dest.reg].offset = -state->stack_size;
1244 }
1245
1246 else if (op->dest.reg == cfa->base) {
1247
1248 /* mov %reg, %rsp */
1249 if (cfa->base == CFI_SP &&
1250 state->vals[op->src.reg].base == CFI_CFA) {
1251
1252 /*
1253 * This is needed for the rare case
1254 * where GCC does something dumb like:
1255 *
1256 * lea 0x8(%rsp), %rcx
1257 * ...
1258 * mov %rcx, %rsp
1259 */
1260 cfa->offset = -state->vals[op->src.reg].offset;
1261 state->stack_size = cfa->offset;
1262
1263 } else {
1264 cfa->base = CFI_UNDEFINED;
1265 cfa->offset = 0;
1266 }
1059 } 1267 }
1060 1268
1061 break; 1269 break;
@@ -1077,11 +1285,25 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1077 break; 1285 break;
1078 } 1286 }
1079 1287
1080 if (op->dest.reg != CFI_BP && op->src.reg == CFI_SP && 1288 if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
1081 cfa->base == CFI_SP) {
1082 1289
1083 /* drap: lea disp(%rsp), %drap */ 1290 /* drap: lea disp(%rsp), %drap */
1084 state->drap_reg = op->dest.reg; 1291 state->drap_reg = op->dest.reg;
1292
1293 /*
1294 * lea disp(%rsp), %reg
1295 *
1296 * This is needed for the rare case where GCC
1297 * does something dumb like:
1298 *
1299 * lea 0x8(%rsp), %rcx
1300 * ...
1301 * mov %rcx, %rsp
1302 */
1303 state->vals[op->dest.reg].base = CFI_CFA;
1304 state->vals[op->dest.reg].offset = \
1305 -state->stack_size + op->src.offset;
1306
1085 break; 1307 break;
1086 } 1308 }
1087 1309
@@ -1118,7 +1340,6 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1118 cfa->base = state->drap_reg; 1340 cfa->base = state->drap_reg;
1119 cfa->offset = state->stack_size = 0; 1341 cfa->offset = state->stack_size = 0;
1120 state->drap = true; 1342 state->drap = true;
1121
1122 } 1343 }
1123 1344
1124 /* 1345 /*
@@ -1136,17 +1357,19 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1136 cfa->base = CFI_SP; 1357 cfa->base = CFI_SP;
1137 } 1358 }
1138 1359
1139 if (regs[op->dest.reg].offset == -state->stack_size) { 1360 if (state->drap && cfa->base == CFI_BP_INDIRECT &&
1361 op->dest.type == OP_DEST_REG &&
1362 op->dest.reg == state->drap_reg &&
1363 state->drap_offset == -state->stack_size) {
1140 1364
1141 if (state->drap && cfa->base == CFI_BP_INDIRECT && 1365 /* drap: pop %drap */
1142 op->dest.type == OP_DEST_REG && 1366 cfa->base = state->drap_reg;
1143 op->dest.reg == state->drap_reg) { 1367 cfa->offset = 0;
1368 state->drap_offset = -1;
1144 1369
1145 /* drap: pop %drap */ 1370 } else if (regs[op->dest.reg].offset == -state->stack_size) {
1146 cfa->base = state->drap_reg;
1147 cfa->offset = 0;
1148 }
1149 1371
1372 /* pop %reg */
1150 restore_reg(state, op->dest.reg); 1373 restore_reg(state, op->dest.reg);
1151 } 1374 }
1152 1375
@@ -1158,14 +1381,18 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1158 1381
1159 case OP_SRC_REG_INDIRECT: 1382 case OP_SRC_REG_INDIRECT:
1160 if (state->drap && op->src.reg == CFI_BP && 1383 if (state->drap && op->src.reg == CFI_BP &&
1384 op->src.offset == state->drap_offset) {
1385
1386 /* drap: mov disp(%rbp), %drap */
1387 cfa->base = state->drap_reg;
1388 cfa->offset = 0;
1389 state->drap_offset = -1;
1390 }
1391
1392 if (state->drap && op->src.reg == CFI_BP &&
1161 op->src.offset == regs[op->dest.reg].offset) { 1393 op->src.offset == regs[op->dest.reg].offset) {
1162 1394
1163 /* drap: mov disp(%rbp), %reg */ 1395 /* drap: mov disp(%rbp), %reg */
1164 if (op->dest.reg == state->drap_reg) {
1165 cfa->base = state->drap_reg;
1166 cfa->offset = 0;
1167 }
1168
1169 restore_reg(state, op->dest.reg); 1396 restore_reg(state, op->dest.reg);
1170 1397
1171 } else if (op->src.reg == cfa->base && 1398 } else if (op->src.reg == cfa->base &&
@@ -1201,8 +1428,8 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1201 cfa->base = CFI_BP_INDIRECT; 1428 cfa->base = CFI_BP_INDIRECT;
1202 cfa->offset = -state->stack_size; 1429 cfa->offset = -state->stack_size;
1203 1430
1204 /* save drap so we know when to undefine it */ 1431 /* save drap so we know when to restore it */
1205 save_reg(state, op->src.reg, CFI_CFA, -state->stack_size); 1432 state->drap_offset = -state->stack_size;
1206 1433
1207 } else if (op->src.reg == CFI_BP && cfa->base == state->drap_reg) { 1434 } else if (op->src.reg == CFI_BP && cfa->base == state->drap_reg) {
1208 1435
@@ -1222,7 +1449,7 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1222 } 1449 }
1223 1450
1224 /* detect when asm code uses rbp as a scratch register */ 1451 /* detect when asm code uses rbp as a scratch register */
1225 if (!nofp && insn->func && op->src.reg == CFI_BP && 1452 if (!no_fp && insn->func && op->src.reg == CFI_BP &&
1226 cfa->base != CFI_BP) 1453 cfa->base != CFI_BP)
1227 state->bp_scratch = true; 1454 state->bp_scratch = true;
1228 break; 1455 break;
@@ -1236,8 +1463,8 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1236 cfa->base = CFI_BP_INDIRECT; 1463 cfa->base = CFI_BP_INDIRECT;
1237 cfa->offset = op->dest.offset; 1464 cfa->offset = op->dest.offset;
1238 1465
1239 /* save drap so we know when to undefine it */ 1466 /* save drap offset so we know when to restore it */
1240 save_reg(state, op->src.reg, CFI_CFA, op->dest.offset); 1467 state->drap_offset = op->dest.offset;
1241 } 1468 }
1242 1469
1243 else if (regs[op->src.reg].base == CFI_UNDEFINED) { 1470 else if (regs[op->src.reg].base == CFI_UNDEFINED) {
@@ -1323,12 +1550,17 @@ static bool insn_state_match(struct instruction *insn, struct insn_state *state)
1323 break; 1550 break;
1324 } 1551 }
1325 1552
1553 } else if (state1->type != state2->type) {
1554 WARN_FUNC("stack state mismatch: type1=%d type2=%d",
1555 insn->sec, insn->offset, state1->type, state2->type);
1556
1326 } else if (state1->drap != state2->drap || 1557 } else if (state1->drap != state2->drap ||
1327 (state1->drap && state1->drap_reg != state2->drap_reg)) { 1558 (state1->drap && state1->drap_reg != state2->drap_reg) ||
1328 WARN_FUNC("stack state mismatch: drap1=%d(%d) drap2=%d(%d)", 1559 (state1->drap && state1->drap_offset != state2->drap_offset)) {
1560 WARN_FUNC("stack state mismatch: drap1=%d(%d,%d) drap2=%d(%d,%d)",
1329 insn->sec, insn->offset, 1561 insn->sec, insn->offset,
1330 state1->drap, state1->drap_reg, 1562 state1->drap, state1->drap_reg, state1->drap_offset,
1331 state2->drap, state2->drap_reg); 1563 state2->drap, state2->drap_reg, state2->drap_offset);
1332 1564
1333 } else 1565 } else
1334 return true; 1566 return true;
@@ -1346,7 +1578,7 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1346 struct insn_state state) 1578 struct insn_state state)
1347{ 1579{
1348 struct alternative *alt; 1580 struct alternative *alt;
1349 struct instruction *insn; 1581 struct instruction *insn, *next_insn;
1350 struct section *sec; 1582 struct section *sec;
1351 struct symbol *func = NULL; 1583 struct symbol *func = NULL;
1352 int ret; 1584 int ret;
@@ -1357,34 +1589,77 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1357 if (insn->alt_group && list_empty(&insn->alts)) { 1589 if (insn->alt_group && list_empty(&insn->alts)) {
1358 WARN_FUNC("don't know how to handle branch to middle of alternative instruction group", 1590 WARN_FUNC("don't know how to handle branch to middle of alternative instruction group",
1359 sec, insn->offset); 1591 sec, insn->offset);
1360 return -1; 1592 return 1;
1361 } 1593 }
1362 1594
1363 while (1) { 1595 while (1) {
1364 if (file->c_file && insn->func) { 1596 next_insn = next_insn_same_sec(file, insn);
1365 if (func && func != insn->func) { 1597
1366 WARN("%s() falls through to next function %s()", 1598
1367 func->name, insn->func->name); 1599 if (file->c_file && func && insn->func && func != insn->func) {
1368 return 1; 1600 WARN("%s() falls through to next function %s()",
1369 } 1601 func->name, insn->func->name);
1602 return 1;
1370 } 1603 }
1371 1604
1372 func = insn->func; 1605 if (insn->func)
1606 func = insn->func;
1373 1607
1374 if (func && insn->ignore) { 1608 if (func && insn->ignore) {
1375 WARN_FUNC("BUG: why am I validating an ignored function?", 1609 WARN_FUNC("BUG: why am I validating an ignored function?",
1376 sec, insn->offset); 1610 sec, insn->offset);
1377 return -1; 1611 return 1;
1378 } 1612 }
1379 1613
1380 if (insn->visited) { 1614 if (insn->visited) {
1381 if (!!insn_state_match(insn, &state)) 1615 if (!insn->hint && !insn_state_match(insn, &state))
1382 return 1; 1616 return 1;
1383 1617
1384 return 0; 1618 return 0;
1385 } 1619 }
1386 1620
1387 insn->state = state; 1621 if (insn->hint) {
1622 if (insn->restore) {
1623 struct instruction *save_insn, *i;
1624
1625 i = insn;
1626 save_insn = NULL;
1627 func_for_each_insn_continue_reverse(file, func, i) {
1628 if (i->save) {
1629 save_insn = i;
1630 break;
1631 }
1632 }
1633
1634 if (!save_insn) {
1635 WARN_FUNC("no corresponding CFI save for CFI restore",
1636 sec, insn->offset);
1637 return 1;
1638 }
1639
1640 if (!save_insn->visited) {
1641 /*
1642 * Oops, no state to copy yet.
1643 * Hopefully we can reach this
1644 * instruction from another branch
1645 * after the save insn has been
1646 * visited.
1647 */
1648 if (insn == first)
1649 return 0;
1650
1651 WARN_FUNC("objtool isn't smart enough to handle this CFI save/restore combo",
1652 sec, insn->offset);
1653 return 1;
1654 }
1655
1656 insn->state = save_insn->state;
1657 }
1658
1659 state = insn->state;
1660
1661 } else
1662 insn->state = state;
1388 1663
1389 insn->visited = true; 1664 insn->visited = true;
1390 1665
@@ -1423,7 +1698,7 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1423 1698
1424 /* fallthrough */ 1699 /* fallthrough */
1425 case INSN_CALL_DYNAMIC: 1700 case INSN_CALL_DYNAMIC:
1426 if (!nofp && func && !has_valid_stack_frame(&state)) { 1701 if (!no_fp && func && !has_valid_stack_frame(&state)) {
1427 WARN_FUNC("call without frame pointer save/setup", 1702 WARN_FUNC("call without frame pointer save/setup",
1428 sec, insn->offset); 1703 sec, insn->offset);
1429 return 1; 1704 return 1;
@@ -1461,9 +1736,17 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1461 1736
1462 return 0; 1737 return 0;
1463 1738
1739 case INSN_CONTEXT_SWITCH:
1740 if (func && (!next_insn || !next_insn->hint)) {
1741 WARN_FUNC("unsupported instruction in callable function",
1742 sec, insn->offset);
1743 return 1;
1744 }
1745 return 0;
1746
1464 case INSN_STACK: 1747 case INSN_STACK:
1465 if (update_insn_state(insn, &state)) 1748 if (update_insn_state(insn, &state))
1466 return -1; 1749 return 1;
1467 1750
1468 break; 1751 break;
1469 1752
@@ -1474,16 +1757,40 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1474 if (insn->dead_end) 1757 if (insn->dead_end)
1475 return 0; 1758 return 0;
1476 1759
1477 insn = next_insn_same_sec(file, insn); 1760 if (!next_insn) {
1478 if (!insn) { 1761 if (state.cfa.base == CFI_UNDEFINED)
1762 return 0;
1479 WARN("%s: unexpected end of section", sec->name); 1763 WARN("%s: unexpected end of section", sec->name);
1480 return 1; 1764 return 1;
1481 } 1765 }
1766
1767 insn = next_insn;
1482 } 1768 }
1483 1769
1484 return 0; 1770 return 0;
1485} 1771}
1486 1772
1773static int validate_unwind_hints(struct objtool_file *file)
1774{
1775 struct instruction *insn;
1776 int ret, warnings = 0;
1777 struct insn_state state;
1778
1779 if (!file->hints)
1780 return 0;
1781
1782 clear_insn_state(&state);
1783
1784 for_each_insn(file, insn) {
1785 if (insn->hint && !insn->visited) {
1786 ret = validate_branch(file, insn, state);
1787 warnings += ret;
1788 }
1789 }
1790
1791 return warnings;
1792}
1793
1487static bool is_kasan_insn(struct instruction *insn) 1794static bool is_kasan_insn(struct instruction *insn)
1488{ 1795{
1489 return (insn->type == INSN_CALL && 1796 return (insn->type == INSN_CALL &&
@@ -1507,8 +1814,13 @@ static bool ignore_unreachable_insn(struct instruction *insn)
1507 /* 1814 /*
1508 * Ignore any unused exceptions. This can happen when a whitelisted 1815 * Ignore any unused exceptions. This can happen when a whitelisted
1509 * function has an exception table entry. 1816 * function has an exception table entry.
1817 *
1818 * Also ignore alternative replacement instructions. This can happen
1819 * when a whitelisted function uses one of the ALTERNATIVE macros.
1510 */ 1820 */
1511 if (!strcmp(insn->sec->name, ".fixup")) 1821 if (!strcmp(insn->sec->name, ".fixup") ||
1822 !strcmp(insn->sec->name, ".altinstr_replacement") ||
1823 !strcmp(insn->sec->name, ".altinstr_aux"))
1512 return true; 1824 return true;
1513 1825
1514 /* 1826 /*
@@ -1580,15 +1892,6 @@ static int validate_reachable_instructions(struct objtool_file *file)
1580 if (insn->visited || ignore_unreachable_insn(insn)) 1892 if (insn->visited || ignore_unreachable_insn(insn))
1581 continue; 1893 continue;
1582 1894
1583 /*
1584 * gcov produces a lot of unreachable instructions. If we get
1585 * an unreachable warning and the file has gcov enabled, just
1586 * ignore it, and all other such warnings for the file. Do
1587 * this here because this is an expensive function.
1588 */
1589 if (gcov_enabled(file))
1590 return 0;
1591
1592 WARN_FUNC("unreachable instruction", insn->sec, insn->offset); 1895 WARN_FUNC("unreachable instruction", insn->sec, insn->offset);
1593 return 1; 1896 return 1;
1594 } 1897 }
@@ -1613,15 +1916,15 @@ static void cleanup(struct objtool_file *file)
1613 elf_close(file->elf); 1916 elf_close(file->elf);
1614} 1917}
1615 1918
1616int check(const char *_objname, bool _nofp) 1919int check(const char *_objname, bool _no_fp, bool no_unreachable, bool orc)
1617{ 1920{
1618 struct objtool_file file; 1921 struct objtool_file file;
1619 int ret, warnings = 0; 1922 int ret, warnings = 0;
1620 1923
1621 objname = _objname; 1924 objname = _objname;
1622 nofp = _nofp; 1925 no_fp = _no_fp;
1623 1926
1624 file.elf = elf_open(objname); 1927 file.elf = elf_open(objname, orc ? O_RDWR : O_RDONLY);
1625 if (!file.elf) 1928 if (!file.elf)
1626 return 1; 1929 return 1;
1627 1930
@@ -1629,8 +1932,9 @@ int check(const char *_objname, bool _nofp)
1629 hash_init(file.insn_hash); 1932 hash_init(file.insn_hash);
1630 file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard"); 1933 file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard");
1631 file.rodata = find_section_by_name(file.elf, ".rodata"); 1934 file.rodata = find_section_by_name(file.elf, ".rodata");
1632 file.ignore_unreachables = false;
1633 file.c_file = find_section_by_name(file.elf, ".comment"); 1935 file.c_file = find_section_by_name(file.elf, ".comment");
1936 file.ignore_unreachables = no_unreachable;
1937 file.hints = false;
1634 1938
1635 arch_initial_func_cfi_state(&initial_func_cfi); 1939 arch_initial_func_cfi_state(&initial_func_cfi);
1636 1940
@@ -1647,6 +1951,11 @@ int check(const char *_objname, bool _nofp)
1647 goto out; 1951 goto out;
1648 warnings += ret; 1952 warnings += ret;
1649 1953
1954 ret = validate_unwind_hints(&file);
1955 if (ret < 0)
1956 goto out;
1957 warnings += ret;
1958
1650 if (!warnings) { 1959 if (!warnings) {
1651 ret = validate_reachable_instructions(&file); 1960 ret = validate_reachable_instructions(&file);
1652 if (ret < 0) 1961 if (ret < 0)
@@ -1654,6 +1963,20 @@ int check(const char *_objname, bool _nofp)
1654 warnings += ret; 1963 warnings += ret;
1655 } 1964 }
1656 1965
1966 if (orc) {
1967 ret = create_orc(&file);
1968 if (ret < 0)
1969 goto out;
1970
1971 ret = create_orc_sections(&file);
1972 if (ret < 0)
1973 goto out;
1974
1975 ret = elf_write(file.elf);
1976 if (ret < 0)
1977 goto out;
1978 }
1979
1657out: 1980out:
1658 cleanup(&file); 1981 cleanup(&file);
1659 1982
diff --git a/tools/objtool/check.h b/tools/objtool/check.h
index da85f5b00ec6..47d9ea70a83d 100644
--- a/tools/objtool/check.h
+++ b/tools/objtool/check.h
@@ -22,15 +22,18 @@
22#include "elf.h" 22#include "elf.h"
23#include "cfi.h" 23#include "cfi.h"
24#include "arch.h" 24#include "arch.h"
25#include "orc.h"
25#include <linux/hashtable.h> 26#include <linux/hashtable.h>
26 27
27struct insn_state { 28struct insn_state {
28 struct cfi_reg cfa; 29 struct cfi_reg cfa;
29 struct cfi_reg regs[CFI_NUM_REGS]; 30 struct cfi_reg regs[CFI_NUM_REGS];
30 int stack_size; 31 int stack_size;
32 unsigned char type;
31 bool bp_scratch; 33 bool bp_scratch;
32 bool drap; 34 bool drap;
33 int drap_reg; 35 int drap_reg, drap_offset;
36 struct cfi_reg vals[CFI_NUM_REGS];
34}; 37};
35 38
36struct instruction { 39struct instruction {
@@ -41,13 +44,14 @@ struct instruction {
41 unsigned int len; 44 unsigned int len;
42 unsigned char type; 45 unsigned char type;
43 unsigned long immediate; 46 unsigned long immediate;
44 bool alt_group, visited, dead_end, ignore; 47 bool alt_group, visited, dead_end, ignore, hint, save, restore;
45 struct symbol *call_dest; 48 struct symbol *call_dest;
46 struct instruction *jump_dest; 49 struct instruction *jump_dest;
47 struct list_head alts; 50 struct list_head alts;
48 struct symbol *func; 51 struct symbol *func;
49 struct stack_op stack_op; 52 struct stack_op stack_op;
50 struct insn_state state; 53 struct insn_state state;
54 struct orc_entry orc;
51}; 55};
52 56
53struct objtool_file { 57struct objtool_file {
@@ -55,12 +59,22 @@ struct objtool_file {
55 struct list_head insn_list; 59 struct list_head insn_list;
56 DECLARE_HASHTABLE(insn_hash, 16); 60 DECLARE_HASHTABLE(insn_hash, 16);
57 struct section *rodata, *whitelist; 61 struct section *rodata, *whitelist;
58 bool ignore_unreachables, c_file; 62 bool ignore_unreachables, c_file, hints;
59}; 63};
60 64
61int check(const char *objname, bool nofp); 65int check(const char *objname, bool no_fp, bool no_unreachable, bool orc);
66
67struct instruction *find_insn(struct objtool_file *file,
68 struct section *sec, unsigned long offset);
62 69
63#define for_each_insn(file, insn) \ 70#define for_each_insn(file, insn) \
64 list_for_each_entry(insn, &file->insn_list, list) 71 list_for_each_entry(insn, &file->insn_list, list)
65 72
73#define sec_for_each_insn(file, sec, insn) \
74 for (insn = find_insn(file, sec, 0); \
75 insn && &insn->list != &file->insn_list && \
76 insn->sec == sec; \
77 insn = list_next_entry(insn, list))
78
79
66#endif /* _CHECK_H */ 80#endif /* _CHECK_H */
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 1a7e8aa2af58..24460155c82c 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -30,16 +30,6 @@
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
40#define WARN_ELF(format, ...) \
41 WARN(format ": %s", ##__VA_ARGS__, elf_errmsg(-1))
42
43struct section *find_section_by_name(struct elf *elf, const char *name) 33struct section *find_section_by_name(struct elf *elf, const char *name)
44{ 34{
45 struct section *sec; 35 struct section *sec;
@@ -185,19 +175,20 @@ static int read_sections(struct elf *elf)
185 return -1; 175 return -1;
186 } 176 }
187 177
188 sec->data = elf_getdata(s, NULL); 178 if (sec->sh.sh_size != 0) {
189 if (!sec->data) { 179 sec->data = elf_getdata(s, NULL);
190 WARN_ELF("elf_getdata"); 180 if (!sec->data) {
191 return -1; 181 WARN_ELF("elf_getdata");
192 } 182 return -1;
193 183 }
194 if (sec->data->d_off != 0 || 184 if (sec->data->d_off != 0 ||
195 sec->data->d_size != sec->sh.sh_size) { 185 sec->data->d_size != sec->sh.sh_size) {
196 WARN("unexpected data attributes for %s", sec->name); 186 WARN("unexpected data attributes for %s",
197 return -1; 187 sec->name);
188 return -1;
189 }
198 } 190 }
199 191 sec->len = sec->sh.sh_size;
200 sec->len = sec->data->d_size;
201 } 192 }
202 193
203 /* sanity check, one more call to elf_nextscn() should return NULL */ 194 /* sanity check, one more call to elf_nextscn() should return NULL */
@@ -349,9 +340,10 @@ static int read_relas(struct elf *elf)
349 return 0; 340 return 0;
350} 341}
351 342
352struct elf *elf_open(const char *name) 343struct elf *elf_open(const char *name, int flags)
353{ 344{
354 struct elf *elf; 345 struct elf *elf;
346 Elf_Cmd cmd;
355 347
356 elf_version(EV_CURRENT); 348 elf_version(EV_CURRENT);
357 349
@@ -364,13 +356,20 @@ struct elf *elf_open(const char *name)
364 356
365 INIT_LIST_HEAD(&elf->sections); 357 INIT_LIST_HEAD(&elf->sections);
366 358
367 elf->fd = open(name, O_RDONLY); 359 elf->fd = open(name, flags);
368 if (elf->fd == -1) { 360 if (elf->fd == -1) {
369 perror("open"); 361 perror("open");
370 goto err; 362 goto err;
371 } 363 }
372 364
373 elf->elf = elf_begin(elf->fd, ELF_C_READ_MMAP, NULL); 365 if ((flags & O_ACCMODE) == O_RDONLY)
366 cmd = ELF_C_READ_MMAP;
367 else if ((flags & O_ACCMODE) == O_RDWR)
368 cmd = ELF_C_RDWR;
369 else /* O_WRONLY */
370 cmd = ELF_C_WRITE;
371
372 elf->elf = elf_begin(elf->fd, cmd, NULL);
374 if (!elf->elf) { 373 if (!elf->elf) {
375 WARN_ELF("elf_begin"); 374 WARN_ELF("elf_begin");
376 goto err; 375 goto err;
@@ -397,6 +396,200 @@ err:
397 return NULL; 396 return NULL;
398} 397}
399 398
399struct section *elf_create_section(struct elf *elf, const char *name,
400 size_t entsize, int nr)
401{
402 struct section *sec, *shstrtab;
403 size_t size = entsize * nr;
404 struct Elf_Scn *s;
405 Elf_Data *data;
406
407 sec = malloc(sizeof(*sec));
408 if (!sec) {
409 perror("malloc");
410 return NULL;
411 }
412 memset(sec, 0, sizeof(*sec));
413
414 INIT_LIST_HEAD(&sec->symbol_list);
415 INIT_LIST_HEAD(&sec->rela_list);
416 hash_init(sec->rela_hash);
417 hash_init(sec->symbol_hash);
418
419 list_add_tail(&sec->list, &elf->sections);
420
421 s = elf_newscn(elf->elf);
422 if (!s) {
423 WARN_ELF("elf_newscn");
424 return NULL;
425 }
426
427 sec->name = strdup(name);
428 if (!sec->name) {
429 perror("strdup");
430 return NULL;
431 }
432
433 sec->idx = elf_ndxscn(s);
434 sec->len = size;
435 sec->changed = true;
436
437 sec->data = elf_newdata(s);
438 if (!sec->data) {
439 WARN_ELF("elf_newdata");
440 return NULL;
441 }
442
443 sec->data->d_size = size;
444 sec->data->d_align = 1;
445
446 if (size) {
447 sec->data->d_buf = malloc(size);
448 if (!sec->data->d_buf) {
449 perror("malloc");
450 return NULL;
451 }
452 memset(sec->data->d_buf, 0, size);
453 }
454
455 if (!gelf_getshdr(s, &sec->sh)) {
456 WARN_ELF("gelf_getshdr");
457 return NULL;
458 }
459
460 sec->sh.sh_size = size;
461 sec->sh.sh_entsize = entsize;
462 sec->sh.sh_type = SHT_PROGBITS;
463 sec->sh.sh_addralign = 1;
464 sec->sh.sh_flags = SHF_ALLOC;
465
466
467 /* Add section name to .shstrtab */
468 shstrtab = find_section_by_name(elf, ".shstrtab");
469 if (!shstrtab) {
470 WARN("can't find .shstrtab section");
471 return NULL;
472 }
473
474 s = elf_getscn(elf->elf, shstrtab->idx);
475 if (!s) {
476 WARN_ELF("elf_getscn");
477 return NULL;
478 }
479
480 data = elf_newdata(s);
481 if (!data) {
482 WARN_ELF("elf_newdata");
483 return NULL;
484 }
485
486 data->d_buf = sec->name;
487 data->d_size = strlen(name) + 1;
488 data->d_align = 1;
489
490 sec->sh.sh_name = shstrtab->len;
491
492 shstrtab->len += strlen(name) + 1;
493 shstrtab->changed = true;
494
495 return sec;
496}
497
498struct section *elf_create_rela_section(struct elf *elf, struct section *base)
499{
500 char *relaname;
501 struct section *sec;
502
503 relaname = malloc(strlen(base->name) + strlen(".rela") + 1);
504 if (!relaname) {
505 perror("malloc");
506 return NULL;
507 }
508 strcpy(relaname, ".rela");
509 strcat(relaname, base->name);
510
511 sec = elf_create_section(elf, relaname, sizeof(GElf_Rela), 0);
512 free(relaname);
513 if (!sec)
514 return NULL;
515
516 base->rela = sec;
517 sec->base = base;
518
519 sec->sh.sh_type = SHT_RELA;
520 sec->sh.sh_addralign = 8;
521 sec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
522 sec->sh.sh_info = base->idx;
523 sec->sh.sh_flags = SHF_INFO_LINK;
524
525 return sec;
526}
527
528int elf_rebuild_rela_section(struct section *sec)
529{
530 struct rela *rela;
531 int nr, idx = 0, size;
532 GElf_Rela *relas;
533
534 nr = 0;
535 list_for_each_entry(rela, &sec->rela_list, list)
536 nr++;
537
538 size = nr * sizeof(*relas);
539 relas = malloc(size);
540 if (!relas) {
541 perror("malloc");
542 return -1;
543 }
544
545 sec->data->d_buf = relas;
546 sec->data->d_size = size;
547
548 sec->sh.sh_size = size;
549
550 idx = 0;
551 list_for_each_entry(rela, &sec->rela_list, list) {
552 relas[idx].r_offset = rela->offset;
553 relas[idx].r_addend = rela->addend;
554 relas[idx].r_info = GELF_R_INFO(rela->sym->idx, rela->type);
555 idx++;
556 }
557
558 return 0;
559}
560
561int elf_write(struct elf *elf)
562{
563 struct section *sec;
564 Elf_Scn *s;
565
566 /* Update section headers for changed sections: */
567 list_for_each_entry(sec, &elf->sections, list) {
568 if (sec->changed) {
569 s = elf_getscn(elf->elf, sec->idx);
570 if (!s) {
571 WARN_ELF("elf_getscn");
572 return -1;
573 }
574 if (!gelf_update_shdr(s, &sec->sh)) {
575 WARN_ELF("gelf_update_shdr");
576 return -1;
577 }
578 }
579 }
580
581 /* Make sure the new section header entries get updated properly. */
582 elf_flagelf(elf->elf, ELF_C_SET, ELF_F_DIRTY);
583
584 /* Write all changes to the file. */
585 if (elf_update(elf->elf, ELF_C_WRITE) < 0) {
586 WARN_ELF("elf_update");
587 return -1;
588 }
589
590 return 0;
591}
592
400void elf_close(struct elf *elf) 593void elf_close(struct elf *elf)
401{ 594{
402 struct section *sec, *tmpsec; 595 struct section *sec, *tmpsec;
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index 343968b778cb..d86e2ff14466 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -28,6 +28,13 @@
28# define elf_getshdrstrndx elf_getshstrndx 28# define elf_getshdrstrndx elf_getshstrndx
29#endif 29#endif
30 30
31/*
32 * Fallback for systems without this "read, mmaping if possible" cmd.
33 */
34#ifndef ELF_C_READ_MMAP
35#define ELF_C_READ_MMAP ELF_C_READ
36#endif
37
31struct section { 38struct section {
32 struct list_head list; 39 struct list_head list;
33 GElf_Shdr sh; 40 GElf_Shdr sh;
@@ -41,6 +48,7 @@ struct section {
41 char *name; 48 char *name;
42 int idx; 49 int idx;
43 unsigned int len; 50 unsigned int len;
51 bool changed, text;
44}; 52};
45 53
46struct symbol { 54struct symbol {
@@ -75,7 +83,7 @@ struct elf {
75}; 83};
76 84
77 85
78struct elf *elf_open(const char *name); 86struct elf *elf_open(const char *name, int flags);
79struct section *find_section_by_name(struct elf *elf, const char *name); 87struct section *find_section_by_name(struct elf *elf, const char *name);
80struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); 88struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
81struct symbol *find_symbol_containing(struct section *sec, unsigned long offset); 89struct symbol *find_symbol_containing(struct section *sec, unsigned long offset);
@@ -83,6 +91,11 @@ struct rela *find_rela_by_dest(struct section *sec, unsigned long offset);
83struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset, 91struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset,
84 unsigned int len); 92 unsigned int len);
85struct symbol *find_containing_func(struct section *sec, unsigned long offset); 93struct symbol *find_containing_func(struct section *sec, unsigned long offset);
94struct section *elf_create_section(struct elf *elf, const char *name, size_t
95 entsize, int nr);
96struct section *elf_create_rela_section(struct elf *elf, struct section *base);
97int elf_rebuild_rela_section(struct section *sec);
98int elf_write(struct elf *elf);
86void elf_close(struct elf *elf); 99void elf_close(struct elf *elf);
87 100
88#define for_each_sec(file, sec) \ 101#define for_each_sec(file, sec) \
diff --git a/tools/objtool/objtool.c b/tools/objtool/objtool.c
index ecc5b1b5d15d..07f329919828 100644
--- a/tools/objtool/objtool.c
+++ b/tools/objtool/objtool.c
@@ -42,10 +42,11 @@ struct cmd_struct {
42}; 42};
43 43
44static const char objtool_usage_string[] = 44static const char objtool_usage_string[] =
45 "objtool [OPTIONS] COMMAND [ARGS]"; 45 "objtool COMMAND [ARGS]";
46 46
47static struct cmd_struct objtool_cmds[] = { 47static struct cmd_struct objtool_cmds[] = {
48 {"check", cmd_check, "Perform stack metadata validation on an object file" }, 48 {"check", cmd_check, "Perform stack metadata validation on an object file" },
49 {"orc", cmd_orc, "Generate in-place ORC unwind tables for an object file" },
49}; 50};
50 51
51bool help; 52bool help;
@@ -69,7 +70,7 @@ static void cmd_usage(void)
69 70
70 printf("\n"); 71 printf("\n");
71 72
72 exit(1); 73 exit(129);
73} 74}
74 75
75static void handle_options(int *argc, const char ***argv) 76static void handle_options(int *argc, const char ***argv)
@@ -85,9 +86,7 @@ static void handle_options(int *argc, const char ***argv)
85 break; 86 break;
86 } else { 87 } else {
87 fprintf(stderr, "Unknown option: %s\n", cmd); 88 fprintf(stderr, "Unknown option: %s\n", cmd);
88 fprintf(stderr, "\n Usage: %s\n", 89 cmd_usage();
89 objtool_usage_string);
90 exit(1);
91 } 90 }
92 91
93 (*argv)++; 92 (*argv)++;
diff --git a/tools/objtool/orc.h b/tools/objtool/orc.h
new file mode 100644
index 000000000000..b0e92a6d0903
--- /dev/null
+++ b/tools/objtool/orc.h
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
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 2
7 * of the License, or (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef _ORC_H
19#define _ORC_H
20
21#include <asm/orc_types.h>
22
23struct objtool_file;
24
25int create_orc(struct objtool_file *file);
26int create_orc_sections(struct objtool_file *file);
27
28int orc_dump(const char *objname);
29
30#endif /* _ORC_H */
diff --git a/tools/objtool/orc_dump.c b/tools/objtool/orc_dump.c
new file mode 100644
index 000000000000..36c5bf6a2675
--- /dev/null
+++ b/tools/objtool/orc_dump.c
@@ -0,0 +1,212 @@
1/*
2 * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
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 2
7 * of the License, or (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <unistd.h>
19#include "orc.h"
20#include "warn.h"
21
22static const char *reg_name(unsigned int reg)
23{
24 switch (reg) {
25 case ORC_REG_PREV_SP:
26 return "prevsp";
27 case ORC_REG_DX:
28 return "dx";
29 case ORC_REG_DI:
30 return "di";
31 case ORC_REG_BP:
32 return "bp";
33 case ORC_REG_SP:
34 return "sp";
35 case ORC_REG_R10:
36 return "r10";
37 case ORC_REG_R13:
38 return "r13";
39 case ORC_REG_BP_INDIRECT:
40 return "bp(ind)";
41 case ORC_REG_SP_INDIRECT:
42 return "sp(ind)";
43 default:
44 return "?";
45 }
46}
47
48static const char *orc_type_name(unsigned int type)
49{
50 switch (type) {
51 case ORC_TYPE_CALL:
52 return "call";
53 case ORC_TYPE_REGS:
54 return "regs";
55 case ORC_TYPE_REGS_IRET:
56 return "iret";
57 default:
58 return "?";
59 }
60}
61
62static void print_reg(unsigned int reg, int offset)
63{
64 if (reg == ORC_REG_BP_INDIRECT)
65 printf("(bp%+d)", offset);
66 else if (reg == ORC_REG_SP_INDIRECT)
67 printf("(sp%+d)", offset);
68 else if (reg == ORC_REG_UNDEFINED)
69 printf("(und)");
70 else
71 printf("%s%+d", reg_name(reg), offset);
72}
73
74int orc_dump(const char *_objname)
75{
76 int fd, nr_entries, i, *orc_ip = NULL, orc_size = 0;
77 struct orc_entry *orc = NULL;
78 char *name;
79 unsigned long nr_sections, orc_ip_addr = 0;
80 size_t shstrtab_idx;
81 Elf *elf;
82 Elf_Scn *scn;
83 GElf_Shdr sh;
84 GElf_Rela rela;
85 GElf_Sym sym;
86 Elf_Data *data, *symtab = NULL, *rela_orc_ip = NULL;
87
88
89 objname = _objname;
90
91 elf_version(EV_CURRENT);
92
93 fd = open(objname, O_RDONLY);
94 if (fd == -1) {
95 perror("open");
96 return -1;
97 }
98
99 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
100 if (!elf) {
101 WARN_ELF("elf_begin");
102 return -1;
103 }
104
105 if (elf_getshdrnum(elf, &nr_sections)) {
106 WARN_ELF("elf_getshdrnum");
107 return -1;
108 }
109
110 if (elf_getshdrstrndx(elf, &shstrtab_idx)) {
111 WARN_ELF("elf_getshdrstrndx");
112 return -1;
113 }
114
115 for (i = 0; i < nr_sections; i++) {
116 scn = elf_getscn(elf, i);
117 if (!scn) {
118 WARN_ELF("elf_getscn");
119 return -1;
120 }
121
122 if (!gelf_getshdr(scn, &sh)) {
123 WARN_ELF("gelf_getshdr");
124 return -1;
125 }
126
127 name = elf_strptr(elf, shstrtab_idx, sh.sh_name);
128 if (!name) {
129 WARN_ELF("elf_strptr");
130 return -1;
131 }
132
133 data = elf_getdata(scn, NULL);
134 if (!data) {
135 WARN_ELF("elf_getdata");
136 return -1;
137 }
138
139 if (!strcmp(name, ".symtab")) {
140 symtab = data;
141 } else if (!strcmp(name, ".orc_unwind")) {
142 orc = data->d_buf;
143 orc_size = sh.sh_size;
144 } else if (!strcmp(name, ".orc_unwind_ip")) {
145 orc_ip = data->d_buf;
146 orc_ip_addr = sh.sh_addr;
147 } else if (!strcmp(name, ".rela.orc_unwind_ip")) {
148 rela_orc_ip = data;
149 }
150 }
151
152 if (!symtab || !orc || !orc_ip)
153 return 0;
154
155 if (orc_size % sizeof(*orc) != 0) {
156 WARN("bad .orc_unwind section size");
157 return -1;
158 }
159
160 nr_entries = orc_size / sizeof(*orc);
161 for (i = 0; i < nr_entries; i++) {
162 if (rela_orc_ip) {
163 if (!gelf_getrela(rela_orc_ip, i, &rela)) {
164 WARN_ELF("gelf_getrela");
165 return -1;
166 }
167
168 if (!gelf_getsym(symtab, GELF_R_SYM(rela.r_info), &sym)) {
169 WARN_ELF("gelf_getsym");
170 return -1;
171 }
172
173 scn = elf_getscn(elf, sym.st_shndx);
174 if (!scn) {
175 WARN_ELF("elf_getscn");
176 return -1;
177 }
178
179 if (!gelf_getshdr(scn, &sh)) {
180 WARN_ELF("gelf_getshdr");
181 return -1;
182 }
183
184 name = elf_strptr(elf, shstrtab_idx, sh.sh_name);
185 if (!name || !*name) {
186 WARN_ELF("elf_strptr");
187 return -1;
188 }
189
190 printf("%s+%lx:", name, rela.r_addend);
191
192 } else {
193 printf("%lx:", orc_ip_addr + (i * sizeof(int)) + orc_ip[i]);
194 }
195
196
197 printf(" sp:");
198
199 print_reg(orc[i].sp_reg, orc[i].sp_offset);
200
201 printf(" bp:");
202
203 print_reg(orc[i].bp_reg, orc[i].bp_offset);
204
205 printf(" type:%s\n", orc_type_name(orc[i].type));
206 }
207
208 elf_end(elf);
209 close(fd);
210
211 return 0;
212}
diff --git a/tools/objtool/orc_gen.c b/tools/objtool/orc_gen.c
new file mode 100644
index 000000000000..e5ca31429c9b
--- /dev/null
+++ b/tools/objtool/orc_gen.c
@@ -0,0 +1,214 @@
1/*
2 * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
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 2
7 * of the License, or (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <stdlib.h>
19#include <string.h>
20
21#include "orc.h"
22#include "check.h"
23#include "warn.h"
24
25int create_orc(struct objtool_file *file)
26{
27 struct instruction *insn;
28
29 for_each_insn(file, insn) {
30 struct orc_entry *orc = &insn->orc;
31 struct cfi_reg *cfa = &insn->state.cfa;
32 struct cfi_reg *bp = &insn->state.regs[CFI_BP];
33
34 if (cfa->base == CFI_UNDEFINED) {
35 orc->sp_reg = ORC_REG_UNDEFINED;
36 continue;
37 }
38
39 switch (cfa->base) {
40 case CFI_SP:
41 orc->sp_reg = ORC_REG_SP;
42 break;
43 case CFI_SP_INDIRECT:
44 orc->sp_reg = ORC_REG_SP_INDIRECT;
45 break;
46 case CFI_BP:
47 orc->sp_reg = ORC_REG_BP;
48 break;
49 case CFI_BP_INDIRECT:
50 orc->sp_reg = ORC_REG_BP_INDIRECT;
51 break;
52 case CFI_R10:
53 orc->sp_reg = ORC_REG_R10;
54 break;
55 case CFI_R13:
56 orc->sp_reg = ORC_REG_R13;
57 break;
58 case CFI_DI:
59 orc->sp_reg = ORC_REG_DI;
60 break;
61 case CFI_DX:
62 orc->sp_reg = ORC_REG_DX;
63 break;
64 default:
65 WARN_FUNC("unknown CFA base reg %d",
66 insn->sec, insn->offset, cfa->base);
67 return -1;
68 }
69
70 switch(bp->base) {
71 case CFI_UNDEFINED:
72 orc->bp_reg = ORC_REG_UNDEFINED;
73 break;
74 case CFI_CFA:
75 orc->bp_reg = ORC_REG_PREV_SP;
76 break;
77 case CFI_BP:
78 orc->bp_reg = ORC_REG_BP;
79 break;
80 default:
81 WARN_FUNC("unknown BP base reg %d",
82 insn->sec, insn->offset, bp->base);
83 return -1;
84 }
85
86 orc->sp_offset = cfa->offset;
87 orc->bp_offset = bp->offset;
88 orc->type = insn->state.type;
89 }
90
91 return 0;
92}
93
94static int create_orc_entry(struct section *u_sec, struct section *ip_relasec,
95 unsigned int idx, struct section *insn_sec,
96 unsigned long insn_off, struct orc_entry *o)
97{
98 struct orc_entry *orc;
99 struct rela *rela;
100
101 /* populate ORC data */
102 orc = (struct orc_entry *)u_sec->data->d_buf + idx;
103 memcpy(orc, o, sizeof(*orc));
104
105 /* populate rela for ip */
106 rela = malloc(sizeof(*rela));
107 if (!rela) {
108 perror("malloc");
109 return -1;
110 }
111 memset(rela, 0, sizeof(*rela));
112
113 rela->sym = insn_sec->sym;
114 rela->addend = insn_off;
115 rela->type = R_X86_64_PC32;
116 rela->offset = idx * sizeof(int);
117
118 list_add_tail(&rela->list, &ip_relasec->rela_list);
119 hash_add(ip_relasec->rela_hash, &rela->hash, rela->offset);
120
121 return 0;
122}
123
124int create_orc_sections(struct objtool_file *file)
125{
126 struct instruction *insn, *prev_insn;
127 struct section *sec, *u_sec, *ip_relasec;
128 unsigned int idx;
129
130 struct orc_entry empty = {
131 .sp_reg = ORC_REG_UNDEFINED,
132 .bp_reg = ORC_REG_UNDEFINED,
133 .type = ORC_TYPE_CALL,
134 };
135
136 sec = find_section_by_name(file->elf, ".orc_unwind");
137 if (sec) {
138 WARN("file already has .orc_unwind section, skipping");
139 return -1;
140 }
141
142 /* count the number of needed orcs */
143 idx = 0;
144 for_each_sec(file, sec) {
145 if (!sec->text)
146 continue;
147
148 prev_insn = NULL;
149 sec_for_each_insn(file, sec, insn) {
150 if (!prev_insn ||
151 memcmp(&insn->orc, &prev_insn->orc,
152 sizeof(struct orc_entry))) {
153 idx++;
154 }
155 prev_insn = insn;
156 }
157
158 /* section terminator */
159 if (prev_insn)
160 idx++;
161 }
162 if (!idx)
163 return -1;
164
165
166 /* create .orc_unwind_ip and .rela.orc_unwind_ip sections */
167 sec = elf_create_section(file->elf, ".orc_unwind_ip", sizeof(int), idx);
168
169 ip_relasec = elf_create_rela_section(file->elf, sec);
170 if (!ip_relasec)
171 return -1;
172
173 /* create .orc_unwind section */
174 u_sec = elf_create_section(file->elf, ".orc_unwind",
175 sizeof(struct orc_entry), idx);
176
177 /* populate sections */
178 idx = 0;
179 for_each_sec(file, sec) {
180 if (!sec->text)
181 continue;
182
183 prev_insn = NULL;
184 sec_for_each_insn(file, sec, insn) {
185 if (!prev_insn || memcmp(&insn->orc, &prev_insn->orc,
186 sizeof(struct orc_entry))) {
187
188 if (create_orc_entry(u_sec, ip_relasec, idx,
189 insn->sec, insn->offset,
190 &insn->orc))
191 return -1;
192
193 idx++;
194 }
195 prev_insn = insn;
196 }
197
198 /* section terminator */
199 if (prev_insn) {
200 if (create_orc_entry(u_sec, ip_relasec, idx,
201 prev_insn->sec,
202 prev_insn->offset + prev_insn->len,
203 &empty))
204 return -1;
205
206 idx++;
207 }
208 }
209
210 if (elf_rebuild_rela_section(ip_relasec))
211 return -1;
212
213 return 0;
214}
diff --git a/tools/objtool/sync-check.sh b/tools/objtool/sync-check.sh
new file mode 100755
index 000000000000..1470e74e9d66
--- /dev/null
+++ b/tools/objtool/sync-check.sh
@@ -0,0 +1,29 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3
4FILES='
5arch/x86/lib/insn.c
6arch/x86/lib/inat.c
7arch/x86/lib/x86-opcode-map.txt
8arch/x86/tools/gen-insn-attr-x86.awk
9arch/x86/include/asm/insn.h
10arch/x86/include/asm/inat.h
11arch/x86/include/asm/inat_types.h
12arch/x86/include/asm/orc_types.h
13'
14
15check()
16{
17 local file=$1
18
19 diff $file ../../$file > /dev/null ||
20 echo "Warning: synced file at 'tools/objtool/$file' differs from latest kernel version at '$file'"
21}
22
23if [ ! -d ../../kernel ] || [ ! -d ../../tools ] || [ ! -d ../objtool ]; then
24 exit 0
25fi
26
27for i in $FILES; do
28 check $i
29done
diff --git a/tools/pci/pcitest.c b/tools/pci/pcitest.c
index ad54a58d7dda..9074b477bff0 100644
--- a/tools/pci/pcitest.c
+++ b/tools/pci/pcitest.c
@@ -173,6 +173,7 @@ usage:
173 "\t-D <dev> PCI endpoint test device {default: /dev/pci-endpoint-test.0}\n" 173 "\t-D <dev> PCI endpoint test device {default: /dev/pci-endpoint-test.0}\n"
174 "\t-b <bar num> BAR test (bar number between 0..5)\n" 174 "\t-b <bar num> BAR test (bar number between 0..5)\n"
175 "\t-m <msi num> MSI test (msi number between 1..32)\n" 175 "\t-m <msi num> MSI test (msi number between 1..32)\n"
176 "\t-l Legacy IRQ test\n"
176 "\t-r Read buffer test\n" 177 "\t-r Read buffer test\n"
177 "\t-w Write buffer test\n" 178 "\t-w Write buffer test\n"
178 "\t-c Copy buffer test\n" 179 "\t-c Copy buffer test\n"
diff --git a/tools/pci/pcitest.sh b/tools/pci/pcitest.sh
index 5442bbea4c22..77e8c85ef744 100644
--- a/tools/pci/pcitest.sh
+++ b/tools/pci/pcitest.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2 3
3echo "BAR tests" 4echo "BAR tests"
4echo 5echo
diff --git a/tools/pcmcia/Makefile b/tools/pcmcia/Makefile
index 81a7498c5cd9..eae24df1dbf5 100644
--- a/tools/pcmcia/Makefile
+++ b/tools/pcmcia/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1CC := $(CROSS_COMPILE)gcc 2CC := $(CROSS_COMPILE)gcc
2CFLAGS := -I../../usr/include 3CFLAGS := -I../../usr/include
3 4
diff --git a/tools/perf/Build b/tools/perf/Build
index bd8eeb60533c..b48ca40fccf9 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -50,6 +50,6 @@ libperf-y += util/
50libperf-y += arch/ 50libperf-y += arch/
51libperf-y += ui/ 51libperf-y += ui/
52libperf-y += scripts/ 52libperf-y += scripts/
53libperf-y += trace/beauty/ 53libperf-$(CONFIG_AUDIT) += trace/beauty/
54 54
55gtk-y += ui/gtk/ 55gtk-y += ui/gtk/
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index 098cfb9ca8f0..db11478e30b4 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -192,7 +192,7 @@ do-install-man: man
192# $(INSTALL) -m 644 $(DOC_MAN5) $(DESTDIR)$(man5dir); \ 192# $(INSTALL) -m 644 $(DOC_MAN5) $(DESTDIR)$(man5dir); \
193# $(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir) 193# $(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir)
194 194
195install-man: check-man-tools man 195install-man: check-man-tools man do-install-man
196 196
197ifdef missing_tools 197ifdef missing_tools
198 DO_INSTALL_MAN = $(warning Please install $(missing_tools) to have the man pages installed) 198 DO_INSTALL_MAN = $(warning Please install $(missing_tools) to have the man pages installed)
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index 4b6cdbf8f935..76971d2e4164 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -104,9 +104,9 @@ system, asynchronous, interrupt, transaction abort, trace begin, trace end, and
104in transaction, respectively. 104in transaction, respectively.
105 105
106While it is possible to create scripts to analyze the data, an alternative 106While it is possible to create scripts to analyze the data, an alternative
107approach is available to export the data to a postgresql database. Refer to 107approach is available to export the data to a sqlite or postgresql database.
108script export-to-postgresql.py for more details, and to script 108Refer to script export-to-sqlite.py or export-to-postgresql.py for more details,
109call-graph-from-postgresql.py for an example of using the database. 109and to script call-graph-from-sql.py for an example of using the database.
110 110
111There is also script intel-pt-events.py which provides an example of how to 111There is also script intel-pt-events.py which provides an example of how to
112unpack the raw data for power events and PTWRITE. 112unpack the raw data for power events and PTWRITE.
@@ -873,7 +873,7 @@ amended to take the number of elements as a parameter.
873 873
874 $ cat ~/.perfconfig 874 $ cat ~/.perfconfig
875 [intel-pt] 875 [intel-pt]
876 mispred-all 876 mispred-all = on
877 877
878 $ perf record -e intel_pt//u ./sort 3000 878 $ perf record -e intel_pt//u ./sort 3000
879 Bubble sorting array of 3000 elements 879 Bubble sorting array of 3000 elements
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index a89273d8e744..c635eab6af54 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -43,6 +43,10 @@ OPTIONS
43--quiet:: 43--quiet::
44 Do not show any message. (Suppress -v) 44 Do not show any message. (Suppress -v)
45 45
46-n::
47--show-nr-samples::
48 Show the number of samples for each symbol
49
46-D:: 50-D::
47--dump-raw-trace:: 51--dump-raw-trace::
48 Dump raw trace in ASCII. 52 Dump raw trace in ASCII.
@@ -88,6 +92,8 @@ OPTIONS
88--asm-raw:: 92--asm-raw::
89 Show raw instruction encoding of assembly instructions. 93 Show raw instruction encoding of assembly instructions.
90 94
95--show-total-period:: Show a column with the sum of periods.
96
91--source:: 97--source::
92 Interleave source code with assembly code. Enabled by default, 98 Interleave source code with assembly code. Enabled by default,
93 disable with --no-source. 99 disable with --no-source.
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index 058064db39d2..84681007f80f 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -61,6 +61,11 @@ OPTIONS
61--verbose:: 61--verbose::
62 Be more verbose. 62 Be more verbose.
63 63
64--target-ns=PID:
65 Obtain mount namespace information from the target pid. This is
66 used when creating a uprobe for a process that resides in a
67 different mount namespace from the perf(1) utility.
68
64SEE ALSO 69SEE ALSO
65-------- 70--------
66linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-buildid-list[1] 71linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-buildid-list[1]
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index f709de54707b..e2a897ae3596 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -8,7 +8,8 @@ perf-list - List all symbolic event types
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf list' [--no-desc] [--long-desc] [hw|sw|cache|tracepoint|pmu|sdt|event_glob] 11'perf list' [--no-desc] [--long-desc]
12 [hw|sw|cache|tracepoint|pmu|sdt|metric|metricgroup|event_glob]
12 13
13DESCRIPTION 14DESCRIPTION
14----------- 15-----------
@@ -47,6 +48,8 @@ counted. The following modifiers exist:
47 P - use maximum detected precise level 48 P - use maximum detected precise level
48 S - read sample value (PERF_SAMPLE_READ) 49 S - read sample value (PERF_SAMPLE_READ)
49 D - pin the event to the PMU 50 D - pin the event to the PMU
51 W - group is weak and will fallback to non-group if not schedulable,
52 only supported in 'perf stat' for now.
50 53
51The 'p' modifier can be used for specifying how precise the instruction 54The 'p' modifier can be used for specifying how precise the instruction
52address should be. The 'p' modifier can be specified multiple times: 55address should be. The 'p' modifier can be specified multiple times:
@@ -201,7 +204,7 @@ For example Intel Core CPUs typically have four generic performance counters
201for the core, plus three fixed counters for instructions, cycles and 204for the core, plus three fixed counters for instructions, cycles and
202ref-cycles. Some special events have restrictions on which counter they 205ref-cycles. Some special events have restrictions on which counter they
203can schedule, and may not support multiple instances in a single group. 206can schedule, and may not support multiple instances in a single group.
204When too many events are specified in the group none of them will not 207When too many events are specified in the group some of them will not
205be measured. 208be measured.
206 209
207Globally pinned events can limit the number of counters available for 210Globally pinned events can limit the number of counters available for
@@ -246,6 +249,10 @@ To limit the list use:
246 249
247. 'sdt' to list all Statically Defined Tracepoint events. 250. 'sdt' to list all Statically Defined Tracepoint events.
248 251
252. 'metric' to list metrics
253
254. 'metricgroup' to list metricgroups with metrics.
255
249. If none of the above is matched, it will apply the supplied glob to all 256. If none of the above is matched, it will apply the supplied glob to all
250 events, printing the ones that match. 257 events, printing the ones that match.
251 258
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 73496320fca3..4be08a1e3f8d 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -59,6 +59,10 @@ OPTIONS
59--ldload:: 59--ldload::
60 Specify desired latency for loads event. 60 Specify desired latency for loads event.
61 61
62-p::
63--phys-data::
64 Record/Report sample physical addresses
65
62SEE ALSO 66SEE ALSO
63-------- 67--------
64linkperf:perf-record[1], linkperf:perf-report[1] 68linkperf:perf-record[1], linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 165c2b1d4317..d7e4869905f1 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -130,6 +130,11 @@ OPTIONS
130--max-probes=NUM:: 130--max-probes=NUM::
131 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.
132 132
133--target-ns=PID:
134 Obtain mount namespace information from the target pid. This is
135 used when creating a uprobe for a process that resides in a
136 different mount namespace from the perf(1) utility.
137
133-x:: 138-x::
134--exec=PATH:: 139--exec=PATH::
135 Specify path to the executable or shared library file for user 140 Specify path to the executable or shared library file for user
@@ -264,6 +269,15 @@ Add probes at malloc() function on libc
264 269
265 ./perf probe -x /lib/libc.so.6 malloc or ./perf probe /lib/libc.so.6 malloc 270 ./perf probe -x /lib/libc.so.6 malloc or ./perf probe /lib/libc.so.6 malloc
266 271
272Add a uprobe to a target process running in a different mount namespace
273
274 ./perf probe --target-ns <target pid> -x /lib64/libc.so.6 malloc
275
276Add a USDT probe to a target process running in a different mount namespace
277
278 ./perf probe --target-ns <target pid> -x /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.121-0.b13.el7_3.x86_64/jre/lib/amd64/server/libjvm.so %sdt_hotspot:thread__sleep__end
279
280
267SEE ALSO 281SEE ALSO
268-------- 282--------
269linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1] 283linkperf: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 b0e9e921d534..5a626ef666c2 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -8,8 +8,8 @@ perf-record - Run a command and record its profile into perf.data
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf record' [-e <EVENT> | --event=EVENT] [-l] [-a] <command> 11'perf record' [-e <EVENT> | --event=EVENT] [-a] <command>
12'perf record' [-e <EVENT> | --event=EVENT] [-l] [-a] -- <command> [<options>] 12'perf record' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>]
13 13
14DESCRIPTION 14DESCRIPTION
15----------- 15-----------
@@ -249,7 +249,10 @@ OPTIONS
249 249
250-d:: 250-d::
251--data:: 251--data::
252 Record the sample addresses. 252 Record the sample virtual addresses.
253
254--phys-data::
255 Record the sample physical addresses.
253 256
254-T:: 257-T::
255--timestamp:: 258--timestamp::
@@ -332,6 +335,7 @@ following filters are defined:
332 - no_tx: only when the target is not in a hardware transaction 335 - no_tx: only when the target is not in a hardware transaction
333 - abort_tx: only when the target is a hardware transaction abort 336 - abort_tx: only when the target is a hardware transaction abort
334 - cond: conditional branches 337 - cond: conditional branches
338 - save_type: save branch type during sampling in case binary is not available later
335 339
336+ 340+
337The option requires at least one branch type among any, any_call, any_ret, ind_call, cond. 341The option requires at least one branch type among any, any_call, any_ret, ind_call, cond.
@@ -373,6 +377,8 @@ symbolic names, e.g. on x86, ax, si. To list the available registers use
373--intr-regs=\?. To name registers, pass a comma separated list such as 377--intr-regs=\?. To name registers, pass a comma separated list such as
374--intr-regs=ax,bx. The list of register is architecture dependent. 378--intr-regs=ax,bx. The list of register is architecture dependent.
375 379
380--user-regs::
381Capture user registers at sample time. Same arguments as -I.
376 382
377--running-time:: 383--running-time::
378Record running and enabled time for read events (:S) 384Record running and enabled time for read events (:S)
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 9fa84617181e..ddde2b54af57 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -137,6 +137,7 @@ OPTIONS
137 - mem: type of memory access for the data at the time of the sample 137 - mem: type of memory access for the data at the time of the sample
138 - snoop: type of snoop (if any) for the data at the time of the sample 138 - snoop: type of snoop (if any) for the data at the time of the sample
139 - dcacheline: the cacheline the data address is on at the time of the sample 139 - dcacheline: the cacheline the data address is on at the time of the sample
140 - phys_daddr: physical address of data being executed on at the time of sample
140 141
141 And the default sort keys are changed to local_weight, mem, sym, dso, 142 And the default sort keys are changed to local_weight, mem, sym, dso,
142 symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'. 143 symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'.
@@ -433,7 +434,8 @@ include::itrace.txt[]
433 434
434--inline:: 435--inline::
435 If a callgraph address belongs to an inlined function, the inline stack 436 If a callgraph address belongs to an inlined function, the inline stack
436 will be printed. Each entry is function name or file/line. 437 will be printed. Each entry is function name or file/line. Enabled by
438 default, disable with --no-inline.
437 439
438include::callchain-overhead-calculation.txt[] 440include::callchain-overhead-calculation.txt[]
439 441
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index a092a2499e8f..55b67338548e 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -106,6 +106,14 @@ OPTIONS for 'perf sched timehist'
106--max-stack:: 106--max-stack::
107 Maximum number of functions to display in backtrace, default 5. 107 Maximum number of functions to display in backtrace, default 5.
108 108
109-p=::
110--pid=::
111 Only show events for given process ID (comma separated list).
112
113-t=::
114--tid=::
115 Only show events for given thread ID (comma separated list).
116
109-s:: 117-s::
110--summary:: 118--summary::
111 Show only a summary of scheduling by thread with min, max, and average 119 Show only a summary of scheduling by thread with min, max, and average
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 5ee8796be96e..2811fcf684cb 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -116,8 +116,8 @@ 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, bpf-output, brstackinsn, brstackoff, 119 srcline, period, iregs, uregs, brstack, brstacksym, flags, bpf-output, brstackinsn,
120 callindent, insn, insnlen, synth. 120 brstackoff, callindent, insn, insnlen, synth, phys_addr.
121 Field list can be prepended with the type, trace, sw or hw, 121 Field list can be prepended with the type, trace, sw or hw,
122 to indicate to which event type the field list applies. 122 to indicate to which event type the field list applies.
123 e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace 123 e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace
@@ -325,9 +325,14 @@ include::itrace.txt[]
325 Set the maximum number of program blocks to print with brstackasm for 325 Set the maximum number of program blocks to print with brstackasm for
326 each sample. 326 each sample.
327 327
328--per-event-dump::
329 Create per event files with a "perf.data.EVENT.dump" name instead of
330 printing to stdout, useful, for instance, for generating flamegraphs.
331
328--inline:: 332--inline::
329 If a callgraph address belongs to an inlined function, the inline stack 333 If a callgraph address belongs to an inlined function, the inline stack
330 will be printed. Each entry has function name and file/line. 334 will be printed. Each entry has function name and file/line. Enabled by
335 default, disable with --no-inline.
331 336
332SEE ALSO 337SEE ALSO
333-------- 338--------
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 698076313606..823fce7674bb 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -41,13 +41,13 @@ report::
41 41
42 - a symbolically formed event like 'pmu/param1=0x3,param2/' where 42 - a symbolically formed event like 'pmu/param1=0x3,param2/' where
43 param1 and param2 are defined as formats for the PMU in 43 param1 and param2 are defined as formats for the PMU in
44 /sys/bus/event_sources/devices/<pmu>/format/* 44 /sys/bus/event_source/devices/<pmu>/format/*
45 45
46 - a symbolically formed event like 'pmu/config=M,config1=N,config2=K/' 46 - a symbolically formed event like 'pmu/config=M,config1=N,config2=K/'
47 where M, N, K are numbers (in decimal, hex, octal format). 47 where M, N, K are numbers (in decimal, hex, octal format).
48 Acceptable values for each of 'config', 'config1' and 'config2' 48 Acceptable values for each of 'config', 'config1' and 'config2'
49 parameters are defined by corresponding entries in 49 parameters are defined by corresponding entries in
50 /sys/bus/event_sources/devices/<pmu>/format/* 50 /sys/bus/event_source/devices/<pmu>/format/*
51 51
52-i:: 52-i::
53--no-inherit:: 53--no-inherit::
@@ -199,6 +199,13 @@ Aggregate counts per processor socket for system-wide mode measurements.
199--per-core:: 199--per-core::
200Aggregate counts per physical processor for system-wide mode measurements. 200Aggregate counts per physical processor for system-wide mode measurements.
201 201
202-M::
203--metrics::
204Print metrics or metricgroups specified in a comma separated list.
205For a group all metrics from the group are added.
206The events from the metrics are automatically measured.
207See perf list output for the possble metrics and metricgroups.
208
202-A:: 209-A::
203--no-aggr:: 210--no-aggr::
204Do not aggregate counts across all monitored CPUs. 211Do not aggregate counts across all monitored CPUs.
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index e71d63843f45..4353262bc462 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -237,6 +237,13 @@ Default is to monitor all CPUS.
237--hierarchy:: 237--hierarchy::
238 Enable hierarchy output. 238 Enable hierarchy output.
239 239
240--force::
241 Don't do ownership validation.
242
243--num-thread-synthesize::
244 The number of threads to run when synthesizing events for existing processes.
245 By default, the number of threads equals to the number of online CPUs.
246
240INTERACTIVE PROMPTING KEYS 247INTERACTIVE PROMPTING KEYS
241-------------------------- 248--------------------------
242 249
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index c1e3288a2dfb..d53bea6bd571 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -37,7 +37,7 @@ OPTIONS
37--expr:: 37--expr::
38--event:: 38--event::
39 List of syscalls and other perf events (tracepoints, HW cache events, 39 List of syscalls and other perf events (tracepoints, HW cache events,
40 etc) to show. 40 etc) to show. Globbing is supported, e.g.: "epoll_*", "*msg*", etc.
41 See 'perf list' for a complete list of events. 41 See 'perf list' for a complete list of events.
42 Prefixing with ! shows all syscalls but the ones specified. You may 42 Prefixing with ! shows all syscalls but the ones specified. You may
43 need to escape it. 43 need to escape it.
diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index de8b39dda7b8..e90c59c6d815 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -398,6 +398,11 @@ struct auxtrace_error_event {
398 char msg[MAX_AUXTRACE_ERROR_MSG]; 398 char msg[MAX_AUXTRACE_ERROR_MSG];
399}; 399};
400 400
401 PERF_RECORD_HEADER_FEATURE = 80,
402
403Describes a header feature. These are records used in pipe-mode that
404contain information that otherwise would be in perf.data file's header.
405
401Event types 406Event types
402 407
403Define the event attributes with their IDs. 408Define the event attributes with their IDs.
@@ -422,8 +427,9 @@ struct perf_pipe_file_header {
422}; 427};
423 428
424The information about attrs, data, and event_types is instead in the 429The information about attrs, data, and event_types is instead in the
425synthesized events PERF_RECORD_ATTR, PERF_RECORD_HEADER_TRACING_DATA and 430synthesized events PERF_RECORD_ATTR, PERF_RECORD_HEADER_TRACING_DATA,
426PERF_RECORD_HEADER_EVENT_TYPE that are generated by perf record in pipe-mode. 431PERF_RECORD_HEADER_EVENT_TYPE, and PERF_RECORD_HEADER_FEATURE
432that are generated by perf record in pipe-mode.
427 433
428 434
429References: 435References:
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index a29da46d180f..627b7cada144 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -1,34 +1,8 @@
1tools/perf 1tools/perf
2tools/arch/alpha/include/asm/barrier.h 2tools/arch
3tools/arch/arm/include/asm/barrier.h
4tools/arch/arm64/include/asm/barrier.h
5tools/arch/ia64/include/asm/barrier.h
6tools/arch/mips/include/asm/barrier.h
7tools/arch/powerpc/include/asm/barrier.h
8tools/arch/s390/include/asm/barrier.h
9tools/arch/sh/include/asm/barrier.h
10tools/arch/sparc/include/asm/barrier.h
11tools/arch/sparc/include/asm/barrier_32.h
12tools/arch/sparc/include/asm/barrier_64.h
13tools/arch/tile/include/asm/barrier.h
14tools/arch/x86/include/asm/barrier.h
15tools/arch/x86/include/asm/cmpxchg.h
16tools/arch/x86/include/asm/cpufeatures.h
17tools/arch/x86/include/asm/disabled-features.h
18tools/arch/x86/include/asm/required-features.h
19tools/arch/x86/include/uapi/asm/svm.h
20tools/arch/x86/include/uapi/asm/vmx.h
21tools/arch/x86/include/uapi/asm/kvm.h
22tools/arch/x86/include/uapi/asm/kvm_perf.h
23tools/arch/x86/lib/memcpy_64.S
24tools/arch/x86/lib/memset_64.S
25tools/arch/s390/include/uapi/asm/kvm_perf.h
26tools/arch/s390/include/uapi/asm/sie.h
27tools/arch/xtensa/include/asm/barrier.h
28tools/scripts 3tools/scripts
29tools/build 4tools/build
30tools/arch/x86/include/asm/atomic.h 5tools/include
31tools/arch/x86/include/asm/rmwcc.h
32tools/lib/traceevent 6tools/lib/traceevent
33tools/lib/api 7tools/lib/api
34tools/lib/bpf 8tools/lib/bpf
@@ -42,52 +16,3 @@ tools/lib/find_bit.c
42tools/lib/bitmap.c 16tools/lib/bitmap.c
43tools/lib/str_error_r.c 17tools/lib/str_error_r.c
44tools/lib/vsprintf.c 18tools/lib/vsprintf.c
45tools/include/asm/alternative-asm.h
46tools/include/asm/atomic.h
47tools/include/asm/barrier.h
48tools/include/asm/bug.h
49tools/include/asm-generic/atomic-gcc.h
50tools/include/asm-generic/barrier.h
51tools/include/asm-generic/bitops/arch_hweight.h
52tools/include/asm-generic/bitops/atomic.h
53tools/include/asm-generic/bitops/const_hweight.h
54tools/include/asm-generic/bitops/__ffs.h
55tools/include/asm-generic/bitops/__ffz.h
56tools/include/asm-generic/bitops/__fls.h
57tools/include/asm-generic/bitops/find.h
58tools/include/asm-generic/bitops/fls64.h
59tools/include/asm-generic/bitops/fls.h
60tools/include/asm-generic/bitops/hweight.h
61tools/include/asm-generic/bitops.h
62tools/include/linux/atomic.h
63tools/include/linux/bitops.h
64tools/include/linux/compiler.h
65tools/include/linux/compiler-gcc.h
66tools/include/linux/coresight-pmu.h
67tools/include/linux/bug.h
68tools/include/linux/filter.h
69tools/include/linux/hash.h
70tools/include/linux/kernel.h
71tools/include/linux/list.h
72tools/include/linux/log2.h
73tools/include/uapi/asm-generic/mman-common.h
74tools/include/uapi/asm-generic/mman.h
75tools/include/uapi/linux/bpf.h
76tools/include/uapi/linux/bpf_common.h
77tools/include/uapi/linux/fcntl.h
78tools/include/uapi/linux/hw_breakpoint.h
79tools/include/uapi/linux/mman.h
80tools/include/uapi/linux/perf_event.h
81tools/include/uapi/linux/stat.h
82tools/include/linux/poison.h
83tools/include/linux/rbtree.h
84tools/include/linux/rbtree_augmented.h
85tools/include/linux/refcount.h
86tools/include/linux/string.h
87tools/include/linux/stringify.h
88tools/include/linux/types.h
89tools/include/linux/err.h
90tools/include/linux/bitmap.h
91tools/include/linux/time64.h
92tools/arch/*/include/uapi/asm/mman.h
93tools/arch/*/include/uapi/asm/perf_regs.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 32a64e619028..225454416ed5 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# 2#
2# This is a simple wrapper Makefile that calls the main Makefile.perf 3# This is a simple wrapper Makefile that calls the main Makefile.perf
3# with a -j option to do parallel builds 4# with a -j option to do parallel builds
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index bdf0e87f9b29..ed65e82f034e 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -35,7 +35,7 @@ ifeq ($(SRCARCH),x86)
35 ifeq (${IS_64_BIT}, 1) 35 ifeq (${IS_64_BIT}, 1)
36 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT -DHAVE_SYSCALL_TABLE -I$(OUTPUT)arch/x86/include/generated 36 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT -DHAVE_SYSCALL_TABLE -I$(OUTPUT)arch/x86/include/generated
37 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S 37 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
38 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 38 LIBUNWIND_LIBS = -lunwind-x86_64 -lunwind -llzma
39 $(call detected,CONFIG_X86_64) 39 $(call detected,CONFIG_X86_64)
40 else 40 else
41 LIBUNWIND_LIBS = -lunwind-x86 -llzma -lunwind 41 LIBUNWIND_LIBS = -lunwind-x86 -llzma -lunwind
@@ -53,6 +53,10 @@ ifeq ($(SRCARCH),arm64)
53 LIBUNWIND_LIBS = -lunwind -lunwind-aarch64 53 LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
54endif 54endif
55 55
56ifeq ($(ARCH),s390)
57 NO_PERF_REGS := 0
58endif
59
56ifeq ($(NO_PERF_REGS),0) 60ifeq ($(NO_PERF_REGS),0)
57 $(call detected,CONFIG_PERF_REGS) 61 $(call detected,CONFIG_PERF_REGS)
58endif 62endif
@@ -61,7 +65,7 @@ endif
61# Disable it on all other architectures in case libdw unwind 65# Disable it on all other architectures in case libdw unwind
62# support is detected in system. Add supported architectures 66# support is detected in system. Add supported architectures
63# to the check. 67# to the check.
64ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm powerpc)) 68ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm powerpc s390))
65 NO_LIBDW_DWARF_UNWIND := 1 69 NO_LIBDW_DWARF_UNWIND := 1
66endif 70endif
67 71
@@ -103,8 +107,12 @@ ifdef LIBDW_DIR
103 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include 107 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
104 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib 108 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
105endif 109endif
110DWARFLIBS := -ldw
111ifeq ($(findstring -static,${LDFLAGS}),-static)
112 DWARFLIBS += -lelf -lebl -ldl -lz -llzma -lbz2
113endif
106FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS) 114FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
107FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw 115FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) $(DWARFLIBS)
108 116
109# for linking with debug library, run like: 117# for linking with debug library, run like:
110# make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/ 118# make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
@@ -144,7 +152,7 @@ ifndef DEBUG
144endif 152endif
145 153
146ifeq ($(DEBUG),0) 154ifeq ($(DEBUG),0)
147ifeq ($(CC), clang) 155ifeq ($(CC_NO_CLANG), 0)
148 CFLAGS += -O3 156 CFLAGS += -O3
149else 157else
150 CFLAGS += -O6 158 CFLAGS += -O6
@@ -180,7 +188,7 @@ ifdef PYTHON_CONFIG
180 PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) 188 PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
181 PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil 189 PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil
182 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) 190 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
183 ifeq ($(CC), clang) 191 ifeq ($(CC_NO_CLANG), 1)
184 PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS)) 192 PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS))
185 endif 193 endif
186 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 194 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
@@ -330,6 +338,11 @@ ifeq ($(feature-sched_getcpu), 1)
330 CFLAGS += -DHAVE_SCHED_GETCPU_SUPPORT 338 CFLAGS += -DHAVE_SCHED_GETCPU_SUPPORT
331endif 339endif
332 340
341ifeq ($(feature-setns), 1)
342 CFLAGS += -DHAVE_SETNS_SUPPORT
343 $(call detected,CONFIG_SETNS)
344endif
345
333ifndef NO_LIBELF 346ifndef NO_LIBELF
334 CFLAGS += -DHAVE_LIBELF_SUPPORT 347 CFLAGS += -DHAVE_LIBELF_SUPPORT
335 EXTLIBS += -lelf 348 EXTLIBS += -lelf
@@ -360,10 +373,6 @@ ifndef NO_LIBELF
360 else 373 else
361 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) 374 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
362 LDFLAGS += $(LIBDW_LDFLAGS) 375 LDFLAGS += $(LIBDW_LDFLAGS)
363 DWARFLIBS := -ldw
364 ifeq ($(findstring -static,${LDFLAGS}),-static)
365 DWARFLIBS += -lelf -lebl -lz -llzma -lbz2
366 endif
367 EXTLIBS += ${DWARFLIBS} 376 EXTLIBS += ${DWARFLIBS}
368 $(call detected,CONFIG_DWARF) 377 $(call detected,CONFIG_DWARF)
369 endif # PERF_HAVE_DWARF_REGS 378 endif # PERF_HAVE_DWARF_REGS
@@ -500,6 +509,10 @@ ifndef NO_LOCAL_LIBUNWIND
500 EXTLIBS += $(LIBUNWIND_LIBS) 509 EXTLIBS += $(LIBUNWIND_LIBS)
501 LDFLAGS += $(LIBUNWIND_LIBS) 510 LDFLAGS += $(LIBUNWIND_LIBS)
502endif 511endif
512ifeq ($(findstring -static,${LDFLAGS}),-static)
513 # gcc -static links libgcc_eh which contans piece of libunwind
514 LIBUNWIND_LDFLAGS += -Wl,--allow-multiple-definition
515endif
503 516
504ifndef NO_LIBUNWIND 517ifndef NO_LIBUNWIND
505 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT 518 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 5008f51a08a2..68cf1360a3f3 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -33,6 +33,11 @@ include ../scripts/utilities.mak
33# 33#
34# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds. 34# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
35# 35#
36# Define EXCLUDE_EXTLIBS=-lmylib to exclude libmylib from the auto-generated
37# EXTLIBS.
38#
39# Define EXTRA_PERFLIBS to pass extra libraries to PERFLIBS.
40#
36# Define NO_DWARF if you do not want debug-info analysis feature at all. 41# Define NO_DWARF if you do not want debug-info analysis feature at all.
37# 42#
38# Define WERROR=0 to disable treating any warnings as errors. 43# Define WERROR=0 to disable treating any warnings as errors.
@@ -159,8 +164,8 @@ LN = ln -f
159MKDIR = mkdir 164MKDIR = mkdir
160FIND = find 165FIND = find
161INSTALL = install 166INSTALL = install
162FLEX = flex 167FLEX ?= flex
163BISON = bison 168BISON ?= bison
164STRIP = strip 169STRIP = strip
165AWK = awk 170AWK = awk
166 171
@@ -168,7 +173,7 @@ AWK = awk
168# non-config cases 173# non-config cases
169config := 1 174config := 1
170 175
171NON_CONFIG_TARGETS := clean TAGS tags cscope help install-doc install-man install-html install-info install-pdf doc man html info pdf 176NON_CONFIG_TARGETS := clean python-clean TAGS tags cscope help install-doc install-man install-html install-info install-pdf doc man html info pdf
172 177
173ifdef MAKECMDGOALS 178ifdef MAKECMDGOALS
174ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),) 179ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
@@ -235,7 +240,7 @@ endif
235ifeq ($(FEATURES_DUMP),) 240ifeq ($(FEATURES_DUMP),)
236FEATURE_DUMP_EXPORT := $(realpath $(OUTPUT)FEATURE-DUMP) 241FEATURE_DUMP_EXPORT := $(realpath $(OUTPUT)FEATURE-DUMP)
237else 242else
238FEATURE_DUMP_EXPORT := $(FEATURES_DUMP) 243FEATURE_DUMP_EXPORT := $(realpath $(FEATURES_DUMP))
239endif 244endif
240 245
241export prefix bindir sharedir sysconfdir DESTDIR 246export prefix bindir sharedir sysconfdir DESTDIR
@@ -274,7 +279,13 @@ LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
274export LIBTRACEEVENT 279export LIBTRACEEVENT
275 280
276LIBTRACEEVENT_DYNAMIC_LIST = $(TE_PATH)libtraceevent-dynamic-list 281LIBTRACEEVENT_DYNAMIC_LIST = $(TE_PATH)libtraceevent-dynamic-list
277LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS = -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYNAMIC_LIST) 282
283#
284# The static build has no dynsym table, so this does not work for
285# static build. Looks like linker starts to scream about that now
286# (in Fedora 26) so we need to switch it off for static build.
287DYNAMIC_LIST_LDFLAGS = -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYNAMIC_LIST)
288LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS = $(if $(findstring -static,$(LDFLAGS)),,$(DYNAMIC_LIST_LDFLAGS))
278 289
279LIBAPI = $(API_PATH)libapi.a 290LIBAPI = $(API_PATH)libapi.a
280export LIBAPI 291export LIBAPI
@@ -352,7 +363,8 @@ ifdef ASCIIDOC8
352 export ASCIIDOC8 363 export ASCIIDOC8
353endif 364endif
354 365
355LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group 366EXTLIBS := $(call filter-out,$(EXCLUDE_EXTLIBS),$(EXTLIBS))
367LIBS = -Wl,--whole-archive $(PERFLIBS) $(EXTRA_PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
356 368
357ifeq ($(USE_CLANG), 1) 369ifeq ($(USE_CLANG), 1)
358 CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization 370 CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization
@@ -375,6 +387,81 @@ export INSTALL SHELL_PATH
375 387
376SHELL = $(SHELL_PATH) 388SHELL = $(SHELL_PATH)
377 389
390beauty_outdir := $(OUTPUT)trace/beauty/generated
391beauty_ioctl_outdir := $(beauty_outdir)/ioctl
392drm_ioctl_array := $(beauty_ioctl_outdir)/drm_ioctl_array.c
393drm_hdr_dir := $(srctree)/tools/include/uapi/drm
394drm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/drm_ioctl.sh
395
396# Create output directory if not already present
397_dummy := $(shell [ -d '$(beauty_ioctl_outdir)' ] || mkdir -p '$(beauty_ioctl_outdir)')
398
399$(drm_ioctl_array): $(drm_hdr_dir)/drm.h $(drm_hdr_dir)/i915_drm.h $(drm_ioctl_tbl)
400 $(Q)$(SHELL) '$(drm_ioctl_tbl)' $(drm_hdr_dir) > $@
401
402pkey_alloc_access_rights_array := $(beauty_outdir)/pkey_alloc_access_rights_array.c
403asm_generic_hdr_dir := $(srctree)/tools/include/uapi/asm-generic/
404pkey_alloc_access_rights_tbl := $(srctree)/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
405
406$(pkey_alloc_access_rights_array): $(asm_generic_hdr_dir)/mman-common.h $(pkey_alloc_access_rights_tbl)
407 $(Q)$(SHELL) '$(pkey_alloc_access_rights_tbl)' $(asm_generic_hdr_dir) > $@
408
409sndrv_ctl_ioctl_array := $(beauty_ioctl_outdir)/sndrv_ctl_ioctl_array.c
410sndrv_ctl_hdr_dir := $(srctree)/tools/include/uapi/sound
411sndrv_ctl_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh
412
413$(sndrv_ctl_ioctl_array): $(sndrv_ctl_hdr_dir)/asound.h $(sndrv_ctl_ioctl_tbl)
414 $(Q)$(SHELL) '$(sndrv_ctl_ioctl_tbl)' $(sndrv_ctl_hdr_dir) > $@
415
416sndrv_pcm_ioctl_array := $(beauty_ioctl_outdir)/sndrv_pcm_ioctl_array.c
417sndrv_pcm_hdr_dir := $(srctree)/tools/include/uapi/sound
418sndrv_pcm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
419
420$(sndrv_pcm_ioctl_array): $(sndrv_pcm_hdr_dir)/asound.h $(sndrv_pcm_ioctl_tbl)
421 $(Q)$(SHELL) '$(sndrv_pcm_ioctl_tbl)' $(sndrv_pcm_hdr_dir) > $@
422
423kcmp_type_array := $(beauty_outdir)/kcmp_type_array.c
424kcmp_hdr_dir := $(srctree)/tools/include/uapi/linux/
425kcmp_type_tbl := $(srctree)/tools/perf/trace/beauty/kcmp_type.sh
426
427$(kcmp_type_array): $(kcmp_hdr_dir)/kcmp.h $(kcmp_type_tbl)
428 $(Q)$(SHELL) '$(kcmp_type_tbl)' $(kcmp_hdr_dir) > $@
429
430kvm_ioctl_array := $(beauty_ioctl_outdir)/kvm_ioctl_array.c
431kvm_hdr_dir := $(srctree)/tools/include/uapi/linux
432kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh
433
434$(kvm_ioctl_array): $(kvm_hdr_dir)/kvm.h $(kvm_ioctl_tbl)
435 $(Q)$(SHELL) '$(kvm_ioctl_tbl)' $(kvm_hdr_dir) > $@
436
437vhost_virtio_ioctl_array := $(beauty_ioctl_outdir)/vhost_virtio_ioctl_array.c
438vhost_virtio_hdr_dir := $(srctree)/tools/include/uapi/linux
439vhost_virtio_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
440
441$(vhost_virtio_ioctl_array): $(vhost_virtio_hdr_dir)/vhost.h $(vhost_virtio_ioctl_tbl)
442 $(Q)$(SHELL) '$(vhost_virtio_ioctl_tbl)' $(vhost_virtio_hdr_dir) > $@
443
444perf_ioctl_array := $(beauty_ioctl_outdir)/perf_ioctl_array.c
445perf_hdr_dir := $(srctree)/tools/include/uapi/linux
446perf_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/perf_ioctl.sh
447
448$(perf_ioctl_array): $(perf_hdr_dir)/perf_event.h $(perf_ioctl_tbl)
449 $(Q)$(SHELL) '$(perf_ioctl_tbl)' $(perf_hdr_dir) > $@
450
451madvise_behavior_array := $(beauty_outdir)/madvise_behavior_array.c
452madvise_hdr_dir := $(srctree)/tools/include/uapi/asm-generic/
453madvise_behavior_tbl := $(srctree)/tools/perf/trace/beauty/madvise_behavior.sh
454
455$(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl)
456 $(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@
457
458prctl_option_array := $(beauty_outdir)/prctl_option_array.c
459prctl_hdr_dir := $(srctree)/tools/include/uapi/linux/
460prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh
461
462$(prctl_option_array): $(prctl_hdr_dir)/prctl.h $(prctl_option_tbl)
463 $(Q)$(SHELL) '$(prctl_option_tbl)' $(prctl_hdr_dir) > $@
464
378all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) 465all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
379 466
380$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST) 467$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
@@ -469,7 +556,16 @@ endif
469__build-dir = $(subst $(OUTPUT),,$(dir $@)) 556__build-dir = $(subst $(OUTPUT),,$(dir $@))
470build-dir = $(if $(__build-dir),$(__build-dir),.) 557build-dir = $(if $(__build-dir),$(__build-dir),.)
471 558
472prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders 559prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioctl_array) \
560 $(pkey_alloc_access_rights_array) \
561 $(sndrv_pcm_ioctl_array) \
562 $(sndrv_ctl_ioctl_array) \
563 $(kcmp_type_array) \
564 $(kvm_ioctl_array) \
565 $(vhost_virtio_ioctl_array) \
566 $(madvise_behavior_array) \
567 $(perf_ioctl_array) \
568 $(prctl_option_array)
473 569
474$(OUTPUT)%.o: %.c prepare FORCE 570$(OUTPUT)%.o: %.c prepare FORCE
475 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 571 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
@@ -512,7 +608,7 @@ $(LIBJVMTI_IN): FORCE
512 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=jvmti obj=jvmti 608 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=jvmti obj=jvmti
513 609
514$(OUTPUT)$(LIBJVMTI): $(LIBJVMTI_IN) 610$(OUTPUT)$(LIBJVMTI): $(LIBJVMTI_IN)
515 $(QUIET_LINK)$(CC) -shared -Wl,-soname -Wl,$(LIBJVMTI) -o $@ $< -lelf -lrt 611 $(QUIET_LINK)$(CC) -shared -Wl,-soname -Wl,$(LIBJVMTI) -o $@ $<
516endif 612endif
517 613
518$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h) 614$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
@@ -703,7 +799,11 @@ install-tests: all install-gtk
703 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ 799 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
704 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ 800 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
705 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ 801 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
706 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' 802 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
803 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell'; \
804 $(INSTALL) tests/shell/*.sh '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell'; \
805 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'; \
806 $(INSTALL) tests/shell/lib/*.sh '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'
707 807
708install-bin: install-tools install-tests install-traceevent-plugins 808install-bin: install-tools install-tests install-traceevent-plugins
709 809
@@ -726,7 +826,10 @@ config-clean:
726 $(call QUIET_CLEAN, config) 826 $(call QUIET_CLEAN, config)
727 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null 827 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null
728 828
729clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean fixdep-clean 829python-clean:
830 $(python-clean)
831
832clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean fixdep-clean python-clean
730 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) 833 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
731 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 834 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
732 $(Q)$(RM) $(OUTPUT).config-detected 835 $(Q)$(RM) $(OUTPUT).config-detected
@@ -734,9 +837,18 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
734 $(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* \ 837 $(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* \
735 $(OUTPUT)util/intel-pt-decoder/inat-tables.c \ 838 $(OUTPUT)util/intel-pt-decoder/inat-tables.c \
736 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \ 839 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
737 $(OUTPUT)pmu-events/pmu-events.c 840 $(OUTPUT)pmu-events/pmu-events.c \
841 $(OUTPUT)$(madvise_behavior_array) \
842 $(OUTPUT)$(drm_ioctl_array) \
843 $(OUTPUT)$(pkey_alloc_access_rights_array) \
844 $(OUTPUT)$(sndrv_ctl_ioctl_array) \
845 $(OUTPUT)$(sndrv_pcm_ioctl_array) \
846 $(OUTPUT)$(kvm_ioctl_array) \
847 $(OUTPUT)$(kcmp_type_array) \
848 $(OUTPUT)$(vhost_virtio_ioctl_array) \
849 $(OUTPUT)$(perf_ioctl_array) \
850 $(OUTPUT)$(prctl_option_array)
738 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 851 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
739 $(python-clean)
740 852
741# 853#
742# To provide FEATURE-DUMP into $(FEATURE_DUMP_COPY) 854# To provide FEATURE-DUMP into $(FEATURE_DUMP_COPY)
diff --git a/tools/perf/arch/arm/annotate/instructions.c b/tools/perf/arch/arm/annotate/instructions.c
index 1ce0872b1726..f64516d5b23e 100644
--- a/tools/perf/arch/arm/annotate/instructions.c
+++ b/tools/perf/arch/arm/annotate/instructions.c
@@ -1,3 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/compiler.h>
1#include <sys/types.h> 3#include <sys/types.h>
2#include <regex.h> 4#include <regex.h>
3 5
@@ -23,7 +25,7 @@ static struct ins_ops *arm__associate_instruction_ops(struct arch *arch, const c
23 return ops; 25 return ops;
24} 26}
25 27
26static int arm__annotate_init(struct arch *arch) 28static int arm__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
27{ 29{
28 struct arm_annotate *arm; 30 struct arm_annotate *arm;
29 int err; 31 int err;
diff --git a/tools/perf/arch/arm/include/dwarf-regs-table.h b/tools/perf/arch/arm/include/dwarf-regs-table.h
index f298d034c37b..5a45046fab72 100644
--- a/tools/perf/arch/arm/include/dwarf-regs-table.h
+++ b/tools/perf/arch/arm/include/dwarf-regs-table.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifdef DEFINE_DWARF_REGSTR_TABLE 2#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */ 3/* This is included in perf/util/dwarf-regs.c */
3 4
diff --git a/tools/perf/arch/arm/include/perf_regs.h b/tools/perf/arch/arm/include/perf_regs.h
index f619c9c5a4bf..ed20e0253e25 100644
--- a/tools/perf/arch/arm/include/perf_regs.h
+++ b/tools/perf/arch/arm/include/perf_regs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef ARCH_PERF_REGS_H 2#ifndef ARCH_PERF_REGS_H
2#define ARCH_PERF_REGS_H 3#define ARCH_PERF_REGS_H
3 4
diff --git a/tools/perf/arch/arm/tests/dwarf-unwind.c b/tools/perf/arch/arm/tests/dwarf-unwind.c
index 62eff847f91c..8cb347760233 100644
--- a/tools/perf/arch/arm/tests/dwarf-unwind.c
+++ b/tools/perf/arch/arm/tests/dwarf-unwind.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <string.h> 2#include <string.h>
2#include "perf_regs.h" 3#include "perf_regs.h"
3#include "thread.h" 4#include "thread.h"
diff --git a/tools/perf/arch/arm/tests/regs_load.S b/tools/perf/arch/arm/tests/regs_load.S
index e09e983946fe..6e2495cc4517 100644
--- a/tools/perf/arch/arm/tests/regs_load.S
+++ b/tools/perf/arch/arm/tests/regs_load.S
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include <linux/linkage.h> 2#include <linux/linkage.h>
2 3
3#define R0 0x00 4#define R0 0x00
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
index 7ce3d1a25133..fbfc055d3f4d 100644
--- a/tools/perf/arch/arm/util/cs-etm.c
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -266,6 +266,32 @@ static u64 cs_etm_get_config(struct auxtrace_record *itr)
266 return config; 266 return config;
267} 267}
268 268
269#ifndef BIT
270#define BIT(N) (1UL << (N))
271#endif
272
273static u64 cs_etmv4_get_config(struct auxtrace_record *itr)
274{
275 u64 config = 0;
276 u64 config_opts = 0;
277
278 /*
279 * The perf event variable config bits represent both
280 * the command line options and register programming
281 * bits in ETMv3/PTM. For ETMv4 we must remap options
282 * to real bits
283 */
284 config_opts = cs_etm_get_config(itr);
285 if (config_opts & BIT(ETM_OPT_CYCACC))
286 config |= BIT(ETM4_CFG_BIT_CYCACC);
287 if (config_opts & BIT(ETM_OPT_TS))
288 config |= BIT(ETM4_CFG_BIT_TS);
289 if (config_opts & BIT(ETM_OPT_RETSTK))
290 config |= BIT(ETM4_CFG_BIT_RETSTK);
291
292 return config;
293}
294
269static size_t 295static size_t
270cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused, 296cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
271 struct perf_evlist *evlist __maybe_unused) 297 struct perf_evlist *evlist __maybe_unused)
@@ -363,7 +389,7 @@ static void cs_etm_get_metadata(int cpu, u32 *offset,
363 magic = __perf_cs_etmv4_magic; 389 magic = __perf_cs_etmv4_magic;
364 /* Get trace configuration register */ 390 /* Get trace configuration register */
365 info->priv[*offset + CS_ETMV4_TRCCONFIGR] = 391 info->priv[*offset + CS_ETMV4_TRCCONFIGR] =
366 cs_etm_get_config(itr); 392 cs_etmv4_get_config(itr);
367 /* Get traceID from the framework */ 393 /* Get traceID from the framework */
368 info->priv[*offset + CS_ETMV4_TRCTRACEIDR] = 394 info->priv[*offset + CS_ETMV4_TRCTRACEIDR] =
369 coresight_get_trace_id(cpu); 395 coresight_get_trace_id(cpu);
diff --git a/tools/perf/arch/arm/util/unwind-libdw.c b/tools/perf/arch/arm/util/unwind-libdw.c
index bacfa00fca39..36ba4c69c3c5 100644
--- a/tools/perf/arch/arm/util/unwind-libdw.c
+++ b/tools/perf/arch/arm/util/unwind-libdw.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <elfutils/libdwfl.h> 2#include <elfutils/libdwfl.h>
2#include "../../util/unwind-libdw.h" 3#include "../../util/unwind-libdw.h"
3#include "../../util/perf_regs.h" 4#include "../../util/perf_regs.h"
diff --git a/tools/perf/arch/arm/util/unwind-libunwind.c b/tools/perf/arch/arm/util/unwind-libunwind.c
index 62c397ed3d97..3a550225dfaf 100644
--- a/tools/perf/arch/arm/util/unwind-libunwind.c
+++ b/tools/perf/arch/arm/util/unwind-libunwind.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1 2
2#include <errno.h> 3#include <errno.h>
3#include <libunwind.h> 4#include <libunwind.h>
diff --git a/tools/perf/arch/arm64/Makefile b/tools/perf/arch/arm64/Makefile
index eebe1ec9d2ee..91de4860faad 100644
--- a/tools/perf/arch/arm64/Makefile
+++ b/tools/perf/arch/arm64/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1ifndef NO_DWARF 2ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 3PERF_HAVE_DWARF_REGS := 1
3endif 4endif
diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index 8f1908756cb6..6688977e4ac7 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -1,3 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/compiler.h>
1#include <sys/types.h> 3#include <sys/types.h>
2#include <regex.h> 4#include <regex.h>
3 5
@@ -25,7 +27,7 @@ static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const
25 return ops; 27 return ops;
26} 28}
27 29
28static int arm64__annotate_init(struct arch *arch) 30static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
29{ 31{
30 struct arm64_annotate *arm; 32 struct arm64_annotate *arm;
31 int err; 33 int err;
diff --git a/tools/perf/arch/arm64/include/dwarf-regs-table.h b/tools/perf/arch/arm64/include/dwarf-regs-table.h
index 36e375f5a211..177b2855f797 100644
--- a/tools/perf/arch/arm64/include/dwarf-regs-table.h
+++ b/tools/perf/arch/arm64/include/dwarf-regs-table.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifdef DEFINE_DWARF_REGSTR_TABLE 2#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */ 3/* This is included in perf/util/dwarf-regs.c */
3 4
diff --git a/tools/perf/arch/arm64/include/perf_regs.h b/tools/perf/arch/arm64/include/perf_regs.h
index 4e5af27e3fbf..baaa5e64a3fb 100644
--- a/tools/perf/arch/arm64/include/perf_regs.h
+++ b/tools/perf/arch/arm64/include/perf_regs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef ARCH_PERF_REGS_H 2#ifndef ARCH_PERF_REGS_H
2#define ARCH_PERF_REGS_H 3#define ARCH_PERF_REGS_H
3 4
diff --git a/tools/perf/arch/arm64/tests/dwarf-unwind.c b/tools/perf/arch/arm64/tests/dwarf-unwind.c
index cf04a4c91c59..e907f0f4c20c 100644
--- a/tools/perf/arch/arm64/tests/dwarf-unwind.c
+++ b/tools/perf/arch/arm64/tests/dwarf-unwind.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <string.h> 2#include <string.h>
2#include "perf_regs.h" 3#include "perf_regs.h"
3#include "thread.h" 4#include "thread.h"
diff --git a/tools/perf/arch/arm64/tests/regs_load.S b/tools/perf/arch/arm64/tests/regs_load.S
index 025b46e579a6..07042511dca9 100644
--- a/tools/perf/arch/arm64/tests/regs_load.S
+++ b/tools/perf/arch/arm64/tests/regs_load.S
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include <linux/linkage.h> 2#include <linux/linkage.h>
2 3
3.text 4.text
diff --git a/tools/perf/arch/arm64/util/unwind-libunwind.c b/tools/perf/arch/arm64/util/unwind-libunwind.c
index b415dfdbccca..002520d4036b 100644
--- a/tools/perf/arch/arm64/util/unwind-libunwind.c
+++ b/tools/perf/arch/arm64/util/unwind-libunwind.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2 3
3#ifndef REMOTE_UNWIND_LIBUNWIND 4#ifndef REMOTE_UNWIND_LIBUNWIND
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index 6b40e9f01740..8c0cfeb55f8e 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <sys/utsname.h> 3#include <sys/utsname.h>
3#include "common.h" 4#include "common.h"
diff --git a/tools/perf/arch/common.h b/tools/perf/arch/common.h
index 6b01c736b7d9..a1546509ad24 100644
--- a/tools/perf/arch/common.h
+++ b/tools/perf/arch/common.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef ARCH_PERF_COMMON_H 2#ifndef ARCH_PERF_COMMON_H
2#define ARCH_PERF_COMMON_H 3#define ARCH_PERF_COMMON_H
3 4
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index cc3930904d68..42dab7c8f508 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1ifndef NO_DWARF 2ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 3PERF_HAVE_DWARF_REGS := 1
3endif 4endif
diff --git a/tools/perf/arch/powerpc/annotate/instructions.c b/tools/perf/arch/powerpc/annotate/instructions.c
index 3c4004db81b9..a3f423c27cae 100644
--- a/tools/perf/arch/powerpc/annotate/instructions.c
+++ b/tools/perf/arch/powerpc/annotate/instructions.c
@@ -1,3 +1,6 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/compiler.h>
3
1static struct ins_ops *powerpc__associate_instruction_ops(struct arch *arch, const char *name) 4static struct ins_ops *powerpc__associate_instruction_ops(struct arch *arch, const char *name)
2{ 5{
3 int i; 6 int i;
@@ -46,7 +49,7 @@ static struct ins_ops *powerpc__associate_instruction_ops(struct arch *arch, con
46 return ops; 49 return ops;
47} 50}
48 51
49static int powerpc__annotate_init(struct arch *arch) 52static int powerpc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
50{ 53{
51 if (!arch->initialized) { 54 if (!arch->initialized) {
52 arch->initialized = true; 55 arch->initialized = true;
diff --git a/tools/perf/arch/powerpc/include/arch-tests.h b/tools/perf/arch/powerpc/include/arch-tests.h
index 84d8dedef2ed..1c7be75cbc78 100644
--- a/tools/perf/arch/powerpc/include/arch-tests.h
+++ b/tools/perf/arch/powerpc/include/arch-tests.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef ARCH_TESTS_H 2#ifndef ARCH_TESTS_H
2#define ARCH_TESTS_H 3#define ARCH_TESTS_H
3 4
diff --git a/tools/perf/arch/powerpc/include/dwarf-regs-table.h b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
index db4730f5585c..66dc015a733d 100644
--- a/tools/perf/arch/powerpc/include/dwarf-regs-table.h
+++ b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifdef DEFINE_DWARF_REGSTR_TABLE 2#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */ 3/* This is included in perf/util/dwarf-regs.c */
3 4
diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h
index c12f4e804f66..00e37b106913 100644
--- a/tools/perf/arch/powerpc/include/perf_regs.h
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef ARCH_PERF_REGS_H 2#ifndef ARCH_PERF_REGS_H
2#define ARCH_PERF_REGS_H 3#define ARCH_PERF_REGS_H
3 4
diff --git a/tools/perf/arch/powerpc/tests/arch-tests.c b/tools/perf/arch/powerpc/tests/arch-tests.c
index e24f46241f40..8c3fbd4af817 100644
--- a/tools/perf/arch/powerpc/tests/arch-tests.c
+++ b/tools/perf/arch/powerpc/tests/arch-tests.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <string.h> 2#include <string.h>
2#include "tests/tests.h" 3#include "tests/tests.h"
3#include "arch-tests.h" 4#include "arch-tests.h"
diff --git a/tools/perf/arch/powerpc/tests/dwarf-unwind.c b/tools/perf/arch/powerpc/tests/dwarf-unwind.c
index 0bac3137ccbd..30cbbd6d5be0 100644
--- a/tools/perf/arch/powerpc/tests/dwarf-unwind.c
+++ b/tools/perf/arch/powerpc/tests/dwarf-unwind.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <string.h> 2#include <string.h>
2#include "perf_regs.h" 3#include "perf_regs.h"
3#include "thread.h" 4#include "thread.h"
diff --git a/tools/perf/arch/powerpc/tests/regs_load.S b/tools/perf/arch/powerpc/tests/regs_load.S
index d76c9a32f327..36a20b0033f9 100644
--- a/tools/perf/arch/powerpc/tests/regs_load.S
+++ b/tools/perf/arch/powerpc/tests/regs_load.S
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include <linux/linkage.h> 2#include <linux/linkage.h>
2 3
3/* Offset is based on macros from arch/powerpc/include/uapi/asm/ptrace.h. */ 4/* Offset is based on macros from arch/powerpc/include/uapi/asm/ptrace.h. */
diff --git a/tools/perf/arch/powerpc/util/book3s_hcalls.h b/tools/perf/arch/powerpc/util/book3s_hcalls.h
index 0dd6b7f2d44f..54cfa0530e86 100644
--- a/tools/perf/arch/powerpc/util/book3s_hcalls.h
+++ b/tools/perf/arch/powerpc/util/book3s_hcalls.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef ARCH_PERF_BOOK3S_HV_HCALLS_H 2#ifndef ARCH_PERF_BOOK3S_HV_HCALLS_H
2#define ARCH_PERF_BOOK3S_HV_HCALLS_H 3#define ARCH_PERF_BOOK3S_HV_HCALLS_H
3 4
diff --git a/tools/perf/arch/powerpc/util/book3s_hv_exits.h b/tools/perf/arch/powerpc/util/book3s_hv_exits.h
index e68ba2da8970..853b95d1e139 100644
--- a/tools/perf/arch/powerpc/util/book3s_hv_exits.h
+++ b/tools/perf/arch/powerpc/util/book3s_hv_exits.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef ARCH_PERF_BOOK3S_HV_EXITS_H 2#ifndef ARCH_PERF_BOOK3S_HV_EXITS_H
2#define ARCH_PERF_BOOK3S_HV_EXITS_H 3#define ARCH_PERF_BOOK3S_HV_EXITS_H
3 4
diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c
index 9aaa6f5a9347..7a4cf80c207a 100644
--- a/tools/perf/arch/powerpc/util/header.c
+++ b/tools/perf/arch/powerpc/util/header.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/types.h> 2#include <sys/types.h>
2#include <unistd.h> 3#include <unistd.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/perf/arch/powerpc/util/kvm-stat.c b/tools/perf/arch/powerpc/util/kvm-stat.c
index 249723f0e6a9..596ad6aedaac 100644
--- a/tools/perf/arch/powerpc/util/kvm-stat.c
+++ b/tools/perf/arch/powerpc/util/kvm-stat.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include "util/kvm-stat.h" 3#include "util/kvm-stat.h"
3#include "util/parse-events.h" 4#include "util/parse-events.h"
diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c
index f860dc411f69..ec50939b0418 100644
--- a/tools/perf/arch/powerpc/util/perf_regs.c
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <string.h> 3#include <string.h>
3#include <regex.h> 4#include <regex.h>
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index bf9a2594572c..9c4e23d8c8ce 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -126,7 +126,7 @@ void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
126 struct rb_node *tmp; 126 struct rb_node *tmp;
127 int i = 0; 127 int i = 0;
128 128
129 map = get_target_map(pev->target, pev->uprobes); 129 map = get_target_map(pev->target, pev->nsi, pev->uprobes);
130 if (!map || map__load(map) < 0) 130 if (!map || map__load(map) < 0)
131 return; 131 return;
132 132
diff --git a/tools/perf/arch/powerpc/util/unwind-libdw.c b/tools/perf/arch/powerpc/util/unwind-libdw.c
index 3a24b3c43273..7a1f05ef2fc0 100644
--- a/tools/perf/arch/powerpc/util/unwind-libdw.c
+++ b/tools/perf/arch/powerpc/util/unwind-libdw.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <elfutils/libdwfl.h> 2#include <elfutils/libdwfl.h>
2#include "../../util/unwind-libdw.h" 3#include "../../util/unwind-libdw.h"
3#include "../../util/perf_regs.h" 4#include "../../util/perf_regs.h"
diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
index 745b4b1b8b21..e0e466c650df 100644
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ b/tools/perf/arch/s390/annotate/instructions.c
@@ -1,3 +1,6 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/compiler.h>
3
1static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name) 4static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name)
2{ 5{
3 struct ins_ops *ops = NULL; 6 struct ins_ops *ops = NULL;
@@ -19,7 +22,7 @@ static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *na
19 return ops; 22 return ops;
20} 23}
21 24
22static int s390__annotate_init(struct arch *arch) 25static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
23{ 26{
24 if (!arch->initialized) { 27 if (!arch->initialized) {
25 arch->initialized = true; 28 arch->initialized = true;
diff --git a/tools/perf/arch/s390/include/dwarf-regs-table.h b/tools/perf/arch/s390/include/dwarf-regs-table.h
index 9da74a933bd6..671553525f41 100644
--- a/tools/perf/arch/s390/include/dwarf-regs-table.h
+++ b/tools/perf/arch/s390/include/dwarf-regs-table.h
@@ -1,8 +1,72 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE 1/* SPDX-License-Identifier: GPL-2.0 */
2/* This is included in perf/util/dwarf-regs.c */ 2#ifndef S390_DWARF_REGS_TABLE_H
3#define S390_DWARF_REGS_TABLE_H
3 4
4static const char * const s390_regstr_tbl[] = { 5#define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg
6
7/*
8 * For reference, see DWARF register mapping:
9 * http://refspecs.linuxfoundation.org/ELF/zSeries/lzsabi0_s390/x1542.html
10 */
11static const char * const s390_dwarf_regs[] = {
5 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", 12 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
6 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", 13 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
14 REG_DWARFNUM_NAME(f0, 16),
15 REG_DWARFNUM_NAME(f1, 20),
16 REG_DWARFNUM_NAME(f2, 17),
17 REG_DWARFNUM_NAME(f3, 21),
18 REG_DWARFNUM_NAME(f4, 18),
19 REG_DWARFNUM_NAME(f5, 22),
20 REG_DWARFNUM_NAME(f6, 19),
21 REG_DWARFNUM_NAME(f7, 23),
22 REG_DWARFNUM_NAME(f8, 24),
23 REG_DWARFNUM_NAME(f9, 28),
24 REG_DWARFNUM_NAME(f10, 25),
25 REG_DWARFNUM_NAME(f11, 29),
26 REG_DWARFNUM_NAME(f12, 26),
27 REG_DWARFNUM_NAME(f13, 30),
28 REG_DWARFNUM_NAME(f14, 27),
29 REG_DWARFNUM_NAME(f15, 31),
30 REG_DWARFNUM_NAME(c0, 32),
31 REG_DWARFNUM_NAME(c1, 33),
32 REG_DWARFNUM_NAME(c2, 34),
33 REG_DWARFNUM_NAME(c3, 35),
34 REG_DWARFNUM_NAME(c4, 36),
35 REG_DWARFNUM_NAME(c5, 37),
36 REG_DWARFNUM_NAME(c6, 38),
37 REG_DWARFNUM_NAME(c7, 39),
38 REG_DWARFNUM_NAME(c8, 40),
39 REG_DWARFNUM_NAME(c9, 41),
40 REG_DWARFNUM_NAME(c10, 42),
41 REG_DWARFNUM_NAME(c11, 43),
42 REG_DWARFNUM_NAME(c12, 44),
43 REG_DWARFNUM_NAME(c13, 45),
44 REG_DWARFNUM_NAME(c14, 46),
45 REG_DWARFNUM_NAME(c15, 47),
46 REG_DWARFNUM_NAME(a0, 48),
47 REG_DWARFNUM_NAME(a1, 49),
48 REG_DWARFNUM_NAME(a2, 50),
49 REG_DWARFNUM_NAME(a3, 51),
50 REG_DWARFNUM_NAME(a4, 52),
51 REG_DWARFNUM_NAME(a5, 53),
52 REG_DWARFNUM_NAME(a6, 54),
53 REG_DWARFNUM_NAME(a7, 55),
54 REG_DWARFNUM_NAME(a8, 56),
55 REG_DWARFNUM_NAME(a9, 57),
56 REG_DWARFNUM_NAME(a10, 58),
57 REG_DWARFNUM_NAME(a11, 59),
58 REG_DWARFNUM_NAME(a12, 60),
59 REG_DWARFNUM_NAME(a13, 61),
60 REG_DWARFNUM_NAME(a14, 62),
61 REG_DWARFNUM_NAME(a15, 63),
62 REG_DWARFNUM_NAME(pswm, 64),
63 REG_DWARFNUM_NAME(pswa, 65),
7}; 64};
8#endif 65
66#ifdef DEFINE_DWARF_REGSTR_TABLE
67/* This is included in perf/util/dwarf-regs.c */
68
69#define s390_regstr_tbl s390_dwarf_regs
70
71#endif /* DEFINE_DWARF_REGSTR_TABLE */
72#endif /* S390_DWARF_REGS_TABLE_H */
diff --git a/tools/perf/arch/s390/include/perf_regs.h b/tools/perf/arch/s390/include/perf_regs.h
new file mode 100644
index 000000000000..d2df54a6bc5a
--- /dev/null
+++ b/tools/perf/arch/s390/include/perf_regs.h
@@ -0,0 +1,95 @@
1#ifndef ARCH_PERF_REGS_H
2#define ARCH_PERF_REGS_H
3
4#include <stdlib.h>
5#include <linux/types.h>
6#include <../../../../arch/s390/include/uapi/asm/perf_regs.h>
7
8void perf_regs_load(u64 *regs);
9
10#define PERF_REGS_MASK ((1ULL << PERF_REG_S390_MAX) - 1)
11#define PERF_REGS_MAX PERF_REG_S390_MAX
12#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
13
14#define PERF_REG_IP PERF_REG_S390_PC
15#define PERF_REG_SP PERF_REG_S390_R15
16
17static inline const char *perf_reg_name(int id)
18{
19 switch (id) {
20 case PERF_REG_S390_R0:
21 return "R0";
22 case PERF_REG_S390_R1:
23 return "R1";
24 case PERF_REG_S390_R2:
25 return "R2";
26 case PERF_REG_S390_R3:
27 return "R3";
28 case PERF_REG_S390_R4:
29 return "R4";
30 case PERF_REG_S390_R5:
31 return "R5";
32 case PERF_REG_S390_R6:
33 return "R6";
34 case PERF_REG_S390_R7:
35 return "R7";
36 case PERF_REG_S390_R8:
37 return "R8";
38 case PERF_REG_S390_R9:
39 return "R9";
40 case PERF_REG_S390_R10:
41 return "R10";
42 case PERF_REG_S390_R11:
43 return "R11";
44 case PERF_REG_S390_R12:
45 return "R12";
46 case PERF_REG_S390_R13:
47 return "R13";
48 case PERF_REG_S390_R14:
49 return "R14";
50 case PERF_REG_S390_R15:
51 return "R15";
52 case PERF_REG_S390_FP0:
53 return "FP0";
54 case PERF_REG_S390_FP1:
55 return "FP1";
56 case PERF_REG_S390_FP2:
57 return "FP2";
58 case PERF_REG_S390_FP3:
59 return "FP3";
60 case PERF_REG_S390_FP4:
61 return "FP4";
62 case PERF_REG_S390_FP5:
63 return "FP5";
64 case PERF_REG_S390_FP6:
65 return "FP6";
66 case PERF_REG_S390_FP7:
67 return "FP7";
68 case PERF_REG_S390_FP8:
69 return "FP8";
70 case PERF_REG_S390_FP9:
71 return "FP9";
72 case PERF_REG_S390_FP10:
73 return "FP10";
74 case PERF_REG_S390_FP11:
75 return "FP11";
76 case PERF_REG_S390_FP12:
77 return "FP12";
78 case PERF_REG_S390_FP13:
79 return "FP13";
80 case PERF_REG_S390_FP14:
81 return "FP14";
82 case PERF_REG_S390_FP15:
83 return "FP15";
84 case PERF_REG_S390_MASK:
85 return "MASK";
86 case PERF_REG_S390_PC:
87 return "PC";
88 default:
89 return NULL;
90 }
91
92 return NULL;
93}
94
95#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/s390/util/Build b/tools/perf/arch/s390/util/Build
index 5bd7b9260cc0..4a233683c684 100644
--- a/tools/perf/arch/s390/util/Build
+++ b/tools/perf/arch/s390/util/Build
@@ -2,5 +2,8 @@ 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
5libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
5 6
6libperf-y += machine.o 7libperf-y += machine.o
8
9libperf-$(CONFIG_AUXTRACE) += auxtrace.o
diff --git a/tools/perf/arch/s390/util/auxtrace.c b/tools/perf/arch/s390/util/auxtrace.c
new file mode 100644
index 000000000000..6cb48e4cffd9
--- /dev/null
+++ b/tools/perf/arch/s390/util/auxtrace.c
@@ -0,0 +1,118 @@
1#include <stdbool.h>
2#include <linux/kernel.h>
3#include <linux/types.h>
4#include <linux/bitops.h>
5#include <linux/log2.h>
6
7#include "../../util/evlist.h"
8#include "../../util/auxtrace.h"
9#include "../../util/evsel.h"
10
11#define PERF_EVENT_CPUM_SF 0xB0000 /* Event: Basic-sampling */
12#define PERF_EVENT_CPUM_SF_DIAG 0xBD000 /* Event: Combined-sampling */
13#define DEFAULT_AUX_PAGES 128
14#define DEFAULT_FREQ 4000
15
16static void cpumsf_free(struct auxtrace_record *itr)
17{
18 free(itr);
19}
20
21static size_t cpumsf_info_priv_size(struct auxtrace_record *itr __maybe_unused,
22 struct perf_evlist *evlist __maybe_unused)
23{
24 return 0;
25}
26
27static int
28cpumsf_info_fill(struct auxtrace_record *itr __maybe_unused,
29 struct perf_session *session __maybe_unused,
30 struct auxtrace_info_event *auxtrace_info __maybe_unused,
31 size_t priv_size __maybe_unused)
32{
33 return 0;
34}
35
36static unsigned long
37cpumsf_reference(struct auxtrace_record *itr __maybe_unused)
38{
39 return 0;
40}
41
42static int
43cpumsf_recording_options(struct auxtrace_record *ar __maybe_unused,
44 struct perf_evlist *evlist __maybe_unused,
45 struct record_opts *opts)
46{
47 unsigned int factor = 1;
48 unsigned int pages;
49
50 opts->full_auxtrace = true;
51
52 /*
53 * The AUX buffer size should be set properly to avoid
54 * overflow of samples if it is not set explicitly.
55 * DEFAULT_AUX_PAGES is an proper size when sampling frequency
56 * is DEFAULT_FREQ. It is expected to hold about 1/2 second
57 * of sampling data. The size used for AUX buffer will scale
58 * according to the specified frequency and DEFAULT_FREQ.
59 */
60 if (!opts->auxtrace_mmap_pages) {
61 if (opts->user_freq != UINT_MAX)
62 factor = (opts->user_freq + DEFAULT_FREQ
63 - 1) / DEFAULT_FREQ;
64 pages = DEFAULT_AUX_PAGES * factor;
65 opts->auxtrace_mmap_pages = roundup_pow_of_two(pages);
66 }
67
68 return 0;
69}
70
71static int
72cpumsf_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused,
73 struct record_opts *opts __maybe_unused,
74 const char *str __maybe_unused)
75{
76 return 0;
77}
78
79/*
80 * auxtrace_record__init is called when perf record
81 * check if the event really need auxtrace
82 */
83struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
84 int *err)
85{
86 struct auxtrace_record *aux;
87 struct perf_evsel *pos;
88 int diagnose = 0;
89
90 if (evlist->nr_entries == 0)
91 return NULL;
92
93 evlist__for_each_entry(evlist, pos) {
94 if (pos->attr.config == PERF_EVENT_CPUM_SF_DIAG) {
95 diagnose = 1;
96 break;
97 }
98 }
99
100 if (!diagnose)
101 return NULL;
102
103 /* sampling in diagnose mode. alloc aux buffer */
104 aux = zalloc(sizeof(*aux));
105 if (aux == NULL) {
106 *err = -ENOMEM;
107 return NULL;
108 }
109
110 aux->parse_snapshot_options = cpumsf_parse_snapshot_options;
111 aux->recording_options = cpumsf_recording_options;
112 aux->info_priv_size = cpumsf_info_priv_size;
113 aux->info_fill = cpumsf_info_fill;
114 aux->free = cpumsf_free;
115 aux->reference = cpumsf_reference;
116
117 return aux;
118}
diff --git a/tools/perf/arch/s390/util/dwarf-regs.c b/tools/perf/arch/s390/util/dwarf-regs.c
index 0469df02ee62..f47576ce13ea 100644
--- a/tools/perf/arch/s390/util/dwarf-regs.c
+++ b/tools/perf/arch/s390/util/dwarf-regs.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Mapping of DWARF debug register numbers into register names. 3 * Mapping of DWARF debug register numbers into register names.
3 * 4 *
@@ -8,15 +9,10 @@
8 9
9#include <stddef.h> 10#include <stddef.h>
10#include <dwarf-regs.h> 11#include <dwarf-regs.h>
11 12#include <linux/kernel.h>
12#define NUM_GPRS 16 13#include "dwarf-regs-table.h"
13
14static const char *gpr_names[NUM_GPRS] = {
15 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
16 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
17};
18 14
19const char *get_arch_regstr(unsigned int n) 15const char *get_arch_regstr(unsigned int n)
20{ 16{
21 return (n >= NUM_GPRS) ? NULL : gpr_names[n]; 17 return (n >= ARRAY_SIZE(s390_dwarf_regs)) ? NULL : s390_dwarf_regs[n];
22} 18}
diff --git a/tools/perf/arch/s390/util/machine.c b/tools/perf/arch/s390/util/machine.c
index b9a95a1a8e69..0b2054007314 100644
--- a/tools/perf/arch/s390/util/machine.c
+++ b/tools/perf/arch/s390/util/machine.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <unistd.h> 2#include <unistd.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <string.h> 4#include <string.h>
diff --git a/tools/perf/arch/s390/util/unwind-libdw.c b/tools/perf/arch/s390/util/unwind-libdw.c
new file mode 100644
index 000000000000..387c698cdd1b
--- /dev/null
+++ b/tools/perf/arch/s390/util/unwind-libdw.c
@@ -0,0 +1,63 @@
1#include <linux/kernel.h>
2#include <elfutils/libdwfl.h>
3#include "../../util/unwind-libdw.h"
4#include "../../util/perf_regs.h"
5#include "../../util/event.h"
6#include "dwarf-regs-table.h"
7
8
9bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
10{
11 struct unwind_info *ui = arg;
12 struct regs_dump *user_regs = &ui->sample->user_regs;
13 Dwarf_Word dwarf_regs[ARRAY_SIZE(s390_dwarf_regs)];
14
15#define REG(r) ({ \
16 Dwarf_Word val = 0; \
17 perf_reg_value(&val, user_regs, PERF_REG_S390_##r); \
18 val; \
19})
20 /*
21 * For DWARF register mapping details,
22 * see also perf/arch/s390/include/dwarf-regs-table.h
23 */
24 dwarf_regs[0] = REG(R0);
25 dwarf_regs[1] = REG(R1);
26 dwarf_regs[2] = REG(R2);
27 dwarf_regs[3] = REG(R3);
28 dwarf_regs[4] = REG(R4);
29 dwarf_regs[5] = REG(R5);
30 dwarf_regs[6] = REG(R6);
31 dwarf_regs[7] = REG(R7);
32 dwarf_regs[8] = REG(R8);
33 dwarf_regs[9] = REG(R9);
34 dwarf_regs[10] = REG(R10);
35 dwarf_regs[11] = REG(R11);
36 dwarf_regs[12] = REG(R12);
37 dwarf_regs[13] = REG(R13);
38 dwarf_regs[14] = REG(R14);
39 dwarf_regs[15] = REG(R15);
40
41 dwarf_regs[16] = REG(FP0);
42 dwarf_regs[17] = REG(FP2);
43 dwarf_regs[18] = REG(FP4);
44 dwarf_regs[19] = REG(FP6);
45 dwarf_regs[20] = REG(FP1);
46 dwarf_regs[21] = REG(FP3);
47 dwarf_regs[22] = REG(FP5);
48 dwarf_regs[23] = REG(FP7);
49 dwarf_regs[24] = REG(FP8);
50 dwarf_regs[25] = REG(FP10);
51 dwarf_regs[26] = REG(FP12);
52 dwarf_regs[27] = REG(FP14);
53 dwarf_regs[28] = REG(FP9);
54 dwarf_regs[29] = REG(FP11);
55 dwarf_regs[30] = REG(FP13);
56 dwarf_regs[31] = REG(FP15);
57
58 dwarf_regs[64] = REG(MASK);
59 dwarf_regs[65] = REG(PC);
60
61 dwfl_thread_state_register_pc(thread, dwarf_regs[65]);
62 return dwfl_thread_state_registers(thread, 0, 32, dwarf_regs);
63}
diff --git a/tools/perf/arch/sh/include/dwarf-regs-table.h b/tools/perf/arch/sh/include/dwarf-regs-table.h
index 3a2deaf3dab4..900e69619970 100644
--- a/tools/perf/arch/sh/include/dwarf-regs-table.h
+++ b/tools/perf/arch/sh/include/dwarf-regs-table.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifdef DEFINE_DWARF_REGSTR_TABLE 2#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */ 3/* This is included in perf/util/dwarf-regs.c */
3 4
diff --git a/tools/perf/arch/sparc/include/dwarf-regs-table.h b/tools/perf/arch/sparc/include/dwarf-regs-table.h
index 12c07619002c..35ede84a6b0d 100644
--- a/tools/perf/arch/sparc/include/dwarf-regs-table.h
+++ b/tools/perf/arch/sparc/include/dwarf-regs-table.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifdef DEFINE_DWARF_REGSTR_TABLE 2#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */ 3/* This is included in perf/util/dwarf-regs.c */
3 4
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 6c9211b18ec0..d74eaa7aa927 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1ifndef NO_DWARF 2ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 3PERF_HAVE_DWARF_REGS := 1
3endif 4endif
@@ -20,7 +21,7 @@ _dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
20$(header): $(sys)/syscall_64.tbl $(systbl) 21$(header): $(sys)/syscall_64.tbl $(systbl)
21 @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \ 22 @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
22 (diff -B arch/x86/entry/syscalls/syscall_64.tbl ../../arch/x86/entry/syscalls/syscall_64.tbl >/dev/null) \ 23 (diff -B arch/x86/entry/syscalls/syscall_64.tbl ../../arch/x86/entry/syscalls/syscall_64.tbl >/dev/null) \
23 || echo "Warning: x86_64's syscall_64.tbl differs from kernel" >&2 )) || true 24 || echo "Warning: Kernel ABI header at 'tools/arch/x86/entry/syscalls/syscall_64.tbl' differs from latest version at 'arch/x86/entry/syscalls/syscall_64.tbl'" >&2 )) || true
24 $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@ 25 $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@
25 26
26clean:: 27clean::
diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c
index c1625f256df3..5bd1ba8c0282 100644
--- a/tools/perf/arch/x86/annotate/instructions.c
+++ b/tools/perf/arch/x86/annotate/instructions.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1static struct ins x86__instructions[] = { 2static struct ins x86__instructions[] = {
2 { .name = "add", .ops = &mov_ops, }, 3 { .name = "add", .ops = &mov_ops, },
3 { .name = "addl", .ops = &mov_ops, }, 4 { .name = "addl", .ops = &mov_ops, },
@@ -76,3 +77,63 @@ static struct ins x86__instructions[] = {
76 { .name = "xbeginq", .ops = &jump_ops, }, 77 { .name = "xbeginq", .ops = &jump_ops, },
77 { .name = "retq", .ops = &ret_ops, }, 78 { .name = "retq", .ops = &ret_ops, },
78}; 79};
80
81static bool x86__ins_is_fused(struct arch *arch, const char *ins1,
82 const char *ins2)
83{
84 if (arch->family != 6 || arch->model < 0x1e || strstr(ins2, "jmp"))
85 return false;
86
87 if (arch->model == 0x1e) {
88 /* Nehalem */
89 if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
90 strstr(ins1, "test")) {
91 return true;
92 }
93 } else {
94 /* Newer platform */
95 if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
96 strstr(ins1, "test") ||
97 strstr(ins1, "add") ||
98 strstr(ins1, "sub") ||
99 strstr(ins1, "and") ||
100 strstr(ins1, "inc") ||
101 strstr(ins1, "dec")) {
102 return true;
103 }
104 }
105
106 return false;
107}
108
109static int x86__cpuid_parse(struct arch *arch, char *cpuid)
110{
111 unsigned int family, model, stepping;
112 int ret;
113
114 /*
115 * cpuid = "GenuineIntel,family,model,stepping"
116 */
117 ret = sscanf(cpuid, "%*[^,],%u,%u,%u", &family, &model, &stepping);
118 if (ret == 3) {
119 arch->family = family;
120 arch->model = model;
121 return 0;
122 }
123
124 return -1;
125}
126
127static int x86__annotate_init(struct arch *arch, char *cpuid)
128{
129 int err = 0;
130
131 if (arch->initialized)
132 return 0;
133
134 if (cpuid)
135 err = x86__cpuid_parse(arch, cpuid);
136
137 arch->initialized = true;
138 return err;
139}
diff --git a/tools/perf/arch/x86/entry/syscalls/syscalltbl.sh b/tools/perf/arch/x86/entry/syscalls/syscalltbl.sh
index 49a18b9ad9cf..029a72c20b19 100755
--- a/tools/perf/arch/x86/entry/syscalls/syscalltbl.sh
+++ b/tools/perf/arch/x86/entry/syscalls/syscalltbl.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2 3
3in="$1" 4in="$1"
4arch="$2" 5arch="$2"
diff --git a/tools/perf/arch/x86/include/arch-tests.h b/tools/perf/arch/x86/include/arch-tests.h
index b48de2f5813c..c1bd979b957b 100644
--- a/tools/perf/arch/x86/include/arch-tests.h
+++ b/tools/perf/arch/x86/include/arch-tests.h
@@ -1,11 +1,14 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef ARCH_TESTS_H 2#ifndef ARCH_TESTS_H
2#define ARCH_TESTS_H 3#define ARCH_TESTS_H
3 4
5#include <linux/compiler.h>
6struct test;
7
4/* Tests */ 8/* Tests */
5int test__rdpmc(int subtest); 9int test__rdpmc(struct test *test __maybe_unused, int subtest);
6int test__perf_time_to_tsc(int subtest); 10int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest);
7int test__insn_x86(int subtest); 11int test__insn_x86(struct test *test __maybe_unused, int subtest);
8int test__intel_cqm_count_nmi_context(int subtest);
9 12
10#ifdef HAVE_DWARF_UNWIND_SUPPORT 13#ifdef HAVE_DWARF_UNWIND_SUPPORT
11struct thread; 14struct thread;
diff --git a/tools/perf/arch/x86/include/dwarf-regs-table.h b/tools/perf/arch/x86/include/dwarf-regs-table.h
index 9b5e5cbb4209..b9bd5dc9d4c0 100644
--- a/tools/perf/arch/x86/include/dwarf-regs-table.h
+++ b/tools/perf/arch/x86/include/dwarf-regs-table.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifdef DEFINE_DWARF_REGSTR_TABLE 2#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */ 3/* This is included in perf/util/dwarf-regs.c */
3 4
diff --git a/tools/perf/arch/x86/include/perf_regs.h b/tools/perf/arch/x86/include/perf_regs.h
index 7df517acfef8..7f6d538f8a89 100644
--- a/tools/perf/arch/x86/include/perf_regs.h
+++ b/tools/perf/arch/x86/include/perf_regs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef ARCH_PERF_REGS_H 2#ifndef ARCH_PERF_REGS_H
2#define ARCH_PERF_REGS_H 3#define ARCH_PERF_REGS_H
3 4
diff --git a/tools/perf/arch/x86/tests/Build b/tools/perf/arch/x86/tests/Build
index cbb7e978166b..8e2c5a38c3b9 100644
--- a/tools/perf/arch/x86/tests/Build
+++ b/tools/perf/arch/x86/tests/Build
@@ -5,4 +5,3 @@ libperf-y += arch-tests.o
5libperf-y += rdpmc.o 5libperf-y += rdpmc.o
6libperf-y += perf-time-to-tsc.o 6libperf-y += perf-time-to-tsc.o
7libperf-$(CONFIG_AUXTRACE) += insn-x86.o 7libperf-$(CONFIG_AUXTRACE) += insn-x86.o
8libperf-y += intel-cqm.o
diff --git a/tools/perf/arch/x86/tests/arch-tests.c b/tools/perf/arch/x86/tests/arch-tests.c
index 99d66191e56c..cc1802ff5410 100644
--- a/tools/perf/arch/x86/tests/arch-tests.c
+++ b/tools/perf/arch/x86/tests/arch-tests.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <string.h> 2#include <string.h>
2#include "tests/tests.h" 3#include "tests/tests.h"
3#include "arch-tests.h" 4#include "arch-tests.h"
@@ -24,10 +25,6 @@ struct test arch_tests[] = {
24 }, 25 },
25#endif 26#endif
26 { 27 {
27 .desc = "Intel cqm nmi context read",
28 .func = test__intel_cqm_count_nmi_context,
29 },
30 {
31 .func = NULL, 28 .func = NULL,
32 }, 29 },
33 30
diff --git a/tools/perf/arch/x86/tests/dwarf-unwind.c b/tools/perf/arch/x86/tests/dwarf-unwind.c
index 7f209ce827bf..95036c7a59e8 100644
--- a/tools/perf/arch/x86/tests/dwarf-unwind.c
+++ b/tools/perf/arch/x86/tests/dwarf-unwind.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <string.h> 2#include <string.h>
2#include "perf_regs.h" 3#include "perf_regs.h"
3#include "thread.h" 4#include "thread.h"
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 3cbf6fad169f..fab3c6de73fa 100644
--- a/tools/perf/arch/x86/tests/insn-x86-dat-32.c
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-32.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Generated by gen-insn-x86-dat.sh and gen-insn-x86-dat.awk 3 * Generated by gen-insn-x86-dat.sh and gen-insn-x86-dat.awk
3 * from insn-x86-dat-src.c for inclusion by insn-x86.c 4 * from insn-x86-dat-src.c for inclusion by insn-x86.c
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 aa512fa944dd..c57f34603b9b 100644
--- a/tools/perf/arch/x86/tests/insn-x86-dat-64.c
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-64.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Generated by gen-insn-x86-dat.sh and gen-insn-x86-dat.awk 3 * Generated by gen-insn-x86-dat.sh and gen-insn-x86-dat.awk
3 * from insn-x86-dat-src.c for inclusion by insn-x86.c 4 * from insn-x86-dat-src.c for inclusion by insn-x86.c
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 6cdb65d25b79..891415b10984 100644
--- a/tools/perf/arch/x86/tests/insn-x86-dat-src.c
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-src.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * This file contains instructions for testing by the test titled: 3 * This file contains instructions for testing by the test titled:
3 * 4 *
diff --git a/tools/perf/arch/x86/tests/insn-x86.c b/tools/perf/arch/x86/tests/insn-x86.c
index 08d9b2bc185c..a5d24ae5810d 100644
--- a/tools/perf/arch/x86/tests/insn-x86.c
+++ b/tools/perf/arch/x86/tests/insn-x86.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/types.h> 2#include <linux/types.h>
2 3
3#include "debug.h" 4#include "debug.h"
@@ -171,7 +172,7 @@ static int test_data_set(struct test_data *dat_set, int x86_64)
171 * verbose (-v) option to see all the instructions and whether or not they 172 * verbose (-v) option to see all the instructions and whether or not they
172 * decoded successfuly. 173 * decoded successfuly.
173 */ 174 */
174int test__insn_x86(int subtest __maybe_unused) 175int test__insn_x86(struct test *test __maybe_unused, int subtest __maybe_unused)
175{ 176{
176 int ret = 0; 177 int ret = 0;
177 178
diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c
index f9713a71d77e..90a4a8c58a62 100644
--- a/tools/perf/arch/x86/tests/intel-cqm.c
+++ b/tools/perf/arch/x86/tests/intel-cqm.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "tests/tests.h" 2#include "tests/tests.h"
2#include "perf.h" 3#include "perf.h"
3#include "cloexec.h" 4#include "cloexec.h"
@@ -36,7 +37,7 @@ static pid_t spawn(void)
36 * the last read counter value to avoid triggering a WARN_ON_ONCE() in 37 * the last read counter value to avoid triggering a WARN_ON_ONCE() in
37 * smp_call_function_many() caused by sending IPIs from NMI context. 38 * smp_call_function_many() caused by sending IPIs from NMI context.
38 */ 39 */
39int test__intel_cqm_count_nmi_context(int subtest __maybe_unused) 40int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, int subtest __maybe_unused)
40{ 41{
41 struct perf_evlist *evlist = NULL; 42 struct perf_evlist *evlist = NULL;
42 struct perf_evsel *evsel = NULL; 43 struct perf_evsel *evsel = NULL;
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 e3ae9cff2b67..b59678e8c1e2 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <inttypes.h> 3#include <inttypes.h>
3#include <stdio.h> 4#include <stdio.h>
@@ -37,7 +38,7 @@
37 * %0 is returned, otherwise %-1 is returned. If TSC conversion is not 38 * %0 is returned, otherwise %-1 is returned. If TSC conversion is not
38 * supported then then the test passes but " (not supported)" is printed. 39 * supported then then the test passes but " (not supported)" is printed.
39 */ 40 */
40int test__perf_time_to_tsc(int subtest __maybe_unused) 41int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe_unused)
41{ 42{
42 struct record_opts opts = { 43 struct record_opts opts = {
43 .mmap_pages = UINT_MAX, 44 .mmap_pages = UINT_MAX,
diff --git a/tools/perf/arch/x86/tests/rdpmc.c b/tools/perf/arch/x86/tests/rdpmc.c
index 500cf96db979..7a11f02d6c6c 100644
--- a/tools/perf/arch/x86/tests/rdpmc.c
+++ b/tools/perf/arch/x86/tests/rdpmc.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <unistd.h> 3#include <unistd.h>
3#include <stdlib.h> 4#include <stdlib.h>
@@ -154,7 +155,7 @@ out_close:
154 return 0; 155 return 0;
155} 156}
156 157
157int test__rdpmc(int subtest __maybe_unused) 158int test__rdpmc(struct test *test __maybe_unused, int subtest __maybe_unused)
158{ 159{
159 int status = 0; 160 int status = 0;
160 int wret = 0; 161 int wret = 0;
diff --git a/tools/perf/arch/x86/tests/regs_load.S b/tools/perf/arch/x86/tests/regs_load.S
index 60875d5c556c..bbe5a0d16e51 100644
--- a/tools/perf/arch/x86/tests/regs_load.S
+++ b/tools/perf/arch/x86/tests/regs_load.S
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include <linux/linkage.h> 2#include <linux/linkage.h>
2 3
3#define AX 0 4#define AX 0
diff --git a/tools/perf/arch/x86/util/group.c b/tools/perf/arch/x86/util/group.c
index 37f92aa39a5d..e2f8034b8973 100644
--- a/tools/perf/arch/x86/util/group.c
+++ b/tools/perf/arch/x86/util/group.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include "api/fs/fs.h" 3#include "api/fs/fs.h"
3#include "util/group.h" 4#include "util/group.h"
diff --git a/tools/perf/arch/x86/util/header.c b/tools/perf/arch/x86/util/header.c
index a74a48db26f5..33027c5e6f92 100644
--- a/tools/perf/arch/x86/util/header.c
+++ b/tools/perf/arch/x86/util/header.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/types.h> 2#include <sys/types.h>
2#include <unistd.h> 3#include <unistd.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index 9535be57033f..db0ba8caf5a2 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -701,6 +701,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
701 perf_evsel__set_sample_bit(switch_evsel, TID); 701 perf_evsel__set_sample_bit(switch_evsel, TID);
702 perf_evsel__set_sample_bit(switch_evsel, TIME); 702 perf_evsel__set_sample_bit(switch_evsel, TIME);
703 perf_evsel__set_sample_bit(switch_evsel, CPU); 703 perf_evsel__set_sample_bit(switch_evsel, CPU);
704 perf_evsel__reset_sample_bit(switch_evsel, BRANCH_STACK);
704 705
705 opts->record_switch_events = false; 706 opts->record_switch_events = false;
706 ptr->have_sched_switch = 3; 707 ptr->have_sched_switch = 3;
@@ -752,6 +753,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
752 tracking_evsel->attr.freq = 0; 753 tracking_evsel->attr.freq = 0;
753 tracking_evsel->attr.sample_period = 1; 754 tracking_evsel->attr.sample_period = 1;
754 755
756 tracking_evsel->no_aux_samples = true;
755 if (need_immediate) 757 if (need_immediate)
756 tracking_evsel->immediate = true; 758 tracking_evsel->immediate = true;
757 759
@@ -761,6 +763,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
761 /* And the CPU for switch events */ 763 /* And the CPU for switch events */
762 perf_evsel__set_sample_bit(tracking_evsel, CPU); 764 perf_evsel__set_sample_bit(tracking_evsel, CPU);
763 } 765 }
766 perf_evsel__reset_sample_bit(tracking_evsel, BRANCH_STACK);
764 } 767 }
765 768
766 /* 769 /*
diff --git a/tools/perf/arch/x86/util/kvm-stat.c b/tools/perf/arch/x86/util/kvm-stat.c
index bf817beca0a8..b32409a0e546 100644
--- a/tools/perf/arch/x86/util/kvm-stat.c
+++ b/tools/perf/arch/x86/util/kvm-stat.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include "../../util/kvm-stat.h" 3#include "../../util/kvm-stat.h"
3#include <asm/svm.h> 4#include <asm/svm.h>
diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index f95edebfb716..4b2caf6d48e7 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <string.h> 3#include <string.h>
3#include <regex.h> 4#include <regex.h>
diff --git a/tools/perf/arch/x86/util/pmu.c b/tools/perf/arch/x86/util/pmu.c
index 79fe07158d00..63a74c32ddc5 100644
--- a/tools/perf/arch/x86/util/pmu.c
+++ b/tools/perf/arch/x86/util/pmu.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <string.h> 2#include <string.h>
2 3
3#include <linux/perf_event.h> 4#include <linux/perf_event.h>
diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c
index 2e5567c94e09..06bae7023a51 100644
--- a/tools/perf/arch/x86/util/tsc.c
+++ b/tools/perf/arch/x86/util/tsc.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdbool.h> 2#include <stdbool.h>
2#include <errno.h> 3#include <errno.h>
3 4
diff --git a/tools/perf/arch/x86/util/unwind-libdw.c b/tools/perf/arch/x86/util/unwind-libdw.c
index 38dc9bb2a7c9..fda8f4206ee4 100644
--- a/tools/perf/arch/x86/util/unwind-libdw.c
+++ b/tools/perf/arch/x86/util/unwind-libdw.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <elfutils/libdwfl.h> 2#include <elfutils/libdwfl.h>
2#include "../../util/unwind-libdw.h" 3#include "../../util/unwind-libdw.h"
3#include "../../util/perf_regs.h" 4#include "../../util/perf_regs.h"
diff --git a/tools/perf/arch/x86/util/unwind-libunwind.c b/tools/perf/arch/x86/util/unwind-libunwind.c
index 4f16661cbdbb..9c917f80c906 100644
--- a/tools/perf/arch/x86/util/unwind-libunwind.c
+++ b/tools/perf/arch/x86/util/unwind-libunwind.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1 2
2#ifndef REMOTE_UNWIND_LIBUNWIND 3#ifndef REMOTE_UNWIND_LIBUNWIND
3#include <errno.h> 4#include <errno.h>
diff --git a/tools/perf/arch/xtensa/include/dwarf-regs-table.h b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
index aa0444a33fe6..d7c9f1fb4444 100644
--- a/tools/perf/arch/xtensa/include/dwarf-regs-table.h
+++ b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifdef DEFINE_DWARF_REGSTR_TABLE 2#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */ 3/* This is included in perf/util/dwarf-regs.c */
3 4
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
index 842ab2781cdc..6c9fcd757f31 100644
--- a/tools/perf/bench/bench.h
+++ b/tools/perf/bench/bench.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef BENCH_H 2#ifndef BENCH_H
2#define BENCH_H 3#define BENCH_H
3 4
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index fe16b310097f..58ae6ed8f38b 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright (C) 2013 Davidlohr Bueso <davidlohr@hp.com> 3 * Copyright (C) 2013 Davidlohr Bueso <davidlohr@hp.com>
3 * 4 *
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index 73a1c44ea63c..08653ae8a8c4 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright (C) 2015 Davidlohr Bueso. 3 * Copyright (C) 2015 Davidlohr Bueso.
3 */ 4 */
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 41786cbea24c..1058c194608a 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright (C) 2013 Davidlohr Bueso <davidlohr@hp.com> 3 * Copyright (C) 2013 Davidlohr Bueso <davidlohr@hp.com>
3 * 4 *
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index 4ab12c8e016a..b4732dad9f89 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright (C) 2015 Davidlohr Bueso. 3 * Copyright (C) 2015 Davidlohr Bueso.
3 * 4 *
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 2fa49222ef8d..8c5c0b6b5c97 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright (C) 2013 Davidlohr Bueso <davidlohr@hp.com> 3 * Copyright (C) 2013 Davidlohr Bueso <davidlohr@hp.com>
3 * 4 *
diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index e44fd3239530..db4853f209c7 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Glibc independent futex library for testing kernel functionality. 3 * Glibc independent futex library for testing kernel functionality.
3 * Shamelessly stolen from Darren Hart <dvhltc@us.ibm.com> 4 * Shamelessly stolen from Darren Hart <dvhltc@us.ibm.com>
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
index fbd732b54047..0251dd348124 100644
--- a/tools/perf/bench/mem-functions.c
+++ b/tools/perf/bench/mem-functions.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * mem-memcpy.c 3 * mem-memcpy.c
3 * 4 *
diff --git a/tools/perf/bench/mem-memcpy-arch.h b/tools/perf/bench/mem-memcpy-arch.h
index 5aad2a9408b0..5bcaec5601a8 100644
--- a/tools/perf/bench/mem-memcpy-arch.h
+++ b/tools/perf/bench/mem-memcpy-arch.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1 2
2#ifdef HAVE_ARCH_X86_64_SUPPORT 3#ifdef HAVE_ARCH_X86_64_SUPPORT
3 4
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
index 8c0c1a2770c8..50ae8bd58296 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1 2
2MEMCPY_FN(memcpy_orig, 3MEMCPY_FN(memcpy_orig,
3 "x86-64-unrolled", 4 "x86-64-unrolled",
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S
index f700369bb0f6..b43f8d2a34ec 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm.S
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1 2
2/* Various wrappers to make the kernel .S file build in user-space: */ 3/* Various wrappers to make the kernel .S file build in user-space: */
3 4
diff --git a/tools/perf/bench/mem-memset-arch.h b/tools/perf/bench/mem-memset-arch.h
index 0d15786d9ae3..53f45482663f 100644
--- a/tools/perf/bench/mem-memset-arch.h
+++ b/tools/perf/bench/mem-memset-arch.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1 2
2#ifdef HAVE_ARCH_X86_64_SUPPORT 3#ifdef HAVE_ARCH_X86_64_SUPPORT
3 4
diff --git a/tools/perf/bench/mem-memset-x86-64-asm-def.h b/tools/perf/bench/mem-memset-x86-64-asm-def.h
index f02d028771d9..dac6d2b7c39b 100644
--- a/tools/perf/bench/mem-memset-x86-64-asm-def.h
+++ b/tools/perf/bench/mem-memset-x86-64-asm-def.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1 2
2MEMSET_FN(memset_orig, 3MEMSET_FN(memset_orig,
3 "x86-64-unrolled", 4 "x86-64-unrolled",
diff --git a/tools/perf/bench/mem-memset-x86-64-asm.S b/tools/perf/bench/mem-memset-x86-64-asm.S
index 58407aa24c1b..d550bd526162 100644
--- a/tools/perf/bench/mem-memset-x86-64-asm.S
+++ b/tools/perf/bench/mem-memset-x86-64-asm.S
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#define memset MEMSET /* don't hide glibc's memset() */ 2#define memset MEMSET /* don't hide glibc's memset() */
2#define altinstr_replacement text 3#define altinstr_replacement text
3#define globl p2align 4; .globl 4#define globl p2align 4; .globl
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 469d65b21122..d95fdcc26f4b 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * numa.c 3 * numa.c
3 * 4 *
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index 4f961e74535b..f9d7641ae833 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * 3 *
3 * sched-messaging.c 4 * sched-messaging.c
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index a152737370c5..0591be008f2a 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * 3 *
3 * sched-pipe.c 4 * sched-pipe.c
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 7a5dc7e5c577..f15731a3d438 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * builtin-annotate.c 3 * builtin-annotate.c
3 * 4 *
@@ -177,14 +178,11 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
177 */ 178 */
178 process_branch_stack(sample->branch_stack, al, sample); 179 process_branch_stack(sample->branch_stack, al, sample);
179 180
180 sample->period = 1;
181 sample->weight = 1;
182
183 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); 181 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
184 if (he == NULL) 182 if (he == NULL)
185 return -ENOMEM; 183 return -ENOMEM;
186 184
187 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 185 ret = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr);
188 hists__inc_nr_samples(hists, true); 186 hists__inc_nr_samples(hists, true);
189 return ret; 187 return ret;
190} 188}
@@ -359,7 +357,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
359 } 357 }
360 358
361 if (total_nr_samples == 0) { 359 if (total_nr_samples == 0) {
362 ui__error("The %s file has no samples!\n", session->file->path); 360 ui__error("The %s file has no samples!\n", session->data->file.path);
363 goto out; 361 goto out;
364 } 362 }
365 363
@@ -397,21 +395,23 @@ int cmd_annotate(int argc, const char **argv)
397 .namespaces = perf_event__process_namespaces, 395 .namespaces = perf_event__process_namespaces,
398 .attr = perf_event__process_attr, 396 .attr = perf_event__process_attr,
399 .build_id = perf_event__process_build_id, 397 .build_id = perf_event__process_build_id,
398 .tracing_data = perf_event__process_tracing_data,
399 .feature = perf_event__process_feature,
400 .ordered_events = true, 400 .ordered_events = true,
401 .ordering_requires_timestamps = true, 401 .ordering_requires_timestamps = true,
402 }, 402 },
403 }; 403 };
404 struct perf_data_file file = { 404 struct perf_data data = {
405 .mode = PERF_DATA_MODE_READ, 405 .mode = PERF_DATA_MODE_READ,
406 }; 406 };
407 const struct option options[] = { 407 struct option options[] = {
408 OPT_STRING('i', "input", &input_name, "file", 408 OPT_STRING('i', "input", &input_name, "file",
409 "input file name"), 409 "input file name"),
410 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 410 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
411 "only consider symbols in these dsos"), 411 "only consider symbols in these dsos"),
412 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol", 412 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol",
413 "symbol to annotate"), 413 "symbol to annotate"),
414 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), 414 OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"),
415 OPT_INCR('v', "verbose", &verbose, 415 OPT_INCR('v', "verbose", &verbose,
416 "be more verbose (show symbol address, etc)"), 416 "be more verbose (show symbol address, etc)"),
417 OPT_BOOLEAN('q', "quiet", &quiet, "do now show any message"), 417 OPT_BOOLEAN('q', "quiet", &quiet, "do now show any message"),
@@ -446,13 +446,20 @@ int cmd_annotate(int argc, const char **argv)
446 "Show event group information together"), 446 "Show event group information together"),
447 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 447 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
448 "Show a column with the sum of periods"), 448 "Show a column with the sum of periods"),
449 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
450 "Show a column with the number of samples"),
449 OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode", 451 OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
450 "'always' (default), 'never' or 'auto' only applicable to --stdio mode", 452 "'always' (default), 'never' or 'auto' only applicable to --stdio mode",
451 stdio__config_color, "always"), 453 stdio__config_color, "always"),
452 OPT_END() 454 OPT_END()
453 }; 455 };
454 int ret = hists__init(); 456 int ret;
457
458 set_option_flag(options, 0, "show-total-period", PARSE_OPT_EXCLUSIVE);
459 set_option_flag(options, 0, "show-nr-samples", PARSE_OPT_EXCLUSIVE);
460
455 461
462 ret = hists__init();
456 if (ret < 0) 463 if (ret < 0)
457 return ret; 464 return ret;
458 465
@@ -468,12 +475,17 @@ int cmd_annotate(int argc, const char **argv)
468 annotate.sym_hist_filter = argv[0]; 475 annotate.sym_hist_filter = argv[0];
469 } 476 }
470 477
478 if (symbol_conf.show_nr_samples && annotate.use_gtk) {
479 pr_err("--show-nr-samples is not available in --gtk mode at this time\n");
480 return ret;
481 }
482
471 if (quiet) 483 if (quiet)
472 perf_quiet_option(); 484 perf_quiet_option();
473 485
474 file.path = input_name; 486 data.file.path = input_name;
475 487
476 annotate.session = perf_session__new(&file, false, &annotate.tool); 488 annotate.session = perf_session__new(&data, false, &annotate.tool);
477 if (annotate.session == NULL) 489 if (annotate.session == NULL)
478 return -1; 490 return -1;
479 491
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index 445e62881254..17a6bcd01aa6 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * builtin-bench.c 3 * builtin-bench.c
3 * 4 *
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 9eba7f1add1f..3d354ba6e9c5 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * builtin-buildid-cache.c 3 * builtin-buildid-cache.c
3 * 4 *
@@ -14,6 +15,7 @@
14#include <unistd.h> 15#include <unistd.h>
15#include "builtin.h" 16#include "builtin.h"
16#include "perf.h" 17#include "perf.h"
18#include "namespaces.h"
17#include "util/cache.h" 19#include "util/cache.h"
18#include "util/debug.h" 20#include "util/debug.h"
19#include "util/header.h" 21#include "util/header.h"
@@ -165,33 +167,41 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
165 return 0; 167 return 0;
166} 168}
167 169
168static int build_id_cache__add_file(const char *filename) 170static int build_id_cache__add_file(const char *filename, struct nsinfo *nsi)
169{ 171{
170 char sbuild_id[SBUILD_ID_SIZE]; 172 char sbuild_id[SBUILD_ID_SIZE];
171 u8 build_id[BUILD_ID_SIZE]; 173 u8 build_id[BUILD_ID_SIZE];
172 int err; 174 int err;
175 struct nscookie nsc;
173 176
174 if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) { 177 nsinfo__mountns_enter(nsi, &nsc);
178 err = filename__read_build_id(filename, &build_id, sizeof(build_id));
179 nsinfo__mountns_exit(&nsc);
180 if (err < 0) {
175 pr_debug("Couldn't read a build-id in %s\n", filename); 181 pr_debug("Couldn't read a build-id in %s\n", filename);
176 return -1; 182 return -1;
177 } 183 }
178 184
179 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 185 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
180 err = build_id_cache__add_s(sbuild_id, filename, 186 err = build_id_cache__add_s(sbuild_id, filename, nsi,
181 false, false); 187 false, false);
182 pr_debug("Adding %s %s: %s\n", sbuild_id, filename, 188 pr_debug("Adding %s %s: %s\n", sbuild_id, filename,
183 err ? "FAIL" : "Ok"); 189 err ? "FAIL" : "Ok");
184 return err; 190 return err;
185} 191}
186 192
187static int build_id_cache__remove_file(const char *filename) 193static int build_id_cache__remove_file(const char *filename, struct nsinfo *nsi)
188{ 194{
189 u8 build_id[BUILD_ID_SIZE]; 195 u8 build_id[BUILD_ID_SIZE];
190 char sbuild_id[SBUILD_ID_SIZE]; 196 char sbuild_id[SBUILD_ID_SIZE];
197 struct nscookie nsc;
191 198
192 int err; 199 int err;
193 200
194 if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) { 201 nsinfo__mountns_enter(nsi, &nsc);
202 err = filename__read_build_id(filename, &build_id, sizeof(build_id));
203 nsinfo__mountns_exit(&nsc);
204 if (err < 0) {
195 pr_debug("Couldn't read a build-id in %s\n", filename); 205 pr_debug("Couldn't read a build-id in %s\n", filename);
196 return -1; 206 return -1;
197 } 207 }
@@ -204,13 +214,13 @@ static int build_id_cache__remove_file(const char *filename)
204 return err; 214 return err;
205} 215}
206 216
207static int build_id_cache__purge_path(const char *pathname) 217static int build_id_cache__purge_path(const char *pathname, struct nsinfo *nsi)
208{ 218{
209 struct strlist *list; 219 struct strlist *list;
210 struct str_node *pos; 220 struct str_node *pos;
211 int err; 221 int err;
212 222
213 err = build_id_cache__list_build_ids(pathname, &list); 223 err = build_id_cache__list_build_ids(pathname, nsi, &list);
214 if (err) 224 if (err)
215 goto out; 225 goto out;
216 226
@@ -234,7 +244,7 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
234 char filename[PATH_MAX]; 244 char filename[PATH_MAX];
235 u8 build_id[BUILD_ID_SIZE]; 245 u8 build_id[BUILD_ID_SIZE];
236 246
237 if (dso__build_id_filename(dso, filename, sizeof(filename)) && 247 if (dso__build_id_filename(dso, filename, sizeof(filename), false) &&
238 filename__read_build_id(filename, build_id, 248 filename__read_build_id(filename, build_id,
239 sizeof(build_id)) != sizeof(build_id)) { 249 sizeof(build_id)) != sizeof(build_id)) {
240 if (errno == ENOENT) 250 if (errno == ENOENT)
@@ -256,24 +266,30 @@ static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *f
256 return 0; 266 return 0;
257} 267}
258 268
259static int build_id_cache__update_file(const char *filename) 269static int build_id_cache__update_file(const char *filename, struct nsinfo *nsi)
260{ 270{
261 u8 build_id[BUILD_ID_SIZE]; 271 u8 build_id[BUILD_ID_SIZE];
262 char sbuild_id[SBUILD_ID_SIZE]; 272 char sbuild_id[SBUILD_ID_SIZE];
273 struct nscookie nsc;
263 274
264 int err = 0; 275 int err;
265 276
266 if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) { 277 nsinfo__mountns_enter(nsi, &nsc);
278 err = filename__read_build_id(filename, &build_id, sizeof(build_id));
279 nsinfo__mountns_exit(&nsc);
280 if (err < 0) {
267 pr_debug("Couldn't read a build-id in %s\n", filename); 281 pr_debug("Couldn't read a build-id in %s\n", filename);
268 return -1; 282 return -1;
269 } 283 }
284 err = 0;
270 285
271 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 286 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
272 if (build_id_cache__cached(sbuild_id)) 287 if (build_id_cache__cached(sbuild_id))
273 err = build_id_cache__remove_s(sbuild_id); 288 err = build_id_cache__remove_s(sbuild_id);
274 289
275 if (!err) 290 if (!err)
276 err = build_id_cache__add_s(sbuild_id, filename, false, false); 291 err = build_id_cache__add_s(sbuild_id, filename, nsi, false,
292 false);
277 293
278 pr_debug("Updating %s %s: %s\n", sbuild_id, filename, 294 pr_debug("Updating %s %s: %s\n", sbuild_id, filename,
279 err ? "FAIL" : "Ok"); 295 err ? "FAIL" : "Ok");
@@ -286,6 +302,7 @@ int cmd_buildid_cache(int argc, const char **argv)
286 struct strlist *list; 302 struct strlist *list;
287 struct str_node *pos; 303 struct str_node *pos;
288 int ret = 0; 304 int ret = 0;
305 int ns_id = -1;
289 bool force = false; 306 bool force = false;
290 char const *add_name_list_str = NULL, 307 char const *add_name_list_str = NULL,
291 *remove_name_list_str = NULL, 308 *remove_name_list_str = NULL,
@@ -295,10 +312,11 @@ int cmd_buildid_cache(int argc, const char **argv)
295 *kcore_filename = NULL; 312 *kcore_filename = NULL;
296 char sbuf[STRERR_BUFSIZE]; 313 char sbuf[STRERR_BUFSIZE];
297 314
298 struct perf_data_file file = { 315 struct perf_data data = {
299 .mode = PERF_DATA_MODE_READ, 316 .mode = PERF_DATA_MODE_READ,
300 }; 317 };
301 struct perf_session *session = NULL; 318 struct perf_session *session = NULL;
319 struct nsinfo *nsi = NULL;
302 320
303 const struct option buildid_cache_options[] = { 321 const struct option buildid_cache_options[] = {
304 OPT_STRING('a', "add", &add_name_list_str, 322 OPT_STRING('a', "add", &add_name_list_str,
@@ -315,6 +333,7 @@ int cmd_buildid_cache(int argc, const char **argv)
315 OPT_STRING('u', "update", &update_name_list_str, "file list", 333 OPT_STRING('u', "update", &update_name_list_str, "file list",
316 "file(s) to update"), 334 "file(s) to update"),
317 OPT_INCR('v', "verbose", &verbose, "be more verbose"), 335 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
336 OPT_INTEGER(0, "target-ns", &ns_id, "target pid for namespace context"),
318 OPT_END() 337 OPT_END()
319 }; 338 };
320 const char * const buildid_cache_usage[] = { 339 const char * const buildid_cache_usage[] = {
@@ -330,11 +349,14 @@ int cmd_buildid_cache(int argc, const char **argv)
330 !missing_filename && !update_name_list_str)) 349 !missing_filename && !update_name_list_str))
331 usage_with_options(buildid_cache_usage, buildid_cache_options); 350 usage_with_options(buildid_cache_usage, buildid_cache_options);
332 351
352 if (ns_id > 0)
353 nsi = nsinfo__new(ns_id);
354
333 if (missing_filename) { 355 if (missing_filename) {
334 file.path = missing_filename; 356 data.file.path = missing_filename;
335 file.force = force; 357 data.force = force;
336 358
337 session = perf_session__new(&file, false, NULL); 359 session = perf_session__new(&data, false, NULL);
338 if (session == NULL) 360 if (session == NULL)
339 return -1; 361 return -1;
340 } 362 }
@@ -348,7 +370,7 @@ int cmd_buildid_cache(int argc, const char **argv)
348 list = strlist__new(add_name_list_str, NULL); 370 list = strlist__new(add_name_list_str, NULL);
349 if (list) { 371 if (list) {
350 strlist__for_each_entry(pos, list) 372 strlist__for_each_entry(pos, list)
351 if (build_id_cache__add_file(pos->s)) { 373 if (build_id_cache__add_file(pos->s, nsi)) {
352 if (errno == EEXIST) { 374 if (errno == EEXIST) {
353 pr_debug("%s already in the cache\n", 375 pr_debug("%s already in the cache\n",
354 pos->s); 376 pos->s);
@@ -366,7 +388,7 @@ int cmd_buildid_cache(int argc, const char **argv)
366 list = strlist__new(remove_name_list_str, NULL); 388 list = strlist__new(remove_name_list_str, NULL);
367 if (list) { 389 if (list) {
368 strlist__for_each_entry(pos, list) 390 strlist__for_each_entry(pos, list)
369 if (build_id_cache__remove_file(pos->s)) { 391 if (build_id_cache__remove_file(pos->s, nsi)) {
370 if (errno == ENOENT) { 392 if (errno == ENOENT) {
371 pr_debug("%s wasn't in the cache\n", 393 pr_debug("%s wasn't in the cache\n",
372 pos->s); 394 pos->s);
@@ -384,7 +406,7 @@ int cmd_buildid_cache(int argc, const char **argv)
384 list = strlist__new(purge_name_list_str, NULL); 406 list = strlist__new(purge_name_list_str, NULL);
385 if (list) { 407 if (list) {
386 strlist__for_each_entry(pos, list) 408 strlist__for_each_entry(pos, list)
387 if (build_id_cache__purge_path(pos->s)) { 409 if (build_id_cache__purge_path(pos->s, nsi)) {
388 if (errno == ENOENT) { 410 if (errno == ENOENT) {
389 pr_debug("%s wasn't in the cache\n", 411 pr_debug("%s wasn't in the cache\n",
390 pos->s); 412 pos->s);
@@ -405,7 +427,7 @@ int cmd_buildid_cache(int argc, const char **argv)
405 list = strlist__new(update_name_list_str, NULL); 427 list = strlist__new(update_name_list_str, NULL);
406 if (list) { 428 if (list) {
407 strlist__for_each_entry(pos, list) 429 strlist__for_each_entry(pos, list)
408 if (build_id_cache__update_file(pos->s)) { 430 if (build_id_cache__update_file(pos->s, nsi)) {
409 if (errno == ENOENT) { 431 if (errno == ENOENT) {
410 pr_debug("%s wasn't in the cache\n", 432 pr_debug("%s wasn't in the cache\n",
411 pos->s); 433 pos->s);
@@ -424,6 +446,7 @@ int cmd_buildid_cache(int argc, const char **argv)
424 446
425out: 447out:
426 perf_session__delete(session); 448 perf_session__delete(session);
449 nsinfo__zput(nsi);
427 450
428 return ret; 451 return ret;
429} 452}
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index fdaca16e0c74..78abbe8d9d5f 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * builtin-buildid-list.c 3 * builtin-buildid-list.c
3 * 4 *
@@ -50,10 +51,12 @@ static bool dso__skip_buildid(struct dso *dso, int with_hits)
50static int perf_session__list_build_ids(bool force, bool with_hits) 51static int perf_session__list_build_ids(bool force, bool with_hits)
51{ 52{
52 struct perf_session *session; 53 struct perf_session *session;
53 struct perf_data_file file = { 54 struct perf_data data = {
54 .path = input_name, 55 .file = {
55 .mode = PERF_DATA_MODE_READ, 56 .path = input_name,
56 .force = force, 57 },
58 .mode = PERF_DATA_MODE_READ,
59 .force = force,
57 }; 60 };
58 61
59 symbol__elf_init(); 62 symbol__elf_init();
@@ -63,7 +66,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
63 if (filename__fprintf_build_id(input_name, stdout) > 0) 66 if (filename__fprintf_build_id(input_name, stdout) > 0)
64 goto out; 67 goto out;
65 68
66 session = perf_session__new(&file, false, &build_id__mark_dso_hit_ops); 69 session = perf_session__new(&data, false, &build_id__mark_dso_hit_ops);
67 if (session == NULL) 70 if (session == NULL)
68 return -1; 71 return -1;
69 72
@@ -71,7 +74,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
71 * We take all buildids when the file contains AUX area tracing data 74 * We take all buildids when the file contains AUX area tracing data
72 * because we do not decode the trace because it would take too long. 75 * because we do not decode the trace because it would take too long.
73 */ 76 */
74 if (!perf_data_file__is_pipe(&file) && 77 if (!perf_data__is_pipe(&data) &&
75 perf_header__has_feat(&session->header, HEADER_AUXTRACE)) 78 perf_header__has_feat(&session->header, HEADER_AUXTRACE))
76 with_hits = false; 79 with_hits = false;
77 80
@@ -79,7 +82,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
79 * in pipe-mode, the only way to get the buildids is to parse 82 * in pipe-mode, the only way to get the buildids is to parse
80 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID 83 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
81 */ 84 */
82 if (with_hits || perf_data_file__is_pipe(&file)) 85 if (with_hits || perf_data__is_pipe(&data))
83 perf_session__process_events(session); 86 perf_session__process_events(session);
84 87
85 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits); 88 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 475999e48f66..17855c4626a0 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * This is rewrite of original c2c tool introduced in here: 3 * This is rewrite of original c2c tool introduced in here:
3 * http://lwn.net/Articles/588866/ 4 * http://lwn.net/Articles/588866/
@@ -2523,7 +2524,7 @@ static int perf_c2c__report(int argc, const char **argv)
2523{ 2524{
2524 struct perf_session *session; 2525 struct perf_session *session;
2525 struct ui_progress prog; 2526 struct ui_progress prog;
2526 struct perf_data_file file = { 2527 struct perf_data data = {
2527 .mode = PERF_DATA_MODE_READ, 2528 .mode = PERF_DATA_MODE_READ,
2528 }; 2529 };
2529 char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT; 2530 char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
@@ -2572,8 +2573,8 @@ static int perf_c2c__report(int argc, const char **argv)
2572 if (!input_name || !strlen(input_name)) 2573 if (!input_name || !strlen(input_name))
2573 input_name = "perf.data"; 2574 input_name = "perf.data";
2574 2575
2575 file.path = input_name; 2576 data.file.path = input_name;
2576 file.force = symbol_conf.force; 2577 data.force = symbol_conf.force;
2577 2578
2578 err = setup_display(display); 2579 err = setup_display(display);
2579 if (err) 2580 if (err)
@@ -2591,7 +2592,7 @@ static int perf_c2c__report(int argc, const char **argv)
2591 goto out; 2592 goto out;
2592 } 2593 }
2593 2594
2594 session = perf_session__new(&file, 0, &c2c.tool); 2595 session = perf_session__new(&data, 0, &c2c.tool);
2595 if (session == NULL) { 2596 if (session == NULL) {
2596 pr_debug("No memory for session\n"); 2597 pr_debug("No memory for session\n");
2597 goto out; 2598 goto out;
@@ -2611,7 +2612,7 @@ static int perf_c2c__report(int argc, const char **argv)
2611 goto out_session; 2612 goto out_session;
2612 2613
2613 /* No pipe support at the moment. */ 2614 /* No pipe support at the moment. */
2614 if (perf_data_file__is_pipe(session->file)) { 2615 if (perf_data__is_pipe(session->data)) {
2615 pr_debug("No pipe support at the moment.\n"); 2616 pr_debug("No pipe support at the moment.\n");
2616 goto out_session; 2617 goto out_session;
2617 } 2618 }
@@ -2732,6 +2733,7 @@ static int perf_c2c__record(int argc, const char **argv)
2732 if (!perf_mem_events[j].supported) { 2733 if (!perf_mem_events[j].supported) {
2733 pr_err("failed: event '%s' not supported\n", 2734 pr_err("failed: event '%s' not supported\n",
2734 perf_mem_events[j].name); 2735 perf_mem_events[j].name);
2736 free(rec_argv);
2735 return -1; 2737 return -1;
2736 } 2738 }
2737 2739
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index ece45582a48d..514f70f95b57 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * builtin-config.c 3 * builtin-config.c
3 * 4 *
@@ -13,6 +14,7 @@
13#include "util/util.h" 14#include "util/util.h"
14#include "util/debug.h" 15#include "util/debug.h"
15#include "util/config.h" 16#include "util/config.h"
17#include <linux/string.h>
16 18
17static bool use_system_config, use_user_config; 19static bool use_system_config, use_user_config;
18 20
@@ -33,8 +35,7 @@ static struct option config_options[] = {
33 OPT_END() 35 OPT_END()
34}; 36};
35 37
36static int set_config(struct perf_config_set *set, const char *file_name, 38static int set_config(struct perf_config_set *set, const char *file_name)
37 const char *var, const char *value)
38{ 39{
39 struct perf_config_section *section = NULL; 40 struct perf_config_section *section = NULL;
40 struct perf_config_item *item = NULL; 41 struct perf_config_item *item = NULL;
@@ -48,7 +49,6 @@ static int set_config(struct perf_config_set *set, const char *file_name,
48 if (!fp) 49 if (!fp)
49 return -1; 50 return -1;
50 51
51 perf_config_set__collect(set, file_name, var, value);
52 fprintf(fp, "%s\n", first_line); 52 fprintf(fp, "%s\n", first_line);
53 53
54 /* overwrite configvariables */ 54 /* overwrite configvariables */
@@ -58,7 +58,7 @@ static int set_config(struct perf_config_set *set, const char *file_name,
58 fprintf(fp, "[%s]\n", section->name); 58 fprintf(fp, "[%s]\n", section->name);
59 59
60 perf_config_items__for_each_entry(&section->items, item) { 60 perf_config_items__for_each_entry(&section->items, item) {
61 if (!use_system_config && section->from_system_config) 61 if (!use_system_config && item->from_system_config)
62 continue; 62 continue;
63 if (item->value) 63 if (item->value)
64 fprintf(fp, "\t%s = %s\n", 64 fprintf(fp, "\t%s = %s\n",
@@ -79,7 +79,7 @@ static int show_spec_config(struct perf_config_set *set, const char *var)
79 return -1; 79 return -1;
80 80
81 perf_config_items__for_each_entry(&set->sections, section) { 81 perf_config_items__for_each_entry(&set->sections, section) {
82 if (prefixcmp(var, section->name) != 0) 82 if (!strstarts(var, section->name))
83 continue; 83 continue;
84 84
85 perf_config_items__for_each_entry(&section->items, item) { 85 perf_config_items__for_each_entry(&section->items, item) {
@@ -160,6 +160,7 @@ int cmd_config(int argc, const char **argv)
160 struct perf_config_set *set; 160 struct perf_config_set *set;
161 char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); 161 char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
162 const char *config_filename; 162 const char *config_filename;
163 bool changed = false;
163 164
164 argc = parse_options(argc, argv, config_options, config_usage, 165 argc = parse_options(argc, argv, config_options, config_usage,
165 PARSE_OPT_STOP_AT_NON_OPTION); 166 PARSE_OPT_STOP_AT_NON_OPTION);
@@ -230,15 +231,26 @@ int cmd_config(int argc, const char **argv)
230 goto out_err; 231 goto out_err;
231 } 232 }
232 } else { 233 } else {
233 if (set_config(set, config_filename, var, value) < 0) { 234 if (perf_config_set__collect(set, config_filename,
234 pr_err("Failed to set '%s=%s' on %s\n", 235 var, value) < 0) {
235 var, value, config_filename); 236 pr_err("Failed to add '%s=%s'\n",
237 var, value);
236 free(arg); 238 free(arg);
237 goto out_err; 239 goto out_err;
238 } 240 }
241 changed = true;
239 } 242 }
240 free(arg); 243 free(arg);
241 } 244 }
245
246 if (!changed)
247 break;
248
249 if (set_config(set, config_filename) < 0) {
250 pr_err("Failed to set the configs on %s\n",
251 config_filename);
252 goto out_err;
253 }
242 } 254 }
243 255
244 ret = 0; 256 ret = 0;
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
index 0adb5f82335a..dde25d4ca56d 100644
--- a/tools/perf/builtin-data.c
+++ b/tools/perf/builtin-data.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include "builtin.h" 3#include "builtin.h"
3#include "perf.h" 4#include "perf.h"
@@ -69,7 +70,7 @@ static int cmd_data_convert(int argc, const char **argv)
69 }; 70 };
70 71
71#ifndef HAVE_LIBBABELTRACE_SUPPORT 72#ifndef HAVE_LIBBABELTRACE_SUPPORT
72 pr_err("No conversion support compiled in.\n"); 73 pr_err("No conversion support compiled in. perf should be compiled with environment variables LIBBABELTRACE=1 and LIBBABELTRACE_DIR=/path/to/libbabeltrace/\n");
73 return -1; 74 return -1;
74#endif 75#endif
75 76
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 0cd4cf6a344b..d660cb7b222b 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * builtin-diff.c 3 * builtin-diff.c
3 * 4 *
@@ -47,7 +48,7 @@ struct diff_hpp_fmt {
47 48
48struct data__file { 49struct data__file {
49 struct perf_session *session; 50 struct perf_session *session;
50 struct perf_data_file file; 51 struct perf_data data;
51 int idx; 52 int idx;
52 struct hists *hists; 53 struct hists *hists;
53 struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX]; 54 struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX];
@@ -707,7 +708,7 @@ static void data__fprintf(void)
707 708
708 data__for_each_file(i, d) 709 data__for_each_file(i, d)
709 fprintf(stdout, "# [%d] %s %s\n", 710 fprintf(stdout, "# [%d] %s %s\n",
710 d->idx, d->file.path, 711 d->idx, d->data.file.path,
711 !d->idx ? "(Baseline)" : ""); 712 !d->idx ? "(Baseline)" : "");
712 713
713 fprintf(stdout, "#\n"); 714 fprintf(stdout, "#\n");
@@ -776,16 +777,16 @@ static int __cmd_diff(void)
776 int ret = -EINVAL, i; 777 int ret = -EINVAL, i;
777 778
778 data__for_each_file(i, d) { 779 data__for_each_file(i, d) {
779 d->session = perf_session__new(&d->file, false, &tool); 780 d->session = perf_session__new(&d->data, false, &tool);
780 if (!d->session) { 781 if (!d->session) {
781 pr_err("Failed to open %s\n", d->file.path); 782 pr_err("Failed to open %s\n", d->data.file.path);
782 ret = -1; 783 ret = -1;
783 goto out_delete; 784 goto out_delete;
784 } 785 }
785 786
786 ret = perf_session__process_events(d->session); 787 ret = perf_session__process_events(d->session);
787 if (ret) { 788 if (ret) {
788 pr_err("Failed to process %s\n", d->file.path); 789 pr_err("Failed to process %s\n", d->data.file.path);
789 goto out_delete; 790 goto out_delete;
790 } 791 }
791 792
@@ -1286,11 +1287,11 @@ static int data_init(int argc, const char **argv)
1286 return -ENOMEM; 1287 return -ENOMEM;
1287 1288
1288 data__for_each_file(i, d) { 1289 data__for_each_file(i, d) {
1289 struct perf_data_file *file = &d->file; 1290 struct perf_data *data = &d->data;
1290 1291
1291 file->path = use_default ? defaults[i] : argv[i]; 1292 data->file.path = use_default ? defaults[i] : argv[i];
1292 file->mode = PERF_DATA_MODE_READ, 1293 data->mode = PERF_DATA_MODE_READ,
1293 file->force = force, 1294 data->force = force,
1294 1295
1295 d->idx = i; 1296 d->idx = i;
1296 } 1297 }
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 6d210e40d611..e06e822ce634 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Builtin evlist command: Show the list of event selectors present 3 * Builtin evlist command: Show the list of event selectors present
3 * in a perf.data file. 4 * in a perf.data file.
@@ -21,14 +22,16 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
21{ 22{
22 struct perf_session *session; 23 struct perf_session *session;
23 struct perf_evsel *pos; 24 struct perf_evsel *pos;
24 struct perf_data_file file = { 25 struct perf_data data = {
25 .path = file_name, 26 .file = {
26 .mode = PERF_DATA_MODE_READ, 27 .path = file_name,
27 .force = details->force, 28 },
29 .mode = PERF_DATA_MODE_READ,
30 .force = details->force,
28 }; 31 };
29 bool has_tracepoint = false; 32 bool has_tracepoint = false;
30 33
31 session = perf_session__new(&file, 0, NULL); 34 session = perf_session__new(&data, 0, NULL);
32 if (session == NULL) 35 if (session == NULL)
33 return -1; 36 return -1;
34 37
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index dd26c62c9893..25a42acabee1 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -381,7 +381,7 @@ static int perf_ftrace_config(const char *var, const char *value, void *cb)
381{ 381{
382 struct perf_ftrace *ftrace = cb; 382 struct perf_ftrace *ftrace = cb;
383 383
384 if (prefixcmp(var, "ftrace.")) 384 if (!strstarts(var, "ftrace."))
385 return 0; 385 return 0;
386 386
387 if (strcmp(var, "ftrace.tracer")) 387 if (strcmp(var, "ftrace.tracer"))
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 530a7f2fa0f3..bd1fedef3d1c 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * builtin-help.c 3 * builtin-help.c
3 * 4 *
@@ -90,7 +91,7 @@ static int check_emacsclient_version(void)
90 */ 91 */
91 finish_command(&ec_process); 92 finish_command(&ec_process);
92 93
93 if (prefixcmp(buffer.buf, "emacsclient")) { 94 if (!strstarts(buffer.buf, "emacsclient")) {
94 fprintf(stderr, "Failed to parse emacsclient version.\n"); 95 fprintf(stderr, "Failed to parse emacsclient version.\n");
95 goto out; 96 goto out;
96 } 97 }
@@ -283,7 +284,7 @@ static int perf_help_config(const char *var, const char *value, void *cb)
283 add_man_viewer(value); 284 add_man_viewer(value);
284 return 0; 285 return 0;
285 } 286 }
286 if (!prefixcmp(var, "man.")) 287 if (!strstarts(var, "man."))
287 return add_man_viewer_info(var, value); 288 return add_man_viewer_info(var, value);
288 289
289 return 0; 290 return 0;
@@ -313,7 +314,7 @@ static const char *cmd_to_page(const char *perf_cmd)
313 314
314 if (!perf_cmd) 315 if (!perf_cmd)
315 return "perf"; 316 return "perf";
316 else if (!prefixcmp(perf_cmd, "perf")) 317 else if (!strstarts(perf_cmd, "perf"))
317 return perf_cmd; 318 return perf_cmd;
318 319
319 return asprintf(&s, "perf-%s", perf_cmd) < 0 ? NULL : s; 320 return asprintf(&s, "perf-%s", perf_cmd) < 0 ? NULL : s;
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index ea8db38eedd1..16a28547ca86 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * builtin-inject.c 3 * builtin-inject.c
3 * 4 *
@@ -35,7 +36,7 @@ struct perf_inject {
35 bool strip; 36 bool strip;
36 bool jit_mode; 37 bool jit_mode;
37 const char *input_name; 38 const char *input_name;
38 struct perf_data_file output; 39 struct perf_data output;
39 u64 bytes_written; 40 u64 bytes_written;
40 u64 aux_id; 41 u64 aux_id;
41 struct list_head samples; 42 struct list_head samples;
@@ -52,7 +53,7 @@ static int output_bytes(struct perf_inject *inject, void *buf, size_t sz)
52{ 53{
53 ssize_t size; 54 ssize_t size;
54 55
55 size = perf_data_file__write(&inject->output, buf, sz); 56 size = perf_data__write(&inject->output, buf, sz);
56 if (size < 0) 57 if (size < 0)
57 return -errno; 58 return -errno;
58 59
@@ -145,7 +146,7 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
145 if (!inject->output.is_pipe) { 146 if (!inject->output.is_pipe) {
146 off_t offset; 147 off_t offset;
147 148
148 offset = lseek(inject->output.fd, 0, SEEK_CUR); 149 offset = lseek(inject->output.file.fd, 0, SEEK_CUR);
149 if (offset == -1) 150 if (offset == -1)
150 return -errno; 151 return -errno;
151 ret = auxtrace_index__auxtrace_event(&session->auxtrace_index, 152 ret = auxtrace_index__auxtrace_event(&session->auxtrace_index,
@@ -154,11 +155,11 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
154 return ret; 155 return ret;
155 } 156 }
156 157
157 if (perf_data_file__is_pipe(session->file) || !session->one_mmap) { 158 if (perf_data__is_pipe(session->data) || !session->one_mmap) {
158 ret = output_bytes(inject, event, event->header.size); 159 ret = output_bytes(inject, event, event->header.size);
159 if (ret < 0) 160 if (ret < 0)
160 return ret; 161 return ret;
161 ret = copy_bytes(inject, perf_data_file__fd(session->file), 162 ret = copy_bytes(inject, perf_data__fd(session->data),
162 event->auxtrace.size); 163 event->auxtrace.size);
163 } else { 164 } else {
164 ret = output_bytes(inject, event, 165 ret = output_bytes(inject, event,
@@ -637,8 +638,8 @@ static int __cmd_inject(struct perf_inject *inject)
637{ 638{
638 int ret = -EINVAL; 639 int ret = -EINVAL;
639 struct perf_session *session = inject->session; 640 struct perf_session *session = inject->session;
640 struct perf_data_file *file_out = &inject->output; 641 struct perf_data *data_out = &inject->output;
641 int fd = perf_data_file__fd(file_out); 642 int fd = perf_data__fd(data_out);
642 u64 output_data_offset; 643 u64 output_data_offset;
643 644
644 signal(SIGINT, sig_handler); 645 signal(SIGINT, sig_handler);
@@ -693,14 +694,14 @@ static int __cmd_inject(struct perf_inject *inject)
693 if (!inject->itrace_synth_opts.set) 694 if (!inject->itrace_synth_opts.set)
694 auxtrace_index__free(&session->auxtrace_index); 695 auxtrace_index__free(&session->auxtrace_index);
695 696
696 if (!file_out->is_pipe) 697 if (!data_out->is_pipe)
697 lseek(fd, output_data_offset, SEEK_SET); 698 lseek(fd, output_data_offset, SEEK_SET);
698 699
699 ret = perf_session__process_events(session); 700 ret = perf_session__process_events(session);
700 if (ret) 701 if (ret)
701 return ret; 702 return ret;
702 703
703 if (!file_out->is_pipe) { 704 if (!data_out->is_pipe) {
704 if (inject->build_ids) 705 if (inject->build_ids)
705 perf_header__set_feat(&session->header, 706 perf_header__set_feat(&session->header,
706 HEADER_BUILD_ID); 707 HEADER_BUILD_ID);
@@ -770,15 +771,18 @@ int cmd_inject(int argc, const char **argv)
770 .finished_round = perf_event__repipe_oe_synth, 771 .finished_round = perf_event__repipe_oe_synth,
771 .build_id = perf_event__repipe_op2_synth, 772 .build_id = perf_event__repipe_op2_synth,
772 .id_index = perf_event__repipe_op2_synth, 773 .id_index = perf_event__repipe_op2_synth,
774 .feature = perf_event__repipe_op2_synth,
773 }, 775 },
774 .input_name = "-", 776 .input_name = "-",
775 .samples = LIST_HEAD_INIT(inject.samples), 777 .samples = LIST_HEAD_INIT(inject.samples),
776 .output = { 778 .output = {
777 .path = "-", 779 .file = {
778 .mode = PERF_DATA_MODE_WRITE, 780 .path = "-",
781 },
782 .mode = PERF_DATA_MODE_WRITE,
779 }, 783 },
780 }; 784 };
781 struct perf_data_file file = { 785 struct perf_data data = {
782 .mode = PERF_DATA_MODE_READ, 786 .mode = PERF_DATA_MODE_READ,
783 }; 787 };
784 int ret; 788 int ret;
@@ -788,7 +792,7 @@ int cmd_inject(int argc, const char **argv)
788 "Inject build-ids into the output stream"), 792 "Inject build-ids into the output stream"),
789 OPT_STRING('i', "input", &inject.input_name, "file", 793 OPT_STRING('i', "input", &inject.input_name, "file",
790 "input file name"), 794 "input file name"),
791 OPT_STRING('o', "output", &inject.output.path, "file", 795 OPT_STRING('o', "output", &inject.output.file.path, "file",
792 "output file name"), 796 "output file name"),
793 OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, 797 OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
794 "Merge sched-stat and sched-switch for getting events " 798 "Merge sched-stat and sched-switch for getting events "
@@ -800,7 +804,7 @@ int cmd_inject(int argc, const char **argv)
800 "be more verbose (show build ids, etc)"), 804 "be more verbose (show build ids, etc)"),
801 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", 805 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
802 "kallsyms pathname"), 806 "kallsyms pathname"),
803 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), 807 OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"),
804 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, 808 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts,
805 NULL, "opts", "Instruction Tracing options", 809 NULL, "opts", "Instruction Tracing options",
806 itrace_parse_synth_opts), 810 itrace_parse_synth_opts),
@@ -828,15 +832,15 @@ int cmd_inject(int argc, const char **argv)
828 return -1; 832 return -1;
829 } 833 }
830 834
831 if (perf_data_file__open(&inject.output)) { 835 if (perf_data__open(&inject.output)) {
832 perror("failed to create output file"); 836 perror("failed to create output file");
833 return -1; 837 return -1;
834 } 838 }
835 839
836 inject.tool.ordered_events = inject.sched_stat; 840 inject.tool.ordered_events = inject.sched_stat;
837 841
838 file.path = inject.input_name; 842 data.file.path = inject.input_name;
839 inject.session = perf_session__new(&file, true, &inject.tool); 843 inject.session = perf_session__new(&data, true, &inject.tool);
840 if (inject.session == NULL) 844 if (inject.session == NULL)
841 return -1; 845 return -1;
842 846
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index a1497c516d85..ae11e4c3516a 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "builtin.h" 2#include "builtin.h"
2#include "perf.h" 3#include "perf.h"
3 4
@@ -627,7 +628,6 @@ static const struct {
627 { "GFP_HIGHUSER_MOVABLE", "HUM" }, 628 { "GFP_HIGHUSER_MOVABLE", "HUM" },
628 { "GFP_HIGHUSER", "HU" }, 629 { "GFP_HIGHUSER", "HU" },
629 { "GFP_USER", "U" }, 630 { "GFP_USER", "U" },
630 { "GFP_TEMPORARY", "TMP" },
631 { "GFP_KERNEL_ACCOUNT", "KAC" }, 631 { "GFP_KERNEL_ACCOUNT", "KAC" },
632 { "GFP_KERNEL", "K" }, 632 { "GFP_KERNEL", "K" },
633 { "GFP_NOFS", "NF" }, 633 { "GFP_NOFS", "NF" },
@@ -641,7 +641,6 @@ static const struct {
641 { "__GFP_ATOMIC", "_A" }, 641 { "__GFP_ATOMIC", "_A" },
642 { "__GFP_IO", "I" }, 642 { "__GFP_IO", "I" },
643 { "__GFP_FS", "F" }, 643 { "__GFP_FS", "F" },
644 { "__GFP_COLD", "CO" },
645 { "__GFP_NOWARN", "NWR" }, 644 { "__GFP_NOWARN", "NWR" },
646 { "__GFP_RETRY_MAYFAIL", "R" }, 645 { "__GFP_RETRY_MAYFAIL", "R" },
647 { "__GFP_NOFAIL", "NF" }, 646 { "__GFP_NOFAIL", "NF" },
@@ -655,7 +654,6 @@ static const struct {
655 { "__GFP_RECLAIMABLE", "RC" }, 654 { "__GFP_RECLAIMABLE", "RC" },
656 { "__GFP_MOVABLE", "M" }, 655 { "__GFP_MOVABLE", "M" },
657 { "__GFP_ACCOUNT", "AC" }, 656 { "__GFP_ACCOUNT", "AC" },
658 { "__GFP_NOTRACK", "NT" },
659 { "__GFP_WRITE", "WR" }, 657 { "__GFP_WRITE", "WR" },
660 { "__GFP_RECLAIM", "R" }, 658 { "__GFP_RECLAIM", "R" },
661 { "__GFP_DIRECT_RECLAIM", "DR" }, 659 { "__GFP_DIRECT_RECLAIM", "DR" },
@@ -1894,7 +1892,7 @@ int cmd_kmem(int argc, const char **argv)
1894{ 1892{
1895 const char * const default_slab_sort = "frag,hit,bytes"; 1893 const char * const default_slab_sort = "frag,hit,bytes";
1896 const char * const default_page_sort = "bytes,hit"; 1894 const char * const default_page_sort = "bytes,hit";
1897 struct perf_data_file file = { 1895 struct perf_data data = {
1898 .mode = PERF_DATA_MODE_READ, 1896 .mode = PERF_DATA_MODE_READ,
1899 }; 1897 };
1900 const struct option kmem_options[] = { 1898 const struct option kmem_options[] = {
@@ -1910,7 +1908,7 @@ int cmd_kmem(int argc, const char **argv)
1910 "page, order, migtype, gfp", parse_sort_opt), 1908 "page, order, migtype, gfp", parse_sort_opt),
1911 OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt), 1909 OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt),
1912 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"), 1910 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
1913 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), 1911 OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"),
1914 OPT_CALLBACK_NOOPT(0, "slab", NULL, NULL, "Analyze slab allocator", 1912 OPT_CALLBACK_NOOPT(0, "slab", NULL, NULL, "Analyze slab allocator",
1915 parse_slab_opt), 1913 parse_slab_opt),
1916 OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator", 1914 OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator",
@@ -1950,9 +1948,9 @@ int cmd_kmem(int argc, const char **argv)
1950 return __cmd_record(argc, argv); 1948 return __cmd_record(argc, argv);
1951 } 1949 }
1952 1950
1953 file.path = input_name; 1951 data.file.path = input_name;
1954 1952
1955 kmem_session = session = perf_session__new(&file, false, &perf_kmem); 1953 kmem_session = session = perf_session__new(&data, false, &perf_kmem);
1956 if (session == NULL) 1954 if (session == NULL)
1957 return -1; 1955 return -1;
1958 1956
@@ -1984,7 +1982,8 @@ int cmd_kmem(int argc, const char **argv)
1984 1982
1985 if (perf_time__parse_str(&ptime, time_str) != 0) { 1983 if (perf_time__parse_str(&ptime, time_str) != 0) {
1986 pr_err("Invalid time string\n"); 1984 pr_err("Invalid time string\n");
1987 return -EINVAL; 1985 ret = -EINVAL;
1986 goto out_delete;
1988 } 1987 }
1989 1988
1990 if (!strcmp(argv[0], "stat")) { 1989 if (!strcmp(argv[0], "stat")) {
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index f309c3773522..0c36f2ac6a0e 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "builtin.h" 2#include "builtin.h"
2#include "perf.h" 3#include "perf.h"
3 4
@@ -34,7 +35,6 @@
34#include <termios.h> 35#include <termios.h>
35#include <semaphore.h> 36#include <semaphore.h>
36#include <signal.h> 37#include <signal.h>
37#include <pthread.h>
38#include <math.h> 38#include <math.h>
39 39
40static const char *get_filename_for_perf_kvm(void) 40static const char *get_filename_for_perf_kvm(void)
@@ -1068,10 +1068,12 @@ static int read_events(struct perf_kvm_stat *kvm)
1068 .namespaces = perf_event__process_namespaces, 1068 .namespaces = perf_event__process_namespaces,
1069 .ordered_events = true, 1069 .ordered_events = true,
1070 }; 1070 };
1071 struct perf_data_file file = { 1071 struct perf_data file = {
1072 .path = kvm->file_name, 1072 .file = {
1073 .mode = PERF_DATA_MODE_READ, 1073 .path = kvm->file_name,
1074 .force = kvm->force, 1074 },
1075 .mode = PERF_DATA_MODE_READ,
1076 .force = kvm->force,
1075 }; 1077 };
1076 1078
1077 kvm->tool = eops; 1079 kvm->tool = eops;
@@ -1359,7 +1361,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1359 "perf kvm stat live [<options>]", 1361 "perf kvm stat live [<options>]",
1360 NULL 1362 NULL
1361 }; 1363 };
1362 struct perf_data_file file = { 1364 struct perf_data data = {
1363 .mode = PERF_DATA_MODE_WRITE, 1365 .mode = PERF_DATA_MODE_WRITE,
1364 }; 1366 };
1365 1367
@@ -1433,7 +1435,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1433 /* 1435 /*
1434 * perf session 1436 * perf session
1435 */ 1437 */
1436 kvm->session = perf_session__new(&file, false, &kvm->tool); 1438 kvm->session = perf_session__new(&data, false, &kvm->tool);
1437 if (kvm->session == NULL) { 1439 if (kvm->session == NULL) {
1438 err = -1; 1440 err = -1;
1439 goto out; 1441 goto out;
@@ -1442,7 +1444,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1442 perf_session__set_id_hdr_size(kvm->session); 1444 perf_session__set_id_hdr_size(kvm->session);
1443 ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true); 1445 ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true);
1444 machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target, 1446 machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target,
1445 kvm->evlist->threads, false, kvm->opts.proc_map_timeout); 1447 kvm->evlist->threads, false,
1448 kvm->opts.proc_map_timeout, 1);
1446 err = kvm_live_open_events(kvm); 1449 err = kvm_live_open_events(kvm);
1447 if (err) 1450 if (err)
1448 goto out; 1451 goto out;
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 4bf2cb4d25aa..ead221e49f00 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * builtin-list.c 3 * builtin-list.c
3 * 4 *
@@ -15,6 +16,7 @@
15#include "util/cache.h" 16#include "util/cache.h"
16#include "util/pmu.h" 17#include "util/pmu.h"
17#include "util/debug.h" 18#include "util/debug.h"
19#include "util/metricgroup.h"
18#include <subcmd/parse-options.h> 20#include <subcmd/parse-options.h>
19 21
20static bool desc_flag = true; 22static bool desc_flag = true;
@@ -79,6 +81,10 @@ int cmd_list(int argc, const char **argv)
79 long_desc_flag, details_flag); 81 long_desc_flag, details_flag);
80 else if (strcmp(argv[i], "sdt") == 0) 82 else if (strcmp(argv[i], "sdt") == 0)
81 print_sdt_events(NULL, NULL, raw_dump); 83 print_sdt_events(NULL, NULL, raw_dump);
84 else if (strcmp(argv[i], "metric") == 0)
85 metricgroup__print(true, false, NULL, raw_dump);
86 else if (strcmp(argv[i], "metricgroup") == 0)
87 metricgroup__print(false, true, NULL, raw_dump);
82 else if ((sep = strchr(argv[i], ':')) != NULL) { 88 else if ((sep = strchr(argv[i], ':')) != NULL) {
83 int sep_idx; 89 int sep_idx;
84 90
@@ -96,6 +102,7 @@ int cmd_list(int argc, const char **argv)
96 s[sep_idx] = '\0'; 102 s[sep_idx] = '\0';
97 print_tracepoint_events(s, s + sep_idx + 1, raw_dump); 103 print_tracepoint_events(s, s + sep_idx + 1, raw_dump);
98 print_sdt_events(s, s + sep_idx + 1, raw_dump); 104 print_sdt_events(s, s + sep_idx + 1, raw_dump);
105 metricgroup__print(true, true, s, raw_dump);
99 free(s); 106 free(s);
100 } else { 107 } else {
101 if (asprintf(&s, "*%s*", argv[i]) < 0) { 108 if (asprintf(&s, "*%s*", argv[i]) < 0) {
@@ -112,6 +119,7 @@ int cmd_list(int argc, const char **argv)
112 details_flag); 119 details_flag);
113 print_tracepoint_events(NULL, s, raw_dump); 120 print_tracepoint_events(NULL, s, raw_dump);
114 print_sdt_events(NULL, s, raw_dump); 121 print_sdt_events(NULL, s, raw_dump);
122 metricgroup__print(true, true, NULL, raw_dump);
115 free(s); 123 free(s);
116 } 124 }
117 } 125 }
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index ff98652484a7..6e0189df2b3b 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <inttypes.h> 3#include <inttypes.h>
3#include "builtin.h" 4#include "builtin.h"
@@ -864,13 +865,15 @@ static int __cmd_report(bool display_info)
864 .namespaces = perf_event__process_namespaces, 865 .namespaces = perf_event__process_namespaces,
865 .ordered_events = true, 866 .ordered_events = true,
866 }; 867 };
867 struct perf_data_file file = { 868 struct perf_data data = {
868 .path = input_name, 869 .file = {
869 .mode = PERF_DATA_MODE_READ, 870 .path = input_name,
870 .force = force, 871 },
872 .mode = PERF_DATA_MODE_READ,
873 .force = force,
871 }; 874 };
872 875
873 session = perf_session__new(&file, false, &eops); 876 session = perf_session__new(&data, false, &eops);
874 if (!session) { 877 if (!session) {
875 pr_err("Initializing perf session failed\n"); 878 pr_err("Initializing perf session failed\n");
876 return -1; 879 return -1;
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index e001c0290793..506564651cda 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <inttypes.h> 2#include <inttypes.h>
2#include <sys/types.h> 3#include <sys/types.h>
3#include <sys/stat.h> 4#include <sys/stat.h>
@@ -23,6 +24,7 @@ struct perf_mem {
23 bool hide_unresolved; 24 bool hide_unresolved;
24 bool dump_raw; 25 bool dump_raw;
25 bool force; 26 bool force;
27 bool phys_addr;
26 int operation; 28 int operation;
27 const char *cpu_list; 29 const char *cpu_list;
28 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 30 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -101,6 +103,9 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
101 103
102 rec_argv[i++] = "-d"; 104 rec_argv[i++] = "-d";
103 105
106 if (mem->phys_addr)
107 rec_argv[i++] = "--phys-data";
108
104 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { 109 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
105 if (!perf_mem_events[j].record) 110 if (!perf_mem_events[j].record)
106 continue; 111 continue;
@@ -108,6 +113,7 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
108 if (!perf_mem_events[j].supported) { 113 if (!perf_mem_events[j].supported) {
109 pr_err("failed: event '%s' not supported\n", 114 pr_err("failed: event '%s' not supported\n",
110 perf_mem_events__name(j)); 115 perf_mem_events__name(j));
116 free(rec_argv);
111 return -1; 117 return -1;
112 } 118 }
113 119
@@ -161,30 +167,60 @@ dump_raw_samples(struct perf_tool *tool,
161 if (al.map != NULL) 167 if (al.map != NULL)
162 al.map->dso->hit = 1; 168 al.map->dso->hit = 1;
163 169
164 if (symbol_conf.field_sep) { 170 if (mem->phys_addr) {
165 fmt = "%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s%"PRIu64 171 if (symbol_conf.field_sep) {
166 "%s0x%"PRIx64"%s%s:%s\n"; 172 fmt = "%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s0x%016"PRIx64
173 "%s%"PRIu64"%s0x%"PRIx64"%s%s:%s\n";
174 } else {
175 fmt = "%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64
176 "%s0x%016"PRIx64"%s%5"PRIu64"%s0x%06"PRIx64
177 "%s%s:%s\n";
178 symbol_conf.field_sep = " ";
179 }
180
181 printf(fmt,
182 sample->pid,
183 symbol_conf.field_sep,
184 sample->tid,
185 symbol_conf.field_sep,
186 sample->ip,
187 symbol_conf.field_sep,
188 sample->addr,
189 symbol_conf.field_sep,
190 sample->phys_addr,
191 symbol_conf.field_sep,
192 sample->weight,
193 symbol_conf.field_sep,
194 sample->data_src,
195 symbol_conf.field_sep,
196 al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???",
197 al.sym ? al.sym->name : "???");
167 } else { 198 } else {
168 fmt = "%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64 199 if (symbol_conf.field_sep) {
169 "%s%5"PRIu64"%s0x%06"PRIx64"%s%s:%s\n"; 200 fmt = "%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s%"PRIu64
170 symbol_conf.field_sep = " "; 201 "%s0x%"PRIx64"%s%s:%s\n";
171 } 202 } else {
203 fmt = "%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64
204 "%s%5"PRIu64"%s0x%06"PRIx64"%s%s:%s\n";
205 symbol_conf.field_sep = " ";
206 }
172 207
173 printf(fmt, 208 printf(fmt,
174 sample->pid, 209 sample->pid,
175 symbol_conf.field_sep, 210 symbol_conf.field_sep,
176 sample->tid, 211 sample->tid,
177 symbol_conf.field_sep, 212 symbol_conf.field_sep,
178 sample->ip, 213 sample->ip,
179 symbol_conf.field_sep, 214 symbol_conf.field_sep,
180 sample->addr, 215 sample->addr,
181 symbol_conf.field_sep, 216 symbol_conf.field_sep,
182 sample->weight, 217 sample->weight,
183 symbol_conf.field_sep, 218 symbol_conf.field_sep,
184 sample->data_src, 219 sample->data_src,
185 symbol_conf.field_sep, 220 symbol_conf.field_sep,
186 al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???", 221 al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???",
187 al.sym ? al.sym->name : "???"); 222 al.sym ? al.sym->name : "???");
223 }
188out_put: 224out_put:
189 addr_location__put(&al); 225 addr_location__put(&al);
190 return 0; 226 return 0;
@@ -201,13 +237,15 @@ static int process_sample_event(struct perf_tool *tool,
201 237
202static int report_raw_events(struct perf_mem *mem) 238static int report_raw_events(struct perf_mem *mem)
203{ 239{
204 struct perf_data_file file = { 240 struct perf_data data = {
205 .path = input_name, 241 .file = {
206 .mode = PERF_DATA_MODE_READ, 242 .path = input_name,
207 .force = mem->force, 243 },
244 .mode = PERF_DATA_MODE_READ,
245 .force = mem->force,
208 }; 246 };
209 int ret; 247 int ret;
210 struct perf_session *session = perf_session__new(&file, false, 248 struct perf_session *session = perf_session__new(&data, false,
211 &mem->tool); 249 &mem->tool);
212 250
213 if (session == NULL) 251 if (session == NULL)
@@ -224,7 +262,10 @@ static int report_raw_events(struct perf_mem *mem)
224 if (ret < 0) 262 if (ret < 0)
225 goto out_delete; 263 goto out_delete;
226 264
227 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n"); 265 if (mem->phys_addr)
266 printf("# PID, TID, IP, ADDR, PHYS ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
267 else
268 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
228 269
229 ret = perf_session__process_events(session); 270 ret = perf_session__process_events(session);
230 271
@@ -254,9 +295,16 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem)
254 * there is no weight (cost) associated with stores, so don't print 295 * there is no weight (cost) associated with stores, so don't print
255 * the column 296 * the column
256 */ 297 */
257 if (!(mem->operation & MEM_OPERATION_LOAD)) 298 if (!(mem->operation & MEM_OPERATION_LOAD)) {
258 rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr," 299 if (mem->phys_addr)
259 "dso_daddr,tlb,locked"; 300 rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr,"
301 "dso_daddr,tlb,locked,phys_daddr";
302 else
303 rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr,"
304 "dso_daddr,tlb,locked";
305 } else if (mem->phys_addr)
306 rep_argv[i++] = "--sort=local_weight,mem,sym,dso,symbol_daddr,"
307 "dso_daddr,snoop,tlb,locked,phys_daddr";
260 308
261 for (j = 1; j < argc; j++, i++) 309 for (j = 1; j < argc; j++, i++)
262 rep_argv[i] = argv[j]; 310 rep_argv[i] = argv[j];
@@ -373,6 +421,7 @@ int cmd_mem(int argc, const char **argv)
373 "separator for columns, no spaces will be added" 421 "separator for columns, no spaces will be added"
374 " between columns '.' is reserved."), 422 " between columns '.' is reserved."),
375 OPT_BOOLEAN('f', "force", &mem.force, "don't complain, do it"), 423 OPT_BOOLEAN('f', "force", &mem.force, "don't complain, do it"),
424 OPT_BOOLEAN('p', "phys-data", &mem.phys_addr, "Record/Report sample physical addresses"),
376 OPT_END() 425 OPT_END()
377 }; 426 };
378 const char *const mem_subcommands[] = { "record", "report", NULL }; 427 const char *const mem_subcommands[] = { "record", "report", NULL };
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index cf9f9e9c2fc0..c0065923a525 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -58,6 +58,7 @@ static struct {
58 struct line_range line_range; 58 struct line_range line_range;
59 char *target; 59 char *target;
60 struct strfilter *filter; 60 struct strfilter *filter;
61 struct nsinfo *nsi;
61} params; 62} params;
62 63
63/* Parse an event definition. Note that any error must die. */ 64/* Parse an event definition. Note that any error must die. */
@@ -80,6 +81,9 @@ static int parse_probe_event(const char *str)
80 params.target_used = true; 81 params.target_used = true;
81 } 82 }
82 83
84 if (params.nsi)
85 pev->nsi = nsinfo__get(params.nsi);
86
83 /* Parse a perf-probe command into event */ 87 /* Parse a perf-probe command into event */
84 ret = parse_perf_probe_command(str, pev); 88 ret = parse_perf_probe_command(str, pev);
85 pr_debug("%d arguments\n", pev->nargs); 89 pr_debug("%d arguments\n", pev->nargs);
@@ -189,7 +193,7 @@ static int opt_set_target(const struct option *opt, const char *str,
189 193
190 /* Expand given path to absolute path, except for modulename */ 194 /* Expand given path to absolute path, except for modulename */
191 if (params.uprobes || strchr(str, '/')) { 195 if (params.uprobes || strchr(str, '/')) {
192 tmp = realpath(str, NULL); 196 tmp = nsinfo__realpath(str, params.nsi);
193 if (!tmp) { 197 if (!tmp) {
194 pr_warning("Failed to get the absolute path of %s: %m\n", str); 198 pr_warning("Failed to get the absolute path of %s: %m\n", str);
195 return ret; 199 return ret;
@@ -208,6 +212,34 @@ static int opt_set_target(const struct option *opt, const char *str,
208 return ret; 212 return ret;
209} 213}
210 214
215static int opt_set_target_ns(const struct option *opt __maybe_unused,
216 const char *str, int unset __maybe_unused)
217{
218 int ret = -ENOENT;
219 pid_t ns_pid;
220 struct nsinfo *nsip;
221
222 if (str) {
223 errno = 0;
224 ns_pid = (pid_t)strtol(str, NULL, 10);
225 if (errno != 0) {
226 ret = -errno;
227 pr_warning("Failed to parse %s as a pid: %s\n", str,
228 strerror(errno));
229 return ret;
230 }
231 nsip = nsinfo__new(ns_pid);
232 if (nsip && nsip->need_setns)
233 params.nsi = nsinfo__get(nsip);
234 nsinfo__put(nsip);
235
236 ret = 0;
237 }
238
239 return ret;
240}
241
242
211/* Command option callbacks */ 243/* Command option callbacks */
212 244
213#ifdef HAVE_DWARF_SUPPORT 245#ifdef HAVE_DWARF_SUPPORT
@@ -299,6 +331,7 @@ static void cleanup_params(void)
299 line_range__clear(&params.line_range); 331 line_range__clear(&params.line_range);
300 free(params.target); 332 free(params.target);
301 strfilter__delete(params.filter); 333 strfilter__delete(params.filter);
334 nsinfo__put(params.nsi);
302 memset(&params, 0, sizeof(params)); 335 memset(&params, 0, sizeof(params));
303} 336}
304 337
@@ -383,7 +416,7 @@ static int del_perf_probe_caches(struct strfilter *filter)
383 } 416 }
384 417
385 strlist__for_each_entry(nd, bidlist) { 418 strlist__for_each_entry(nd, bidlist) {
386 cache = probe_cache__new(nd->s); 419 cache = probe_cache__new(nd->s, NULL);
387 if (!cache) 420 if (!cache)
388 continue; 421 continue;
389 if (probe_cache__filter_purge(cache, filter) < 0 || 422 if (probe_cache__filter_purge(cache, filter) < 0 ||
@@ -554,6 +587,8 @@ __cmd_probe(int argc, const char **argv)
554 OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"), 587 OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
555 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 588 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
556 "Look for files with symbols relative to this directory"), 589 "Look for files with symbols relative to this directory"),
590 OPT_CALLBACK(0, "target-ns", NULL, "pid",
591 "target pid for namespace contexts", opt_set_target_ns),
557 OPT_END() 592 OPT_END()
558 }; 593 };
559 int ret; 594 int ret;
@@ -634,15 +669,15 @@ __cmd_probe(int argc, const char **argv)
634 pr_err_with_code(" Error: Failed to show event list.", ret); 669 pr_err_with_code(" Error: Failed to show event list.", ret);
635 return ret; 670 return ret;
636 case 'F': 671 case 'F':
637 ret = show_available_funcs(params.target, params.filter, 672 ret = show_available_funcs(params.target, params.nsi,
638 params.uprobes); 673 params.filter, params.uprobes);
639 if (ret < 0) 674 if (ret < 0)
640 pr_err_with_code(" Error: Failed to show functions.", ret); 675 pr_err_with_code(" Error: Failed to show functions.", ret);
641 return ret; 676 return ret;
642#ifdef HAVE_DWARF_SUPPORT 677#ifdef HAVE_DWARF_SUPPORT
643 case 'L': 678 case 'L':
644 ret = show_line_range(&params.line_range, params.target, 679 ret = show_line_range(&params.line_range, params.target,
645 params.uprobes); 680 params.nsi, params.uprobes);
646 if (ret < 0) 681 if (ret < 0)
647 pr_err_with_code(" Error: Failed to show lines.", ret); 682 pr_err_with_code(" Error: Failed to show lines.", ret);
648 return ret; 683 return ret;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 17a14bcce34a..3d7f33e19df2 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * builtin-record.c 3 * builtin-record.c
3 * 4 *
@@ -66,7 +67,7 @@ struct record {
66 struct perf_tool tool; 67 struct perf_tool tool;
67 struct record_opts opts; 68 struct record_opts opts;
68 u64 bytes_written; 69 u64 bytes_written;
69 struct perf_data_file file; 70 struct perf_data data;
70 struct auxtrace_record *itr; 71 struct auxtrace_record *itr;
71 struct perf_evlist *evlist; 72 struct perf_evlist *evlist;
72 struct perf_session *session; 73 struct perf_session *session;
@@ -107,7 +108,7 @@ static bool switch_output_time(struct record *rec)
107 108
108static int record__write(struct record *rec, void *bf, size_t size) 109static int record__write(struct record *rec, void *bf, size_t size)
109{ 110{
110 if (perf_data_file__write(rec->session->file, bf, size) < 0) { 111 if (perf_data__write(rec->session->data, bf, size) < 0) {
111 pr_err("failed to write perf data, error: %m\n"); 112 pr_err("failed to write perf data, error: %m\n");
112 return -1; 113 return -1;
113 } 114 }
@@ -129,107 +130,12 @@ static int process_synthesized_event(struct perf_tool *tool,
129 return record__write(rec, event, event->header.size); 130 return record__write(rec, event, event->header.size);
130} 131}
131 132
132static int 133static int record__pushfn(void *to, void *bf, size_t size)
133backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end)
134{ 134{
135 struct perf_event_header *pheader; 135 struct record *rec = to;
136 u64 evt_head = head;
137 int size = mask + 1;
138
139 pr_debug2("backward_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head);
140 pheader = (struct perf_event_header *)(buf + (head & mask));
141 *start = head;
142 while (true) {
143 if (evt_head - head >= (unsigned int)size) {
144 pr_debug("Finished reading backward ring buffer: rewind\n");
145 if (evt_head - head > (unsigned int)size)
146 evt_head -= pheader->size;
147 *end = evt_head;
148 return 0;
149 }
150
151 pheader = (struct perf_event_header *)(buf + (evt_head & mask));
152
153 if (pheader->size == 0) {
154 pr_debug("Finished reading backward ring buffer: get start\n");
155 *end = evt_head;
156 return 0;
157 }
158
159 evt_head += pheader->size;
160 pr_debug3("move evt_head: %"PRIx64"\n", evt_head);
161 }
162 WARN_ONCE(1, "Shouldn't get here\n");
163 return -1;
164}
165
166static int
167rb_find_range(void *data, int mask, u64 head, u64 old,
168 u64 *start, u64 *end, bool backward)
169{
170 if (!backward) {
171 *start = old;
172 *end = head;
173 return 0;
174 }
175
176 return backward_rb_find_range(data, mask, head, start, end);
177}
178
179static int
180record__mmap_read(struct record *rec, struct perf_mmap *md,
181 bool overwrite, bool backward)
182{
183 u64 head = perf_mmap__read_head(md);
184 u64 old = md->prev;
185 u64 end = head, start = old;
186 unsigned char *data = md->base + page_size;
187 unsigned long size;
188 void *buf;
189 int rc = 0;
190
191 if (rb_find_range(data, md->mask, head,
192 old, &start, &end, backward))
193 return -1;
194
195 if (start == end)
196 return 0;
197 136
198 rec->samples++; 137 rec->samples++;
199 138 return record__write(rec, bf, size);
200 size = end - start;
201 if (size > (unsigned long)(md->mask) + 1) {
202 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
203
204 md->prev = head;
205 perf_mmap__consume(md, overwrite || backward);
206 return 0;
207 }
208
209 if ((start & md->mask) + size != (end & md->mask)) {
210 buf = &data[start & md->mask];
211 size = md->mask + 1 - (start & md->mask);
212 start += size;
213
214 if (record__write(rec, buf, size) < 0) {
215 rc = -1;
216 goto out;
217 }
218 }
219
220 buf = &data[start & md->mask];
221 size = end - start;
222 start += size;
223
224 if (record__write(rec, buf, size) < 0) {
225 rc = -1;
226 goto out;
227 }
228
229 md->prev = head;
230 perf_mmap__consume(md, overwrite || backward);
231out:
232 return rc;
233} 139}
234 140
235static volatile int done; 141static volatile int done;
@@ -268,13 +174,13 @@ static int record__process_auxtrace(struct perf_tool *tool,
268 size_t len1, void *data2, size_t len2) 174 size_t len1, void *data2, size_t len2)
269{ 175{
270 struct record *rec = container_of(tool, struct record, tool); 176 struct record *rec = container_of(tool, struct record, tool);
271 struct perf_data_file *file = &rec->file; 177 struct perf_data *data = &rec->data;
272 size_t padding; 178 size_t padding;
273 u8 pad[8] = {0}; 179 u8 pad[8] = {0};
274 180
275 if (!perf_data_file__is_pipe(file)) { 181 if (!perf_data__is_pipe(data)) {
276 off_t file_offset; 182 off_t file_offset;
277 int fd = perf_data_file__fd(file); 183 int fd = perf_data__fd(data);
278 int err; 184 int err;
279 185
280 file_offset = lseek(fd, 0, SEEK_CUR); 186 file_offset = lseek(fd, 0, SEEK_CUR);
@@ -493,10 +399,10 @@ static int process_sample_event(struct perf_tool *tool,
493 399
494static int process_buildids(struct record *rec) 400static int process_buildids(struct record *rec)
495{ 401{
496 struct perf_data_file *file = &rec->file; 402 struct perf_data *data = &rec->data;
497 struct perf_session *session = rec->session; 403 struct perf_session *session = rec->session;
498 404
499 if (file->size == 0) 405 if (data->size == 0)
500 return 0; 406 return 0;
501 407
502 /* 408 /*
@@ -576,8 +482,7 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
576 struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap; 482 struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
577 483
578 if (maps[i].base) { 484 if (maps[i].base) {
579 if (record__mmap_read(rec, &maps[i], 485 if (perf_mmap__push(&maps[i], evlist->overwrite, backward, rec, record__pushfn) != 0) {
580 evlist->overwrite, backward) != 0) {
581 rc = -1; 486 rc = -1;
582 goto out; 487 goto out;
583 } 488 }
@@ -640,14 +545,14 @@ static void record__init_features(struct record *rec)
640static void 545static void
641record__finish_output(struct record *rec) 546record__finish_output(struct record *rec)
642{ 547{
643 struct perf_data_file *file = &rec->file; 548 struct perf_data *data = &rec->data;
644 int fd = perf_data_file__fd(file); 549 int fd = perf_data__fd(data);
645 550
646 if (file->is_pipe) 551 if (data->is_pipe)
647 return; 552 return;
648 553
649 rec->session->header.data_size += rec->bytes_written; 554 rec->session->header.data_size += rec->bytes_written;
650 file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 555 data->size = lseek(perf_data__fd(data), 0, SEEK_CUR);
651 556
652 if (!rec->no_buildid) { 557 if (!rec->no_buildid) {
653 process_buildids(rec); 558 process_buildids(rec);
@@ -686,7 +591,7 @@ static int record__synthesize(struct record *rec, bool tail);
686static int 591static int
687record__switch_output(struct record *rec, bool at_exit) 592record__switch_output(struct record *rec, bool at_exit)
688{ 593{
689 struct perf_data_file *file = &rec->file; 594 struct perf_data *data = &rec->data;
690 int fd, err; 595 int fd, err;
691 596
692 /* Same Size: "2015122520103046"*/ 597 /* Same Size: "2015122520103046"*/
@@ -704,7 +609,7 @@ record__switch_output(struct record *rec, bool at_exit)
704 return -EINVAL; 609 return -EINVAL;
705 } 610 }
706 611
707 fd = perf_data_file__switch(file, timestamp, 612 fd = perf_data__switch(data, timestamp,
708 rec->session->header.data_offset, 613 rec->session->header.data_offset,
709 at_exit); 614 at_exit);
710 if (fd >= 0 && !at_exit) { 615 if (fd >= 0 && !at_exit) {
@@ -714,7 +619,7 @@ record__switch_output(struct record *rec, bool at_exit)
714 619
715 if (!quiet) 620 if (!quiet)
716 fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 621 fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
717 file->path, timestamp); 622 data->file.path, timestamp);
718 623
719 /* Output tracking events */ 624 /* Output tracking events */
720 if (!at_exit) { 625 if (!at_exit) {
@@ -789,16 +694,23 @@ static int record__synthesize(struct record *rec, bool tail)
789{ 694{
790 struct perf_session *session = rec->session; 695 struct perf_session *session = rec->session;
791 struct machine *machine = &session->machines.host; 696 struct machine *machine = &session->machines.host;
792 struct perf_data_file *file = &rec->file; 697 struct perf_data *data = &rec->data;
793 struct record_opts *opts = &rec->opts; 698 struct record_opts *opts = &rec->opts;
794 struct perf_tool *tool = &rec->tool; 699 struct perf_tool *tool = &rec->tool;
795 int fd = perf_data_file__fd(file); 700 int fd = perf_data__fd(data);
796 int err = 0; 701 int err = 0;
797 702
798 if (rec->opts.tail_synthesize != tail) 703 if (rec->opts.tail_synthesize != tail)
799 return 0; 704 return 0;
800 705
801 if (file->is_pipe) { 706 if (data->is_pipe) {
707 err = perf_event__synthesize_features(
708 tool, session, rec->evlist, process_synthesized_event);
709 if (err < 0) {
710 pr_err("Couldn't synthesize features.\n");
711 return err;
712 }
713
802 err = perf_event__synthesize_attrs(tool, session, 714 err = perf_event__synthesize_attrs(tool, session,
803 process_synthesized_event); 715 process_synthesized_event);
804 if (err < 0) { 716 if (err < 0) {
@@ -856,7 +768,7 @@ static int record__synthesize(struct record *rec, bool tail)
856 768
857 err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 769 err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
858 process_synthesized_event, opts->sample_address, 770 process_synthesized_event, opts->sample_address,
859 opts->proc_map_timeout); 771 opts->proc_map_timeout, 1);
860out: 772out:
861 return err; 773 return err;
862} 774}
@@ -870,7 +782,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
870 struct machine *machine; 782 struct machine *machine;
871 struct perf_tool *tool = &rec->tool; 783 struct perf_tool *tool = &rec->tool;
872 struct record_opts *opts = &rec->opts; 784 struct record_opts *opts = &rec->opts;
873 struct perf_data_file *file = &rec->file; 785 struct perf_data *data = &rec->data;
874 struct perf_session *session; 786 struct perf_session *session;
875 bool disabled = false, draining = false; 787 bool disabled = false, draining = false;
876 int fd; 788 int fd;
@@ -896,20 +808,20 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
896 signal(SIGUSR2, SIG_IGN); 808 signal(SIGUSR2, SIG_IGN);
897 } 809 }
898 810
899 session = perf_session__new(file, false, tool); 811 session = perf_session__new(data, false, tool);
900 if (session == NULL) { 812 if (session == NULL) {
901 pr_err("Perf session creation failed.\n"); 813 pr_err("Perf session creation failed.\n");
902 return -1; 814 return -1;
903 } 815 }
904 816
905 fd = perf_data_file__fd(file); 817 fd = perf_data__fd(data);
906 rec->session = session; 818 rec->session = session;
907 819
908 record__init_features(rec); 820 record__init_features(rec);
909 821
910 if (forks) { 822 if (forks) {
911 err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 823 err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
912 argv, file->is_pipe, 824 argv, data->is_pipe,
913 workload_exec_failed_signal); 825 workload_exec_failed_signal);
914 if (err < 0) { 826 if (err < 0) {
915 pr_err("Couldn't run the workload!\n"); 827 pr_err("Couldn't run the workload!\n");
@@ -945,7 +857,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
945 if (!rec->evlist->nr_groups) 857 if (!rec->evlist->nr_groups)
946 perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 858 perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
947 859
948 if (file->is_pipe) { 860 if (data->is_pipe) {
949 err = perf_header__write_pipe(fd); 861 err = perf_header__write_pipe(fd);
950 if (err < 0) 862 if (err < 0)
951 goto out_child; 863 goto out_child;
@@ -1206,8 +1118,8 @@ out_child:
1206 samples[0] = '\0'; 1118 samples[0] = '\0';
1207 1119
1208 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", 1120 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
1209 perf_data_file__size(file) / 1024.0 / 1024.0, 1121 perf_data__size(data) / 1024.0 / 1024.0,
1210 file->path, postfix, samples); 1122 data->file.path, postfix, samples);
1211 } 1123 }
1212 1124
1213out_delete_session: 1125out_delete_session:
@@ -1571,7 +1483,7 @@ static struct option __record_options[] = {
1571 OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1483 OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1572 "list of cpus to monitor"), 1484 "list of cpus to monitor"),
1573 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1485 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1574 OPT_STRING('o', "output", &record.file.path, "file", 1486 OPT_STRING('o', "output", &record.data.file.path, "file",
1575 "output file name"), 1487 "output file name"),
1576 OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 1488 OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
1577 &record.opts.no_inherit_set, 1489 &record.opts.no_inherit_set,
@@ -1597,6 +1509,8 @@ static struct option __record_options[] = {
1597 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1509 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1598 "per thread counts"), 1510 "per thread counts"),
1599 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 1511 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
1512 OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
1513 "Record the sample physical addresses"),
1600 OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), 1514 OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
1601 OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 1515 OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
1602 &record.opts.sample_time_set, 1516 &record.opts.sample_time_set,
@@ -1634,6 +1548,9 @@ static struct option __record_options[] = {
1634 OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1548 OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
1635 "sample selected machine registers on interrupt," 1549 "sample selected machine registers on interrupt,"
1636 " use -I ? to list register names", parse_regs), 1550 " use -I ? to list register names", parse_regs),
1551 OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register",
1552 "sample selected machine registers on interrupt,"
1553 " use -I ? to list register names", parse_regs),
1637 OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 1554 OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
1638 "Record running/enabled time of read (:S) events"), 1555 "Record running/enabled time of read (:S) events"),
1639 OPT_CALLBACK('k', "clockid", &record.opts, 1556 OPT_CALLBACK('k', "clockid", &record.opts,
@@ -1821,7 +1738,7 @@ int cmd_record(int argc, const char **argv)
1821 record.opts.tail_synthesize = true; 1738 record.opts.tail_synthesize = true;
1822 1739
1823 if (rec->evlist->nr_entries == 0 && 1740 if (rec->evlist->nr_entries == 0 &&
1824 perf_evlist__add_default(rec->evlist) < 0) { 1741 __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) {
1825 pr_err("Not enough memory for event selector list\n"); 1742 pr_err("Not enough memory for event selector list\n");
1826 goto out; 1743 goto out;
1827 } 1744 }
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 79a33eb1a10d..1394cd8d96f7 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * builtin-report.c 3 * builtin-report.c
3 * 4 *
@@ -38,6 +39,7 @@
38#include "util/time-utils.h" 39#include "util/time-utils.h"
39#include "util/auxtrace.h" 40#include "util/auxtrace.h"
40#include "util/units.h" 41#include "util/units.h"
42#include "util/branch.h"
41 43
42#include <dlfcn.h> 44#include <dlfcn.h>
43#include <errno.h> 45#include <errno.h>
@@ -73,6 +75,7 @@ struct report {
73 u64 queue_size; 75 u64 queue_size;
74 int socket_filter; 76 int socket_filter;
75 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 77 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
78 struct branch_type_stat brtype_stat;
76}; 79};
77 80
78static int report__config(const char *var, const char *value, void *cb) 81static int report__config(const char *var, const char *value, void *cb)
@@ -113,43 +116,60 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
113 struct report *rep = arg; 116 struct report *rep = arg;
114 struct hist_entry *he = iter->he; 117 struct hist_entry *he = iter->he;
115 struct perf_evsel *evsel = iter->evsel; 118 struct perf_evsel *evsel = iter->evsel;
119 struct perf_sample *sample = iter->sample;
116 struct mem_info *mi; 120 struct mem_info *mi;
117 struct branch_info *bi; 121 struct branch_info *bi;
118 122
119 if (!ui__has_annotation()) 123 if (!ui__has_annotation())
120 return 0; 124 return 0;
121 125
122 hist__account_cycles(iter->sample->branch_stack, al, iter->sample, 126 hist__account_cycles(sample->branch_stack, al, sample,
123 rep->nonany_branch_mode); 127 rep->nonany_branch_mode);
124 128
125 if (sort__mode == SORT_MODE__BRANCH) { 129 if (sort__mode == SORT_MODE__BRANCH) {
126 bi = he->branch_info; 130 bi = he->branch_info;
127 err = addr_map_symbol__inc_samples(&bi->from, evsel->idx); 131 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel->idx);
128 if (err) 132 if (err)
129 goto out; 133 goto out;
130 134
131 err = addr_map_symbol__inc_samples(&bi->to, evsel->idx); 135 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel->idx);
132 136
133 } else if (rep->mem_mode) { 137 } else if (rep->mem_mode) {
134 mi = he->mem_info; 138 mi = he->mem_info;
135 err = addr_map_symbol__inc_samples(&mi->daddr, evsel->idx); 139 err = addr_map_symbol__inc_samples(&mi->daddr, sample, evsel->idx);
136 if (err) 140 if (err)
137 goto out; 141 goto out;
138 142
139 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 143 err = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr);
140 144
141 } else if (symbol_conf.cumulate_callchain) { 145 } else if (symbol_conf.cumulate_callchain) {
142 if (single) 146 if (single)
143 err = hist_entry__inc_addr_samples(he, evsel->idx, 147 err = hist_entry__inc_addr_samples(he, sample, evsel->idx,
144 al->addr); 148 al->addr);
145 } else { 149 } else {
146 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 150 err = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr);
147 } 151 }
148 152
149out: 153out:
150 return err; 154 return err;
151} 155}
152 156
157static int hist_iter__branch_callback(struct hist_entry_iter *iter,
158 struct addr_location *al __maybe_unused,
159 bool single __maybe_unused,
160 void *arg)
161{
162 struct hist_entry *he = iter->he;
163 struct report *rep = arg;
164 struct branch_info *bi;
165
166 bi = he->branch_info;
167 branch_type_count(&rep->brtype_stat, &bi->flags,
168 bi->from.addr, bi->to.addr);
169
170 return 0;
171}
172
153static int process_sample_event(struct perf_tool *tool, 173static int process_sample_event(struct perf_tool *tool,
154 union perf_event *event, 174 union perf_event *event,
155 struct perf_sample *sample, 175 struct perf_sample *sample,
@@ -188,6 +208,8 @@ static int process_sample_event(struct perf_tool *tool,
188 */ 208 */
189 if (!sample->branch_stack) 209 if (!sample->branch_stack)
190 goto out_put; 210 goto out_put;
211
212 iter.add_entry_cb = hist_iter__branch_callback;
191 iter.ops = &hist_iter_branch; 213 iter.ops = &hist_iter_branch;
192 } else if (rep->mem_mode) { 214 } else if (rep->mem_mode) {
193 iter.ops = &hist_iter_mem; 215 iter.ops = &hist_iter_mem;
@@ -220,7 +242,7 @@ static int process_read_event(struct perf_tool *tool,
220 const char *name = evsel ? perf_evsel__name(evsel) : "unknown"; 242 const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
221 int err = perf_read_values_add_value(&rep->show_threads_values, 243 int err = perf_read_values_add_value(&rep->show_threads_values,
222 event->read.pid, event->read.tid, 244 event->read.pid, event->read.tid,
223 event->read.id, 245 evsel->idx,
224 name, 246 name,
225 event->read.value); 247 event->read.value);
226 248
@@ -228,10 +250,6 @@ static int process_read_event(struct perf_tool *tool,
228 return err; 250 return err;
229 } 251 }
230 252
231 dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
232 evsel ? perf_evsel__name(evsel) : "FAIL",
233 event->read.value);
234
235 return 0; 253 return 0;
236} 254}
237 255
@@ -240,7 +258,7 @@ static int report__setup_sample_type(struct report *rep)
240{ 258{
241 struct perf_session *session = rep->session; 259 struct perf_session *session = rep->session;
242 u64 sample_type = perf_evlist__combined_sample_type(session->evlist); 260 u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
243 bool is_pipe = perf_data_file__is_pipe(session->file); 261 bool is_pipe = perf_data__is_pipe(session->data);
244 262
245 if (session->itrace_synth_opts->callchain || 263 if (session->itrace_synth_opts->callchain ||
246 (!is_pipe && 264 (!is_pipe &&
@@ -258,10 +276,11 @@ static int report__setup_sample_type(struct report *rep)
258 "'perf record' without -g?\n"); 276 "'perf record' without -g?\n");
259 return -EINVAL; 277 return -EINVAL;
260 } 278 }
261 if (symbol_conf.use_callchain) { 279 if (symbol_conf.use_callchain &&
262 ui__error("Selected -g or --branch-history but no " 280 !symbol_conf.show_branchflag_count) {
263 "callchain data. Did\n" 281 ui__error("Selected -g or --branch-history.\n"
264 "you call 'perf record' without -g?\n"); 282 "But no callchain or branch data.\n"
283 "Did you call 'perf record' without -g or -b?\n");
265 return -1; 284 return -1;
266 } 285 }
267 } else if (!callchain_param.enabled && 286 } else if (!callchain_param.enabled &&
@@ -396,7 +415,8 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
396 415
397 hists__fprintf_nr_sample_events(hists, rep, evname, stdout); 416 hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
398 hists__fprintf(hists, !quiet, 0, 0, rep->min_percent, stdout, 417 hists__fprintf(hists, !quiet, 0, 0, rep->min_percent, stdout,
399 symbol_conf.use_callchain); 418 symbol_conf.use_callchain ||
419 symbol_conf.show_branchflag_count);
400 fprintf(stdout, "\n\n"); 420 fprintf(stdout, "\n\n");
401 } 421 }
402 422
@@ -410,6 +430,9 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
410 perf_read_values_destroy(&rep->show_threads_values); 430 perf_read_values_destroy(&rep->show_threads_values);
411 } 431 }
412 432
433 if (sort__mode == SORT_MODE__BRANCH)
434 branch_type_stat_display(stdout, &rep->brtype_stat);
435
413 return 0; 436 return 0;
414} 437}
415 438
@@ -546,7 +569,7 @@ static int __cmd_report(struct report *rep)
546 int ret; 569 int ret;
547 struct perf_session *session = rep->session; 570 struct perf_session *session = rep->session;
548 struct perf_evsel *pos; 571 struct perf_evsel *pos;
549 struct perf_data_file *file = session->file; 572 struct perf_data *data = session->data;
550 573
551 signal(SIGINT, sig_handler); 574 signal(SIGINT, sig_handler);
552 575
@@ -615,7 +638,7 @@ static int __cmd_report(struct report *rep)
615 rep->nr_entries += evsel__hists(pos)->nr_entries; 638 rep->nr_entries += evsel__hists(pos)->nr_entries;
616 639
617 if (rep->nr_entries == 0) { 640 if (rep->nr_entries == 0) {
618 ui__error("The %s file has no samples!\n", file->path); 641 ui__error("The %s file has no samples!\n", data->file.path);
619 return 0; 642 return 0;
620 } 643 }
621 644
@@ -718,6 +741,7 @@ int cmd_report(int argc, const char **argv)
718 .id_index = perf_event__process_id_index, 741 .id_index = perf_event__process_id_index,
719 .auxtrace_info = perf_event__process_auxtrace_info, 742 .auxtrace_info = perf_event__process_auxtrace_info,
720 .auxtrace = perf_event__process_auxtrace, 743 .auxtrace = perf_event__process_auxtrace,
744 .feature = perf_event__process_feature,
721 .ordered_events = true, 745 .ordered_events = true,
722 .ordering_requires_timestamps = true, 746 .ordering_requires_timestamps = true,
723 }, 747 },
@@ -856,7 +880,7 @@ int cmd_report(int argc, const char **argv)
856 "Show inline function"), 880 "Show inline function"),
857 OPT_END() 881 OPT_END()
858 }; 882 };
859 struct perf_data_file file = { 883 struct perf_data data = {
860 .mode = PERF_DATA_MODE_READ, 884 .mode = PERF_DATA_MODE_READ,
861 }; 885 };
862 int ret = hists__init(); 886 int ret = hists__init();
@@ -917,11 +941,11 @@ int cmd_report(int argc, const char **argv)
917 input_name = "perf.data"; 941 input_name = "perf.data";
918 } 942 }
919 943
920 file.path = input_name; 944 data.file.path = input_name;
921 file.force = symbol_conf.force; 945 data.force = symbol_conf.force;
922 946
923repeat: 947repeat:
924 session = perf_session__new(&file, false, &report.tool); 948 session = perf_session__new(&data, false, &report.tool);
925 if (session == NULL) 949 if (session == NULL)
926 return -1; 950 return -1;
927 951
@@ -943,6 +967,8 @@ repeat:
943 if (has_br_stack && branch_call_mode) 967 if (has_br_stack && branch_call_mode)
944 symbol_conf.show_branchflag_count = true; 968 symbol_conf.show_branchflag_count = true;
945 969
970 memset(&report.brtype_stat, 0, sizeof(struct branch_type_stat));
971
946 /* 972 /*
947 * Branch mode is a tristate: 973 * Branch mode is a tristate:
948 * -1 means default, so decide based on the file having branch data. 974 * -1 means default, so decide based on the file having branch data.
@@ -988,6 +1014,10 @@ repeat:
988 /* Force tty output for header output and per-thread stat. */ 1014 /* Force tty output for header output and per-thread stat. */
989 if (report.header || report.header_only || report.show_threads) 1015 if (report.header || report.header_only || report.show_threads)
990 use_browser = 0; 1016 use_browser = 0;
1017 if (report.header || report.header_only)
1018 report.tool.show_feat_hdr = SHOW_FEAT_HEADER;
1019 if (report.show_full_info)
1020 report.tool.show_feat_hdr = SHOW_FEAT_HEADER_FULL_INFO;
991 1021
992 if (strcmp(input_name, "-") != 0) 1022 if (strcmp(input_name, "-") != 0)
993 setup_browser(true); 1023 setup_browser(true);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 322b4def8411..83283fedb00f 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "builtin.h" 2#include "builtin.h"
2#include "perf.h" 3#include "perf.h"
3 4
@@ -1700,14 +1701,16 @@ static int perf_sched__read_events(struct perf_sched *sched)
1700 { "sched:sched_migrate_task", process_sched_migrate_task_event, }, 1701 { "sched:sched_migrate_task", process_sched_migrate_task_event, },
1701 }; 1702 };
1702 struct perf_session *session; 1703 struct perf_session *session;
1703 struct perf_data_file file = { 1704 struct perf_data data = {
1704 .path = input_name, 1705 .file = {
1705 .mode = PERF_DATA_MODE_READ, 1706 .path = input_name,
1706 .force = sched->force, 1707 },
1708 .mode = PERF_DATA_MODE_READ,
1709 .force = sched->force,
1707 }; 1710 };
1708 int rc = -1; 1711 int rc = -1;
1709 1712
1710 session = perf_session__new(&file, false, &sched->tool); 1713 session = perf_session__new(&data, false, &sched->tool);
1711 if (session == NULL) { 1714 if (session == NULL) {
1712 pr_debug("No Memory for session\n"); 1715 pr_debug("No Memory for session\n");
1713 return -1; 1716 return -1;
@@ -2902,10 +2905,12 @@ static int perf_sched__timehist(struct perf_sched *sched)
2902 const struct perf_evsel_str_handler migrate_handlers[] = { 2905 const struct perf_evsel_str_handler migrate_handlers[] = {
2903 { "sched:sched_migrate_task", timehist_migrate_task_event, }, 2906 { "sched:sched_migrate_task", timehist_migrate_task_event, },
2904 }; 2907 };
2905 struct perf_data_file file = { 2908 struct perf_data data = {
2906 .path = input_name, 2909 .file = {
2907 .mode = PERF_DATA_MODE_READ, 2910 .path = input_name,
2908 .force = sched->force, 2911 },
2912 .mode = PERF_DATA_MODE_READ,
2913 .force = sched->force,
2909 }; 2914 };
2910 2915
2911 struct perf_session *session; 2916 struct perf_session *session;
@@ -2930,7 +2935,7 @@ static int perf_sched__timehist(struct perf_sched *sched)
2930 2935
2931 symbol_conf.use_callchain = sched->show_callchain; 2936 symbol_conf.use_callchain = sched->show_callchain;
2932 2937
2933 session = perf_session__new(&file, false, &sched->tool); 2938 session = perf_session__new(&data, false, &sched->tool);
2934 if (session == NULL) 2939 if (session == NULL)
2935 return -ENOMEM; 2940 return -ENOMEM;
2936 2941
@@ -3363,6 +3368,10 @@ int cmd_sched(int argc, const char **argv)
3363 OPT_STRING(0, "time", &sched.time_str, "str", 3368 OPT_STRING(0, "time", &sched.time_str, "str",
3364 "Time span for analysis (start,stop)"), 3369 "Time span for analysis (start,stop)"),
3365 OPT_BOOLEAN(0, "state", &sched.show_state, "Show task state when sched-out"), 3370 OPT_BOOLEAN(0, "state", &sched.show_state, "Show task state when sched-out"),
3371 OPT_STRING('p', "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
3372 "analyze events only for given process id(s)"),
3373 OPT_STRING('t', "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
3374 "analyze events only for given thread id(s)"),
3366 OPT_PARENT(sched_options) 3375 OPT_PARENT(sched_options)
3367 }; 3376 };
3368 3377
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 83cdc0a61fd6..68f36dc0344f 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "builtin.h" 2#include "builtin.h"
2 3
3#include "perf.h" 4#include "perf.h"
@@ -87,6 +88,8 @@ enum perf_output_field {
87 PERF_OUTPUT_BRSTACKINSN = 1U << 23, 88 PERF_OUTPUT_BRSTACKINSN = 1U << 23,
88 PERF_OUTPUT_BRSTACKOFF = 1U << 24, 89 PERF_OUTPUT_BRSTACKOFF = 1U << 24,
89 PERF_OUTPUT_SYNTH = 1U << 25, 90 PERF_OUTPUT_SYNTH = 1U << 25,
91 PERF_OUTPUT_PHYS_ADDR = 1U << 26,
92 PERF_OUTPUT_UREGS = 1U << 27,
90}; 93};
91 94
92struct output_option { 95struct output_option {
@@ -108,6 +111,7 @@ struct output_option {
108 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, 111 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
109 {.str = "period", .field = PERF_OUTPUT_PERIOD}, 112 {.str = "period", .field = PERF_OUTPUT_PERIOD},
110 {.str = "iregs", .field = PERF_OUTPUT_IREGS}, 113 {.str = "iregs", .field = PERF_OUTPUT_IREGS},
114 {.str = "uregs", .field = PERF_OUTPUT_UREGS},
111 {.str = "brstack", .field = PERF_OUTPUT_BRSTACK}, 115 {.str = "brstack", .field = PERF_OUTPUT_BRSTACK},
112 {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM}, 116 {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM},
113 {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC}, 117 {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC},
@@ -119,6 +123,7 @@ struct output_option {
119 {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN}, 123 {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},
120 {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF}, 124 {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF},
121 {.str = "synth", .field = PERF_OUTPUT_SYNTH}, 125 {.str = "synth", .field = PERF_OUTPUT_SYNTH},
126 {.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR},
122}; 127};
123 128
124enum { 129enum {
@@ -175,7 +180,8 @@ static struct {
175 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 180 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
176 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | 181 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
177 PERF_OUTPUT_PERIOD | PERF_OUTPUT_ADDR | 182 PERF_OUTPUT_PERIOD | PERF_OUTPUT_ADDR |
178 PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT, 183 PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT |
184 PERF_OUTPUT_PHYS_ADDR,
179 185
180 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, 186 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
181 }, 187 },
@@ -205,6 +211,51 @@ static struct {
205 }, 211 },
206}; 212};
207 213
214struct perf_evsel_script {
215 char *filename;
216 FILE *fp;
217 u64 samples;
218};
219
220static struct perf_evsel_script *perf_evsel_script__new(struct perf_evsel *evsel,
221 struct perf_data *data)
222{
223 struct perf_evsel_script *es = malloc(sizeof(*es));
224
225 if (es != NULL) {
226 if (asprintf(&es->filename, "%s.%s.dump", data->file.path, perf_evsel__name(evsel)) < 0)
227 goto out_free;
228 es->fp = fopen(es->filename, "w");
229 if (es->fp == NULL)
230 goto out_free_filename;
231 es->samples = 0;
232 }
233
234 return es;
235out_free_filename:
236 zfree(&es->filename);
237out_free:
238 free(es);
239 return NULL;
240}
241
242static void perf_evsel_script__delete(struct perf_evsel_script *es)
243{
244 zfree(&es->filename);
245 fclose(es->fp);
246 es->fp = NULL;
247 free(es);
248}
249
250static int perf_evsel_script__fprintf(struct perf_evsel_script *es, FILE *fp)
251{
252 struct stat st;
253
254 fstat(fileno(es->fp), &st);
255 return fprintf(fp, "[ perf script: Wrote %.3f MB %s (%" PRIu64 " samples) ]\n",
256 st.st_size / 1024.0 / 1024.0, es->filename, es->samples);
257}
258
208static inline int output_type(unsigned int type) 259static inline int output_type(unsigned int type)
209{ 260{
210 switch (type) { 261 switch (type) {
@@ -382,6 +433,16 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
382 PERF_OUTPUT_IREGS)) 433 PERF_OUTPUT_IREGS))
383 return -EINVAL; 434 return -EINVAL;
384 435
436 if (PRINT_FIELD(UREGS) &&
437 perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_USER, "UREGS",
438 PERF_OUTPUT_UREGS))
439 return -EINVAL;
440
441 if (PRINT_FIELD(PHYS_ADDR) &&
442 perf_evsel__check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR",
443 PERF_OUTPUT_PHYS_ADDR))
444 return -EINVAL;
445
385 return 0; 446 return 0;
386} 447}
387 448
@@ -485,51 +546,76 @@ out:
485 return 0; 546 return 0;
486} 547}
487 548
488static void print_sample_iregs(struct perf_sample *sample, 549static int perf_sample__fprintf_iregs(struct perf_sample *sample,
489 struct perf_event_attr *attr) 550 struct perf_event_attr *attr, FILE *fp)
490{ 551{
491 struct regs_dump *regs = &sample->intr_regs; 552 struct regs_dump *regs = &sample->intr_regs;
492 uint64_t mask = attr->sample_regs_intr; 553 uint64_t mask = attr->sample_regs_intr;
493 unsigned i = 0, r; 554 unsigned i = 0, r;
555 int printed = 0;
494 556
495 if (!regs) 557 if (!regs)
496 return; 558 return 0;
559
560 for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) {
561 u64 val = regs->regs[i++];
562 printed += fprintf(fp, "%5s:0x%"PRIx64" ", perf_reg_name(r), val);
563 }
564
565 return printed;
566}
567
568static int perf_sample__fprintf_uregs(struct perf_sample *sample,
569 struct perf_event_attr *attr, FILE *fp)
570{
571 struct regs_dump *regs = &sample->user_regs;
572 uint64_t mask = attr->sample_regs_user;
573 unsigned i = 0, r;
574 int printed = 0;
575
576 if (!regs || !regs->regs)
577 return 0;
578
579 printed += fprintf(fp, " ABI:%" PRIu64 " ", regs->abi);
497 580
498 for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) { 581 for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) {
499 u64 val = regs->regs[i++]; 582 u64 val = regs->regs[i++];
500 printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val); 583 printed += fprintf(fp, "%5s:0x%"PRIx64" ", perf_reg_name(r), val);
501 } 584 }
585
586 return printed;
502} 587}
503 588
504static void print_sample_start(struct perf_sample *sample, 589static int perf_sample__fprintf_start(struct perf_sample *sample,
505 struct thread *thread, 590 struct thread *thread,
506 struct perf_evsel *evsel) 591 struct perf_evsel *evsel, FILE *fp)
507{ 592{
508 struct perf_event_attr *attr = &evsel->attr; 593 struct perf_event_attr *attr = &evsel->attr;
509 unsigned long secs; 594 unsigned long secs;
510 unsigned long long nsecs; 595 unsigned long long nsecs;
596 int printed = 0;
511 597
512 if (PRINT_FIELD(COMM)) { 598 if (PRINT_FIELD(COMM)) {
513 if (latency_format) 599 if (latency_format)
514 printf("%8.8s ", thread__comm_str(thread)); 600 printed += fprintf(fp, "%8.8s ", thread__comm_str(thread));
515 else if (PRINT_FIELD(IP) && symbol_conf.use_callchain) 601 else if (PRINT_FIELD(IP) && symbol_conf.use_callchain)
516 printf("%s ", thread__comm_str(thread)); 602 printed += fprintf(fp, "%s ", thread__comm_str(thread));
517 else 603 else
518 printf("%16s ", thread__comm_str(thread)); 604 printed += fprintf(fp, "%16s ", thread__comm_str(thread));
519 } 605 }
520 606
521 if (PRINT_FIELD(PID) && PRINT_FIELD(TID)) 607 if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
522 printf("%5d/%-5d ", sample->pid, sample->tid); 608 printed += fprintf(fp, "%5d/%-5d ", sample->pid, sample->tid);
523 else if (PRINT_FIELD(PID)) 609 else if (PRINT_FIELD(PID))
524 printf("%5d ", sample->pid); 610 printed += fprintf(fp, "%5d ", sample->pid);
525 else if (PRINT_FIELD(TID)) 611 else if (PRINT_FIELD(TID))
526 printf("%5d ", sample->tid); 612 printed += fprintf(fp, "%5d ", sample->tid);
527 613
528 if (PRINT_FIELD(CPU)) { 614 if (PRINT_FIELD(CPU)) {
529 if (latency_format) 615 if (latency_format)
530 printf("%3d ", sample->cpu); 616 printed += fprintf(fp, "%3d ", sample->cpu);
531 else 617 else
532 printf("[%03d] ", sample->cpu); 618 printed += fprintf(fp, "[%03d] ", sample->cpu);
533 } 619 }
534 620
535 if (PRINT_FIELD(TIME)) { 621 if (PRINT_FIELD(TIME)) {
@@ -538,13 +624,15 @@ static void print_sample_start(struct perf_sample *sample,
538 nsecs -= secs * NSEC_PER_SEC; 624 nsecs -= secs * NSEC_PER_SEC;
539 625
540 if (nanosecs) 626 if (nanosecs)
541 printf("%5lu.%09llu: ", secs, nsecs); 627 printed += fprintf(fp, "%5lu.%09llu: ", secs, nsecs);
542 else { 628 else {
543 char sample_time[32]; 629 char sample_time[32];
544 timestamp__scnprintf_usec(sample->time, sample_time, sizeof(sample_time)); 630 timestamp__scnprintf_usec(sample->time, sample_time, sizeof(sample_time));
545 printf("%12s: ", sample_time); 631 printed += fprintf(fp, "%12s: ", sample_time);
546 } 632 }
547 } 633 }
634
635 return printed;
548} 636}
549 637
550static inline char 638static inline char
@@ -556,16 +644,17 @@ mispred_str(struct branch_entry *br)
556 return br->flags.predicted ? 'P' : 'M'; 644 return br->flags.predicted ? 'P' : 'M';
557} 645}
558 646
559static void print_sample_brstack(struct perf_sample *sample, 647static int perf_sample__fprintf_brstack(struct perf_sample *sample,
560 struct thread *thread, 648 struct thread *thread,
561 struct perf_event_attr *attr) 649 struct perf_event_attr *attr, FILE *fp)
562{ 650{
563 struct branch_stack *br = sample->branch_stack; 651 struct branch_stack *br = sample->branch_stack;
564 struct addr_location alf, alt; 652 struct addr_location alf, alt;
565 u64 i, from, to; 653 u64 i, from, to;
654 int printed = 0;
566 655
567 if (!(br && br->nr)) 656 if (!(br && br->nr))
568 return; 657 return 0;
569 658
570 for (i = 0; i < br->nr; i++) { 659 for (i = 0; i < br->nr; i++) {
571 from = br->entries[i].from; 660 from = br->entries[i].from;
@@ -578,38 +667,41 @@ static void print_sample_brstack(struct perf_sample *sample,
578 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt); 667 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt);
579 } 668 }
580 669
581 printf("0x%"PRIx64, from); 670 printed += fprintf(fp, " 0x%"PRIx64, from);
582 if (PRINT_FIELD(DSO)) { 671 if (PRINT_FIELD(DSO)) {
583 printf("("); 672 printed += fprintf(fp, "(");
584 map__fprintf_dsoname(alf.map, stdout); 673 printed += map__fprintf_dsoname(alf.map, fp);
585 printf(")"); 674 printed += fprintf(fp, ")");
586 } 675 }
587 676
588 printf("/0x%"PRIx64, to); 677 printed += fprintf(fp, "/0x%"PRIx64, to);
589 if (PRINT_FIELD(DSO)) { 678 if (PRINT_FIELD(DSO)) {
590 printf("("); 679 printed += fprintf(fp, "(");
591 map__fprintf_dsoname(alt.map, stdout); 680 printed += map__fprintf_dsoname(alt.map, fp);
592 printf(")"); 681 printed += fprintf(fp, ")");
593 } 682 }
594 683
595 printf("/%c/%c/%c/%d ", 684 printed += fprintf(fp, "/%c/%c/%c/%d ",
596 mispred_str( br->entries + i), 685 mispred_str( br->entries + i),
597 br->entries[i].flags.in_tx? 'X' : '-', 686 br->entries[i].flags.in_tx? 'X' : '-',
598 br->entries[i].flags.abort? 'A' : '-', 687 br->entries[i].flags.abort? 'A' : '-',
599 br->entries[i].flags.cycles); 688 br->entries[i].flags.cycles);
600 } 689 }
690
691 return printed;
601} 692}
602 693
603static void print_sample_brstacksym(struct perf_sample *sample, 694static int perf_sample__fprintf_brstacksym(struct perf_sample *sample,
604 struct thread *thread, 695 struct thread *thread,
605 struct perf_event_attr *attr) 696 struct perf_event_attr *attr, FILE *fp)
606{ 697{
607 struct branch_stack *br = sample->branch_stack; 698 struct branch_stack *br = sample->branch_stack;
608 struct addr_location alf, alt; 699 struct addr_location alf, alt;
609 u64 i, from, to; 700 u64 i, from, to;
701 int printed = 0;
610 702
611 if (!(br && br->nr)) 703 if (!(br && br->nr))
612 return; 704 return 0;
613 705
614 for (i = 0; i < br->nr; i++) { 706 for (i = 0; i < br->nr; i++) {
615 707
@@ -626,37 +718,40 @@ static void print_sample_brstacksym(struct perf_sample *sample,
626 if (alt.map) 718 if (alt.map)
627 alt.sym = map__find_symbol(alt.map, alt.addr); 719 alt.sym = map__find_symbol(alt.map, alt.addr);
628 720
629 symbol__fprintf_symname_offs(alf.sym, &alf, stdout); 721 printed += symbol__fprintf_symname_offs(alf.sym, &alf, fp);
630 if (PRINT_FIELD(DSO)) { 722 if (PRINT_FIELD(DSO)) {
631 printf("("); 723 printed += fprintf(fp, "(");
632 map__fprintf_dsoname(alf.map, stdout); 724 printed += map__fprintf_dsoname(alf.map, fp);
633 printf(")"); 725 printed += fprintf(fp, ")");
634 } 726 }
635 putchar('/'); 727 printed += fprintf(fp, "%c", '/');
636 symbol__fprintf_symname_offs(alt.sym, &alt, stdout); 728 printed += symbol__fprintf_symname_offs(alt.sym, &alt, fp);
637 if (PRINT_FIELD(DSO)) { 729 if (PRINT_FIELD(DSO)) {
638 printf("("); 730 printed += fprintf(fp, "(");
639 map__fprintf_dsoname(alt.map, stdout); 731 printed += map__fprintf_dsoname(alt.map, fp);
640 printf(")"); 732 printed += fprintf(fp, ")");
641 } 733 }
642 printf("/%c/%c/%c/%d ", 734 printed += fprintf(fp, "/%c/%c/%c/%d ",
643 mispred_str( br->entries + i), 735 mispred_str( br->entries + i),
644 br->entries[i].flags.in_tx? 'X' : '-', 736 br->entries[i].flags.in_tx? 'X' : '-',
645 br->entries[i].flags.abort? 'A' : '-', 737 br->entries[i].flags.abort? 'A' : '-',
646 br->entries[i].flags.cycles); 738 br->entries[i].flags.cycles);
647 } 739 }
740
741 return printed;
648} 742}
649 743
650static void print_sample_brstackoff(struct perf_sample *sample, 744static int perf_sample__fprintf_brstackoff(struct perf_sample *sample,
651 struct thread *thread, 745 struct thread *thread,
652 struct perf_event_attr *attr) 746 struct perf_event_attr *attr, FILE *fp)
653{ 747{
654 struct branch_stack *br = sample->branch_stack; 748 struct branch_stack *br = sample->branch_stack;
655 struct addr_location alf, alt; 749 struct addr_location alf, alt;
656 u64 i, from, to; 750 u64 i, from, to;
751 int printed = 0;
657 752
658 if (!(br && br->nr)) 753 if (!(br && br->nr))
659 return; 754 return 0;
660 755
661 for (i = 0; i < br->nr; i++) { 756 for (i = 0; i < br->nr; i++) {
662 757
@@ -673,24 +768,26 @@ static void print_sample_brstackoff(struct perf_sample *sample,
673 if (alt.map && !alt.map->dso->adjust_symbols) 768 if (alt.map && !alt.map->dso->adjust_symbols)
674 to = map__map_ip(alt.map, to); 769 to = map__map_ip(alt.map, to);
675 770
676 printf("0x%"PRIx64, from); 771 printed += fprintf(fp, " 0x%"PRIx64, from);
677 if (PRINT_FIELD(DSO)) { 772 if (PRINT_FIELD(DSO)) {
678 printf("("); 773 printed += fprintf(fp, "(");
679 map__fprintf_dsoname(alf.map, stdout); 774 printed += map__fprintf_dsoname(alf.map, fp);
680 printf(")"); 775 printed += fprintf(fp, ")");
681 } 776 }
682 printf("/0x%"PRIx64, to); 777 printed += fprintf(fp, "/0x%"PRIx64, to);
683 if (PRINT_FIELD(DSO)) { 778 if (PRINT_FIELD(DSO)) {
684 printf("("); 779 printed += fprintf(fp, "(");
685 map__fprintf_dsoname(alt.map, stdout); 780 printed += map__fprintf_dsoname(alt.map, fp);
686 printf(")"); 781 printed += fprintf(fp, ")");
687 } 782 }
688 printf("/%c/%c/%c/%d ", 783 printed += fprintf(fp, "/%c/%c/%c/%d ",
689 mispred_str(br->entries + i), 784 mispred_str(br->entries + i),
690 br->entries[i].flags.in_tx ? 'X' : '-', 785 br->entries[i].flags.in_tx ? 'X' : '-',
691 br->entries[i].flags.abort ? 'A' : '-', 786 br->entries[i].flags.abort ? 'A' : '-',
692 br->entries[i].flags.cycles); 787 br->entries[i].flags.cycles);
693 } 788 }
789
790 return printed;
694} 791}
695#define MAXBB 16384UL 792#define MAXBB 16384UL
696 793
@@ -718,27 +815,26 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,
718 * but the exit is not. Let the caller patch it up. 815 * but the exit is not. Let the caller patch it up.
719 */ 816 */
720 if (kernel != machine__kernel_ip(machine, end)) { 817 if (kernel != machine__kernel_ip(machine, end)) {
721 printf("\tblock %" PRIx64 "-%" PRIx64 " transfers between kernel and user\n", 818 pr_debug("\tblock %" PRIx64 "-%" PRIx64 " transfers between kernel and user\n", start, end);
722 start, end);
723 return -ENXIO; 819 return -ENXIO;
724 } 820 }
725 821
726 memset(&al, 0, sizeof(al)); 822 memset(&al, 0, sizeof(al));
727 if (end - start > MAXBB - MAXINSN) { 823 if (end - start > MAXBB - MAXINSN) {
728 if (last) 824 if (last)
729 printf("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end); 825 pr_debug("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end);
730 else 826 else
731 printf("\tblock %" PRIx64 "-%" PRIx64 " (%" PRIu64 ") too long to dump\n", start, end, end - start); 827 pr_debug("\tblock %" PRIx64 "-%" PRIx64 " (%" PRIu64 ") too long to dump\n", start, end, end - start);
732 return 0; 828 return 0;
733 } 829 }
734 830
735 thread__find_addr_map(thread, *cpumode, MAP__FUNCTION, start, &al); 831 thread__find_addr_map(thread, *cpumode, MAP__FUNCTION, start, &al);
736 if (!al.map || !al.map->dso) { 832 if (!al.map || !al.map->dso) {
737 printf("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end); 833 pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
738 return 0; 834 return 0;
739 } 835 }
740 if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR) { 836 if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR) {
741 printf("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end); 837 pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
742 return 0; 838 return 0;
743 } 839 }
744 840
@@ -751,36 +847,35 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,
751 847
752 *is64bit = al.map->dso->is_64_bit; 848 *is64bit = al.map->dso->is_64_bit;
753 if (len <= 0) 849 if (len <= 0)
754 printf("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n", 850 pr_debug("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n",
755 start, end); 851 start, end);
756 return len; 852 return len;
757} 853}
758 854
759static void print_jump(uint64_t ip, struct branch_entry *en, 855static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
760 struct perf_insn *x, u8 *inbuf, int len, 856 struct perf_insn *x, u8 *inbuf, int len,
761 int insn) 857 int insn, FILE *fp)
762{ 858{
763 printf("\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", 859 int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", ip,
764 ip, 860 dump_insn(x, ip, inbuf, len, NULL),
765 dump_insn(x, ip, inbuf, len, NULL), 861 en->flags.predicted ? " PRED" : "",
766 en->flags.predicted ? " PRED" : "", 862 en->flags.mispred ? " MISPRED" : "",
767 en->flags.mispred ? " MISPRED" : "", 863 en->flags.in_tx ? " INTX" : "",
768 en->flags.in_tx ? " INTX" : "", 864 en->flags.abort ? " ABORT" : "");
769 en->flags.abort ? " ABORT" : "");
770 if (en->flags.cycles) { 865 if (en->flags.cycles) {
771 printf(" %d cycles", en->flags.cycles); 866 printed += fprintf(fp, " %d cycles", en->flags.cycles);
772 if (insn) 867 if (insn)
773 printf(" %.2f IPC", (float)insn / en->flags.cycles); 868 printed += fprintf(fp, " %.2f IPC", (float)insn / en->flags.cycles);
774 } 869 }
775 putchar('\n'); 870 return printed + fprintf(fp, "\n");
776} 871}
777 872
778static void print_ip_sym(struct thread *thread, u8 cpumode, int cpu, 873static int ip__fprintf_sym(uint64_t addr, struct thread *thread,
779 uint64_t addr, struct symbol **lastsym, 874 u8 cpumode, int cpu, struct symbol **lastsym,
780 struct perf_event_attr *attr) 875 struct perf_event_attr *attr, FILE *fp)
781{ 876{
782 struct addr_location al; 877 struct addr_location al;
783 int off; 878 int off, printed = 0;
784 879
785 memset(&al, 0, sizeof(al)); 880 memset(&al, 0, sizeof(al));
786 881
@@ -789,7 +884,7 @@ static void print_ip_sym(struct thread *thread, u8 cpumode, int cpu,
789 thread__find_addr_map(thread, cpumode, MAP__VARIABLE, 884 thread__find_addr_map(thread, cpumode, MAP__VARIABLE,
790 addr, &al); 885 addr, &al);
791 if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end) 886 if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end)
792 return; 887 return 0;
793 888
794 al.cpu = cpu; 889 al.cpu = cpu;
795 al.sym = NULL; 890 al.sym = NULL;
@@ -797,37 +892,39 @@ static void print_ip_sym(struct thread *thread, u8 cpumode, int cpu,
797 al.sym = map__find_symbol(al.map, al.addr); 892 al.sym = map__find_symbol(al.map, al.addr);
798 893
799 if (!al.sym) 894 if (!al.sym)
800 return; 895 return 0;
801 896
802 if (al.addr < al.sym->end) 897 if (al.addr < al.sym->end)
803 off = al.addr - al.sym->start; 898 off = al.addr - al.sym->start;
804 else 899 else
805 off = al.addr - al.map->start - al.sym->start; 900 off = al.addr - al.map->start - al.sym->start;
806 printf("\t%s", al.sym->name); 901 printed += fprintf(fp, "\t%s", al.sym->name);
807 if (off) 902 if (off)
808 printf("%+d", off); 903 printed += fprintf(fp, "%+d", off);
809 putchar(':'); 904 printed += fprintf(fp, ":");
810 if (PRINT_FIELD(SRCLINE)) 905 if (PRINT_FIELD(SRCLINE))
811 map__fprintf_srcline(al.map, al.addr, "\t", stdout); 906 printed += map__fprintf_srcline(al.map, al.addr, "\t", fp);
812 putchar('\n'); 907 printed += fprintf(fp, "\n");
813 *lastsym = al.sym; 908 *lastsym = al.sym;
909
910 return printed;
814} 911}
815 912
816static void print_sample_brstackinsn(struct perf_sample *sample, 913static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
817 struct thread *thread, 914 struct thread *thread,
818 struct perf_event_attr *attr, 915 struct perf_event_attr *attr,
819 struct machine *machine) 916 struct machine *machine, FILE *fp)
820{ 917{
821 struct branch_stack *br = sample->branch_stack; 918 struct branch_stack *br = sample->branch_stack;
822 u64 start, end; 919 u64 start, end;
823 int i, insn, len, nr, ilen; 920 int i, insn, len, nr, ilen, printed = 0;
824 struct perf_insn x; 921 struct perf_insn x;
825 u8 buffer[MAXBB]; 922 u8 buffer[MAXBB];
826 unsigned off; 923 unsigned off;
827 struct symbol *lastsym = NULL; 924 struct symbol *lastsym = NULL;
828 925
829 if (!(br && br->nr)) 926 if (!(br && br->nr))
830 return; 927 return 0;
831 nr = br->nr; 928 nr = br->nr;
832 if (max_blocks && nr > max_blocks + 1) 929 if (max_blocks && nr > max_blocks + 1)
833 nr = max_blocks + 1; 930 nr = max_blocks + 1;
@@ -835,17 +932,17 @@ static void print_sample_brstackinsn(struct perf_sample *sample,
835 x.thread = thread; 932 x.thread = thread;
836 x.cpu = sample->cpu; 933 x.cpu = sample->cpu;
837 934
838 putchar('\n'); 935 printed += fprintf(fp, "%c", '\n');
839 936
840 /* Handle first from jump, of which we don't know the entry. */ 937 /* Handle first from jump, of which we don't know the entry. */
841 len = grab_bb(buffer, br->entries[nr-1].from, 938 len = grab_bb(buffer, br->entries[nr-1].from,
842 br->entries[nr-1].from, 939 br->entries[nr-1].from,
843 machine, thread, &x.is64bit, &x.cpumode, false); 940 machine, thread, &x.is64bit, &x.cpumode, false);
844 if (len > 0) { 941 if (len > 0) {
845 print_ip_sym(thread, x.cpumode, x.cpu, 942 printed += ip__fprintf_sym(br->entries[nr - 1].from, thread,
846 br->entries[nr - 1].from, &lastsym, attr); 943 x.cpumode, x.cpu, &lastsym, attr, fp);
847 print_jump(br->entries[nr - 1].from, &br->entries[nr - 1], 944 printed += ip__fprintf_jump(br->entries[nr - 1].from, &br->entries[nr - 1],
848 &x, buffer, len, 0); 945 &x, buffer, len, 0, fp);
849 } 946 }
850 947
851 /* Print all blocks */ 948 /* Print all blocks */
@@ -871,13 +968,13 @@ static void print_sample_brstackinsn(struct perf_sample *sample,
871 for (off = 0;; off += ilen) { 968 for (off = 0;; off += ilen) {
872 uint64_t ip = start + off; 969 uint64_t ip = start + off;
873 970
874 print_ip_sym(thread, x.cpumode, x.cpu, ip, &lastsym, attr); 971 printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
875 if (ip == end) { 972 if (ip == end) {
876 print_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn); 973 printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp);
877 break; 974 break;
878 } else { 975 } else {
879 printf("\t%016" PRIx64 "\t%s\n", ip, 976 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip,
880 dump_insn(&x, ip, buffer + off, len - off, &ilen)); 977 dump_insn(&x, ip, buffer + off, len - off, &ilen));
881 if (ilen == 0) 978 if (ilen == 0)
882 break; 979 break;
883 insn++; 980 insn++;
@@ -890,9 +987,9 @@ static void print_sample_brstackinsn(struct perf_sample *sample,
890 * has not been executed yet. 987 * has not been executed yet.
891 */ 988 */
892 if (br->entries[0].from == sample->ip) 989 if (br->entries[0].from == sample->ip)
893 return; 990 goto out;
894 if (br->entries[0].flags.abort) 991 if (br->entries[0].flags.abort)
895 return; 992 goto out;
896 993
897 /* 994 /*
898 * Print final block upto sample 995 * Print final block upto sample
@@ -900,58 +997,61 @@ static void print_sample_brstackinsn(struct perf_sample *sample,
900 start = br->entries[0].to; 997 start = br->entries[0].to;
901 end = sample->ip; 998 end = sample->ip;
902 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true); 999 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true);
903 print_ip_sym(thread, x.cpumode, x.cpu, start, &lastsym, attr); 1000 printed += ip__fprintf_sym(start, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
904 if (len <= 0) { 1001 if (len <= 0) {
905 /* Print at least last IP if basic block did not work */ 1002 /* Print at least last IP if basic block did not work */
906 len = grab_bb(buffer, sample->ip, sample->ip, 1003 len = grab_bb(buffer, sample->ip, sample->ip,
907 machine, thread, &x.is64bit, &x.cpumode, false); 1004 machine, thread, &x.is64bit, &x.cpumode, false);
908 if (len <= 0) 1005 if (len <= 0)
909 return; 1006 goto out;
910 1007
911 printf("\t%016" PRIx64 "\t%s\n", sample->ip, 1008 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", sample->ip,
912 dump_insn(&x, sample->ip, buffer, len, NULL)); 1009 dump_insn(&x, sample->ip, buffer, len, NULL));
913 return; 1010 goto out;
914 } 1011 }
915 for (off = 0; off <= end - start; off += ilen) { 1012 for (off = 0; off <= end - start; off += ilen) {
916 printf("\t%016" PRIx64 "\t%s\n", start + off, 1013 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", start + off,
917 dump_insn(&x, start + off, buffer + off, len - off, &ilen)); 1014 dump_insn(&x, start + off, buffer + off, len - off, &ilen));
918 if (ilen == 0) 1015 if (ilen == 0)
919 break; 1016 break;
920 } 1017 }
1018out:
1019 return printed;
921} 1020}
922 1021
923static void print_sample_addr(struct perf_sample *sample, 1022static int perf_sample__fprintf_addr(struct perf_sample *sample,
924 struct thread *thread, 1023 struct thread *thread,
925 struct perf_event_attr *attr) 1024 struct perf_event_attr *attr, FILE *fp)
926{ 1025{
927 struct addr_location al; 1026 struct addr_location al;
928 1027 int printed = fprintf(fp, "%16" PRIx64, sample->addr);
929 printf("%16" PRIx64, sample->addr);
930 1028
931 if (!sample_addr_correlates_sym(attr)) 1029 if (!sample_addr_correlates_sym(attr))
932 return; 1030 goto out;
933 1031
934 thread__resolve(thread, &al, sample); 1032 thread__resolve(thread, &al, sample);
935 1033
936 if (PRINT_FIELD(SYM)) { 1034 if (PRINT_FIELD(SYM)) {
937 printf(" "); 1035 printed += fprintf(fp, " ");
938 if (PRINT_FIELD(SYMOFFSET)) 1036 if (PRINT_FIELD(SYMOFFSET))
939 symbol__fprintf_symname_offs(al.sym, &al, stdout); 1037 printed += symbol__fprintf_symname_offs(al.sym, &al, fp);
940 else 1038 else
941 symbol__fprintf_symname(al.sym, stdout); 1039 printed += symbol__fprintf_symname(al.sym, fp);
942 } 1040 }
943 1041
944 if (PRINT_FIELD(DSO)) { 1042 if (PRINT_FIELD(DSO)) {
945 printf(" ("); 1043 printed += fprintf(fp, " (");
946 map__fprintf_dsoname(al.map, stdout); 1044 printed += map__fprintf_dsoname(al.map, fp);
947 printf(")"); 1045 printed += fprintf(fp, ")");
948 } 1046 }
1047out:
1048 return printed;
949} 1049}
950 1050
951static void print_sample_callindent(struct perf_sample *sample, 1051static int perf_sample__fprintf_callindent(struct perf_sample *sample,
952 struct perf_evsel *evsel, 1052 struct perf_evsel *evsel,
953 struct thread *thread, 1053 struct thread *thread,
954 struct addr_location *al) 1054 struct addr_location *al, FILE *fp)
955{ 1055{
956 struct perf_event_attr *attr = &evsel->attr; 1056 struct perf_event_attr *attr = &evsel->attr;
957 size_t depth = thread_stack__depth(thread); 1057 size_t depth = thread_stack__depth(thread);
@@ -986,12 +1086,12 @@ static void print_sample_callindent(struct perf_sample *sample,
986 } 1086 }
987 1087
988 if (name) 1088 if (name)
989 len = printf("%*s%s", (int)depth * 4, "", name); 1089 len = fprintf(fp, "%*s%s", (int)depth * 4, "", name);
990 else if (ip) 1090 else if (ip)
991 len = printf("%*s%16" PRIx64, (int)depth * 4, "", ip); 1091 len = fprintf(fp, "%*s%16" PRIx64, (int)depth * 4, "", ip);
992 1092
993 if (len < 0) 1093 if (len < 0)
994 return; 1094 return len;
995 1095
996 /* 1096 /*
997 * Try to keep the output length from changing frequently so that the 1097 * Try to keep the output length from changing frequently so that the
@@ -1001,39 +1101,46 @@ static void print_sample_callindent(struct perf_sample *sample,
1001 spacing = round_up(len + 4, 32); 1101 spacing = round_up(len + 4, 32);
1002 1102
1003 if (len < spacing) 1103 if (len < spacing)
1004 printf("%*s", spacing - len, ""); 1104 len += fprintf(fp, "%*s", spacing - len, "");
1105
1106 return len;
1005} 1107}
1006 1108
1007static void print_insn(struct perf_sample *sample, 1109static int perf_sample__fprintf_insn(struct perf_sample *sample,
1008 struct perf_event_attr *attr, 1110 struct perf_event_attr *attr,
1009 struct thread *thread, 1111 struct thread *thread,
1010 struct machine *machine) 1112 struct machine *machine, FILE *fp)
1011{ 1113{
1114 int printed = 0;
1115
1012 if (PRINT_FIELD(INSNLEN)) 1116 if (PRINT_FIELD(INSNLEN))
1013 printf(" ilen: %d", sample->insn_len); 1117 printed += fprintf(fp, " ilen: %d", sample->insn_len);
1014 if (PRINT_FIELD(INSN)) { 1118 if (PRINT_FIELD(INSN)) {
1015 int i; 1119 int i;
1016 1120
1017 printf(" insn:"); 1121 printed += fprintf(fp, " insn:");
1018 for (i = 0; i < sample->insn_len; i++) 1122 for (i = 0; i < sample->insn_len; i++)
1019 printf(" %02x", (unsigned char)sample->insn[i]); 1123 printed += fprintf(fp, " %02x", (unsigned char)sample->insn[i]);
1020 } 1124 }
1021 if (PRINT_FIELD(BRSTACKINSN)) 1125 if (PRINT_FIELD(BRSTACKINSN))
1022 print_sample_brstackinsn(sample, thread, attr, machine); 1126 printed += perf_sample__fprintf_brstackinsn(sample, thread, attr, machine, fp);
1127
1128 return printed;
1023} 1129}
1024 1130
1025static void print_sample_bts(struct perf_sample *sample, 1131static int perf_sample__fprintf_bts(struct perf_sample *sample,
1026 struct perf_evsel *evsel, 1132 struct perf_evsel *evsel,
1027 struct thread *thread, 1133 struct thread *thread,
1028 struct addr_location *al, 1134 struct addr_location *al,
1029 struct machine *machine) 1135 struct machine *machine, FILE *fp)
1030{ 1136{
1031 struct perf_event_attr *attr = &evsel->attr; 1137 struct perf_event_attr *attr = &evsel->attr;
1032 unsigned int type = output_type(attr->type); 1138 unsigned int type = output_type(attr->type);
1033 bool print_srcline_last = false; 1139 bool print_srcline_last = false;
1140 int printed = 0;
1034 1141
1035 if (PRINT_FIELD(CALLINDENT)) 1142 if (PRINT_FIELD(CALLINDENT))
1036 print_sample_callindent(sample, evsel, thread, al); 1143 printed += perf_sample__fprintf_callindent(sample, evsel, thread, al, fp);
1037 1144
1038 /* print branch_from information */ 1145 /* print branch_from information */
1039 if (PRINT_FIELD(IP)) { 1146 if (PRINT_FIELD(IP)) {
@@ -1046,31 +1153,30 @@ static void print_sample_bts(struct perf_sample *sample,
1046 cursor = &callchain_cursor; 1153 cursor = &callchain_cursor;
1047 1154
1048 if (cursor == NULL) { 1155 if (cursor == NULL) {
1049 putchar(' '); 1156 printed += fprintf(fp, " ");
1050 if (print_opts & EVSEL__PRINT_SRCLINE) { 1157 if (print_opts & EVSEL__PRINT_SRCLINE) {
1051 print_srcline_last = true; 1158 print_srcline_last = true;
1052 print_opts &= ~EVSEL__PRINT_SRCLINE; 1159 print_opts &= ~EVSEL__PRINT_SRCLINE;
1053 } 1160 }
1054 } else 1161 } else
1055 putchar('\n'); 1162 printed += fprintf(fp, "\n");
1056 1163
1057 sample__fprintf_sym(sample, al, 0, print_opts, cursor, stdout); 1164 printed += sample__fprintf_sym(sample, al, 0, print_opts, cursor, fp);
1058 } 1165 }
1059 1166
1060 /* print branch_to information */ 1167 /* print branch_to information */
1061 if (PRINT_FIELD(ADDR) || 1168 if (PRINT_FIELD(ADDR) ||
1062 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && 1169 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
1063 !output[type].user_set)) { 1170 !output[type].user_set)) {
1064 printf(" => "); 1171 printed += fprintf(fp, " => ");
1065 print_sample_addr(sample, thread, attr); 1172 printed += perf_sample__fprintf_addr(sample, thread, attr, fp);
1066 } 1173 }
1067 1174
1068 if (print_srcline_last) 1175 if (print_srcline_last)
1069 map__fprintf_srcline(al->map, al->addr, "\n ", stdout); 1176 printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);
1070
1071 print_insn(sample, attr, thread, machine);
1072 1177
1073 printf("\n"); 1178 printed += perf_sample__fprintf_insn(sample, attr, thread, machine, fp);
1179 return printed + fprintf(fp, "\n");
1074} 1180}
1075 1181
1076static struct { 1182static struct {
@@ -1093,7 +1199,7 @@ static struct {
1093 {0, NULL} 1199 {0, NULL}
1094}; 1200};
1095 1201
1096static void print_sample_flags(u32 flags) 1202static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
1097{ 1203{
1098 const char *chars = PERF_IP_FLAG_CHARS; 1204 const char *chars = PERF_IP_FLAG_CHARS;
1099 const int n = strlen(PERF_IP_FLAG_CHARS); 1205 const int n = strlen(PERF_IP_FLAG_CHARS);
@@ -1120,9 +1226,9 @@ static void print_sample_flags(u32 flags)
1120 str[pos] = 0; 1226 str[pos] = 0;
1121 1227
1122 if (name) 1228 if (name)
1123 printf(" %-7s%4s ", name, in_tx ? "(x)" : ""); 1229 return fprintf(fp, " %-7s%4s ", name, in_tx ? "(x)" : "");
1124 else 1230
1125 printf(" %-11s ", str); 1231 return fprintf(fp, " %-11s ", str);
1126} 1232}
1127 1233
1128struct printer_data { 1234struct printer_data {
@@ -1131,40 +1237,40 @@ struct printer_data {
1131 bool is_printable; 1237 bool is_printable;
1132}; 1238};
1133 1239
1134static void 1240static int sample__fprintf_bpf_output(enum binary_printer_ops op,
1135print_sample_bpf_output_printer(enum binary_printer_ops op, 1241 unsigned int val,
1136 unsigned int val, 1242 void *extra, FILE *fp)
1137 void *extra)
1138{ 1243{
1139 unsigned char ch = (unsigned char)val; 1244 unsigned char ch = (unsigned char)val;
1140 struct printer_data *printer_data = extra; 1245 struct printer_data *printer_data = extra;
1246 int printed = 0;
1141 1247
1142 switch (op) { 1248 switch (op) {
1143 case BINARY_PRINT_DATA_BEGIN: 1249 case BINARY_PRINT_DATA_BEGIN:
1144 printf("\n"); 1250 printed += fprintf(fp, "\n");
1145 break; 1251 break;
1146 case BINARY_PRINT_LINE_BEGIN: 1252 case BINARY_PRINT_LINE_BEGIN:
1147 printf("%17s", !printer_data->line_no ? "BPF output:" : 1253 printed += fprintf(fp, "%17s", !printer_data->line_no ? "BPF output:" :
1148 " "); 1254 " ");
1149 break; 1255 break;
1150 case BINARY_PRINT_ADDR: 1256 case BINARY_PRINT_ADDR:
1151 printf(" %04x:", val); 1257 printed += fprintf(fp, " %04x:", val);
1152 break; 1258 break;
1153 case BINARY_PRINT_NUM_DATA: 1259 case BINARY_PRINT_NUM_DATA:
1154 printf(" %02x", val); 1260 printed += fprintf(fp, " %02x", val);
1155 break; 1261 break;
1156 case BINARY_PRINT_NUM_PAD: 1262 case BINARY_PRINT_NUM_PAD:
1157 printf(" "); 1263 printed += fprintf(fp, " ");
1158 break; 1264 break;
1159 case BINARY_PRINT_SEP: 1265 case BINARY_PRINT_SEP:
1160 printf(" "); 1266 printed += fprintf(fp, " ");
1161 break; 1267 break;
1162 case BINARY_PRINT_CHAR_DATA: 1268 case BINARY_PRINT_CHAR_DATA:
1163 if (printer_data->hit_nul && ch) 1269 if (printer_data->hit_nul && ch)
1164 printer_data->is_printable = false; 1270 printer_data->is_printable = false;
1165 1271
1166 if (!isprint(ch)) { 1272 if (!isprint(ch)) {
1167 printf("%c", '.'); 1273 printed += fprintf(fp, "%c", '.');
1168 1274
1169 if (!printer_data->is_printable) 1275 if (!printer_data->is_printable)
1170 break; 1276 break;
@@ -1174,154 +1280,154 @@ print_sample_bpf_output_printer(enum binary_printer_ops op,
1174 else 1280 else
1175 printer_data->is_printable = false; 1281 printer_data->is_printable = false;
1176 } else { 1282 } else {
1177 printf("%c", ch); 1283 printed += fprintf(fp, "%c", ch);
1178 } 1284 }
1179 break; 1285 break;
1180 case BINARY_PRINT_CHAR_PAD: 1286 case BINARY_PRINT_CHAR_PAD:
1181 printf(" "); 1287 printed += fprintf(fp, " ");
1182 break; 1288 break;
1183 case BINARY_PRINT_LINE_END: 1289 case BINARY_PRINT_LINE_END:
1184 printf("\n"); 1290 printed += fprintf(fp, "\n");
1185 printer_data->line_no++; 1291 printer_data->line_no++;
1186 break; 1292 break;
1187 case BINARY_PRINT_DATA_END: 1293 case BINARY_PRINT_DATA_END:
1188 default: 1294 default:
1189 break; 1295 break;
1190 } 1296 }
1297
1298 return printed;
1191} 1299}
1192 1300
1193static void print_sample_bpf_output(struct perf_sample *sample) 1301static int perf_sample__fprintf_bpf_output(struct perf_sample *sample, FILE *fp)
1194{ 1302{
1195 unsigned int nr_bytes = sample->raw_size; 1303 unsigned int nr_bytes = sample->raw_size;
1196 struct printer_data printer_data = {0, false, true}; 1304 struct printer_data printer_data = {0, false, true};
1197 1305 int printed = binary__fprintf(sample->raw_data, nr_bytes, 8,
1198 print_binary(sample->raw_data, nr_bytes, 8, 1306 sample__fprintf_bpf_output, &printer_data, fp);
1199 print_sample_bpf_output_printer, &printer_data);
1200 1307
1201 if (printer_data.is_printable && printer_data.hit_nul) 1308 if (printer_data.is_printable && printer_data.hit_nul)
1202 printf("%17s \"%s\"\n", "BPF string:", 1309 printed += fprintf(fp, "%17s \"%s\"\n", "BPF string:", (char *)(sample->raw_data));
1203 (char *)(sample->raw_data)); 1310
1311 return printed;
1204} 1312}
1205 1313
1206static void print_sample_spacing(int len, int spacing) 1314static int perf_sample__fprintf_spacing(int len, int spacing, FILE *fp)
1207{ 1315{
1208 if (len > 0 && len < spacing) 1316 if (len > 0 && len < spacing)
1209 printf("%*s", spacing - len, ""); 1317 return fprintf(fp, "%*s", spacing - len, "");
1318
1319 return 0;
1210} 1320}
1211 1321
1212static void print_sample_pt_spacing(int len) 1322static int perf_sample__fprintf_pt_spacing(int len, FILE *fp)
1213{ 1323{
1214 print_sample_spacing(len, 34); 1324 return perf_sample__fprintf_spacing(len, 34, fp);
1215} 1325}
1216 1326
1217static void print_sample_synth_ptwrite(struct perf_sample *sample) 1327static int perf_sample__fprintf_synth_ptwrite(struct perf_sample *sample, FILE *fp)
1218{ 1328{
1219 struct perf_synth_intel_ptwrite *data = perf_sample__synth_ptr(sample); 1329 struct perf_synth_intel_ptwrite *data = perf_sample__synth_ptr(sample);
1220 int len; 1330 int len;
1221 1331
1222 if (perf_sample__bad_synth_size(sample, *data)) 1332 if (perf_sample__bad_synth_size(sample, *data))
1223 return; 1333 return 0;
1224 1334
1225 len = printf(" IP: %u payload: %#" PRIx64 " ", 1335 len = fprintf(fp, " IP: %u payload: %#" PRIx64 " ",
1226 data->ip, le64_to_cpu(data->payload)); 1336 data->ip, le64_to_cpu(data->payload));
1227 print_sample_pt_spacing(len); 1337 return len + perf_sample__fprintf_pt_spacing(len, fp);
1228} 1338}
1229 1339
1230static void print_sample_synth_mwait(struct perf_sample *sample) 1340static int perf_sample__fprintf_synth_mwait(struct perf_sample *sample, FILE *fp)
1231{ 1341{
1232 struct perf_synth_intel_mwait *data = perf_sample__synth_ptr(sample); 1342 struct perf_synth_intel_mwait *data = perf_sample__synth_ptr(sample);
1233 int len; 1343 int len;
1234 1344
1235 if (perf_sample__bad_synth_size(sample, *data)) 1345 if (perf_sample__bad_synth_size(sample, *data))
1236 return; 1346 return 0;
1237 1347
1238 len = printf(" hints: %#x extensions: %#x ", 1348 len = fprintf(fp, " hints: %#x extensions: %#x ",
1239 data->hints, data->extensions); 1349 data->hints, data->extensions);
1240 print_sample_pt_spacing(len); 1350 return len + perf_sample__fprintf_pt_spacing(len, fp);
1241} 1351}
1242 1352
1243static void print_sample_synth_pwre(struct perf_sample *sample) 1353static int perf_sample__fprintf_synth_pwre(struct perf_sample *sample, FILE *fp)
1244{ 1354{
1245 struct perf_synth_intel_pwre *data = perf_sample__synth_ptr(sample); 1355 struct perf_synth_intel_pwre *data = perf_sample__synth_ptr(sample);
1246 int len; 1356 int len;
1247 1357
1248 if (perf_sample__bad_synth_size(sample, *data)) 1358 if (perf_sample__bad_synth_size(sample, *data))
1249 return; 1359 return 0;
1250 1360
1251 len = printf(" hw: %u cstate: %u sub-cstate: %u ", 1361 len = fprintf(fp, " hw: %u cstate: %u sub-cstate: %u ",
1252 data->hw, data->cstate, data->subcstate); 1362 data->hw, data->cstate, data->subcstate);
1253 print_sample_pt_spacing(len); 1363 return len + perf_sample__fprintf_pt_spacing(len, fp);
1254} 1364}
1255 1365
1256static void print_sample_synth_exstop(struct perf_sample *sample) 1366static int perf_sample__fprintf_synth_exstop(struct perf_sample *sample, FILE *fp)
1257{ 1367{
1258 struct perf_synth_intel_exstop *data = perf_sample__synth_ptr(sample); 1368 struct perf_synth_intel_exstop *data = perf_sample__synth_ptr(sample);
1259 int len; 1369 int len;
1260 1370
1261 if (perf_sample__bad_synth_size(sample, *data)) 1371 if (perf_sample__bad_synth_size(sample, *data))
1262 return; 1372 return 0;
1263 1373
1264 len = printf(" IP: %u ", data->ip); 1374 len = fprintf(fp, " IP: %u ", data->ip);
1265 print_sample_pt_spacing(len); 1375 return len + perf_sample__fprintf_pt_spacing(len, fp);
1266} 1376}
1267 1377
1268static void print_sample_synth_pwrx(struct perf_sample *sample) 1378static int perf_sample__fprintf_synth_pwrx(struct perf_sample *sample, FILE *fp)
1269{ 1379{
1270 struct perf_synth_intel_pwrx *data = perf_sample__synth_ptr(sample); 1380 struct perf_synth_intel_pwrx *data = perf_sample__synth_ptr(sample);
1271 int len; 1381 int len;
1272 1382
1273 if (perf_sample__bad_synth_size(sample, *data)) 1383 if (perf_sample__bad_synth_size(sample, *data))
1274 return; 1384 return 0;
1275 1385
1276 len = printf(" deepest cstate: %u last cstate: %u wake reason: %#x ", 1386 len = fprintf(fp, " deepest cstate: %u last cstate: %u wake reason: %#x ",
1277 data->deepest_cstate, data->last_cstate, 1387 data->deepest_cstate, data->last_cstate,
1278 data->wake_reason); 1388 data->wake_reason);
1279 print_sample_pt_spacing(len); 1389 return len + perf_sample__fprintf_pt_spacing(len, fp);
1280} 1390}
1281 1391
1282static void print_sample_synth_cbr(struct perf_sample *sample) 1392static int perf_sample__fprintf_synth_cbr(struct perf_sample *sample, FILE *fp)
1283{ 1393{
1284 struct perf_synth_intel_cbr *data = perf_sample__synth_ptr(sample); 1394 struct perf_synth_intel_cbr *data = perf_sample__synth_ptr(sample);
1285 unsigned int percent, freq; 1395 unsigned int percent, freq;
1286 int len; 1396 int len;
1287 1397
1288 if (perf_sample__bad_synth_size(sample, *data)) 1398 if (perf_sample__bad_synth_size(sample, *data))
1289 return; 1399 return 0;
1290 1400
1291 freq = (le32_to_cpu(data->freq) + 500) / 1000; 1401 freq = (le32_to_cpu(data->freq) + 500) / 1000;
1292 len = printf(" cbr: %2u freq: %4u MHz ", data->cbr, freq); 1402 len = fprintf(fp, " cbr: %2u freq: %4u MHz ", data->cbr, freq);
1293 if (data->max_nonturbo) { 1403 if (data->max_nonturbo) {
1294 percent = (5 + (1000 * data->cbr) / data->max_nonturbo) / 10; 1404 percent = (5 + (1000 * data->cbr) / data->max_nonturbo) / 10;
1295 len += printf("(%3u%%) ", percent); 1405 len += fprintf(fp, "(%3u%%) ", percent);
1296 } 1406 }
1297 print_sample_pt_spacing(len); 1407 return len + perf_sample__fprintf_pt_spacing(len, fp);
1298} 1408}
1299 1409
1300static void print_sample_synth(struct perf_sample *sample, 1410static int perf_sample__fprintf_synth(struct perf_sample *sample,
1301 struct perf_evsel *evsel) 1411 struct perf_evsel *evsel, FILE *fp)
1302{ 1412{
1303 switch (evsel->attr.config) { 1413 switch (evsel->attr.config) {
1304 case PERF_SYNTH_INTEL_PTWRITE: 1414 case PERF_SYNTH_INTEL_PTWRITE:
1305 print_sample_synth_ptwrite(sample); 1415 return perf_sample__fprintf_synth_ptwrite(sample, fp);
1306 break;
1307 case PERF_SYNTH_INTEL_MWAIT: 1416 case PERF_SYNTH_INTEL_MWAIT:
1308 print_sample_synth_mwait(sample); 1417 return perf_sample__fprintf_synth_mwait(sample, fp);
1309 break;
1310 case PERF_SYNTH_INTEL_PWRE: 1418 case PERF_SYNTH_INTEL_PWRE:
1311 print_sample_synth_pwre(sample); 1419 return perf_sample__fprintf_synth_pwre(sample, fp);
1312 break;
1313 case PERF_SYNTH_INTEL_EXSTOP: 1420 case PERF_SYNTH_INTEL_EXSTOP:
1314 print_sample_synth_exstop(sample); 1421 return perf_sample__fprintf_synth_exstop(sample, fp);
1315 break;
1316 case PERF_SYNTH_INTEL_PWRX: 1422 case PERF_SYNTH_INTEL_PWRX:
1317 print_sample_synth_pwrx(sample); 1423 return perf_sample__fprintf_synth_pwrx(sample, fp);
1318 break;
1319 case PERF_SYNTH_INTEL_CBR: 1424 case PERF_SYNTH_INTEL_CBR:
1320 print_sample_synth_cbr(sample); 1425 return perf_sample__fprintf_synth_cbr(sample, fp);
1321 break;
1322 default: 1426 default:
1323 break; 1427 break;
1324 } 1428 }
1429
1430 return 0;
1325} 1431}
1326 1432
1327struct perf_script { 1433struct perf_script {
@@ -1332,6 +1438,7 @@ struct perf_script {
1332 bool show_switch_events; 1438 bool show_switch_events;
1333 bool show_namespace_events; 1439 bool show_namespace_events;
1334 bool allocated; 1440 bool allocated;
1441 bool per_event_dump;
1335 struct cpu_map *cpus; 1442 struct cpu_map *cpus;
1336 struct thread_map *threads; 1443 struct thread_map *threads;
1337 int name_width; 1444 int name_width;
@@ -1353,7 +1460,7 @@ static int perf_evlist__max_name_len(struct perf_evlist *evlist)
1353 return max; 1460 return max;
1354} 1461}
1355 1462
1356static size_t data_src__printf(u64 data_src) 1463static int data_src__fprintf(u64 data_src, FILE *fp)
1357{ 1464{
1358 struct mem_info mi = { .data_src.val = data_src }; 1465 struct mem_info mi = { .data_src.val = data_src };
1359 char decode[100]; 1466 char decode[100];
@@ -1367,7 +1474,7 @@ static size_t data_src__printf(u64 data_src)
1367 if (maxlen < len) 1474 if (maxlen < len)
1368 maxlen = len; 1475 maxlen = len;
1369 1476
1370 return printf("%-*s", maxlen, out); 1477 return fprintf(fp, "%-*s", maxlen, out);
1371} 1478}
1372 1479
1373static void process_event(struct perf_script *script, 1480static void process_event(struct perf_script *script,
@@ -1378,14 +1485,18 @@ static void process_event(struct perf_script *script,
1378 struct thread *thread = al->thread; 1485 struct thread *thread = al->thread;
1379 struct perf_event_attr *attr = &evsel->attr; 1486 struct perf_event_attr *attr = &evsel->attr;
1380 unsigned int type = output_type(attr->type); 1487 unsigned int type = output_type(attr->type);
1488 struct perf_evsel_script *es = evsel->priv;
1489 FILE *fp = es->fp;
1381 1490
1382 if (output[type].fields == 0) 1491 if (output[type].fields == 0)
1383 return; 1492 return;
1384 1493
1385 print_sample_start(sample, thread, evsel); 1494 ++es->samples;
1495
1496 perf_sample__fprintf_start(sample, thread, evsel, fp);
1386 1497
1387 if (PRINT_FIELD(PERIOD)) 1498 if (PRINT_FIELD(PERIOD))
1388 printf("%10" PRIu64 " ", sample->period); 1499 fprintf(fp, "%10" PRIu64 " ", sample->period);
1389 1500
1390 if (PRINT_FIELD(EVNAME)) { 1501 if (PRINT_FIELD(EVNAME)) {
1391 const char *evname = perf_evsel__name(evsel); 1502 const char *evname = perf_evsel__name(evsel);
@@ -1393,33 +1504,33 @@ static void process_event(struct perf_script *script,
1393 if (!script->name_width) 1504 if (!script->name_width)
1394 script->name_width = perf_evlist__max_name_len(script->session->evlist); 1505 script->name_width = perf_evlist__max_name_len(script->session->evlist);
1395 1506
1396 printf("%*s: ", script->name_width, 1507 fprintf(fp, "%*s: ", script->name_width, evname ?: "[unknown]");
1397 evname ? evname : "[unknown]");
1398 } 1508 }
1399 1509
1400 if (print_flags) 1510 if (print_flags)
1401 print_sample_flags(sample->flags); 1511 perf_sample__fprintf_flags(sample->flags, fp);
1402 1512
1403 if (is_bts_event(attr)) { 1513 if (is_bts_event(attr)) {
1404 print_sample_bts(sample, evsel, thread, al, machine); 1514 perf_sample__fprintf_bts(sample, evsel, thread, al, machine, fp);
1405 return; 1515 return;
1406 } 1516 }
1407 1517
1408 if (PRINT_FIELD(TRACE)) 1518 if (PRINT_FIELD(TRACE)) {
1409 event_format__print(evsel->tp_format, sample->cpu, 1519 event_format__fprintf(evsel->tp_format, sample->cpu,
1410 sample->raw_data, sample->raw_size); 1520 sample->raw_data, sample->raw_size, fp);
1521 }
1411 1522
1412 if (attr->type == PERF_TYPE_SYNTH && PRINT_FIELD(SYNTH)) 1523 if (attr->type == PERF_TYPE_SYNTH && PRINT_FIELD(SYNTH))
1413 print_sample_synth(sample, evsel); 1524 perf_sample__fprintf_synth(sample, evsel, fp);
1414 1525
1415 if (PRINT_FIELD(ADDR)) 1526 if (PRINT_FIELD(ADDR))
1416 print_sample_addr(sample, thread, attr); 1527 perf_sample__fprintf_addr(sample, thread, attr, fp);
1417 1528
1418 if (PRINT_FIELD(DATA_SRC)) 1529 if (PRINT_FIELD(DATA_SRC))
1419 data_src__printf(sample->data_src); 1530 data_src__fprintf(sample->data_src, fp);
1420 1531
1421 if (PRINT_FIELD(WEIGHT)) 1532 if (PRINT_FIELD(WEIGHT))
1422 printf("%16" PRIu64, sample->weight); 1533 fprintf(fp, "%16" PRIu64, sample->weight);
1423 1534
1424 if (PRINT_FIELD(IP)) { 1535 if (PRINT_FIELD(IP)) {
1425 struct callchain_cursor *cursor = NULL; 1536 struct callchain_cursor *cursor = NULL;
@@ -1429,24 +1540,30 @@ static void process_event(struct perf_script *script,
1429 sample, NULL, NULL, scripting_max_stack) == 0) 1540 sample, NULL, NULL, scripting_max_stack) == 0)
1430 cursor = &callchain_cursor; 1541 cursor = &callchain_cursor;
1431 1542
1432 putchar(cursor ? '\n' : ' '); 1543 fputc(cursor ? '\n' : ' ', fp);
1433 sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor, stdout); 1544 sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor, fp);
1434 } 1545 }
1435 1546
1436 if (PRINT_FIELD(IREGS)) 1547 if (PRINT_FIELD(IREGS))
1437 print_sample_iregs(sample, attr); 1548 perf_sample__fprintf_iregs(sample, attr, fp);
1549
1550 if (PRINT_FIELD(UREGS))
1551 perf_sample__fprintf_uregs(sample, attr, fp);
1438 1552
1439 if (PRINT_FIELD(BRSTACK)) 1553 if (PRINT_FIELD(BRSTACK))
1440 print_sample_brstack(sample, thread, attr); 1554 perf_sample__fprintf_brstack(sample, thread, attr, fp);
1441 else if (PRINT_FIELD(BRSTACKSYM)) 1555 else if (PRINT_FIELD(BRSTACKSYM))
1442 print_sample_brstacksym(sample, thread, attr); 1556 perf_sample__fprintf_brstacksym(sample, thread, attr, fp);
1443 else if (PRINT_FIELD(BRSTACKOFF)) 1557 else if (PRINT_FIELD(BRSTACKOFF))
1444 print_sample_brstackoff(sample, thread, attr); 1558 perf_sample__fprintf_brstackoff(sample, thread, attr, fp);
1445 1559
1446 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT)) 1560 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
1447 print_sample_bpf_output(sample); 1561 perf_sample__fprintf_bpf_output(sample, fp);
1448 print_insn(sample, attr, thread, machine); 1562 perf_sample__fprintf_insn(sample, attr, thread, machine, fp);
1449 printf("\n"); 1563
1564 if (PRINT_FIELD(PHYS_ADDR))
1565 fprintf(fp, "%16" PRIx64, sample->phys_addr);
1566 fprintf(fp, "\n");
1450} 1567}
1451 1568
1452static struct scripting_ops *scripting_ops; 1569static struct scripting_ops *scripting_ops;
@@ -1620,7 +1737,7 @@ static int process_comm_event(struct perf_tool *tool,
1620 sample->tid = event->comm.tid; 1737 sample->tid = event->comm.tid;
1621 sample->pid = event->comm.pid; 1738 sample->pid = event->comm.pid;
1622 } 1739 }
1623 print_sample_start(sample, thread, evsel); 1740 perf_sample__fprintf_start(sample, thread, evsel, stdout);
1624 perf_event__fprintf(event, stdout); 1741 perf_event__fprintf(event, stdout);
1625 ret = 0; 1742 ret = 0;
1626out: 1743out:
@@ -1655,7 +1772,7 @@ static int process_namespaces_event(struct perf_tool *tool,
1655 sample->tid = event->namespaces.tid; 1772 sample->tid = event->namespaces.tid;
1656 sample->pid = event->namespaces.pid; 1773 sample->pid = event->namespaces.pid;
1657 } 1774 }
1658 print_sample_start(sample, thread, evsel); 1775 perf_sample__fprintf_start(sample, thread, evsel, stdout);
1659 perf_event__fprintf(event, stdout); 1776 perf_event__fprintf(event, stdout);
1660 ret = 0; 1777 ret = 0;
1661out: 1778out:
@@ -1688,7 +1805,7 @@ static int process_fork_event(struct perf_tool *tool,
1688 sample->tid = event->fork.tid; 1805 sample->tid = event->fork.tid;
1689 sample->pid = event->fork.pid; 1806 sample->pid = event->fork.pid;
1690 } 1807 }
1691 print_sample_start(sample, thread, evsel); 1808 perf_sample__fprintf_start(sample, thread, evsel, stdout);
1692 perf_event__fprintf(event, stdout); 1809 perf_event__fprintf(event, stdout);
1693 thread__put(thread); 1810 thread__put(thread);
1694 1811
@@ -1717,7 +1834,7 @@ static int process_exit_event(struct perf_tool *tool,
1717 sample->tid = event->fork.tid; 1834 sample->tid = event->fork.tid;
1718 sample->pid = event->fork.pid; 1835 sample->pid = event->fork.pid;
1719 } 1836 }
1720 print_sample_start(sample, thread, evsel); 1837 perf_sample__fprintf_start(sample, thread, evsel, stdout);
1721 perf_event__fprintf(event, stdout); 1838 perf_event__fprintf(event, stdout);
1722 1839
1723 if (perf_event__process_exit(tool, event, sample, machine) < 0) 1840 if (perf_event__process_exit(tool, event, sample, machine) < 0)
@@ -1752,7 +1869,7 @@ static int process_mmap_event(struct perf_tool *tool,
1752 sample->tid = event->mmap.tid; 1869 sample->tid = event->mmap.tid;
1753 sample->pid = event->mmap.pid; 1870 sample->pid = event->mmap.pid;
1754 } 1871 }
1755 print_sample_start(sample, thread, evsel); 1872 perf_sample__fprintf_start(sample, thread, evsel, stdout);
1756 perf_event__fprintf(event, stdout); 1873 perf_event__fprintf(event, stdout);
1757 thread__put(thread); 1874 thread__put(thread);
1758 return 0; 1875 return 0;
@@ -1783,7 +1900,7 @@ static int process_mmap2_event(struct perf_tool *tool,
1783 sample->tid = event->mmap2.tid; 1900 sample->tid = event->mmap2.tid;
1784 sample->pid = event->mmap2.pid; 1901 sample->pid = event->mmap2.pid;
1785 } 1902 }
1786 print_sample_start(sample, thread, evsel); 1903 perf_sample__fprintf_start(sample, thread, evsel, stdout);
1787 perf_event__fprintf(event, stdout); 1904 perf_event__fprintf(event, stdout);
1788 thread__put(thread); 1905 thread__put(thread);
1789 return 0; 1906 return 0;
@@ -1809,7 +1926,7 @@ static int process_switch_event(struct perf_tool *tool,
1809 return -1; 1926 return -1;
1810 } 1927 }
1811 1928
1812 print_sample_start(sample, thread, evsel); 1929 perf_sample__fprintf_start(sample, thread, evsel, stdout);
1813 perf_event__fprintf(event, stdout); 1930 perf_event__fprintf(event, stdout);
1814 thread__put(thread); 1931 thread__put(thread);
1815 return 0; 1932 return 0;
@@ -1820,6 +1937,65 @@ static void sig_handler(int sig __maybe_unused)
1820 session_done = 1; 1937 session_done = 1;
1821} 1938}
1822 1939
1940static void perf_script__fclose_per_event_dump(struct perf_script *script)
1941{
1942 struct perf_evlist *evlist = script->session->evlist;
1943 struct perf_evsel *evsel;
1944
1945 evlist__for_each_entry(evlist, evsel) {
1946 if (!evsel->priv)
1947 break;
1948 perf_evsel_script__delete(evsel->priv);
1949 evsel->priv = NULL;
1950 }
1951}
1952
1953static int perf_script__fopen_per_event_dump(struct perf_script *script)
1954{
1955 struct perf_evsel *evsel;
1956
1957 evlist__for_each_entry(script->session->evlist, evsel) {
1958 evsel->priv = perf_evsel_script__new(evsel, script->session->data);
1959 if (evsel->priv == NULL)
1960 goto out_err_fclose;
1961 }
1962
1963 return 0;
1964
1965out_err_fclose:
1966 perf_script__fclose_per_event_dump(script);
1967 return -1;
1968}
1969
1970static int perf_script__setup_per_event_dump(struct perf_script *script)
1971{
1972 struct perf_evsel *evsel;
1973 static struct perf_evsel_script es_stdout;
1974
1975 if (script->per_event_dump)
1976 return perf_script__fopen_per_event_dump(script);
1977
1978 es_stdout.fp = stdout;
1979
1980 evlist__for_each_entry(script->session->evlist, evsel)
1981 evsel->priv = &es_stdout;
1982
1983 return 0;
1984}
1985
1986static void perf_script__exit_per_event_dump_stats(struct perf_script *script)
1987{
1988 struct perf_evsel *evsel;
1989
1990 evlist__for_each_entry(script->session->evlist, evsel) {
1991 struct perf_evsel_script *es = evsel->priv;
1992
1993 perf_evsel_script__fprintf(es, stdout);
1994 perf_evsel_script__delete(es);
1995 evsel->priv = NULL;
1996 }
1997}
1998
1823static int __cmd_script(struct perf_script *script) 1999static int __cmd_script(struct perf_script *script)
1824{ 2000{
1825 int ret; 2001 int ret;
@@ -1841,8 +2017,16 @@ static int __cmd_script(struct perf_script *script)
1841 if (script->show_namespace_events) 2017 if (script->show_namespace_events)
1842 script->tool.namespaces = process_namespaces_event; 2018 script->tool.namespaces = process_namespaces_event;
1843 2019
2020 if (perf_script__setup_per_event_dump(script)) {
2021 pr_err("Couldn't create the per event dump files\n");
2022 return -1;
2023 }
2024
1844 ret = perf_session__process_events(script->session); 2025 ret = perf_session__process_events(script->session);
1845 2026
2027 if (script->per_event_dump)
2028 perf_script__exit_per_event_dump_stats(script);
2029
1846 if (debug_mode) 2030 if (debug_mode)
1847 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); 2031 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
1848 2032
@@ -2199,16 +2383,11 @@ static struct script_desc *script_desc__findnew(const char *name)
2199 2383
2200 s = script_desc__new(name); 2384 s = script_desc__new(name);
2201 if (!s) 2385 if (!s)
2202 goto out_delete_desc; 2386 return NULL;
2203 2387
2204 script_desc__add(s); 2388 script_desc__add(s);
2205 2389
2206 return s; 2390 return s;
2207
2208out_delete_desc:
2209 script_desc__delete(s);
2210
2211 return NULL;
2212} 2391}
2213 2392
2214static const char *ends_with(const char *str, const char *suffix) 2393static const char *ends_with(const char *str, const char *suffix)
@@ -2412,14 +2591,16 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
2412 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; 2591 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
2413 DIR *scripts_dir, *lang_dir; 2592 DIR *scripts_dir, *lang_dir;
2414 struct perf_session *session; 2593 struct perf_session *session;
2415 struct perf_data_file file = { 2594 struct perf_data data = {
2416 .path = input_name, 2595 .file = {
2417 .mode = PERF_DATA_MODE_READ, 2596 .path = input_name,
2597 },
2598 .mode = PERF_DATA_MODE_READ,
2418 }; 2599 };
2419 char *temp; 2600 char *temp;
2420 int i = 0; 2601 int i = 0;
2421 2602
2422 session = perf_session__new(&file, false, NULL); 2603 session = perf_session__new(&data, false, NULL);
2423 if (!session) 2604 if (!session)
2424 return -1; 2605 return -1;
2425 2606
@@ -2682,6 +2863,7 @@ int cmd_script(int argc, const char **argv)
2682 .attr = process_attr, 2863 .attr = process_attr,
2683 .event_update = perf_event__process_event_update, 2864 .event_update = perf_event__process_event_update,
2684 .tracing_data = perf_event__process_tracing_data, 2865 .tracing_data = perf_event__process_tracing_data,
2866 .feature = perf_event__process_feature,
2685 .build_id = perf_event__process_build_id, 2867 .build_id = perf_event__process_build_id,
2686 .id_index = perf_event__process_id_index, 2868 .id_index = perf_event__process_id_index,
2687 .auxtrace_info = perf_event__process_auxtrace_info, 2869 .auxtrace_info = perf_event__process_auxtrace_info,
@@ -2696,7 +2878,7 @@ int cmd_script(int argc, const char **argv)
2696 .ordering_requires_timestamps = true, 2878 .ordering_requires_timestamps = true,
2697 }, 2879 },
2698 }; 2880 };
2699 struct perf_data_file file = { 2881 struct perf_data data = {
2700 .mode = PERF_DATA_MODE_READ, 2882 .mode = PERF_DATA_MODE_READ,
2701 }; 2883 };
2702 const struct option options[] = { 2884 const struct option options[] = {
@@ -2732,8 +2914,8 @@ int cmd_script(int argc, const char **argv)
2732 "+field to add and -field to remove." 2914 "+field to add and -field to remove."
2733 "Valid types: hw,sw,trace,raw,synth. " 2915 "Valid types: hw,sw,trace,raw,synth. "
2734 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 2916 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
2735 "addr,symoff,period,iregs,brstack,brstacksym,flags," 2917 "addr,symoff,period,iregs,uregs,brstack,brstacksym,flags,"
2736 "bpf-output,callindent,insn,insnlen,brstackinsn,synth", 2918 "bpf-output,callindent,insn,insnlen,brstackinsn,synth,phys_addr",
2737 parse_output_fields), 2919 parse_output_fields),
2738 OPT_BOOLEAN('a', "all-cpus", &system_wide, 2920 OPT_BOOLEAN('a', "all-cpus", &system_wide,
2739 "system-wide collection from all CPUs"), 2921 "system-wide collection from all CPUs"),
@@ -2764,6 +2946,8 @@ int cmd_script(int argc, const char **argv)
2764 "Show context switch events (if recorded)"), 2946 "Show context switch events (if recorded)"),
2765 OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events, 2947 OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events,
2766 "Show namespace events (if recorded)"), 2948 "Show namespace events (if recorded)"),
2949 OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump,
2950 "Dump trace output to files named by the monitored events"),
2767 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), 2951 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
2768 OPT_INTEGER(0, "max-blocks", &max_blocks, 2952 OPT_INTEGER(0, "max-blocks", &max_blocks,
2769 "Maximum number of code blocks to dump with brstackinsn"), 2953 "Maximum number of code blocks to dump with brstackinsn"),
@@ -2794,13 +2978,15 @@ int cmd_script(int argc, const char **argv)
2794 NULL 2978 NULL
2795 }; 2979 };
2796 2980
2981 perf_set_singlethreaded();
2982
2797 setup_scripting(); 2983 setup_scripting();
2798 2984
2799 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage, 2985 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
2800 PARSE_OPT_STOP_AT_NON_OPTION); 2986 PARSE_OPT_STOP_AT_NON_OPTION);
2801 2987
2802 file.path = input_name; 2988 data.file.path = input_name;
2803 file.force = symbol_conf.force; 2989 data.force = symbol_conf.force;
2804 2990
2805 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { 2991 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
2806 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); 2992 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
@@ -2967,15 +3153,18 @@ int cmd_script(int argc, const char **argv)
2967 if (!script_name) 3153 if (!script_name)
2968 setup_pager(); 3154 setup_pager();
2969 3155
2970 session = perf_session__new(&file, false, &script.tool); 3156 session = perf_session__new(&data, false, &script.tool);
2971 if (session == NULL) 3157 if (session == NULL)
2972 return -1; 3158 return -1;
2973 3159
2974 if (header || header_only) { 3160 if (header || header_only) {
3161 script.tool.show_feat_hdr = SHOW_FEAT_HEADER;
2975 perf_session__fprintf_info(session, stdout, show_full_info); 3162 perf_session__fprintf_info(session, stdout, show_full_info);
2976 if (header_only) 3163 if (header_only)
2977 goto out_delete; 3164 goto out_delete;
2978 } 3165 }
3166 if (show_full_info)
3167 script.tool.show_feat_hdr = SHOW_FEAT_HEADER_FULL_INFO;
2979 3168
2980 if (symbol__init(&session->header.env) < 0) 3169 if (symbol__init(&session->header.env) < 0)
2981 goto out_delete; 3170 goto out_delete;
@@ -3005,7 +3194,8 @@ int cmd_script(int argc, const char **argv)
3005 machine__resolve_kernel_addr, 3194 machine__resolve_kernel_addr,
3006 &session->machines.host) < 0) { 3195 &session->machines.host) < 0) {
3007 pr_err("%s: failed to set libtraceevent function resolver\n", __func__); 3196 pr_err("%s: failed to set libtraceevent function resolver\n", __func__);
3008 return -1; 3197 err = -1;
3198 goto out_delete;
3009 } 3199 }
3010 3200
3011 if (generate_script_lang) { 3201 if (generate_script_lang) {
@@ -3019,7 +3209,7 @@ int cmd_script(int argc, const char **argv)
3019 goto out_delete; 3209 goto out_delete;
3020 } 3210 }
3021 3211
3022 input = open(file.path, O_RDONLY); /* input_name */ 3212 input = open(data.file.path, O_RDONLY); /* input_name */
3023 if (input < 0) { 3213 if (input < 0) {
3024 err = -errno; 3214 err = -errno;
3025 perror("failed to open file"); 3215 perror("failed to open file");
@@ -3065,7 +3255,8 @@ int cmd_script(int argc, const char **argv)
3065 /* needs to be parsed after looking up reference time */ 3255 /* needs to be parsed after looking up reference time */
3066 if (perf_time__parse_str(&script.ptime, script.time_str) != 0) { 3256 if (perf_time__parse_str(&script.ptime, script.time_str) != 0) {
3067 pr_err("Invalid time string\n"); 3257 pr_err("Invalid time string\n");
3068 return -EINVAL; 3258 err = -EINVAL;
3259 goto out_delete;
3069 } 3260 }
3070 3261
3071 err = __cmd_script(&script); 3262 err = __cmd_script(&script);
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 48ac53b199fc..59af5a8419e2 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -65,6 +65,7 @@
65#include "util/tool.h" 65#include "util/tool.h"
66#include "util/group.h" 66#include "util/group.h"
67#include "util/string2.h" 67#include "util/string2.h"
68#include "util/metricgroup.h"
68#include "asm/bug.h" 69#include "asm/bug.h"
69 70
70#include <linux/time64.h> 71#include <linux/time64.h>
@@ -133,6 +134,8 @@ static const char *smi_cost_attrs = {
133 134
134static struct perf_evlist *evsel_list; 135static struct perf_evlist *evsel_list;
135 136
137static struct rblist metric_events;
138
136static struct target target = { 139static struct target target = {
137 .uid = UINT_MAX, 140 .uid = UINT_MAX,
138}; 141};
@@ -172,7 +175,7 @@ static int print_free_counters_hint;
172 175
173struct perf_stat { 176struct perf_stat {
174 bool record; 177 bool record;
175 struct perf_data_file file; 178 struct perf_data data;
176 struct perf_session *session; 179 struct perf_session *session;
177 u64 bytes_written; 180 u64 bytes_written;
178 struct perf_tool tool; 181 struct perf_tool tool;
@@ -192,6 +195,11 @@ static struct perf_stat_config stat_config = {
192 .scale = true, 195 .scale = true,
193}; 196};
194 197
198static bool is_duration_time(struct perf_evsel *evsel)
199{
200 return !strcmp(evsel->name, "duration_time");
201}
202
195static inline void diff_timespec(struct timespec *r, struct timespec *a, 203static inline void diff_timespec(struct timespec *r, struct timespec *a,
196 struct timespec *b) 204 struct timespec *b)
197{ 205{
@@ -213,10 +221,20 @@ static void perf_stat__reset_stats(void)
213static int create_perf_stat_counter(struct perf_evsel *evsel) 221static int create_perf_stat_counter(struct perf_evsel *evsel)
214{ 222{
215 struct perf_event_attr *attr = &evsel->attr; 223 struct perf_event_attr *attr = &evsel->attr;
224 struct perf_evsel *leader = evsel->leader;
216 225
217 if (stat_config.scale) 226 if (stat_config.scale) {
218 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 227 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
219 PERF_FORMAT_TOTAL_TIME_RUNNING; 228 PERF_FORMAT_TOTAL_TIME_RUNNING;
229 }
230
231 /*
232 * The event is part of non trivial group, let's enable
233 * the group read (for leader) and ID retrieval for all
234 * members.
235 */
236 if (leader->nr_members > 1)
237 attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
220 238
221 attr->inherit = !no_inherit; 239 attr->inherit = !no_inherit;
222 240
@@ -235,7 +253,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
235 * by attr->sample_type != 0, and we can't run it on 253 * by attr->sample_type != 0, and we can't run it on
236 * stat sessions. 254 * stat sessions.
237 */ 255 */
238 if (!(STAT_RECORD && perf_stat.file.is_pipe)) 256 if (!(STAT_RECORD && perf_stat.data.is_pipe))
239 attr->sample_type = PERF_SAMPLE_IDENTIFIER; 257 attr->sample_type = PERF_SAMPLE_IDENTIFIER;
240 258
241 /* 259 /*
@@ -277,7 +295,7 @@ static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
277 struct perf_sample *sample __maybe_unused, 295 struct perf_sample *sample __maybe_unused,
278 struct machine *machine __maybe_unused) 296 struct machine *machine __maybe_unused)
279{ 297{
280 if (perf_data_file__write(&perf_stat.file, event, event->header.size) < 0) { 298 if (perf_data__write(&perf_stat.data, event, event->header.size) < 0) {
281 pr_err("failed to write perf data, error: %m\n"); 299 pr_err("failed to write perf data, error: %m\n");
282 return -1; 300 return -1;
283 } 301 }
@@ -333,13 +351,21 @@ static int read_counter(struct perf_evsel *counter)
333 struct perf_counts_values *count; 351 struct perf_counts_values *count;
334 352
335 count = perf_counts(counter->counts, cpu, thread); 353 count = perf_counts(counter->counts, cpu, thread);
336 if (perf_evsel__read(counter, cpu, thread, count)) { 354
355 /*
356 * The leader's group read loads data into its group members
357 * (via perf_evsel__read_counter) and sets threir count->loaded.
358 */
359 if (!count->loaded &&
360 perf_evsel__read_counter(counter, cpu, thread)) {
337 counter->counts->scaled = -1; 361 counter->counts->scaled = -1;
338 perf_counts(counter->counts, cpu, thread)->ena = 0; 362 perf_counts(counter->counts, cpu, thread)->ena = 0;
339 perf_counts(counter->counts, cpu, thread)->run = 0; 363 perf_counts(counter->counts, cpu, thread)->run = 0;
340 return -1; 364 return -1;
341 } 365 }
342 366
367 count->loaded = false;
368
343 if (STAT_RECORD) { 369 if (STAT_RECORD) {
344 if (perf_evsel__write_stat_event(counter, cpu, thread, count)) { 370 if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
345 pr_err("failed to write stat event\n"); 371 pr_err("failed to write stat event\n");
@@ -389,6 +415,8 @@ static void process_interval(void)
389 pr_err("failed to write stat round event\n"); 415 pr_err("failed to write stat round event\n");
390 } 416 }
391 417
418 init_stats(&walltime_nsecs_stats);
419 update_stats(&walltime_nsecs_stats, stat_config.interval * 1000000);
392 print_counters(&rs, 0, NULL); 420 print_counters(&rs, 0, NULL);
393} 421}
394 422
@@ -559,6 +587,37 @@ static int store_counter_ids(struct perf_evsel *counter)
559 return __store_counter_ids(counter, cpus, threads); 587 return __store_counter_ids(counter, cpus, threads);
560} 588}
561 589
590static bool perf_evsel__should_store_id(struct perf_evsel *counter)
591{
592 return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID;
593}
594
595static struct perf_evsel *perf_evsel__reset_weak_group(struct perf_evsel *evsel)
596{
597 struct perf_evsel *c2, *leader;
598 bool is_open = true;
599
600 leader = evsel->leader;
601 pr_debug("Weak group for %s/%d failed\n",
602 leader->name, leader->nr_members);
603
604 /*
605 * for_each_group_member doesn't work here because it doesn't
606 * include the first entry.
607 */
608 evlist__for_each_entry(evsel_list, c2) {
609 if (c2 == evsel)
610 is_open = false;
611 if (c2->leader == leader) {
612 if (is_open)
613 perf_evsel__close(c2);
614 c2->leader = c2;
615 c2->nr_members = 0;
616 }
617 }
618 return leader;
619}
620
562static int __run_perf_stat(int argc, const char **argv) 621static int __run_perf_stat(int argc, const char **argv)
563{ 622{
564 int interval = stat_config.interval; 623 int interval = stat_config.interval;
@@ -569,7 +628,7 @@ static int __run_perf_stat(int argc, const char **argv)
569 size_t l; 628 size_t l;
570 int status = 0; 629 int status = 0;
571 const bool forks = (argc > 0); 630 const bool forks = (argc > 0);
572 bool is_pipe = STAT_RECORD ? perf_stat.file.is_pipe : false; 631 bool is_pipe = STAT_RECORD ? perf_stat.data.is_pipe : false;
573 struct perf_evsel_config_term *err_term; 632 struct perf_evsel_config_term *err_term;
574 633
575 if (interval) { 634 if (interval) {
@@ -595,6 +654,15 @@ static int __run_perf_stat(int argc, const char **argv)
595 evlist__for_each_entry(evsel_list, counter) { 654 evlist__for_each_entry(evsel_list, counter) {
596try_again: 655try_again:
597 if (create_perf_stat_counter(counter) < 0) { 656 if (create_perf_stat_counter(counter) < 0) {
657
658 /* Weak group failed. Reset the group. */
659 if ((errno == EINVAL || errno == EBADF) &&
660 counter->leader != counter &&
661 counter->weak_group) {
662 counter = perf_evsel__reset_weak_group(counter);
663 goto try_again;
664 }
665
598 /* 666 /*
599 * PPC returns ENXIO for HW counters until 2.6.37 667 * PPC returns ENXIO for HW counters until 2.6.37
600 * (behavior changed with commit b0a873e). 668 * (behavior changed with commit b0a873e).
@@ -631,7 +699,8 @@ try_again:
631 if (l > unit_width) 699 if (l > unit_width)
632 unit_width = l; 700 unit_width = l;
633 701
634 if (STAT_RECORD && store_counter_ids(counter)) 702 if (perf_evsel__should_store_id(counter) &&
703 store_counter_ids(counter))
635 return -1; 704 return -1;
636 } 705 }
637 706
@@ -650,10 +719,10 @@ try_again:
650 } 719 }
651 720
652 if (STAT_RECORD) { 721 if (STAT_RECORD) {
653 int err, fd = perf_data_file__fd(&perf_stat.file); 722 int err, fd = perf_data__fd(&perf_stat.data);
654 723
655 if (is_pipe) { 724 if (is_pipe) {
656 err = perf_header__write_pipe(perf_data_file__fd(&perf_stat.file)); 725 err = perf_header__write_pipe(perf_data__fd(&perf_stat.data));
657 } else { 726 } else {
658 err = perf_session__write_header(perf_stat.session, evsel_list, 727 err = perf_session__write_header(perf_stat.session, evsel_list,
659 fd, false); 728 fd, false);
@@ -683,7 +752,7 @@ try_again:
683 process_interval(); 752 process_interval();
684 } 753 }
685 } 754 }
686 wait(&status); 755 waitpid(child_pid, &status, 0);
687 756
688 if (workload_exec_errno) { 757 if (workload_exec_errno) {
689 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 758 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
@@ -776,7 +845,7 @@ static void print_noise(struct perf_evsel *evsel, double avg)
776 if (run_count == 1) 845 if (run_count == 1)
777 return; 846 return;
778 847
779 ps = evsel->priv; 848 ps = evsel->stats;
780 print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); 849 print_noise_pct(stddev_stats(&ps->res_stats[0]), avg);
781} 850}
782 851
@@ -1175,7 +1244,7 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
1175 1244
1176 perf_stat__print_shadow_stats(counter, uval, 1245 perf_stat__print_shadow_stats(counter, uval,
1177 first_shadow_cpu(counter, id), 1246 first_shadow_cpu(counter, id),
1178 &out); 1247 &out, &metric_events);
1179 if (!csv_output && !metric_only) { 1248 if (!csv_output && !metric_only) {
1180 print_noise(counter, noise); 1249 print_noise(counter, noise);
1181 print_running(run, ena); 1250 print_running(run, ena);
@@ -1198,8 +1267,7 @@ static void aggr_update_shadow(void)
1198 continue; 1267 continue;
1199 val += perf_counts(counter->counts, cpu, 0)->val; 1268 val += perf_counts(counter->counts, cpu, 0)->val;
1200 } 1269 }
1201 val = val * counter->scale; 1270 perf_stat__update_shadow_stats(counter, val,
1202 perf_stat__update_shadow_stats(counter, &val,
1203 first_shadow_cpu(counter, id)); 1271 first_shadow_cpu(counter, id));
1204 } 1272 }
1205 } 1273 }
@@ -1233,7 +1301,7 @@ static bool collect_data(struct perf_evsel *counter,
1233 if (counter->merged_stat) 1301 if (counter->merged_stat)
1234 return false; 1302 return false;
1235 cb(counter, data, true); 1303 cb(counter, data, true);
1236 if (!no_merge) 1304 if (!no_merge && counter->auto_merge_stats)
1237 collect_all_aliases(counter, cb, data); 1305 collect_all_aliases(counter, cb, data);
1238 return true; 1306 return true;
1239} 1307}
@@ -1301,6 +1369,9 @@ static void print_aggr(char *prefix)
1301 ad.id = id = aggr_map->map[s]; 1369 ad.id = id = aggr_map->map[s];
1302 first = true; 1370 first = true;
1303 evlist__for_each_entry(evsel_list, counter) { 1371 evlist__for_each_entry(evsel_list, counter) {
1372 if (is_duration_time(counter))
1373 continue;
1374
1304 ad.val = ad.ena = ad.run = 0; 1375 ad.val = ad.ena = ad.run = 0;
1305 ad.nr = 0; 1376 ad.nr = 0;
1306 if (!collect_data(counter, aggr_cb, &ad)) 1377 if (!collect_data(counter, aggr_cb, &ad))
@@ -1360,7 +1431,7 @@ static void counter_aggr_cb(struct perf_evsel *counter, void *data,
1360 bool first __maybe_unused) 1431 bool first __maybe_unused)
1361{ 1432{
1362 struct caggr_data *cd = data; 1433 struct caggr_data *cd = data;
1363 struct perf_stat_evsel *ps = counter->priv; 1434 struct perf_stat_evsel *ps = counter->stats;
1364 1435
1365 cd->avg += avg_stats(&ps->res_stats[0]); 1436 cd->avg += avg_stats(&ps->res_stats[0]);
1366 cd->avg_enabled += avg_stats(&ps->res_stats[1]); 1437 cd->avg_enabled += avg_stats(&ps->res_stats[1]);
@@ -1444,6 +1515,8 @@ static void print_no_aggr_metric(char *prefix)
1444 if (prefix) 1515 if (prefix)
1445 fputs(prefix, stat_config.output); 1516 fputs(prefix, stat_config.output);
1446 evlist__for_each_entry(evsel_list, counter) { 1517 evlist__for_each_entry(evsel_list, counter) {
1518 if (is_duration_time(counter))
1519 continue;
1447 if (first) { 1520 if (first) {
1448 aggr_printout(counter, cpu, 0); 1521 aggr_printout(counter, cpu, 0);
1449 first = false; 1522 first = false;
@@ -1498,6 +1571,8 @@ static void print_metric_headers(const char *prefix, bool no_indent)
1498 1571
1499 /* Print metrics headers only */ 1572 /* Print metrics headers only */
1500 evlist__for_each_entry(evsel_list, counter) { 1573 evlist__for_each_entry(evsel_list, counter) {
1574 if (is_duration_time(counter))
1575 continue;
1501 os.evsel = counter; 1576 os.evsel = counter;
1502 out.ctx = &os; 1577 out.ctx = &os;
1503 out.print_metric = print_metric_header; 1578 out.print_metric = print_metric_header;
@@ -1506,7 +1581,8 @@ static void print_metric_headers(const char *prefix, bool no_indent)
1506 os.evsel = counter; 1581 os.evsel = counter;
1507 perf_stat__print_shadow_stats(counter, 0, 1582 perf_stat__print_shadow_stats(counter, 0,
1508 0, 1583 0,
1509 &out); 1584 &out,
1585 &metric_events);
1510 } 1586 }
1511 fputc('\n', stat_config.output); 1587 fputc('\n', stat_config.output);
1512} 1588}
@@ -1619,7 +1695,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
1619 char buf[64], *prefix = NULL; 1695 char buf[64], *prefix = NULL;
1620 1696
1621 /* Do not print anything if we record to the pipe. */ 1697 /* Do not print anything if we record to the pipe. */
1622 if (STAT_RECORD && perf_stat.file.is_pipe) 1698 if (STAT_RECORD && perf_stat.data.is_pipe)
1623 return; 1699 return;
1624 1700
1625 if (interval) 1701 if (interval)
@@ -1644,12 +1720,18 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
1644 print_aggr(prefix); 1720 print_aggr(prefix);
1645 break; 1721 break;
1646 case AGGR_THREAD: 1722 case AGGR_THREAD:
1647 evlist__for_each_entry(evsel_list, counter) 1723 evlist__for_each_entry(evsel_list, counter) {
1724 if (is_duration_time(counter))
1725 continue;
1648 print_aggr_thread(counter, prefix); 1726 print_aggr_thread(counter, prefix);
1727 }
1649 break; 1728 break;
1650 case AGGR_GLOBAL: 1729 case AGGR_GLOBAL:
1651 evlist__for_each_entry(evsel_list, counter) 1730 evlist__for_each_entry(evsel_list, counter) {
1731 if (is_duration_time(counter))
1732 continue;
1652 print_counter_aggr(counter, prefix); 1733 print_counter_aggr(counter, prefix);
1734 }
1653 if (metric_only) 1735 if (metric_only)
1654 fputc('\n', stat_config.output); 1736 fputc('\n', stat_config.output);
1655 break; 1737 break;
@@ -1657,8 +1739,11 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
1657 if (metric_only) 1739 if (metric_only)
1658 print_no_aggr_metric(prefix); 1740 print_no_aggr_metric(prefix);
1659 else { 1741 else {
1660 evlist__for_each_entry(evsel_list, counter) 1742 evlist__for_each_entry(evsel_list, counter) {
1743 if (is_duration_time(counter))
1744 continue;
1661 print_counter(counter, prefix); 1745 print_counter(counter, prefix);
1746 }
1662 } 1747 }
1663 break; 1748 break;
1664 case AGGR_UNSET: 1749 case AGGR_UNSET:
@@ -1730,6 +1815,13 @@ static int enable_metric_only(const struct option *opt __maybe_unused,
1730 return 0; 1815 return 0;
1731} 1816}
1732 1817
1818static int parse_metric_groups(const struct option *opt,
1819 const char *str,
1820 int unset __maybe_unused)
1821{
1822 return metricgroup__parse_groups(opt, str, &metric_events);
1823}
1824
1733static const struct option stat_options[] = { 1825static const struct option stat_options[] = {
1734 OPT_BOOLEAN('T', "transaction", &transaction_run, 1826 OPT_BOOLEAN('T', "transaction", &transaction_run,
1735 "hardware transaction statistics"), 1827 "hardware transaction statistics"),
@@ -1795,6 +1887,9 @@ static const struct option stat_options[] = {
1795 "measure topdown level 1 statistics"), 1887 "measure topdown level 1 statistics"),
1796 OPT_BOOLEAN(0, "smi-cost", &smi_cost, 1888 OPT_BOOLEAN(0, "smi-cost", &smi_cost,
1797 "measure SMI cost"), 1889 "measure SMI cost"),
1890 OPT_CALLBACK('M', "metrics", &evsel_list, "metric/metric group list",
1891 "monitor specified metrics or metric groups (separated by ,)",
1892 parse_metric_groups),
1798 OPT_END() 1893 OPT_END()
1799}; 1894};
1800 1895
@@ -2310,20 +2405,20 @@ static void init_features(struct perf_session *session)
2310static int __cmd_record(int argc, const char **argv) 2405static int __cmd_record(int argc, const char **argv)
2311{ 2406{
2312 struct perf_session *session; 2407 struct perf_session *session;
2313 struct perf_data_file *file = &perf_stat.file; 2408 struct perf_data *data = &perf_stat.data;
2314 2409
2315 argc = parse_options(argc, argv, stat_options, stat_record_usage, 2410 argc = parse_options(argc, argv, stat_options, stat_record_usage,
2316 PARSE_OPT_STOP_AT_NON_OPTION); 2411 PARSE_OPT_STOP_AT_NON_OPTION);
2317 2412
2318 if (output_name) 2413 if (output_name)
2319 file->path = output_name; 2414 data->file.path = output_name;
2320 2415
2321 if (run_count != 1 || forever) { 2416 if (run_count != 1 || forever) {
2322 pr_err("Cannot use -r option with perf stat record.\n"); 2417 pr_err("Cannot use -r option with perf stat record.\n");
2323 return -1; 2418 return -1;
2324 } 2419 }
2325 2420
2326 session = perf_session__new(file, false, NULL); 2421 session = perf_session__new(data, false, NULL);
2327 if (session == NULL) { 2422 if (session == NULL) {
2328 pr_err("Perf session creation failed.\n"); 2423 pr_err("Perf session creation failed.\n");
2329 return -1; 2424 return -1;
@@ -2381,7 +2476,7 @@ int process_stat_config_event(struct perf_tool *tool,
2381 if (st->aggr_mode != AGGR_UNSET) 2476 if (st->aggr_mode != AGGR_UNSET)
2382 stat_config.aggr_mode = st->aggr_mode; 2477 stat_config.aggr_mode = st->aggr_mode;
2383 2478
2384 if (perf_stat.file.is_pipe) 2479 if (perf_stat.data.is_pipe)
2385 perf_stat_init_aggr_mode(); 2480 perf_stat_init_aggr_mode();
2386 else 2481 else
2387 perf_stat_init_aggr_mode_file(st); 2482 perf_stat_init_aggr_mode_file(st);
@@ -2489,10 +2584,10 @@ static int __cmd_report(int argc, const char **argv)
2489 input_name = "perf.data"; 2584 input_name = "perf.data";
2490 } 2585 }
2491 2586
2492 perf_stat.file.path = input_name; 2587 perf_stat.data.file.path = input_name;
2493 perf_stat.file.mode = PERF_DATA_MODE_READ; 2588 perf_stat.data.mode = PERF_DATA_MODE_READ;
2494 2589
2495 session = perf_session__new(&perf_stat.file, false, &perf_stat.tool); 2590 session = perf_session__new(&perf_stat.data, false, &perf_stat.tool);
2496 if (session == NULL) 2591 if (session == NULL)
2497 return -1; 2592 return -1;
2498 2593
@@ -2763,7 +2858,7 @@ int cmd_stat(int argc, const char **argv)
2763 * records, but the need to suppress the kptr_restrict messages in older 2858 * records, but the need to suppress the kptr_restrict messages in older
2764 * tools remain -acme 2859 * tools remain -acme
2765 */ 2860 */
2766 int fd = perf_data_file__fd(&perf_stat.file); 2861 int fd = perf_data__fd(&perf_stat.data);
2767 int err = perf_event__synthesize_kernel_mmap((void *)&perf_stat, 2862 int err = perf_event__synthesize_kernel_mmap((void *)&perf_stat,
2768 process_synthesized_event, 2863 process_synthesized_event,
2769 &perf_stat.session->machines.host); 2864 &perf_stat.session->machines.host);
@@ -2777,7 +2872,7 @@ int cmd_stat(int argc, const char **argv)
2777 pr_err("failed to write stat round event\n"); 2872 pr_err("failed to write stat round event\n");
2778 } 2873 }
2779 2874
2780 if (!perf_stat.file.is_pipe) { 2875 if (!perf_stat.data.is_pipe) {
2781 perf_stat.session->header.data_size += perf_stat.bytes_written; 2876 perf_stat.session->header.data_size += perf_stat.bytes_written;
2782 perf_session__write_header(perf_stat.session, evsel_list, fd, true); 2877 perf_session__write_header(perf_stat.session, evsel_list, fd, true);
2783 } 2878 }
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 4e2e61695986..813698a9b8c7 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1601,13 +1601,15 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1601 { "syscalls:sys_exit_pselect6", process_exit_poll }, 1601 { "syscalls:sys_exit_pselect6", process_exit_poll },
1602 { "syscalls:sys_exit_select", process_exit_poll }, 1602 { "syscalls:sys_exit_select", process_exit_poll },
1603 }; 1603 };
1604 struct perf_data_file file = { 1604 struct perf_data data = {
1605 .path = input_name, 1605 .file = {
1606 .mode = PERF_DATA_MODE_READ, 1606 .path = input_name,
1607 .force = tchart->force, 1607 },
1608 .mode = PERF_DATA_MODE_READ,
1609 .force = tchart->force,
1608 }; 1610 };
1609 1611
1610 struct perf_session *session = perf_session__new(&file, false, 1612 struct perf_session *session = perf_session__new(&data, false,
1611 &tchart->tool); 1613 &tchart->tool);
1612 int ret = -EINVAL; 1614 int ret = -EINVAL;
1613 1615
@@ -1617,7 +1619,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1617 symbol__init(&session->header.env); 1619 symbol__init(&session->header.env);
1618 1620
1619 (void)perf_header__process_sections(&session->header, 1621 (void)perf_header__process_sections(&session->header,
1620 perf_data_file__fd(session->file), 1622 perf_data__fd(session->data),
1621 tchart, 1623 tchart,
1622 process_header); 1624 process_header);
1623 1625
@@ -1732,8 +1734,10 @@ static int timechart__io_record(int argc, const char **argv)
1732 if (rec_argv == NULL) 1734 if (rec_argv == NULL)
1733 return -ENOMEM; 1735 return -ENOMEM;
1734 1736
1735 if (asprintf(&filter, "common_pid != %d", getpid()) < 0) 1737 if (asprintf(&filter, "common_pid != %d", getpid()) < 0) {
1738 free(rec_argv);
1736 return -ENOMEM; 1739 return -ENOMEM;
1740 }
1737 1741
1738 p = rec_argv; 1742 p = rec_argv;
1739 for (i = 0; i < common_args_nr; i++) 1743 for (i = 0; i < common_args_nr; i++)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 6052376634c0..477a8699f0b5 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -134,7 +134,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
134 return err; 134 return err;
135 } 135 }
136 136
137 err = symbol__disassemble(sym, map, NULL, 0, NULL); 137 err = symbol__disassemble(sym, map, NULL, 0, NULL, NULL);
138 if (err == 0) { 138 if (err == 0) {
139out_assign: 139out_assign:
140 top->sym_filter_entry = he; 140 top->sym_filter_entry = he;
@@ -183,6 +183,7 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
183 183
184static void perf_top__record_precise_ip(struct perf_top *top, 184static void perf_top__record_precise_ip(struct perf_top *top,
185 struct hist_entry *he, 185 struct hist_entry *he,
186 struct perf_sample *sample,
186 int counter, u64 ip) 187 int counter, u64 ip)
187{ 188{
188 struct annotation *notes; 189 struct annotation *notes;
@@ -199,7 +200,7 @@ static void perf_top__record_precise_ip(struct perf_top *top,
199 if (pthread_mutex_trylock(&notes->lock)) 200 if (pthread_mutex_trylock(&notes->lock))
200 return; 201 return;
201 202
202 err = hist_entry__inc_addr_samples(he, counter, ip); 203 err = hist_entry__inc_addr_samples(he, sample, counter, ip);
203 204
204 pthread_mutex_unlock(&notes->lock); 205 pthread_mutex_unlock(&notes->lock);
205 206
@@ -586,6 +587,13 @@ static void *display_thread_tui(void *arg)
586 .refresh = top->delay_secs, 587 .refresh = top->delay_secs,
587 }; 588 };
588 589
590 /* In order to read symbols from other namespaces perf to needs to call
591 * setns(2). This isn't permitted if the struct_fs has multiple users.
592 * unshare(2) the fs so that we may continue to setns into namespaces
593 * that we're observing.
594 */
595 unshare(CLONE_FS);
596
589 perf_top__sort_new_samples(top); 597 perf_top__sort_new_samples(top);
590 598
591 /* 599 /*
@@ -627,6 +635,13 @@ static void *display_thread(void *arg)
627 struct perf_top *top = arg; 635 struct perf_top *top = arg;
628 int delay_msecs, c; 636 int delay_msecs, c;
629 637
638 /* In order to read symbols from other namespaces perf to needs to call
639 * setns(2). This isn't permitted if the struct_fs has multiple users.
640 * unshare(2) the fs so that we may continue to setns into namespaces
641 * that we're observing.
642 */
643 unshare(CLONE_FS);
644
630 display_setup_sig(); 645 display_setup_sig();
631 pthread__unblock_sigwinch(); 646 pthread__unblock_sigwinch();
632repeat: 647repeat:
@@ -671,7 +686,7 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter,
671 struct perf_evsel *evsel = iter->evsel; 686 struct perf_evsel *evsel = iter->evsel;
672 687
673 if (perf_hpp_list.sym && single) 688 if (perf_hpp_list.sym && single)
674 perf_top__record_precise_ip(top, he, evsel->idx, al->addr); 689 perf_top__record_precise_ip(top, he, iter->sample, evsel->idx, al->addr);
675 690
676 hist__account_cycles(iter->sample->branch_stack, al, iter->sample, 691 hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
677 !(top->record_opts.branch_stack & PERF_SAMPLE_BRANCH_ANY)); 692 !(top->record_opts.branch_stack & PERF_SAMPLE_BRANCH_ANY));
@@ -943,8 +958,16 @@ static int __cmd_top(struct perf_top *top)
943 if (perf_session__register_idle_thread(top->session) < 0) 958 if (perf_session__register_idle_thread(top->session) < 0)
944 goto out_delete; 959 goto out_delete;
945 960
961 if (top->nr_threads_synthesize > 1)
962 perf_set_multithreaded();
963
946 machine__synthesize_threads(&top->session->machines.host, &opts->target, 964 machine__synthesize_threads(&top->session->machines.host, &opts->target,
947 top->evlist->threads, false, opts->proc_map_timeout); 965 top->evlist->threads, false,
966 opts->proc_map_timeout,
967 top->nr_threads_synthesize);
968
969 if (top->nr_threads_synthesize > 1)
970 perf_set_singlethreaded();
948 971
949 if (perf_hpp_list.socket) { 972 if (perf_hpp_list.socket) {
950 ret = perf_env__read_cpu_topology_map(&perf_env); 973 ret = perf_env__read_cpu_topology_map(&perf_env);
@@ -1097,6 +1120,7 @@ int cmd_top(int argc, const char **argv)
1097 }, 1120 },
1098 .max_stack = sysctl_perf_event_max_stack, 1121 .max_stack = sysctl_perf_event_max_stack,
1099 .sym_pcnt_filter = 5, 1122 .sym_pcnt_filter = 5,
1123 .nr_threads_synthesize = UINT_MAX,
1100 }; 1124 };
1101 struct record_opts *opts = &top.record_opts; 1125 struct record_opts *opts = &top.record_opts;
1102 struct target *target = &opts->target; 1126 struct target *target = &opts->target;
@@ -1205,6 +1229,9 @@ int cmd_top(int argc, const char **argv)
1205 "Show raw trace event output (do not use print fmt or plugins)"), 1229 "Show raw trace event output (do not use print fmt or plugins)"),
1206 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy, 1230 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
1207 "Show entries in a hierarchy"), 1231 "Show entries in a hierarchy"),
1232 OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"),
1233 OPT_UINTEGER(0, "num-thread-synthesize", &top.nr_threads_synthesize,
1234 "number of thread to run event synthesize"),
1208 OPT_END() 1235 OPT_END()
1209 }; 1236 };
1210 const char * const top_usage[] = { 1237 const char * const top_usage[] = {
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 4b2a5d298197..f2757d38c7d7 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -64,6 +64,10 @@
64# define O_CLOEXEC 02000000 64# define O_CLOEXEC 02000000
65#endif 65#endif
66 66
67#ifndef F_LINUX_SPECIFIC_BASE
68# define F_LINUX_SPECIFIC_BASE 1024
69#endif
70
67struct trace { 71struct trace {
68 struct perf_tool tool; 72 struct perf_tool tool;
69 struct syscalltbl *sctbl; 73 struct syscalltbl *sctbl;
@@ -279,34 +283,21 @@ out_delete:
279 ({ struct syscall_tp *fields = evsel->priv; \ 283 ({ struct syscall_tp *fields = evsel->priv; \
280 fields->name.pointer(&fields->name, sample); }) 284 fields->name.pointer(&fields->name, sample); })
281 285
282struct strarray { 286size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val)
283 int offset; 287{
284 int nr_entries; 288 int idx = val - sa->offset;
285 const char **entries;
286};
287 289
288#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \ 290 if (idx < 0 || idx >= sa->nr_entries)
289 .nr_entries = ARRAY_SIZE(array), \ 291 return scnprintf(bf, size, intfmt, val);
290 .entries = array, \
291}
292 292
293#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \ 293 return scnprintf(bf, size, "%s", sa->entries[idx]);
294 .offset = off, \
295 .nr_entries = ARRAY_SIZE(array), \
296 .entries = array, \
297} 294}
298 295
299static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size, 296static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
300 const char *intfmt, 297 const char *intfmt,
301 struct syscall_arg *arg) 298 struct syscall_arg *arg)
302{ 299{
303 struct strarray *sa = arg->parm; 300 return strarray__scnprintf(arg->parm, bf, size, intfmt, arg->val);
304 int idx = arg->val - sa->offset;
305
306 if (idx < 0 || idx >= sa->nr_entries)
307 return scnprintf(bf, size, intfmt, arg->val);
308
309 return scnprintf(bf, size, "%s", sa->entries[idx]);
310} 301}
311 302
312static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size, 303static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
@@ -317,24 +308,35 @@ static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
317 308
318#define SCA_STRARRAY syscall_arg__scnprintf_strarray 309#define SCA_STRARRAY syscall_arg__scnprintf_strarray
319 310
320#if defined(__i386__) || defined(__x86_64__) 311struct strarrays {
321/* 312 int nr_entries;
322 * FIXME: Make this available to all arches as soon as the ioctl beautifier 313 struct strarray **entries;
323 * gets rewritten to support all arches. 314};
324 */ 315
325static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size, 316#define DEFINE_STRARRAYS(array) struct strarrays strarrays__##array = { \
326 struct syscall_arg *arg) 317 .nr_entries = ARRAY_SIZE(array), \
327{ 318 .entries = array, \
328 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
329} 319}
330 320
331#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray 321size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size,
332#endif /* defined(__i386__) || defined(__x86_64__) */ 322 struct syscall_arg *arg)
323{
324 struct strarrays *sas = arg->parm;
325 int i;
333 326
334static size_t syscall_arg__scnprintf_fd(char *bf, size_t size, 327 for (i = 0; i < sas->nr_entries; ++i) {
335 struct syscall_arg *arg); 328 struct strarray *sa = sas->entries[i];
329 int idx = arg->val - sa->offset;
336 330
337#define SCA_FD syscall_arg__scnprintf_fd 331 if (idx >= 0 && idx < sa->nr_entries) {
332 if (sa->entries[idx] == NULL)
333 break;
334 return scnprintf(bf, size, "%s", sa->entries[idx]);
335 }
336 }
337
338 return scnprintf(bf, size, "%d", arg->val);
339}
338 340
339#ifndef AT_FDCWD 341#ifndef AT_FDCWD
340#define AT_FDCWD -100 342#define AT_FDCWD -100
@@ -358,21 +360,20 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
358 360
359#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd 361#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
360 362
361static size_t syscall_arg__scnprintf_hex(char *bf, size_t size, 363size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg)
362 struct syscall_arg *arg)
363{ 364{
364 return scnprintf(bf, size, "%#lx", arg->val); 365 return scnprintf(bf, size, "%#lx", arg->val);
365} 366}
366 367
367#define SCA_HEX syscall_arg__scnprintf_hex 368size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg)
368
369static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
370 struct syscall_arg *arg)
371{ 369{
372 return scnprintf(bf, size, "%d", arg->val); 370 return scnprintf(bf, size, "%d", arg->val);
373} 371}
374 372
375#define SCA_INT syscall_arg__scnprintf_int 373size_t syscall_arg__scnprintf_long(char *bf, size_t size, struct syscall_arg *arg)
374{
375 return scnprintf(bf, size, "%ld", arg->val);
376}
376 377
377static const char *bpf_cmd[] = { 378static const char *bpf_cmd[] = {
378 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM", 379 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
@@ -407,12 +408,27 @@ static DEFINE_STRARRAY(whences);
407 408
408static const char *fcntl_cmds[] = { 409static const char *fcntl_cmds[] = {
409 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK", 410 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
410 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64", 411 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "GETLK64",
411 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX", 412 "SETLK64", "SETLKW64", "SETOWN_EX", "GETOWN_EX",
412 "F_GETOWNER_UIDS", 413 "GETOWNER_UIDS",
413}; 414};
414static DEFINE_STRARRAY(fcntl_cmds); 415static DEFINE_STRARRAY(fcntl_cmds);
415 416
417static const char *fcntl_linux_specific_cmds[] = {
418 "SETLEASE", "GETLEASE", "NOTIFY", [5] = "CANCELLK", "DUPFD_CLOEXEC",
419 "SETPIPE_SZ", "GETPIPE_SZ", "ADD_SEALS", "GET_SEALS",
420 "GET_RW_HINT", "SET_RW_HINT", "GET_FILE_RW_HINT", "SET_FILE_RW_HINT",
421};
422
423static DEFINE_STRARRAY_OFFSET(fcntl_linux_specific_cmds, F_LINUX_SPECIFIC_BASE);
424
425static struct strarray *fcntl_cmds_arrays[] = {
426 &strarray__fcntl_cmds,
427 &strarray__fcntl_linux_specific_cmds,
428};
429
430static DEFINE_STRARRAYS(fcntl_cmds_arrays);
431
416static const char *rlimit_resources[] = { 432static const char *rlimit_resources[] = {
417 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE", 433 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
418 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO", 434 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
@@ -495,33 +511,6 @@ static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
495 511
496#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags 512#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
497 513
498#if defined(__i386__) || defined(__x86_64__)
499/*
500 * FIXME: Make this available to all arches.
501 */
502#define TCGETS 0x5401
503
504static const char *tioctls[] = {
505 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
506 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
507 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
508 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
509 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
510 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
511 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
512 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
513 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
514 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
515 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
516 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
517 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
518 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
519 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
520};
521
522static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
523#endif /* defined(__i386__) || defined(__x86_64__) */
524
525#ifndef GRND_NONBLOCK 514#ifndef GRND_NONBLOCK
526#define GRND_NONBLOCK 0x0001 515#define GRND_NONBLOCK 0x0001
527#endif 516#endif
@@ -552,9 +541,9 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
552 541
553#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags 542#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
554 543
555#define STRARRAY(arg, name, array) \ 544#define STRARRAY(name, array) \
556 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \ 545 { .scnprintf = SCA_STRARRAY, \
557 .arg_parm = { [arg] = &strarray__##array, } 546 .parm = &strarray__##array, }
558 547
559#include "trace/beauty/eventfd.c" 548#include "trace/beauty/eventfd.c"
560#include "trace/beauty/flock.c" 549#include "trace/beauty/flock.c"
@@ -571,242 +560,228 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
571#include "trace/beauty/socket_type.c" 560#include "trace/beauty/socket_type.c"
572#include "trace/beauty/waitid_options.c" 561#include "trace/beauty/waitid_options.c"
573 562
563struct syscall_arg_fmt {
564 size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
565 void *parm;
566 const char *name;
567 bool show_zero;
568};
569
574static struct syscall_fmt { 570static struct syscall_fmt {
575 const char *name; 571 const char *name;
576 const char *alias; 572 const char *alias;
577 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg); 573 struct syscall_arg_fmt arg[6];
578 void *arg_parm[6]; 574 u8 nr_args;
579 bool errmsg;
580 bool errpid; 575 bool errpid;
581 bool timeout; 576 bool timeout;
582 bool hexret; 577 bool hexret;
583} syscall_fmts[] = { 578} syscall_fmts[] = {
584 { .name = "access", .errmsg = true, 579 { .name = "access",
585 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, }, 580 .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, },
586 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, 581 { .name = "bpf",
587 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), }, 582 .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, },
588 { .name = "brk", .hexret = true, 583 { .name = "brk", .hexret = true,
589 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, 584 .arg = { [0] = { .scnprintf = SCA_HEX, /* brk */ }, }, },
590 { .name = "chdir", .errmsg = true, }, 585 { .name = "clock_gettime",
591 { .name = "chmod", .errmsg = true, }, 586 .arg = { [0] = STRARRAY(clk_id, clockid), }, },
592 { .name = "chroot", .errmsg = true, }, 587 { .name = "clone", .errpid = true, .nr_args = 5,
593 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, 588 .arg = { [0] = { .name = "flags", .scnprintf = SCA_CLONE_FLAGS, },
594 { .name = "clone", .errpid = true, }, 589 [1] = { .name = "child_stack", .scnprintf = SCA_HEX, },
595 { .name = "close", .errmsg = true, 590 [2] = { .name = "parent_tidptr", .scnprintf = SCA_HEX, },
596 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, 591 [3] = { .name = "child_tidptr", .scnprintf = SCA_HEX, },
597 { .name = "connect", .errmsg = true, }, 592 [4] = { .name = "tls", .scnprintf = SCA_HEX, }, }, },
598 { .name = "creat", .errmsg = true, }, 593 { .name = "close",
599 { .name = "dup", .errmsg = true, }, 594 .arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, },
600 { .name = "dup2", .errmsg = true, }, 595 { .name = "epoll_ctl",
601 { .name = "dup3", .errmsg = true, }, 596 .arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, },
602 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), }, 597 { .name = "eventfd2",
603 { .name = "eventfd2", .errmsg = true, 598 .arg = { [1] = { .scnprintf = SCA_EFD_FLAGS, /* flags */ }, }, },
604 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, 599 { .name = "fchmodat",
605 { .name = "faccessat", .errmsg = true, }, 600 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
606 { .name = "fadvise64", .errmsg = true, }, 601 { .name = "fchownat",
607 { .name = "fallocate", .errmsg = true, }, 602 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
608 { .name = "fchdir", .errmsg = true, }, 603 { .name = "fcntl",
609 { .name = "fchmod", .errmsg = true, }, 604 .arg = { [1] = { .scnprintf = SCA_FCNTL_CMD, /* cmd */
610 { .name = "fchmodat", .errmsg = true, 605 .parm = &strarrays__fcntl_cmds_arrays,
611 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 606 .show_zero = true, },
612 { .name = "fchown", .errmsg = true, }, 607 [2] = { .scnprintf = SCA_FCNTL_ARG, /* arg */ }, }, },
613 { .name = "fchownat", .errmsg = true, 608 { .name = "flock",
614 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 609 .arg = { [1] = { .scnprintf = SCA_FLOCK, /* cmd */ }, }, },
615 { .name = "fcntl", .errmsg = true, 610 { .name = "fstat", .alias = "newfstat", },
616 .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ }, 611 { .name = "fstatat", .alias = "newfstatat", },
617 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, }, 612 { .name = "futex",
618 { .name = "fdatasync", .errmsg = true, }, 613 .arg = { [1] = { .scnprintf = SCA_FUTEX_OP, /* op */ }, }, },
619 { .name = "flock", .errmsg = true, 614 { .name = "futimesat",
620 .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, }, 615 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
621 { .name = "fsetxattr", .errmsg = true, }, 616 { .name = "getitimer",
622 { .name = "fstat", .errmsg = true, .alias = "newfstat", }, 617 .arg = { [0] = STRARRAY(which, itimers), }, },
623 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
624 { .name = "fstatfs", .errmsg = true, },
625 { .name = "fsync", .errmsg = true, },
626 { .name = "ftruncate", .errmsg = true, },
627 { .name = "futex", .errmsg = true,
628 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
629 { .name = "futimesat", .errmsg = true,
630 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
631 { .name = "getdents", .errmsg = true, },
632 { .name = "getdents64", .errmsg = true, },
633 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
634 { .name = "getpid", .errpid = true, }, 618 { .name = "getpid", .errpid = true, },
635 { .name = "getpgid", .errpid = true, }, 619 { .name = "getpgid", .errpid = true, },
636 { .name = "getppid", .errpid = true, }, 620 { .name = "getppid", .errpid = true, },
637 { .name = "getrandom", .errmsg = true, 621 { .name = "getrandom",
638 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, }, 622 .arg = { [2] = { .scnprintf = SCA_GETRANDOM_FLAGS, /* flags */ }, }, },
639 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 623 { .name = "getrlimit",
640 { .name = "getxattr", .errmsg = true, }, 624 .arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
641 { .name = "inotify_add_watch", .errmsg = true, }, 625 { .name = "ioctl",
642 { .name = "ioctl", .errmsg = true, 626 .arg = {
643 .arg_scnprintf = {
644#if defined(__i386__) || defined(__x86_64__) 627#if defined(__i386__) || defined(__x86_64__)
645/* 628/*
646 * FIXME: Make this available to all arches. 629 * FIXME: Make this available to all arches.
647 */ 630 */
648 [1] = SCA_STRHEXARRAY, /* cmd */ 631 [1] = { .scnprintf = SCA_IOCTL_CMD, /* cmd */ },
649 [2] = SCA_HEX, /* arg */ }, 632 [2] = { .scnprintf = SCA_HEX, /* arg */ }, }, },
650 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
651#else 633#else
652 [2] = SCA_HEX, /* arg */ }, }, 634 [2] = { .scnprintf = SCA_HEX, /* arg */ }, }, },
653#endif 635#endif
654 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), }, 636 { .name = "kcmp", .nr_args = 5,
655 { .name = "kill", .errmsg = true, 637 .arg = { [0] = { .name = "pid1", .scnprintf = SCA_PID, },
656 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 638 [1] = { .name = "pid2", .scnprintf = SCA_PID, },
657 { .name = "lchown", .errmsg = true, }, 639 [2] = { .name = "type", .scnprintf = SCA_KCMP_TYPE, },
658 { .name = "lgetxattr", .errmsg = true, }, 640 [3] = { .name = "idx1", .scnprintf = SCA_KCMP_IDX, },
659 { .name = "linkat", .errmsg = true, 641 [4] = { .name = "idx2", .scnprintf = SCA_KCMP_IDX, }, }, },
660 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 642 { .name = "keyctl",
661 { .name = "listxattr", .errmsg = true, }, 643 .arg = { [0] = STRARRAY(option, keyctl_options), }, },
662 { .name = "llistxattr", .errmsg = true, }, 644 { .name = "kill",
663 { .name = "lremovexattr", .errmsg = true, }, 645 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
664 { .name = "lseek", .errmsg = true, 646 { .name = "linkat",
665 .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ }, 647 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
666 .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, 648 { .name = "lseek",
667 { .name = "lsetxattr", .errmsg = true, }, 649 .arg = { [2] = STRARRAY(whence, whences), }, },
668 { .name = "lstat", .errmsg = true, .alias = "newlstat", }, 650 { .name = "lstat", .alias = "newlstat", },
669 { .name = "lsxattr", .errmsg = true, }, 651 { .name = "madvise",
670 { .name = "madvise", .errmsg = true, 652 .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
671 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 653 [2] = { .scnprintf = SCA_MADV_BHV, /* behavior */ }, }, },
672 [2] = SCA_MADV_BHV, /* behavior */ }, }, 654 { .name = "mkdirat",
673 { .name = "mkdir", .errmsg = true, }, 655 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
674 { .name = "mkdirat", .errmsg = true, 656 { .name = "mknodat",
675 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 657 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
676 { .name = "mknod", .errmsg = true, }, 658 { .name = "mlock",
677 { .name = "mknodat", .errmsg = true, 659 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
678 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 660 { .name = "mlockall",
679 { .name = "mlock", .errmsg = true, 661 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
680 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
681 { .name = "mlockall", .errmsg = true,
682 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
683 { .name = "mmap", .hexret = true, 662 { .name = "mmap", .hexret = true,
684/* The standard mmap maps to old_mmap on s390x */ 663/* The standard mmap maps to old_mmap on s390x */
685#if defined(__s390x__) 664#if defined(__s390x__)
686 .alias = "old_mmap", 665 .alias = "old_mmap",
687#endif 666#endif
688 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 667 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
689 [2] = SCA_MMAP_PROT, /* prot */ 668 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
690 [3] = SCA_MMAP_FLAGS, /* flags */ }, }, 669 [3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, },
691 { .name = "mprotect", .errmsg = true, 670 { .name = "mprotect",
692 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 671 .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
693 [2] = SCA_MMAP_PROT, /* prot */ }, }, 672 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, },
694 { .name = "mq_unlink", .errmsg = true, 673 { .name = "mq_unlink",
695 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, }, 674 .arg = { [0] = { .scnprintf = SCA_FILENAME, /* u_name */ }, }, },
696 { .name = "mremap", .hexret = true, 675 { .name = "mremap", .hexret = true,
697 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 676 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
698 [3] = SCA_MREMAP_FLAGS, /* flags */ 677 [3] = { .scnprintf = SCA_MREMAP_FLAGS, /* flags */ },
699 [4] = SCA_HEX, /* new_addr */ }, }, 678 [4] = { .scnprintf = SCA_HEX, /* new_addr */ }, }, },
700 { .name = "munlock", .errmsg = true, 679 { .name = "munlock",
701 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 680 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
702 { .name = "munmap", .errmsg = true, 681 { .name = "munmap",
703 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 682 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
704 { .name = "name_to_handle_at", .errmsg = true, 683 { .name = "name_to_handle_at",
705 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 684 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
706 { .name = "newfstatat", .errmsg = true, 685 { .name = "newfstatat",
707 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 686 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
708 { .name = "open", .errmsg = true, 687 { .name = "open",
709 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, }, 688 .arg = { [1] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
710 { .name = "open_by_handle_at", .errmsg = true, 689 { .name = "open_by_handle_at",
711 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 690 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
712 [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 691 [2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
713 { .name = "openat", .errmsg = true, 692 { .name = "openat",
714 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 693 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
715 [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 694 [2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
716 { .name = "perf_event_open", .errmsg = true, 695 { .name = "perf_event_open",
717 .arg_scnprintf = { [2] = SCA_INT, /* cpu */ 696 .arg = { [2] = { .scnprintf = SCA_INT, /* cpu */ },
718 [3] = SCA_FD, /* group_fd */ 697 [3] = { .scnprintf = SCA_FD, /* group_fd */ },
719 [4] = SCA_PERF_FLAGS, /* flags */ }, }, 698 [4] = { .scnprintf = SCA_PERF_FLAGS, /* flags */ }, }, },
720 { .name = "pipe2", .errmsg = true, 699 { .name = "pipe2",
721 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, }, 700 .arg = { [1] = { .scnprintf = SCA_PIPE_FLAGS, /* flags */ }, }, },
722 { .name = "poll", .errmsg = true, .timeout = true, }, 701 { .name = "pkey_alloc",
723 { .name = "ppoll", .errmsg = true, .timeout = true, }, 702 .arg = { [1] = { .scnprintf = SCA_PKEY_ALLOC_ACCESS_RIGHTS, /* access_rights */ }, }, },
724 { .name = "pread", .errmsg = true, .alias = "pread64", }, 703 { .name = "pkey_free",
725 { .name = "preadv", .errmsg = true, .alias = "pread", }, 704 .arg = { [0] = { .scnprintf = SCA_INT, /* key */ }, }, },
726 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), }, 705 { .name = "pkey_mprotect",
727 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", }, 706 .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
728 { .name = "pwritev", .errmsg = true, }, 707 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
729 { .name = "read", .errmsg = true, }, 708 [3] = { .scnprintf = SCA_INT, /* pkey */ }, }, },
730 { .name = "readlink", .errmsg = true, }, 709 { .name = "poll", .timeout = true, },
731 { .name = "readlinkat", .errmsg = true, 710 { .name = "ppoll", .timeout = true, },
732 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 711 { .name = "prctl", .alias = "arch_prctl",
733 { .name = "readv", .errmsg = true, }, 712 .arg = { [0] = { .scnprintf = SCA_PRCTL_OPTION, /* option */ },
734 { .name = "recvfrom", .errmsg = true, 713 [1] = { .scnprintf = SCA_PRCTL_ARG2, /* arg2 */ },
735 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 714 [2] = { .scnprintf = SCA_PRCTL_ARG3, /* arg3 */ }, }, },
736 { .name = "recvmmsg", .errmsg = true, 715 { .name = "pread", .alias = "pread64", },
737 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 716 { .name = "preadv", .alias = "pread", },
738 { .name = "recvmsg", .errmsg = true, 717 { .name = "prlimit64",
739 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, 718 .arg = { [1] = STRARRAY(resource, rlimit_resources), }, },
740 { .name = "removexattr", .errmsg = true, }, 719 { .name = "pwrite", .alias = "pwrite64", },
741 { .name = "renameat", .errmsg = true, 720 { .name = "readlinkat",
742 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 721 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
743 { .name = "rmdir", .errmsg = true, }, 722 { .name = "recvfrom",
744 { .name = "rt_sigaction", .errmsg = true, 723 .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
745 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, 724 { .name = "recvmmsg",
746 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), }, 725 .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
747 { .name = "rt_sigqueueinfo", .errmsg = true, 726 { .name = "recvmsg",
748 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 727 .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
749 { .name = "rt_tgsigqueueinfo", .errmsg = true, 728 { .name = "renameat",
750 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 729 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
751 { .name = "sched_getattr", .errmsg = true, }, 730 { .name = "rt_sigaction",
752 { .name = "sched_setattr", .errmsg = true, }, 731 .arg = { [0] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
753 { .name = "sched_setscheduler", .errmsg = true, 732 { .name = "rt_sigprocmask",
754 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, }, 733 .arg = { [0] = STRARRAY(how, sighow), }, },
755 { .name = "seccomp", .errmsg = true, 734 { .name = "rt_sigqueueinfo",
756 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */ 735 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
757 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, }, 736 { .name = "rt_tgsigqueueinfo",
758 { .name = "select", .errmsg = true, .timeout = true, }, 737 .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
759 { .name = "sendmmsg", .errmsg = true, 738 { .name = "sched_setscheduler",
760 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 739 .arg = { [1] = { .scnprintf = SCA_SCHED_POLICY, /* policy */ }, }, },
761 { .name = "sendmsg", .errmsg = true, 740 { .name = "seccomp",
762 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, 741 .arg = { [0] = { .scnprintf = SCA_SECCOMP_OP, /* op */ },
763 { .name = "sendto", .errmsg = true, 742 [1] = { .scnprintf = SCA_SECCOMP_FLAGS, /* flags */ }, }, },
764 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 743 { .name = "select", .timeout = true, },
744 { .name = "sendmmsg",
745 .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
746 { .name = "sendmsg",
747 .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
748 { .name = "sendto",
749 .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
765 { .name = "set_tid_address", .errpid = true, }, 750 { .name = "set_tid_address", .errpid = true, },
766 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, 751 { .name = "setitimer",
767 { .name = "setpgid", .errmsg = true, }, 752 .arg = { [0] = STRARRAY(which, itimers), }, },
768 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 753 { .name = "setrlimit",
769 { .name = "setxattr", .errmsg = true, }, 754 .arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
770 { .name = "shutdown", .errmsg = true, }, 755 { .name = "socket",
771 { .name = "socket", .errmsg = true, 756 .arg = { [0] = STRARRAY(family, socket_families),
772 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ 757 [1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, },
773 [1] = SCA_SK_TYPE, /* type */ }, 758 { .name = "socketpair",
774 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, 759 .arg = { [0] = STRARRAY(family, socket_families),
775 { .name = "socketpair", .errmsg = true, 760 [1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, },
776 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ 761 { .name = "stat", .alias = "newstat", },
777 [1] = SCA_SK_TYPE, /* type */ }, 762 { .name = "statx",
778 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, 763 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fdat */ },
779 { .name = "stat", .errmsg = true, .alias = "newstat", }, 764 [2] = { .scnprintf = SCA_STATX_FLAGS, /* flags */ } ,
780 { .name = "statfs", .errmsg = true, }, 765 [3] = { .scnprintf = SCA_STATX_MASK, /* mask */ }, }, },
781 { .name = "statx", .errmsg = true, 766 { .name = "swapoff",
782 .arg_scnprintf = { [0] = SCA_FDAT, /* flags */ 767 .arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, },
783 [2] = SCA_STATX_FLAGS, /* flags */ 768 { .name = "swapon",
784 [3] = SCA_STATX_MASK, /* mask */ }, }, 769 .arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, },
785 { .name = "swapoff", .errmsg = true, 770 { .name = "symlinkat",
786 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, 771 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
787 { .name = "swapon", .errmsg = true, 772 { .name = "tgkill",
788 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, 773 .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
789 { .name = "symlinkat", .errmsg = true, 774 { .name = "tkill",
790 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 775 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
791 { .name = "tgkill", .errmsg = true, 776 { .name = "uname", .alias = "newuname", },
792 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 777 { .name = "unlinkat",
793 { .name = "tkill", .errmsg = true, 778 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
794 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 779 { .name = "utimensat",
795 { .name = "truncate", .errmsg = true, }, 780 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dirfd */ }, }, },
796 { .name = "uname", .errmsg = true, .alias = "newuname", },
797 { .name = "unlinkat", .errmsg = true,
798 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
799 { .name = "utime", .errmsg = true, },
800 { .name = "utimensat", .errmsg = true,
801 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
802 { .name = "utimes", .errmsg = true, },
803 { .name = "vmsplice", .errmsg = true, },
804 { .name = "wait4", .errpid = true, 781 { .name = "wait4", .errpid = true,
805 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, }, 782 .arg = { [2] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, },
806 { .name = "waitid", .errpid = true, 783 { .name = "waitid", .errpid = true,
807 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, }, 784 .arg = { [3] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, },
808 { .name = "write", .errmsg = true, },
809 { .name = "writev", .errmsg = true, },
810}; 785};
811 786
812static int syscall_fmt__cmp(const void *name, const void *fmtp) 787static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -828,8 +803,7 @@ struct syscall {
828 const char *name; 803 const char *name;
829 bool is_exit; 804 bool is_exit;
830 struct syscall_fmt *fmt; 805 struct syscall_fmt *fmt;
831 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg); 806 struct syscall_arg_fmt *arg_fmt;
832 void **arg_parm;
833}; 807};
834 808
835/* 809/*
@@ -859,6 +833,8 @@ static size_t fprintf_duration(unsigned long t, bool calculated, FILE *fp)
859 * filename.ptr: The filename char pointer that will be vfs_getname'd 833 * filename.ptr: The filename char pointer that will be vfs_getname'd
860 * filename.entry_str_pos: Where to insert the string translated from 834 * filename.entry_str_pos: Where to insert the string translated from
861 * filename.ptr by the vfs_getname tracepoint/kprobe. 835 * filename.ptr by the vfs_getname tracepoint/kprobe.
836 * ret_scnprintf: syscall args may set this to a different syscall return
837 * formatter, for instance, fcntl may return fds, file flags, etc.
862 */ 838 */
863struct thread_trace { 839struct thread_trace {
864 u64 entry_time; 840 u64 entry_time;
@@ -867,6 +843,7 @@ struct thread_trace {
867 unsigned long pfmaj, pfmin; 843 unsigned long pfmaj, pfmin;
868 char *entry_str; 844 char *entry_str;
869 double runtime_ms; 845 double runtime_ms;
846 size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
870 struct { 847 struct {
871 unsigned long ptr; 848 unsigned long ptr;
872 short int entry_str_pos; 849 short int entry_str_pos;
@@ -917,6 +894,15 @@ fail:
917 return NULL; 894 return NULL;
918} 895}
919 896
897
898void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
899 size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg))
900{
901 struct thread_trace *ttrace = thread__priv(arg->thread);
902
903 ttrace->ret_scnprintf = ret_scnprintf;
904}
905
920#define TRACE_PFMAJ (1 << 0) 906#define TRACE_PFMAJ (1 << 0)
921#define TRACE_PFMIN (1 << 1) 907#define TRACE_PFMIN (1 << 1)
922 908
@@ -996,8 +982,7 @@ static const char *thread__fd_path(struct thread *thread, int fd,
996 return ttrace->paths.table[fd]; 982 return ttrace->paths.table[fd];
997} 983}
998 984
999static size_t syscall_arg__scnprintf_fd(char *bf, size_t size, 985size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg)
1000 struct syscall_arg *arg)
1001{ 986{
1002 int fd = arg->val; 987 int fd = arg->val;
1003 size_t printed = scnprintf(bf, size, "%d", fd); 988 size_t printed = scnprintf(bf, size, "%d", fd);
@@ -1009,6 +994,23 @@ static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1009 return printed; 994 return printed;
1010} 995}
1011 996
997size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size)
998{
999 size_t printed = scnprintf(bf, size, "%d", fd);
1000 struct thread *thread = machine__find_thread(trace->host, pid, pid);
1001
1002 if (thread) {
1003 const char *path = thread__fd_path(thread, fd, trace);
1004
1005 if (path)
1006 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1007
1008 thread__put(thread);
1009 }
1010
1011 return printed;
1012}
1013
1012static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size, 1014static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1013 struct syscall_arg *arg) 1015 struct syscall_arg *arg)
1014{ 1016{
@@ -1155,39 +1157,61 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1155 1157
1156 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, 1158 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
1157 evlist->threads, trace__tool_process, false, 1159 evlist->threads, trace__tool_process, false,
1158 trace->opts.proc_map_timeout); 1160 trace->opts.proc_map_timeout, 1);
1159 if (err) 1161 if (err)
1160 symbol__exit(); 1162 symbol__exit();
1161 1163
1162 return err; 1164 return err;
1163} 1165}
1164 1166
1167static void trace__symbols__exit(struct trace *trace)
1168{
1169 machine__exit(trace->host);
1170 trace->host = NULL;
1171
1172 symbol__exit();
1173}
1174
1175static int syscall__alloc_arg_fmts(struct syscall *sc, int nr_args)
1176{
1177 int idx;
1178
1179 if (nr_args == 6 && sc->fmt && sc->fmt->nr_args != 0)
1180 nr_args = sc->fmt->nr_args;
1181
1182 sc->arg_fmt = calloc(nr_args, sizeof(*sc->arg_fmt));
1183 if (sc->arg_fmt == NULL)
1184 return -1;
1185
1186 for (idx = 0; idx < nr_args; ++idx) {
1187 if (sc->fmt)
1188 sc->arg_fmt[idx] = sc->fmt->arg[idx];
1189 }
1190
1191 sc->nr_args = nr_args;
1192 return 0;
1193}
1194
1165static int syscall__set_arg_fmts(struct syscall *sc) 1195static int syscall__set_arg_fmts(struct syscall *sc)
1166{ 1196{
1167 struct format_field *field; 1197 struct format_field *field;
1168 int idx = 0, len; 1198 int idx = 0, len;
1169 1199
1170 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *)); 1200 for (field = sc->args; field; field = field->next, ++idx) {
1171 if (sc->arg_scnprintf == NULL) 1201 if (sc->fmt && sc->fmt->arg[idx].scnprintf)
1172 return -1; 1202 continue;
1173
1174 if (sc->fmt)
1175 sc->arg_parm = sc->fmt->arg_parm;
1176 1203
1177 for (field = sc->args; field; field = field->next) { 1204 if (strcmp(field->type, "const char *") == 0 &&
1178 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1179 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1180 else if (strcmp(field->type, "const char *") == 0 &&
1181 (strcmp(field->name, "filename") == 0 || 1205 (strcmp(field->name, "filename") == 0 ||
1182 strcmp(field->name, "path") == 0 || 1206 strcmp(field->name, "path") == 0 ||
1183 strcmp(field->name, "pathname") == 0)) 1207 strcmp(field->name, "pathname") == 0))
1184 sc->arg_scnprintf[idx] = SCA_FILENAME; 1208 sc->arg_fmt[idx].scnprintf = SCA_FILENAME;
1185 else if (field->flags & FIELD_IS_POINTER) 1209 else if (field->flags & FIELD_IS_POINTER)
1186 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex; 1210 sc->arg_fmt[idx].scnprintf = syscall_arg__scnprintf_hex;
1187 else if (strcmp(field->type, "pid_t") == 0) 1211 else if (strcmp(field->type, "pid_t") == 0)
1188 sc->arg_scnprintf[idx] = SCA_PID; 1212 sc->arg_fmt[idx].scnprintf = SCA_PID;
1189 else if (strcmp(field->type, "umode_t") == 0) 1213 else if (strcmp(field->type, "umode_t") == 0)
1190 sc->arg_scnprintf[idx] = SCA_MODE_T; 1214 sc->arg_fmt[idx].scnprintf = SCA_MODE_T;
1191 else if ((strcmp(field->type, "int") == 0 || 1215 else if ((strcmp(field->type, "int") == 0 ||
1192 strcmp(field->type, "unsigned int") == 0 || 1216 strcmp(field->type, "unsigned int") == 0 ||
1193 strcmp(field->type, "long") == 0) && 1217 strcmp(field->type, "long") == 0) &&
@@ -1200,9 +1224,8 @@ static int syscall__set_arg_fmts(struct syscall *sc)
1200 * 23 unsigned int 1224 * 23 unsigned int
1201 * 7 unsigned long 1225 * 7 unsigned long
1202 */ 1226 */
1203 sc->arg_scnprintf[idx] = SCA_FD; 1227 sc->arg_fmt[idx].scnprintf = SCA_FD;
1204 } 1228 }
1205 ++idx;
1206 } 1229 }
1207 1230
1208 return 0; 1231 return 0;
@@ -1247,11 +1270,13 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1247 sc->tp_format = trace_event__tp_format("syscalls", tp_name); 1270 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
1248 } 1271 }
1249 1272
1273 if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ? 6 : sc->tp_format->format.nr_fields))
1274 return -1;
1275
1250 if (IS_ERR(sc->tp_format)) 1276 if (IS_ERR(sc->tp_format))
1251 return -1; 1277 return -1;
1252 1278
1253 sc->args = sc->tp_format->format.fields; 1279 sc->args = sc->tp_format->format.fields;
1254 sc->nr_args = sc->tp_format->format.nr_fields;
1255 /* 1280 /*
1256 * We need to check and discard the first variable '__syscall_nr' 1281 * We need to check and discard the first variable '__syscall_nr'
1257 * or 'nr' that mean the syscall number. It is needless here. 1282 * or 'nr' that mean the syscall number. It is needless here.
@@ -1270,6 +1295,7 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1270static int trace__validate_ev_qualifier(struct trace *trace) 1295static int trace__validate_ev_qualifier(struct trace *trace)
1271{ 1296{
1272 int err = 0, i; 1297 int err = 0, i;
1298 size_t nr_allocated;
1273 struct str_node *pos; 1299 struct str_node *pos;
1274 1300
1275 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier); 1301 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
@@ -1283,13 +1309,18 @@ static int trace__validate_ev_qualifier(struct trace *trace)
1283 goto out; 1309 goto out;
1284 } 1310 }
1285 1311
1312 nr_allocated = trace->ev_qualifier_ids.nr;
1286 i = 0; 1313 i = 0;
1287 1314
1288 strlist__for_each_entry(pos, trace->ev_qualifier) { 1315 strlist__for_each_entry(pos, trace->ev_qualifier) {
1289 const char *sc = pos->s; 1316 const char *sc = pos->s;
1290 int id = syscalltbl__id(trace->sctbl, sc); 1317 int id = syscalltbl__id(trace->sctbl, sc), match_next = -1;
1291 1318
1292 if (id < 0) { 1319 if (id < 0) {
1320 id = syscalltbl__strglobmatch_first(trace->sctbl, sc, &match_next);
1321 if (id >= 0)
1322 goto matches;
1323
1293 if (err == 0) { 1324 if (err == 0) {
1294 fputs("Error:\tInvalid syscall ", trace->output); 1325 fputs("Error:\tInvalid syscall ", trace->output);
1295 err = -EINVAL; 1326 err = -EINVAL;
@@ -1299,13 +1330,37 @@ static int trace__validate_ev_qualifier(struct trace *trace)
1299 1330
1300 fputs(sc, trace->output); 1331 fputs(sc, trace->output);
1301 } 1332 }
1302 1333matches:
1303 trace->ev_qualifier_ids.entries[i++] = id; 1334 trace->ev_qualifier_ids.entries[i++] = id;
1335 if (match_next == -1)
1336 continue;
1337
1338 while (1) {
1339 id = syscalltbl__strglobmatch_next(trace->sctbl, sc, &match_next);
1340 if (id < 0)
1341 break;
1342 if (nr_allocated == trace->ev_qualifier_ids.nr) {
1343 void *entries;
1344
1345 nr_allocated += 8;
1346 entries = realloc(trace->ev_qualifier_ids.entries,
1347 nr_allocated * sizeof(trace->ev_qualifier_ids.entries[0]));
1348 if (entries == NULL) {
1349 err = -ENOMEM;
1350 fputs("\nError:\t Not enough memory for parsing\n", trace->output);
1351 goto out_free;
1352 }
1353 trace->ev_qualifier_ids.entries = entries;
1354 }
1355 trace->ev_qualifier_ids.nr++;
1356 trace->ev_qualifier_ids.entries[i++] = id;
1357 }
1304 } 1358 }
1305 1359
1306 if (err < 0) { 1360 if (err < 0) {
1307 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'" 1361 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1308 "\nHint:\tand: 'man syscalls'\n", trace->output); 1362 "\nHint:\tand: 'man syscalls'\n", trace->output);
1363out_free:
1309 zfree(&trace->ev_qualifier_ids.entries); 1364 zfree(&trace->ev_qualifier_ids.entries);
1310 trace->ev_qualifier_ids.nr = 0; 1365 trace->ev_qualifier_ids.nr = 0;
1311 } 1366 }
@@ -1321,33 +1376,68 @@ out:
1321 * variable to read it. Most notably this avoids extended load instructions 1376 * variable to read it. Most notably this avoids extended load instructions
1322 * on unaligned addresses 1377 * on unaligned addresses
1323 */ 1378 */
1379unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx)
1380{
1381 unsigned long val;
1382 unsigned char *p = arg->args + sizeof(unsigned long) * idx;
1383
1384 memcpy(&val, p, sizeof(val));
1385 return val;
1386}
1387
1388static size_t syscall__scnprintf_name(struct syscall *sc, char *bf, size_t size,
1389 struct syscall_arg *arg)
1390{
1391 if (sc->arg_fmt && sc->arg_fmt[arg->idx].name)
1392 return scnprintf(bf, size, "%s: ", sc->arg_fmt[arg->idx].name);
1393
1394 return scnprintf(bf, size, "arg%d: ", arg->idx);
1395}
1396
1397static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size,
1398 struct syscall_arg *arg, unsigned long val)
1399{
1400 if (sc->arg_fmt && sc->arg_fmt[arg->idx].scnprintf) {
1401 arg->val = val;
1402 if (sc->arg_fmt[arg->idx].parm)
1403 arg->parm = sc->arg_fmt[arg->idx].parm;
1404 return sc->arg_fmt[arg->idx].scnprintf(bf, size, arg);
1405 }
1406 return scnprintf(bf, size, "%ld", val);
1407}
1324 1408
1325static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, 1409static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1326 unsigned char *args, struct trace *trace, 1410 unsigned char *args, struct trace *trace,
1327 struct thread *thread) 1411 struct thread *thread)
1328{ 1412{
1329 size_t printed = 0; 1413 size_t printed = 0;
1330 unsigned char *p;
1331 unsigned long val; 1414 unsigned long val;
1415 u8 bit = 1;
1416 struct syscall_arg arg = {
1417 .args = args,
1418 .idx = 0,
1419 .mask = 0,
1420 .trace = trace,
1421 .thread = thread,
1422 };
1423 struct thread_trace *ttrace = thread__priv(thread);
1424
1425 /*
1426 * Things like fcntl will set this in its 'cmd' formatter to pick the
1427 * right formatter for the return value (an fd? file flags?), which is
1428 * not needed for syscalls that always return a given type, say an fd.
1429 */
1430 ttrace->ret_scnprintf = NULL;
1332 1431
1333 if (sc->args != NULL) { 1432 if (sc->args != NULL) {
1334 struct format_field *field; 1433 struct format_field *field;
1335 u8 bit = 1;
1336 struct syscall_arg arg = {
1337 .idx = 0,
1338 .mask = 0,
1339 .trace = trace,
1340 .thread = thread,
1341 };
1342 1434
1343 for (field = sc->args; field; 1435 for (field = sc->args; field;
1344 field = field->next, ++arg.idx, bit <<= 1) { 1436 field = field->next, ++arg.idx, bit <<= 1) {
1345 if (arg.mask & bit) 1437 if (arg.mask & bit)
1346 continue; 1438 continue;
1347 1439
1348 /* special care for unaligned accesses */ 1440 val = syscall_arg__val(&arg, arg.idx);
1349 p = args + sizeof(unsigned long) * arg.idx;
1350 memcpy(&val, p, sizeof(val));
1351 1441
1352 /* 1442 /*
1353 * Suppress this argument if its value is zero and 1443 * Suppress this argument if its value is zero and
@@ -1355,23 +1445,16 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1355 * strarray for it. 1445 * strarray for it.
1356 */ 1446 */
1357 if (val == 0 && 1447 if (val == 0 &&
1358 !(sc->arg_scnprintf && 1448 !(sc->arg_fmt &&
1359 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY && 1449 (sc->arg_fmt[arg.idx].show_zero ||
1360 sc->arg_parm[arg.idx])) 1450 sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAY ||
1451 sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAYS) &&
1452 sc->arg_fmt[arg.idx].parm))
1361 continue; 1453 continue;
1362 1454
1363 printed += scnprintf(bf + printed, size - printed, 1455 printed += scnprintf(bf + printed, size - printed,
1364 "%s%s: ", printed ? ", " : "", field->name); 1456 "%s%s: ", printed ? ", " : "", field->name);
1365 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) { 1457 printed += syscall__scnprintf_val(sc, bf + printed, size - printed, &arg, val);
1366 arg.val = val;
1367 if (sc->arg_parm)
1368 arg.parm = sc->arg_parm[arg.idx];
1369 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1370 size - printed, &arg);
1371 } else {
1372 printed += scnprintf(bf + printed, size - printed,
1373 "%ld", val);
1374 }
1375 } 1458 }
1376 } else if (IS_ERR(sc->tp_format)) { 1459 } else if (IS_ERR(sc->tp_format)) {
1377 /* 1460 /*
@@ -1379,16 +1462,17 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1379 * may end up not having any args, like with gettid(), so only 1462 * may end up not having any args, like with gettid(), so only
1380 * print the raw args when we didn't manage to read it. 1463 * print the raw args when we didn't manage to read it.
1381 */ 1464 */
1382 int i = 0; 1465 while (arg.idx < sc->nr_args) {
1383 1466 if (arg.mask & bit)
1384 while (i < 6) { 1467 goto next_arg;
1385 /* special care for unaligned accesses */ 1468 val = syscall_arg__val(&arg, arg.idx);
1386 p = args + sizeof(unsigned long) * i; 1469 if (printed)
1387 memcpy(&val, p, sizeof(val)); 1470 printed += scnprintf(bf + printed, size - printed, ", ");
1388 printed += scnprintf(bf + printed, size - printed, 1471 printed += syscall__scnprintf_name(sc, bf + printed, size - printed, &arg);
1389 "%sarg%d: %ld", 1472 printed += syscall__scnprintf_val(sc, bf + printed, size - printed, &arg, val);
1390 printed ? ", " : "", i, val); 1473next_arg:
1391 ++i; 1474 ++arg.idx;
1475 bit <<= 1;
1392 } 1476 }
1393 } 1477 }
1394 1478
@@ -1635,17 +1719,31 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1635 } 1719 }
1636 1720
1637 if (sc->fmt == NULL) { 1721 if (sc->fmt == NULL) {
1722 if (ret < 0)
1723 goto errno_print;
1638signed_print: 1724signed_print:
1639 fprintf(trace->output, ") = %ld", ret); 1725 fprintf(trace->output, ") = %ld", ret);
1640 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) { 1726 } else if (ret < 0) {
1727errno_print: {
1641 char bf[STRERR_BUFSIZE]; 1728 char bf[STRERR_BUFSIZE];
1642 const char *emsg = str_error_r(-ret, bf, sizeof(bf)), 1729 const char *emsg = str_error_r(-ret, bf, sizeof(bf)),
1643 *e = audit_errno_to_name(-ret); 1730 *e = audit_errno_to_name(-ret);
1644 1731
1645 fprintf(trace->output, ") = -1 %s %s", e, emsg); 1732 fprintf(trace->output, ") = -1 %s %s", e, emsg);
1733 }
1646 } else if (ret == 0 && sc->fmt->timeout) 1734 } else if (ret == 0 && sc->fmt->timeout)
1647 fprintf(trace->output, ") = 0 Timeout"); 1735 fprintf(trace->output, ") = 0 Timeout");
1648 else if (sc->fmt->hexret) 1736 else if (ttrace->ret_scnprintf) {
1737 char bf[1024];
1738 struct syscall_arg arg = {
1739 .val = ret,
1740 .thread = thread,
1741 .trace = trace,
1742 };
1743 ttrace->ret_scnprintf(bf, sizeof(bf), &arg);
1744 ttrace->ret_scnprintf = NULL;
1745 fprintf(trace->output, ") = %s", bf);
1746 } else if (sc->fmt->hexret)
1649 fprintf(trace->output, ") = %#lx", ret); 1747 fprintf(trace->output, ") = %#lx", ret);
1650 else if (sc->fmt->errpid) { 1748 else if (sc->fmt->errpid) {
1651 struct thread *child = machine__find_thread(trace->host, ret, ret); 1749 struct thread *child = machine__find_thread(trace->host, ret, ret);
@@ -1764,16 +1862,14 @@ out_dump:
1764 goto out_put; 1862 goto out_put;
1765} 1863}
1766 1864
1767static void bpf_output__printer(enum binary_printer_ops op, 1865static int bpf_output__printer(enum binary_printer_ops op,
1768 unsigned int val, void *extra) 1866 unsigned int val, void *extra __maybe_unused, FILE *fp)
1769{ 1867{
1770 FILE *output = extra;
1771 unsigned char ch = (unsigned char)val; 1868 unsigned char ch = (unsigned char)val;
1772 1869
1773 switch (op) { 1870 switch (op) {
1774 case BINARY_PRINT_CHAR_DATA: 1871 case BINARY_PRINT_CHAR_DATA:
1775 fprintf(output, "%c", isprint(ch) ? ch : '.'); 1872 return fprintf(fp, "%c", isprint(ch) ? ch : '.');
1776 break;
1777 case BINARY_PRINT_DATA_BEGIN: 1873 case BINARY_PRINT_DATA_BEGIN:
1778 case BINARY_PRINT_LINE_BEGIN: 1874 case BINARY_PRINT_LINE_BEGIN:
1779 case BINARY_PRINT_ADDR: 1875 case BINARY_PRINT_ADDR:
@@ -1786,13 +1882,15 @@ static void bpf_output__printer(enum binary_printer_ops op,
1786 default: 1882 default:
1787 break; 1883 break;
1788 } 1884 }
1885
1886 return 0;
1789} 1887}
1790 1888
1791static void bpf_output__fprintf(struct trace *trace, 1889static void bpf_output__fprintf(struct trace *trace,
1792 struct perf_sample *sample) 1890 struct perf_sample *sample)
1793{ 1891{
1794 print_binary(sample->raw_data, sample->raw_size, 8, 1892 binary__fprintf(sample->raw_data, sample->raw_size, 8,
1795 bpf_output__printer, trace->output); 1893 bpf_output__printer, NULL, trace->output);
1796} 1894}
1797 1895
1798static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, 1896static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
@@ -2014,6 +2112,7 @@ static int trace__record(struct trace *trace, int argc, const char **argv)
2014 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit"; 2112 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2015 else { 2113 else {
2016 pr_err("Neither raw_syscalls nor syscalls events exist.\n"); 2114 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2115 free(rec_argv);
2017 return -1; 2116 return -1;
2018 } 2117 }
2019 } 2118 }
@@ -2171,6 +2270,30 @@ out_enomem:
2171 goto out; 2270 goto out;
2172} 2271}
2173 2272
2273static int trace__set_filter_loop_pids(struct trace *trace)
2274{
2275 unsigned int nr = 1;
2276 pid_t pids[32] = {
2277 getpid(),
2278 };
2279 struct thread *thread = machine__find_thread(trace->host, pids[0], pids[0]);
2280
2281 while (thread && nr < ARRAY_SIZE(pids)) {
2282 struct thread *parent = machine__find_thread(trace->host, thread->ppid, thread->ppid);
2283
2284 if (parent == NULL)
2285 break;
2286
2287 if (!strcmp(thread__comm_str(parent), "sshd")) {
2288 pids[nr++] = parent->tid;
2289 break;
2290 }
2291 thread = parent;
2292 }
2293
2294 return perf_evlist__set_filter_pids(trace->evlist, nr, pids);
2295}
2296
2174static int trace__run(struct trace *trace, int argc, const char **argv) 2297static int trace__run(struct trace *trace, int argc, const char **argv)
2175{ 2298{
2176 struct perf_evlist *evlist = trace->evlist; 2299 struct perf_evlist *evlist = trace->evlist;
@@ -2294,7 +2417,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2294 if (trace->filter_pids.nr > 0) 2417 if (trace->filter_pids.nr > 0)
2295 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries); 2418 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
2296 else if (thread_map__pid(evlist->threads, 0) == -1) 2419 else if (thread_map__pid(evlist->threads, 0) == -1)
2297 err = perf_evlist__set_filter_pid(evlist, getpid()); 2420 err = trace__set_filter_loop_pids(trace);
2298 2421
2299 if (err < 0) 2422 if (err < 0)
2300 goto out_error_mem; 2423 goto out_error_mem;
@@ -2393,6 +2516,8 @@ out_disable:
2393 } 2516 }
2394 2517
2395out_delete_evlist: 2518out_delete_evlist:
2519 trace__symbols__exit(trace);
2520
2396 perf_evlist__delete(evlist); 2521 perf_evlist__delete(evlist);
2397 trace->evlist = NULL; 2522 trace->evlist = NULL;
2398 trace->live = false; 2523 trace->live = false;
@@ -2440,10 +2565,12 @@ static int trace__replay(struct trace *trace)
2440 const struct perf_evsel_str_handler handlers[] = { 2565 const struct perf_evsel_str_handler handlers[] = {
2441 { "probe:vfs_getname", trace__vfs_getname, }, 2566 { "probe:vfs_getname", trace__vfs_getname, },
2442 }; 2567 };
2443 struct perf_data_file file = { 2568 struct perf_data data = {
2444 .path = input_name, 2569 .file = {
2445 .mode = PERF_DATA_MODE_READ, 2570 .path = input_name,
2446 .force = trace->force, 2571 },
2572 .mode = PERF_DATA_MODE_READ,
2573 .force = trace->force,
2447 }; 2574 };
2448 struct perf_session *session; 2575 struct perf_session *session;
2449 struct perf_evsel *evsel; 2576 struct perf_evsel *evsel;
@@ -2466,7 +2593,7 @@ static int trace__replay(struct trace *trace)
2466 /* add tid to output */ 2593 /* add tid to output */
2467 trace->multiple_threads = true; 2594 trace->multiple_threads = true;
2468 2595
2469 session = perf_session__new(&file, false, &trace->tool); 2596 session = perf_session__new(&data, false, &trace->tool);
2470 if (session == NULL) 2597 if (session == NULL)
2471 return -1; 2598 return -1;
2472 2599
@@ -2642,20 +2769,23 @@ DEFINE_RESORT_RB(threads, (thread__nr_events(a->thread->priv) < thread__nr_event
2642 2769
2643static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp) 2770static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2644{ 2771{
2645 DECLARE_RESORT_RB_MACHINE_THREADS(threads, trace->host);
2646 size_t printed = trace__fprintf_threads_header(fp); 2772 size_t printed = trace__fprintf_threads_header(fp);
2647 struct rb_node *nd; 2773 struct rb_node *nd;
2774 int i;
2648 2775
2649 if (threads == NULL) { 2776 for (i = 0; i < THREADS__TABLE_SIZE; i++) {
2650 fprintf(fp, "%s", "Error sorting output by nr_events!\n"); 2777 DECLARE_RESORT_RB_MACHINE_THREADS(threads, trace->host, i);
2651 return 0;
2652 }
2653 2778
2654 resort_rb__for_each_entry(nd, threads) 2779 if (threads == NULL) {
2655 printed += trace__fprintf_thread(fp, threads_entry->thread, trace); 2780 fprintf(fp, "%s", "Error sorting output by nr_events!\n");
2781 return 0;
2782 }
2656 2783
2657 resort_rb__delete(threads); 2784 resort_rb__for_each_entry(nd, threads)
2785 printed += trace__fprintf_thread(fp, threads_entry->thread, trace);
2658 2786
2787 resort_rb__delete(threads);
2788 }
2659 return printed; 2789 return printed;
2660} 2790}
2661 2791
@@ -2756,7 +2886,7 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
2756 struct trace *trace = (struct trace *)opt->value; 2886 struct trace *trace = (struct trace *)opt->value;
2757 const char *s = str; 2887 const char *s = str;
2758 char *sep = NULL, *lists[2] = { NULL, NULL, }; 2888 char *sep = NULL, *lists[2] = { NULL, NULL, };
2759 int len = strlen(str), err = -1, list; 2889 int len = strlen(str) + 1, err = -1, list, idx;
2760 char *strace_groups_dir = system_path(STRACE_GROUPS_DIR); 2890 char *strace_groups_dir = system_path(STRACE_GROUPS_DIR);
2761 char group_name[PATH_MAX]; 2891 char group_name[PATH_MAX];
2762 2892
@@ -2773,7 +2903,8 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
2773 *sep = '\0'; 2903 *sep = '\0';
2774 2904
2775 list = 0; 2905 list = 0;
2776 if (syscalltbl__id(trace->sctbl, s) >= 0) { 2906 if (syscalltbl__id(trace->sctbl, s) >= 0 ||
2907 syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) {
2777 list = 1; 2908 list = 1;
2778 } else { 2909 } else {
2779 path__join(group_name, sizeof(group_name), strace_groups_dir, s); 2910 path__join(group_name, sizeof(group_name), strace_groups_dir, s);
diff --git a/tools/perf/builtin-version.c b/tools/perf/builtin-version.c
index d25149456a2f..37019c5d675f 100644
--- a/tools/perf/builtin-version.c
+++ b/tools/perf/builtin-version.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "builtin.h" 2#include "builtin.h"
2#include "perf.h" 3#include "perf.h"
3#include <linux/compiler.h> 4#include <linux/compiler.h>
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index d4d19fe3d050..05745f3ce912 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef BUILTIN_H 2#ifndef BUILTIN_H
2#define BUILTIN_H 3#define BUILTIN_H
3 4
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 83fe2202382e..77406d25e521 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -1,9 +1,18 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2 3
3HEADERS=' 4HEADERS='
5include/uapi/drm/drm.h
6include/uapi/drm/i915_drm.h
4include/uapi/linux/fcntl.h 7include/uapi/linux/fcntl.h
8include/uapi/linux/kcmp.h
9include/uapi/linux/kvm.h
5include/uapi/linux/perf_event.h 10include/uapi/linux/perf_event.h
11include/uapi/linux/prctl.h
12include/uapi/linux/sched.h
6include/uapi/linux/stat.h 13include/uapi/linux/stat.h
14include/uapi/linux/vhost.h
15include/uapi/sound/asound.h
7include/linux/hash.h 16include/linux/hash.h
8include/uapi/linux/hw_breakpoint.h 17include/uapi/linux/hw_breakpoint.h
9arch/x86/include/asm/disabled-features.h 18arch/x86/include/asm/disabled-features.h
@@ -16,6 +25,7 @@ arch/x86/include/uapi/asm/perf_regs.h
16arch/x86/include/uapi/asm/kvm.h 25arch/x86/include/uapi/asm/kvm.h
17arch/x86/include/uapi/asm/kvm_perf.h 26arch/x86/include/uapi/asm/kvm_perf.h
18arch/x86/include/uapi/asm/svm.h 27arch/x86/include/uapi/asm/svm.h
28arch/x86/include/uapi/asm/unistd.h
19arch/x86/include/uapi/asm/vmx.h 29arch/x86/include/uapi/asm/vmx.h
20arch/powerpc/include/uapi/asm/kvm.h 30arch/powerpc/include/uapi/asm/kvm.h
21arch/s390/include/uapi/asm/kvm.h 31arch/s390/include/uapi/asm/kvm.h
@@ -29,12 +39,13 @@ include/asm-generic/bitops/__fls.h
29include/asm-generic/bitops/fls.h 39include/asm-generic/bitops/fls.h
30include/asm-generic/bitops/fls64.h 40include/asm-generic/bitops/fls64.h
31include/linux/coresight-pmu.h 41include/linux/coresight-pmu.h
42include/uapi/asm-generic/ioctls.h
32include/uapi/asm-generic/mman-common.h 43include/uapi/asm-generic/mman-common.h
33' 44'
34 45
35check () { 46check () {
36 file=$1 47 file=$1
37 opts= 48 opts="--ignore-blank-lines --ignore-space-change"
38 49
39 shift 50 shift
40 while [ -n "$*" ]; do 51 while [ -n "$*" ]; do
@@ -45,17 +56,22 @@ check () {
45 cmd="diff $opts ../$file ../../$file > /dev/null" 56 cmd="diff $opts ../$file ../../$file > /dev/null"
46 57
47 test -f ../../$file && 58 test -f ../../$file &&
48 eval $cmd || echo "Warning: $file differs from kernel" >&2 59 eval $cmd || echo "Warning: Kernel ABI header at 'tools/$file' differs from latest version at '$file'" >&2
49} 60}
50 61
51 62
63# Check if we have the kernel headers (tools/perf/../../include), else
64# we're probably on a detached tarball, so no point in trying to check
65# differences.
66test -d ../../include || exit 0
67
52# simple diff check 68# simple diff check
53for i in $HEADERS; do 69for i in $HEADERS; do
54 check $i -B 70 check $i -B
55done 71done
56 72
57# diff with extra ignore lines 73# diff with extra ignore lines
58check arch/x86/lib/memcpy_64.S -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" 74check arch/x86/lib/memcpy_64.S -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"
59check arch/x86/lib/memset_64.S -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" 75check arch/x86/lib/memset_64.S -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"
60check include/uapi/asm-generic/mman.h -B -I "^#include <\(uapi/\)*asm-generic/mman-common.h>" 76check include/uapi/asm-generic/mman.h -I "^#include <\(uapi/\)*asm-generic/mman-common.h>"
61check include/uapi/linux/mman.h -B -I "^#include <\(uapi/\)*asm/mman.h>" 77check include/uapi/linux/mman.h -I "^#include <\(uapi/\)*asm/mman.h>"
diff --git a/tools/perf/jvmti/jvmti_agent.h b/tools/perf/jvmti/jvmti_agent.h
index c53a41f48b63..fe32d8344a82 100644
--- a/tools/perf/jvmti/jvmti_agent.h
+++ b/tools/perf/jvmti/jvmti_agent.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __JVMTI_AGENT_H__ 2#ifndef __JVMTI_AGENT_H__
2#define __JVMTI_AGENT_H__ 3#define __JVMTI_AGENT_H__
3 4
diff --git a/tools/perf/jvmti/libjvmti.c b/tools/perf/jvmti/libjvmti.c
index 6d710904c837..c62c9fc9a525 100644
--- a/tools/perf/jvmti/libjvmti.c
+++ b/tools/perf/jvmti/libjvmti.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include <sys/types.h> 3#include <sys/types.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/perf/perf-archive.sh b/tools/perf/perf-archive.sh
index e91930620269..0cfb3e2cefef 100644
--- a/tools/perf/perf-archive.sh
+++ b/tools/perf/perf-archive.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2# perf archive 3# perf archive
3# Arnaldo Carvalho de Melo <acme@redhat.com> 4# Arnaldo Carvalho de Melo <acme@redhat.com>
4 5
diff --git a/tools/perf/perf-completion.sh b/tools/perf/perf-completion.sh
index 3ba80b2359cc..345f5d6e9ed5 100644
--- a/tools/perf/perf-completion.sh
+++ b/tools/perf/perf-completion.sh
@@ -1,4 +1,5 @@
1# perf bash and zsh completion 1# perf bash and zsh completion
2# SPDX-License-Identifier: GPL-2.0
2 3
3# Taken from git.git's completion script. 4# Taken from git.git's completion script.
4__my_reassemble_comp_words_by_ref() 5__my_reassemble_comp_words_by_ref()
diff --git a/tools/perf/perf-read-vdso.c b/tools/perf/perf-read-vdso.c
index 764e2547c25a..8c0ca0cc428f 100644
--- a/tools/perf/perf-read-vdso.c
+++ b/tools/perf/perf-read-vdso.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <string.h> 3#include <string.h>
3 4
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h
index e4b717e9eb6c..36673f98d66b 100644
--- a/tools/perf/perf-sys.h
+++ b/tools/perf/perf-sys.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_SYS_H 2#ifndef _PERF_SYS_H
2#define _PERF_SYS_H 3#define _PERF_SYS_H
3 4
@@ -9,16 +10,6 @@
9#include <linux/perf_event.h> 10#include <linux/perf_event.h>
10#include <asm/barrier.h> 11#include <asm/barrier.h>
11 12
12#if defined(__i386__)
13#define cpu_relax() asm volatile("rep; nop" ::: "memory");
14#define CPUINFO_PROC {"model name"}
15#endif
16
17#if defined(__x86_64__)
18#define cpu_relax() asm volatile("rep; nop" ::: "memory");
19#define CPUINFO_PROC {"model name"}
20#endif
21
22#ifdef __powerpc__ 13#ifdef __powerpc__
23#define CPUINFO_PROC {"cpu"} 14#define CPUINFO_PROC {"cpu"}
24#endif 15#endif
@@ -43,19 +34,10 @@
43#define CPUINFO_PROC {"cpu model"} 34#define CPUINFO_PROC {"cpu model"}
44#endif 35#endif
45 36
46#ifdef __ia64__
47#define cpu_relax() asm volatile ("hint @pause" ::: "memory")
48#define CPUINFO_PROC {"model name"}
49#endif
50
51#ifdef __arm__ 37#ifdef __arm__
52#define CPUINFO_PROC {"model name", "Processor"} 38#define CPUINFO_PROC {"model name", "Processor"}
53#endif 39#endif
54 40
55#ifdef __aarch64__
56#define cpu_relax() asm volatile("yield" ::: "memory")
57#endif
58
59#ifdef __mips__ 41#ifdef __mips__
60#define CPUINFO_PROC {"cpu model"} 42#define CPUINFO_PROC {"cpu model"}
61#endif 43#endif
@@ -72,13 +54,8 @@
72#define CPUINFO_PROC {"core ID"} 54#define CPUINFO_PROC {"core ID"}
73#endif 55#endif
74 56
75#ifdef __tile__ 57#ifndef CPUINFO_PROC
76#define cpu_relax() asm volatile ("mfspr zero, PASS" ::: "memory") 58#define CPUINFO_PROC { "model name", }
77#define CPUINFO_PROC {"model name"}
78#endif
79
80#ifndef cpu_relax
81#define cpu_relax() barrier()
82#endif 59#endif
83 60
84static inline int 61static inline int
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 628a5e412cb1..62b13518bc6e 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * perf.c 3 * perf.c
3 * 4 *
@@ -89,7 +90,7 @@ struct pager_config {
89static int pager_command_config(const char *var, const char *value, void *data) 90static int pager_command_config(const char *var, const char *value, void *data)
90{ 91{
91 struct pager_config *c = data; 92 struct pager_config *c = data;
92 if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd)) 93 if (strstarts(var, "pager.") && !strcmp(var + 6, c->cmd))
93 c->val = perf_config_bool(var, value); 94 c->val = perf_config_bool(var, value);
94 return 0; 95 return 0;
95} 96}
@@ -108,9 +109,9 @@ static int check_pager_config(const char *cmd)
108static int browser_command_config(const char *var, const char *value, void *data) 109static int browser_command_config(const char *var, const char *value, void *data)
109{ 110{
110 struct pager_config *c = data; 111 struct pager_config *c = data;
111 if (!prefixcmp(var, "tui.") && !strcmp(var + 4, c->cmd)) 112 if (strstarts(var, "tui.") && !strcmp(var + 4, c->cmd))
112 c->val = perf_config_bool(var, value); 113 c->val = perf_config_bool(var, value);
113 if (!prefixcmp(var, "gtk.") && !strcmp(var + 4, c->cmd)) 114 if (strstarts(var, "gtk.") && !strcmp(var + 4, c->cmd))
114 c->val = perf_config_bool(var, value) ? 2 : 0; 115 c->val = perf_config_bool(var, value) ? 2 : 0;
115 return 0; 116 return 0;
116} 117}
@@ -192,7 +193,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
192 /* 193 /*
193 * Check remaining flags. 194 * Check remaining flags.
194 */ 195 */
195 if (!prefixcmp(cmd, CMD_EXEC_PATH)) { 196 if (strstarts(cmd, CMD_EXEC_PATH)) {
196 cmd += strlen(CMD_EXEC_PATH); 197 cmd += strlen(CMD_EXEC_PATH);
197 if (*cmd == '=') 198 if (*cmd == '=')
198 set_argv_exec_path(cmd + 1); 199 set_argv_exec_path(cmd + 1);
@@ -229,7 +230,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
229 *envchanged = 1; 230 *envchanged = 1;
230 (*argv)++; 231 (*argv)++;
231 (*argc)--; 232 (*argc)--;
232 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { 233 } else if (strstarts(cmd, CMD_DEBUGFS_DIR)) {
233 tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR)); 234 tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR));
234 fprintf(stderr, "dir: %s\n", tracing_path); 235 fprintf(stderr, "dir: %s\n", tracing_path);
235 if (envchanged) 236 if (envchanged)
@@ -467,17 +468,23 @@ int main(int argc, const char **argv)
467 * - cannot execute it externally (since it would just do 468 * - cannot execute it externally (since it would just do
468 * the same thing over again) 469 * the same thing over again)
469 * 470 *
470 * So we just directly call the internal command handler, and 471 * So we just directly call the internal command handler. If that one
471 * die if that one cannot handle it. 472 * fails to handle this, then maybe we just run a renamed perf binary
473 * that contains a dash in its name. To handle this scenario, we just
474 * fall through and ignore the "xxxx" part of the command string.
472 */ 475 */
473 if (!prefixcmp(cmd, "perf-")) { 476 if (strstarts(cmd, "perf-")) {
474 cmd += 5; 477 cmd += 5;
475 argv[0] = cmd; 478 argv[0] = cmd;
476 handle_internal_command(argc, argv); 479 handle_internal_command(argc, argv);
477 fprintf(stderr, "cannot handle %s internally", cmd); 480 /*
478 goto out; 481 * If the command is handled, the above function does not
482 * return undo changes and fall through in such a case.
483 */
484 cmd -= 5;
485 argv[0] = cmd;
479 } 486 }
480 if (!prefixcmp(cmd, "trace")) { 487 if (strstarts(cmd, "trace")) {
481#ifdef HAVE_LIBAUDIT_SUPPORT 488#ifdef HAVE_LIBAUDIT_SUPPORT
482 setup_path(); 489 setup_path();
483 argv[0] = "trace"; 490 argv[0] = "trace";
@@ -495,7 +502,7 @@ int main(int argc, const char **argv)
495 commit_pager_choice(); 502 commit_pager_choice();
496 503
497 if (argc > 0) { 504 if (argc > 0) {
498 if (!prefixcmp(argv[0], "--")) 505 if (strstarts(argv[0], "--"))
499 argv[0] += 2; 506 argv[0] += 2;
500 } else { 507 } else {
501 /* The user didn't specify a command; give them help */ 508 /* The user didn't specify a command; give them help */
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 806c216a1078..2357f4ccc9c7 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_PERF_H 2#ifndef _PERF_PERF_H
2#define _PERF_PERF_H 3#define _PERF_PERF_H
3 4
@@ -7,6 +8,7 @@
7#include <linux/perf_event.h> 8#include <linux/perf_event.h>
8 9
9extern bool test_attr__enabled; 10extern bool test_attr__enabled;
11void test_attr__ready(void);
10void test_attr__init(void); 12void test_attr__init(void);
11void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu, 13void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
12 int fd, int group_fd, unsigned long flags); 14 int fd, int group_fd, unsigned long flags);
@@ -42,6 +44,7 @@ struct record_opts {
42 bool no_samples; 44 bool no_samples;
43 bool raw_samples; 45 bool raw_samples;
44 bool sample_address; 46 bool sample_address;
47 bool sample_phys_addr;
45 bool sample_weight; 48 bool sample_weight;
46 bool sample_time; 49 bool sample_time;
47 bool sample_time_set; 50 bool sample_time_set;
@@ -63,6 +66,7 @@ struct record_opts {
63 unsigned int user_freq; 66 unsigned int user_freq;
64 u64 branch_stack; 67 u64 branch_stack;
65 u64 sample_intr_regs; 68 u64 sample_intr_regs;
69 u64 sample_user_regs;
66 u64 default_interval; 70 u64 default_interval;
67 u64 user_interval; 71 u64 user_interval;
68 size_t auxtrace_snapshot_size; 72 size_t auxtrace_snapshot_size;
diff --git a/tools/perf/pmu-events/README b/tools/perf/pmu-events/README
index 1408ade0d773..c2ee3e4417fe 100644
--- a/tools/perf/pmu-events/README
+++ b/tools/perf/pmu-events/README
@@ -85,10 +85,6 @@ users to specify events by their name:
85 85
86where 'pm_1plus_ppc_cmpl' is a Power8 PMU event. 86where 'pm_1plus_ppc_cmpl' is a Power8 PMU event.
87 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. 88However some errors in processing may cause the perf build to fail.
93 89
94Mapfile format 90Mapfile format
diff --git a/tools/perf/pmu-events/arch/powerpc/mapfile.csv b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
index e925baa0c30b..a0f3a11ca19f 100644
--- a/tools/perf/pmu-events/arch/powerpc/mapfile.csv
+++ b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
@@ -13,9 +13,13 @@
13# 13#
14 14
15# Power8 entries 15# Power8 entries
16004b0000,1,power8.json,core 16004b0000,1,power8,core
17004b0201,1,power8.json,core 17004b0201,1,power8,core
18004c0000,1,power8.json,core 18004c0000,1,power8,core
19004d0000,1,power8.json,core 19004d0000,1,power8,core
20004d0100,1,power8.json,core 20004d0100,1,power8,core
21004d0200,1,power8.json,core 21004d0200,1,power8,core
22004c0100,1,power8,core
23004e0100,1,power9,core
24004e0200,1,power9,core
25004e1200,1,power9,core
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/cache.json b/tools/perf/pmu-events/arch/powerpc/power9/cache.json
new file mode 100644
index 000000000000..18f6645f2897
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power9/cache.json
@@ -0,0 +1,137 @@
1[
2 {,
3 "EventCode": "0x300F4",
4 "EventName": "PM_THRD_CONC_RUN_INST",
5 "BriefDescription": "PPC Instructions Finished by this thread when all threads in the core had the run-latch set"
6 },
7 {,
8 "EventCode": "0x1E056",
9 "EventName": "PM_CMPLU_STALL_FLUSH_ANY_THREAD",
10 "BriefDescription": "Cycles in which the NTC instruction is not allowed to complete because any of the 4 threads in the same core suffered a flush, which blocks completion"
11 },
12 {,
13 "EventCode": "0x4D016",
14 "EventName": "PM_CMPLU_STALL_FXLONG",
15 "BriefDescription": "Completion stall due to a long latency scalar fixed point instruction (division, square root)"
16 },
17 {,
18 "EventCode": "0x2D016",
19 "EventName": "PM_CMPLU_STALL_FXU",
20 "BriefDescription": "Finish stall due to a scalar fixed point or CR instruction in the execution pipeline. These instructions get routed to the ALU, ALU2, and DIV pipes"
21 },
22 {,
23 "EventCode": "0x1D15C",
24 "EventName": "PM_MRK_DTLB_MISS_1G",
25 "BriefDescription": "Marked Data TLB reload (after a miss) page size 2M. Implies radix translation was used"
26 },
27 {,
28 "EventCode": "0x4D12A",
29 "EventName": "PM_MRK_DATA_FROM_RL4_CYC",
30 "BriefDescription": "Duration in cycles to reload from another chip's L4 on the same Node or Group ( Remote) due to a marked load"
31 },
32 {,
33 "EventCode": "0x1003C",
34 "EventName": "PM_CMPLU_STALL_DMISS_L2L3",
35 "BriefDescription": "Completion stall by Dcache miss which resolved in L2/L3"
36 },
37 {,
38 "EventCode": "0x4C014",
39 "EventName": "PM_CMPLU_STALL_LMQ_FULL",
40 "BriefDescription": "Finish stall because the NTF instruction was a load that missed in the L1 and the LMQ was unable to accept this load miss request because it was full"
41 },
42 {,
43 "EventCode": "0x14048",
44 "EventName": "PM_INST_FROM_ON_CHIP_CACHE",
45 "BriefDescription": "The processor's Instruction cache was reloaded either shared or modified data from another core's L2/L3 on the same chip due to an instruction fetch (not prefetch)"
46 },
47 {,
48 "EventCode": "0x4D014",
49 "EventName": "PM_CMPLU_STALL_LOAD_FINISH",
50 "BriefDescription": "Finish stall because the NTF instruction was a load instruction with all its dependencies satisfied just going through the LSU pipe to finish"
51 },
52 {,
53 "EventCode": "0x2404A",
54 "EventName": "PM_INST_FROM_RL4",
55 "BriefDescription": "The processor's Instruction cache was reloaded from another chip's L4 on the same Node or Group ( Remote) due to an instruction fetch (not prefetch)"
56 },
57 {,
58 "EventCode": "0x1404A",
59 "EventName": "PM_INST_FROM_RL2L3_SHR",
60 "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to an instruction fetch (not prefetch)"
61 },
62 {,
63 "EventCode": "0x401EA",
64 "EventName": "PM_THRESH_EXC_128",
65 "BriefDescription": "Threshold counter exceeded a value of 128"
66 },
67 {,
68 "EventCode": "0x400F6",
69 "EventName": "PM_BR_MPRED_CMPL",
70 "BriefDescription": "Number of Branch Mispredicts"
71 },
72 {,
73 "EventCode": "0x2F140",
74 "EventName": "PM_MRK_DPTEG_FROM_L2_MEPF",
75 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 hit without dispatch conflicts on Mepf state. due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
76 },
77 {,
78 "EventCode": "0x101E6",
79 "EventName": "PM_THRESH_EXC_4096",
80 "BriefDescription": "Threshold counter exceed a count of 4096"
81 },
82 {,
83 "EventCode": "0x3D156",
84 "EventName": "PM_MRK_DTLB_MISS_64K",
85 "BriefDescription": "Marked Data TLB Miss page size 64K"
86 },
87 {,
88 "EventCode": "0x4C15E",
89 "EventName": "PM_MRK_DTLB_MISS_16M",
90 "BriefDescription": "Marked Data TLB Miss page size 16M"
91 },
92 {,
93 "EventCode": "0x2D15E",
94 "EventName": "PM_MRK_DTLB_MISS_16G",
95 "BriefDescription": "Marked Data TLB Miss page size 16G"
96 },
97 {,
98 "EventCode": "0x3F14A",
99 "EventName": "PM_MRK_DPTEG_FROM_RMEM",
100 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group ( Remote) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
101 },
102 {,
103 "EventCode": "0x4C016",
104 "EventName": "PM_CMPLU_STALL_DMISS_L2L3_CONFLICT",
105 "BriefDescription": "Completion stall due to cache miss that resolves in the L2 or L3 with a conflict"
106 },
107 {,
108 "EventCode": "0x2C01A",
109 "EventName": "PM_CMPLU_STALL_LHS",
110 "BriefDescription": "Finish stall because the NTF instruction was a load that hit on an older store and it was waiting for store data"
111 },
112 {,
113 "EventCode": "0x401E4",
114 "EventName": "PM_MRK_DTLB_MISS",
115 "BriefDescription": "Marked dtlb miss"
116 },
117 {,
118 "EventCode": "0x24046",
119 "EventName": "PM_INST_FROM_RL2L3_MOD",
120 "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to an instruction fetch (not prefetch)"
121 },
122 {,
123 "EventCode": "0x1002A",
124 "EventName": "PM_CMPLU_STALL_LARX",
125 "BriefDescription": "Finish stall because the NTF instruction was a larx waiting to be satisfied"
126 },
127 {,
128 "EventCode": "0x3006C",
129 "EventName": "PM_RUN_CYC_SMT2_MODE",
130 "BriefDescription": "Cycles in which this thread's run latch is set and the core is in SMT2 mode"
131 },
132 {,
133 "EventCode": "0x1C058",
134 "EventName": "PM_DTLB_MISS_16G",
135 "BriefDescription": "Data TLB Miss page size 16G"
136 }
137] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/floating-point.json b/tools/perf/pmu-events/arch/powerpc/power9/floating-point.json
new file mode 100644
index 000000000000..8a83bca26552
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power9/floating-point.json
@@ -0,0 +1,32 @@
1[
2 {,
3 "EventCode": "0x1415A",
4 "EventName": "PM_MRK_DATA_FROM_L2_DISP_CONFLICT_LDHITST_CYC",
5 "BriefDescription": "Duration in cycles to reload from local core's L2 with load hit store conflict due to a marked load"
6 },
7 {,
8 "EventCode": "0x10058",
9 "EventName": "PM_MEM_LOC_THRESH_IFU",
10 "BriefDescription": "Local Memory above threshold for IFU speculation control"
11 },
12 {,
13 "EventCode": "0x2D028",
14 "EventName": "PM_RADIX_PWC_L2_PDE_FROM_L2",
15 "BriefDescription": "A Page Directory Entry was reloaded to a level 2 page walk cache from the core's L2 data cache"
16 },
17 {,
18 "EventCode": "0x30012",
19 "EventName": "PM_FLUSH_COMPLETION",
20 "BriefDescription": "The instruction that was next to complete did not complete because it suffered a flush"
21 },
22 {,
23 "EventCode": "0x2D154",
24 "EventName": "PM_MRK_DERAT_MISS_64K",
25 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 64K"
26 },
27 {,
28 "EventCode": "0x4016E",
29 "EventName": "PM_THRESH_NOT_MET",
30 "BriefDescription": "Threshold counter did not meet threshold"
31 }
32] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/frontend.json b/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
new file mode 100644
index 000000000000..c63a919eda98
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
@@ -0,0 +1,372 @@
1[
2 {,
3 "EventCode": "0x3E15C",
4 "EventName": "PM_MRK_L2_TM_ST_ABORT_SISTER",
5 "BriefDescription": "TM marked store abort for this thread"
6 },
7 {,
8 "EventCode": "0x25044",
9 "EventName": "PM_IPTEG_FROM_L31_MOD",
10 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L3 on the same chip due to a instruction side request"
11 },
12 {,
13 "EventCode": "0x101E8",
14 "EventName": "PM_THRESH_EXC_256",
15 "BriefDescription": "Threshold counter exceed a count of 256"
16 },
17 {,
18 "EventCode": "0x4504E",
19 "EventName": "PM_IPTEG_FROM_L3MISS",
20 "BriefDescription": "A Page Table Entry was loaded into the TLB from a location other than the local core's L3 due to a instruction side request"
21 },
22 {,
23 "EventCode": "0x1006A",
24 "EventName": "PM_NTC_ISSUE_HELD_DARQ_FULL",
25 "BriefDescription": "The NTC instruction is being held at dispatch because there are no slots in the DARQ for it"
26 },
27 {,
28 "EventCode": "0x4E016",
29 "EventName": "PM_CMPLU_STALL_LSAQ_ARB",
30 "BriefDescription": "Finish stall because the NTF instruction was a load or store that was held in LSAQ because an older instruction from SRQ or LRQ won arbitration to the LSU pipe when this instruction tried to launch"
31 },
32 {,
33 "EventCode": "0x1001A",
34 "EventName": "PM_LSU_SRQ_FULL_CYC",
35 "BriefDescription": "Cycles in which the Store Queue is full on all 4 slices. This is event is not per thread. All the threads will see the same count for this core resource"
36 },
37 {,
38 "EventCode": "0x1E15E",
39 "EventName": "PM_MRK_L2_TM_REQ_ABORT",
40 "BriefDescription": "TM abort"
41 },
42 {,
43 "EventCode": "0x34052",
44 "EventName": "PM_INST_SYS_PUMP_MPRED",
45 "BriefDescription": "Final Pump Scope (system) mispredicted. Either the original scope was too small (Chip/Group) or the original scope was System and it should have been smaller. Counts for an instruction fetch"
46 },
47 {,
48 "EventCode": "0x20114",
49 "EventName": "PM_MRK_L2_RC_DISP",
50 "BriefDescription": "Marked Instruction RC dispatched in L2"
51 },
52 {,
53 "EventCode": "0x4C044",
54 "EventName": "PM_DATA_FROM_L31_ECO_MOD",
55 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to a demand load"
56 },
57 {,
58 "EventCode": "0x1C044",
59 "EventName": "PM_DATA_FROM_L3_NO_CONFLICT",
60 "BriefDescription": "The processor's data cache was reloaded from local core's L3 without conflict due to a demand load"
61 },
62 {,
63 "EventCode": "0x44050",
64 "EventName": "PM_INST_SYS_PUMP_MPRED_RTY",
65 "BriefDescription": "Final Pump Scope (system) ended up larger than Initial Pump Scope (Chip/Group) for an instruction fetch"
66 },
67 {,
68 "EventCode": "0x30154",
69 "EventName": "PM_MRK_FAB_RSP_DCLAIM",
70 "BriefDescription": "Marked store had to do a dclaim"
71 },
72 {,
73 "EventCode": "0x30014",
74 "EventName": "PM_CMPLU_STALL_STORE_FIN_ARB",
75 "BriefDescription": "Finish stall because the NTF instruction was a store waiting for a slot in the store finish pipe. This means the instruction is ready to finish but there are instructions ahead of it, using the finish pipe"
76 },
77 {,
78 "EventCode": "0x3E054",
79 "EventName": "PM_LD_MISS_L1",
80 "BriefDescription": "Load Missed L1, counted at execution time (can be greater than loads finished). LMQ merges are not included in this count. i.e. if a load instruction misses on an address that is already allocated on the LMQ, this event will not increment for that load). Note that this count is per slice, so if a load spans multiple slices this event will increment multiple times for a single load."
81 },
82 {,
83 "EventCode": "0x2E01A",
84 "EventName": "PM_CMPLU_STALL_LSU_FLUSH_NEXT",
85 "BriefDescription": "Completion stall of one cycle because the LSU requested to flush the next iop in the sequence. It takes 1 cycle for the ISU to process this request before the LSU instruction is allowed to complete"
86 },
87 {,
88 "EventCode": "0x2D01C",
89 "EventName": "PM_CMPLU_STALL_STCX",
90 "BriefDescription": "Finish stall because the NTF instruction was a stcx waiting for response from L2"
91 },
92 {,
93 "EventCode": "0x2C010",
94 "EventName": "PM_CMPLU_STALL_LSU",
95 "BriefDescription": "Completion stall by LSU instruction"
96 },
97 {,
98 "EventCode": "0x2C042",
99 "EventName": "PM_DATA_FROM_L3_MEPF",
100 "BriefDescription": "The processor's data cache was reloaded from local core's L3 without dispatch conflicts hit on Mepf state due to a demand load"
101 },
102 {,
103 "EventCode": "0x4E012",
104 "EventName": "PM_CMPLU_STALL_MTFPSCR",
105 "BriefDescription": "Completion stall because the ISU is updating the register and notifying the Effective Address Table (EAT)"
106 },
107 {,
108 "EventCode": "0x100F2",
109 "EventName": "PM_1PLUS_PPC_CMPL",
110 "BriefDescription": "1 or more ppc insts finished"
111 },
112 {,
113 "EventCode": "0x3001C",
114 "EventName": "PM_LSU_REJECT_LMQ_FULL",
115 "BriefDescription": "LSU Reject due to LMQ full (up to 4 per cycles)"
116 },
117 {,
118 "EventCode": "0x15046",
119 "EventName": "PM_IPTEG_FROM_L31_SHR",
120 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's L3 on the same chip due to a instruction side request"
121 },
122 {,
123 "EventCode": "0x1015E",
124 "EventName": "PM_MRK_FAB_RSP_RD_T_INTV",
125 "BriefDescription": "Sampled Read got a T intervention"
126 },
127 {,
128 "EventCode": "0x101EC",
129 "EventName": "PM_THRESH_MET",
130 "BriefDescription": "threshold exceeded"
131 },
132 {,
133 "EventCode": "0x10020",
134 "EventName": "PM_PMC4_REWIND",
135 "BriefDescription": "PMC4 Rewind Event"
136 },
137 {,
138 "EventCode": "0x301EA",
139 "EventName": "PM_THRESH_EXC_1024",
140 "BriefDescription": "Threshold counter exceeded a value of 1024"
141 },
142 {,
143 "EventCode": "0x34056",
144 "EventName": "PM_CMPLU_STALL_LSU_MFSPR",
145 "BriefDescription": "Finish stall because the NTF instruction was a mfspr instruction targeting an LSU SPR and it was waiting for the register data to be returned"
146 },
147 {,
148 "EventCode": "0x44056",
149 "EventName": "PM_VECTOR_ST_CMPL",
150 "BriefDescription": "Number of vector store instructions completed"
151 },
152 {,
153 "EventCode": "0x2C124",
154 "EventName": "PM_MRK_DATA_FROM_L2_DISP_CONFLICT_OTHER",
155 "BriefDescription": "The processor's data cache was reloaded from local core's L2 with dispatch conflict due to a marked load"
156 },
157 {,
158 "EventCode": "0x4C12A",
159 "EventName": "PM_MRK_DATA_FROM_RL2L3_SHR_CYC",
160 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load"
161 },
162 {,
163 "EventCode": "0x3C056",
164 "EventName": "PM_DTLB_MISS_64K",
165 "BriefDescription": "Data TLB Miss page size 64K"
166 },
167 {,
168 "EventCode": "0x30060",
169 "EventName": "PM_TM_TRANS_RUN_INST",
170 "BriefDescription": "Run instructions completed in transactional state (gated by the run latch)"
171 },
172 {,
173 "EventCode": "0x2C014",
174 "EventName": "PM_CMPLU_STALL_STORE_FINISH",
175 "BriefDescription": "Finish stall because the NTF instruction was a store with all its dependencies met, just waiting to go through the LSU pipe to finish"
176 },
177 {,
178 "EventCode": "0x3515A",
179 "EventName": "PM_MRK_DATA_FROM_ON_CHIP_CACHE_CYC",
180 "BriefDescription": "Duration in cycles to reload either shared or modified data from another core's L2/L3 on the same chip due to a marked load"
181 },
182 {,
183 "EventCode": "0x34050",
184 "EventName": "PM_INST_SYS_PUMP_CPRED",
185 "BriefDescription": "Initial and Final Pump Scope was system pump (prediction=correct) for an instruction fetch"
186 },
187 {,
188 "EventCode": "0x3015E",
189 "EventName": "PM_MRK_FAB_RSP_CLAIM_RTY",
190 "BriefDescription": "Sampled store did a rwitm and got a rty"
191 },
192 {,
193 "EventCode": "0x0",
194 "EventName": "PM_SUSPENDED",
195 "BriefDescription": "Counter OFF"
196 },
197 {,
198 "EventCode": "0x10010",
199 "EventName": "PM_PMC4_OVERFLOW",
200 "BriefDescription": "Overflow from counter 4"
201 },
202 {,
203 "EventCode": "0x3E04A",
204 "EventName": "PM_DPTEG_FROM_RMEM",
205 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group ( Remote) due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
206 },
207 {,
208 "EventCode": "0x2F152",
209 "EventName": "PM_MRK_FAB_RSP_DCLAIM_CYC",
210 "BriefDescription": "cycles L2 RC took for a dclaim"
211 },
212 {,
213 "EventCode": "0x10004",
214 "EventName": "PM_CMPLU_STALL_LRQ_OTHER",
215 "BriefDescription": "Finish stall due to LRQ miscellaneous reasons, lost arbitration to LMQ slot, bank collisions, set prediction cleanup, set prediction multihit and others"
216 },
217 {,
218 "EventCode": "0x4F150",
219 "EventName": "PM_MRK_FAB_RSP_RWITM_CYC",
220 "BriefDescription": "cycles L2 RC took for a rwitm"
221 },
222 {,
223 "EventCode": "0x4E042",
224 "EventName": "PM_DPTEG_FROM_L3",
225 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
226 },
227 {,
228 "EventCode": "0x1F054",
229 "EventName": "PM_TLB_HIT",
230 "BriefDescription": "Number of times the TLB had the data required by the instruction. Applies to both HPT and RPT"
231 },
232 {,
233 "EventCode": "0x2C01E",
234 "EventName": "PM_CMPLU_STALL_SYNC_PMU_INT",
235 "BriefDescription": "Cycles in which the NTC instruction is waiting for a synchronous PMU interrupt"
236 },
237 {,
238 "EventCode": "0x24050",
239 "EventName": "PM_IOPS_CMPL",
240 "BriefDescription": "Internal Operations completed"
241 },
242 {,
243 "EventCode": "0x1515C",
244 "EventName": "PM_SYNC_MRK_BR_MPRED",
245 "BriefDescription": "Marked Branch mispredict that can cause a synchronous interrupt"
246 },
247 {,
248 "EventCode": "0x300FA",
249 "EventName": "PM_INST_FROM_L3MISS",
250 "BriefDescription": "Marked instruction was reloaded from a location beyond the local chiplet"
251 },
252 {,
253 "EventCode": "0x15044",
254 "EventName": "PM_IPTEG_FROM_L3_NO_CONFLICT",
255 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without conflict due to a instruction side request"
256 },
257 {,
258 "EventCode": "0x15152",
259 "EventName": "PM_SYNC_MRK_BR_LINK",
260 "BriefDescription": "Marked Branch and link branch that can cause a synchronous interrupt"
261 },
262 {,
263 "EventCode": "0x1E050",
264 "EventName": "PM_CMPLU_STALL_TEND",
265 "BriefDescription": "Finish stall because the NTF instruction was a tend instruction awaiting response from L2"
266 },
267 {,
268 "EventCode": "0x1013E",
269 "EventName": "PM_MRK_LD_MISS_EXPOSED_CYC",
270 "BriefDescription": "Marked Load exposed Miss (use edge detect to count #)"
271 },
272 {,
273 "EventCode": "0x25042",
274 "EventName": "PM_IPTEG_FROM_L3_MEPF",
275 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without dispatch conflicts hit on Mepf state. due to a instruction side request"
276 },
277 {,
278 "EventCode": "0x14054",
279 "EventName": "PM_INST_PUMP_CPRED",
280 "BriefDescription": "Pump prediction correct. Counts across all types of pumps for an instruction fetch"
281 },
282 {,
283 "EventCode": "0x4015E",
284 "EventName": "PM_MRK_FAB_RSP_RD_RTY",
285 "BriefDescription": "Sampled L2 reads retry count"
286 },
287 {,
288 "EventCode": "0x45048",
289 "EventName": "PM_IPTEG_FROM_DL2L3_MOD",
290 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a instruction side request"
291 },
292 {,
293 "EventCode": "0x44052",
294 "EventName": "PM_INST_PUMP_MPRED",
295 "BriefDescription": "Pump misprediction. Counts across all types of pumps for an instruction fetch"
296 },
297 {,
298 "EventCode": "0x30026",
299 "EventName": "PM_CMPLU_STALL_STORE_DATA",
300 "BriefDescription": "Finish stall because the next to finish instruction was a store waiting on data"
301 },
302 {,
303 "EventCode": "0x301E6",
304 "EventName": "PM_MRK_DERAT_MISS",
305 "BriefDescription": "Erat Miss (TLB Access) All page sizes"
306 },
307 {,
308 "EventCode": "0x24154",
309 "EventName": "PM_THRESH_ACC",
310 "BriefDescription": "This event increments every time the threshold event counter ticks. Thresholding must be enabled (via MMCRA) and the thresholding start event must occur for this counter to increment. It will stop incrementing when the thresholding stop event occurs or when thresholding is disabled, until the next time a configured thresholding start event occurs."
311 },
312 {,
313 "EventCode": "0x2015E",
314 "EventName": "PM_MRK_FAB_RSP_RWITM_RTY",
315 "BriefDescription": "Sampled store did a rwitm and got a rty"
316 },
317 {,
318 "EventCode": "0x200FA",
319 "EventName": "PM_BR_TAKEN_CMPL",
320 "BriefDescription": "New event for Branch Taken"
321 },
322 {,
323 "EventCode": "0x35044",
324 "EventName": "PM_IPTEG_FROM_L31_ECO_SHR",
325 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's ECO L3 on the same chip due to a instruction side request"
326 },
327 {,
328 "EventCode": "0x4C010",
329 "EventName": "PM_CMPLU_STALL_STORE_PIPE_ARB",
330 "BriefDescription": "Finish stall because the NTF instruction was a store waiting for the next relaunch opportunity after an internal reject. This means the instruction is ready to relaunch and tried once but lost arbitration"
331 },
332 {,
333 "EventCode": "0x4C01C",
334 "EventName": "PM_CMPLU_STALL_ST_FWD",
335 "BriefDescription": "Completion stall due to store forward"
336 },
337 {,
338 "EventCode": "0x3515C",
339 "EventName": "PM_MRK_DATA_FROM_RL4",
340 "BriefDescription": "The processor's data cache was reloaded from another chip's L4 on the same Node or Group ( Remote) due to a marked load"
341 },
342 {,
343 "EventCode": "0x2D14C",
344 "EventName": "PM_MRK_DATA_FROM_L31_ECO_SHR",
345 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's ECO L3 on the same chip due to a marked load"
346 },
347 {,
348 "EventCode": "0x40116",
349 "EventName": "PM_MRK_LARX_FIN",
350 "BriefDescription": "Larx finished"
351 },
352 {,
353 "EventCode": "0x4C056",
354 "EventName": "PM_DTLB_MISS_16M",
355 "BriefDescription": "Data TLB Miss page size 16M"
356 },
357 {,
358 "EventCode": "0x1003A",
359 "EventName": "PM_CMPLU_STALL_LSU_FIN",
360 "BriefDescription": "Finish stall because the NTF instruction was an LSU op (other than a load or a store) with all its dependencies met and just going through the LSU pipe to finish"
361 },
362 {,
363 "EventCode": "0x3012A",
364 "EventName": "PM_MRK_L2_RC_DONE",
365 "BriefDescription": "Marked RC done"
366 },
367 {,
368 "EventCode": "0x45044",
369 "EventName": "PM_IPTEG_FROM_L31_ECO_MOD",
370 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's ECO L3 on the same chip due to a instruction side request"
371 }
372]
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/marked.json b/tools/perf/pmu-events/arch/powerpc/power9/marked.json
new file mode 100644
index 000000000000..b9df54fb37e3
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power9/marked.json
@@ -0,0 +1,647 @@
1[
2 {,
3 "EventCode": "0x3C052",
4 "EventName": "PM_DATA_SYS_PUMP_MPRED",
5 "BriefDescription": "Final Pump Scope (system) mispredicted. Either the original scope was too small (Chip/Group) or the original scope was System and it should have been smaller. Counts for a demand load"
6 },
7 {,
8 "EventCode": "0x3013E",
9 "EventName": "PM_MRK_STALL_CMPLU_CYC",
10 "BriefDescription": "Number of cycles the marked instruction is experiencing a stall while it is next to complete (NTC)"
11 },
12 {,
13 "EventCode": "0x4F056",
14 "EventName": "PM_RADIX_PWC_L1_PDE_FROM_L3MISS",
15 "BriefDescription": "A Page Directory Entry was reloaded to a level 1 page walk cache from beyond the core's L3 data cache. The source could be local/remote/distant memory or another core's cache"
16 },
17 {,
18 "EventCode": "0x24158",
19 "EventName": "PM_MRK_INST",
20 "BriefDescription": "An instruction was marked. Includes both Random Instruction Sampling (RIS) at decode time and Random Event Sampling (RES) at the time the configured event happens"
21 },
22 {,
23 "EventCode": "0x1E046",
24 "EventName": "PM_DPTEG_FROM_L31_SHR",
25 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's L3 on the same chip due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
26 },
27 {,
28 "EventCode": "0x3C04A",
29 "EventName": "PM_DATA_FROM_RMEM",
30 "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group ( Remote) due to a demand load"
31 },
32 {,
33 "EventCode": "0x2C01C",
34 "EventName": "PM_CMPLU_STALL_DMISS_REMOTE",
35 "BriefDescription": "Completion stall by Dcache miss which resolved from remote chip (cache or memory)"
36 },
37 {,
38 "EventCode": "0x44040",
39 "EventName": "PM_INST_FROM_L2_DISP_CONFLICT_OTHER",
40 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 with dispatch conflict due to an instruction fetch (not prefetch)"
41 },
42 {,
43 "EventCode": "0x2E050",
44 "EventName": "PM_DARQ0_7_9_ENTRIES",
45 "BriefDescription": "Cycles in which 7,8, or 9 DARQ entries (out of 12) are in use"
46 },
47 {,
48 "EventCode": "0x2D02E",
49 "EventName": "PM_RADIX_PWC_L3_PTE_FROM_L2",
50 "BriefDescription": "A Page Table Entry was reloaded to a level 3 page walk cache from the core's L2 data cache. This implies that a level 4 PWC access was not necessary for this translation"
51 },
52 {,
53 "EventCode": "0x3F05E",
54 "EventName": "PM_RADIX_PWC_L3_PTE_FROM_L3",
55 "BriefDescription": "A Page Table Entry was reloaded to a level 3 page walk cache from the core's L3 data cache. This implies that a level 4 PWC access was not necessary for this translation"
56 },
57 {,
58 "EventCode": "0x2E01E",
59 "EventName": "PM_CMPLU_STALL_NTC_FLUSH",
60 "BriefDescription": "Completion stall due to ntc flush"
61 },
62 {,
63 "EventCode": "0x1F14C",
64 "EventName": "PM_MRK_DPTEG_FROM_LL4",
65 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's L4 cache due to a marked data side request.. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
66 },
67 {,
68 "EventCode": "0x20130",
69 "EventName": "PM_MRK_INST_DECODED",
70 "BriefDescription": "An instruction was marked at decode time. Random Instruction Sampling (RIS) only"
71 },
72 {,
73 "EventCode": "0x3F144",
74 "EventName": "PM_MRK_DPTEG_FROM_L31_ECO_SHR",
75 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's ECO L3 on the same chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
76 },
77 {,
78 "EventCode": "0x4D058",
79 "EventName": "PM_VECTOR_FLOP_CMPL",
80 "BriefDescription": "Vector FP instruction completed"
81 },
82 {,
83 "EventCode": "0x14040",
84 "EventName": "PM_INST_FROM_L2_NO_CONFLICT",
85 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 without conflict due to an instruction fetch (not prefetch)"
86 },
87 {,
88 "EventCode": "0x4404E",
89 "EventName": "PM_INST_FROM_L3MISS_MOD",
90 "BriefDescription": "The processor's Instruction cache was reloaded from a location other than the local core's L3 due to a instruction fetch"
91 },
92 {,
93 "EventCode": "0x3003A",
94 "EventName": "PM_CMPLU_STALL_EXCEPTION",
95 "BriefDescription": "Cycles in which the NTC instruction is not allowed to complete because it was interrupted by ANY exception, which has to be serviced before the instruction can complete"
96 },
97 {,
98 "EventCode": "0x4F144",
99 "EventName": "PM_MRK_DPTEG_FROM_L31_ECO_MOD",
100 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's ECO L3 on the same chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
101 },
102 {,
103 "EventCode": "0x3E044",
104 "EventName": "PM_DPTEG_FROM_L31_ECO_SHR",
105 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's ECO L3 on the same chip due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
106 },
107 {,
108 "EventCode": "0x300F6",
109 "EventName": "PM_L1_DCACHE_RELOAD_VALID",
110 "BriefDescription": "DL1 reloaded due to Demand Load"
111 },
112 {,
113 "EventCode": "0x1415E",
114 "EventName": "PM_MRK_DATA_FROM_L3MISS_CYC",
115 "BriefDescription": "Duration in cycles to reload from a location other than the local core's L3 due to a marked load"
116 },
117 {,
118 "EventCode": "0x1E052",
119 "EventName": "PM_CMPLU_STALL_SLB",
120 "BriefDescription": "Finish stall because the NTF instruction was awaiting L2 response for an SLB"
121 },
122 {,
123 "EventCode": "0x4404C",
124 "EventName": "PM_INST_FROM_DMEM",
125 "BriefDescription": "The processor's Instruction cache was reloaded from another chip's memory on the same Node or Group (Distant) due to an instruction fetch (not prefetch)"
126 },
127 {,
128 "EventCode": "0x3000E",
129 "EventName": "PM_FXU_1PLUS_BUSY",
130 "BriefDescription": "At least one of the 4 FXU units is busy"
131 },
132 {,
133 "EventCode": "0x2C048",
134 "EventName": "PM_DATA_FROM_LMEM",
135 "BriefDescription": "The processor's data cache was reloaded from the local chip's Memory due to a demand load"
136 },
137 {,
138 "EventCode": "0x3000A",
139 "EventName": "PM_CMPLU_STALL_PM",
140 "BriefDescription": "Finish stall because the NTF instruction was issued to the Permute execution pipe and waiting to finish. Includes permute and decimal fixed point instructions (128 bit BCD arithmetic) + a few 128 bit fixpoint add/subtract instructions with carry. Not qualified by vector or multicycle"
141 },
142 {,
143 "EventCode": "0x1504E",
144 "EventName": "PM_IPTEG_FROM_L2MISS",
145 "BriefDescription": "A Page Table Entry was loaded into the TLB from a location other than the local core's L2 due to a instruction side request"
146 },
147 {,
148 "EventCode": "0x1C052",
149 "EventName": "PM_DATA_GRP_PUMP_MPRED_RTY",
150 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for a demand load"
151 },
152 {,
153 "EventCode": "0x30008",
154 "EventName": "PM_DISP_STARVED",
155 "BriefDescription": "Dispatched Starved"
156 },
157 {,
158 "EventCode": "0x14042",
159 "EventName": "PM_INST_FROM_L2",
160 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 due to an instruction fetch (not prefetch)"
161 },
162 {,
163 "EventCode": "0x4000C",
164 "EventName": "PM_FREQ_UP",
165 "BriefDescription": "Power Management: Above Threshold A"
166 },
167 {,
168 "EventCode": "0x3C050",
169 "EventName": "PM_DATA_SYS_PUMP_CPRED",
170 "BriefDescription": "Initial and Final Pump Scope was system pump (prediction=correct) for a demand load"
171 },
172 {,
173 "EventCode": "0x25040",
174 "EventName": "PM_IPTEG_FROM_L2_MEPF",
175 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 hit without dispatch conflicts on Mepf state. due to a instruction side request"
176 },
177 {,
178 "EventCode": "0x10132",
179 "EventName": "PM_MRK_INST_ISSUED",
180 "BriefDescription": "Marked instruction issued"
181 },
182 {,
183 "EventCode": "0x1C046",
184 "EventName": "PM_DATA_FROM_L31_SHR",
185 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L3 on the same chip due to a demand load"
186 },
187 {,
188 "EventCode": "0x2C044",
189 "EventName": "PM_DATA_FROM_L31_MOD",
190 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L3 on the same chip due to a demand load"
191 },
192 {,
193 "EventCode": "0x2C04A",
194 "EventName": "PM_DATA_FROM_RL4",
195 "BriefDescription": "The processor's data cache was reloaded from another chip's L4 on the same Node or Group ( Remote) due to a demand load"
196 },
197 {,
198 "EventCode": "0x24044",
199 "EventName": "PM_INST_FROM_L31_MOD",
200 "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's L3 on the same chip due to an instruction fetch (not prefetch)"
201 },
202 {,
203 "EventCode": "0x4C050",
204 "EventName": "PM_DATA_SYS_PUMP_MPRED_RTY",
205 "BriefDescription": "Final Pump Scope (system) ended up larger than Initial Pump Scope (Chip/Group) for a demand load"
206 },
207 {,
208 "EventCode": "0x2C052",
209 "EventName": "PM_DATA_GRP_PUMP_MPRED",
210 "BriefDescription": "Final Pump Scope (Group) ended up either larger or smaller than Initial Pump Scope for a demand load"
211 },
212 {,
213 "EventCode": "0x2F148",
214 "EventName": "PM_MRK_DPTEG_FROM_LMEM",
215 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's Memory due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
216 },
217 {,
218 "EventCode": "0x4D01A",
219 "EventName": "PM_CMPLU_STALL_EIEIO",
220 "BriefDescription": "Finish stall because the NTF instruction is an EIEIO waiting for response from L2"
221 },
222 {,
223 "EventCode": "0x4F14E",
224 "EventName": "PM_MRK_DPTEG_FROM_L3MISS",
225 "BriefDescription": "A Page Table Entry was loaded into the TLB from a location other than the local core's L3 due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
226 },
227 {,
228 "EventCode": "0x4F05A",
229 "EventName": "PM_RADIX_PWC_L4_PTE_FROM_L3",
230 "BriefDescription": "A Page Table Entry was reloaded to a level 4 page walk cache from the core's L3 data cache. This is the deepest level of PWC possible for a translation"
231 },
232 {,
233 "EventCode": "0x1F05A",
234 "EventName": "PM_RADIX_PWC_L4_PTE_FROM_L2",
235 "BriefDescription": "A Page Table Entry was reloaded to a level 4 page walk cache from the core's L2 data cache. This is the deepest level of PWC possible for a translation"
236 },
237 {,
238 "EventCode": "0x30068",
239 "EventName": "PM_L1_ICACHE_RELOADED_PREF",
240 "BriefDescription": "Counts all Icache prefetch reloads ( includes demand turned into prefetch)"
241 },
242 {,
243 "EventCode": "0x4C04A",
244 "EventName": "PM_DATA_FROM_OFF_CHIP_CACHE",
245 "BriefDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a demand load"
246 },
247 {,
248 "EventCode": "0x400FE",
249 "EventName": "PM_DATA_FROM_MEMORY",
250 "BriefDescription": "The processor's data cache was reloaded from a memory location including L4 from local remote or distant due to a demand load"
251 },
252 {,
253 "EventCode": "0x3F058",
254 "EventName": "PM_RADIX_PWC_L1_PDE_FROM_L3",
255 "BriefDescription": "A Page Directory Entry was reloaded to a level 1 page walk cache from the core's L3 data cache"
256 },
257 {,
258 "EventCode": "0x4D142",
259 "EventName": "PM_MRK_DATA_FROM_L3",
260 "BriefDescription": "The processor's data cache was reloaded from local core's L3 due to a marked load"
261 },
262 {,
263 "EventCode": "0x30050",
264 "EventName": "PM_SYS_PUMP_CPRED",
265 "BriefDescription": "Initial and Final Pump Scope was system pump for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
266 },
267 {,
268 "EventCode": "0x30028",
269 "EventName": "PM_CMPLU_STALL_SPEC_FINISH",
270 "BriefDescription": "Finish stall while waiting for the non-speculative finish of either a stcx waiting for its result or a load waiting for non-critical sectors of data and ECC"
271 },
272 {,
273 "EventCode": "0x400F4",
274 "EventName": "PM_RUN_PURR",
275 "BriefDescription": "Run_PURR"
276 },
277 {,
278 "EventCode": "0x3404C",
279 "EventName": "PM_INST_FROM_DL4",
280 "BriefDescription": "The processor's Instruction cache was reloaded from another chip's L4 on a different Node or Group (Distant) due to an instruction fetch (not prefetch)"
281 },
282 {,
283 "EventCode": "0x3D05A",
284 "EventName": "PM_NTC_ISSUE_HELD_OTHER",
285 "BriefDescription": "The NTC instruction is being held at dispatch during regular pipeline cycles, or because the VSU is busy with multi-cycle instructions, or because of a write-back collision with VSU"
286 },
287 {,
288 "EventCode": "0x2E048",
289 "EventName": "PM_DPTEG_FROM_LMEM",
290 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's Memory due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
291 },
292 {,
293 "EventCode": "0x2D02A",
294 "EventName": "PM_RADIX_PWC_L3_PDE_FROM_L2",
295 "BriefDescription": "A Page Directory Entry was reloaded to a level 3 page walk cache from the core's L2 data cache"
296 },
297 {,
298 "EventCode": "0x1F05C",
299 "EventName": "PM_RADIX_PWC_L3_PDE_FROM_L3",
300 "BriefDescription": "A Page Directory Entry was reloaded to a level 3 page walk cache from the core's L3 data cache"
301 },
302 {,
303 "EventCode": "0x4D04A",
304 "EventName": "PM_DARQ0_0_3_ENTRIES",
305 "BriefDescription": "Cycles in which 3 or less DARQ entries (out of 12) are in use"
306 },
307 {,
308 "EventCode": "0x1404C",
309 "EventName": "PM_INST_FROM_LL4",
310 "BriefDescription": "The processor's Instruction cache was reloaded from the local chip's L4 cache due to an instruction fetch (not prefetch)"
311 },
312 {,
313 "EventCode": "0x200FD",
314 "EventName": "PM_L1_ICACHE_MISS",
315 "BriefDescription": "Demand iCache Miss"
316 },
317 {,
318 "EventCode": "0x34040",
319 "EventName": "PM_INST_FROM_L2_DISP_CONFLICT_LDHITST",
320 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 with load hit store conflict due to an instruction fetch (not prefetch)"
321 },
322 {,
323 "EventCode": "0x20138",
324 "EventName": "PM_MRK_ST_NEST",
325 "BriefDescription": "Marked store sent to nest"
326 },
327 {,
328 "EventCode": "0x44048",
329 "EventName": "PM_INST_FROM_DL2L3_MOD",
330 "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to an instruction fetch (not prefetch)"
331 },
332 {,
333 "EventCode": "0x35046",
334 "EventName": "PM_IPTEG_FROM_L21_SHR",
335 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's L2 on the same chip due to a instruction side request"
336 },
337 {,
338 "EventCode": "0x4C04E",
339 "EventName": "PM_DATA_FROM_L3MISS_MOD",
340 "BriefDescription": "The processor's data cache was reloaded from a location other than the local core's L3 due to a demand load"
341 },
342 {,
343 "EventCode": "0x401E0",
344 "EventName": "PM_MRK_INST_CMPL",
345 "BriefDescription": "marked instruction completed"
346 },
347 {,
348 "EventCode": "0x2C128",
349 "EventName": "PM_MRK_DATA_FROM_DL2L3_SHR_CYC",
350 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a marked load"
351 },
352 {,
353 "EventCode": "0x34044",
354 "EventName": "PM_INST_FROM_L31_ECO_SHR",
355 "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's ECO L3 on the same chip due to an instruction fetch (not prefetch)"
356 },
357 {,
358 "EventCode": "0x4E018",
359 "EventName": "PM_CMPLU_STALL_NTC_DISP_FIN",
360 "BriefDescription": "Finish stall because the NTF instruction was one that must finish at dispatch."
361 },
362 {,
363 "EventCode": "0x2E05E",
364 "EventName": "PM_LMQ_EMPTY_CYC",
365 "BriefDescription": "Cycles in which the LMQ has no pending load misses for this thread"
366 },
367 {,
368 "EventCode": "0x4C122",
369 "EventName": "PM_DARQ1_0_3_ENTRIES",
370 "BriefDescription": "Cycles in which 3 or fewer DARQ1 entries (out of 12) are in use"
371 },
372 {,
373 "EventCode": "0x4F058",
374 "EventName": "PM_RADIX_PWC_L2_PTE_FROM_L3",
375 "BriefDescription": "A Page Table Entry was reloaded to a level 2 page walk cache from the core's L3 data cache. This implies that level 3 and level 4 PWC accesses were not necessary for this translation"
376 },
377 {,
378 "EventCode": "0x14046",
379 "EventName": "PM_INST_FROM_L31_SHR",
380 "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's L3 on the same chip due to an instruction fetch (not prefetch)"
381 },
382 {,
383 "EventCode": "0x3012C",
384 "EventName": "PM_MRK_ST_FWD",
385 "BriefDescription": "Marked st forwards"
386 },
387 {,
388 "EventCode": "0x101E0",
389 "EventName": "PM_MRK_INST_DISP",
390 "BriefDescription": "The thread has dispatched a randomly sampled marked instruction"
391 },
392 {,
393 "EventCode": "0x1D058",
394 "EventName": "PM_DARQ0_10_12_ENTRIES",
395 "BriefDescription": "Cycles in which 10 or more DARQ entries (out of 12) are in use"
396 },
397 {,
398 "EventCode": "0x300FE",
399 "EventName": "PM_DATA_FROM_L3MISS",
400 "BriefDescription": "Demand LD - L3 Miss (not L2 hit and not L3 hit)"
401 },
402 {,
403 "EventCode": "0x30006",
404 "EventName": "PM_CMPLU_STALL_OTHER_CMPL",
405 "BriefDescription": "Instructions the core completed while this tread was stalled"
406 },
407 {,
408 "EventCode": "0x1005C",
409 "EventName": "PM_CMPLU_STALL_DP",
410 "BriefDescription": "Finish stall because the NTF instruction was a scalar instruction issued to the Double Precision execution pipe and waiting to finish. Includes binary floating point instructions in 32 and 64 bit binary floating point format. Not qualified multicycle. Qualified by NOT vector"
411 },
412 {,
413 "EventCode": "0x1E042",
414 "EventName": "PM_DPTEG_FROM_L2",
415 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
416 },
417 {,
418 "EventCode": "0x1016E",
419 "EventName": "PM_MRK_BR_CMPL",
420 "BriefDescription": "Branch Instruction completed"
421 },
422 {,
423 "EventCode": "0x2013A",
424 "EventName": "PM_MRK_BRU_FIN",
425 "BriefDescription": "bru marked instr finish"
426 },
427 {,
428 "EventCode": "0x4F05E",
429 "EventName": "PM_RADIX_PWC_L3_PTE_FROM_L3MISS",
430 "BriefDescription": "A Page Table Entry was reloaded to a level 3 page walk cache from beyond the core's L3 data cache. This implies that a level 4 PWC access was not necessary for this translation. The source could be local/remote/distant memory or another core's cache"
431 },
432 {,
433 "EventCode": "0x400FC",
434 "EventName": "PM_ITLB_MISS",
435 "BriefDescription": "ITLB Reloaded. Counts 1 per ITLB miss for HPT but multiple for radix depending on number of levels traveresed"
436 },
437 {,
438 "EventCode": "0x2D024",
439 "EventName": "PM_RADIX_PWC_L2_HIT",
440 "BriefDescription": "A radix translation attempt missed in the TLB but hit on both the first and second levels of page walk cache."
441 },
442 {,
443 "EventCode": "0x3F056",
444 "EventName": "PM_RADIX_PWC_L3_HIT",
445 "BriefDescription": "A radix translation attempt missed in the TLB but hit on the first, second, and third levels of page walk cache."
446 },
447 {,
448 "EventCode": "0x4E014",
449 "EventName": "PM_TM_TX_PASS_RUN_INST",
450 "BriefDescription": "Run instructions spent in successful transactions"
451 },
452 {,
453 "EventCode": "0x1E044",
454 "EventName": "PM_DPTEG_FROM_L3_NO_CONFLICT",
455 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without conflict due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
456 },
457 {,
458 "EventCode": "0x4D05A",
459 "EventName": "PM_NON_MATH_FLOP_CMPL",
460 "BriefDescription": "Non FLOP operation completed"
461 },
462 {,
463 "EventCode": "0x101E2",
464 "EventName": "PM_MRK_BR_TAKEN_CMPL",
465 "BriefDescription": "Marked Branch Taken completed"
466 },
467 {,
468 "EventCode": "0x3E158",
469 "EventName": "PM_MRK_STCX_FAIL",
470 "BriefDescription": "marked stcx failed"
471 },
472 {,
473 "EventCode": "0x1C048",
474 "EventName": "PM_DATA_FROM_ON_CHIP_CACHE",
475 "BriefDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on the same chip due to a demand load"
476 },
477 {,
478 "EventCode": "0x1C054",
479 "EventName": "PM_DATA_PUMP_CPRED",
480 "BriefDescription": "Pump prediction correct. Counts across all types of pumps for a demand load"
481 },
482 {,
483 "EventCode": "0x4405E",
484 "EventName": "PM_DARQ_STORE_REJECT",
485 "BriefDescription": "The DARQ attempted to transmit a store into an LSAQ or SRQ entry but It was rejected. Divide by PM_DARQ_STORE_XMIT to get reject ratio"
486 },
487 {,
488 "EventCode": "0x1C042",
489 "EventName": "PM_DATA_FROM_L2",
490 "BriefDescription": "The processor's data cache was reloaded from local core's L2 due to a demand load"
491 },
492 {,
493 "EventCode": "0x1D14C",
494 "EventName": "PM_MRK_DATA_FROM_LL4",
495 "BriefDescription": "The processor's data cache was reloaded from the local chip's L4 cache due to a marked load"
496 },
497 {,
498 "EventCode": "0x1006C",
499 "EventName": "PM_RUN_CYC_ST_MODE",
500 "BriefDescription": "Cycles run latch is set and core is in ST mode"
501 },
502 {,
503 "EventCode": "0x3C044",
504 "EventName": "PM_DATA_FROM_L31_ECO_SHR",
505 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's ECO L3 on the same chip due to a demand load"
506 },
507 {,
508 "EventCode": "0x4C052",
509 "EventName": "PM_DATA_PUMP_MPRED",
510 "BriefDescription": "Pump misprediction. Counts across all types of pumps for a demand load"
511 },
512 {,
513 "EventCode": "0x20050",
514 "EventName": "PM_GRP_PUMP_CPRED",
515 "BriefDescription": "Initial and Final Pump Scope and data sourced across this scope was group pump for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
516 },
517 {,
518 "EventCode": "0x1F150",
519 "EventName": "PM_MRK_ST_L2DISP_TO_CMPL_CYC",
520 "BriefDescription": "cycles from L2 rc disp to l2 rc completion"
521 },
522 {,
523 "EventCode": "0x4505A",
524 "EventName": "PM_SP_FLOP_CMPL",
525 "BriefDescription": "SP instruction completed"
526 },
527 {,
528 "EventCode": "0x4000A",
529 "EventName": "PM_ISQ_36_44_ENTRIES",
530 "BriefDescription": "Cycles in which 36 or more Issue Queue entries are in use. This is a shared event, not per thread. There are 44 issue queue entries across 4 slices in the whole core"
531 },
532 {,
533 "EventCode": "0x2C12E",
534 "EventName": "PM_MRK_DATA_FROM_LL4_CYC",
535 "BriefDescription": "Duration in cycles to reload from the local chip's L4 cache due to a marked load"
536 },
537 {,
538 "EventCode": "0x2C058",
539 "EventName": "PM_MEM_PREF",
540 "BriefDescription": "Memory prefetch for this thread. Includes L4"
541 },
542 {,
543 "EventCode": "0x40012",
544 "EventName": "PM_L1_ICACHE_RELOADED_ALL",
545 "BriefDescription": "Counts all Icache reloads includes demand, prefetch, prefetch turned into demand and demand turned into prefetch"
546 },
547 {,
548 "EventCode": "0x4003C",
549 "EventName": "PM_DISP_HELD_SYNC_HOLD",
550 "BriefDescription": "Cycles in which dispatch is held because of a synchronizing instruction in the pipeline"
551 },
552 {,
553 "EventCode": "0x3003C",
554 "EventName": "PM_CMPLU_STALL_NESTED_TEND",
555 "BriefDescription": "Completion stall because the ISU is updating the TEXASR to keep track of the nested tend and decrement the TEXASR nested level. This is a short delay"
556 },
557 {,
558 "EventCode": "0x3D05C",
559 "EventName": "PM_DISP_HELD_HB_FULL",
560 "BriefDescription": "Dispatch held due to History Buffer full. Could be GPR/VSR/VMR/FPR/CR/XVF; CR; XVF (XER/VSCR/FPSCR)"
561 },
562 {,
563 "EventCode": "0x30052",
564 "EventName": "PM_SYS_PUMP_MPRED",
565 "BriefDescription": "Final Pump Scope (system) mispredicted. Either the original scope was too small (Chip/Group) or the original scope was System and it should have been smaller. Counts for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
566 },
567 {,
568 "EventCode": "0x2E044",
569 "EventName": "PM_DPTEG_FROM_L31_MOD",
570 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L3 on the same chip due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
571 },
572 {,
573 "EventCode": "0x34048",
574 "EventName": "PM_INST_FROM_DL2L3_SHR",
575 "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to an instruction fetch (not prefetch)"
576 },
577 {,
578 "EventCode": "0x45042",
579 "EventName": "PM_IPTEG_FROM_L3",
580 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 due to a instruction side request"
581 },
582 {,
583 "EventCode": "0x15042",
584 "EventName": "PM_IPTEG_FROM_L2",
585 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 due to a instruction side request"
586 },
587 {,
588 "EventCode": "0x1C05E",
589 "EventName": "PM_MEM_LOC_THRESH_LSU_MED",
590 "BriefDescription": "Local memory above threshold for data prefetch"
591 },
592 {,
593 "EventCode": "0x40134",
594 "EventName": "PM_MRK_INST_TIMEO",
595 "BriefDescription": "marked Instruction finish timeout (instruction lost)"
596 },
597 {,
598 "EventCode": "0x1002C",
599 "EventName": "PM_L1_DCACHE_RELOADED_ALL",
600 "BriefDescription": "L1 data cache reloaded for demand. If MMCR1[16] is 1, prefetches will be included as well"
601 },
602 {,
603 "EventCode": "0x30130",
604 "EventName": "PM_MRK_INST_FIN",
605 "BriefDescription": "marked instruction finished"
606 },
607 {,
608 "EventCode": "0x1F14A",
609 "EventName": "PM_MRK_DPTEG_FROM_RL2L3_SHR",
610 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked data side request.. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
611 },
612 {,
613 "EventCode": "0x3504E",
614 "EventName": "PM_DARQ0_4_6_ENTRIES",
615 "BriefDescription": "Cycles in which 4, 5, or 6 DARQ entries (out of 12) are in use"
616 },
617 {,
618 "EventCode": "0x30064",
619 "EventName": "PM_DARQ_STORE_XMIT",
620 "BriefDescription": "The DARQ attempted to transmit a store into an LSAQ or SRQ entry. Includes rejects. Not qualified by thread, so it includes counts for the whole core"
621 },
622 {,
623 "EventCode": "0x45046",
624 "EventName": "PM_IPTEG_FROM_L21_MOD",
625 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L2 on the same chip due to a instruction side request"
626 },
627 {,
628 "EventCode": "0x2C016",
629 "EventName": "PM_CMPLU_STALL_PASTE",
630 "BriefDescription": "Finish stall because the NTF instruction was a paste waiting for response from L2"
631 },
632 {,
633 "EventCode": "0x24156",
634 "EventName": "PM_MRK_STCX_FIN",
635 "BriefDescription": "Number of marked stcx instructions finished. This includes instructions in the speculative path of a branch that may be flushed"
636 },
637 {,
638 "EventCode": "0x15150",
639 "EventName": "PM_SYNC_MRK_PROBE_NOP",
640 "BriefDescription": "Marked probeNops which can cause synchronous interrupts"
641 },
642 {,
643 "EventCode": "0x301E4",
644 "EventName": "PM_MRK_BR_MPRED_CMPL",
645 "BriefDescription": "Marked Branch Mispredicted"
646 }
647]
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/memory.json b/tools/perf/pmu-events/arch/powerpc/power9/memory.json
new file mode 100644
index 000000000000..9960d1c0dd44
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power9/memory.json
@@ -0,0 +1,132 @@
1[
2 {,
3 "EventCode": "0x3006E",
4 "EventName": "PM_NEST_REF_CLK",
5 "BriefDescription": "Multiply by 4 to obtain the number of PB cycles"
6 },
7 {,
8 "EventCode": "0x20010",
9 "EventName": "PM_PMC1_OVERFLOW",
10 "BriefDescription": "Overflow from counter 1"
11 },
12 {,
13 "EventCode": "0x2005A",
14 "EventName": "PM_DARQ1_7_9_ENTRIES",
15 "BriefDescription": "Cycles in which 7 to 9 DARQ1 entries (out of 12) are in use"
16 },
17 {,
18 "EventCode": "0x3C048",
19 "EventName": "PM_DATA_FROM_DL2L3_SHR",
20 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a demand load"
21 },
22 {,
23 "EventCode": "0x10008",
24 "EventName": "PM_RUN_SPURR",
25 "BriefDescription": "Run SPURR"
26 },
27 {,
28 "EventCode": "0x200F6",
29 "EventName": "PM_LSU_DERAT_MISS",
30 "BriefDescription": "DERAT Reloaded due to a DERAT miss"
31 },
32 {,
33 "EventCode": "0x4C048",
34 "EventName": "PM_DATA_FROM_DL2L3_MOD",
35 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a demand load"
36 },
37 {,
38 "EventCode": "0x1D15E",
39 "EventName": "PM_MRK_RUN_CYC",
40 "BriefDescription": "Run cycles in which a marked instruction is in the pipeline"
41 },
42 {,
43 "EventCode": "0x4003E",
44 "EventName": "PM_LD_CMPL",
45 "BriefDescription": "count of Loads completed"
46 },
47 {,
48 "EventCode": "0x2D156",
49 "EventName": "PM_MRK_DTLB_MISS_4K",
50 "BriefDescription": "Marked Data TLB Miss page size 4k"
51 },
52 {,
53 "EventCode": "0x4C042",
54 "EventName": "PM_DATA_FROM_L3",
55 "BriefDescription": "The processor's data cache was reloaded from local core's L3 due to a demand load"
56 },
57 {,
58 "EventCode": "0x4D02C",
59 "EventName": "PM_PMC1_REWIND",
60 "BriefDescription": ""
61 },
62 {,
63 "EventCode": "0x15158",
64 "EventName": "PM_SYNC_MRK_L2HIT",
65 "BriefDescription": "Marked L2 Hits that can throw a synchronous interrupt"
66 },
67 {,
68 "EventCode": "0x3404A",
69 "EventName": "PM_INST_FROM_RMEM",
70 "BriefDescription": "The processor's Instruction cache was reloaded from another chip's memory on the same Node or Group ( Remote) due to an instruction fetch (not prefetch)"
71 },
72 {,
73 "EventCode": "0x301E2",
74 "EventName": "PM_MRK_ST_CMPL",
75 "BriefDescription": "Marked store completed and sent to nest"
76 },
77 {,
78 "EventCode": "0x1C050",
79 "EventName": "PM_DATA_CHIP_PUMP_CPRED",
80 "BriefDescription": "Initial and Final Pump Scope was chip pump (prediction=correct) for a demand load"
81 },
82 {,
83 "EventCode": "0x4C040",
84 "EventName": "PM_DATA_FROM_L2_DISP_CONFLICT_OTHER",
85 "BriefDescription": "The processor's data cache was reloaded from local core's L2 with dispatch conflict due to a demand load"
86 },
87 {,
88 "EventCode": "0x2E05C",
89 "EventName": "PM_LSU_REJECT_ERAT_MISS",
90 "BriefDescription": "LSU Reject due to ERAT (up to 4 per cycles)"
91 },
92 {,
93 "EventCode": "0x1000A",
94 "EventName": "PM_PMC3_REWIND",
95 "BriefDescription": "PMC3 rewind event. A rewind happens when a speculative event (such as latency or CPI stack) is selected on PMC3 and the stall reason or reload source did not match the one programmed in PMC3. When this occurs, the count in PMC3 will not change."
96 },
97 {,
98 "EventCode": "0x3C058",
99 "EventName": "PM_LARX_FIN",
100 "BriefDescription": "Larx finished"
101 },
102 {,
103 "EventCode": "0x1C040",
104 "EventName": "PM_DATA_FROM_L2_NO_CONFLICT",
105 "BriefDescription": "The processor's data cache was reloaded from local core's L2 without conflict due to a demand load"
106 },
107 {,
108 "EventCode": "0x2C040",
109 "EventName": "PM_DATA_FROM_L2_MEPF",
110 "BriefDescription": "The processor's data cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state due to a demand load"
111 },
112 {,
113 "EventCode": "0x2E05A",
114 "EventName": "PM_LRQ_REJECT",
115 "BriefDescription": "Internal LSU reject from LRQ. Rejects cause the load to go back to LRQ, but it stays contained within the LSU once it gets issued. This event counts the number of times the LRQ attempts to relaunch an instruction after a reject. Any load can suffer multiple rejects"
116 },
117 {,
118 "EventCode": "0x2C05C",
119 "EventName": "PM_INST_GRP_PUMP_CPRED",
120 "BriefDescription": "Initial and Final Pump Scope was group pump (prediction=correct) for an instruction fetch (demand only)"
121 },
122 {,
123 "EventCode": "0x4D056",
124 "EventName": "PM_NON_FMA_FLOP_CMPL",
125 "BriefDescription": "Non FMA instruction completed"
126 },
127 {,
128 "EventCode": "0x3E050",
129 "EventName": "PM_DARQ1_4_6_ENTRIES",
130 "BriefDescription": "Cycles in which 4, 5, or 6 DARQ1 entries (out of 12) are in use"
131 }
132] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/other.json b/tools/perf/pmu-events/arch/powerpc/power9/other.json
new file mode 100644
index 000000000000..54cc3be00fc2
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power9/other.json
@@ -0,0 +1,2392 @@
1[
2 {,
3 "EventCode": "0x3084",
4 "EventName": "PM_ISU1_ISS_HOLD_ALL",
5 "BriefDescription": "All ISU rejects"
6 },
7 {,
8 "EventCode": "0xF880",
9 "EventName": "PM_SNOOP_TLBIE",
10 "BriefDescription": "TLBIE snoop"
11 },
12 {,
13 "EventCode": "0x4088",
14 "EventName": "PM_IC_DEMAND_REQ",
15 "BriefDescription": "Demand Instruction fetch request"
16 },
17 {,
18 "EventCode": "0x20A4",
19 "EventName": "PM_TM_TRESUME",
20 "BriefDescription": "TM resume instruction completed"
21 },
22 {,
23 "EventCode": "0x40008",
24 "EventName": "PM_SRQ_EMPTY_CYC",
25 "BriefDescription": "Cycles in which the SRQ has at least one (out of four) empty slice"
26 },
27 {,
28 "EventCode": "0x20064",
29 "EventName": "PM_IERAT_RELOAD_4K",
30 "BriefDescription": "IERAT reloaded (after a miss) for 4K pages"
31 },
32 {,
33 "EventCode": "0x260B4",
34 "EventName": "PM_L3_P2_LCO_RTY",
35 "BriefDescription": "L3 initiated LCO received retry on port 2 (can try 4 times)"
36 },
37 {,
38 "EventCode": "0x20006",
39 "EventName": "PM_DISP_HELD_ISSQ_FULL",
40 "BriefDescription": "Dispatch held due to Issue q full. Includes issue queue and branch queue"
41 },
42 {,
43 "EventCode": "0x201E4",
44 "EventName": "PM_MRK_DATA_FROM_L3MISS",
45 "BriefDescription": "The processor's data cache was reloaded from a location other than the local core's L3 due to a marked load"
46 },
47 {,
48 "EventCode": "0x4E044",
49 "EventName": "PM_DPTEG_FROM_L31_ECO_MOD",
50 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's ECO L3 on the same chip due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
51 },
52 {,
53 "EventCode": "0x40B8",
54 "EventName": "PM_BR_MPRED_TAKEN_CR",
55 "BriefDescription": "A Conditional Branch that resolved to taken was mispredicted as not taken (due to the BHT Direction Prediction)."
56 },
57 {,
58 "EventCode": "0xF8AC",
59 "EventName": "PM_DC_DEALLOC_NO_CONF",
60 "BriefDescription": "A demand load referenced a line in an active fuzzy prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software.Fuzzy stream confirm (out of order effects, or pf cant keep up)"
61 },
62 {,
63 "EventCode": "0xD090",
64 "EventName": "PM_LS0_DC_COLLISIONS",
65 "BriefDescription": "Read-write data cache collisions"
66 },
67 {,
68 "EventCode": "0x40BC",
69 "EventName": "PM_THRD_PRIO_0_1_CYC",
70 "BriefDescription": "Cycles thread running at priority level 0 or 1"
71 },
72 {,
73 "EventCode": "0x2084",
74 "EventName": "PM_FLUSH_HB_RESTORE_CYC",
75 "BriefDescription": "Cycles in which no new instructions can be dispatched to the ICT after a flush. History buffer recovery"
76 },
77 {,
78 "EventCode": "0x4F054",
79 "EventName": "PM_RADIX_PWC_MISS",
80 "BriefDescription": "A radix translation attempt missed in the TLB and all levels of page walk cache."
81 },
82 {,
83 "EventCode": "0x24048",
84 "EventName": "PM_INST_FROM_LMEM",
85 "BriefDescription": "The processor's Instruction cache was reloaded from the local chip's Memory due to an instruction fetch (not prefetch)"
86 },
87 {,
88 "EventCode": "0xD8B4",
89 "EventName": "PM_LSU0_LRQ_S0_VALID_CYC",
90 "BriefDescription": "Slot 0 of LRQ valid"
91 },
92 {,
93 "EventCode": "0x2E052",
94 "EventName": "PM_TM_PASSED",
95 "BriefDescription": "Number of TM transactions that passed"
96 },
97 {,
98 "EventCode": "0xD1A0",
99 "EventName": "PM_MRK_LSU_FLUSH_LHS",
100 "BriefDescription": "Effective Address alias flush : no EA match but Real Address match. If the data has not yet been returned for this load, the instruction will just be rejected, but if it has returned data, it will be flushed"
101 },
102 {,
103 "EventCode": "0xF088",
104 "EventName": "PM_LSU0_STORE_REJECT",
105 "BriefDescription": "All internal store rejects cause the instruction to go back to the SRQ and go to sleep until woken up to try again after the condition has been met"
106 },
107 {,
108 "EventCode": "0x360B2",
109 "EventName": "PM_L3_GRP_GUESS_WRONG_LOW",
110 "BriefDescription": "Initial scope=group (GS or NNS) but data from outside group (far or rem). Prediction too Low"
111 },
112 {,
113 "EventCode": "0x168A6",
114 "EventName": "PM_TM_CAM_OVERFLOW",
115 "BriefDescription": "L3 TM cam overflow during L2 co of SC"
116 },
117 {,
118 "EventCode": "0xE8B0",
119 "EventName": "PM_TEND_PEND_CYC",
120 "BriefDescription": "TEND latency per thread"
121 },
122 {,
123 "EventCode": "0x4884",
124 "EventName": "PM_IBUF_FULL_CYC",
125 "BriefDescription": "Cycles No room in ibuff"
126 },
127 {,
128 "EventCode": "0xD08C",
129 "EventName": "PM_LSU2_LDMX_FIN",
130 "BriefDescription": "New P9 instruction LDMX. The definition of this new PMU event is (from the ldmx RFC02491): The thread has executed an ldmx instruction that accessed a doubleword that contains an effective address within an enabled section of the Load Monitored region. This event, therefore, should not occur if the FSCR has disabled the load monitored facility (FSCR[52]) or disabled the EBB facility (FSCR[56])"
131 },
132 {,
133 "EventCode": "0x300F8",
134 "EventName": "PM_TB_BIT_TRANS",
135 "BriefDescription": "timebase event"
136 },
137 {,
138 "EventCode": "0x3C040",
139 "EventName": "PM_DATA_FROM_L2_DISP_CONFLICT_LDHITST",
140 "BriefDescription": "The processor's data cache was reloaded from local core's L2 with load hit store conflict due to a demand load"
141 },
142 {,
143 "EventCode": "0xE0BC",
144 "EventName": "PM_LS0_PTE_TABLEWALK_CYC",
145 "BriefDescription": "Cycles when a tablewalk is pending on this thread on table 0"
146 },
147 {,
148 "EventCode": "0x3884",
149 "EventName": "PM_ISU3_ISS_HOLD_ALL",
150 "BriefDescription": "All ISU rejects"
151 },
152 {,
153 "EventCode": "0x460A6",
154 "EventName": "PM_RD_FORMING_SC",
155 "BriefDescription": "Read forming SC"
156 },
157 {,
158 "EventCode": "0x468A0",
159 "EventName": "PM_L3_PF_OFF_CHIP_MEM",
160 "BriefDescription": "L3 PF from Off chip memory"
161 },
162 {,
163 "EventCode": "0x268AA",
164 "EventName": "PM_L3_P1_LCO_DATA",
165 "BriefDescription": "LCO sent with data port 1"
166 },
167 {,
168 "EventCode": "0xE894",
169 "EventName": "PM_LSU1_TM_L1_HIT",
170 "BriefDescription": "Load tm hit in L1"
171 },
172 {,
173 "EventCode": "0x5888",
174 "EventName": "PM_IC_INVALIDATE",
175 "BriefDescription": "Ic line invalidated"
176 },
177 {,
178 "EventCode": "0x2890",
179 "EventName": "PM_DISP_CLB_HELD_TLBIE",
180 "BriefDescription": "Dispatch Hold: Due to TLBIE"
181 },
182 {,
183 "EventCode": "0x1001C",
184 "EventName": "PM_CMPLU_STALL_THRD",
185 "BriefDescription": "Completion Stalled because the thread was blocked"
186 },
187 {,
188 "EventCode": "0x368A6",
189 "EventName": "PM_SNP_TM_HIT_T",
190 "BriefDescription": "Snp TM sthit T/Tn/Te"
191 },
192 {,
193 "EventCode": "0x3001A",
194 "EventName": "PM_DATA_TABLEWALK_CYC",
195 "BriefDescription": "Data Tablewalk Cycles. Could be 1 or 2 active tablewalks. Includes data prefetches."
196 },
197 {,
198 "EventCode": "0xD894",
199 "EventName": "PM_LS3_DC_COLLISIONS",
200 "BriefDescription": "Read-write data cache collisions"
201 },
202 {,
203 "EventCode": "0x35158",
204 "EventName": "PM_MRK_DATA_FROM_L31_ECO_MOD_CYC",
205 "BriefDescription": "Duration in cycles to reload with Modified (M) data from another core's ECO L3 on the same chip due to a marked load"
206 },
207 {,
208 "EventCode": "0xF0B4",
209 "EventName": "PM_DC_PREF_CONS_ALLOC",
210 "BriefDescription": "Prefetch stream allocated in the conservative phase by either the hardware prefetch mechanism or software prefetch"
211 },
212 {,
213 "EventCode": "0xF894",
214 "EventName": "PM_LSU3_L1_CAM_CANCEL",
215 "BriefDescription": "ls3 l1 tm cam cancel"
216 },
217 {,
218 "EventCode": "0x2888",
219 "EventName": "PM_FLUSH_DISP_TLBIE",
220 "BriefDescription": "Dispatch Flush: TLBIE"
221 },
222 {,
223 "EventCode": "0xD1A4",
224 "EventName": "PM_MRK_LSU_FLUSH_SAO",
225 "BriefDescription": "A load-hit-load condition with Strong Address Ordering will have address compare disabled and flush"
226 },
227 {,
228 "EventCode": "0x4E11E",
229 "EventName": "PM_MRK_DATA_FROM_DMEM_CYC",
230 "BriefDescription": "Duration in cycles to reload from another chip's memory on the same Node or Group (Distant) due to a marked load"
231 },
232 {,
233 "EventCode": "0x5894",
234 "EventName": "PM_LWSYNC",
235 "BriefDescription": "Lwsync instruction decoded and transferred"
236 },
237 {,
238 "EventCode": "0x14156",
239 "EventName": "PM_MRK_DATA_FROM_L2_CYC",
240 "BriefDescription": "Duration in cycles to reload from local core's L2 due to a marked load"
241 },
242 {,
243 "EventCode": "0x468A6",
244 "EventName": "PM_RD_CLEARING_SC",
245 "BriefDescription": "Read clearing SC"
246 },
247 {,
248 "EventCode": "0x50A0",
249 "EventName": "PM_HWSYNC",
250 "BriefDescription": "Hwsync instruction decoded and transferred"
251 },
252 {,
253 "EventCode": "0x168B0",
254 "EventName": "PM_L3_P1_NODE_PUMP",
255 "BriefDescription": "L3 PF sent with nodal scope port 1, counts even retried requests"
256 },
257 {,
258 "EventCode": "0xD0BC",
259 "EventName": "PM_LSU0_1_LRQF_FULL_CYC",
260 "BriefDescription": "Counts the number of cycles the LRQF is full. LRQF is the queue that holds loads between finish and completion. If it fills up, instructions stay in LRQ until completion, potentially backing up the LRQ"
261 },
262 {,
263 "EventCode": "0x2D148",
264 "EventName": "PM_MRK_DATA_FROM_L2_DISP_CONFLICT_LDHITST",
265 "BriefDescription": "The processor's data cache was reloaded from local core's L2 with load hit store conflict due to a marked load"
266 },
267 {,
268 "EventCode": "0x460A8",
269 "EventName": "PM_SN_HIT",
270 "BriefDescription": "Any port snooper hit L3. Up to 4 can happen in a cycle but we only count 1"
271 },
272 {,
273 "EventCode": "0x360AA",
274 "EventName": "PM_L3_P0_CO_MEM",
275 "BriefDescription": "L3 CO to memory port 0 with or without data"
276 },
277 {,
278 "EventCode": "0xF0A4",
279 "EventName": "PM_DC_PREF_HW_ALLOC",
280 "BriefDescription": "Prefetch stream allocated by the hardware prefetch mechanism"
281 },
282 {,
283 "EventCode": "0xF0BC",
284 "EventName": "PM_LS2_UNALIGNED_ST",
285 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
286 },
287 {,
288 "EventCode": "0xD0AC",
289 "EventName": "PM_SRQ_SYNC_CYC",
290 "BriefDescription": "A sync is in the S2Q (edge detect to count)"
291 },
292 {,
293 "EventCode": "0x401E6",
294 "EventName": "PM_MRK_INST_FROM_L3MISS",
295 "BriefDescription": "Marked instruction was reloaded from a location beyond the local chiplet"
296 },
297 {,
298 "EventCode": "0x26082",
299 "EventName": "PM_L2_IC_INV",
300 "BriefDescription": "I-cache Invalidates sent over the realod bus to the core"
301 },
302 {,
303 "EventCode": "0xC8AC",
304 "EventName": "PM_LSU_FLUSH_RELAUNCH_MISS",
305 "BriefDescription": "If a load that has already returned data and has to relaunch for any reason then gets a miss (erat, setp, data cache), it will often be flushed at relaunch time because the data might be inconsistent"
306 },
307 {,
308 "EventCode": "0x260A4",
309 "EventName": "PM_L3_LD_HIT",
310 "BriefDescription": "L3 Hits for demand LDs"
311 },
312 {,
313 "EventCode": "0xF0A0",
314 "EventName": "PM_DATA_STORE",
315 "BriefDescription": "All ops that drain from s2q to L2 containing data"
316 },
317 {,
318 "EventCode": "0x1D148",
319 "EventName": "PM_MRK_DATA_FROM_RMEM",
320 "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group ( Remote) due to a marked load"
321 },
322 {,
323 "EventCode": "0x16088",
324 "EventName": "PM_L2_LOC_GUESS_CORRECT",
325 "BriefDescription": "L2 guess local (LNS) and guess was correct (ie data local)"
326 },
327 {,
328 "EventCode": "0x160A4",
329 "EventName": "PM_L3_HIT",
330 "BriefDescription": "L3 Hits (L2 miss hitting L3, including data/instrn/xlate)"
331 },
332 {,
333 "EventCode": "0xE09C",
334 "EventName": "PM_LSU0_TM_L1_MISS",
335 "BriefDescription": "Load tm L1 miss"
336 },
337 {,
338 "EventCode": "0x168B4",
339 "EventName": "PM_L3_P1_LCO_RTY",
340 "BriefDescription": "L3 initiated LCO received retry on port 1 (can try 4 times)"
341 },
342 {,
343 "EventCode": "0x268AC",
344 "EventName": "PM_L3_RD_USAGE",
345 "BriefDescription": "Rotating sample of 16 RD actives"
346 },
347 {,
348 "EventCode": "0x1415C",
349 "EventName": "PM_MRK_DATA_FROM_L3_MEPF_CYC",
350 "BriefDescription": "Duration in cycles to reload from local core's L3 without dispatch conflicts hit on Mepf state due to a marked load"
351 },
352 {,
353 "EventCode": "0xE880",
354 "EventName": "PM_L1_SW_PREF",
355 "BriefDescription": "Software L1 Prefetches, including SW Transient Prefetches"
356 },
357 {,
358 "EventCode": "0x288C",
359 "EventName": "PM_DISP_CLB_HELD_BAL",
360 "BriefDescription": "Dispatch/CLB Hold: Balance Flush"
361 },
362 {,
363 "EventCode": "0x101EA",
364 "EventName": "PM_MRK_L1_RELOAD_VALID",
365 "BriefDescription": "Marked demand reload"
366 },
367 {,
368 "EventCode": "0x1D156",
369 "EventName": "PM_MRK_LD_MISS_L1_CYC",
370 "BriefDescription": "Marked ld latency"
371 },
372 {,
373 "EventCode": "0x4C01A",
374 "EventName": "PM_CMPLU_STALL_DMISS_L3MISS",
375 "BriefDescription": "Completion stall due to cache miss resolving missed the L3"
376 },
377 {,
378 "EventCode": "0x2006C",
379 "EventName": "PM_RUN_CYC_SMT4_MODE",
380 "BriefDescription": "Cycles in which this thread's run latch is set and the core is in SMT4 mode"
381 },
382 {,
383 "EventCode": "0x5088",
384 "EventName": "PM_DECODE_FUSION_OP_PRESERV",
385 "BriefDescription": "Destructive op operand preservation"
386 },
387 {,
388 "EventCode": "0x1D14E",
389 "EventName": "PM_MRK_DATA_FROM_OFF_CHIP_CACHE_CYC",
390 "BriefDescription": "Duration in cycles to reload either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked load"
391 },
392 {,
393 "EventCode": "0x509C",
394 "EventName": "PM_FORCED_NOP",
395 "BriefDescription": "Instruction was forced to execute as a nop because it was found to behave like a nop (have no effect) at decode time"
396 },
397 {,
398 "EventCode": "0xC098",
399 "EventName": "PM_LS2_UNALIGNED_LD",
400 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
401 },
402 {,
403 "EventCode": "0x20058",
404 "EventName": "PM_DARQ1_10_12_ENTRIES",
405 "BriefDescription": "Cycles in which 10 or more DARQ1 entries (out of 12) are in use"
406 },
407 {,
408 "EventCode": "0x360A6",
409 "EventName": "PM_SNP_TM_HIT_M",
410 "BriefDescription": "Snp TM st hit M/Mu"
411 },
412 {,
413 "EventCode": "0x5898",
414 "EventName": "PM_LINK_STACK_INVALID_PTR",
415 "BriefDescription": "It is most often caused by certain types of flush where the pointer is not available. Can result in the data in the link stack becoming unusable."
416 },
417 {,
418 "EventCode": "0x46088",
419 "EventName": "PM_L2_CHIP_PUMP",
420 "BriefDescription": "RC requests that were local (aka chip) pump attempts"
421 },
422 {,
423 "EventCode": "0x28A0",
424 "EventName": "PM_TM_TSUSPEND",
425 "BriefDescription": "TM suspend instruction completed"
426 },
427 {,
428 "EventCode": "0x20054",
429 "EventName": "PM_L1_PREF",
430 "BriefDescription": "A data line was written to the L1 due to a hardware or software prefetch"
431 },
432 {,
433 "EventCode": "0xF888",
434 "EventName": "PM_LSU1_STORE_REJECT",
435 "BriefDescription": "All internal store rejects cause the instruction to go back to the SRQ and go to sleep until woken up to try again after the condition has been met"
436 },
437 {,
438 "EventCode": "0x4505E",
439 "EventName": "PM_FLOP_CMPL",
440 "BriefDescription": "Floating Point Operation Finished"
441 },
442 {,
443 "EventCode": "0x1D144",
444 "EventName": "PM_MRK_DATA_FROM_L3_DISP_CONFLICT",
445 "BriefDescription": "The processor's data cache was reloaded from local core's L3 with dispatch conflict due to a marked load"
446 },
447 {,
448 "EventCode": "0x400FA",
449 "EventName": "PM_RUN_INST_CMPL",
450 "BriefDescription": "Run_Instructions"
451 },
452 {,
453 "EventCode": "0x15154",
454 "EventName": "PM_SYNC_MRK_L3MISS",
455 "BriefDescription": "Marked L3 misses that can throw a synchronous interrupt"
456 },
457 {,
458 "EventCode": "0xE0B4",
459 "EventName": "PM_LS0_TM_DISALLOW",
460 "BriefDescription": "A TM-ineligible instruction tries to execute inside a transaction and the LSU disallows it"
461 },
462 {,
463 "EventCode": "0x26884",
464 "EventName": "PM_DSIDE_MRU_TOUCH",
465 "BriefDescription": "D-side L2 MRU touch sent to L2"
466 },
467 {,
468 "EventCode": "0x30134",
469 "EventName": "PM_MRK_ST_CMPL_INT",
470 "BriefDescription": "marked store finished with intervention"
471 },
472 {,
473 "EventCode": "0xC0B8",
474 "EventName": "PM_LSU_FLUSH_SAO",
475 "BriefDescription": "A load-hit-load condition with Strong Address Ordering will have address compare disabled and flush"
476 },
477 {,
478 "EventCode": "0x50A8",
479 "EventName": "PM_EAT_FORCE_MISPRED",
480 "BriefDescription": "XL-form branch was mispredicted due to the predicted target address missing from EAT. The EAT forces a mispredict in this case since there is no predicated target to validate. This is a rare case that may occur when the EAT is full and a branch is issued"
481 },
482 {,
483 "EventCode": "0xC094",
484 "EventName": "PM_LS0_UNALIGNED_LD",
485 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
486 },
487 {,
488 "EventCode": "0xF8BC",
489 "EventName": "PM_LS3_UNALIGNED_ST",
490 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
491 },
492 {,
493 "EventCode": "0x58B0",
494 "EventName": "PM_BTAC_GOOD_RESULT",
495 "BriefDescription": "BTAC predicts a taken branch and the BHT agrees, and the target address is correct"
496 },
497 {,
498 "EventCode": "0x1C04C",
499 "EventName": "PM_DATA_FROM_LL4",
500 "BriefDescription": "The processor's data cache was reloaded from the local chip's L4 cache due to a demand load"
501 },
502 {,
503 "EventCode": "0x3608E",
504 "EventName": "PM_TM_ST_CONF",
505 "BriefDescription": "TM Store (fav or non-fav) ran into conflict (failed)"
506 },
507 {,
508 "EventCode": "0xD998",
509 "EventName": "PM_MRK_LSU_FLUSH_EMSH",
510 "BriefDescription": "An ERAT miss was detected after a set-p hit. Erat tracker indicates fail due to tlbmiss and the instruction gets flushed because the instruction was working on the wrong address"
511 },
512 {,
513 "EventCode": "0xF8A0",
514 "EventName": "PM_NON_DATA_STORE",
515 "BriefDescription": "All ops that drain from s2q to L2 and contain no data"
516 },
517 {,
518 "EventCode": "0x3F146",
519 "EventName": "PM_MRK_DPTEG_FROM_L21_SHR",
520 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's L2 on the same chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
521 },
522 {,
523 "EventCode": "0x40A0",
524 "EventName": "PM_BR_UNCOND",
525 "BriefDescription": "Unconditional Branch Completed. HW branch prediction was not used for this branch. This can be an I-form branch, a B-form branch with BO-field set to branch always, or a B-form branch which was covenrted to a Resolve."
526 },
527 {,
528 "EventCode": "0x1F056",
529 "EventName": "PM_RADIX_PWC_L1_HIT",
530 "BriefDescription": "A radix translation attempt missed in the TLB and only the first level page walk cache was a hit."
531 },
532 {,
533 "EventCode": "0xF8A8",
534 "EventName": "PM_DC_PREF_FUZZY_CONF",
535 "BriefDescription": "A demand load referenced a line in an active fuzzy prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software.Fuzzy stream confirm (out of order effects, or pf cant keep up)"
536 },
537 {,
538 "EventCode": "0xF8A4",
539 "EventName": "PM_DC_PREF_SW_ALLOC",
540 "BriefDescription": "Prefetch stream allocated by software prefetching"
541 },
542 {,
543 "EventCode": "0xE0A0",
544 "EventName": "PM_LSU2_TM_L1_MISS",
545 "BriefDescription": "Load tm L1 miss"
546 },
547 {,
548 "EventCode": "0x2894",
549 "EventName": "PM_TM_OUTER_TEND",
550 "BriefDescription": "Completion time outer tend"
551 },
552 {,
553 "EventCode": "0xF098",
554 "EventName": "PM_XLATE_HPT_MODE",
555 "BriefDescription": "LSU reports every cycle the thread is in HPT translation mode (as opposed to radix mode)"
556 },
557 {,
558 "EventCode": "0x2C04E",
559 "EventName": "PM_LD_MISS_L1_FIN",
560 "BriefDescription": "Number of load instructions that finished with an L1 miss. Note that even if a load spans multiple slices this event will increment only once per load op."
561 },
562 {,
563 "EventCode": "0x30162",
564 "EventName": "PM_MRK_LSU_DERAT_MISS",
565 "BriefDescription": "Marked derat reload (miss) for any page size"
566 },
567 {,
568 "EventCode": "0x160A0",
569 "EventName": "PM_L3_PF_MISS_L3",
570 "BriefDescription": "L3 PF missed in L3"
571 },
572 {,
573 "EventCode": "0x1C04A",
574 "EventName": "PM_DATA_FROM_RL2L3_SHR",
575 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load"
576 },
577 {,
578 "EventCode": "0xD99C",
579 "EventName": "PM_MRK_LSU_FLUSH_UE",
580 "BriefDescription": "Correctable ECC error on reload data, reported at critical data forward time"
581 },
582 {,
583 "EventCode": "0x268B0",
584 "EventName": "PM_L3_P1_GRP_PUMP",
585 "BriefDescription": "L3 PF sent with grp scope port 1, counts even retried requests"
586 },
587 {,
588 "EventCode": "0x30016",
589 "EventName": "PM_CMPLU_STALL_SRQ_FULL",
590 "BriefDescription": "Finish stall because the NTF instruction was a store that was held in LSAQ because the SRQ was full"
591 },
592 {,
593 "EventCode": "0x40B4",
594 "EventName": "PM_BR_PRED_TA",
595 "BriefDescription": "Conditional Branch Completed that had its target address predicted. Only XL-form branches set this event. This equal the sum of CCACHE, LSTACK, and PCACHE"
596 },
597 {,
598 "EventCode": "0x40AC",
599 "EventName": "PM_BR_MPRED_CCACHE",
600 "BriefDescription": "Conditional Branch Completed that was Mispredicted due to the Count Cache Target Prediction"
601 },
602 {,
603 "EventCode": "0x3688A",
604 "EventName": "PM_L2_RTY_LD",
605 "BriefDescription": "RC retries on PB for any load from core (excludes DCBFs)"
606 },
607 {,
608 "EventCode": "0xE08C",
609 "EventName": "PM_LSU0_ERAT_HIT",
610 "BriefDescription": "Primary ERAT hit. There is no secondary ERAT"
611 },
612 {,
613 "EventCode": "0xE088",
614 "EventName": "PM_LS2_ERAT_MISS_PREF",
615 "BriefDescription": "LS0 Erat miss due to prefetch"
616 },
617 {,
618 "EventCode": "0xF0A8",
619 "EventName": "PM_DC_PREF_CONF",
620 "BriefDescription": "A demand load referenced a line in an active prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software. Includes forwards and backwards streams"
621 },
622 {,
623 "EventCode": "0x16888",
624 "EventName": "PM_L2_LOC_GUESS_WRONG",
625 "BriefDescription": "L2 guess local (LNS) and guess was not correct (ie data not on chip)"
626 },
627 {,
628 "EventCode": "0xE0A4",
629 "EventName": "PM_TMA_REQ_L2",
630 "BriefDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding"
631 },
632 {,
633 "EventCode": "0x5884",
634 "EventName": "PM_DECODE_LANES_NOT_AVAIL",
635 "BriefDescription": "Decode has something to transmit but dispatch lanes are not available"
636 },
637 {,
638 "EventCode": "0x3C042",
639 "EventName": "PM_DATA_FROM_L3_DISP_CONFLICT",
640 "BriefDescription": "The processor's data cache was reloaded from local core's L3 with dispatch conflict due to a demand load"
641 },
642 {,
643 "EventCode": "0x168AA",
644 "EventName": "PM_L3_P1_LCO_NO_DATA",
645 "BriefDescription": "Dataless L3 LCO sent port 1"
646 },
647 {,
648 "EventCode": "0x3D140",
649 "EventName": "PM_MRK_DATA_FROM_L2_DISP_CONFLICT_OTHER_CYC",
650 "BriefDescription": "Duration in cycles to reload from local core's L2 with dispatch conflict due to a marked load"
651 },
652 {,
653 "EventCode": "0xC89C",
654 "EventName": "PM_LS1_LAUNCH_HELD_PREF",
655 "BriefDescription": "Number of times a load or store instruction was unable to launch/relaunch because a high priority prefetch used that relaunch cycle"
656 },
657 {,
658 "EventCode": "0x4894",
659 "EventName": "PM_IC_RELOAD_PRIVATE",
660 "BriefDescription": "Reloading line was brought in private for a specific thread. Most lines are brought in shared for all eight threads. If RA does not match then invalidates and then brings it shared to other thread. In P7 line brought in private , then line was invalidat"
661 },
662 {,
663 "EventCode": "0x1688E",
664 "EventName": "PM_TM_LD_CAUSED_FAIL",
665 "BriefDescription": "Non-TM Load caused any thread to fail"
666 },
667 {,
668 "EventCode": "0x26084",
669 "EventName": "PM_L2_RCLD_DISP_FAIL_OTHER",
670 "BriefDescription": "All I-or-D side load dispatch attempts for this thread that failed due to reason other than address collision (excludes i_l2mru_tch_reqs)"
671 },
672 {,
673 "EventCode": "0x101E4",
674 "EventName": "PM_MRK_L1_ICACHE_MISS",
675 "BriefDescription": "sampled Instruction suffered an icache Miss"
676 },
677 {,
678 "EventCode": "0x20A0",
679 "EventName": "PM_TM_NESTED_TBEGIN",
680 "BriefDescription": "Completion Tm nested tbegin"
681 },
682 {,
683 "EventCode": "0x368AA",
684 "EventName": "PM_L3_P1_CO_MEM",
685 "BriefDescription": "L3 CO to memory port 1 with or without data"
686 },
687 {,
688 "EventCode": "0xC8A4",
689 "EventName": "PM_LSU3_FALSE_LHS",
690 "BriefDescription": "False LHS match detected"
691 },
692 {,
693 "EventCode": "0xD9A4",
694 "EventName": "PM_MRK_LSU_FLUSH_LARX_STCX",
695 "BriefDescription": "A larx is flushed because an older larx has an LMQ reservation for the same thread. A stcx is flushed because an older stcx is in the LMQ. The flush happens when the older larx/stcx relaunches"
696 },
697 {,
698 "EventCode": "0x4D012",
699 "EventName": "PM_PMC3_SAVED",
700 "BriefDescription": "PMC3 Rewind Value saved"
701 },
702 {,
703 "EventCode": "0xE888",
704 "EventName": "PM_LS3_ERAT_MISS_PREF",
705 "BriefDescription": "LS1 Erat miss due to prefetch"
706 },
707 {,
708 "EventCode": "0x368B4",
709 "EventName": "PM_L3_RD0_BUSY",
710 "BriefDescription": "Lifetime, sample of RD machine 0 valid"
711 },
712 {,
713 "EventCode": "0x46080",
714 "EventName": "PM_L2_DISP_ALL_L2MISS",
715 "BriefDescription": "All successful Ld/St dispatches for this thread that were an L2 miss (excludes i_l2mru_tch_reqs)"
716 },
717 {,
718 "EventCode": "0xF8B8",
719 "EventName": "PM_LS1_UNALIGNED_ST",
720 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
721 },
722 {,
723 "EventCode": "0x408C",
724 "EventName": "PM_L1_DEMAND_WRITE",
725 "BriefDescription": "Instruction Demand sectors written into IL1"
726 },
727 {,
728 "EventCode": "0x368A8",
729 "EventName": "PM_SN_INVL",
730 "BriefDescription": "Any port snooper detects a store to a line in the Sx state and invalidates the line. Up to 4 can happen in a cycle but we only count 1"
731 },
732 {,
733 "EventCode": "0x160B2",
734 "EventName": "PM_L3_LOC_GUESS_CORRECT",
735 "BriefDescription": "initial scope=node/chip (LNS) and data from local node (local) (pred successful) - always PFs only"
736 },
737 {,
738 "EventCode": "0x48B4",
739 "EventName": "PM_DECODE_FUSION_CONST_GEN",
740 "BriefDescription": "32-bit constant generation"
741 },
742 {,
743 "EventCode": "0x4D146",
744 "EventName": "PM_MRK_DATA_FROM_L21_MOD",
745 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L2 on the same chip due to a marked load"
746 },
747 {,
748 "EventCode": "0xE080",
749 "EventName": "PM_S2Q_FULL",
750 "BriefDescription": "Cycles during which the S2Q is full"
751 },
752 {,
753 "EventCode": "0x268B4",
754 "EventName": "PM_L3_P3_LCO_RTY",
755 "BriefDescription": "L3 initiated LCO received retry on port 3 (can try 4 times)"
756 },
757 {,
758 "EventCode": "0xD8B8",
759 "EventName": "PM_LSU0_LMQ_S0_VALID",
760 "BriefDescription": "Slot 0 of LMQ valid"
761 },
762 {,
763 "EventCode": "0x2098",
764 "EventName": "PM_TM_NESTED_TEND",
765 "BriefDescription": "Completion time nested tend"
766 },
767 {,
768 "EventCode": "0x36084",
769 "EventName": "PM_L2_RCST_DISP",
770 "BriefDescription": "All D-side store dispatch attempts for this thread"
771 },
772 {,
773 "EventCode": "0x368A0",
774 "EventName": "PM_L3_PF_OFF_CHIP_CACHE",
775 "BriefDescription": "L3 PF from Off chip cache"
776 },
777 {,
778 "EventCode": "0x20056",
779 "EventName": "PM_TAKEN_BR_MPRED_CMPL",
780 "BriefDescription": "Total number of taken branches that were incorrectly predicted as not-taken. This event counts branches completed and does not include speculative instructions"
781 },
782 {,
783 "EventCode": "0x4688A",
784 "EventName": "PM_L2_SYS_PUMP",
785 "BriefDescription": "RC requests that were system pump attempts"
786 },
787 {,
788 "EventCode": "0xE090",
789 "EventName": "PM_LSU2_ERAT_HIT",
790 "BriefDescription": "Primary ERAT hit. There is no secondary ERAT"
791 },
792 {,
793 "EventCode": "0x4001C",
794 "EventName": "PM_INST_IMC_MATCH_CMPL",
795 "BriefDescription": "IMC Match Count"
796 },
797 {,
798 "EventCode": "0x40A8",
799 "EventName": "PM_BR_PRED_LSTACK",
800 "BriefDescription": "Conditional Branch Completed that used the Link Stack for Target Prediction"
801 },
802 {,
803 "EventCode": "0x268A2",
804 "EventName": "PM_L3_CI_MISS",
805 "BriefDescription": "L3 castins miss (total count)"
806 },
807 {,
808 "EventCode": "0x289C",
809 "EventName": "PM_TM_NON_FAV_TBEGIN",
810 "BriefDescription": "Dispatch time non favored tbegin"
811 },
812 {,
813 "EventCode": "0xF08C",
814 "EventName": "PM_LSU2_STORE_REJECT",
815 "BriefDescription": "All internal store rejects cause the instruction to go back to the SRQ and go to sleep until woken up to try again after the condition has been met"
816 },
817 {,
818 "EventCode": "0x360A0",
819 "EventName": "PM_L3_PF_ON_CHIP_CACHE",
820 "BriefDescription": "L3 PF from On chip cache"
821 },
822 {,
823 "EventCode": "0x35152",
824 "EventName": "PM_MRK_DATA_FROM_L2MISS_CYC",
825 "BriefDescription": "Duration in cycles to reload from a location other than the local core's L2 due to a marked load"
826 },
827 {,
828 "EventCode": "0x160AC",
829 "EventName": "PM_L3_SN_USAGE",
830 "BriefDescription": "Rotating sample of 16 snoop valids"
831 },
832 {,
833 "EventCode": "0x16084",
834 "EventName": "PM_L2_RCLD_DISP",
835 "BriefDescription": "All I-or-D side load dispatch attempts for this thread (excludes i_l2mru_tch_reqs)"
836 },
837 {,
838 "EventCode": "0x1608C",
839 "EventName": "PM_RC0_BUSY",
840 "BriefDescription": "RC mach 0 Busy. Used by PMU to sample ave RC lifetime (mach0 used as sample point)"
841 },
842 {,
843 "EventCode": "0x36082",
844 "EventName": "PM_L2_LD_DISP",
845 "BriefDescription": "All successful I-or-D side load dispatches for this thread (excludes i_l2mru_tch_reqs)."
846 },
847 {,
848 "EventCode": "0xF8B0",
849 "EventName": "PM_L3_SW_PREF",
850 "BriefDescription": "L3 load prefetch, sourced from a software prefetch stream, was sent to the nest"
851 },
852 {,
853 "EventCode": "0xF884",
854 "EventName": "PM_TABLEWALK_CYC_PREF",
855 "BriefDescription": "tablewalk qualified for pte prefetches"
856 },
857 {,
858 "EventCode": "0x4D144",
859 "EventName": "PM_MRK_DATA_FROM_L31_ECO_MOD",
860 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to a marked load"
861 },
862 {,
863 "EventCode": "0x16884",
864 "EventName": "PM_L2_RCLD_DISP_FAIL_ADDR",
865 "BriefDescription": "All I-od-D side load dispatch attempts for this thread that failed due to address collision with RC/CO/SN/SQ machine (excludes i_l2mru_tch_reqs)"
866 },
867 {,
868 "EventCode": "0x460A0",
869 "EventName": "PM_L3_PF_ON_CHIP_MEM",
870 "BriefDescription": "L3 PF from On chip memory"
871 },
872 {,
873 "EventCode": "0xF084",
874 "EventName": "PM_PTE_PREFETCH",
875 "BriefDescription": "PTE prefetches"
876 },
877 {,
878 "EventCode": "0x2D026",
879 "EventName": "PM_RADIX_PWC_L1_PDE_FROM_L2",
880 "BriefDescription": "A Page Directory Entry was reloaded to a level 1 page walk cache from the core's L2 data cache"
881 },
882 {,
883 "EventCode": "0x48B0",
884 "EventName": "PM_BR_MPRED_PCACHE",
885 "BriefDescription": "Conditional Branch Completed that was Mispredicted due to pattern cache prediction"
886 },
887 {,
888 "EventCode": "0x2C126",
889 "EventName": "PM_MRK_DATA_FROM_L2",
890 "BriefDescription": "The processor's data cache was reloaded from local core's L2 due to a marked load"
891 },
892 {,
893 "EventCode": "0xE0AC",
894 "EventName": "PM_TM_FAIL_TLBIE",
895 "BriefDescription": "Transaction failed because there was a TLBIE hit in the bloom filter"
896 },
897 {,
898 "EventCode": "0x260AA",
899 "EventName": "PM_L3_P0_LCO_DATA",
900 "BriefDescription": "LCO sent with data port 0"
901 },
902 {,
903 "EventCode": "0x4888",
904 "EventName": "PM_IC_PREF_REQ",
905 "BriefDescription": "Instruction prefetch requests"
906 },
907 {,
908 "EventCode": "0xC898",
909 "EventName": "PM_LS3_UNALIGNED_LD",
910 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
911 },
912 {,
913 "EventCode": "0x488C",
914 "EventName": "PM_IC_PREF_WRITE",
915 "BriefDescription": "Instruction prefetch written into IL1"
916 },
917 {,
918 "EventCode": "0xF89C",
919 "EventName": "PM_XLATE_MISS",
920 "BriefDescription": "The LSU requested a line from L2 for translation. It may be satisfied from any source beyond L2. Includes speculative instructions"
921 },
922 {,
923 "EventCode": "0x14158",
924 "EventName": "PM_MRK_DATA_FROM_L2_NO_CONFLICT_CYC",
925 "BriefDescription": "Duration in cycles to reload from local core's L2 without conflict due to a marked load"
926 },
927 {,
928 "EventCode": "0x35156",
929 "EventName": "PM_MRK_DATA_FROM_L31_SHR_CYC",
930 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L3 on the same chip due to a marked load"
931 },
932 {,
933 "EventCode": "0x268A6",
934 "EventName": "PM_TM_RST_SC",
935 "BriefDescription": "TM-snp rst RM SC"
936 },
937 {,
938 "EventCode": "0x468A4",
939 "EventName": "PM_L3_TRANS_PF",
940 "BriefDescription": "L3 Transient prefetch received from L2"
941 },
942 {,
943 "EventCode": "0x4094",
944 "EventName": "PM_IC_PREF_CANCEL_L2",
945 "BriefDescription": "L2 Squashed a demand or prefetch request"
946 },
947 {,
948 "EventCode": "0x48AC",
949 "EventName": "PM_BR_MPRED_LSTACK",
950 "BriefDescription": "Conditional Branch Completed that was Mispredicted due to the Link Stack Target Prediction"
951 },
952 {,
953 "EventCode": "0xE88C",
954 "EventName": "PM_LSU1_ERAT_HIT",
955 "BriefDescription": "Primary ERAT hit. There is no secondary ERAT"
956 },
957 {,
958 "EventCode": "0xC0B4",
959 "EventName": "PM_LSU_FLUSH_WRK_ARND",
960 "BriefDescription": "LSU workaround flush. These flushes are setup with programmable scan only latches to perform various actions when the flush macro receives a trigger from the dbg macros. These actions include things like flushing the next op encountered for a particular thread or flushing the next op that is NTC op that is encountered on a particular slice. The kind of flush that the workaround is setup to perform is highly variable."
961 },
962 {,
963 "EventCode": "0x34054",
964 "EventName": "PM_PARTIAL_ST_FIN",
965 "BriefDescription": "Any store finished by an LSU slice"
966 },
967 {,
968 "EventCode": "0x5880",
969 "EventName": "PM_THRD_PRIO_6_7_CYC",
970 "BriefDescription": "Cycles thread running at priority level 6 or 7"
971 },
972 {,
973 "EventCode": "0x4898",
974 "EventName": "PM_IC_DEMAND_L2_BR_REDIRECT",
975 "BriefDescription": "L2 I cache demand request due to branch Mispredict ( 15 cycle path)"
976 },
977 {,
978 "EventCode": "0x4880",
979 "EventName": "PM_BANK_CONFLICT",
980 "BriefDescription": "Read blocked due to interleave conflict. The ifar logic will detect an interleave conflict and kill the data that was read that cycle."
981 },
982 {,
983 "EventCode": "0x360B0",
984 "EventName": "PM_L3_P0_SYS_PUMP",
985 "BriefDescription": "L3 PF sent with sys scope port 0, counts even retried requests"
986 },
987 {,
988 "EventCode": "0x3006A",
989 "EventName": "PM_IERAT_RELOAD_64K",
990 "BriefDescription": "IERAT Reloaded (Miss) for a 64k page"
991 },
992 {,
993 "EventCode": "0xD8BC",
994 "EventName": "PM_LSU2_3_LRQF_FULL_CYC",
995 "BriefDescription": "Counts the number of cycles the LRQF is full. LRQF is the queue that holds loads between finish and completion. If it fills up, instructions stay in LRQ until completion, potentially backing up the LRQ"
996 },
997 {,
998 "EventCode": "0x46086",
999 "EventName": "PM_L2_SN_M_RD_DONE",
1000 "BriefDescription": "SNP dispatched for a read and was M (true M)"
1001 },
1002 {,
1003 "EventCode": "0x40154",
1004 "EventName": "PM_MRK_FAB_RSP_BKILL",
1005 "BriefDescription": "Marked store had to do a bkill"
1006 },
1007 {,
1008 "EventCode": "0xF094",
1009 "EventName": "PM_LSU2_L1_CAM_CANCEL",
1010 "BriefDescription": "ls2 l1 tm cam cancel"
1011 },
1012 {,
1013 "EventCode": "0x2D014",
1014 "EventName": "PM_CMPLU_STALL_LRQ_FULL",
1015 "BriefDescription": "Finish stall because the NTF instruction was a load that was held in LSAQ (load-store address queue) because the LRQ (load-reorder queue) was full"
1016 },
1017 {,
1018 "EventCode": "0x3E05E",
1019 "EventName": "PM_L3_CO_MEPF",
1020 "BriefDescription": "L3 castouts in Mepf state for this thread"
1021 },
1022 {,
1023 "EventCode": "0x460A2",
1024 "EventName": "PM_L3_LAT_CI_HIT",
1025 "BriefDescription": "L3 Lateral Castins Hit"
1026 },
1027 {,
1028 "EventCode": "0x3D14E",
1029 "EventName": "PM_MRK_DATA_FROM_DL2L3_MOD",
1030 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a marked load"
1031 },
1032 {,
1033 "EventCode": "0x3D15E",
1034 "EventName": "PM_MULT_MRK",
1035 "BriefDescription": "mult marked instr"
1036 },
1037 {,
1038 "EventCode": "0x4084",
1039 "EventName": "PM_EAT_FULL_CYC",
1040 "BriefDescription": "Cycles No room in EAT"
1041 },
1042 {,
1043 "EventCode": "0x5098",
1044 "EventName": "PM_LINK_STACK_WRONG_ADD_PRED",
1045 "BriefDescription": "Link stack predicts wrong address, because of link stack design limitation or software violating the coding conventions"
1046 },
1047 {,
1048 "EventCode": "0x2C050",
1049 "EventName": "PM_DATA_GRP_PUMP_CPRED",
1050 "BriefDescription": "Initial and Final Pump Scope was group pump (prediction=correct) for a demand load"
1051 },
1052 {,
1053 "EventCode": "0xC0A4",
1054 "EventName": "PM_LSU2_FALSE_LHS",
1055 "BriefDescription": "False LHS match detected"
1056 },
1057 {,
1058 "EventCode": "0x58A0",
1059 "EventName": "PM_LINK_STACK_CORRECT",
1060 "BriefDescription": "Link stack predicts right address"
1061 },
1062 {,
1063 "EventCode": "0x4C05A",
1064 "EventName": "PM_DTLB_MISS_1G",
1065 "BriefDescription": "Data TLB reload (after a miss) page size 1G. Implies radix translation was used"
1066 },
1067 {,
1068 "EventCode": "0x36886",
1069 "EventName": "PM_L2_SN_SX_I_DONE",
1070 "BriefDescription": "SNP dispatched and went from Sx to Ix"
1071 },
1072 {,
1073 "EventCode": "0x4E04A",
1074 "EventName": "PM_DPTEG_FROM_OFF_CHIP_CACHE",
1075 "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
1076 },
1077 {,
1078 "EventCode": "0x2C12C",
1079 "EventName": "PM_MRK_DATA_FROM_DL4_CYC",
1080 "BriefDescription": "Duration in cycles to reload from another chip's L4 on a different Node or Group (Distant) due to a marked load"
1081 },
1082 {,
1083 "EventCode": "0x2608E",
1084 "EventName": "PM_TM_LD_CONF",
1085 "BriefDescription": "TM Load (fav or non-fav) ran into conflict (failed)"
1086 },
1087 {,
1088 "EventCode": "0x4080",
1089 "EventName": "PM_INST_FROM_L1",
1090 "BriefDescription": "Instruction fetches from L1. L1 instruction hit"
1091 },
1092 {,
1093 "EventCode": "0xE898",
1094 "EventName": "PM_LSU3_TM_L1_HIT",
1095 "BriefDescription": "Load tm hit in L1"
1096 },
1097 {,
1098 "EventCode": "0x260A0",
1099 "EventName": "PM_L3_CO_MEM",
1100 "BriefDescription": "L3 CO to memory OR of port 0 and 1 (lossy = may undercount if two cresp come in the same cyc)"
1101 },
1102 {,
1103 "EventCode": "0x16082",
1104 "EventName": "PM_L2_CASTOUT_MOD",
1105 "BriefDescription": "L2 Castouts - Modified (M,Mu,Me)"
1106 },
1107 {,
1108 "EventCode": "0xC09C",
1109 "EventName": "PM_LS0_LAUNCH_HELD_PREF",
1110 "BriefDescription": "Number of times a load or store instruction was unable to launch/relaunch because a high priority prefetch used that relaunch cycle"
1111 },
1112 {,
1113 "EventCode": "0xC8B8",
1114 "EventName": "PM_LSU_FLUSH_LARX_STCX",
1115 "BriefDescription": "A larx is flushed because an older larx has an LMQ reservation for the same thread. A stcx is flushed because an older stcx is in the LMQ. The flush happens when the older larx/stcx relaunches"
1116 },
1117 {,
1118 "EventCode": "0x260A6",
1119 "EventName": "PM_NON_TM_RST_SC",
1120 "BriefDescription": "Non-TM snp rst TM SC"
1121 },
1122 {,
1123 "EventCode": "0x3608A",
1124 "EventName": "PM_L2_RTY_ST",
1125 "BriefDescription": "RC retries on PB for any store from core (excludes DCBFs)"
1126 },
1127 {,
1128 "EventCode": "0x24040",
1129 "EventName": "PM_INST_FROM_L2_MEPF",
1130 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state. due to an instruction fetch (not prefetch)"
1131 },
1132 {,
1133 "EventCode": "0x209C",
1134 "EventName": "PM_TM_FAV_TBEGIN",
1135 "BriefDescription": "Dispatch time Favored tbegin"
1136 },
1137 {,
1138 "EventCode": "0x2D01E",
1139 "EventName": "PM_ICT_NOSLOT_DISP_HELD_ISSQ",
1140 "BriefDescription": "Ict empty for this thread due to dispatch hold on this thread due to Issue q full, BRQ full, XVCF Full, Count cache, Link, Tar full"
1141 },
1142 {,
1143 "EventCode": "0x50A4",
1144 "EventName": "PM_FLUSH_MPRED",
1145 "BriefDescription": "Branch mispredict flushes. Includes target and address misprecition"
1146 },
1147 {,
1148 "EventCode": "0x508C",
1149 "EventName": "PM_SHL_CREATED",
1150 "BriefDescription": "Store-Hit-Load Table Entry Created"
1151 },
1152 {,
1153 "EventCode": "0x1504C",
1154 "EventName": "PM_IPTEG_FROM_LL4",
1155 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's L4 cache due to a instruction side request"
1156 },
1157 {,
1158 "EventCode": "0x268A4",
1159 "EventName": "PM_L3_LD_MISS",
1160 "BriefDescription": "L3 Misses for demand LDs"
1161 },
1162 {,
1163 "EventCode": "0x26088",
1164 "EventName": "PM_L2_GRP_GUESS_CORRECT",
1165 "BriefDescription": "L2 guess grp (GS or NNS) and guess was correct (data intra-group AND ^on-chip)"
1166 },
1167 {,
1168 "EventCode": "0xD088",
1169 "EventName": "PM_LSU0_LDMX_FIN",
1170 "BriefDescription": "New P9 instruction LDMX. The definition of this new PMU event is (from the ldmx RFC02491): The thread has executed an ldmx instruction that accessed a doubleword that contains an effective address within an enabled section of the Load Monitored region. This event, therefore, should not occur if the FSCR has disabled the load monitored facility (FSCR[52]) or disabled the EBB facility (FSCR[56])."
1171 },
1172 {,
1173 "EventCode": "0xE8B4",
1174 "EventName": "PM_LS1_TM_DISALLOW",
1175 "BriefDescription": "A TM-ineligible instruction tries to execute inside a transaction and the LSU disallows it"
1176 },
1177 {,
1178 "EventCode": "0x1688C",
1179 "EventName": "PM_RC_USAGE",
1180 "BriefDescription": "Continuous 16 cycle (2to1) window where this signals rotates thru sampling each RC machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running"
1181 },
1182 {,
1183 "EventCode": "0x3F054",
1184 "EventName": "PM_RADIX_PWC_L4_PTE_FROM_L3MISS",
1185 "BriefDescription": "A Page Table Entry was reloaded to a level 4 page walk cache from beyond the core's L3 data cache. This is the deepest level of PWC possible for a translation. The source could be local/remote/distant memory or another core's cache"
1186 },
1187 {,
1188 "EventCode": "0x2608A",
1189 "EventName": "PM_ISIDE_DISP_FAIL_ADDR",
1190 "BriefDescription": "All I-side dispatch attempts for this thread that failed due to a addr collision with another machine (excludes i_l2mru_tch_reqs)"
1191 },
1192 {,
1193 "EventCode": "0x50B4",
1194 "EventName": "PM_TAGE_CORRECT_TAKEN_CMPL",
1195 "BriefDescription": "The TAGE overrode BHT direction prediction and it was correct. Counted at completion for taken branches only"
1196 },
1197 {,
1198 "EventCode": "0x2090",
1199 "EventName": "PM_DISP_CLB_HELD_SB",
1200 "BriefDescription": "Dispatch/CLB Hold: Scoreboard"
1201 },
1202 {,
1203 "EventCode": "0xE0B0",
1204 "EventName": "PM_TM_FAIL_NON_TX_CONFLICT",
1205 "BriefDescription": "Non transactional conflict from LSU, gets reported to TEXASR"
1206 },
1207 {,
1208 "EventCode": "0xD198",
1209 "EventName": "PM_MRK_LSU_FLUSH_ATOMIC",
1210 "BriefDescription": "Quad-word loads (lq) are considered atomic because they always span at least 2 slices. If a snoop or store from another thread changes the data the load is accessing between the 2 or 3 pieces of the lq instruction, the lq will be flushed"
1211 },
1212 {,
1213 "EventCode": "0x201E0",
1214 "EventName": "PM_MRK_DATA_FROM_MEMORY",
1215 "BriefDescription": "The processor's data cache was reloaded from a memory location including L4 from local remote or distant due to a marked load"
1216 },
1217 {,
1218 "EventCode": "0x368A2",
1219 "EventName": "PM_L3_L2_CO_MISS",
1220 "BriefDescription": "L2 CO miss"
1221 },
1222 {,
1223 "EventCode": "0x3608C",
1224 "EventName": "PM_CO0_BUSY",
1225 "BriefDescription": "CO mach 0 Busy. Used by PMU to sample ave CO lifetime (mach0 used as sample point)"
1226 },
1227 {,
1228 "EventCode": "0x2C122",
1229 "EventName": "PM_MRK_DATA_FROM_L3_DISP_CONFLICT_CYC",
1230 "BriefDescription": "Duration in cycles to reload from local core's L3 with dispatch conflict due to a marked load"
1231 },
1232 {,
1233 "EventCode": "0x35154",
1234 "EventName": "PM_MRK_DATA_FROM_L3_CYC",
1235 "BriefDescription": "Duration in cycles to reload from local core's L3 due to a marked load"
1236 },
1237 {,
1238 "EventCode": "0x1D140",
1239 "EventName": "PM_MRK_DATA_FROM_L31_MOD_CYC",
1240 "BriefDescription": "Duration in cycles to reload with Modified (M) data from another core's L3 on the same chip due to a marked load"
1241 },
1242 {,
1243 "EventCode": "0x4404A",
1244 "EventName": "PM_INST_FROM_OFF_CHIP_CACHE",
1245 "BriefDescription": "The processor's Instruction cache was reloaded either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to an instruction fetch (not prefetch)"
1246 },
1247 {,
1248 "EventCode": "0x28AC",
1249 "EventName": "PM_TM_FAIL_SELF",
1250 "BriefDescription": "TM aborted because a self-induced conflict occurred in Suspended state, due to one of the following: a store to a storage location that was previously accessed transactionally; a dcbf, dcbi, or icbi specify- ing a block that was previously accessed transactionally; a dcbst specifying a block that was previously written transactionally; or a tlbie that specifies a translation that was pre- viously used transactionally"
1251 },
1252 {,
1253 "EventCode": "0x45056",
1254 "EventName": "PM_SCALAR_FLOP_CMPL",
1255 "BriefDescription": "Scalar flop operation completed"
1256 },
1257 {,
1258 "EventCode": "0x16092",
1259 "EventName": "PM_L2_LD_MISS_128B",
1260 "BriefDescription": "All successful D-side load dispatches that were an L2 miss (NOT Sx,Tx,Mx) for this thread and the RC calculated the request should be for 128B (i.e., M=0)"
1261 },
1262 {,
1263 "EventCode": "0x2E014",
1264 "EventName": "PM_STCX_FIN",
1265 "BriefDescription": "Number of stcx instructions finished. This includes instructions in the speculative path of a branch that may be flushed"
1266 },
1267 {,
1268 "EventCode": "0xE0B8",
1269 "EventName": "PM_LS2_TM_DISALLOW",
1270 "BriefDescription": "A TM-ineligible instruction tries to execute inside a transaction and the LSU disallows it"
1271 },
1272 {,
1273 "EventCode": "0x2094",
1274 "EventName": "PM_TM_OUTER_TBEGIN",
1275 "BriefDescription": "Completion time outer tbegin"
1276 },
1277 {,
1278 "EventCode": "0x160B4",
1279 "EventName": "PM_L3_P0_LCO_RTY",
1280 "BriefDescription": "L3 initiated LCO received retry on port 0 (can try 4 times)"
1281 },
1282 {,
1283 "EventCode": "0x36892",
1284 "EventName": "PM_DSIDE_OTHER_64B_L2MEMACC",
1285 "BriefDescription": "Valid when first beat of data comes in for an D-side fetch where data came EXCLUSIVELY from memory that was for hpc_read64, (RC had to fetch other 64B of a line from MC) i.e., number of times RC had to go to memory to get 'missing' 64B"
1286 },
1287 {,
1288 "EventCode": "0x20A8",
1289 "EventName": "PM_TM_FAIL_FOOTPRINT_OVERFLOW",
1290 "BriefDescription": "TM aborted because the tracking limit for transactional storage accesses was exceeded.. Asynchronous"
1291 },
1292 {,
1293 "EventCode": "0x30018",
1294 "EventName": "PM_ICT_NOSLOT_DISP_HELD_HB_FULL",
1295 "BriefDescription": "Ict empty for this thread due to dispatch holds because the History Buffer was full. Could be GPR/VSR/VMR/FPR/CR/XVF; CR; XVF (XER/VSCR/FPSCR)"
1296 },
1297 {,
1298 "EventCode": "0xC894",
1299 "EventName": "PM_LS1_UNALIGNED_LD",
1300 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
1301 },
1302 {,
1303 "EventCode": "0x360A2",
1304 "EventName": "PM_L3_L2_CO_HIT",
1305 "BriefDescription": "L2 CO hits"
1306 },
1307 {,
1308 "EventCode": "0x36092",
1309 "EventName": "PM_DSIDE_L2MEMACC",
1310 "BriefDescription": "Valid when first beat of data comes in for an D-side fetch where data came EXCLUSIVELY from memory (excluding hpcread64 accesses), i.e., total memory accesses by RCs"
1311 },
1312 {,
1313 "EventCode": "0x10138",
1314 "EventName": "PM_MRK_BR_2PATH",
1315 "BriefDescription": "marked branches which are not strongly biased"
1316 },
1317 {,
1318 "EventCode": "0x2884",
1319 "EventName": "PM_ISYNC",
1320 "BriefDescription": "Isync completion count per thread"
1321 },
1322 {,
1323 "EventCode": "0x16882",
1324 "EventName": "PM_L2_CASTOUT_SHR",
1325 "BriefDescription": "L2 Castouts - Shared (Tx,Sx)"
1326 },
1327 {,
1328 "EventCode": "0xD884",
1329 "EventName": "PM_LSU3_SET_MPRED",
1330 "BriefDescription": "Set prediction(set-p) miss. The entry was not found in the Set prediction table"
1331 },
1332 {,
1333 "EventCode": "0x26092",
1334 "EventName": "PM_L2_LD_MISS_64B",
1335 "BriefDescription": "All successful D-side load dispatches that were an L2 miss (NOT Sx,Tx,Mx) for this thread and the RC calculated the request should be for 64B(i.e., M=1)"
1336 },
1337 {,
1338 "EventCode": "0x26080",
1339 "EventName": "PM_L2_LD_MISS",
1340 "BriefDescription": "All successful D-Side Load dispatches that were an L2 miss for this thread"
1341 },
1342 {,
1343 "EventCode": "0x3D14C",
1344 "EventName": "PM_MRK_DATA_FROM_DMEM",
1345 "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to a marked load"
1346 },
1347 {,
1348 "EventCode": "0x100FA",
1349 "EventName": "PM_ANY_THRD_RUN_CYC",
1350 "BriefDescription": "Cycles in which at least one thread has the run latch set"
1351 },
1352 {,
1353 "EventCode": "0x2C12A",
1354 "EventName": "PM_MRK_DATA_FROM_RMEM_CYC",
1355 "BriefDescription": "Duration in cycles to reload from another chip's memory on the same Node or Group ( Remote) due to a marked load"
1356 },
1357 {,
1358 "EventCode": "0x25048",
1359 "EventName": "PM_IPTEG_FROM_LMEM",
1360 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's Memory due to a instruction side request"
1361 },
1362 {,
1363 "EventCode": "0xD8A8",
1364 "EventName": "PM_ISLB_MISS",
1365 "BriefDescription": "Instruction SLB miss - Total of all segment sizes"
1366 },
1367 {,
1368 "EventCode": "0xD19C",
1369 "EventName": "PM_MRK_LSU_FLUSH_RELAUNCH_MISS",
1370 "BriefDescription": "If a load that has already returned data and has to relaunch for any reason then gets a miss (erat, setp, data cache), it will often be flushed at relaunch time because the data might be inconsistent"
1371 },
1372 {,
1373 "EventCode": "0x260A2",
1374 "EventName": "PM_L3_CI_HIT",
1375 "BriefDescription": "L3 Castins Hit (total count)"
1376 },
1377 {,
1378 "EventCode": "0x44054",
1379 "EventName": "PM_VECTOR_LD_CMPL",
1380 "BriefDescription": "Number of vector load instructions completed"
1381 },
1382 {,
1383 "EventCode": "0x1E05C",
1384 "EventName": "PM_CMPLU_STALL_NESTED_TBEGIN",
1385 "BriefDescription": "Completion stall because the ISU is updating the TEXASR to keep track of the nested tbegin. This is a short delay, and it includes ROT"
1386 },
1387 {,
1388 "EventCode": "0x1608E",
1389 "EventName": "PM_ST_CAUSED_FAIL",
1390 "BriefDescription": "Non-TM Store caused any thread to fail"
1391 },
1392 {,
1393 "EventCode": "0x3080",
1394 "EventName": "PM_ISU0_ISS_HOLD_ALL",
1395 "BriefDescription": "All ISU rejects"
1396 },
1397 {,
1398 "EventCode": "0x1515A",
1399 "EventName": "PM_SYNC_MRK_L2MISS",
1400 "BriefDescription": "Marked L2 Miss that can throw a synchronous interrupt"
1401 },
1402 {,
1403 "EventCode": "0x26892",
1404 "EventName": "PM_L2_ST_MISS_64B",
1405 "BriefDescription": "All successful D-side store dispatches that were an L2 miss (NOT Sx,Tx,Mx) for this thread and the RC calculated the request should be for 64B (i.e., M=1)"
1406 },
1407 {,
1408 "EventCode": "0x2688C",
1409 "EventName": "PM_CO_USAGE",
1410 "BriefDescription": "Continuous 16 cycle (2to1) window where this signals rotates thru sampling each CO machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running"
1411 },
1412 {,
1413 "EventCode": "0xD084",
1414 "EventName": "PM_LSU2_SET_MPRED",
1415 "BriefDescription": "Set prediction(set-p) miss. The entry was not found in the Set prediction table"
1416 },
1417 {,
1418 "EventCode": "0x48B8",
1419 "EventName": "PM_BR_MPRED_TAKEN_TA",
1420 "BriefDescription": "Conditional Branch Completed that was Mispredicted due to the Target Address Prediction from the Count Cache or Link Stack. Only XL-form branches that resolved Taken set this event."
1421 },
1422 {,
1423 "EventCode": "0x50B0",
1424 "EventName": "PM_BTAC_BAD_RESULT",
1425 "BriefDescription": "BTAC thinks branch will be taken but it is either predicted not-taken by the BHT, or the target address is wrong (less common). In both cases, a redirect will happen"
1426 },
1427 {,
1428 "EventCode": "0xD888",
1429 "EventName": "PM_LSU1_LDMX_FIN",
1430 "BriefDescription": "New P9 instruction LDMX. The definition of this new PMU event is (from the ldmx RFC02491): The thread has executed an ldmx instruction that accessed a doubleword that contains an effective address within an enabled section of the Load Monitored region. This event, therefore, should not occur if the FSCR has disabled the load monitored facility (FSCR[52]) or disabled the EBB facility (FSCR[56])."
1431 },
1432 {,
1433 "EventCode": "0x58B4",
1434 "EventName": "PM_TAGE_CORRECT",
1435 "BriefDescription": "The TAGE overrode BHT direction prediction and it was correct. Includes taken and not taken and is counted at execution time"
1436 },
1437 {,
1438 "EventCode": "0x3688C",
1439 "EventName": "PM_SN_USAGE",
1440 "BriefDescription": "Continuous 16 cycle (2to1) window where this signals rotates thru sampling each SN machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running"
1441 },
1442 {,
1443 "EventCode": "0x46084",
1444 "EventName": "PM_L2_RCST_DISP_FAIL_OTHER",
1445 "BriefDescription": "All D-side store dispatch attempts for this thread that failed due to reason other than address collision"
1446 },
1447 {,
1448 "EventCode": "0xF0AC",
1449 "EventName": "PM_DC_PREF_STRIDED_CONF",
1450 "BriefDescription": "A demand load referenced a line in an active strided prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software."
1451 },
1452 {,
1453 "EventCode": "0x45054",
1454 "EventName": "PM_FMA_CMPL",
1455 "BriefDescription": "two flops operation completed (fmadd, fnmadd, fmsub, fnmsub) Scalar instructions only. "
1456 },
1457 {,
1458 "EventCode": "0x5090",
1459 "EventName": "PM_SHL_ST_DISABLE",
1460 "BriefDescription": "Store-Hit-Load Table Read Hit with entry Disabled (entry was disabled due to the entry shown to not prevent the flush)"
1461 },
1462 {,
1463 "EventCode": "0x201E8",
1464 "EventName": "PM_THRESH_EXC_512",
1465 "BriefDescription": "Threshold counter exceeded a value of 512"
1466 },
1467 {,
1468 "EventCode": "0x5084",
1469 "EventName": "PM_DECODE_FUSION_EXT_ADD",
1470 "BriefDescription": "32-bit extended addition"
1471 },
1472 {,
1473 "EventCode": "0x36080",
1474 "EventName": "PM_L2_INST",
1475 "BriefDescription": "All successful I-side dispatches for this thread (excludes i_l2mru_tch reqs)."
1476 },
1477 {,
1478 "EventCode": "0x3504C",
1479 "EventName": "PM_IPTEG_FROM_DL4",
1480 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on a different Node or Group (Distant) due to a instruction side request"
1481 },
1482 {,
1483 "EventCode": "0xD890",
1484 "EventName": "PM_LS1_DC_COLLISIONS",
1485 "BriefDescription": "Read-write data cache collisions"
1486 },
1487 {,
1488 "EventCode": "0x1688A",
1489 "EventName": "PM_ISIDE_DISP",
1490 "BriefDescription": "All I-side dispatch attempts for this thread (excludes i_l2mru_tch_reqs)"
1491 },
1492 {,
1493 "EventCode": "0x468AA",
1494 "EventName": "PM_L3_P1_CO_L31",
1495 "BriefDescription": "L3 CO to L3.1 (LCO) port 1 with or without data"
1496 },
1497 {,
1498 "EventCode": "0x28B0",
1499 "EventName": "PM_DISP_HELD_TBEGIN",
1500 "BriefDescription": "This outer tbegin transaction cannot be dispatched until the previous tend instruction completes"
1501 },
1502 {,
1503 "EventCode": "0xE8A0",
1504 "EventName": "PM_LSU3_TM_L1_MISS",
1505 "BriefDescription": "Load tm L1 miss"
1506 },
1507 {,
1508 "EventCode": "0x2C05E",
1509 "EventName": "PM_INST_GRP_PUMP_MPRED",
1510 "BriefDescription": "Final Pump Scope (Group) ended up either larger or smaller than Initial Pump Scope for an instruction fetch (demand only)"
1511 },
1512 {,
1513 "EventCode": "0xC8BC",
1514 "EventName": "PM_STCX_SUCCESS_CMPL",
1515 "BriefDescription": "Number of stcx instructions that completed successfully"
1516 },
1517 {,
1518 "EventCode": "0xE098",
1519 "EventName": "PM_LSU2_TM_L1_HIT",
1520 "BriefDescription": "Load tm hit in L1"
1521 },
1522 {,
1523 "EventCode": "0x44044",
1524 "EventName": "PM_INST_FROM_L31_ECO_MOD",
1525 "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to an instruction fetch (not prefetch)"
1526 },
1527 {,
1528 "EventCode": "0x16886",
1529 "EventName": "PM_CO_DISP_FAIL",
1530 "BriefDescription": "CO dispatch failed due to all CO machines being busy"
1531 },
1532 {,
1533 "EventCode": "0x3D146",
1534 "EventName": "PM_MRK_DATA_FROM_L3_NO_CONFLICT",
1535 "BriefDescription": "The processor's data cache was reloaded from local core's L3 without conflict due to a marked load"
1536 },
1537 {,
1538 "EventCode": "0x16892",
1539 "EventName": "PM_L2_ST_MISS_128B",
1540 "BriefDescription": "All successful D-side store dispatches that were an L2 miss (NOT Sx,Tx,Mx) for this thread and the RC calculated the request should be for 128B (i.e., M=0)"
1541 },
1542 {,
1543 "EventCode": "0x26890",
1544 "EventName": "PM_ISIDE_L2MEMACC",
1545 "BriefDescription": "Valid when first beat of data comes in for an I-side fetch where data came from memory"
1546 },
1547 {,
1548 "EventCode": "0xD094",
1549 "EventName": "PM_LS2_DC_COLLISIONS",
1550 "BriefDescription": "Read-write data cache collisions"
1551 },
1552 {,
1553 "EventCode": "0x3C05E",
1554 "EventName": "PM_MEM_RWITM",
1555 "BriefDescription": "Memory Read With Intent to Modify for this thread"
1556 },
1557 {,
1558 "EventCode": "0x26882",
1559 "EventName": "PM_L2_DC_INV",
1560 "BriefDescription": "D-cache invalidates sent over the reload bus to the core"
1561 },
1562 {,
1563 "EventCode": "0xC090",
1564 "EventName": "PM_LSU_STCX",
1565 "BriefDescription": "STCX sent to nest, i.e. total"
1566 },
1567 {,
1568 "EventCode": "0xD080",
1569 "EventName": "PM_LSU0_SET_MPRED",
1570 "BriefDescription": "Set prediction(set-p) miss. The entry was not found in the Set prediction table"
1571 },
1572 {,
1573 "EventCode": "0x2C120",
1574 "EventName": "PM_MRK_DATA_FROM_L2_NO_CONFLICT",
1575 "BriefDescription": "The processor's data cache was reloaded from local core's L2 without conflict due to a marked load"
1576 },
1577 {,
1578 "EventCode": "0x36086",
1579 "EventName": "PM_L2_RC_ST_DONE",
1580 "BriefDescription": "RC did store to line that was Tx or Sx"
1581 },
1582 {,
1583 "EventCode": "0xE8AC",
1584 "EventName": "PM_TM_FAIL_TX_CONFLICT",
1585 "BriefDescription": "Transactional conflict from LSU, gets reported to TEXASR"
1586 },
1587 {,
1588 "EventCode": "0x48A8",
1589 "EventName": "PM_DECODE_FUSION_LD_ST_DISP",
1590 "BriefDescription": "32-bit displacement D-form and 16-bit displacement X-form"
1591 },
1592 {,
1593 "EventCode": "0x3D144",
1594 "EventName": "PM_MRK_DATA_FROM_L2_MEPF_CYC",
1595 "BriefDescription": "Duration in cycles to reload from local core's L2 hit without dispatch conflicts on Mepf state. due to a marked load"
1596 },
1597 {,
1598 "EventCode": "0x44046",
1599 "EventName": "PM_INST_FROM_L21_MOD",
1600 "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's L2 on the same chip due to an instruction fetch (not prefetch)"
1601 },
1602 {,
1603 "EventCode": "0x40B0",
1604 "EventName": "PM_BR_PRED_TAKEN_CR",
1605 "BriefDescription": "Conditional Branch that had its direction predicted. I-form branches do not set this event. In addition, B-form branches which do not use the BHT do not set this event - these are branches with BO-field set to 'always taken' and branches"
1606 },
1607 {,
1608 "EventCode": "0x15040",
1609 "EventName": "PM_IPTEG_FROM_L2_NO_CONFLICT",
1610 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a instruction side request"
1611 },
1612 {,
1613 "EventCode": "0xD9A0",
1614 "EventName": "PM_MRK_LSU_FLUSH_LHL_SHL",
1615 "BriefDescription": "The instruction was flushed because of a sequential load/store consistency. If a load or store hits on an older load that has either been snooped (for loads) or has stale data (for stores)."
1616 },
1617 {,
1618 "EventCode": "0x35042",
1619 "EventName": "PM_IPTEG_FROM_L3_DISP_CONFLICT",
1620 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 with dispatch conflict due to a instruction side request"
1621 },
1622 {,
1623 "EventCode": "0xF898",
1624 "EventName": "PM_XLATE_RADIX_MODE",
1625 "BriefDescription": "LSU reports every cycle the thread is in radix translation mode (as opposed to HPT mode)"
1626 },
1627 {,
1628 "EventCode": "0x2D142",
1629 "EventName": "PM_MRK_DATA_FROM_L3_MEPF",
1630 "BriefDescription": "The processor's data cache was reloaded from local core's L3 without dispatch conflicts hit on Mepf state. due to a marked load"
1631 },
1632 {,
1633 "EventCode": "0x160B0",
1634 "EventName": "PM_L3_P0_NODE_PUMP",
1635 "BriefDescription": "L3 PF sent with nodal scope port 0, counts even retried requests"
1636 },
1637 {,
1638 "EventCode": "0xD88C",
1639 "EventName": "PM_LSU3_LDMX_FIN",
1640 "BriefDescription": "New P9 instruction LDMX. The definition of this new PMU event is (from the ldmx RFC02491): The thread has executed an ldmx instruction that accessed a doubleword that contains an effective address within an enabled section of the Load Monitored region. This event, therefore, should not occur if the FSCR has disabled the load monitored facility (FSCR[52]) or disabled the EBB facility (FSCR[56])."
1641 },
1642 {,
1643 "EventCode": "0x36882",
1644 "EventName": "PM_L2_LD_HIT",
1645 "BriefDescription": "All successful I-or-D side load dispatches for this thread that were L2 hits (excludes i_l2mru_tch_reqs)"
1646 },
1647 {,
1648 "EventCode": "0x168AC",
1649 "EventName": "PM_L3_CI_USAGE",
1650 "BriefDescription": "Rotating sample of 16 CI or CO actives"
1651 },
1652 {,
1653 "EventCode": "0x20134",
1654 "EventName": "PM_MRK_FXU_FIN",
1655 "BriefDescription": "fxu marked instr finish"
1656 },
1657 {,
1658 "EventCode": "0x4608E",
1659 "EventName": "PM_TM_CAP_OVERFLOW",
1660 "BriefDescription": "TM Footprint Capacity Overflow"
1661 },
1662 {,
1663 "EventCode": "0x4F05C",
1664 "EventName": "PM_RADIX_PWC_L2_PTE_FROM_L3MISS",
1665 "BriefDescription": "A Page Table Entry was reloaded to a level 2 page walk cache from beyond the core's L3 data cache. This implies that level 3 and level 4 PWC accesses were not necessary for this translation. The source could be local/remote/distant memory or another core's cache"
1666 },
1667 {,
1668 "EventCode": "0x40014",
1669 "EventName": "PM_PROBE_NOP_DISP",
1670 "BriefDescription": "ProbeNops dispatched"
1671 },
1672 {,
1673 "EventCode": "0x58A8",
1674 "EventName": "PM_DECODE_HOLD_ICT_FULL",
1675 "BriefDescription": "Counts the number of cycles in which the IFU was not able to decode and transmit one or more instructions because all itags were in use. This means the ICT is full for this thread"
1676 },
1677 {,
1678 "EventCode": "0x10052",
1679 "EventName": "PM_GRP_PUMP_MPRED_RTY",
1680 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
1681 },
1682 {,
1683 "EventCode": "0x2505E",
1684 "EventName": "PM_BACK_BR_CMPL",
1685 "BriefDescription": "Branch instruction completed with a target address less than current instruction address"
1686 },
1687 {,
1688 "EventCode": "0x2688A",
1689 "EventName": "PM_ISIDE_DISP_FAIL_OTHER",
1690 "BriefDescription": "All I-side dispatch attempts for this thread that failed due to a reason other than addrs collision (excludes i_l2mru_tch_reqs)"
1691 },
1692 {,
1693 "EventCode": "0x2001A",
1694 "EventName": "PM_NTC_ALL_FIN",
1695 "BriefDescription": "Cycles after all instructions have finished to group completed"
1696 },
1697 {,
1698 "EventCode": "0x3005A",
1699 "EventName": "PM_ISQ_0_8_ENTRIES",
1700 "BriefDescription": "Cycles in which 8 or less Issue Queue entries are in use. This is a shared event, not per thread"
1701 },
1702 {,
1703 "EventCode": "0x3515E",
1704 "EventName": "PM_MRK_BACK_BR_CMPL",
1705 "BriefDescription": "Marked branch instruction completed with a target address less than current instruction address"
1706 },
1707 {,
1708 "EventCode": "0xF890",
1709 "EventName": "PM_LSU1_L1_CAM_CANCEL",
1710 "BriefDescription": "ls1 l1 tm cam cancel"
1711 },
1712 {,
1713 "EventCode": "0xE884",
1714 "EventName": "PM_LS1_ERAT_MISS_PREF",
1715 "BriefDescription": "LS1 Erat miss due to prefetch"
1716 },
1717 {,
1718 "EventCode": "0xE89C",
1719 "EventName": "PM_LSU1_TM_L1_MISS",
1720 "BriefDescription": "Load tm L1 miss"
1721 },
1722 {,
1723 "EventCode": "0x28A8",
1724 "EventName": "PM_TM_FAIL_CONF_NON_TM",
1725 "BriefDescription": "TM aborted because a conflict occurred with a non-transactional access by another processor"
1726 },
1727 {,
1728 "EventCode": "0x16890",
1729 "EventName": "PM_L1PF_L2MEMACC",
1730 "BriefDescription": "Valid when first beat of data comes in for an L1PF where data came from memory"
1731 },
1732 {,
1733 "EventCode": "0x4504C",
1734 "EventName": "PM_IPTEG_FROM_DMEM",
1735 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group (Distant) due to a instruction side request"
1736 },
1737 {,
1738 "EventCode": "0x1002E",
1739 "EventName": "PM_LMQ_MERGE",
1740 "BriefDescription": "A demand miss collides with a prefetch for the same line"
1741 },
1742 {,
1743 "EventCode": "0x160B6",
1744 "EventName": "PM_L3_WI0_BUSY",
1745 "BriefDescription": "Rotating sample of 8 WI valid"
1746 },
1747 {,
1748 "EventCode": "0x368AC",
1749 "EventName": "PM_L3_CO0_BUSY",
1750 "BriefDescription": "Lifetime, sample of CO machine 0 valid"
1751 },
1752 {,
1753 "EventCode": "0x2E040",
1754 "EventName": "PM_DPTEG_FROM_L2_MEPF",
1755 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 hit without dispatch conflicts on Mepf state. due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
1756 },
1757 {,
1758 "EventCode": "0x1D152",
1759 "EventName": "PM_MRK_DATA_FROM_DL4",
1760 "BriefDescription": "The processor's data cache was reloaded from another chip's L4 on a different Node or Group (Distant) due to a marked load"
1761 },
1762 {,
1763 "EventCode": "0x46880",
1764 "EventName": "PM_ISIDE_MRU_TOUCH",
1765 "BriefDescription": "I-side L2 MRU touch sent to L2 for this thread"
1766 },
1767 {,
1768 "EventCode": "0x1C05C",
1769 "EventName": "PM_DTLB_MISS_2M",
1770 "BriefDescription": "Data TLB reload (after a miss) page size 2M. Implies radix translation was used"
1771 },
1772 {,
1773 "EventCode": "0x50B8",
1774 "EventName": "PM_TAGE_OVERRIDE_WRONG",
1775 "BriefDescription": "The TAGE overrode BHT direction prediction but it was incorrect. Counted at completion for taken branches only"
1776 },
1777 {,
1778 "EventCode": "0x160AE",
1779 "EventName": "PM_L3_P0_PF_RTY",
1780 "BriefDescription": "L3 PF received retry port 0, every retry counted"
1781 },
1782 {,
1783 "EventCode": "0x268B2",
1784 "EventName": "PM_L3_LOC_GUESS_WRONG",
1785 "BriefDescription": "Initial scope=node (LNS) but data from out side local node (near or far or rem). Prediction too Low"
1786 },
1787 {,
1788 "EventCode": "0x36088",
1789 "EventName": "PM_L2_SYS_GUESS_CORRECT",
1790 "BriefDescription": "L2 guess system (VGS or RNS) and guess was correct (ie data beyond-group)"
1791 },
1792 {,
1793 "EventCode": "0x589C",
1794 "EventName": "PM_PTESYNC",
1795 "BriefDescription": "ptesync instruction counted when the instruction is decoded and transmitted"
1796 },
1797 {,
1798 "EventCode": "0x26086",
1799 "EventName": "PM_CO_TM_SC_FOOTPRINT",
1800 "BriefDescription": "L2 did a cleanifdirty CO to the L3 (ie created an SC line in the L3) OR L2 TM_store hit dirty HPC line and L3 indicated SC line formed in L3 on RDR bus"
1801 },
1802 {,
1803 "EventCode": "0x1E05A",
1804 "EventName": "PM_CMPLU_STALL_ANY_SYNC",
1805 "BriefDescription": "Cycles in which the NTC sync instruction (isync, lwsync or hwsync) is not allowed to complete"
1806 },
1807 {,
1808 "EventCode": "0xF090",
1809 "EventName": "PM_LSU0_L1_CAM_CANCEL",
1810 "BriefDescription": "ls0 l1 tm cam cancel"
1811 },
1812 {,
1813 "EventCode": "0xC0A8",
1814 "EventName": "PM_LSU_FLUSH_CI",
1815 "BriefDescription": "Load was not issued to LSU as a cache inhibited (non-cacheable) load but it was later determined to be cache inhibited"
1816 },
1817 {,
1818 "EventCode": "0x20AC",
1819 "EventName": "PM_TM_FAIL_CONF_TM",
1820 "BriefDescription": "TM aborted because a conflict occurred with another transaction."
1821 },
1822 {,
1823 "EventCode": "0x588C",
1824 "EventName": "PM_SHL_ST_DEP_CREATED",
1825 "BriefDescription": "Store-Hit-Load Table Read Hit with entry Enabled"
1826 },
1827 {,
1828 "EventCode": "0x360AC",
1829 "EventName": "PM_L3_SN0_BUSY",
1830 "BriefDescription": "Lifetime, sample of snooper machine 0 valid"
1831 },
1832 {,
1833 "EventCode": "0x3005C",
1834 "EventName": "PM_BFU_BUSY",
1835 "BriefDescription": "Cycles in which all 4 Binary Floating Point units are busy. The BFU is running at capacity"
1836 },
1837 {,
1838 "EventCode": "0x48A0",
1839 "EventName": "PM_BR_PRED_PCACHE",
1840 "BriefDescription": "Conditional branch completed that used pattern cache prediction"
1841 },
1842 {,
1843 "EventCode": "0x26880",
1844 "EventName": "PM_L2_ST_MISS",
1845 "BriefDescription": "All successful D-Side Store dispatches that were an L2 miss for this thread"
1846 },
1847 {,
1848 "EventCode": "0xF8B4",
1849 "EventName": "PM_DC_PREF_XCONS_ALLOC",
1850 "BriefDescription": "Prefetch stream allocated in the Ultra conservative phase by either the hardware prefetch mechanism or software prefetch"
1851 },
1852 {,
1853 "EventCode": "0x35048",
1854 "EventName": "PM_IPTEG_FROM_DL2L3_SHR",
1855 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a instruction side request"
1856 },
1857 {,
1858 "EventCode": "0x260A8",
1859 "EventName": "PM_L3_PF_HIT_L3",
1860 "BriefDescription": "L3 PF hit in L3 (abandoned)"
1861 },
1862 {,
1863 "EventCode": "0x360B4",
1864 "EventName": "PM_L3_PF0_BUSY",
1865 "BriefDescription": "Lifetime, sample of PF machine 0 valid"
1866 },
1867 {,
1868 "EventCode": "0xC0B0",
1869 "EventName": "PM_LSU_FLUSH_UE",
1870 "BriefDescription": "Correctable ECC error on reload data, reported at critical data forward time"
1871 },
1872 {,
1873 "EventCode": "0x4013A",
1874 "EventName": "PM_MRK_IC_MISS",
1875 "BriefDescription": "Marked instruction experienced I cache miss"
1876 },
1877 {,
1878 "EventCode": "0x2088",
1879 "EventName": "PM_FLUSH_DISP_SB",
1880 "BriefDescription": "Dispatch Flush: Scoreboard"
1881 },
1882 {,
1883 "EventCode": "0x401E8",
1884 "EventName": "PM_MRK_DATA_FROM_L2MISS",
1885 "BriefDescription": "The processor's data cache was reloaded from a location other than the local core's L2 due to a marked load"
1886 },
1887 {,
1888 "EventCode": "0x3688E",
1889 "EventName": "PM_TM_ST_CAUSED_FAIL",
1890 "BriefDescription": "TM Store (fav or non-fav) caused another thread to fail"
1891 },
1892 {,
1893 "EventCode": "0x460B2",
1894 "EventName": "PM_L3_SYS_GUESS_WRONG",
1895 "BriefDescription": "Initial scope=system (VGS or RNS) but data from local or near. Prediction too high"
1896 },
1897 {,
1898 "EventCode": "0x58B8",
1899 "EventName": "PM_TAGE_OVERRIDE_WRONG_SPEC",
1900 "BriefDescription": "The TAGE overrode BHT direction prediction and it was correct. Includes taken and not taken and is counted at execution time"
1901 },
1902 {,
1903 "EventCode": "0xE890",
1904 "EventName": "PM_LSU3_ERAT_HIT",
1905 "BriefDescription": "Primary ERAT hit. There is no secondary ERAT"
1906 },
1907 {,
1908 "EventCode": "0x2898",
1909 "EventName": "PM_TM_TABORT_TRECLAIM",
1910 "BriefDescription": "Completion time tabortnoncd, tabortcd, treclaim"
1911 },
1912 {,
1913 "EventCode": "0x4C054",
1914 "EventName": "PM_DERAT_MISS_16G",
1915 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16G"
1916 },
1917 {,
1918 "EventCode": "0x268A0",
1919 "EventName": "PM_L3_CO_L31",
1920 "BriefDescription": "L3 CO to L3.1 OR of port 0 and 1 (lossy = may undercount if two cresps come in the same cyc)"
1921 },
1922 {,
1923 "EventCode": "0x5080",
1924 "EventName": "PM_THRD_PRIO_4_5_CYC",
1925 "BriefDescription": "Cycles thread running at priority level 4 or 5"
1926 },
1927 {,
1928 "EventCode": "0x2505C",
1929 "EventName": "PM_VSU_FIN",
1930 "BriefDescription": "VSU instruction finished. Up to 4 per cycle"
1931 },
1932 {,
1933 "EventCode": "0x40A4",
1934 "EventName": "PM_BR_PRED_CCACHE",
1935 "BriefDescription": "Conditional Branch Completed that used the Count Cache for Target Prediction"
1936 },
1937 {,
1938 "EventCode": "0x2E04A",
1939 "EventName": "PM_DPTEG_FROM_RL4",
1940 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on the same Node or Group ( Remote) due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
1941 },
1942 {,
1943 "EventCode": "0x4D12E",
1944 "EventName": "PM_MRK_DATA_FROM_DL2L3_MOD_CYC",
1945 "BriefDescription": "Duration in cycles to reload with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a marked load"
1946 },
1947 {,
1948 "EventCode": "0xC8B4",
1949 "EventName": "PM_LSU_FLUSH_LHL_SHL",
1950 "BriefDescription": "The instruction was flushed because of a sequential load/store consistency. If a load or store hits on an older load that has either been snooped (for loads) or has stale data (for stores)."
1951 },
1952 {,
1953 "EventCode": "0x58A4",
1954 "EventName": "PM_FLUSH_LSU",
1955 "BriefDescription": "LSU flushes. Includes all lsu flushes"
1956 },
1957 {,
1958 "EventCode": "0x1D150",
1959 "EventName": "PM_MRK_DATA_FROM_DL2L3_SHR",
1960 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a marked load"
1961 },
1962 {,
1963 "EventCode": "0xC8A0",
1964 "EventName": "PM_LSU1_FALSE_LHS",
1965 "BriefDescription": "False LHS match detected"
1966 },
1967 {,
1968 "EventCode": "0x48BC",
1969 "EventName": "PM_THRD_PRIO_2_3_CYC",
1970 "BriefDescription": "Cycles thread running at priority level 2 or 3"
1971 },
1972 {,
1973 "EventCode": "0x10134",
1974 "EventName": "PM_MRK_ST_DONE_L2",
1975 "BriefDescription": "marked store completed in L2 ( RC machine done)"
1976 },
1977 {,
1978 "EventCode": "0x368B2",
1979 "EventName": "PM_L3_GRP_GUESS_WRONG_HIGH",
1980 "BriefDescription": "Initial scope=group (GS or NNS) but data from local node. Prediction too high"
1981 },
1982 {,
1983 "EventCode": "0xE8BC",
1984 "EventName": "PM_LS1_PTE_TABLEWALK_CYC",
1985 "BriefDescription": "Cycles when a tablewalk is pending on this thread on table 1"
1986 },
1987 {,
1988 "EventCode": "0x1F152",
1989 "EventName": "PM_MRK_FAB_RSP_BKILL_CYC",
1990 "BriefDescription": "cycles L2 RC took for a bkill"
1991 },
1992 {,
1993 "EventCode": "0x4C124",
1994 "EventName": "PM_MRK_DATA_FROM_L3_NO_CONFLICT_CYC",
1995 "BriefDescription": "Duration in cycles to reload from local core's L3 without conflict due to a marked load"
1996 },
1997 {,
1998 "EventCode": "0x2F14A",
1999 "EventName": "PM_MRK_DPTEG_FROM_RL4",
2000 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on the same Node or Group ( Remote) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
2001 },
2002 {,
2003 "EventCode": "0x26888",
2004 "EventName": "PM_L2_GRP_GUESS_WRONG",
2005 "BriefDescription": "L2 guess grp (GS or NNS) and guess was not correct (ie data on-chip OR beyond-group)"
2006 },
2007 {,
2008 "EventCode": "0x368AE",
2009 "EventName": "PM_L3_P1_CO_RTY",
2010 "BriefDescription": "L3 CO received retry port 1 (memory only), every retry counted"
2011 },
2012 {,
2013 "EventCode": "0xC0AC",
2014 "EventName": "PM_LSU_FLUSH_EMSH",
2015 "BriefDescription": "An ERAT miss was detected after a set-p hit. Erat tracker indicates fail due to tlbmiss and the instruction gets flushed because the instruction was working on the wrong address"
2016 },
2017 {,
2018 "EventCode": "0x260B2",
2019 "EventName": "PM_L3_SYS_GUESS_CORRECT",
2020 "BriefDescription": "Initial scope=system (VGS or RNS) and data from outside group (far or rem)(pred successful)"
2021 },
2022 {,
2023 "EventCode": "0x1D146",
2024 "EventName": "PM_MRK_DATA_FROM_MEMORY_CYC",
2025 "BriefDescription": "Duration in cycles to reload from a memory location including L4 from local remote or distant due to a marked load"
2026 },
2027 {,
2028 "EventCode": "0xE094",
2029 "EventName": "PM_LSU0_TM_L1_HIT",
2030 "BriefDescription": "Load tm hit in L1"
2031 },
2032 {,
2033 "EventCode": "0x46888",
2034 "EventName": "PM_L2_GROUP_PUMP",
2035 "BriefDescription": "RC requests that were on group (aka nodel) pump attempts"
2036 },
2037 {,
2038 "EventCode": "0xF0B0",
2039 "EventName": "PM_L3_LD_PREF",
2040 "BriefDescription": "L3 load prefetch, sourced from a hardware or software stream, was sent to the nest"
2041 },
2042 {,
2043 "EventCode": "0x16080",
2044 "EventName": "PM_L2_LD",
2045 "BriefDescription": "All successful D-side Load dispatches for this thread (L2 miss + L2 hits)"
2046 },
2047 {,
2048 "EventCode": "0x4505C",
2049 "EventName": "PM_MATH_FLOP_CMPL",
2050 "BriefDescription": "Math flop instruction completed"
2051 },
2052 {,
2053 "EventCode": "0x368B0",
2054 "EventName": "PM_L3_P1_SYS_PUMP",
2055 "BriefDescription": "L3 PF sent with sys scope port 1, counts even retried requests"
2056 },
2057 {,
2058 "EventCode": "0x1F146",
2059 "EventName": "PM_MRK_DPTEG_FROM_L31_SHR",
2060 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's L3 on the same chip due to a marked data side request.. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
2061 },
2062 {,
2063 "EventCode": "0x2000C",
2064 "EventName": "PM_THRD_ALL_RUN_CYC",
2065 "BriefDescription": "Cycles in which all the threads have the run latch set"
2066 },
2067 {,
2068 "EventCode": "0xC0BC",
2069 "EventName": "PM_LSU_FLUSH_OTHER",
2070 "BriefDescription": "Other LSU flushes including: Sync (sync ack from L2 caused search of LRQ for oldest snooped load, This will either signal a Precise Flush of the oldest snooped loa or a Flush Next PPC); Data Valid Flush Next (several cases of this, one example is store and reload are lined up such that a store-hit-reload scenario exists and the CDF has already launched and has gotten bad/stale data); Bad Data Valid Flush Next (might be a few cases of this, one example is a larxa (D$ hit) return data and dval but can't allocate to LMQ (LMQ full or other reason). Already gave dval but can't watch it for snoop_hit_larx. Need to take the “bad dval” back and flush all younger ops)"
2071 },
2072 {,
2073 "EventCode": "0x5094",
2074 "EventName": "PM_IC_MISS_ICBI",
2075 "BriefDescription": "threaded version, IC Misses where we got EA dir hit but no sector valids were on. ICBI took line out"
2076 },
2077 {,
2078 "EventCode": "0xC8A8",
2079 "EventName": "PM_LSU_FLUSH_ATOMIC",
2080 "BriefDescription": "Quad-word loads (lq) are considered atomic because they always span at least 2 slices. If a snoop or store from another thread changes the data the load is accessing between the 2 or 3 pieces of the lq instruction, the lq will be flushed"
2081 },
2082 {,
2083 "EventCode": "0x1E04E",
2084 "EventName": "PM_DPTEG_FROM_L2MISS",
2085 "BriefDescription": "A Page Table Entry was loaded into the TLB from a location other than the local core's L2 due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
2086 },
2087 {,
2088 "EventCode": "0x4D05E",
2089 "EventName": "PM_BR_CMPL",
2090 "BriefDescription": "Any Branch instruction completed"
2091 },
2092 {,
2093 "EventCode": "0x260B0",
2094 "EventName": "PM_L3_P0_GRP_PUMP",
2095 "BriefDescription": "L3 PF sent with grp scope port 0, counts even retried requests"
2096 },
2097 {,
2098 "EventCode": "0x30132",
2099 "EventName": "PM_MRK_VSU_FIN",
2100 "BriefDescription": "VSU marked instr finish"
2101 },
2102 {,
2103 "EventCode": "0x2D120",
2104 "EventName": "PM_MRK_DATA_FROM_OFF_CHIP_CACHE",
2105 "BriefDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked load"
2106 },
2107 {,
2108 "EventCode": "0x1E048",
2109 "EventName": "PM_DPTEG_FROM_ON_CHIP_CACHE",
2110 "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on the same chip due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
2111 },
2112 {,
2113 "EventCode": "0x16086",
2114 "EventName": "PM_L2_SN_M_WR_DONE",
2115 "BriefDescription": "SNP dispatched for a write and was M (true M); for DMA cacheinj this will pulse if rty/push is required (won't pulse if cacheinj is accepted)"
2116 },
2117 {,
2118 "EventCode": "0x489C",
2119 "EventName": "PM_BR_CORECT_PRED_TAKEN_CMPL",
2120 "BriefDescription": "Conditional Branch Completed in which the HW correctly predicted the direction as taken. Counted at completion time"
2121 },
2122 {,
2123 "EventCode": "0xF0B8",
2124 "EventName": "PM_LS0_UNALIGNED_ST",
2125 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
2126 },
2127 {,
2128 "EventCode": "0x20132",
2129 "EventName": "PM_MRK_DFU_FIN",
2130 "BriefDescription": "Decimal Unit marked Instruction Finish"
2131 },
2132 {,
2133 "EventCode": "0x160A6",
2134 "EventName": "PM_TM_SC_CO",
2135 "BriefDescription": "L3 castout TM SC line"
2136 },
2137 {,
2138 "EventCode": "0xC8B0",
2139 "EventName": "PM_LSU_FLUSH_LHS",
2140 "BriefDescription": "Effective Address alias flush : no EA match but Real Address match. If the data has not yet been returned for this load, the instruction will just be rejected, but if it has returned data, it will be flushed"
2141 },
2142 {,
2143 "EventCode": "0x3F150",
2144 "EventName": "PM_MRK_ST_DRAIN_TO_L2DISP_CYC",
2145 "BriefDescription": "cycles to drain st from core to L2"
2146 },
2147 {,
2148 "EventCode": "0x168A4",
2149 "EventName": "PM_L3_MISS",
2150 "BriefDescription": "L3 Misses (L2 miss also missing L3, including data/instrn/xlate)"
2151 },
2152 {,
2153 "EventCode": "0xF080",
2154 "EventName": "PM_LSU_STCX_FAIL",
2155 "BriefDescription": ""
2156 },
2157 {,
2158 "EventCode": "0x30038",
2159 "EventName": "PM_CMPLU_STALL_DMISS_LMEM",
2160 "BriefDescription": "Completion stall due to cache miss that resolves in local memory"
2161 },
2162 {,
2163 "EventCode": "0x28A4",
2164 "EventName": "PM_MRK_TEND_FAIL",
2165 "BriefDescription": "Nested or not nested tend failed for a marked tend instruction"
2166 },
2167 {,
2168 "EventCode": "0x100FC",
2169 "EventName": "PM_LD_REF_L1",
2170 "BriefDescription": "All L1 D cache load references counted at finish, gated by reject"
2171 },
2172 {,
2173 "EventCode": "0xC0A0",
2174 "EventName": "PM_LSU0_FALSE_LHS",
2175 "BriefDescription": "False LHS match detected"
2176 },
2177 {,
2178 "EventCode": "0x468A8",
2179 "EventName": "PM_SN_MISS",
2180 "BriefDescription": "Any port snooper L3 miss or collision. Up to 4 can happen in a cycle but we only count 1"
2181 },
2182 {,
2183 "EventCode": "0x36888",
2184 "EventName": "PM_L2_SYS_GUESS_WRONG",
2185 "BriefDescription": "L2 guess system (VGS or RNS) and guess was not correct (ie data ^beyond-group)"
2186 },
2187 {,
2188 "EventCode": "0x2080",
2189 "EventName": "PM_EE_OFF_EXT_INT",
2190 "BriefDescription": "CyclesMSR[EE] is off and external interrupts are active"
2191 },
2192 {,
2193 "EventCode": "0xE8B8",
2194 "EventName": "PM_LS3_TM_DISALLOW",
2195 "BriefDescription": "A TM-ineligible instruction tries to execute inside a transaction and the LSU disallows it"
2196 },
2197 {,
2198 "EventCode": "0x2688E",
2199 "EventName": "PM_TM_FAV_CAUSED_FAIL",
2200 "BriefDescription": "TM Load (fav) caused another thread to fail"
2201 },
2202 {,
2203 "EventCode": "0x16090",
2204 "EventName": "PM_SN0_BUSY",
2205 "BriefDescription": "SN mach 0 Busy. Used by PMU to sample ave SN lifetime (mach0 used as sample point)"
2206 },
2207 {,
2208 "EventCode": "0x360AE",
2209 "EventName": "PM_L3_P0_CO_RTY",
2210 "BriefDescription": "L3 CO received retry port 0 (memory only), every retry counted"
2211 },
2212 {,
2213 "EventCode": "0x168A8",
2214 "EventName": "PM_L3_WI_USAGE",
2215 "BriefDescription": "Lifetime, sample of Write Inject machine 0 valid"
2216 },
2217 {,
2218 "EventCode": "0x468A2",
2219 "EventName": "PM_L3_LAT_CI_MISS",
2220 "BriefDescription": "L3 Lateral Castins Miss"
2221 },
2222 {,
2223 "EventCode": "0x4090",
2224 "EventName": "PM_IC_PREF_CANCEL_PAGE",
2225 "BriefDescription": "Prefetch Canceled due to page boundary"
2226 },
2227 {,
2228 "EventCode": "0xF09C",
2229 "EventName": "PM_SLB_TABLEWALK_CYC",
2230 "BriefDescription": "Cycles when a tablewalk is pending on this thread on the SLB table"
2231 },
2232 {,
2233 "EventCode": "0x460AA",
2234 "EventName": "PM_L3_P0_CO_L31",
2235 "BriefDescription": "L3 CO to L3.1 (LCO) port 0 with or without data"
2236 },
2237 {,
2238 "EventCode": "0x2880",
2239 "EventName": "PM_FLUSH_DISP",
2240 "BriefDescription": "Dispatch flush"
2241 },
2242 {,
2243 "EventCode": "0x168AE",
2244 "EventName": "PM_L3_P1_PF_RTY",
2245 "BriefDescription": "L3 PF received retry port 1, every retry counted"
2246 },
2247 {,
2248 "EventCode": "0x46082",
2249 "EventName": "PM_L2_ST_DISP",
2250 "BriefDescription": "All successful D-side store dispatches for this thread "
2251 },
2252 {,
2253 "EventCode": "0x4609E",
2254 "EventName": "PM_L2_INST_MISS",
2255 "BriefDescription": "All successful I-side dispatches that were an L2 miss for this thread (excludes i_l2mru_tch reqs)"
2256 },
2257 {,
2258 "EventCode": "0xE084",
2259 "EventName": "PM_LS0_ERAT_MISS_PREF",
2260 "BriefDescription": "LS0 Erat miss due to prefetch"
2261 },
2262 {,
2263 "EventCode": "0x409C",
2264 "EventName": "PM_BR_PRED",
2265 "BriefDescription": "Conditional Branch Executed in which the HW predicted the Direction or Target. Includes taken and not taken and is counted at execution time"
2266 },
2267 {,
2268 "EventCode": "0x2D144",
2269 "EventName": "PM_MRK_DATA_FROM_L31_MOD",
2270 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L3 on the same chip due to a marked load"
2271 },
2272 {,
2273 "EventCode": "0x360A4",
2274 "EventName": "PM_L3_CO_LCO",
2275 "BriefDescription": "Total L3 COs occurred on LCO L3.1 (good cresp, may end up in mem on a retry)"
2276 },
2277 {,
2278 "EventCode": "0x4890",
2279 "EventName": "PM_IC_PREF_CANCEL_HIT",
2280 "BriefDescription": "Prefetch Canceled due to icache hit"
2281 },
2282 {,
2283 "EventCode": "0x268A8",
2284 "EventName": "PM_RD_HIT_PF",
2285 "BriefDescription": "RD machine hit L3 PF machine"
2286 },
2287 {,
2288 "EventCode": "0x16880",
2289 "EventName": "PM_L2_ST",
2290 "BriefDescription": "All successful D-side store dispatches for this thread (L2 miss + L2 hits)"
2291 },
2292 {,
2293 "EventCode": "0x4098",
2294 "EventName": "PM_IC_DEMAND_L2_BHT_REDIRECT",
2295 "BriefDescription": "L2 I cache demand request due to BHT redirect, branch redirect ( 2 bubbles 3 cycles)"
2296 },
2297 {,
2298 "EventCode": "0xD0B4",
2299 "EventName": "PM_LSU0_SRQ_S0_VALID_CYC",
2300 "BriefDescription": "Slot 0 of SRQ valid"
2301 },
2302 {,
2303 "EventCode": "0x160AA",
2304 "EventName": "PM_L3_P0_LCO_NO_DATA",
2305 "BriefDescription": "Dataless L3 LCO sent port 0"
2306 },
2307 {,
2308 "EventCode": "0x208C",
2309 "EventName": "PM_CLB_HELD",
2310 "BriefDescription": "CLB (control logic block - indicates quadword fetch block) Hold: Any Reason"
2311 },
2312 {,
2313 "EventCode": "0xF88C",
2314 "EventName": "PM_LSU3_STORE_REJECT",
2315 "BriefDescription": "All internal store rejects cause the instruction to go back to the SRQ and go to sleep until woken up to try again after the condition has been met"
2316 },
2317 {,
2318 "EventCode": "0x200F2",
2319 "EventName": "PM_INST_DISP",
2320 "BriefDescription": "# PPC Dispatched"
2321 },
2322 {,
2323 "EventCode": "0x4E05E",
2324 "EventName": "PM_TM_OUTER_TBEGIN_DISP",
2325 "BriefDescription": "Number of outer tbegin instructions dispatched. The dispatch unit determines whether the tbegin instruction is outer or nested. This is a speculative count, which includes flushed instructions"
2326 },
2327 {,
2328 "EventCode": "0x2D018",
2329 "EventName": "PM_CMPLU_STALL_EXEC_UNIT",
2330 "BriefDescription": "Completion stall due to execution units (FXU/VSU/CRU)"
2331 },
2332 {,
2333 "EventCode": "0x20B0",
2334 "EventName": "PM_LSU_FLUSH_NEXT",
2335 "BriefDescription": "LSU flush next reported at flush time. Sometimes these also come with an exception"
2336 },
2337 {,
2338 "EventCode": "0x3880",
2339 "EventName": "PM_ISU2_ISS_HOLD_ALL",
2340 "BriefDescription": "All ISU rejects"
2341 },
2342 {,
2343 "EventCode": "0x46882",
2344 "EventName": "PM_L2_ST_HIT",
2345 "BriefDescription": "All successful D-side store dispatches for this thread that were L2 hits"
2346 },
2347 {,
2348 "EventCode": "0x360A8",
2349 "EventName": "PM_L3_CO",
2350 "BriefDescription": "L3 castout occurring (does not include casthrough or log writes (cinj/dmaw))"
2351 },
2352 {,
2353 "EventCode": "0x368A4",
2354 "EventName": "PM_L3_CINJ",
2355 "BriefDescription": "L3 castin of cache inject"
2356 },
2357 {,
2358 "EventCode": "0xC890",
2359 "EventName": "PM_LSU_NCST",
2360 "BriefDescription": "Asserts when a i=1 store op is sent to the nest. No record of issue pipe (LS0/LS1) is maintained so this is for both pipes. Probably don't need separate LS0 and LS1"
2361 },
2362 {,
2363 "EventCode": "0xD880",
2364 "EventName": "PM_LSU1_SET_MPRED",
2365 "BriefDescription": "Set prediction(set-p) miss. The entry was not found in the Set prediction table"
2366 },
2367 {,
2368 "EventCode": "0xD0B8",
2369 "EventName": "PM_LSU_LMQ_FULL_CYC",
2370 "BriefDescription": "Counts the number of cycles the LMQ is full"
2371 },
2372 {,
2373 "EventCode": "0x168B2",
2374 "EventName": "PM_L3_GRP_GUESS_CORRECT",
2375 "BriefDescription": "Initial scope=group (GS or NNS) and data from same group (near) (pred successful)"
2376 },
2377 {,
2378 "EventCode": "0x48A4",
2379 "EventName": "PM_STOP_FETCH_PENDING_CYC",
2380 "BriefDescription": "Fetching is stopped due to an incoming instruction that will result in a flush"
2381 },
2382 {,
2383 "EventCode": "0x36884",
2384 "EventName": "PM_L2_RCST_DISP_FAIL_ADDR",
2385 "BriefDescription": "All D-side store dispatch attempts for this thread that failed due to address collision with RC/CO/SN/SQ"
2386 },
2387 {,
2388 "EventCode": "0x260AC",
2389 "EventName": "PM_L3_PF_USAGE",
2390 "BriefDescription": "Rotating sample of 32 PF actives"
2391 }
2392]
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json b/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
new file mode 100644
index 000000000000..bc2db636dabf
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
@@ -0,0 +1,552 @@
1[
2 {,
3 "EventCode": "0x4D04C",
4 "EventName": "PM_DFU_BUSY",
5 "BriefDescription": "Cycles in which all 4 Decimal Floating Point units are busy. The DFU is running at capacity"
6 },
7 {,
8 "EventCode": "0x100F6",
9 "EventName": "PM_IERAT_RELOAD",
10 "BriefDescription": "Number of I-ERAT reloads"
11 },
12 {,
13 "EventCode": "0x201E2",
14 "EventName": "PM_MRK_LD_MISS_L1",
15 "BriefDescription": "Marked DL1 Demand Miss counted at exec time. Note that this count is per slice, so if a load spans multiple slices this event will increment multiple times for a single load."
16 },
17 {,
18 "EventCode": "0x40010",
19 "EventName": "PM_PMC3_OVERFLOW",
20 "BriefDescription": "Overflow from counter 3"
21 },
22 {,
23 "EventCode": "0x1005A",
24 "EventName": "PM_CMPLU_STALL_DFLONG",
25 "BriefDescription": "Finish stall because the NTF instruction was a multi-cycle instruction issued to the Decimal Floating Point execution pipe and waiting to finish. Includes decimal floating point instructions + 128 bit binary floating point instructions. Qualified by multicycle"
26 },
27 {,
28 "EventCode": "0x4D140",
29 "EventName": "PM_MRK_DATA_FROM_ON_CHIP_CACHE",
30 "BriefDescription": "The processor's data cache was reloaded either shared or modified data from another core's L2/L3 on the same chip due to a marked load"
31 },
32 {,
33 "EventCode": "0x3F14C",
34 "EventName": "PM_MRK_DPTEG_FROM_DL4",
35 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on a different Node or Group (Distant) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
36 },
37 {,
38 "EventCode": "0x1E040",
39 "EventName": "PM_DPTEG_FROM_L2_NO_CONFLICT",
40 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
41 },
42 {,
43 "EventCode": "0x24052",
44 "EventName": "PM_FXU_IDLE",
45 "BriefDescription": "Cycles in which FXU0, FXU1, FXU2, and FXU3 are all idle"
46 },
47 {,
48 "EventCode": "0x1E054",
49 "EventName": "PM_CMPLU_STALL",
50 "BriefDescription": "Nothing completed and ICT not empty"
51 },
52 {,
53 "EventCode": "0x2",
54 "EventName": "PM_INST_CMPL",
55 "BriefDescription": "Number of PowerPC Instructions that completed."
56 },
57 {,
58 "EventCode": "0x3D058",
59 "EventName": "PM_VSU_DP_FSQRT_FDIV",
60 "BriefDescription": "vector versions of fdiv,fsqrt"
61 },
62 {,
63 "EventCode": "0x10006",
64 "EventName": "PM_DISP_HELD",
65 "BriefDescription": "Dispatch Held"
66 },
67 {,
68 "EventCode": "0x3D154",
69 "EventName": "PM_MRK_DERAT_MISS_16M",
70 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16M"
71 },
72 {,
73 "EventCode": "0x200F8",
74 "EventName": "PM_EXT_INT",
75 "BriefDescription": "external interrupt"
76 },
77 {,
78 "EventCode": "0x20008",
79 "EventName": "PM_ICT_EMPTY_CYC",
80 "BriefDescription": "Cycles in which the ICT is completely empty. No itags are assigned to any thread"
81 },
82 {,
83 "EventCode": "0x4F146",
84 "EventName": "PM_MRK_DPTEG_FROM_L21_MOD",
85 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L2 on the same chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
86 },
87 {,
88 "EventCode": "0x10056",
89 "EventName": "PM_MEM_READ",
90 "BriefDescription": "Reads from Memory from this thread (includes data/inst/xlate/l1prefetch/inst prefetch). Includes L4"
91 },
92 {,
93 "EventCode": "0x3C04C",
94 "EventName": "PM_DATA_FROM_DL4",
95 "BriefDescription": "The processor's data cache was reloaded from another chip's L4 on a different Node or Group (Distant) due to a demand load"
96 },
97 {,
98 "EventCode": "0x4E046",
99 "EventName": "PM_DPTEG_FROM_L21_MOD",
100 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L2 on the same chip due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
101 },
102 {,
103 "EventCode": "0x2E016",
104 "EventName": "PM_NTC_ISSUE_HELD_ARB",
105 "BriefDescription": "The NTC instruction is being held at dispatch because it lost arbitration onto the issue pipe to another instruction (from the same thread or a different thread)"
106 },
107 {,
108 "EventCode": "0x15156",
109 "EventName": "PM_SYNC_MRK_FX_DIVIDE",
110 "BriefDescription": "Marked fixed point divide that can cause a synchronous interrupt"
111 },
112 {,
113 "EventCode": "0x1C056",
114 "EventName": "PM_DERAT_MISS_4K",
115 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 4K"
116 },
117 {,
118 "EventCode": "0x2F142",
119 "EventName": "PM_MRK_DPTEG_FROM_L3_MEPF",
120 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without dispatch conflicts hit on Mepf state. due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
121 },
122 {,
123 "EventCode": "0x10024",
124 "EventName": "PM_PMC5_OVERFLOW",
125 "BriefDescription": "Overflow from counter 5"
126 },
127 {,
128 "EventCode": "0x2C018",
129 "EventName": "PM_CMPLU_STALL_DMISS_L21_L31",
130 "BriefDescription": "Completion stall by Dcache miss which resolved on chip ( excluding local L2/L3)"
131 },
132 {,
133 "EventCode": "0x4006A",
134 "EventName": "PM_IERAT_RELOAD_16M",
135 "BriefDescription": "IERAT Reloaded (Miss) for a 16M page"
136 },
137 {,
138 "EventCode": "0x4E010",
139 "EventName": "PM_ICT_NOSLOT_IC_L3MISS",
140 "BriefDescription": "Ict empty for this thread due to icache misses that were sourced from beyond the local L3. The source could be local/remote/distant memory or another core's cache"
141 },
142 {,
143 "EventCode": "0x4D01C",
144 "EventName": "PM_ICT_NOSLOT_DISP_HELD_SYNC",
145 "BriefDescription": "Dispatch held due to a synchronizing instruction at dispatch"
146 },
147 {,
148 "EventCode": "0x2D01A",
149 "EventName": "PM_ICT_NOSLOT_IC_MISS",
150 "BriefDescription": "Ict empty for this thread due to Icache Miss"
151 },
152 {,
153 "EventCode": "0x3D152",
154 "EventName": "PM_MRK_DERAT_MISS_1G",
155 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 1G. Implies radix translation"
156 },
157 {,
158 "EventCode": "0x4F14A",
159 "EventName": "PM_MRK_DPTEG_FROM_OFF_CHIP_CACHE",
160 "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
161 },
162 {,
163 "EventCode": "0x30058",
164 "EventName": "PM_TLBIE_FIN",
165 "BriefDescription": "tlbie finished"
166 },
167 {,
168 "EventCode": "0x100F8",
169 "EventName": "PM_ICT_NOSLOT_CYC",
170 "BriefDescription": "Number of cycles the ICT has no itags assigned to this thread"
171 },
172 {,
173 "EventCode": "0x3E042",
174 "EventName": "PM_DPTEG_FROM_L3_DISP_CONFLICT",
175 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 with dispatch conflict due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
176 },
177 {,
178 "EventCode": "0x1F140",
179 "EventName": "PM_MRK_DPTEG_FROM_L2_NO_CONFLICT",
180 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
181 },
182 {,
183 "EventCode": "0x2C05A",
184 "EventName": "PM_DERAT_MISS_1G",
185 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 1G. Implies radix translation"
186 },
187 {,
188 "EventCode": "0x1F058",
189 "EventName": "PM_RADIX_PWC_L2_PTE_FROM_L2",
190 "BriefDescription": "A Page Table Entry was reloaded to a level 2 page walk cache from the core's L2 data cache. This implies that level 3 and level 4 PWC accesses were not necessary for this translation"
191 },
192 {,
193 "EventCode": "0x1D14A",
194 "EventName": "PM_MRK_DATA_FROM_RL2L3_MOD",
195 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load"
196 },
197 {,
198 "EventCode": "0x10050",
199 "EventName": "PM_CHIP_PUMP_CPRED",
200 "BriefDescription": "Initial and Final Pump Scope was chip pump (prediction=correct) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
201 },
202 {,
203 "EventCode": "0x45058",
204 "EventName": "PM_IC_MISS_CMPL",
205 "BriefDescription": "Non-speculative icache miss, counted at completion"
206 },
207 {,
208 "EventCode": "0x2D150",
209 "EventName": "PM_MRK_DERAT_MISS_4K",
210 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 4K"
211 },
212 {,
213 "EventCode": "0x34058",
214 "EventName": "PM_ICT_NOSLOT_BR_MPRED_ICMISS",
215 "BriefDescription": "Ict empty for this thread due to Icache Miss and branch mispred"
216 },
217 {,
218 "EventCode": "0x10022",
219 "EventName": "PM_PMC2_SAVED",
220 "BriefDescription": "PMC2 Rewind Value saved"
221 },
222 {,
223 "EventCode": "0x2000A",
224 "EventName": "PM_HV_CYC",
225 "BriefDescription": "Cycles in which msr_hv is high. Note that this event does not take msr_pr into consideration"
226 },
227 {,
228 "EventCode": "0x1F144",
229 "EventName": "PM_MRK_DPTEG_FROM_L3_NO_CONFLICT",
230 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without conflict due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
231 },
232 {,
233 "EventCode": "0x300FC",
234 "EventName": "PM_DTLB_MISS",
235 "BriefDescription": "Data PTEG reload"
236 },
237 {,
238 "EventCode": "0x2D152",
239 "EventName": "PM_MRK_DERAT_MISS_2M",
240 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 2M. Implies radix translation"
241 },
242 {,
243 "EventCode": "0x2C046",
244 "EventName": "PM_DATA_FROM_RL2L3_MOD",
245 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load"
246 },
247 {,
248 "EventCode": "0x20052",
249 "EventName": "PM_GRP_PUMP_MPRED",
250 "BriefDescription": "Final Pump Scope (Group) ended up either larger or smaller than Initial Pump Scope for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
251 },
252 {,
253 "EventCode": "0x3F05A",
254 "EventName": "PM_RADIX_PWC_L2_PDE_FROM_L3",
255 "BriefDescription": "A Page Directory Entry was reloaded to a level 2 page walk cache from the core's L3 data cache"
256 },
257 {,
258 "EventCode": "0x1E04A",
259 "EventName": "PM_DPTEG_FROM_RL2L3_SHR",
260 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
261 },
262 {,
263 "EventCode": "0x10064",
264 "EventName": "PM_ICT_NOSLOT_DISP_HELD_TBEGIN",
265 "BriefDescription": "the NTC instruction is being held at dispatch because it is a tbegin instruction and there is an older tbegin in the pipeline that must complete before the younger tbegin can dispatch"
266 },
267 {,
268 "EventCode": "0x2E046",
269 "EventName": "PM_DPTEG_FROM_RL2L3_MOD",
270 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
271 },
272 {,
273 "EventCode": "0x4F14C",
274 "EventName": "PM_MRK_DPTEG_FROM_DMEM",
275 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group (Distant) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
276 },
277 {,
278 "EventCode": "0x2E042",
279 "EventName": "PM_DPTEG_FROM_L3_MEPF",
280 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without dispatch conflicts hit on Mepf state. due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
281 },
282 {,
283 "EventCode": "0x2D012",
284 "EventName": "PM_CMPLU_STALL_DFU",
285 "BriefDescription": "Finish stall because the NTF instruction was issued to the Decimal Floating Point execution pipe and waiting to finish. Includes decimal floating point instructions + 128 bit binary floating point instructions. Not qualified by multicycle"
286 },
287 {,
288 "EventCode": "0x4C04C",
289 "EventName": "PM_DATA_FROM_DMEM",
290 "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to a demand load"
291 },
292 {,
293 "EventCode": "0x30022",
294 "EventName": "PM_PMC4_SAVED",
295 "BriefDescription": "PMC4 Rewind Value saved (matched condition)"
296 },
297 {,
298 "EventCode": "0x200F4",
299 "EventName": "PM_RUN_CYC",
300 "BriefDescription": "Run_cycles"
301 },
302 {,
303 "EventCode": "0x400F2",
304 "EventName": "PM_1PLUS_PPC_DISP",
305 "BriefDescription": "Cycles at least one Instr Dispatched"
306 },
307 {,
308 "EventCode": "0x3D148",
309 "EventName": "PM_MRK_DATA_FROM_L21_MOD_CYC",
310 "BriefDescription": "Duration in cycles to reload with Modified (M) data from another core's L2 on the same chip due to a marked load"
311 },
312 {,
313 "EventCode": "0x2F146",
314 "EventName": "PM_MRK_DPTEG_FROM_RL2L3_MOD",
315 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
316 },
317 {,
318 "EventCode": "0x4E01A",
319 "EventName": "PM_ICT_NOSLOT_DISP_HELD",
320 "BriefDescription": "Cycles in which the NTC instruction is held at dispatch for any reason"
321 },
322 {,
323 "EventCode": "0x401EC",
324 "EventName": "PM_THRESH_EXC_2048",
325 "BriefDescription": "Threshold counter exceeded a value of 2048"
326 },
327 {,
328 "EventCode": "0x35150",
329 "EventName": "PM_MRK_DATA_FROM_RL2L3_SHR",
330 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load"
331 },
332 {,
333 "EventCode": "0x3E052",
334 "EventName": "PM_ICT_NOSLOT_IC_L3",
335 "BriefDescription": "Ict empty for this thread due to icache misses that were sourced from the local L3"
336 },
337 {,
338 "EventCode": "0x2405A",
339 "EventName": "PM_NTC_FIN",
340 "BriefDescription": "Cycles in which the oldest instruction in the pipeline (NTC) finishes. This event is used to account for cycles in which work is being completed in the CPI stack"
341 },
342 {,
343 "EventCode": "0x40052",
344 "EventName": "PM_PUMP_MPRED",
345 "BriefDescription": "Pump misprediction. Counts across all types of pumps for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
346 },
347 {,
348 "EventCode": "0x30056",
349 "EventName": "PM_TM_ABORTS",
350 "BriefDescription": "Number of TM transactions aborted"
351 },
352 {,
353 "EventCode": "0x2404C",
354 "EventName": "PM_INST_FROM_MEMORY",
355 "BriefDescription": "The processor's Instruction cache was reloaded from a memory location including L4 from local remote or distant due to an instruction fetch (not prefetch)"
356 },
357 {,
358 "EventCode": "0x1C05A",
359 "EventName": "PM_DERAT_MISS_2M",
360 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 2M. Implies radix translation"
361 },
362 {,
363 "EventCode": "0x30024",
364 "EventName": "PM_PMC6_OVERFLOW",
365 "BriefDescription": "Overflow from counter 6"
366 },
367 {,
368 "EventCode": "0x10068",
369 "EventName": "PM_BRU_FIN",
370 "BriefDescription": "Branch Instruction Finished"
371 },
372 {,
373 "EventCode": "0x30020",
374 "EventName": "PM_PMC2_REWIND",
375 "BriefDescription": "PMC2 Rewind Event (did not match condition)"
376 },
377 {,
378 "EventCode": "0x40064",
379 "EventName": "PM_DUMMY2_REMOVE_ME",
380 "BriefDescription": "Space holder for LS_PC_RELOAD_RA"
381 },
382 {,
383 "EventCode": "0x3F148",
384 "EventName": "PM_MRK_DPTEG_FROM_DL2L3_SHR",
385 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
386 },
387 {,
388 "EventCode": "0x4D01E",
389 "EventName": "PM_ICT_NOSLOT_BR_MPRED",
390 "BriefDescription": "Ict empty for this thread due to branch mispred"
391 },
392 {,
393 "EventCode": "0x3405E",
394 "EventName": "PM_IFETCH_THROTTLE",
395 "BriefDescription": "Cycles in which Instruction fetch throttle was active."
396 },
397 {,
398 "EventCode": "0x1F148",
399 "EventName": "PM_MRK_DPTEG_FROM_ON_CHIP_CACHE",
400 "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on the same chip due to a marked data side request.. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
401 },
402 {,
403 "EventCode": "0x3E046",
404 "EventName": "PM_DPTEG_FROM_L21_SHR",
405 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's L2 on the same chip due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
406 },
407 {,
408 "EventCode": "0x2F144",
409 "EventName": "PM_MRK_DPTEG_FROM_L31_MOD",
410 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L3 on the same chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
411 },
412 {,
413 "EventCode": "0x4C15C",
414 "EventName": "PM_MRK_DERAT_MISS_16G",
415 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16G"
416 },
417 {,
418 "EventCode": "0x14052",
419 "EventName": "PM_INST_GRP_PUMP_MPRED_RTY",
420 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for an instruction fetch"
421 },
422 {,
423 "EventCode": "0xD0A8",
424 "EventName": "PM_DSLB_MISS",
425 "BriefDescription": "Data SLB Miss - Total of all segment sizes"
426 },
427 {,
428 "EventCode": "0x4C058",
429 "EventName": "PM_MEM_CO",
430 "BriefDescription": "Memory castouts from this thread"
431 },
432 {,
433 "EventCode": "0x40004",
434 "EventName": "PM_FXU_FIN",
435 "BriefDescription": "The fixed point unit Unit finished an instruction. Instructions that finish may not necessary complete."
436 },
437 {,
438 "EventCode": "0x2C054",
439 "EventName": "PM_DERAT_MISS_64K",
440 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 64K"
441 },
442 {,
443 "EventCode": "0x10018",
444 "EventName": "PM_IC_DEMAND_CYC",
445 "BriefDescription": "Icache miss demand cycles"
446 },
447 {,
448 "EventCode": "0x3C054",
449 "EventName": "PM_DERAT_MISS_16M",
450 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16M"
451 },
452 {,
453 "EventCode": "0x2D14E",
454 "EventName": "PM_MRK_DATA_FROM_L21_SHR",
455 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L2 on the same chip due to a marked load"
456 },
457 {,
458 "EventCode": "0x3405C",
459 "EventName": "PM_CMPLU_STALL_DPLONG",
460 "BriefDescription": "Finish stall because the NTF instruction was a scalar multi-cycle instruction issued to the Double Precision execution pipe and waiting to finish. Includes binary floating point instructions in 32 and 64 bit binary floating point format. Qualified by NOT vector AND multicycle"
461 },
462 {,
463 "EventCode": "0x4D052",
464 "EventName": "PM_2FLOP_CMPL",
465 "BriefDescription": "DP vector version of fmul, fsub, fcmp, fsel, fabs, fnabs, fres ,fsqrte, fneg "
466 },
467 {,
468 "EventCode": "0x1F142",
469 "EventName": "PM_MRK_DPTEG_FROM_L2",
470 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
471 },
472 {,
473 "EventCode": "0x40062",
474 "EventName": "PM_DUMMY1_REMOVE_ME",
475 "BriefDescription": "Space holder for L2_PC_PM_MK_LDST_SCOPE_PRED_STATUS"
476 },
477 {,
478 "EventCode": "0x4C012",
479 "EventName": "PM_CMPLU_STALL_ERAT_MISS",
480 "BriefDescription": "Finish stall because the NTF instruction was a load or store that suffered a translation miss"
481 },
482 {,
483 "EventCode": "0x4D050",
484 "EventName": "PM_VSU_NON_FLOP_CMPL",
485 "BriefDescription": "Non FLOP operation completed"
486 },
487 {,
488 "EventCode": "0x2E012",
489 "EventName": "PM_TM_TX_PASS_RUN_CYC",
490 "BriefDescription": "cycles spent in successful transactions"
491 },
492 {,
493 "EventCode": "0x4D04E",
494 "EventName": "PM_VSU_FSQRT_FDIV",
495 "BriefDescription": "four flops operation (fdiv,fsqrt) Scalar Instructions only"
496 },
497 {,
498 "EventCode": "0x4C120",
499 "EventName": "PM_MRK_DATA_FROM_L2_MEPF",
500 "BriefDescription": "The processor's data cache was reloaded from local core's L2 hit without dispatch conflicts on Mepf state. due to a marked load"
501 },
502 {,
503 "EventCode": "0x10062",
504 "EventName": "PM_LD_L3MISS_PEND_CYC",
505 "BriefDescription": "Cycles L3 miss was pending for this thread"
506 },
507 {,
508 "EventCode": "0x2F14C",
509 "EventName": "PM_MRK_DPTEG_FROM_MEMORY",
510 "BriefDescription": "A Page Table Entry was loaded into the TLB from a memory location including L4 from local remote or distant due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
511 },
512 {,
513 "EventCode": "0x14050",
514 "EventName": "PM_INST_CHIP_PUMP_CPRED",
515 "BriefDescription": "Initial and Final Pump Scope was chip pump (prediction=correct) for an instruction fetch"
516 },
517 {,
518 "EventCode": "0x2000E",
519 "EventName": "PM_FXU_BUSY",
520 "BriefDescription": "Cycles in which all 4 FXUs are busy. The FXU is running at capacity"
521 },
522 {,
523 "EventCode": "0x20066",
524 "EventName": "PM_TLB_MISS",
525 "BriefDescription": "TLB Miss (I + D)"
526 },
527 {,
528 "EventCode": "0x10054",
529 "EventName": "PM_PUMP_CPRED",
530 "BriefDescription": "Pump prediction correct. Counts across all types of pumps for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
531 },
532 {,
533 "EventCode": "0x4D124",
534 "EventName": "PM_MRK_DATA_FROM_L31_SHR",
535 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L3 on the same chip due to a marked load"
536 },
537 {,
538 "EventCode": "0x400F8",
539 "EventName": "PM_FLUSH",
540 "BriefDescription": "Flush (any type)"
541 },
542 {,
543 "EventCode": "0x30004",
544 "EventName": "PM_CMPLU_STALL_EMQ_FULL",
545 "BriefDescription": "Finish stall because the next to finish instruction suffered an ERAT miss and the EMQ was full"
546 },
547 {,
548 "EventCode": "0x1D154",
549 "EventName": "PM_MRK_DATA_FROM_L21_SHR_CYC",
550 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L2 on the same chip due to a marked load"
551 }
552]
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/pmc.json b/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
new file mode 100644
index 000000000000..3ef8a10aac86
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
@@ -0,0 +1,122 @@
1[
2 {,
3 "EventCode": "0x20036",
4 "EventName": "PM_BR_2PATH",
5 "BriefDescription": "Branches that are not strongly biased"
6 },
7 {,
8 "EventCode": "0x40056",
9 "EventName": "PM_MEM_LOC_THRESH_LSU_HIGH",
10 "BriefDescription": "Local memory above threshold for LSU medium"
11 },
12 {,
13 "EventCode": "0x2C056",
14 "EventName": "PM_DTLB_MISS_4K",
15 "BriefDescription": "Data TLB Miss page size 4k"
16 },
17 {,
18 "EventCode": "0x40118",
19 "EventName": "PM_MRK_DCACHE_RELOAD_INTV",
20 "BriefDescription": "Combined Intervention event"
21 },
22 {,
23 "EventCode": "0x4F148",
24 "EventName": "PM_MRK_DPTEG_FROM_DL2L3_MOD",
25 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
26 },
27 {,
28 "EventCode": "0x301E8",
29 "EventName": "PM_THRESH_EXC_64",
30 "BriefDescription": "Threshold counter exceeded a value of 64"
31 },
32 {,
33 "EventCode": "0x4E04E",
34 "EventName": "PM_DPTEG_FROM_L3MISS",
35 "BriefDescription": "A Page Table Entry was loaded into the TLB from a location other than the local core's L3 due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
36 },
37 {,
38 "EventCode": "0x40050",
39 "EventName": "PM_SYS_PUMP_MPRED_RTY",
40 "BriefDescription": "Final Pump Scope (system) ended up larger than Initial Pump Scope (Chip/Group) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
41 },
42 {,
43 "EventCode": "0x1F14E",
44 "EventName": "PM_MRK_DPTEG_FROM_L2MISS",
45 "BriefDescription": "A Page Table Entry was loaded into the TLB from a location other than the local core's L2 due to a marked data side request.. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
46 },
47 {,
48 "EventCode": "0x4D018",
49 "EventName": "PM_CMPLU_STALL_BRU",
50 "BriefDescription": "Completion stall due to a Branch Unit"
51 },
52 {,
53 "EventCode": "0x45052",
54 "EventName": "PM_4FLOP_CMPL",
55 "BriefDescription": "4 FLOP instruction completed"
56 },
57 {,
58 "EventCode": "0x3D142",
59 "EventName": "PM_MRK_DATA_FROM_LMEM",
60 "BriefDescription": "The processor's data cache was reloaded from the local chip's Memory due to a marked load"
61 },
62 {,
63 "EventCode": "0x4C01E",
64 "EventName": "PM_CMPLU_STALL_CRYPTO",
65 "BriefDescription": "Finish stall because the NTF instruction was routed to the crypto execution pipe and was waiting to finish"
66 },
67 {,
68 "EventCode": "0x3000C",
69 "EventName": "PM_FREQ_DOWN",
70 "BriefDescription": "Power Management: Below Threshold B"
71 },
72 {,
73 "EventCode": "0x4D128",
74 "EventName": "PM_MRK_DATA_FROM_LMEM_CYC",
75 "BriefDescription": "Duration in cycles to reload from the local chip's Memory due to a marked load"
76 },
77 {,
78 "EventCode": "0x4D054",
79 "EventName": "PM_8FLOP_CMPL",
80 "BriefDescription": "8 FLOP instruction completed"
81 },
82 {,
83 "EventCode": "0x10026",
84 "EventName": "PM_TABLEWALK_CYC",
85 "BriefDescription": "Cycles when an instruction tablewalk is active"
86 },
87 {,
88 "EventCode": "0x2C012",
89 "EventName": "PM_CMPLU_STALL_DCACHE_MISS",
90 "BriefDescription": "Finish stall because the NTF instruction was a load that missed the L1 and was waiting for the data to return from the nest"
91 },
92 {,
93 "EventCode": "0x2E04C",
94 "EventName": "PM_DPTEG_FROM_MEMORY",
95 "BriefDescription": "A Page Table Entry was loaded into the TLB from a memory location including L4 from local remote or distant due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
96 },
97 {,
98 "EventCode": "0x3F142",
99 "EventName": "PM_MRK_DPTEG_FROM_L3_DISP_CONFLICT",
100 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 with dispatch conflict due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
101 },
102 {,
103 "EventCode": "0x4F142",
104 "EventName": "PM_MRK_DPTEG_FROM_L3",
105 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
106 },
107 {,
108 "EventCode": "0x10060",
109 "EventName": "PM_TM_TRANS_RUN_CYC",
110 "BriefDescription": "run cycles in transactional state"
111 },
112 {,
113 "EventCode": "0x1E04C",
114 "EventName": "PM_DPTEG_FROM_LL4",
115 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's L4 cache due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
116 },
117 {,
118 "EventCode": "0x45050",
119 "EventName": "PM_1FLOP_CMPL",
120 "BriefDescription": "one flop (fadd, fmul, fsub, fcmp, fsel, fabs, fnabs, fres, fsqrte, fneg) operation completed"
121 }
122]
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/translation.json b/tools/perf/pmu-events/arch/powerpc/power9/translation.json
new file mode 100644
index 000000000000..8c0f12024afa
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power9/translation.json
@@ -0,0 +1,232 @@
1[
2 {,
3 "EventCode": "0x1E",
4 "EventName": "PM_CYC",
5 "BriefDescription": "Processor cycles"
6 },
7 {,
8 "EventCode": "0x30010",
9 "EventName": "PM_PMC2_OVERFLOW",
10 "BriefDescription": "Overflow from counter 2"
11 },
12 {,
13 "EventCode": "0x3C046",
14 "EventName": "PM_DATA_FROM_L21_SHR",
15 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L2 on the same chip due to a demand load"
16 },
17 {,
18 "EventCode": "0x4D05C",
19 "EventName": "PM_DP_QP_FLOP_CMPL",
20 "BriefDescription": "Double-Precion or Quad-Precision instruction completed"
21 },
22 {,
23 "EventCode": "0x4E04C",
24 "EventName": "PM_DPTEG_FROM_DMEM",
25 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group (Distant) due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
26 },
27 {,
28 "EventCode": "0x20016",
29 "EventName": "PM_ST_FIN",
30 "BriefDescription": "Store finish count. Includes speculative activity"
31 },
32 {,
33 "EventCode": "0x44042",
34 "EventName": "PM_INST_FROM_L3",
35 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 due to an instruction fetch (not prefetch)"
36 },
37 {,
38 "EventCode": "0x1504A",
39 "EventName": "PM_IPTEG_FROM_RL2L3_SHR",
40 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a instruction side request"
41 },
42 {,
43 "EventCode": "0x40132",
44 "EventName": "PM_MRK_LSU_FIN",
45 "BriefDescription": "lsu marked instr PPC finish"
46 },
47 {,
48 "EventCode": "0x3C05C",
49 "EventName": "PM_CMPLU_STALL_VFXU",
50 "BriefDescription": "Finish stall due to a vector fixed point instruction in the execution pipeline. These instructions get routed to the ALU, ALU2, and DIV pipes"
51 },
52 {,
53 "EventCode": "0x30066",
54 "EventName": "PM_LSU_FIN",
55 "BriefDescription": "LSU Finished a PPC instruction (up to 4 per cycle)"
56 },
57 {,
58 "EventCode": "0x2011C",
59 "EventName": "PM_MRK_NTC_CYC",
60 "BriefDescription": "Cycles during which the marked instruction is next to complete (completion is held up because the marked instruction hasn't completed yet)"
61 },
62 {,
63 "EventCode": "0x3E048",
64 "EventName": "PM_DPTEG_FROM_DL2L3_SHR",
65 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
66 },
67 {,
68 "EventCode": "0x2E018",
69 "EventName": "PM_CMPLU_STALL_VFXLONG",
70 "BriefDescription": "Completion stall due to a long latency vector fixed point instruction (division, square root)"
71 },
72 {,
73 "EventCode": "0x1C04E",
74 "EventName": "PM_DATA_FROM_L2MISS_MOD",
75 "BriefDescription": "The processor's data cache was reloaded from a location other than the local core's L2 due to a demand load"
76 },
77 {,
78 "EventCode": "0x15048",
79 "EventName": "PM_IPTEG_FROM_ON_CHIP_CACHE",
80 "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on the same chip due to a instruction side request"
81 },
82 {,
83 "EventCode": "0x34046",
84 "EventName": "PM_INST_FROM_L21_SHR",
85 "BriefDescription": "The processor's Instruction cache was reloaded with Shared (S) data from another core's L2 on the same chip due to an instruction fetch (not prefetch)"
86 },
87 {,
88 "EventCode": "0x1E058",
89 "EventName": "PM_STCX_FAIL",
90 "BriefDescription": "stcx failed"
91 },
92 {,
93 "EventCode": "0x20112",
94 "EventName": "PM_MRK_NTF_FIN",
95 "BriefDescription": "Marked next to finish instruction finished"
96 },
97 {,
98 "EventCode": "0x300F0",
99 "EventName": "PM_ST_MISS_L1",
100 "BriefDescription": "Store Missed L1"
101 },
102 {,
103 "EventCode": "0x4C046",
104 "EventName": "PM_DATA_FROM_L21_MOD",
105 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another core's L2 on the same chip due to a demand load"
106 },
107 {,
108 "EventCode": "0x2504A",
109 "EventName": "PM_IPTEG_FROM_RL4",
110 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on the same Node or Group ( Remote) due to a instruction side request"
111 },
112 {,
113 "EventCode": "0x2003E",
114 "EventName": "PM_LSU_LMQ_SRQ_EMPTY_CYC",
115 "BriefDescription": "Cycles in which the LSU is empty for all threads (lmq and srq are completely empty)"
116 },
117 {,
118 "EventCode": "0x201E6",
119 "EventName": "PM_THRESH_EXC_32",
120 "BriefDescription": "Threshold counter exceeded a value of 32"
121 },
122 {,
123 "EventCode": "0x4405C",
124 "EventName": "PM_CMPLU_STALL_VDP",
125 "BriefDescription": "Finish stall because the NTF instruction was a vector instruction issued to the Double Precision execution pipe and waiting to finish. Includes binary floating point instructions in 32 and 64 bit binary floating point format. Not qualified multicycle. Qualified by vector"
126 },
127 {,
128 "EventCode": "0x4D010",
129 "EventName": "PM_PMC1_SAVED",
130 "BriefDescription": "PMC1 Rewind Value saved"
131 },
132 {,
133 "EventCode": "0x200FE",
134 "EventName": "PM_DATA_FROM_L2MISS",
135 "BriefDescription": "Demand LD - L2 Miss (not L2 hit)"
136 },
137 {,
138 "EventCode": "0x2D14A",
139 "EventName": "PM_MRK_DATA_FROM_RL2L3_MOD_CYC",
140 "BriefDescription": "Duration in cycles to reload with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load"
141 },
142 {,
143 "EventCode": "0x10028",
144 "EventName": "PM_STALL_END_ICT_EMPTY",
145 "BriefDescription": "The number a times the core transitioned from a stall to ICT-empty for this thread"
146 },
147 {,
148 "EventCode": "0x2504C",
149 "EventName": "PM_IPTEG_FROM_MEMORY",
150 "BriefDescription": "A Page Table Entry was loaded into the TLB from a memory location including L4 from local remote or distant due to a instruction side request"
151 },
152 {,
153 "EventCode": "0x4504A",
154 "EventName": "PM_IPTEG_FROM_OFF_CHIP_CACHE",
155 "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a instruction side request"
156 },
157 {,
158 "EventCode": "0x1404E",
159 "EventName": "PM_INST_FROM_L2MISS",
160 "BriefDescription": "The processor's Instruction cache was reloaded from a location other than the local core's L2 due to an instruction fetch (not prefetch)"
161 },
162 {,
163 "EventCode": "0x34042",
164 "EventName": "PM_INST_FROM_L3_DISP_CONFLICT",
165 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 with dispatch conflict due to an instruction fetch (not prefetch)"
166 },
167 {,
168 "EventCode": "0x4E048",
169 "EventName": "PM_DPTEG_FROM_DL2L3_MOD",
170 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
171 },
172 {,
173 "EventCode": "0x200F0",
174 "EventName": "PM_ST_CMPL",
175 "BriefDescription": "Stores completed from S2Q (2nd-level store queue)."
176 },
177 {,
178 "EventCode": "0x4E05C",
179 "EventName": "PM_LSU_REJECT_LHS",
180 "BriefDescription": "LSU Reject due to LHS (up to 4 per cycle)"
181 },
182 {,
183 "EventCode": "0x14044",
184 "EventName": "PM_INST_FROM_L3_NO_CONFLICT",
185 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 without conflict due to an instruction fetch (not prefetch)"
186 },
187 {,
188 "EventCode": "0x3E04C",
189 "EventName": "PM_DPTEG_FROM_DL4",
190 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's L4 on a different Node or Group (Distant) due to a data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
191 },
192 {,
193 "EventCode": "0x1F15E",
194 "EventName": "PM_MRK_PROBE_NOP_CMPL",
195 "BriefDescription": "Marked probeNops completed"
196 },
197 {,
198 "EventCode": "0x20018",
199 "EventName": "PM_ST_FWD",
200 "BriefDescription": "Store forwards that finished"
201 },
202 {,
203 "EventCode": "0x1D142",
204 "EventName": "PM_MRK_DATA_FROM_L31_ECO_SHR_CYC",
205 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's ECO L3 on the same chip due to a marked load"
206 },
207 {,
208 "EventCode": "0x24042",
209 "EventName": "PM_INST_FROM_L3_MEPF",
210 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 without dispatch conflicts hit on Mepf state. due to an instruction fetch (not prefetch)"
211 },
212 {,
213 "EventCode": "0x25046",
214 "EventName": "PM_IPTEG_FROM_RL2L3_MOD",
215 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a instruction side request"
216 },
217 {,
218 "EventCode": "0x3504A",
219 "EventName": "PM_IPTEG_FROM_RMEM",
220 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group ( Remote) due to a instruction side request"
221 },
222 {,
223 "EventCode": "0x3C05A",
224 "EventName": "PM_CMPLU_STALL_VDPLONG",
225 "BriefDescription": "Finish stall because the NTF instruction was a scalar multi-cycle instruction issued to the Double Precision execution pipe and waiting to finish. Includes binary floating point instructions in 32 and 64 bit binary floating point format. Qualified by NOT vector AND multicycle"
226 },
227 {,
228 "EventCode": "0x2E01C",
229 "EventName": "PM_CMPLU_STALL_TLBIE",
230 "BriefDescription": "Finish stall because the NTF instruction was a tlbie waiting for response from L2"
231 }
232] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwell/bdw-metrics.json b/tools/perf/pmu-events/arch/x86/broadwell/bdw-metrics.json
new file mode 100644
index 000000000000..00bfdb5c5acb
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwell/bdw-metrics.json
@@ -0,0 +1,164 @@
1[
2 {
3 "BriefDescription": "Instructions Per Cycle (per logical thread)",
4 "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
5 "MetricGroup": "TopDownL1",
6 "MetricName": "IPC"
7 },
8 {
9 "BriefDescription": "Uops Per Instruction",
10 "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY",
11 "MetricGroup": "Pipeline",
12 "MetricName": "UPI"
13 },
14 {
15 "BriefDescription": "Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions",
16 "MetricExpr": "min( 1 , IDQ.MITE_UOPS / ( (UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY) * 16 * ( ICACHE.HIT + ICACHE.MISSES ) / 4.0 ) )",
17 "MetricGroup": "Frontend",
18 "MetricName": "IFetch_Line_Utilization"
19 },
20 {
21 "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)",
22 "MetricExpr": "IDQ.DSB_UOPS / ( IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS )",
23 "MetricGroup": "DSB; Frontend_Bandwidth",
24 "MetricName": "DSB_Coverage"
25 },
26 {
27 "BriefDescription": "Cycles Per Instruction (threaded)",
28 "MetricExpr": "1 / (INST_RETIRED.ANY / cycles)",
29 "MetricGroup": "Pipeline;Summary",
30 "MetricName": "CPI"
31 },
32 {
33 "BriefDescription": "Per-thread actual clocks when the logical processor is active. This is called 'Clockticks' in VTune.",
34 "MetricExpr": "CPU_CLK_UNHALTED.THREAD",
35 "MetricGroup": "Summary",
36 "MetricName": "CLKS"
37 },
38 {
39 "BriefDescription": "Total issue-pipeline slots",
40 "MetricExpr": "4*(( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
41 "MetricGroup": "TopDownL1",
42 "MetricName": "SLOTS"
43 },
44 {
45 "BriefDescription": "Total number of retired Instructions",
46 "MetricExpr": "INST_RETIRED.ANY",
47 "MetricGroup": "Summary",
48 "MetricName": "Instructions"
49 },
50 {
51 "BriefDescription": "Instructions Per Cycle (per physical core)",
52 "MetricExpr": "INST_RETIRED.ANY / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
53 "MetricGroup": "SMT",
54 "MetricName": "CoreIPC"
55 },
56 {
57 "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
58 "MetricExpr": "UOPS_EXECUTED.THREAD / (( cpu@UOPS_EXECUTED.CORE\\,cmask\\=1@ / 2) if #SMT_on else UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC)",
59 "MetricGroup": "Pipeline;Ports_Utilization",
60 "MetricName": "ILP"
61 },
62 {
63 "BriefDescription": "Average Branch Address Clear Cost (fraction of cycles)",
64 "MetricExpr": "2* (( RS_EVENTS.EMPTY_CYCLES - ICACHE.IFDATA_STALL - (( 14 * ITLB_MISSES.STLB_HIT + cpu@ITLB_MISSES.WALK_DURATION\\,cmask\\=1@ + 7* ITLB_MISSES.WALK_COMPLETED )) ) / RS_EVENTS.EMPTY_END)",
65 "MetricGroup": "Unknown_Branches",
66 "MetricName": "BAClear_Cost"
67 },
68 {
69 "BriefDescription": "Core actual clocks when any thread is active on the physical core",
70 "MetricExpr": "( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else CPU_CLK_UNHALTED.THREAD",
71 "MetricGroup": "SMT",
72 "MetricName": "CORE_CLKS"
73 },
74 {
75 "BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads",
76 "MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_UOPS_RETIRED.L1_MISS + mem_load_uops_retired.hit_lfb )",
77 "MetricGroup": "Memory_Bound;Memory_Lat",
78 "MetricName": "Load_Miss_Real_Latency"
79 },
80 {
81 "BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least 1 such miss)",
82 "MetricExpr": "L1D_PEND_MISS.PENDING / (( cpu@l1d_pend_miss.pending_cycles\\,any\\=1@ / 2) if #SMT_on else L1D_PEND_MISS.PENDING_CYCLES)",
83 "MetricGroup": "Memory_Bound;Memory_BW",
84 "MetricName": "MLP"
85 },
86 {
87 "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
88 "MetricExpr": "( cpu@ITLB_MISSES.WALK_DURATION\\,cmask\\=1@ + cpu@DTLB_LOAD_MISSES.WALK_DURATION\\,cmask\\=1@ + cpu@DTLB_STORE_MISSES.WALK_DURATION\\,cmask\\=1@ + 7*(DTLB_STORE_MISSES.WALK_COMPLETED+DTLB_LOAD_MISSES.WALK_COMPLETED+ITLB_MISSES.WALK_COMPLETED)) / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
89 "MetricGroup": "TLB",
90 "MetricName": "Page_Walks_Utilization"
91 },
92 {
93 "BriefDescription": "Average CPU Utilization",
94 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
95 "MetricGroup": "Summary",
96 "MetricName": "CPU_Utilization"
97 },
98 {
99 "BriefDescription": "Giga Floating Point Operations Per Second",
100 "MetricExpr": "(( 1*( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2* FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4*( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8* FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE )) / 1000000000 / duration_time",
101 "MetricGroup": "FLOPS;Summary",
102 "MetricName": "GFLOPs"
103 },
104 {
105 "BriefDescription": "Average Frequency Utilization relative nominal frequency",
106 "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC",
107 "MetricGroup": "Power",
108 "MetricName": "Turbo_Utilization"
109 },
110 {
111 "BriefDescription": "Fraction of cycles where both hardware threads were active",
112 "MetricExpr": "1 - CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
113 "MetricGroup": "SMT;Summary",
114 "MetricName": "SMT_2T_Utilization"
115 },
116 {
117 "BriefDescription": "Fraction of cycles spent in Kernel mode",
118 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
119 "MetricGroup": "Summary",
120 "MetricName": "Kernel_Utilization"
121 },
122 {
123 "BriefDescription": "C3 residency percent per core",
124 "MetricExpr": "(cstate_core@c3\\-residency@ / msr@tsc@) * 100",
125 "MetricGroup": "Power",
126 "MetricName": "C3_Core_Residency"
127 },
128 {
129 "BriefDescription": "C6 residency percent per core",
130 "MetricExpr": "(cstate_core@c6\\-residency@ / msr@tsc@) * 100",
131 "MetricGroup": "Power",
132 "MetricName": "C6_Core_Residency"
133 },
134 {
135 "BriefDescription": "C7 residency percent per core",
136 "MetricExpr": "(cstate_core@c7\\-residency@ / msr@tsc@) * 100",
137 "MetricGroup": "Power",
138 "MetricName": "C7_Core_Residency"
139 },
140 {
141 "BriefDescription": "C2 residency percent per package",
142 "MetricExpr": "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100",
143 "MetricGroup": "Power",
144 "MetricName": "C2_Pkg_Residency"
145 },
146 {
147 "BriefDescription": "C3 residency percent per package",
148 "MetricExpr": "(cstate_pkg@c3\\-residency@ / msr@tsc@) * 100",
149 "MetricGroup": "Power",
150 "MetricName": "C3_Pkg_Residency"
151 },
152 {
153 "BriefDescription": "C6 residency percent per package",
154 "MetricExpr": "(cstate_pkg@c6\\-residency@ / msr@tsc@) * 100",
155 "MetricGroup": "Power",
156 "MetricName": "C6_Pkg_Residency"
157 },
158 {
159 "BriefDescription": "C7 residency percent per package",
160 "MetricExpr": "(cstate_pkg@c7\\-residency@ / msr@tsc@) * 100",
161 "MetricGroup": "Power",
162 "MetricName": "C7_Pkg_Residency"
163 }
164]
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json b/tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json
new file mode 100644
index 000000000000..49c5f123d811
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json
@@ -0,0 +1,164 @@
1[
2 {
3 "BriefDescription": "Instructions Per Cycle (per logical thread)",
4 "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
5 "MetricGroup": "TopDownL1",
6 "MetricName": "IPC"
7 },
8 {
9 "BriefDescription": "Uops Per Instruction",
10 "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY",
11 "MetricGroup": "Pipeline",
12 "MetricName": "UPI"
13 },
14 {
15 "BriefDescription": "Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions",
16 "MetricExpr": "min( 1 , IDQ.MITE_UOPS / ( UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY * 16 * ( ICACHE.HIT + ICACHE.MISSES ) / 4.0 ) )",
17 "MetricGroup": "Frontend",
18 "MetricName": "IFetch_Line_Utilization"
19 },
20 {
21 "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)",
22 "MetricExpr": "IDQ.DSB_UOPS / ( IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS )",
23 "MetricGroup": "DSB; Frontend_Bandwidth",
24 "MetricName": "DSB_Coverage"
25 },
26 {
27 "BriefDescription": "Cycles Per Instruction (threaded)",
28 "MetricExpr": "1 / INST_RETIRED.ANY / cycles",
29 "MetricGroup": "Pipeline;Summary",
30 "MetricName": "CPI"
31 },
32 {
33 "BriefDescription": "Per-thread actual clocks when the logical processor is active. This is called 'Clockticks' in VTune.",
34 "MetricExpr": "CPU_CLK_UNHALTED.THREAD",
35 "MetricGroup": "Summary",
36 "MetricName": "CLKS"
37 },
38 {
39 "BriefDescription": "Total issue-pipeline slots",
40 "MetricExpr": "4*( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles",
41 "MetricGroup": "TopDownL1",
42 "MetricName": "SLOTS"
43 },
44 {
45 "BriefDescription": "Total number of retired Instructions",
46 "MetricExpr": "INST_RETIRED.ANY",
47 "MetricGroup": "Summary",
48 "MetricName": "Instructions"
49 },
50 {
51 "BriefDescription": "Instructions Per Cycle (per physical core)",
52 "MetricExpr": "INST_RETIRED.ANY / ( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles",
53 "MetricGroup": "SMT",
54 "MetricName": "CoreIPC"
55 },
56 {
57 "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
58 "MetricExpr": "UOPS_EXECUTED.THREAD / ( cpu@uops_executed.core\\,cmask\\=1@ / 2) if #SMT_on else UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
59 "MetricGroup": "Pipeline;Ports_Utilization",
60 "MetricName": "ILP"
61 },
62 {
63 "BriefDescription": "Average Branch Address Clear Cost (fraction of cycles)",
64 "MetricExpr": "2* ( RS_EVENTS.EMPTY_CYCLES - ICACHE.IFDATA_STALL - ( 14 * ITLB_MISSES.STLB_HIT + cpu@ITLB_MISSES.WALK_DURATION\\,cmask\\=1@ + 7* ITLB_MISSES.WALK_COMPLETED ) ) / RS_EVENTS.EMPTY_END",
65 "MetricGroup": "Unknown_Branches",
66 "MetricName": "BAClear_Cost"
67 },
68 {
69 "BriefDescription": "Core actual clocks when any thread is active on the physical core",
70 "MetricExpr": "( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else CPU_CLK_UNHALTED.THREAD",
71 "MetricGroup": "SMT",
72 "MetricName": "CORE_CLKS"
73 },
74 {
75 "BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads",
76 "MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_UOPS_RETIRED.L1_MISS + mem_load_uops_retired.hit_lfb )",
77 "MetricGroup": "Memory_Bound;Memory_Lat",
78 "MetricName": "Load_Miss_Real_Latency"
79 },
80 {
81 "BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least 1 such miss)",
82 "MetricExpr": "L1D_PEND_MISS.PENDING / ( cpu@l1d_pend_miss.pending_cycles\\,any\\=1@ / 2) if #SMT_on else L1D_PEND_MISS.PENDING_CYCLES",
83 "MetricGroup": "Memory_Bound;Memory_BW",
84 "MetricName": "MLP"
85 },
86 {
87 "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
88 "MetricExpr": "( cpu@ITLB_MISSES.WALK_DURATION\\,cmask\\=1@ + cpu@DTLB_LOAD_MISSES.WALK_DURATION\\,cmask\\=1@ + cpu@DTLB_STORE_MISSES.WALK_DURATION\\,cmask\\=1@ + 7*(DTLB_STORE_MISSES.WALK_COMPLETED+DTLB_LOAD_MISSES.WALK_COMPLETED+ITLB_MISSES.WALK_COMPLETED)) / ( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles",
89 "MetricGroup": "TLB",
90 "MetricName": "Page_Walks_Utilization"
91 },
92 {
93 "BriefDescription": "Average CPU Utilization",
94 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
95 "MetricGroup": "Summary",
96 "MetricName": "CPU_Utilization"
97 },
98 {
99 "BriefDescription": "Giga Floating Point Operations Per Second",
100 "MetricExpr": "( 1*( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2* FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4*( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8* FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE ) / 1000000000 / duration_time",
101 "MetricGroup": "FLOPS;Summary",
102 "MetricName": "GFLOPs"
103 },
104 {
105 "BriefDescription": "Average Frequency Utilization relative nominal frequency",
106 "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC",
107 "MetricGroup": "Power",
108 "MetricName": "Turbo_Utilization"
109 },
110 {
111 "BriefDescription": "Fraction of cycles where both hardware threads were active",
112 "MetricExpr": "1 - CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
113 "MetricGroup": "SMT;Summary",
114 "MetricName": "SMT_2T_Utilization"
115 },
116 {
117 "BriefDescription": "Fraction of cycles spent in Kernel mode",
118 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
119 "MetricGroup": "Summary",
120 "MetricName": "Kernel_Utilization"
121 },
122 {
123 "BriefDescription": "C3 residency percent per core",
124 "MetricExpr": "(cstate_core@c3\\-residency@ / msr@tsc@) * 100",
125 "MetricGroup": "Power",
126 "MetricName": "C3_Core_Residency"
127 },
128 {
129 "BriefDescription": "C6 residency percent per core",
130 "MetricExpr": "(cstate_core@c6\\-residency@ / msr@tsc@) * 100",
131 "MetricGroup": "Power",
132 "MetricName": "C6_Core_Residency"
133 },
134 {
135 "BriefDescription": "C7 residency percent per core",
136 "MetricExpr": "(cstate_core@c7\\-residency@ / msr@tsc@) * 100",
137 "MetricGroup": "Power",
138 "MetricName": "C7_Core_Residency"
139 },
140 {
141 "BriefDescription": "C2 residency percent per package",
142 "MetricExpr": "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100",
143 "MetricGroup": "Power",
144 "MetricName": "C2_Pkg_Residency"
145 },
146 {
147 "BriefDescription": "C3 residency percent per package",
148 "MetricExpr": "(cstate_pkg@c3\\-residency@ / msr@tsc@) * 100",
149 "MetricGroup": "Power",
150 "MetricName": "C3_Pkg_Residency"
151 },
152 {
153 "BriefDescription": "C6 residency percent per package",
154 "MetricExpr": "(cstate_pkg@c6\\-residency@ / msr@tsc@) * 100",
155 "MetricGroup": "Power",
156 "MetricName": "C6_Pkg_Residency"
157 },
158 {
159 "BriefDescription": "C7 residency percent per package",
160 "MetricExpr": "(cstate_pkg@c7\\-residency@ / msr@tsc@) * 100",
161 "MetricGroup": "Power",
162 "MetricName": "C7_Pkg_Residency"
163 }
164]
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/bdx-metrics.json b/tools/perf/pmu-events/arch/x86/broadwellx/bdx-metrics.json
new file mode 100644
index 000000000000..5a7f1ec24200
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/bdx-metrics.json
@@ -0,0 +1,164 @@
1[
2 {
3 "BriefDescription": "Instructions Per Cycle (per logical thread)",
4 "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
5 "MetricGroup": "TopDownL1",
6 "MetricName": "IPC"
7 },
8 {
9 "BriefDescription": "Uops Per Instruction",
10 "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY",
11 "MetricGroup": "Pipeline",
12 "MetricName": "UPI"
13 },
14 {
15 "BriefDescription": "Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions",
16 "MetricExpr": "min( 1 , IDQ.MITE_UOPS / ( (UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY) * 16 * ( ICACHE.HIT + ICACHE.MISSES ) / 4.0 ) )",
17 "MetricGroup": "Frontend",
18 "MetricName": "IFetch_Line_Utilization"
19 },
20 {
21 "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)",
22 "MetricExpr": "IDQ.DSB_UOPS / ( IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS )",
23 "MetricGroup": "DSB; Frontend_Bandwidth",
24 "MetricName": "DSB_Coverage"
25 },
26 {
27 "BriefDescription": "Cycles Per Instruction (threaded)",
28 "MetricExpr": "1 / (INST_RETIRED.ANY / cycles)",
29 "MetricGroup": "Pipeline;Summary",
30 "MetricName": "CPI"
31 },
32 {
33 "BriefDescription": "Per-thread actual clocks when the logical processor is active. This is called 'Clockticks' in VTune.",
34 "MetricExpr": "CPU_CLK_UNHALTED.THREAD",
35 "MetricGroup": "Summary",
36 "MetricName": "CLKS"
37 },
38 {
39 "BriefDescription": "Total issue-pipeline slots",
40 "MetricExpr": "4*(( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
41 "MetricGroup": "TopDownL1",
42 "MetricName": "SLOTS"
43 },
44 {
45 "BriefDescription": "Total number of retired Instructions",
46 "MetricExpr": "INST_RETIRED.ANY",
47 "MetricGroup": "Summary",
48 "MetricName": "Instructions"
49 },
50 {
51 "BriefDescription": "Instructions Per Cycle (per physical core)",
52 "MetricExpr": "INST_RETIRED.ANY / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
53 "MetricGroup": "SMT",
54 "MetricName": "CoreIPC"
55 },
56 {
57 "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
58 "MetricExpr": "UOPS_EXECUTED.THREAD / (( cpu@UOPS_EXECUTED.CORE\\,cmask\\=1@ / 2) if #SMT_on else UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC)",
59 "MetricGroup": "Pipeline;Ports_Utilization",
60 "MetricName": "ILP"
61 },
62 {
63 "BriefDescription": "Average Branch Address Clear Cost (fraction of cycles)",
64 "MetricExpr": "2* (( RS_EVENTS.EMPTY_CYCLES - ICACHE.IFDATA_STALL - (( 14 * ITLB_MISSES.STLB_HIT + cpu@ITLB_MISSES.WALK_DURATION\\,cmask\\=1@ + 7* ITLB_MISSES.WALK_COMPLETED )) ) / RS_EVENTS.EMPTY_END)",
65 "MetricGroup": "Unknown_Branches",
66 "MetricName": "BAClear_Cost"
67 },
68 {
69 "BriefDescription": "Core actual clocks when any thread is active on the physical core",
70 "MetricExpr": "( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else CPU_CLK_UNHALTED.THREAD",
71 "MetricGroup": "SMT",
72 "MetricName": "CORE_CLKS"
73 },
74 {
75 "BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads",
76 "MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_UOPS_RETIRED.L1_MISS + mem_load_uops_retired.hit_lfb )",
77 "MetricGroup": "Memory_Bound;Memory_Lat",
78 "MetricName": "Load_Miss_Real_Latency"
79 },
80 {
81 "BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least 1 such miss)",
82 "MetricExpr": "L1D_PEND_MISS.PENDING / (( cpu@l1d_pend_miss.pending_cycles\\,any\\=1@ / 2) if #SMT_on else L1D_PEND_MISS.PENDING_CYCLES)",
83 "MetricGroup": "Memory_Bound;Memory_BW",
84 "MetricName": "MLP"
85 },
86 {
87 "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
88 "MetricExpr": "( ITLB_MISSES.WALK_DURATION + DTLB_LOAD_MISSES.WALK_DURATION + DTLB_STORE_MISSES.WALK_DURATION + 7*(DTLB_STORE_MISSES.WALK_COMPLETED+DTLB_LOAD_MISSES.WALK_COMPLETED+ITLB_MISSES.WALK_COMPLETED) ) / (2*(( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles))",
89 "MetricGroup": "TLB",
90 "MetricName": "Page_Walks_Utilization"
91 },
92 {
93 "BriefDescription": "Average CPU Utilization",
94 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
95 "MetricGroup": "Summary",
96 "MetricName": "CPU_Utilization"
97 },
98 {
99 "BriefDescription": "Giga Floating Point Operations Per Second",
100 "MetricExpr": "(( 1*( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2* FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4*( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8* FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE )) / 1000000000 / duration_time",
101 "MetricGroup": "FLOPS;Summary",
102 "MetricName": "GFLOPs"
103 },
104 {
105 "BriefDescription": "Average Frequency Utilization relative nominal frequency",
106 "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC",
107 "MetricGroup": "Power",
108 "MetricName": "Turbo_Utilization"
109 },
110 {
111 "BriefDescription": "Fraction of cycles where both hardware threads were active",
112 "MetricExpr": "1 - CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
113 "MetricGroup": "SMT;Summary",
114 "MetricName": "SMT_2T_Utilization"
115 },
116 {
117 "BriefDescription": "Fraction of cycles spent in Kernel mode",
118 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
119 "MetricGroup": "Summary",
120 "MetricName": "Kernel_Utilization"
121 },
122 {
123 "BriefDescription": "C3 residency percent per core",
124 "MetricExpr": "(cstate_core@c3\\-residency@ / msr@tsc@) * 100",
125 "MetricGroup": "Power",
126 "MetricName": "C3_Core_Residency"
127 },
128 {
129 "BriefDescription": "C6 residency percent per core",
130 "MetricExpr": "(cstate_core@c6\\-residency@ / msr@tsc@) * 100",
131 "MetricGroup": "Power",
132 "MetricName": "C6_Core_Residency"
133 },
134 {
135 "BriefDescription": "C7 residency percent per core",
136 "MetricExpr": "(cstate_core@c7\\-residency@ / msr@tsc@) * 100",
137 "MetricGroup": "Power",
138 "MetricName": "C7_Core_Residency"
139 },
140 {
141 "BriefDescription": "C2 residency percent per package",
142 "MetricExpr": "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100",
143 "MetricGroup": "Power",
144 "MetricName": "C2_Pkg_Residency"
145 },
146 {
147 "BriefDescription": "C3 residency percent per package",
148 "MetricExpr": "(cstate_pkg@c3\\-residency@ / msr@tsc@) * 100",
149 "MetricGroup": "Power",
150 "MetricName": "C3_Pkg_Residency"
151 },
152 {
153 "BriefDescription": "C6 residency percent per package",
154 "MetricExpr": "(cstate_pkg@c6\\-residency@ / msr@tsc@) * 100",
155 "MetricGroup": "Power",
156 "MetricName": "C6_Pkg_Residency"
157 },
158 {
159 "BriefDescription": "C7 residency percent per package",
160 "MetricExpr": "(cstate_pkg@c7\\-residency@ / msr@tsc@) * 100",
161 "MetricGroup": "Power",
162 "MetricName": "C7_Pkg_Residency"
163 }
164]
diff --git a/tools/perf/pmu-events/arch/x86/goldmontplus/cache.json b/tools/perf/pmu-events/arch/x86/goldmontplus/cache.json
new file mode 100644
index 000000000000..b4791b443a66
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/goldmontplus/cache.json
@@ -0,0 +1,1453 @@
1[
2 {
3 "CollectPEBSRecord": "1",
4 "PublicDescription": "Counts memory requests originating from the core that miss in the L2 cache.",
5 "EventCode": "0x2E",
6 "Counter": "0,1,2,3",
7 "UMask": "0x41",
8 "PEBScounters": "0,1,2,3",
9 "EventName": "LONGEST_LAT_CACHE.MISS",
10 "PDIR_COUNTER": "na",
11 "SampleAfterValue": "200003",
12 "BriefDescription": "L2 cache request misses"
13 },
14 {
15 "CollectPEBSRecord": "1",
16 "PublicDescription": "Counts memory requests originating from the core that reference a cache line in the L2 cache.",
17 "EventCode": "0x2E",
18 "Counter": "0,1,2,3",
19 "UMask": "0x4f",
20 "PEBScounters": "0,1,2,3",
21 "EventName": "LONGEST_LAT_CACHE.REFERENCE",
22 "PDIR_COUNTER": "na",
23 "SampleAfterValue": "200003",
24 "BriefDescription": "L2 cache requests"
25 },
26 {
27 "CollectPEBSRecord": "1",
28 "PublicDescription": "Counts the number of demand and prefetch transactions that the L2 XQ rejects due to a full or near full condition which likely indicates back pressure from the intra-die interconnect (IDI) fabric. The XQ may reject transactions from the L2Q (non-cacheable requests), L2 misses and L2 write-back victims.",
29 "EventCode": "0x30",
30 "Counter": "0,1,2,3",
31 "UMask": "0x0",
32 "PEBScounters": "0,1,2,3",
33 "EventName": "L2_REJECT_XQ.ALL",
34 "PDIR_COUNTER": "na",
35 "SampleAfterValue": "200003",
36 "BriefDescription": "Requests rejected by the XQ"
37 },
38 {
39 "CollectPEBSRecord": "1",
40 "PublicDescription": "Counts the number of demand and L1 prefetcher requests rejected by the L2Q due to a full or nearly full condition which likely indicates back pressure from L2Q. It also counts requests that would have gone directly to the XQ, but are rejected due to a full or nearly full condition, indicating back pressure from the IDI link. The L2Q may also reject transactions from a core to insure fairness between cores, or to delay a core's dirty eviction when the address conflicts with incoming external snoops.",
41 "EventCode": "0x31",
42 "Counter": "0,1,2,3",
43 "UMask": "0x0",
44 "PEBScounters": "0,1,2,3",
45 "EventName": "CORE_REJECT_L2Q.ALL",
46 "PDIR_COUNTER": "na",
47 "SampleAfterValue": "200003",
48 "BriefDescription": "Requests rejected by the L2Q"
49 },
50 {
51 "CollectPEBSRecord": "1",
52 "PublicDescription": "Counts when a modified (dirty) cache line is evicted from the data L1 cache and needs to be written back to memory. No count will occur if the evicted line is clean, and hence does not require a writeback.",
53 "EventCode": "0x51",
54 "Counter": "0,1,2,3",
55 "UMask": "0x1",
56 "PEBScounters": "0,1,2,3",
57 "EventName": "DL1.REPLACEMENT",
58 "PDIR_COUNTER": "na",
59 "SampleAfterValue": "200003",
60 "BriefDescription": "L1 Cache evictions for dirty data"
61 },
62 {
63 "CollectPEBSRecord": "1",
64 "PublicDescription": "Counts cycles that fetch is stalled due to an outstanding ICache miss. That is, the decoder queue is able to accept bytes, but the fetch unit is unable to provide bytes due to an ICache miss. Note: this event is not the same as the total number of cycles spent retrieving instruction cache lines from the memory hierarchy.",
65 "EventCode": "0x86",
66 "Counter": "0,1,2,3",
67 "UMask": "0x2",
68 "PEBScounters": "0,1,2,3",
69 "EventName": "FETCH_STALL.ICACHE_FILL_PENDING_CYCLES",
70 "PDIR_COUNTER": "na",
71 "SampleAfterValue": "200003",
72 "BriefDescription": "Cycles code-fetch stalled due to an outstanding ICache miss."
73 },
74 {
75 "CollectPEBSRecord": "1",
76 "EventCode": "0xB7",
77 "Counter": "0,1,2,3",
78 "UMask": "0x1",
79 "PEBScounters": "0,1,2,3",
80 "EventName": "OFFCORE_RESPONSE",
81 "PDIR_COUNTER": "na",
82 "SampleAfterValue": "100007",
83 "BriefDescription": "Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)"
84 },
85 {
86 "PEBS": "2",
87 "CollectPEBSRecord": "2",
88 "PublicDescription": "Counts locked memory uops retired. This includes regular locks and bus locks. (To specifically count bus locks only, see the Offcore response event.) A locked access is one with a lock prefix, or an exchange to memory. See the SDM for a complete description of which memory load accesses are locks.",
89 "EventCode": "0xD0",
90 "Counter": "0,1,2,3",
91 "UMask": "0x21",
92 "PEBScounters": "0,1,2,3",
93 "EventName": "MEM_UOPS_RETIRED.LOCK_LOADS",
94 "SampleAfterValue": "200003",
95 "BriefDescription": "Locked load uops retired (Precise event capable)"
96 },
97 {
98 "PEBS": "2",
99 "CollectPEBSRecord": "2",
100 "PublicDescription": "Counts load uops retired where the data requested spans a 64 byte cache line boundary.",
101 "EventCode": "0xD0",
102 "Counter": "0,1,2,3",
103 "UMask": "0x41",
104 "PEBScounters": "0,1,2,3",
105 "EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS",
106 "SampleAfterValue": "200003",
107 "BriefDescription": "Load uops retired that split a cache-line (Precise event capable)"
108 },
109 {
110 "PEBS": "2",
111 "CollectPEBSRecord": "2",
112 "PublicDescription": "Counts store uops retired where the data requested spans a 64 byte cache line boundary.",
113 "EventCode": "0xD0",
114 "Counter": "0,1,2,3",
115 "UMask": "0x42",
116 "PEBScounters": "0,1,2,3",
117 "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
118 "SampleAfterValue": "200003",
119 "BriefDescription": "Stores uops retired that split a cache-line (Precise event capable)"
120 },
121 {
122 "PEBS": "2",
123 "CollectPEBSRecord": "2",
124 "PublicDescription": "Counts memory uops retired where the data requested spans a 64 byte cache line boundary.",
125 "EventCode": "0xD0",
126 "Counter": "0,1,2,3",
127 "UMask": "0x43",
128 "PEBScounters": "0,1,2,3",
129 "EventName": "MEM_UOPS_RETIRED.SPLIT",
130 "SampleAfterValue": "200003",
131 "BriefDescription": "Memory uops retired that split a cache-line (Precise event capable)"
132 },
133 {
134 "PEBS": "2",
135 "CollectPEBSRecord": "2",
136 "PublicDescription": "Counts the number of load uops retired.",
137 "EventCode": "0xD0",
138 "Counter": "0,1,2,3",
139 "UMask": "0x81",
140 "PEBScounters": "0,1,2,3",
141 "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
142 "SampleAfterValue": "200003",
143 "BriefDescription": "Load uops retired (Precise event capable)"
144 },
145 {
146 "PEBS": "2",
147 "CollectPEBSRecord": "2",
148 "PublicDescription": "Counts the number of store uops retired.",
149 "EventCode": "0xD0",
150 "Counter": "0,1,2,3",
151 "UMask": "0x82",
152 "PEBScounters": "0,1,2,3",
153 "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
154 "SampleAfterValue": "200003",
155 "BriefDescription": "Store uops retired (Precise event capable)"
156 },
157 {
158 "PEBS": "2",
159 "CollectPEBSRecord": "2",
160 "PublicDescription": "Counts the number of memory uops retired that is either a loads or a store or both.",
161 "EventCode": "0xD0",
162 "Counter": "0,1,2,3",
163 "UMask": "0x83",
164 "PEBScounters": "0,1,2,3",
165 "EventName": "MEM_UOPS_RETIRED.ALL",
166 "SampleAfterValue": "200003",
167 "BriefDescription": "Memory uops retired (Precise event capable)"
168 },
169 {
170 "PEBS": "2",
171 "CollectPEBSRecord": "2",
172 "PublicDescription": "Counts load uops retired that hit the L1 data cache.",
173 "EventCode": "0xD1",
174 "Counter": "0,1,2,3",
175 "UMask": "0x1",
176 "PEBScounters": "0,1,2,3",
177 "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
178 "SampleAfterValue": "200003",
179 "BriefDescription": "Load uops retired that hit L1 data cache (Precise event capable)"
180 },
181 {
182 "PEBS": "2",
183 "CollectPEBSRecord": "2",
184 "PublicDescription": "Counts load uops retired that hit in the L2 cache.",
185 "EventCode": "0xD1",
186 "Counter": "0,1,2,3",
187 "UMask": "0x2",
188 "PEBScounters": "0,1,2,3",
189 "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
190 "SampleAfterValue": "200003",
191 "BriefDescription": "Load uops retired that hit L2 (Precise event capable)"
192 },
193 {
194 "PEBS": "2",
195 "CollectPEBSRecord": "2",
196 "PublicDescription": "Counts load uops retired that miss the L1 data cache.",
197 "EventCode": "0xD1",
198 "Counter": "0,1,2,3",
199 "UMask": "0x8",
200 "PEBScounters": "0,1,2,3",
201 "EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS",
202 "SampleAfterValue": "200003",
203 "BriefDescription": "Load uops retired that missed L1 data cache (Precise event capable)"
204 },
205 {
206 "PEBS": "2",
207 "CollectPEBSRecord": "2",
208 "PublicDescription": "Counts load uops retired that miss in the L2 cache.",
209 "EventCode": "0xD1",
210 "Counter": "0,1,2,3",
211 "UMask": "0x10",
212 "PEBScounters": "0,1,2,3",
213 "EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS",
214 "SampleAfterValue": "200003",
215 "BriefDescription": "Load uops retired that missed L2 (Precise event capable)"
216 },
217 {
218 "PEBS": "2",
219 "CollectPEBSRecord": "2",
220 "PublicDescription": "Counts load uops retired where the cache line containing the data was in the modified state of another core or modules cache (HITM). More specifically, this means that when the load address was checked by other caching agents (typically another processor) in the system, one of those caching agents indicated that they had a dirty copy of the data. Loads that obtain a HITM response incur greater latency than most is typical for a load. In addition, since HITM indicates that some other processor had this data in its cache, it implies that the data was shared between processors, or potentially was a lock or semaphore value. This event is useful for locating sharing, false sharing, and contended locks.",
221 "EventCode": "0xD1",
222 "Counter": "0,1,2,3",
223 "UMask": "0x20",
224 "PEBScounters": "0,1,2,3",
225 "EventName": "MEM_LOAD_UOPS_RETIRED.HITM",
226 "SampleAfterValue": "200003",
227 "BriefDescription": "Memory uop retired where cross core or cross module HITM occurred (Precise event capable)"
228 },
229 {
230 "PEBS": "2",
231 "CollectPEBSRecord": "2",
232 "PublicDescription": "Counts memory load uops retired where the data is retrieved from the WCB (or fill buffer), indicating that the load found its data while that data was in the process of being brought into the L1 cache. Typically a load will receive this indication when some other load or prefetch missed the L1 cache and was in the process of retrieving the cache line containing the data, but that process had not yet finished (and written the data back to the cache). For example, consider load X and Y, both referencing the same cache line that is not in the L1 cache. If load X misses cache first, it obtains and WCB (or fill buffer) and begins the process of requesting the data. When load Y requests the data, it will either hit the WCB, or the L1 cache, depending on exactly what time the request to Y occurs.",
233 "EventCode": "0xD1",
234 "Counter": "0,1,2,3",
235 "UMask": "0x40",
236 "PEBScounters": "0,1,2,3",
237 "EventName": "MEM_LOAD_UOPS_RETIRED.WCB_HIT",
238 "SampleAfterValue": "200003",
239 "BriefDescription": "Loads retired that hit WCB (Precise event capable)"
240 },
241 {
242 "PEBS": "2",
243 "CollectPEBSRecord": "2",
244 "PublicDescription": "Counts memory load uops retired where the data is retrieved from DRAM. Event is counted at retirement, so the speculative loads are ignored. A memory load can hit (or miss) the L1 cache, hit (or miss) the L2 cache, hit DRAM, hit in the WCB or receive a HITM response.",
245 "EventCode": "0xD1",
246 "Counter": "0,1,2,3",
247 "UMask": "0x80",
248 "PEBScounters": "0,1,2,3",
249 "EventName": "MEM_LOAD_UOPS_RETIRED.DRAM_HIT",
250 "SampleAfterValue": "200003",
251 "BriefDescription": "Loads retired that came from DRAM (Precise event capable)"
252 },
253 {
254 "CollectPEBSRecord": "1",
255 "PublicDescription": "Counts demand cacheable data reads of full cache lines have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
256 "EventCode": "0xB7",
257 "MSRValue": "0x0000010001",
258 "Counter": "0,1,2,3",
259 "UMask": "0x1",
260 "PEBScounters": "0,1,2,3",
261 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
262 "PDIR_COUNTER": "na",
263 "MSRIndex": "0x1a6, 0x1a7",
264 "SampleAfterValue": "100007",
265 "BriefDescription": "Counts demand cacheable data reads of full cache lines have any transaction responses from the uncore subsystem.",
266 "Offcore": "1"
267 },
268 {
269 "CollectPEBSRecord": "1",
270 "PublicDescription": "Counts demand cacheable data reads of full cache lines hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
271 "EventCode": "0xB7",
272 "MSRValue": "0x0000040001",
273 "Counter": "0,1,2,3",
274 "UMask": "0x1",
275 "PEBScounters": "0,1,2,3",
276 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_HIT",
277 "PDIR_COUNTER": "na",
278 "MSRIndex": "0x1a6, 0x1a7",
279 "SampleAfterValue": "100007",
280 "BriefDescription": "Counts demand cacheable data reads of full cache lines hit the L2 cache.",
281 "Offcore": "1"
282 },
283 {
284 "CollectPEBSRecord": "1",
285 "PublicDescription": "Counts demand cacheable data reads of full cache lines true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
286 "EventCode": "0xB7",
287 "MSRValue": "0x0200000001",
288 "Counter": "0,1,2,3",
289 "UMask": "0x1",
290 "PEBScounters": "0,1,2,3",
291 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
292 "PDIR_COUNTER": "na",
293 "MSRIndex": "0x1a6, 0x1a7",
294 "SampleAfterValue": "100007",
295 "BriefDescription": "Counts demand cacheable data reads of full cache lines true miss for the L2 cache with a snoop miss in the other processor module. ",
296 "Offcore": "1"
297 },
298 {
299 "CollectPEBSRecord": "1",
300 "PublicDescription": "Counts demand cacheable data reads of full cache lines miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
301 "EventCode": "0xB7",
302 "MSRValue": "0x1000000001",
303 "Counter": "0,1,2,3",
304 "UMask": "0x1",
305 "PEBScounters": "0,1,2,3",
306 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_MISS.HITM_OTHER_CORE",
307 "PDIR_COUNTER": "na",
308 "MSRIndex": "0x1a6, 0x1a7",
309 "SampleAfterValue": "100007",
310 "BriefDescription": "Counts demand cacheable data reads of full cache lines miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
311 "Offcore": "1"
312 },
313 {
314 "CollectPEBSRecord": "1",
315 "PublicDescription": "Counts demand cacheable data reads of full cache lines outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
316 "EventCode": "0xB7",
317 "MSRValue": "0x4000000001",
318 "Counter": "0,1,2,3",
319 "UMask": "0x1",
320 "PEBScounters": "0,1,2,3",
321 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.OUTSTANDING",
322 "PDIR_COUNTER": "na",
323 "MSRIndex": "0x1a6",
324 "SampleAfterValue": "100007",
325 "BriefDescription": "Counts demand cacheable data reads of full cache lines outstanding, per cycle, from the time of the L2 miss to when any response is received.",
326 "Offcore": "1"
327 },
328 {
329 "CollectPEBSRecord": "1",
330 "PublicDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
331 "EventCode": "0xB7",
332 "MSRValue": "0x0000010002",
333 "Counter": "0,1,2,3",
334 "UMask": "0x1",
335 "PEBScounters": "0,1,2,3",
336 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE",
337 "PDIR_COUNTER": "na",
338 "MSRIndex": "0x1a6, 0x1a7",
339 "SampleAfterValue": "100007",
340 "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line have any transaction responses from the uncore subsystem.",
341 "Offcore": "1"
342 },
343 {
344 "CollectPEBSRecord": "1",
345 "PublicDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
346 "EventCode": "0xB7",
347 "MSRValue": "0x0000040002",
348 "Counter": "0,1,2,3",
349 "UMask": "0x1",
350 "PEBScounters": "0,1,2,3",
351 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_HIT",
352 "PDIR_COUNTER": "na",
353 "MSRIndex": "0x1a6, 0x1a7",
354 "SampleAfterValue": "100007",
355 "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line hit the L2 cache.",
356 "Offcore": "1"
357 },
358 {
359 "CollectPEBSRecord": "1",
360 "PublicDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
361 "EventCode": "0xB7",
362 "MSRValue": "0x0200000002",
363 "Counter": "0,1,2,3",
364 "UMask": "0x1",
365 "PEBScounters": "0,1,2,3",
366 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
367 "PDIR_COUNTER": "na",
368 "MSRIndex": "0x1a6, 0x1a7",
369 "SampleAfterValue": "100007",
370 "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line true miss for the L2 cache with a snoop miss in the other processor module. ",
371 "Offcore": "1"
372 },
373 {
374 "CollectPEBSRecord": "1",
375 "PublicDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
376 "EventCode": "0xB7",
377 "MSRValue": "0x1000000002",
378 "Counter": "0,1,2,3",
379 "UMask": "0x1",
380 "PEBScounters": "0,1,2,3",
381 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_MISS.HITM_OTHER_CORE",
382 "PDIR_COUNTER": "na",
383 "MSRIndex": "0x1a6, 0x1a7",
384 "SampleAfterValue": "100007",
385 "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
386 "Offcore": "1"
387 },
388 {
389 "CollectPEBSRecord": "1",
390 "PublicDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
391 "EventCode": "0xB7",
392 "MSRValue": "0x4000000002",
393 "Counter": "0,1,2,3",
394 "UMask": "0x1",
395 "PEBScounters": "0,1,2,3",
396 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.OUTSTANDING",
397 "PDIR_COUNTER": "na",
398 "MSRIndex": "0x1a6",
399 "SampleAfterValue": "100007",
400 "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line outstanding, per cycle, from the time of the L2 miss to when any response is received.",
401 "Offcore": "1"
402 },
403 {
404 "CollectPEBSRecord": "1",
405 "PublicDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
406 "EventCode": "0xB7",
407 "MSRValue": "0x0000010004",
408 "Counter": "0,1,2,3",
409 "UMask": "0x1",
410 "PEBScounters": "0,1,2,3",
411 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
412 "PDIR_COUNTER": "na",
413 "MSRIndex": "0x1a6, 0x1a7",
414 "SampleAfterValue": "100007",
415 "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache have any transaction responses from the uncore subsystem.",
416 "Offcore": "1"
417 },
418 {
419 "CollectPEBSRecord": "1",
420 "PublicDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
421 "EventCode": "0xB7",
422 "MSRValue": "0x0000040004",
423 "Counter": "0,1,2,3",
424 "UMask": "0x1",
425 "PEBScounters": "0,1,2,3",
426 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_HIT",
427 "PDIR_COUNTER": "na",
428 "MSRIndex": "0x1a6, 0x1a7",
429 "SampleAfterValue": "100007",
430 "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache hit the L2 cache.",
431 "Offcore": "1"
432 },
433 {
434 "CollectPEBSRecord": "1",
435 "PublicDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
436 "EventCode": "0xB7",
437 "MSRValue": "0x0200000004",
438 "Counter": "0,1,2,3",
439 "UMask": "0x1",
440 "PEBScounters": "0,1,2,3",
441 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
442 "PDIR_COUNTER": "na",
443 "MSRIndex": "0x1a6, 0x1a7",
444 "SampleAfterValue": "100007",
445 "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache true miss for the L2 cache with a snoop miss in the other processor module. ",
446 "Offcore": "1"
447 },
448 {
449 "CollectPEBSRecord": "1",
450 "PublicDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
451 "EventCode": "0xB7",
452 "MSRValue": "0x1000000004",
453 "Counter": "0,1,2,3",
454 "UMask": "0x1",
455 "PEBScounters": "0,1,2,3",
456 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_MISS.HITM_OTHER_CORE",
457 "PDIR_COUNTER": "na",
458 "MSRIndex": "0x1a6, 0x1a7",
459 "SampleAfterValue": "100007",
460 "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
461 "Offcore": "1"
462 },
463 {
464 "CollectPEBSRecord": "1",
465 "PublicDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
466 "EventCode": "0xB7",
467 "MSRValue": "0x4000000004",
468 "Counter": "0,1,2,3",
469 "UMask": "0x1",
470 "PEBScounters": "0,1,2,3",
471 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.OUTSTANDING",
472 "PDIR_COUNTER": "na",
473 "MSRIndex": "0x1a6",
474 "SampleAfterValue": "100007",
475 "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache outstanding, per cycle, from the time of the L2 miss to when any response is received.",
476 "Offcore": "1"
477 },
478 {
479 "CollectPEBSRecord": "1",
480 "PublicDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
481 "EventCode": "0xB7",
482 "MSRValue": "0x0000010008",
483 "Counter": "0,1,2,3",
484 "UMask": "0x1",
485 "PEBScounters": "0,1,2,3",
486 "EventName": "OFFCORE_RESPONSE.COREWB.ANY_RESPONSE",
487 "PDIR_COUNTER": "na",
488 "MSRIndex": "0x1a6, 0x1a7",
489 "SampleAfterValue": "100007",
490 "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions have any transaction responses from the uncore subsystem.",
491 "Offcore": "1"
492 },
493 {
494 "CollectPEBSRecord": "1",
495 "PublicDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
496 "EventCode": "0xB7",
497 "MSRValue": "0x0000040008",
498 "Counter": "0,1,2,3",
499 "UMask": "0x1",
500 "PEBScounters": "0,1,2,3",
501 "EventName": "OFFCORE_RESPONSE.COREWB.L2_HIT",
502 "PDIR_COUNTER": "na",
503 "MSRIndex": "0x1a6, 0x1a7",
504 "SampleAfterValue": "100007",
505 "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions hit the L2 cache.",
506 "Offcore": "1"
507 },
508 {
509 "CollectPEBSRecord": "1",
510 "PublicDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
511 "EventCode": "0xB7",
512 "MSRValue": "0x0200000008",
513 "Counter": "0,1,2,3",
514 "UMask": "0x1",
515 "PEBScounters": "0,1,2,3",
516 "EventName": "OFFCORE_RESPONSE.COREWB.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
517 "PDIR_COUNTER": "na",
518 "MSRIndex": "0x1a6, 0x1a7",
519 "SampleAfterValue": "100007",
520 "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions true miss for the L2 cache with a snoop miss in the other processor module. ",
521 "Offcore": "1"
522 },
523 {
524 "CollectPEBSRecord": "1",
525 "PublicDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
526 "EventCode": "0xB7",
527 "MSRValue": "0x1000000008",
528 "Counter": "0,1,2,3",
529 "UMask": "0x1",
530 "PEBScounters": "0,1,2,3",
531 "EventName": "OFFCORE_RESPONSE.COREWB.L2_MISS.HITM_OTHER_CORE",
532 "PDIR_COUNTER": "na",
533 "MSRIndex": "0x1a6, 0x1a7",
534 "SampleAfterValue": "100007",
535 "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
536 "Offcore": "1"
537 },
538 {
539 "CollectPEBSRecord": "1",
540 "PublicDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
541 "EventCode": "0xB7",
542 "MSRValue": "0x4000000008",
543 "Counter": "0,1,2,3",
544 "UMask": "0x1",
545 "PEBScounters": "0,1,2,3",
546 "EventName": "OFFCORE_RESPONSE.COREWB.OUTSTANDING",
547 "PDIR_COUNTER": "na",
548 "MSRIndex": "0x1a6",
549 "SampleAfterValue": "100007",
550 "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions outstanding, per cycle, from the time of the L2 miss to when any response is received.",
551 "Offcore": "1"
552 },
553 {
554 "CollectPEBSRecord": "1",
555 "PublicDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
556 "EventCode": "0xB7",
557 "MSRValue": "0x0000010010",
558 "Counter": "0,1,2,3",
559 "UMask": "0x1",
560 "PEBScounters": "0,1,2,3",
561 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.ANY_RESPONSE",
562 "PDIR_COUNTER": "na",
563 "MSRIndex": "0x1a6, 0x1a7",
564 "SampleAfterValue": "100007",
565 "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher have any transaction responses from the uncore subsystem.",
566 "Offcore": "1"
567 },
568 {
569 "CollectPEBSRecord": "1",
570 "PublicDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
571 "EventCode": "0xB7",
572 "MSRValue": "0x0000040010",
573 "Counter": "0,1,2,3",
574 "UMask": "0x1",
575 "PEBScounters": "0,1,2,3",
576 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_HIT",
577 "PDIR_COUNTER": "na",
578 "MSRIndex": "0x1a6, 0x1a7",
579 "SampleAfterValue": "100007",
580 "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher hit the L2 cache.",
581 "Offcore": "1"
582 },
583 {
584 "CollectPEBSRecord": "1",
585 "PublicDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
586 "EventCode": "0xB7",
587 "MSRValue": "0x0200000010",
588 "Counter": "0,1,2,3",
589 "UMask": "0x1",
590 "PEBScounters": "0,1,2,3",
591 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
592 "PDIR_COUNTER": "na",
593 "MSRIndex": "0x1a6, 0x1a7",
594 "SampleAfterValue": "100007",
595 "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher true miss for the L2 cache with a snoop miss in the other processor module. ",
596 "Offcore": "1"
597 },
598 {
599 "CollectPEBSRecord": "1",
600 "PublicDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
601 "EventCode": "0xB7",
602 "MSRValue": "0x1000000010",
603 "Counter": "0,1,2,3",
604 "UMask": "0x1",
605 "PEBScounters": "0,1,2,3",
606 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_MISS.HITM_OTHER_CORE",
607 "PDIR_COUNTER": "na",
608 "MSRIndex": "0x1a6, 0x1a7",
609 "SampleAfterValue": "100007",
610 "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
611 "Offcore": "1"
612 },
613 {
614 "CollectPEBSRecord": "1",
615 "PublicDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
616 "EventCode": "0xB7",
617 "MSRValue": "0x4000000010",
618 "Counter": "0,1,2,3",
619 "UMask": "0x1",
620 "PEBScounters": "0,1,2,3",
621 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.OUTSTANDING",
622 "PDIR_COUNTER": "na",
623 "MSRIndex": "0x1a6",
624 "SampleAfterValue": "100007",
625 "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher outstanding, per cycle, from the time of the L2 miss to when any response is received.",
626 "Offcore": "1"
627 },
628 {
629 "CollectPEBSRecord": "1",
630 "PublicDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
631 "EventCode": "0xB7",
632 "MSRValue": "0x0000010020",
633 "Counter": "0,1,2,3",
634 "UMask": "0x1",
635 "PEBScounters": "0,1,2,3",
636 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.ANY_RESPONSE",
637 "PDIR_COUNTER": "na",
638 "MSRIndex": "0x1a6, 0x1a7",
639 "SampleAfterValue": "100007",
640 "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher have any transaction responses from the uncore subsystem.",
641 "Offcore": "1"
642 },
643 {
644 "CollectPEBSRecord": "1",
645 "PublicDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
646 "EventCode": "0xB7",
647 "MSRValue": "0x0000040020",
648 "Counter": "0,1,2,3",
649 "UMask": "0x1",
650 "PEBScounters": "0,1,2,3",
651 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_HIT",
652 "PDIR_COUNTER": "na",
653 "MSRIndex": "0x1a6, 0x1a7",
654 "SampleAfterValue": "100007",
655 "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher hit the L2 cache.",
656 "Offcore": "1"
657 },
658 {
659 "CollectPEBSRecord": "1",
660 "PublicDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
661 "EventCode": "0xB7",
662 "MSRValue": "0x0200000020",
663 "Counter": "0,1,2,3",
664 "UMask": "0x1",
665 "PEBScounters": "0,1,2,3",
666 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
667 "PDIR_COUNTER": "na",
668 "MSRIndex": "0x1a6, 0x1a7",
669 "SampleAfterValue": "100007",
670 "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher true miss for the L2 cache with a snoop miss in the other processor module. ",
671 "Offcore": "1"
672 },
673 {
674 "CollectPEBSRecord": "1",
675 "PublicDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
676 "EventCode": "0xB7",
677 "MSRValue": "0x1000000020",
678 "Counter": "0,1,2,3",
679 "UMask": "0x1",
680 "PEBScounters": "0,1,2,3",
681 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_MISS.HITM_OTHER_CORE",
682 "PDIR_COUNTER": "na",
683 "MSRIndex": "0x1a6, 0x1a7",
684 "SampleAfterValue": "100007",
685 "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
686 "Offcore": "1"
687 },
688 {
689 "CollectPEBSRecord": "1",
690 "PublicDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
691 "EventCode": "0xB7",
692 "MSRValue": "0x4000000020",
693 "Counter": "0,1,2,3",
694 "UMask": "0x1",
695 "PEBScounters": "0,1,2,3",
696 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.OUTSTANDING",
697 "PDIR_COUNTER": "na",
698 "MSRIndex": "0x1a6",
699 "SampleAfterValue": "100007",
700 "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher outstanding, per cycle, from the time of the L2 miss to when any response is received.",
701 "Offcore": "1"
702 },
703 {
704 "CollectPEBSRecord": "1",
705 "PublicDescription": "Counts bus lock and split lock requests have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
706 "EventCode": "0xB7",
707 "MSRValue": "0x0000010400",
708 "Counter": "0,1,2,3",
709 "UMask": "0x1",
710 "PEBScounters": "0,1,2,3",
711 "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.ANY_RESPONSE",
712 "PDIR_COUNTER": "na",
713 "MSRIndex": "0x1a6, 0x1a7",
714 "SampleAfterValue": "100007",
715 "BriefDescription": "Counts bus lock and split lock requests have any transaction responses from the uncore subsystem.",
716 "Offcore": "1"
717 },
718 {
719 "CollectPEBSRecord": "1",
720 "PublicDescription": "Counts bus lock and split lock requests hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
721 "EventCode": "0xB7",
722 "MSRValue": "0x0000040400",
723 "Counter": "0,1,2,3",
724 "UMask": "0x1",
725 "PEBScounters": "0,1,2,3",
726 "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_HIT",
727 "PDIR_COUNTER": "na",
728 "MSRIndex": "0x1a6, 0x1a7",
729 "SampleAfterValue": "100007",
730 "BriefDescription": "Counts bus lock and split lock requests hit the L2 cache.",
731 "Offcore": "1"
732 },
733 {
734 "CollectPEBSRecord": "1",
735 "PublicDescription": "Counts bus lock and split lock requests true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
736 "EventCode": "0xB7",
737 "MSRValue": "0x0200000400",
738 "Counter": "0,1,2,3",
739 "UMask": "0x1",
740 "PEBScounters": "0,1,2,3",
741 "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
742 "PDIR_COUNTER": "na",
743 "MSRIndex": "0x1a6, 0x1a7",
744 "SampleAfterValue": "100007",
745 "BriefDescription": "Counts bus lock and split lock requests true miss for the L2 cache with a snoop miss in the other processor module. ",
746 "Offcore": "1"
747 },
748 {
749 "CollectPEBSRecord": "1",
750 "PublicDescription": "Counts bus lock and split lock requests miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
751 "EventCode": "0xB7",
752 "MSRValue": "0x1000000400",
753 "Counter": "0,1,2,3",
754 "UMask": "0x1",
755 "PEBScounters": "0,1,2,3",
756 "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_MISS.HITM_OTHER_CORE",
757 "PDIR_COUNTER": "na",
758 "MSRIndex": "0x1a6, 0x1a7",
759 "SampleAfterValue": "100007",
760 "BriefDescription": "Counts bus lock and split lock requests miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
761 "Offcore": "1"
762 },
763 {
764 "CollectPEBSRecord": "1",
765 "PublicDescription": "Counts bus lock and split lock requests outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
766 "EventCode": "0xB7",
767 "MSRValue": "0x4000000400",
768 "Counter": "0,1,2,3",
769 "UMask": "0x1",
770 "PEBScounters": "0,1,2,3",
771 "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.OUTSTANDING",
772 "PDIR_COUNTER": "na",
773 "MSRIndex": "0x1a6",
774 "SampleAfterValue": "100007",
775 "BriefDescription": "Counts bus lock and split lock requests outstanding, per cycle, from the time of the L2 miss to when any response is received.",
776 "Offcore": "1"
777 },
778 {
779 "CollectPEBSRecord": "1",
780 "PublicDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
781 "EventCode": "0xB7",
782 "MSRValue": "0x0000010800",
783 "Counter": "0,1,2,3",
784 "UMask": "0x1",
785 "PEBScounters": "0,1,2,3",
786 "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.ANY_RESPONSE",
787 "PDIR_COUNTER": "na",
788 "MSRIndex": "0x1a6, 0x1a7",
789 "SampleAfterValue": "100007",
790 "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes have any transaction responses from the uncore subsystem.",
791 "Offcore": "1"
792 },
793 {
794 "CollectPEBSRecord": "1",
795 "PublicDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
796 "EventCode": "0xB7",
797 "MSRValue": "0x0000040800",
798 "Counter": "0,1,2,3",
799 "UMask": "0x1",
800 "PEBScounters": "0,1,2,3",
801 "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.L2_HIT",
802 "PDIR_COUNTER": "na",
803 "MSRIndex": "0x1a6, 0x1a7",
804 "SampleAfterValue": "100007",
805 "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes hit the L2 cache.",
806 "Offcore": "1"
807 },
808 {
809 "CollectPEBSRecord": "1",
810 "PublicDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
811 "EventCode": "0xB7",
812 "MSRValue": "0x0200000800",
813 "Counter": "0,1,2,3",
814 "UMask": "0x1",
815 "PEBScounters": "0,1,2,3",
816 "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
817 "PDIR_COUNTER": "na",
818 "MSRIndex": "0x1a6, 0x1a7",
819 "SampleAfterValue": "100007",
820 "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes true miss for the L2 cache with a snoop miss in the other processor module. ",
821 "Offcore": "1"
822 },
823 {
824 "CollectPEBSRecord": "1",
825 "PublicDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
826 "EventCode": "0xB7",
827 "MSRValue": "0x1000000800",
828 "Counter": "0,1,2,3",
829 "UMask": "0x1",
830 "PEBScounters": "0,1,2,3",
831 "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.L2_MISS.HITM_OTHER_CORE",
832 "PDIR_COUNTER": "na",
833 "MSRIndex": "0x1a6, 0x1a7",
834 "SampleAfterValue": "100007",
835 "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
836 "Offcore": "1"
837 },
838 {
839 "CollectPEBSRecord": "1",
840 "PublicDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
841 "EventCode": "0xB7",
842 "MSRValue": "0x4000000800",
843 "Counter": "0,1,2,3",
844 "UMask": "0x1",
845 "PEBScounters": "0,1,2,3",
846 "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.OUTSTANDING",
847 "PDIR_COUNTER": "na",
848 "MSRIndex": "0x1a6",
849 "SampleAfterValue": "100007",
850 "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes outstanding, per cycle, from the time of the L2 miss to when any response is received.",
851 "Offcore": "1"
852 },
853 {
854 "CollectPEBSRecord": "1",
855 "PublicDescription": "Counts data cache lines requests by software prefetch instructions have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
856 "EventCode": "0xB7",
857 "MSRValue": "0x0000011000",
858 "Counter": "0,1,2,3",
859 "UMask": "0x1",
860 "PEBScounters": "0,1,2,3",
861 "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.ANY_RESPONSE",
862 "PDIR_COUNTER": "na",
863 "MSRIndex": "0x1a6, 0x1a7",
864 "SampleAfterValue": "100007",
865 "BriefDescription": "Counts data cache lines requests by software prefetch instructions have any transaction responses from the uncore subsystem.",
866 "Offcore": "1"
867 },
868 {
869 "CollectPEBSRecord": "1",
870 "PublicDescription": "Counts data cache lines requests by software prefetch instructions hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
871 "EventCode": "0xB7",
872 "MSRValue": "0x0000041000",
873 "Counter": "0,1,2,3",
874 "UMask": "0x1",
875 "PEBScounters": "0,1,2,3",
876 "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.L2_HIT",
877 "PDIR_COUNTER": "na",
878 "MSRIndex": "0x1a6, 0x1a7",
879 "SampleAfterValue": "100007",
880 "BriefDescription": "Counts data cache lines requests by software prefetch instructions hit the L2 cache.",
881 "Offcore": "1"
882 },
883 {
884 "CollectPEBSRecord": "1",
885 "PublicDescription": "Counts data cache lines requests by software prefetch instructions true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
886 "EventCode": "0xB7",
887 "MSRValue": "0x0200001000",
888 "Counter": "0,1,2,3",
889 "UMask": "0x1",
890 "PEBScounters": "0,1,2,3",
891 "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
892 "PDIR_COUNTER": "na",
893 "MSRIndex": "0x1a6, 0x1a7",
894 "SampleAfterValue": "100007",
895 "BriefDescription": "Counts data cache lines requests by software prefetch instructions true miss for the L2 cache with a snoop miss in the other processor module. ",
896 "Offcore": "1"
897 },
898 {
899 "CollectPEBSRecord": "1",
900 "PublicDescription": "Counts data cache lines requests by software prefetch instructions miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
901 "EventCode": "0xB7",
902 "MSRValue": "0x1000001000",
903 "Counter": "0,1,2,3",
904 "UMask": "0x1",
905 "PEBScounters": "0,1,2,3",
906 "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.L2_MISS.HITM_OTHER_CORE",
907 "PDIR_COUNTER": "na",
908 "MSRIndex": "0x1a6, 0x1a7",
909 "SampleAfterValue": "100007",
910 "BriefDescription": "Counts data cache lines requests by software prefetch instructions miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
911 "Offcore": "1"
912 },
913 {
914 "CollectPEBSRecord": "1",
915 "PublicDescription": "Counts data cache lines requests by software prefetch instructions outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
916 "EventCode": "0xB7",
917 "MSRValue": "0x4000001000",
918 "Counter": "0,1,2,3",
919 "UMask": "0x1",
920 "PEBScounters": "0,1,2,3",
921 "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.OUTSTANDING",
922 "PDIR_COUNTER": "na",
923 "MSRIndex": "0x1a6",
924 "SampleAfterValue": "100007",
925 "BriefDescription": "Counts data cache lines requests by software prefetch instructions outstanding, per cycle, from the time of the L2 miss to when any response is received.",
926 "Offcore": "1"
927 },
928 {
929 "CollectPEBSRecord": "1",
930 "PublicDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
931 "EventCode": "0xB7",
932 "MSRValue": "0x0000012000",
933 "Counter": "0,1,2,3",
934 "UMask": "0x1",
935 "PEBScounters": "0,1,2,3",
936 "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.ANY_RESPONSE",
937 "PDIR_COUNTER": "na",
938 "MSRIndex": "0x1a6, 0x1a7",
939 "SampleAfterValue": "100007",
940 "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher have any transaction responses from the uncore subsystem.",
941 "Offcore": "1"
942 },
943 {
944 "CollectPEBSRecord": "1",
945 "PublicDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
946 "EventCode": "0xB7",
947 "MSRValue": "0x0000042000",
948 "Counter": "0,1,2,3",
949 "UMask": "0x1",
950 "PEBScounters": "0,1,2,3",
951 "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_HIT",
952 "PDIR_COUNTER": "na",
953 "MSRIndex": "0x1a6, 0x1a7",
954 "SampleAfterValue": "100007",
955 "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher hit the L2 cache.",
956 "Offcore": "1"
957 },
958 {
959 "CollectPEBSRecord": "1",
960 "PublicDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
961 "EventCode": "0xB7",
962 "MSRValue": "0x0200002000",
963 "Counter": "0,1,2,3",
964 "UMask": "0x1",
965 "PEBScounters": "0,1,2,3",
966 "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
967 "PDIR_COUNTER": "na",
968 "MSRIndex": "0x1a6, 0x1a7",
969 "SampleAfterValue": "100007",
970 "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher true miss for the L2 cache with a snoop miss in the other processor module. ",
971 "Offcore": "1"
972 },
973 {
974 "CollectPEBSRecord": "1",
975 "PublicDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
976 "EventCode": "0xB7",
977 "MSRValue": "0x1000002000",
978 "Counter": "0,1,2,3",
979 "UMask": "0x1",
980 "PEBScounters": "0,1,2,3",
981 "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_MISS.HITM_OTHER_CORE",
982 "PDIR_COUNTER": "na",
983 "MSRIndex": "0x1a6, 0x1a7",
984 "SampleAfterValue": "100007",
985 "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
986 "Offcore": "1"
987 },
988 {
989 "CollectPEBSRecord": "1",
990 "PublicDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
991 "EventCode": "0xB7",
992 "MSRValue": "0x4000002000",
993 "Counter": "0,1,2,3",
994 "UMask": "0x1",
995 "PEBScounters": "0,1,2,3",
996 "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.OUTSTANDING",
997 "PDIR_COUNTER": "na",
998 "MSRIndex": "0x1a6",
999 "SampleAfterValue": "100007",
1000 "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher outstanding, per cycle, from the time of the L2 miss to when any response is received.",
1001 "Offcore": "1"
1002 },
1003 {
1004 "CollectPEBSRecord": "1",
1005 "PublicDescription": "Counts any data writes to uncacheable write combining (USWC) memory region have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1006 "EventCode": "0xB7",
1007 "MSRValue": "0x0000014800",
1008 "Counter": "0,1,2,3",
1009 "UMask": "0x1",
1010 "PEBScounters": "0,1,2,3",
1011 "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.ANY_RESPONSE",
1012 "PDIR_COUNTER": "na",
1013 "MSRIndex": "0x1a6, 0x1a7",
1014 "SampleAfterValue": "100007",
1015 "BriefDescription": "Counts any data writes to uncacheable write combining (USWC) memory region have any transaction responses from the uncore subsystem.",
1016 "Offcore": "1"
1017 },
1018 {
1019 "CollectPEBSRecord": "1",
1020 "PublicDescription": "Counts any data writes to uncacheable write combining (USWC) memory region hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1021 "EventCode": "0xB7",
1022 "MSRValue": "0x0000044800",
1023 "Counter": "0,1,2,3",
1024 "UMask": "0x1",
1025 "PEBScounters": "0,1,2,3",
1026 "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L2_HIT",
1027 "PDIR_COUNTER": "na",
1028 "MSRIndex": "0x1a6, 0x1a7",
1029 "SampleAfterValue": "100007",
1030 "BriefDescription": "Counts any data writes to uncacheable write combining (USWC) memory region hit the L2 cache.",
1031 "Offcore": "1"
1032 },
1033 {
1034 "CollectPEBSRecord": "1",
1035 "PublicDescription": "Counts any data writes to uncacheable write combining (USWC) memory region true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1036 "EventCode": "0xB7",
1037 "MSRValue": "0x0200004800",
1038 "Counter": "0,1,2,3",
1039 "UMask": "0x1",
1040 "PEBScounters": "0,1,2,3",
1041 "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
1042 "PDIR_COUNTER": "na",
1043 "MSRIndex": "0x1a6, 0x1a7",
1044 "SampleAfterValue": "100007",
1045 "BriefDescription": "Counts any data writes to uncacheable write combining (USWC) memory region true miss for the L2 cache with a snoop miss in the other processor module. ",
1046 "Offcore": "1"
1047 },
1048 {
1049 "CollectPEBSRecord": "1",
1050 "PublicDescription": "Counts any data writes to uncacheable write combining (USWC) memory region miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1051 "EventCode": "0xB7",
1052 "MSRValue": "0x1000004800",
1053 "Counter": "0,1,2,3",
1054 "UMask": "0x1",
1055 "PEBScounters": "0,1,2,3",
1056 "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L2_MISS.HITM_OTHER_CORE",
1057 "PDIR_COUNTER": "na",
1058 "MSRIndex": "0x1a6, 0x1a7",
1059 "SampleAfterValue": "100007",
1060 "BriefDescription": "Counts any data writes to uncacheable write combining (USWC) memory region miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
1061 "Offcore": "1"
1062 },
1063 {
1064 "CollectPEBSRecord": "1",
1065 "PublicDescription": "Counts any data writes to uncacheable write combining (USWC) memory region outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1066 "EventCode": "0xB7",
1067 "MSRValue": "0x4000004800",
1068 "Counter": "0,1,2,3",
1069 "UMask": "0x1",
1070 "PEBScounters": "0,1,2,3",
1071 "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.OUTSTANDING",
1072 "PDIR_COUNTER": "na",
1073 "MSRIndex": "0x1a6",
1074 "SampleAfterValue": "100007",
1075 "BriefDescription": "Counts any data writes to uncacheable write combining (USWC) memory region outstanding, per cycle, from the time of the L2 miss to when any response is received.",
1076 "Offcore": "1"
1077 },
1078 {
1079 "CollectPEBSRecord": "1",
1080 "PublicDescription": "Counts requests to the uncore subsystem have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1081 "EventCode": "0xB7",
1082 "MSRValue": "0x0000018000",
1083 "Counter": "0,1,2,3",
1084 "UMask": "0x1",
1085 "PEBScounters": "0,1,2,3",
1086 "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_RESPONSE",
1087 "PDIR_COUNTER": "na",
1088 "MSRIndex": "0x1a6, 0x1a7",
1089 "SampleAfterValue": "100007",
1090 "BriefDescription": "Counts requests to the uncore subsystem have any transaction responses from the uncore subsystem.",
1091 "Offcore": "1"
1092 },
1093 {
1094 "CollectPEBSRecord": "1",
1095 "PublicDescription": "Counts requests to the uncore subsystem hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1096 "EventCode": "0xB7",
1097 "MSRValue": "0x0000048000",
1098 "Counter": "0,1,2,3",
1099 "UMask": "0x1",
1100 "PEBScounters": "0,1,2,3",
1101 "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_HIT",
1102 "PDIR_COUNTER": "na",
1103 "MSRIndex": "0x1a6, 0x1a7",
1104 "SampleAfterValue": "100007",
1105 "BriefDescription": "Counts requests to the uncore subsystem hit the L2 cache.",
1106 "Offcore": "1"
1107 },
1108 {
1109 "CollectPEBSRecord": "1",
1110 "PublicDescription": "Counts requests to the uncore subsystem true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1111 "EventCode": "0xB7",
1112 "MSRValue": "0x0200008000",
1113 "Counter": "0,1,2,3",
1114 "UMask": "0x1",
1115 "PEBScounters": "0,1,2,3",
1116 "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
1117 "PDIR_COUNTER": "na",
1118 "MSRIndex": "0x1a6, 0x1a7",
1119 "SampleAfterValue": "100007",
1120 "BriefDescription": "Counts requests to the uncore subsystem true miss for the L2 cache with a snoop miss in the other processor module. ",
1121 "Offcore": "1"
1122 },
1123 {
1124 "CollectPEBSRecord": "1",
1125 "PublicDescription": "Counts requests to the uncore subsystem miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1126 "EventCode": "0xB7",
1127 "MSRValue": "0x1000008000",
1128 "Counter": "0,1,2,3",
1129 "UMask": "0x1",
1130 "PEBScounters": "0,1,2,3",
1131 "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_MISS.HITM_OTHER_CORE",
1132 "PDIR_COUNTER": "na",
1133 "MSRIndex": "0x1a6, 0x1a7",
1134 "SampleAfterValue": "100007",
1135 "BriefDescription": "Counts requests to the uncore subsystem miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
1136 "Offcore": "1"
1137 },
1138 {
1139 "CollectPEBSRecord": "1",
1140 "PublicDescription": "Counts requests to the uncore subsystem outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1141 "EventCode": "0xB7",
1142 "MSRValue": "0x4000008000",
1143 "Counter": "0,1,2,3",
1144 "UMask": "0x1",
1145 "PEBScounters": "0,1,2,3",
1146 "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.OUTSTANDING",
1147 "PDIR_COUNTER": "na",
1148 "MSRIndex": "0x1a6",
1149 "SampleAfterValue": "100007",
1150 "BriefDescription": "Counts requests to the uncore subsystem outstanding, per cycle, from the time of the L2 miss to when any response is received.",
1151 "Offcore": "1"
1152 },
1153 {
1154 "CollectPEBSRecord": "1",
1155 "PublicDescription": "Counts data reads generated by L1 or L2 prefetchers have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1156 "EventCode": "0xB7",
1157 "MSRValue": "0x0000013010",
1158 "Counter": "0,1,2,3",
1159 "UMask": "0x1",
1160 "PEBScounters": "0,1,2,3",
1161 "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.ANY_RESPONSE",
1162 "PDIR_COUNTER": "na",
1163 "MSRIndex": "0x1a6, 0x1a7",
1164 "SampleAfterValue": "100007",
1165 "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers have any transaction responses from the uncore subsystem.",
1166 "Offcore": "1"
1167 },
1168 {
1169 "CollectPEBSRecord": "1",
1170 "PublicDescription": "Counts data reads generated by L1 or L2 prefetchers hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1171 "EventCode": "0xB7",
1172 "MSRValue": "0x0000043010",
1173 "Counter": "0,1,2,3",
1174 "UMask": "0x1",
1175 "PEBScounters": "0,1,2,3",
1176 "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.L2_HIT",
1177 "PDIR_COUNTER": "na",
1178 "MSRIndex": "0x1a6, 0x1a7",
1179 "SampleAfterValue": "100007",
1180 "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers hit the L2 cache.",
1181 "Offcore": "1"
1182 },
1183 {
1184 "CollectPEBSRecord": "1",
1185 "PublicDescription": "Counts data reads generated by L1 or L2 prefetchers true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1186 "EventCode": "0xB7",
1187 "MSRValue": "0x0200003010",
1188 "Counter": "0,1,2,3",
1189 "UMask": "0x1",
1190 "PEBScounters": "0,1,2,3",
1191 "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
1192 "PDIR_COUNTER": "na",
1193 "MSRIndex": "0x1a6, 0x1a7",
1194 "SampleAfterValue": "100007",
1195 "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers true miss for the L2 cache with a snoop miss in the other processor module. ",
1196 "Offcore": "1"
1197 },
1198 {
1199 "CollectPEBSRecord": "1",
1200 "PublicDescription": "Counts data reads generated by L1 or L2 prefetchers miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1201 "EventCode": "0xB7",
1202 "MSRValue": "0x1000003010",
1203 "Counter": "0,1,2,3",
1204 "UMask": "0x1",
1205 "PEBScounters": "0,1,2,3",
1206 "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.L2_MISS.HITM_OTHER_CORE",
1207 "PDIR_COUNTER": "na",
1208 "MSRIndex": "0x1a6, 0x1a7",
1209 "SampleAfterValue": "100007",
1210 "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
1211 "Offcore": "1"
1212 },
1213 {
1214 "CollectPEBSRecord": "1",
1215 "PublicDescription": "Counts data reads generated by L1 or L2 prefetchers outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1216 "EventCode": "0xB7",
1217 "MSRValue": "0x4000003010",
1218 "Counter": "0,1,2,3",
1219 "UMask": "0x1",
1220 "PEBScounters": "0,1,2,3",
1221 "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.OUTSTANDING",
1222 "PDIR_COUNTER": "na",
1223 "MSRIndex": "0x1a6",
1224 "SampleAfterValue": "100007",
1225 "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers outstanding, per cycle, from the time of the L2 miss to when any response is received.",
1226 "Offcore": "1"
1227 },
1228 {
1229 "CollectPEBSRecord": "1",
1230 "PublicDescription": "Counts data reads (demand & prefetch) have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1231 "EventCode": "0xB7",
1232 "MSRValue": "0x0000013091",
1233 "Counter": "0,1,2,3",
1234 "UMask": "0x1",
1235 "PEBScounters": "0,1,2,3",
1236 "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.ANY_RESPONSE",
1237 "PDIR_COUNTER": "na",
1238 "MSRIndex": "0x1a6, 0x1a7",
1239 "SampleAfterValue": "100007",
1240 "BriefDescription": "Counts data reads (demand & prefetch) have any transaction responses from the uncore subsystem.",
1241 "Offcore": "1"
1242 },
1243 {
1244 "CollectPEBSRecord": "1",
1245 "PublicDescription": "Counts data reads (demand & prefetch) hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1246 "EventCode": "0xB7",
1247 "MSRValue": "0x0000043091",
1248 "Counter": "0,1,2,3",
1249 "UMask": "0x1",
1250 "PEBScounters": "0,1,2,3",
1251 "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_HIT",
1252 "PDIR_COUNTER": "na",
1253 "MSRIndex": "0x1a6, 0x1a7",
1254 "SampleAfterValue": "100007",
1255 "BriefDescription": "Counts data reads (demand & prefetch) hit the L2 cache.",
1256 "Offcore": "1"
1257 },
1258 {
1259 "CollectPEBSRecord": "1",
1260 "PublicDescription": "Counts data reads (demand & prefetch) true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1261 "EventCode": "0xB7",
1262 "MSRValue": "0x0200003091",
1263 "Counter": "0,1,2,3",
1264 "UMask": "0x1",
1265 "PEBScounters": "0,1,2,3",
1266 "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
1267 "PDIR_COUNTER": "na",
1268 "MSRIndex": "0x1a6, 0x1a7",
1269 "SampleAfterValue": "100007",
1270 "BriefDescription": "Counts data reads (demand & prefetch) true miss for the L2 cache with a snoop miss in the other processor module. ",
1271 "Offcore": "1"
1272 },
1273 {
1274 "CollectPEBSRecord": "1",
1275 "PublicDescription": "Counts data reads (demand & prefetch) miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1276 "EventCode": "0xB7",
1277 "MSRValue": "0x1000003091",
1278 "Counter": "0,1,2,3",
1279 "UMask": "0x1",
1280 "PEBScounters": "0,1,2,3",
1281 "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_MISS.HITM_OTHER_CORE",
1282 "PDIR_COUNTER": "na",
1283 "MSRIndex": "0x1a6, 0x1a7",
1284 "SampleAfterValue": "100007",
1285 "BriefDescription": "Counts data reads (demand & prefetch) miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
1286 "Offcore": "1"
1287 },
1288 {
1289 "CollectPEBSRecord": "1",
1290 "PublicDescription": "Counts data reads (demand & prefetch) outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1291 "EventCode": "0xB7",
1292 "MSRValue": "0x4000003091",
1293 "Counter": "0,1,2,3",
1294 "UMask": "0x1",
1295 "PEBScounters": "0,1,2,3",
1296 "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.OUTSTANDING",
1297 "PDIR_COUNTER": "na",
1298 "MSRIndex": "0x1a6",
1299 "SampleAfterValue": "100007",
1300 "BriefDescription": "Counts data reads (demand & prefetch) outstanding, per cycle, from the time of the L2 miss to when any response is received.",
1301 "Offcore": "1"
1302 },
1303 {
1304 "CollectPEBSRecord": "1",
1305 "PublicDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1306 "EventCode": "0xB7",
1307 "MSRValue": "0x0000010022",
1308 "Counter": "0,1,2,3",
1309 "UMask": "0x1",
1310 "PEBScounters": "0,1,2,3",
1311 "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_RESPONSE",
1312 "PDIR_COUNTER": "na",
1313 "MSRIndex": "0x1a6, 0x1a7",
1314 "SampleAfterValue": "100007",
1315 "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) have any transaction responses from the uncore subsystem.",
1316 "Offcore": "1"
1317 },
1318 {
1319 "CollectPEBSRecord": "1",
1320 "PublicDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1321 "EventCode": "0xB7",
1322 "MSRValue": "0x0000040022",
1323 "Counter": "0,1,2,3",
1324 "UMask": "0x1",
1325 "PEBScounters": "0,1,2,3",
1326 "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_HIT",
1327 "PDIR_COUNTER": "na",
1328 "MSRIndex": "0x1a6, 0x1a7",
1329 "SampleAfterValue": "100007",
1330 "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) hit the L2 cache.",
1331 "Offcore": "1"
1332 },
1333 {
1334 "CollectPEBSRecord": "1",
1335 "PublicDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1336 "EventCode": "0xB7",
1337 "MSRValue": "0x0200000022",
1338 "Counter": "0,1,2,3",
1339 "UMask": "0x1",
1340 "PEBScounters": "0,1,2,3",
1341 "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
1342 "PDIR_COUNTER": "na",
1343 "MSRIndex": "0x1a6, 0x1a7",
1344 "SampleAfterValue": "100007",
1345 "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) true miss for the L2 cache with a snoop miss in the other processor module. ",
1346 "Offcore": "1"
1347 },
1348 {
1349 "CollectPEBSRecord": "1",
1350 "PublicDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1351 "EventCode": "0xB7",
1352 "MSRValue": "0x1000000022",
1353 "Counter": "0,1,2,3",
1354 "UMask": "0x1",
1355 "PEBScounters": "0,1,2,3",
1356 "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_MISS.HITM_OTHER_CORE",
1357 "PDIR_COUNTER": "na",
1358 "MSRIndex": "0x1a6, 0x1a7",
1359 "SampleAfterValue": "100007",
1360 "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
1361 "Offcore": "1"
1362 },
1363 {
1364 "CollectPEBSRecord": "1",
1365 "PublicDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1366 "EventCode": "0xB7",
1367 "MSRValue": "0x4000000022",
1368 "Counter": "0,1,2,3",
1369 "UMask": "0x1",
1370 "PEBScounters": "0,1,2,3",
1371 "EventName": "OFFCORE_RESPONSE.ANY_RFO.OUTSTANDING",
1372 "PDIR_COUNTER": "na",
1373 "MSRIndex": "0x1a6",
1374 "SampleAfterValue": "100007",
1375 "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) outstanding, per cycle, from the time of the L2 miss to when any response is received.",
1376 "Offcore": "1"
1377 },
1378 {
1379 "CollectPEBSRecord": "1",
1380 "PublicDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1381 "EventCode": "0xB7",
1382 "MSRValue": "0x00000132b7",
1383 "Counter": "0,1,2,3",
1384 "UMask": "0x1",
1385 "PEBScounters": "0,1,2,3",
1386 "EventName": "OFFCORE_RESPONSE.ANY_READ.ANY_RESPONSE",
1387 "PDIR_COUNTER": "na",
1388 "MSRIndex": "0x1a6, 0x1a7",
1389 "SampleAfterValue": "100007",
1390 "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) have any transaction responses from the uncore subsystem.",
1391 "Offcore": "1"
1392 },
1393 {
1394 "CollectPEBSRecord": "1",
1395 "PublicDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1396 "EventCode": "0xB7",
1397 "MSRValue": "0x00000432b7",
1398 "Counter": "0,1,2,3",
1399 "UMask": "0x1",
1400 "PEBScounters": "0,1,2,3",
1401 "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_HIT",
1402 "PDIR_COUNTER": "na",
1403 "MSRIndex": "0x1a6, 0x1a7",
1404 "SampleAfterValue": "100007",
1405 "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) hit the L2 cache.",
1406 "Offcore": "1"
1407 },
1408 {
1409 "CollectPEBSRecord": "1",
1410 "PublicDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1411 "EventCode": "0xB7",
1412 "MSRValue": "0x02000032b7",
1413 "Counter": "0,1,2,3",
1414 "UMask": "0x1",
1415 "PEBScounters": "0,1,2,3",
1416 "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED",
1417 "PDIR_COUNTER": "na",
1418 "MSRIndex": "0x1a6, 0x1a7",
1419 "SampleAfterValue": "100007",
1420 "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) true miss for the L2 cache with a snoop miss in the other processor module. ",
1421 "Offcore": "1"
1422 },
1423 {
1424 "CollectPEBSRecord": "1",
1425 "PublicDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1426 "EventCode": "0xB7",
1427 "MSRValue": "0x10000032b7",
1428 "Counter": "0,1,2,3",
1429 "UMask": "0x1",
1430 "PEBScounters": "0,1,2,3",
1431 "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_MISS.HITM_OTHER_CORE",
1432 "PDIR_COUNTER": "na",
1433 "MSRIndex": "0x1a6, 0x1a7",
1434 "SampleAfterValue": "100007",
1435 "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.",
1436 "Offcore": "1"
1437 },
1438 {
1439 "CollectPEBSRecord": "1",
1440 "PublicDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)",
1441 "EventCode": "0xB7",
1442 "MSRValue": "0x40000032b7",
1443 "Counter": "0,1,2,3",
1444 "UMask": "0x1",
1445 "PEBScounters": "0,1,2,3",
1446 "EventName": "OFFCORE_RESPONSE.ANY_READ.OUTSTANDING",
1447 "PDIR_COUNTER": "na",
1448 "MSRIndex": "0x1a6",
1449 "SampleAfterValue": "100007",
1450 "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) outstanding, per cycle, from the time of the L2 miss to when any response is received.",
1451 "Offcore": "1"
1452 }
1453] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/goldmontplus/frontend.json b/tools/perf/pmu-events/arch/x86/goldmontplus/frontend.json
new file mode 100644
index 000000000000..a7878965ceab
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/goldmontplus/frontend.json
@@ -0,0 +1,62 @@
1[
2 {
3 "CollectPEBSRecord": "1",
4 "PublicDescription": "Counts requests to the Instruction Cache (ICache) for one or more bytes in an ICache Line and that cache line is in the ICache (hit). The event strives to count on a cache line basis, so that multiple accesses which hit in a single cache line count as one ICACHE.HIT. Specifically, the event counts when straight line code crosses the cache line boundary, or when a branch target is to a new line, and that cache line is in the ICache. This event counts differently than Intel processors based on Silvermont microarchitecture.",
5 "EventCode": "0x80",
6 "Counter": "0,1,2,3",
7 "UMask": "0x1",
8 "PEBScounters": "0,1,2,3",
9 "EventName": "ICACHE.HIT",
10 "PDIR_COUNTER": "na",
11 "SampleAfterValue": "200003",
12 "BriefDescription": "References per ICache line that are available in the ICache (hit). This event counts differently than Intel processors based on Silvermont microarchitecture"
13 },
14 {
15 "CollectPEBSRecord": "1",
16 "PublicDescription": "Counts requests to the Instruction Cache (ICache) for one or more bytes in an ICache Line and that cache line is not in the ICache (miss). The event strives to count on a cache line basis, so that multiple accesses which miss in a single cache line count as one ICACHE.MISS. Specifically, the event counts when straight line code crosses the cache line boundary, or when a branch target is to a new line, and that cache line is not in the ICache. This event counts differently than Intel processors based on Silvermont microarchitecture.",
17 "EventCode": "0x80",
18 "Counter": "0,1,2,3",
19 "UMask": "0x2",
20 "PEBScounters": "0,1,2,3",
21 "EventName": "ICACHE.MISSES",
22 "PDIR_COUNTER": "na",
23 "SampleAfterValue": "200003",
24 "BriefDescription": "References per ICache line that are not available in the ICache (miss). This event counts differently than Intel processors based on Silvermont microarchitecture"
25 },
26 {
27 "CollectPEBSRecord": "1",
28 "PublicDescription": "Counts requests to the Instruction Cache (ICache) for one or more bytes in an ICache Line. The event strives to count on a cache line basis, so that multiple fetches to a single cache line count as one ICACHE.ACCESS. Specifically, the event counts when accesses from straight line code crosses the cache line boundary, or when a branch target is to a new line.\r\nThis event counts differently than Intel processors based on Silvermont microarchitecture.",
29 "EventCode": "0x80",
30 "Counter": "0,1,2,3",
31 "UMask": "0x3",
32 "PEBScounters": "0,1,2,3",
33 "EventName": "ICACHE.ACCESSES",
34 "PDIR_COUNTER": "na",
35 "SampleAfterValue": "200003",
36 "BriefDescription": "References per ICache line. This event counts differently than Intel processors based on Silvermont microarchitecture"
37 },
38 {
39 "CollectPEBSRecord": "1",
40 "PublicDescription": "Counts the number of times the Microcode Sequencer (MS) starts a flow of uops from the MSROM. It does not count every time a uop is read from the MSROM. The most common case that this counts is when a micro-coded instruction is encountered by the front end of the machine. Other cases include when an instruction encounters a fault, trap, or microcode assist of any sort that initiates a flow of uops. The event will count MS startups for uops that are speculative, and subsequently cleared by branch mispredict or a machine clear.",
41 "EventCode": "0xE7",
42 "Counter": "0,1,2,3",
43 "UMask": "0x1",
44 "PEBScounters": "0,1,2,3",
45 "EventName": "MS_DECODED.MS_ENTRY",
46 "PDIR_COUNTER": "na",
47 "SampleAfterValue": "200003",
48 "BriefDescription": "MS decode starts"
49 },
50 {
51 "CollectPEBSRecord": "1",
52 "PublicDescription": "Counts the number of times the prediction (from the predecode cache) for instruction length is incorrect.",
53 "EventCode": "0xE9",
54 "Counter": "0,1,2,3",
55 "UMask": "0x1",
56 "PEBScounters": "0,1,2,3",
57 "EventName": "DECODE_RESTRICTION.PREDECODE_WRONG",
58 "PDIR_COUNTER": "na",
59 "SampleAfterValue": "200003",
60 "BriefDescription": "Decode restrictions due to predicting wrong instruction length"
61 }
62] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/goldmontplus/memory.json b/tools/perf/pmu-events/arch/x86/goldmontplus/memory.json
new file mode 100644
index 000000000000..91e0815f3ffb
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/goldmontplus/memory.json
@@ -0,0 +1,38 @@
1[
2 {
3 "PEBS": "2",
4 "CollectPEBSRecord": "2",
5 "PublicDescription": "Counts when a memory load of a uop spans a page boundary (a split) is retired.",
6 "EventCode": "0x13",
7 "Counter": "0,1,2,3",
8 "UMask": "0x2",
9 "PEBScounters": "0,1,2,3",
10 "EventName": "MISALIGN_MEM_REF.LOAD_PAGE_SPLIT",
11 "SampleAfterValue": "200003",
12 "BriefDescription": "Load uops that split a page (Precise event capable)"
13 },
14 {
15 "PEBS": "2",
16 "CollectPEBSRecord": "2",
17 "PublicDescription": "Counts when a memory store of a uop spans a page boundary (a split) is retired.",
18 "EventCode": "0x13",
19 "Counter": "0,1,2,3",
20 "UMask": "0x4",
21 "PEBScounters": "0,1,2,3",
22 "EventName": "MISALIGN_MEM_REF.STORE_PAGE_SPLIT",
23 "SampleAfterValue": "200003",
24 "BriefDescription": "Store uops that split a page (Precise event capable)"
25 },
26 {
27 "CollectPEBSRecord": "1",
28 "PublicDescription": "Counts machine clears due to memory ordering issues. This occurs when a snoop request happens and the machine is uncertain if memory ordering will be preserved - as another core is in the process of modifying the data.",
29 "EventCode": "0xC3",
30 "Counter": "0,1,2,3",
31 "UMask": "0x2",
32 "PEBScounters": "0,1,2,3",
33 "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
34 "PDIR_COUNTER": "na",
35 "SampleAfterValue": "20003",
36 "BriefDescription": "Machine clears due to memory ordering issue"
37 }
38] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/goldmontplus/other.json b/tools/perf/pmu-events/arch/x86/goldmontplus/other.json
new file mode 100644
index 000000000000..b860374418ab
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/goldmontplus/other.json
@@ -0,0 +1,98 @@
1[
2 {
3 "CollectPEBSRecord": "1",
4 "PublicDescription": "Counts cycles that fetch is stalled due to any reason. That is, the decoder queue is able to accept bytes, but the fetch unit is unable to provide bytes. This will include cycles due to an ITLB miss, ICache miss and other events.",
5 "EventCode": "0x86",
6 "Counter": "0,1,2,3",
7 "UMask": "0x0",
8 "PEBScounters": "0,1,2,3",
9 "EventName": "FETCH_STALL.ALL",
10 "PDIR_COUNTER": "na",
11 "SampleAfterValue": "200003",
12 "BriefDescription": "Cycles code-fetch stalled due to any reason."
13 },
14 {
15 "CollectPEBSRecord": "1",
16 "PublicDescription": "Counts cycles that fetch is stalled due to an outstanding ITLB miss. That is, the decoder queue is able to accept bytes, but the fetch unit is unable to provide bytes due to an ITLB miss. Note: this event is not the same as page walk cycles to retrieve an instruction translation.",
17 "EventCode": "0x86",
18 "Counter": "0,1,2,3",
19 "UMask": "0x1",
20 "PEBScounters": "0,1,2,3",
21 "EventName": "FETCH_STALL.ITLB_FILL_PENDING_CYCLES",
22 "PDIR_COUNTER": "na",
23 "SampleAfterValue": "200003",
24 "BriefDescription": "Cycles the code-fetch stalls and an ITLB miss is outstanding."
25 },
26 {
27 "CollectPEBSRecord": "1",
28 "PublicDescription": "Counts the number of issue slots per core cycle that were not consumed by the backend due to either a full resource in the backend (RESOURCE_FULL) or due to the processor recovering from some event (RECOVERY).",
29 "EventCode": "0xCA",
30 "Counter": "0,1,2,3",
31 "UMask": "0x0",
32 "PEBScounters": "0,1,2,3",
33 "EventName": "ISSUE_SLOTS_NOT_CONSUMED.ANY",
34 "PDIR_COUNTER": "na",
35 "SampleAfterValue": "200003",
36 "BriefDescription": "Unfilled issue slots per cycle"
37 },
38 {
39 "CollectPEBSRecord": "1",
40 "PublicDescription": "Counts the number of issue slots per core cycle that were not consumed because of a full resource in the backend. Including but not limited to resources such as the Re-order Buffer (ROB), reservation stations (RS), load/store buffers, physical registers, or any other needed machine resource that is currently unavailable. Note that uops must be available for consumption in order for this event to fire. If a uop is not available (Instruction Queue is empty), this event will not count.",
41 "EventCode": "0xCA",
42 "Counter": "0,1,2,3",
43 "UMask": "0x1",
44 "PEBScounters": "0,1,2,3",
45 "EventName": "ISSUE_SLOTS_NOT_CONSUMED.RESOURCE_FULL",
46 "PDIR_COUNTER": "na",
47 "SampleAfterValue": "200003",
48 "BriefDescription": "Unfilled issue slots per cycle because of a full resource in the backend"
49 },
50 {
51 "CollectPEBSRecord": "1",
52 "PublicDescription": "Counts the number of issue slots per core cycle that were not consumed by the backend because allocation is stalled waiting for a mispredicted jump to retire or other branch-like conditions (e.g. the event is relevant during certain microcode flows). Counts all issue slots blocked while within this window including slots where uops were not available in the Instruction Queue.",
53 "EventCode": "0xCA",
54 "Counter": "0,1,2,3",
55 "UMask": "0x2",
56 "PEBScounters": "0,1,2,3",
57 "EventName": "ISSUE_SLOTS_NOT_CONSUMED.RECOVERY",
58 "PDIR_COUNTER": "na",
59 "SampleAfterValue": "200003",
60 "BriefDescription": "Unfilled issue slots per cycle to recover"
61 },
62 {
63 "CollectPEBSRecord": "2",
64 "PublicDescription": "Counts hardware interrupts received by the processor.",
65 "EventCode": "0xCB",
66 "Counter": "0,1,2,3",
67 "UMask": "0x1",
68 "PEBScounters": "0,1,2,3",
69 "EventName": "HW_INTERRUPTS.RECEIVED",
70 "PDIR_COUNTER": "na",
71 "SampleAfterValue": "203",
72 "BriefDescription": "Hardware interrupts received"
73 },
74 {
75 "CollectPEBSRecord": "2",
76 "PublicDescription": "Counts the number of core cycles during which interrupts are masked (disabled). Increments by 1 each core cycle that EFLAGS.IF is 0, regardless of whether interrupts are pending or not.",
77 "EventCode": "0xCB",
78 "Counter": "0,1,2,3",
79 "UMask": "0x2",
80 "PEBScounters": "0,1,2,3",
81 "EventName": "HW_INTERRUPTS.MASKED",
82 "PDIR_COUNTER": "na",
83 "SampleAfterValue": "200003",
84 "BriefDescription": "Cycles hardware interrupts are masked"
85 },
86 {
87 "CollectPEBSRecord": "2",
88 "PublicDescription": "Counts core cycles during which there are pending interrupts, but interrupts are masked (EFLAGS.IF = 0).",
89 "EventCode": "0xCB",
90 "Counter": "0,1,2,3",
91 "UMask": "0x4",
92 "PEBScounters": "0,1,2,3",
93 "EventName": "HW_INTERRUPTS.PENDING_AND_MASKED",
94 "PDIR_COUNTER": "na",
95 "SampleAfterValue": "200003",
96 "BriefDescription": "Cycles pending interrupts are masked"
97 }
98] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/goldmontplus/pipeline.json b/tools/perf/pmu-events/arch/x86/goldmontplus/pipeline.json
new file mode 100644
index 000000000000..ccf1aed69197
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/goldmontplus/pipeline.json
@@ -0,0 +1,544 @@
1[
2 {
3 "PEBS": "2",
4 "CollectPEBSRecord": "1",
5 "PublicDescription": "Counts the number of instructions that retire execution. For instructions that consist of multiple uops, this event counts the retirement of the last uop of the instruction. The counter continues counting during hardware interrupts, traps, and inside interrupt handlers. This event uses fixed counter 0. You cannot collect a PEBs record for this event.",
6 "EventCode": "0x00",
7 "Counter": "Fixed counter 0",
8 "UMask": "0x1",
9 "PEBScounters": "32",
10 "EventName": "INST_RETIRED.ANY",
11 "PDIR_COUNTER": "na",
12 "SampleAfterValue": "2000003",
13 "BriefDescription": "Instructions retired (Fixed event)"
14 },
15 {
16 "CollectPEBSRecord": "1",
17 "PublicDescription": "Counts the number of core cycles while the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. In mobile systems the core frequency may change from time to time. For this reason this event may have a changing ratio with regards to time. This event uses fixed counter 1. You cannot collect a PEBs record for this event.",
18 "EventCode": "0x00",
19 "Counter": "Fixed counter 1",
20 "UMask": "0x2",
21 "PEBScounters": "33",
22 "EventName": "CPU_CLK_UNHALTED.CORE",
23 "PDIR_COUNTER": "na",
24 "SampleAfterValue": "2000003",
25 "BriefDescription": "Core cycles when core is not halted (Fixed event)"
26 },
27 {
28 "CollectPEBSRecord": "1",
29 "PublicDescription": "Counts the number of reference cycles that the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. In mobile systems the core frequency may change from time. This event is not affected by core frequency changes but counts as if the core is running at the maximum frequency all the time. This event uses fixed counter 2. You cannot collect a PEBs record for this event.",
30 "EventCode": "0x00",
31 "Counter": "Fixed counter 2",
32 "UMask": "0x3",
33 "PEBScounters": "34",
34 "EventName": "CPU_CLK_UNHALTED.REF_TSC",
35 "PDIR_COUNTER": "na",
36 "SampleAfterValue": "2000003",
37 "BriefDescription": "Reference cycles when core is not halted (Fixed event)"
38 },
39 {
40 "PEBS": "2",
41 "CollectPEBSRecord": "2",
42 "PublicDescription": "Counts a load blocked from using a store forward, but did not occur because the store data was not available at the right time. The forward might occur subsequently when the data is available.",
43 "EventCode": "0x03",
44 "Counter": "0,1,2,3",
45 "UMask": "0x1",
46 "PEBScounters": "0,1,2,3",
47 "EventName": "LD_BLOCKS.DATA_UNKNOWN",
48 "SampleAfterValue": "200003",
49 "BriefDescription": "Loads blocked due to store data not ready (Precise event capable)"
50 },
51 {
52 "PEBS": "2",
53 "CollectPEBSRecord": "2",
54 "PublicDescription": "Counts a load blocked from using a store forward because of an address/size mismatch, only one of the loads blocked from each store will be counted.",
55 "EventCode": "0x03",
56 "Counter": "0,1,2,3",
57 "UMask": "0x2",
58 "PEBScounters": "0,1,2,3",
59 "EventName": "LD_BLOCKS.STORE_FORWARD",
60 "SampleAfterValue": "200003",
61 "BriefDescription": "Loads blocked due to store forward restriction (Precise event capable)"
62 },
63 {
64 "PEBS": "2",
65 "CollectPEBSRecord": "2",
66 "PublicDescription": "Counts loads that block because their address modulo 4K matches a pending store.",
67 "EventCode": "0x03",
68 "Counter": "0,1,2,3",
69 "UMask": "0x4",
70 "PEBScounters": "0,1,2,3",
71 "EventName": "LD_BLOCKS.4K_ALIAS",
72 "SampleAfterValue": "200003",
73 "BriefDescription": "Loads blocked because address has 4k partial address false dependence (Precise event capable)"
74 },
75 {
76 "PEBS": "2",
77 "CollectPEBSRecord": "2",
78 "PublicDescription": "Counts loads blocked because they are unable to find their physical address in the micro TLB (UTLB).",
79 "EventCode": "0x03",
80 "Counter": "0,1,2,3",
81 "UMask": "0x8",
82 "PEBScounters": "0,1,2,3",
83 "EventName": "LD_BLOCKS.UTLB_MISS",
84 "SampleAfterValue": "200003",
85 "BriefDescription": "Loads blocked because address in not in the UTLB (Precise event capable)"
86 },
87 {
88 "PEBS": "2",
89 "CollectPEBSRecord": "2",
90 "PublicDescription": "Counts anytime a load that retires is blocked for any reason.",
91 "EventCode": "0x03",
92 "Counter": "0,1,2,3",
93 "UMask": "0x10",
94 "PEBScounters": "0,1,2,3",
95 "EventName": "LD_BLOCKS.ALL_BLOCK",
96 "SampleAfterValue": "200003",
97 "BriefDescription": "Loads blocked (Precise event capable)"
98 },
99 {
100 "CollectPEBSRecord": "1",
101 "PublicDescription": "Counts uops issued by the front end and allocated into the back end of the machine. This event counts uops that retire as well as uops that were speculatively executed but didn't retire. The sort of speculative uops that might be counted includes, but is not limited to those uops issued in the shadow of a miss-predicted branch, those uops that are inserted during an assist (such as for a denormal floating point result), and (previously allocated) uops that might be canceled during a machine clear.",
102 "EventCode": "0x0E",
103 "Counter": "0,1,2,3",
104 "UMask": "0x0",
105 "PEBScounters": "0,1,2,3",
106 "EventName": "UOPS_ISSUED.ANY",
107 "PDIR_COUNTER": "na",
108 "SampleAfterValue": "200003",
109 "BriefDescription": "Uops issued to the back end per cycle"
110 },
111 {
112 "CollectPEBSRecord": "1",
113 "PublicDescription": "Core cycles when core is not halted. This event uses a (_P)rogrammable general purpose performance counter.",
114 "EventCode": "0x3C",
115 "Counter": "0,1,2,3",
116 "UMask": "0x0",
117 "PEBScounters": "0,1,2,3",
118 "EventName": "CPU_CLK_UNHALTED.CORE_P",
119 "PDIR_COUNTER": "na",
120 "SampleAfterValue": "2000003",
121 "BriefDescription": "Core cycles when core is not halted"
122 },
123 {
124 "CollectPEBSRecord": "1",
125 "PublicDescription": "Reference cycles when core is not halted. This event uses a (_P)rogrammable general purpose performance counter.",
126 "EventCode": "0x3C",
127 "Counter": "0,1,2,3",
128 "UMask": "0x1",
129 "PEBScounters": "0,1,2,3",
130 "EventName": "CPU_CLK_UNHALTED.REF",
131 "PDIR_COUNTER": "na",
132 "SampleAfterValue": "2000003",
133 "BriefDescription": "Reference cycles when core is not halted"
134 },
135 {
136 "CollectPEBSRecord": "1",
137 "PublicDescription": "This event used to measure front-end inefficiencies. I.e. when front-end of the machine is not delivering uops to the back-end and the back-end has is not stalled. This event can be used to identify if the machine is truly front-end bound. When this event occurs, it is an indication that the front-end of the machine is operating at less than its theoretical peak performance. Background: We can think of the processor pipeline as being divided into 2 broader parts: Front-end and Back-end. Front-end is responsible for fetching the instruction, decoding into uops in machine understandable format and putting them into a uop queue to be consumed by back end. The back-end then takes these uops, allocates the required resources. When all resources are ready, uops are executed. If the back-end is not ready to accept uops from the front-end, then we do not want to count these as front-end bottlenecks. However, whenever we have bottlenecks in the back-end, we will have allocation unit stalls and eventually forcing the front-end to wait until the back-end is ready to receive more uops. This event counts only when back-end is requesting more uops and front-end is not able to provide them. When 3 uops are requested and no uops are delivered, the event counts 3. When 3 are requested, and only 1 is delivered, the event counts 2. When only 2 are delivered, the event counts 1. Alternatively stated, the event will not count if 3 uops are delivered, or if the back end is stalled and not requesting any uops at all. Counts indicate missed opportunities for the front-end to deliver a uop to the back end. Some examples of conditions that cause front-end efficiencies are: ICache misses, ITLB misses, and decoder restrictions that limit the front-end bandwidth. Known Issues: Some uops require multiple allocation slots. These uops will not be charged as a front end 'not delivered' opportunity, and will be regarded as a back end problem. For example, the INC instruction has one uop that requires 2 issue slots. A stream of INC instructions will not count as UOPS_NOT_DELIVERED, even though only one instruction can be issued per clock. The low uop issue rate for a stream of INC instructions is considered to be a back end issue.",
138 "EventCode": "0x9C",
139 "Counter": "0,1,2,3",
140 "UMask": "0x0",
141 "PEBScounters": "0,1,2,3",
142 "EventName": "UOPS_NOT_DELIVERED.ANY",
143 "PDIR_COUNTER": "na",
144 "SampleAfterValue": "200003",
145 "BriefDescription": "Uops requested but not-delivered to the back-end per cycle"
146 },
147 {
148 "PEBS": "2",
149 "CollectPEBSRecord": "1",
150 "PublicDescription": "Counts the number of instructions that retire execution. For instructions that consist of multiple uops, this event counts the retirement of the last uop of the instruction. The event continues counting during hardware interrupts, traps, and inside interrupt handlers. This is an architectural performance event. This event uses a (_P)rogrammable general purpose performance counter. *This event is Precise Event capable: The EventingRIP field in the PEBS record is precise to the address of the instruction which caused the event. Note: Because PEBS records can be collected only on IA32_PMC0, only one event can use the PEBS facility at a time.",
151 "EventCode": "0xC0",
152 "Counter": "0,1,2,3",
153 "UMask": "0x0",
154 "PEBScounters": "0,1,2,3",
155 "EventName": "INST_RETIRED.ANY_P",
156 "SampleAfterValue": "2000003",
157 "BriefDescription": "Instructions retired (Precise event capable)"
158 },
159 {
160 "PEBS": "2",
161 "CollectPEBSRecord": "2",
162 "PublicDescription": "Counts INST_RETIRED.ANY using the Reduced Skid PEBS feature that reduces the shadow in which events aren't counted allowing for a more unbiased distribution of samples across instructions retired.",
163 "EventCode": "0xC0",
164 "Counter": "0,1,2,3",
165 "UMask": "0x0",
166 "EventName": "INST_RETIRED.PREC_DIST",
167 "SampleAfterValue": "2000003",
168 "BriefDescription": "Instructions retired - using Reduced Skid PEBS feature"
169 },
170 {
171 "PEBS": "2",
172 "CollectPEBSRecord": "2",
173 "PublicDescription": "Counts uops which retired.",
174 "EventCode": "0xC2",
175 "Counter": "0,1,2,3",
176 "UMask": "0x0",
177 "PEBScounters": "0,1,2,3",
178 "EventName": "UOPS_RETIRED.ANY",
179 "PDIR_COUNTER": "na",
180 "SampleAfterValue": "2000003",
181 "BriefDescription": "Uops retired (Precise event capable)"
182 },
183 {
184 "PEBS": "2",
185 "CollectPEBSRecord": "2",
186 "PublicDescription": "Counts uops retired that are from the complex flows issued by the micro-sequencer (MS). Counts both the uops from a micro-coded instruction, and the uops that might be generated from a micro-coded assist.",
187 "EventCode": "0xC2",
188 "Counter": "0,1,2,3",
189 "UMask": "0x1",
190 "PEBScounters": "0,1,2,3",
191 "EventName": "UOPS_RETIRED.MS",
192 "PDIR_COUNTER": "na",
193 "SampleAfterValue": "2000003",
194 "BriefDescription": "MS uops retired (Precise event capable)"
195 },
196 {
197 "PEBS": "2",
198 "CollectPEBSRecord": "1",
199 "PublicDescription": "Counts the number of floating point divide uops retired.",
200 "EventCode": "0xC2",
201 "Counter": "0,1,2,3",
202 "UMask": "0x8",
203 "PEBScounters": "0,1,2,3",
204 "EventName": "UOPS_RETIRED.FPDIV",
205 "SampleAfterValue": "2000003",
206 "BriefDescription": "Floating point divide uops retired (Precise Event Capable)"
207 },
208 {
209 "PEBS": "2",
210 "CollectPEBSRecord": "1",
211 "PublicDescription": "Counts the number of integer divide uops retired.",
212 "EventCode": "0xC2",
213 "Counter": "0,1,2,3",
214 "UMask": "0x10",
215 "PEBScounters": "0,1,2,3",
216 "EventName": "UOPS_RETIRED.IDIV",
217 "SampleAfterValue": "2000003",
218 "BriefDescription": "Integer divide uops retired (Precise Event Capable)"
219 },
220 {
221 "CollectPEBSRecord": "1",
222 "PublicDescription": "Counts machine clears for any reason.",
223 "EventCode": "0xC3",
224 "Counter": "0,1,2,3",
225 "UMask": "0x0",
226 "PEBScounters": "0,1,2,3",
227 "EventName": "MACHINE_CLEARS.ALL",
228 "PDIR_COUNTER": "na",
229 "SampleAfterValue": "20003",
230 "BriefDescription": "All machine clears"
231 },
232 {
233 "CollectPEBSRecord": "1",
234 "PublicDescription": "Counts the number of times that the processor detects that a program is writing to a code section and has to perform a machine clear because of that modification. Self-modifying code (SMC) causes a severe penalty in all Intel architecture processors.",
235 "EventCode": "0xC3",
236 "Counter": "0,1,2,3",
237 "UMask": "0x1",
238 "PEBScounters": "0,1,2,3",
239 "EventName": "MACHINE_CLEARS.SMC",
240 "PDIR_COUNTER": "na",
241 "SampleAfterValue": "20003",
242 "BriefDescription": "Self-Modifying Code detected"
243 },
244 {
245 "CollectPEBSRecord": "1",
246 "PublicDescription": "Counts machine clears due to floating point (FP) operations needing assists. For instance, if the result was a floating point denormal, the hardware clears the pipeline and reissues uops to produce the correct IEEE compliant denormal result.",
247 "EventCode": "0xC3",
248 "Counter": "0,1,2,3",
249 "UMask": "0x4",
250 "PEBScounters": "0,1,2,3",
251 "EventName": "MACHINE_CLEARS.FP_ASSIST",
252 "PDIR_COUNTER": "na",
253 "SampleAfterValue": "20003",
254 "BriefDescription": "Machine clears due to FP assists"
255 },
256 {
257 "CollectPEBSRecord": "1",
258 "PublicDescription": "Counts machine clears due to memory disambiguation. Memory disambiguation happens when a load which has been issued conflicts with a previous unretired store in the pipeline whose address was not known at issue time, but is later resolved to be the same as the load address.",
259 "EventCode": "0xC3",
260 "Counter": "0,1,2,3",
261 "UMask": "0x8",
262 "PEBScounters": "0,1,2,3",
263 "EventName": "MACHINE_CLEARS.DISAMBIGUATION",
264 "PDIR_COUNTER": "na",
265 "SampleAfterValue": "20003",
266 "BriefDescription": "Machine clears due to memory disambiguation"
267 },
268 {
269 "CollectPEBSRecord": "1",
270 "PublicDescription": "Counts the number of times that the machines clears due to a page fault. Covers both I-side and D-side(Loads/Stores) page faults. A page fault occurs when either page is not present, or an access violation",
271 "EventCode": "0xC3",
272 "Counter": "0,1,2,3",
273 "UMask": "0x20",
274 "PEBScounters": "0,1,2,3",
275 "EventName": "MACHINE_CLEARS.PAGE_FAULT",
276 "PDIR_COUNTER": "na",
277 "SampleAfterValue": "20003",
278 "BriefDescription": "Machines clear due to a page fault"
279 },
280 {
281 "PEBS": "2",
282 "CollectPEBSRecord": "2",
283 "PublicDescription": "Counts branch instructions retired for all branch types. This is an architectural performance event.",
284 "EventCode": "0xC4",
285 "Counter": "0,1,2,3",
286 "UMask": "0x0",
287 "PEBScounters": "0,1,2,3",
288 "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
289 "SampleAfterValue": "200003",
290 "BriefDescription": "Retired branch instructions (Precise event capable)"
291 },
292 {
293 "PEBS": "2",
294 "CollectPEBSRecord": "2",
295 "PublicDescription": "Counts retired Jcc (Jump on Conditional Code/Jump if Condition is Met) branch instructions retired, including both when the branch was taken and when it was not taken.",
296 "EventCode": "0xC4",
297 "Counter": "0,1,2,3",
298 "UMask": "0x7e",
299 "PEBScounters": "0,1,2,3",
300 "EventName": "BR_INST_RETIRED.JCC",
301 "SampleAfterValue": "200003",
302 "BriefDescription": "Retired conditional branch instructions (Precise event capable)"
303 },
304 {
305 "PEBS": "2",
306 "CollectPEBSRecord": "2",
307 "PublicDescription": "Counts the number of taken branch instructions retired.",
308 "EventCode": "0xC4",
309 "Counter": "0,1,2,3",
310 "UMask": "0x80",
311 "PEBScounters": "0,1,2,3",
312 "EventName": "BR_INST_RETIRED.ALL_TAKEN_BRANCHES",
313 "SampleAfterValue": "200003",
314 "BriefDescription": "Retired taken branch instructions (Precise event capable)"
315 },
316 {
317 "PEBS": "2",
318 "CollectPEBSRecord": "2",
319 "PublicDescription": "Counts far branch instructions retired. This includes far jump, far call and return, and Interrupt call and return.",
320 "EventCode": "0xC4",
321 "Counter": "0,1,2,3",
322 "UMask": "0xbf",
323 "PEBScounters": "0,1,2,3",
324 "EventName": "BR_INST_RETIRED.FAR_BRANCH",
325 "SampleAfterValue": "200003",
326 "BriefDescription": "Retired far branch instructions (Precise event capable)"
327 },
328 {
329 "PEBS": "2",
330 "CollectPEBSRecord": "2",
331 "PublicDescription": "Counts near indirect call or near indirect jmp branch instructions retired.",
332 "EventCode": "0xC4",
333 "Counter": "0,1,2,3",
334 "UMask": "0xeb",
335 "PEBScounters": "0,1,2,3",
336 "EventName": "BR_INST_RETIRED.NON_RETURN_IND",
337 "SampleAfterValue": "200003",
338 "BriefDescription": "Retired instructions of near indirect Jmp or call (Precise event capable)"
339 },
340 {
341 "PEBS": "2",
342 "CollectPEBSRecord": "2",
343 "PublicDescription": "Counts near return branch instructions retired.",
344 "EventCode": "0xC4",
345 "Counter": "0,1,2,3",
346 "UMask": "0xf7",
347 "PEBScounters": "0,1,2,3",
348 "EventName": "BR_INST_RETIRED.RETURN",
349 "SampleAfterValue": "200003",
350 "BriefDescription": "Retired near return instructions (Precise event capable)"
351 },
352 {
353 "PEBS": "2",
354 "CollectPEBSRecord": "2",
355 "PublicDescription": "Counts near CALL branch instructions retired.",
356 "EventCode": "0xC4",
357 "Counter": "0,1,2,3",
358 "UMask": "0xf9",
359 "PEBScounters": "0,1,2,3",
360 "EventName": "BR_INST_RETIRED.CALL",
361 "SampleAfterValue": "200003",
362 "BriefDescription": "Retired near call instructions (Precise event capable)"
363 },
364 {
365 "PEBS": "2",
366 "CollectPEBSRecord": "2",
367 "PublicDescription": "Counts near indirect CALL branch instructions retired.",
368 "EventCode": "0xC4",
369 "Counter": "0,1,2,3",
370 "UMask": "0xfb",
371 "PEBScounters": "0,1,2,3",
372 "EventName": "BR_INST_RETIRED.IND_CALL",
373 "SampleAfterValue": "200003",
374 "BriefDescription": "Retired near indirect call instructions (Precise event capable)"
375 },
376 {
377 "PEBS": "2",
378 "CollectPEBSRecord": "2",
379 "PublicDescription": "Counts near relative CALL branch instructions retired.",
380 "EventCode": "0xC4",
381 "Counter": "0,1,2,3",
382 "UMask": "0xfd",
383 "PEBScounters": "0,1,2,3",
384 "EventName": "BR_INST_RETIRED.REL_CALL",
385 "SampleAfterValue": "200003",
386 "BriefDescription": "Retired near relative call instructions (Precise event capable)"
387 },
388 {
389 "PEBS": "2",
390 "CollectPEBSRecord": "2",
391 "PublicDescription": "Counts Jcc (Jump on Conditional Code/Jump if Condition is Met) branch instructions retired that were taken and does not count when the Jcc branch instruction were not taken.",
392 "EventCode": "0xC4",
393 "Counter": "0,1,2,3",
394 "UMask": "0xfe",
395 "PEBScounters": "0,1,2,3",
396 "EventName": "BR_INST_RETIRED.TAKEN_JCC",
397 "SampleAfterValue": "200003",
398 "BriefDescription": "Retired conditional branch instructions that were taken (Precise event capable)"
399 },
400 {
401 "PEBS": "2",
402 "CollectPEBSRecord": "2",
403 "PublicDescription": "Counts mispredicted branch instructions retired including all branch types.",
404 "EventCode": "0xC5",
405 "Counter": "0,1,2,3",
406 "UMask": "0x0",
407 "PEBScounters": "0,1,2,3",
408 "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
409 "SampleAfterValue": "200003",
410 "BriefDescription": "Retired mispredicted branch instructions (Precise event capable)"
411 },
412 {
413 "PEBS": "2",
414 "CollectPEBSRecord": "2",
415 "PublicDescription": "Counts mispredicted retired Jcc (Jump on Conditional Code/Jump if Condition is Met) branch instructions retired, including both when the branch was supposed to be taken and when it was not supposed to be taken (but the processor predicted the opposite condition).",
416 "EventCode": "0xC5",
417 "Counter": "0,1,2,3",
418 "UMask": "0x7e",
419 "PEBScounters": "0,1,2,3",
420 "EventName": "BR_MISP_RETIRED.JCC",
421 "SampleAfterValue": "200003",
422 "BriefDescription": "Retired mispredicted conditional branch instructions (Precise event capable)"
423 },
424 {
425 "PEBS": "2",
426 "CollectPEBSRecord": "2",
427 "PublicDescription": "Counts mispredicted branch instructions retired that were near indirect call or near indirect jmp, where the target address taken was not what the processor predicted.",
428 "EventCode": "0xC5",
429 "Counter": "0,1,2,3",
430 "UMask": "0xeb",
431 "PEBScounters": "0,1,2,3",
432 "EventName": "BR_MISP_RETIRED.NON_RETURN_IND",
433 "SampleAfterValue": "200003",
434 "BriefDescription": "Retired mispredicted instructions of near indirect Jmp or near indirect call (Precise event capable)"
435 },
436 {
437 "PEBS": "2",
438 "CollectPEBSRecord": "2",
439 "PublicDescription": "Counts mispredicted near RET branch instructions retired, where the return address taken was not what the processor predicted.",
440 "EventCode": "0xC5",
441 "Counter": "0,1,2,3",
442 "UMask": "0xf7",
443 "PEBScounters": "0,1,2,3",
444 "EventName": "BR_MISP_RETIRED.RETURN",
445 "SampleAfterValue": "200003",
446 "BriefDescription": "Retired mispredicted near return instructions (Precise event capable)"
447 },
448 {
449 "PEBS": "2",
450 "CollectPEBSRecord": "2",
451 "PublicDescription": "Counts mispredicted near indirect CALL branch instructions retired, where the target address taken was not what the processor predicted.",
452 "EventCode": "0xC5",
453 "Counter": "0,1,2,3",
454 "UMask": "0xfb",
455 "PEBScounters": "0,1,2,3",
456 "EventName": "BR_MISP_RETIRED.IND_CALL",
457 "SampleAfterValue": "200003",
458 "BriefDescription": "Retired mispredicted near indirect call instructions (Precise event capable)"
459 },
460 {
461 "PEBS": "2",
462 "CollectPEBSRecord": "2",
463 "PublicDescription": "Counts mispredicted retired Jcc (Jump on Conditional Code/Jump if Condition is Met) branch instructions retired that were supposed to be taken but the processor predicted that it would not be taken.",
464 "EventCode": "0xC5",
465 "Counter": "0,1,2,3",
466 "UMask": "0xfe",
467 "PEBScounters": "0,1,2,3",
468 "EventName": "BR_MISP_RETIRED.TAKEN_JCC",
469 "SampleAfterValue": "200003",
470 "BriefDescription": "Retired mispredicted conditional branch instructions that were taken (Precise event capable)"
471 },
472 {
473 "CollectPEBSRecord": "1",
474 "PublicDescription": "Counts core cycles if either divide unit is busy.",
475 "EventCode": "0xCD",
476 "Counter": "0,1,2,3",
477 "UMask": "0x0",
478 "PEBScounters": "0,1,2,3",
479 "EventName": "CYCLES_DIV_BUSY.ALL",
480 "PDIR_COUNTER": "na",
481 "SampleAfterValue": "2000003",
482 "BriefDescription": "Cycles a divider is busy"
483 },
484 {
485 "CollectPEBSRecord": "1",
486 "PublicDescription": "Counts core cycles the integer divide unit is busy.",
487 "EventCode": "0xCD",
488 "Counter": "0,1,2,3",
489 "UMask": "0x1",
490 "PEBScounters": "0,1,2,3",
491 "EventName": "CYCLES_DIV_BUSY.IDIV",
492 "PDIR_COUNTER": "na",
493 "SampleAfterValue": "200003",
494 "BriefDescription": "Cycles the integer divide unit is busy"
495 },
496 {
497 "CollectPEBSRecord": "1",
498 "PublicDescription": "Counts core cycles the floating point divide unit is busy.",
499 "EventCode": "0xCD",
500 "Counter": "0,1,2,3",
501 "UMask": "0x2",
502 "PEBScounters": "0,1,2,3",
503 "EventName": "CYCLES_DIV_BUSY.FPDIV",
504 "PDIR_COUNTER": "na",
505 "SampleAfterValue": "200003",
506 "BriefDescription": "Cycles the FP divide unit is busy"
507 },
508 {
509 "CollectPEBSRecord": "1",
510 "PublicDescription": "Counts the number of times a BACLEAR is signaled for any reason, including, but not limited to indirect branch/call, Jcc (Jump on Conditional Code/Jump if Condition is Met) branch, unconditional branch/call, and returns.",
511 "EventCode": "0xE6",
512 "Counter": "0,1,2,3",
513 "UMask": "0x1",
514 "PEBScounters": "0,1,2,3",
515 "EventName": "BACLEARS.ALL",
516 "PDIR_COUNTER": "na",
517 "SampleAfterValue": "200003",
518 "BriefDescription": "BACLEARs asserted for any branch type"
519 },
520 {
521 "CollectPEBSRecord": "1",
522 "PublicDescription": "Counts BACLEARS on return instructions.",
523 "EventCode": "0xE6",
524 "Counter": "0,1,2,3",
525 "UMask": "0x8",
526 "PEBScounters": "0,1,2,3",
527 "EventName": "BACLEARS.RETURN",
528 "PDIR_COUNTER": "na",
529 "SampleAfterValue": "200003",
530 "BriefDescription": "BACLEARs asserted for return branch"
531 },
532 {
533 "CollectPEBSRecord": "1",
534 "PublicDescription": "Counts BACLEARS on Jcc (Jump on Conditional Code/Jump if Condition is Met) branches.",
535 "EventCode": "0xE6",
536 "Counter": "0,1,2,3",
537 "UMask": "0x10",
538 "PEBScounters": "0,1,2,3",
539 "EventName": "BACLEARS.COND",
540 "PDIR_COUNTER": "na",
541 "SampleAfterValue": "200003",
542 "BriefDescription": "BACLEARs asserted for conditional branch"
543 }
544] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/goldmontplus/virtual-memory.json b/tools/perf/pmu-events/arch/x86/goldmontplus/virtual-memory.json
new file mode 100644
index 000000000000..0b53a3b0dfb8
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/goldmontplus/virtual-memory.json
@@ -0,0 +1,218 @@
1[
2 {
3 "CollectPEBSRecord": "1",
4 "PublicDescription": "Counts page walks completed due to demand data loads (including SW prefetches) whose address translations missed in all TLB levels and were mapped to 4K pages. The page walks can end with or without a page fault.",
5 "EventCode": "0x08",
6 "Counter": "0,1,2,3",
7 "UMask": "0x2",
8 "PEBScounters": "0,1,2,3",
9 "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
10 "PDIR_COUNTER": "na",
11 "SampleAfterValue": "200003",
12 "BriefDescription": "Page walk completed due to a demand load to a 4K page"
13 },
14 {
15 "CollectPEBSRecord": "1",
16 "PublicDescription": "Counts page walks completed due to demand data loads (including SW prefetches) whose address translations missed in all TLB levels and were mapped to 2M or 4M pages. The page walks can end with or without a page fault.",
17 "EventCode": "0x08",
18 "Counter": "0,1,2,3",
19 "UMask": "0x4",
20 "PEBScounters": "0,1,2,3",
21 "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
22 "PDIR_COUNTER": "na",
23 "SampleAfterValue": "200003",
24 "BriefDescription": "Page walk completed due to a demand load to a 2M or 4M page"
25 },
26 {
27 "CollectPEBSRecord": "1",
28 "PublicDescription": "Counts page walks completed due to demand data loads (including SW prefetches) whose address translations missed in all TLB levels and were mapped to 1GB pages. The page walks can end with or without a page fault.",
29 "EventCode": "0x08",
30 "Counter": "0,1,2,3",
31 "UMask": "0x8",
32 "PEBScounters": "0,1,2,3",
33 "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1GB",
34 "PDIR_COUNTER": "na",
35 "SampleAfterValue": "200003",
36 "BriefDescription": "Page walk completed due to a demand load to a 1GB page"
37 },
38 {
39 "CollectPEBSRecord": "1",
40 "PublicDescription": "Counts once per cycle for each page walk occurring due to a load (demand data loads or SW prefetches). Includes cycles spent traversing the Extended Page Table (EPT). Average cycles per walk can be calculated by dividing by the number of walks.",
41 "EventCode": "0x08",
42 "Counter": "0,1,2,3",
43 "UMask": "0x10",
44 "PEBScounters": "0,1,2,3",
45 "EventName": "DTLB_LOAD_MISSES.WALK_PENDING",
46 "PDIR_COUNTER": "na",
47 "SampleAfterValue": "200003",
48 "BriefDescription": "Page walks outstanding due to a demand load every cycle."
49 },
50 {
51 "CollectPEBSRecord": "1",
52 "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.",
53 "EventCode": "0x49",
54 "Counter": "0,1,2,3",
55 "UMask": "0x2",
56 "PEBScounters": "0,1,2,3",
57 "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
58 "PDIR_COUNTER": "na",
59 "SampleAfterValue": "2000003",
60 "BriefDescription": "Page walk completed due to a demand data store to a 4K page"
61 },
62 {
63 "CollectPEBSRecord": "1",
64 "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 2M or 4M pages. The page walks can end with or without a page fault.",
65 "EventCode": "0x49",
66 "Counter": "0,1,2,3",
67 "UMask": "0x4",
68 "PEBScounters": "0,1,2,3",
69 "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
70 "PDIR_COUNTER": "na",
71 "SampleAfterValue": "2000003",
72 "BriefDescription": "Page walk completed due to a demand data store to a 2M or 4M page"
73 },
74 {
75 "CollectPEBSRecord": "1",
76 "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 1GB pages. The page walks can end with or without a page fault.",
77 "EventCode": "0x49",
78 "Counter": "0,1,2,3",
79 "UMask": "0x8",
80 "PEBScounters": "0,1,2,3",
81 "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1GB",
82 "PDIR_COUNTER": "na",
83 "SampleAfterValue": "2000003",
84 "BriefDescription": "Page walk completed due to a demand data store to a 1GB page"
85 },
86 {
87 "CollectPEBSRecord": "1",
88 "PublicDescription": "Counts once per cycle for each page walk occurring due to a demand data store. Includes cycles spent traversing the Extended Page Table (EPT). Average cycles per walk can be calculated by dividing by the number of walks.",
89 "EventCode": "0x49",
90 "Counter": "0,1,2,3",
91 "UMask": "0x10",
92 "PEBScounters": "0,1,2,3",
93 "EventName": "DTLB_STORE_MISSES.WALK_PENDING",
94 "PDIR_COUNTER": "na",
95 "SampleAfterValue": "200003",
96 "BriefDescription": "Page walks outstanding due to a demand data store every cycle."
97 },
98 {
99 "CollectPEBSRecord": "1",
100 "PublicDescription": "Counts once per cycle for each page walk only while traversing the Extended Page Table (EPT), and does not count during the rest of the translation. The EPT is used for translating Guest-Physical Addresses to Physical Addresses for Virtual Machine Monitors (VMMs). Average cycles per walk can be calculated by dividing the count by number of walks.",
101 "EventCode": "0x4F",
102 "Counter": "0,1,2,3",
103 "UMask": "0x10",
104 "PEBScounters": "0,1,2,3",
105 "EventName": "EPT.WALK_PENDING",
106 "PDIR_COUNTER": "na",
107 "SampleAfterValue": "200003",
108 "BriefDescription": "Page walks outstanding due to walking the EPT every cycle"
109 },
110 {
111 "CollectPEBSRecord": "1",
112 "PublicDescription": "Counts the number of times the machine was unable to find a translation in the Instruction Translation Lookaside Buffer (ITLB) for a linear address of an instruction fetch. It counts when new translation are filled into the ITLB. The event is speculative in nature, but will not count translations (page walks) that are begun and not finished, or translations that are finished but not filled into the ITLB.",
113 "EventCode": "0x81",
114 "Counter": "0,1,2,3",
115 "UMask": "0x4",
116 "PEBScounters": "0,1,2,3",
117 "EventName": "ITLB.MISS",
118 "PDIR_COUNTER": "na",
119 "SampleAfterValue": "200003",
120 "BriefDescription": "ITLB misses"
121 },
122 {
123 "CollectPEBSRecord": "1",
124 "PublicDescription": "Counts page walks completed due to instruction fetches whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.",
125 "EventCode": "0x85",
126 "Counter": "0,1,2,3",
127 "UMask": "0x2",
128 "PEBScounters": "0,1,2,3",
129 "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
130 "PDIR_COUNTER": "na",
131 "SampleAfterValue": "2000003",
132 "BriefDescription": "Page walk completed due to an instruction fetch in a 4K page"
133 },
134 {
135 "CollectPEBSRecord": "1",
136 "PublicDescription": "Counts page walks completed due to instruction fetches whose address translations missed in the TLB and were mapped to 2M or 4M pages. The page walks can end with or without a page fault.",
137 "EventCode": "0x85",
138 "Counter": "0,1,2,3",
139 "UMask": "0x4",
140 "PEBScounters": "0,1,2,3",
141 "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
142 "PDIR_COUNTER": "na",
143 "SampleAfterValue": "2000003",
144 "BriefDescription": "Page walk completed due to an instruction fetch in a 2M or 4M page"
145 },
146 {
147 "CollectPEBSRecord": "1",
148 "PublicDescription": "Counts page walks completed due to instruction fetches whose address translations missed in the TLB and were mapped to 1GB pages. The page walks can end with or without a page fault.",
149 "EventCode": "0x85",
150 "Counter": "0,1,2,3",
151 "UMask": "0x8",
152 "PEBScounters": "0,1,2,3",
153 "EventName": "ITLB_MISSES.WALK_COMPLETED_1GB",
154 "PDIR_COUNTER": "na",
155 "SampleAfterValue": "2000003",
156 "BriefDescription": "Page walk completed due to an instruction fetch in a 1GB page"
157 },
158 {
159 "CollectPEBSRecord": "1",
160 "PublicDescription": "Counts once per cycle for each page walk occurring due to an instruction fetch. Includes cycles spent traversing the Extended Page Table (EPT). Average cycles per walk can be calculated by dividing by the number of walks.",
161 "EventCode": "0x85",
162 "Counter": "0,1,2,3",
163 "UMask": "0x10",
164 "PEBScounters": "0,1,2,3",
165 "EventName": "ITLB_MISSES.WALK_PENDING",
166 "PDIR_COUNTER": "na",
167 "SampleAfterValue": "200003",
168 "BriefDescription": "Page walks outstanding due to an instruction fetch every cycle."
169 },
170 {
171 "CollectPEBSRecord": "1",
172 "PublicDescription": "Counts STLB flushes. The TLBs are flushed on instructions like INVLPG and MOV to CR3.",
173 "EventCode": "0xBD",
174 "Counter": "0,1,2,3",
175 "UMask": "0x20",
176 "PEBScounters": "0,1,2,3",
177 "EventName": "TLB_FLUSHES.STLB_ANY",
178 "PDIR_COUNTER": "na",
179 "SampleAfterValue": "20003",
180 "BriefDescription": "STLB flushes"
181 },
182 {
183 "PEBS": "2",
184 "CollectPEBSRecord": "2",
185 "PublicDescription": "Counts load uops retired that caused a DTLB miss.",
186 "EventCode": "0xD0",
187 "Counter": "0,1,2,3",
188 "UMask": "0x11",
189 "PEBScounters": "0,1,2,3",
190 "EventName": "MEM_UOPS_RETIRED.DTLB_MISS_LOADS",
191 "SampleAfterValue": "200003",
192 "BriefDescription": "Load uops retired that missed the DTLB (Precise event capable)"
193 },
194 {
195 "PEBS": "2",
196 "CollectPEBSRecord": "2",
197 "PublicDescription": "Counts store uops retired that caused a DTLB miss.",
198 "EventCode": "0xD0",
199 "Counter": "0,1,2,3",
200 "UMask": "0x12",
201 "PEBScounters": "0,1,2,3",
202 "EventName": "MEM_UOPS_RETIRED.DTLB_MISS_STORES",
203 "SampleAfterValue": "200003",
204 "BriefDescription": "Store uops retired that missed the DTLB (Precise event capable)"
205 },
206 {
207 "PEBS": "2",
208 "CollectPEBSRecord": "2",
209 "PublicDescription": "Counts uops retired that had a DTLB miss on load, store or either. Note that when two distinct memory operations to the same page miss the DTLB, only one of them will be recorded as a DTLB miss.",
210 "EventCode": "0xD0",
211 "Counter": "0,1,2,3",
212 "UMask": "0x13",
213 "PEBScounters": "0,1,2,3",
214 "EventName": "MEM_UOPS_RETIRED.DTLB_MISS",
215 "SampleAfterValue": "200003",
216 "BriefDescription": "Memory uops retired that missed the DTLB (Precise event capable)"
217 }
218] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswell/hsw-metrics.json b/tools/perf/pmu-events/arch/x86/haswell/hsw-metrics.json
new file mode 100644
index 000000000000..5ab5c78fe580
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswell/hsw-metrics.json
@@ -0,0 +1,158 @@
1[
2 {
3 "BriefDescription": "Instructions Per Cycle (per logical thread)",
4 "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
5 "MetricGroup": "TopDownL1",
6 "MetricName": "IPC"
7 },
8 {
9 "BriefDescription": "Uops Per Instruction",
10 "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY",
11 "MetricGroup": "Pipeline",
12 "MetricName": "UPI"
13 },
14 {
15 "BriefDescription": "Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions",
16 "MetricExpr": "min( 1 , IDQ.MITE_UOPS / ( (UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY) * 16 * ( ICACHE.HIT + ICACHE.MISSES ) / 4.0 ) )",
17 "MetricGroup": "Frontend",
18 "MetricName": "IFetch_Line_Utilization"
19 },
20 {
21 "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)",
22 "MetricExpr": "IDQ.DSB_UOPS / ( IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS )",
23 "MetricGroup": "DSB; Frontend_Bandwidth",
24 "MetricName": "DSB_Coverage"
25 },
26 {
27 "BriefDescription": "Cycles Per Instruction (threaded)",
28 "MetricExpr": "1 / (INST_RETIRED.ANY / cycles)",
29 "MetricGroup": "Pipeline;Summary",
30 "MetricName": "CPI"
31 },
32 {
33 "BriefDescription": "Per-thread actual clocks when the logical processor is active. This is called 'Clockticks' in VTune.",
34 "MetricExpr": "CPU_CLK_UNHALTED.THREAD",
35 "MetricGroup": "Summary",
36 "MetricName": "CLKS"
37 },
38 {
39 "BriefDescription": "Total issue-pipeline slots",
40 "MetricExpr": "4*(( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
41 "MetricGroup": "TopDownL1",
42 "MetricName": "SLOTS"
43 },
44 {
45 "BriefDescription": "Total number of retired Instructions",
46 "MetricExpr": "INST_RETIRED.ANY",
47 "MetricGroup": "Summary",
48 "MetricName": "Instructions"
49 },
50 {
51 "BriefDescription": "Instructions Per Cycle (per physical core)",
52 "MetricExpr": "INST_RETIRED.ANY / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
53 "MetricGroup": "SMT",
54 "MetricName": "CoreIPC"
55 },
56 {
57 "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
58 "MetricExpr": "( UOPS_EXECUTED.CORE / 2 / (( cpu@UOPS_EXECUTED.CORE\\,cmask\\=1@ / 2) if #SMT_on else cpu@UOPS_EXECUTED.CORE\\,cmask\\=1@) ) if #SMT_on else UOPS_EXECUTED.CORE / (( cpu@UOPS_EXECUTED.CORE\\,cmask\\=1@ / 2) if #SMT_on else cpu@UOPS_EXECUTED.CORE\\,cmask\\=1@)",
59 "MetricGroup": "Pipeline;Ports_Utilization",
60 "MetricName": "ILP"
61 },
62 {
63 "BriefDescription": "Average Branch Address Clear Cost (fraction of cycles)",
64 "MetricExpr": "2* (( RS_EVENTS.EMPTY_CYCLES - ICACHE.IFDATA_STALL - (( 14 * ITLB_MISSES.STLB_HIT + ITLB_MISSES.WALK_DURATION )) ) / RS_EVENTS.EMPTY_END)",
65 "MetricGroup": "Unknown_Branches",
66 "MetricName": "BAClear_Cost"
67 },
68 {
69 "BriefDescription": "Core actual clocks when any thread is active on the physical core",
70 "MetricExpr": "( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else CPU_CLK_UNHALTED.THREAD",
71 "MetricGroup": "SMT",
72 "MetricName": "CORE_CLKS"
73 },
74 {
75 "BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads",
76 "MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_UOPS_RETIRED.L1_MISS + mem_load_uops_retired.hit_lfb )",
77 "MetricGroup": "Memory_Bound;Memory_Lat",
78 "MetricName": "Load_Miss_Real_Latency"
79 },
80 {
81 "BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least 1 such miss)",
82 "MetricExpr": "L1D_PEND_MISS.PENDING / (( cpu@l1d_pend_miss.pending_cycles\\,any\\=1@ / 2) if #SMT_on else L1D_PEND_MISS.PENDING_CYCLES)",
83 "MetricGroup": "Memory_Bound;Memory_BW",
84 "MetricName": "MLP"
85 },
86 {
87 "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
88 "MetricExpr": "( ITLB_MISSES.WALK_DURATION + DTLB_LOAD_MISSES.WALK_DURATION + DTLB_STORE_MISSES.WALK_DURATION ) / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
89 "MetricGroup": "TLB",
90 "MetricName": "Page_Walks_Utilization"
91 },
92 {
93 "BriefDescription": "Average CPU Utilization",
94 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
95 "MetricGroup": "Summary",
96 "MetricName": "CPU_Utilization"
97 },
98 {
99 "BriefDescription": "Average Frequency Utilization relative nominal frequency",
100 "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC",
101 "MetricGroup": "Power",
102 "MetricName": "Turbo_Utilization"
103 },
104 {
105 "BriefDescription": "Fraction of cycles where both hardware threads were active",
106 "MetricExpr": "1 - CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
107 "MetricGroup": "SMT;Summary",
108 "MetricName": "SMT_2T_Utilization"
109 },
110 {
111 "BriefDescription": "Fraction of cycles spent in Kernel mode",
112 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
113 "MetricGroup": "Summary",
114 "MetricName": "Kernel_Utilization"
115 },
116 {
117 "BriefDescription": "C3 residency percent per core",
118 "MetricExpr": "(cstate_core@c3\\-residency@ / msr@tsc@) * 100",
119 "MetricGroup": "Power",
120 "MetricName": "C3_Core_Residency"
121 },
122 {
123 "BriefDescription": "C6 residency percent per core",
124 "MetricExpr": "(cstate_core@c6\\-residency@ / msr@tsc@) * 100",
125 "MetricGroup": "Power",
126 "MetricName": "C6_Core_Residency"
127 },
128 {
129 "BriefDescription": "C7 residency percent per core",
130 "MetricExpr": "(cstate_core@c7\\-residency@ / msr@tsc@) * 100",
131 "MetricGroup": "Power",
132 "MetricName": "C7_Core_Residency"
133 },
134 {
135 "BriefDescription": "C2 residency percent per package",
136 "MetricExpr": "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100",
137 "MetricGroup": "Power",
138 "MetricName": "C2_Pkg_Residency"
139 },
140 {
141 "BriefDescription": "C3 residency percent per package",
142 "MetricExpr": "(cstate_pkg@c3\\-residency@ / msr@tsc@) * 100",
143 "MetricGroup": "Power",
144 "MetricName": "C3_Pkg_Residency"
145 },
146 {
147 "BriefDescription": "C6 residency percent per package",
148 "MetricExpr": "(cstate_pkg@c6\\-residency@ / msr@tsc@) * 100",
149 "MetricGroup": "Power",
150 "MetricName": "C6_Pkg_Residency"
151 },
152 {
153 "BriefDescription": "C7 residency percent per package",
154 "MetricExpr": "(cstate_pkg@c7\\-residency@ / msr@tsc@) * 100",
155 "MetricGroup": "Power",
156 "MetricName": "C7_Pkg_Residency"
157 }
158]
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/hsx-metrics.json b/tools/perf/pmu-events/arch/x86/haswellx/hsx-metrics.json
new file mode 100644
index 000000000000..5ab5c78fe580
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswellx/hsx-metrics.json
@@ -0,0 +1,158 @@
1[
2 {
3 "BriefDescription": "Instructions Per Cycle (per logical thread)",
4 "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
5 "MetricGroup": "TopDownL1",
6 "MetricName": "IPC"
7 },
8 {
9 "BriefDescription": "Uops Per Instruction",
10 "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY",
11 "MetricGroup": "Pipeline",
12 "MetricName": "UPI"
13 },
14 {
15 "BriefDescription": "Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions",
16 "MetricExpr": "min( 1 , IDQ.MITE_UOPS / ( (UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY) * 16 * ( ICACHE.HIT + ICACHE.MISSES ) / 4.0 ) )",
17 "MetricGroup": "Frontend",
18 "MetricName": "IFetch_Line_Utilization"
19 },
20 {
21 "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)",
22 "MetricExpr": "IDQ.DSB_UOPS / ( IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS )",
23 "MetricGroup": "DSB; Frontend_Bandwidth",
24 "MetricName": "DSB_Coverage"
25 },
26 {
27 "BriefDescription": "Cycles Per Instruction (threaded)",
28 "MetricExpr": "1 / (INST_RETIRED.ANY / cycles)",
29 "MetricGroup": "Pipeline;Summary",
30 "MetricName": "CPI"
31 },
32 {
33 "BriefDescription": "Per-thread actual clocks when the logical processor is active. This is called 'Clockticks' in VTune.",
34 "MetricExpr": "CPU_CLK_UNHALTED.THREAD",
35 "MetricGroup": "Summary",
36 "MetricName": "CLKS"
37 },
38 {
39 "BriefDescription": "Total issue-pipeline slots",
40 "MetricExpr": "4*(( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
41 "MetricGroup": "TopDownL1",
42 "MetricName": "SLOTS"
43 },
44 {
45 "BriefDescription": "Total number of retired Instructions",
46 "MetricExpr": "INST_RETIRED.ANY",
47 "MetricGroup": "Summary",
48 "MetricName": "Instructions"
49 },
50 {
51 "BriefDescription": "Instructions Per Cycle (per physical core)",
52 "MetricExpr": "INST_RETIRED.ANY / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
53 "MetricGroup": "SMT",
54 "MetricName": "CoreIPC"
55 },
56 {
57 "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
58 "MetricExpr": "( UOPS_EXECUTED.CORE / 2 / (( cpu@UOPS_EXECUTED.CORE\\,cmask\\=1@ / 2) if #SMT_on else cpu@UOPS_EXECUTED.CORE\\,cmask\\=1@) ) if #SMT_on else UOPS_EXECUTED.CORE / (( cpu@UOPS_EXECUTED.CORE\\,cmask\\=1@ / 2) if #SMT_on else cpu@UOPS_EXECUTED.CORE\\,cmask\\=1@)",
59 "MetricGroup": "Pipeline;Ports_Utilization",
60 "MetricName": "ILP"
61 },
62 {
63 "BriefDescription": "Average Branch Address Clear Cost (fraction of cycles)",
64 "MetricExpr": "2* (( RS_EVENTS.EMPTY_CYCLES - ICACHE.IFDATA_STALL - (( 14 * ITLB_MISSES.STLB_HIT + ITLB_MISSES.WALK_DURATION )) ) / RS_EVENTS.EMPTY_END)",
65 "MetricGroup": "Unknown_Branches",
66 "MetricName": "BAClear_Cost"
67 },
68 {
69 "BriefDescription": "Core actual clocks when any thread is active on the physical core",
70 "MetricExpr": "( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else CPU_CLK_UNHALTED.THREAD",
71 "MetricGroup": "SMT",
72 "MetricName": "CORE_CLKS"
73 },
74 {
75 "BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads",
76 "MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_UOPS_RETIRED.L1_MISS + mem_load_uops_retired.hit_lfb )",
77 "MetricGroup": "Memory_Bound;Memory_Lat",
78 "MetricName": "Load_Miss_Real_Latency"
79 },
80 {
81 "BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least 1 such miss)",
82 "MetricExpr": "L1D_PEND_MISS.PENDING / (( cpu@l1d_pend_miss.pending_cycles\\,any\\=1@ / 2) if #SMT_on else L1D_PEND_MISS.PENDING_CYCLES)",
83 "MetricGroup": "Memory_Bound;Memory_BW",
84 "MetricName": "MLP"
85 },
86 {
87 "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
88 "MetricExpr": "( ITLB_MISSES.WALK_DURATION + DTLB_LOAD_MISSES.WALK_DURATION + DTLB_STORE_MISSES.WALK_DURATION ) / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
89 "MetricGroup": "TLB",
90 "MetricName": "Page_Walks_Utilization"
91 },
92 {
93 "BriefDescription": "Average CPU Utilization",
94 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
95 "MetricGroup": "Summary",
96 "MetricName": "CPU_Utilization"
97 },
98 {
99 "BriefDescription": "Average Frequency Utilization relative nominal frequency",
100 "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC",
101 "MetricGroup": "Power",
102 "MetricName": "Turbo_Utilization"
103 },
104 {
105 "BriefDescription": "Fraction of cycles where both hardware threads were active",
106 "MetricExpr": "1 - CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
107 "MetricGroup": "SMT;Summary",
108 "MetricName": "SMT_2T_Utilization"
109 },
110 {
111 "BriefDescription": "Fraction of cycles spent in Kernel mode",
112 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
113 "MetricGroup": "Summary",
114 "MetricName": "Kernel_Utilization"
115 },
116 {
117 "BriefDescription": "C3 residency percent per core",
118 "MetricExpr": "(cstate_core@c3\\-residency@ / msr@tsc@) * 100",
119 "MetricGroup": "Power",
120 "MetricName": "C3_Core_Residency"
121 },
122 {
123 "BriefDescription": "C6 residency percent per core",
124 "MetricExpr": "(cstate_core@c6\\-residency@ / msr@tsc@) * 100",
125 "MetricGroup": "Power",
126 "MetricName": "C6_Core_Residency"
127 },
128 {
129 "BriefDescription": "C7 residency percent per core",
130 "MetricExpr": "(cstate_core@c7\\-residency@ / msr@tsc@) * 100",
131 "MetricGroup": "Power",
132 "MetricName": "C7_Core_Residency"
133 },
134 {
135 "BriefDescription": "C2 residency percent per package",
136 "MetricExpr": "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100",
137 "MetricGroup": "Power",
138 "MetricName": "C2_Pkg_Residency"
139 },
140 {
141 "BriefDescription": "C3 residency percent per package",
142 "MetricExpr": "(cstate_pkg@c3\\-residency@ / msr@tsc@) * 100",
143 "MetricGroup": "Power",
144 "MetricName": "C3_Pkg_Residency"
145 },
146 {
147 "BriefDescription": "C6 residency percent per package",
148 "MetricExpr": "(cstate_pkg@c6\\-residency@ / msr@tsc@) * 100",
149 "MetricGroup": "Power",
150 "MetricName": "C6_Pkg_Residency"
151 },
152 {
153 "BriefDescription": "C7 residency percent per package",
154 "MetricExpr": "(cstate_pkg@c7\\-residency@ / msr@tsc@) * 100",
155 "MetricGroup": "Power",
156 "MetricName": "C7_Pkg_Residency"
157 }
158]
diff --git a/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json b/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json
new file mode 100644
index 000000000000..7c2679514efb
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json
@@ -0,0 +1,164 @@
1[
2 {
3 "BriefDescription": "Instructions Per Cycle (per logical thread)",
4 "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
5 "MetricGroup": "TopDownL1",
6 "MetricName": "IPC"
7 },
8 {
9 "BriefDescription": "Uops Per Instruction",
10 "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY",
11 "MetricGroup": "Pipeline",
12 "MetricName": "UPI"
13 },
14 {
15 "BriefDescription": "Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions",
16 "MetricExpr": "min( 1 , UOPS_ISSUED.ANY / ( (UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY) * 32 * ( ICACHE.HIT + ICACHE.MISSES ) / 4) )",
17 "MetricGroup": "Frontend",
18 "MetricName": "IFetch_Line_Utilization"
19 },
20 {
21 "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)",
22 "MetricExpr": "IDQ.DSB_UOPS / ( IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS )",
23 "MetricGroup": "DSB; Frontend_Bandwidth",
24 "MetricName": "DSB_Coverage"
25 },
26 {
27 "BriefDescription": "Cycles Per Instruction (threaded)",
28 "MetricExpr": "1 / (INST_RETIRED.ANY / cycles)",
29 "MetricGroup": "Pipeline;Summary",
30 "MetricName": "CPI"
31 },
32 {
33 "BriefDescription": "Per-thread actual clocks when the logical processor is active. This is called 'Clockticks' in VTune.",
34 "MetricExpr": "CPU_CLK_UNHALTED.THREAD",
35 "MetricGroup": "Summary",
36 "MetricName": "CLKS"
37 },
38 {
39 "BriefDescription": "Total issue-pipeline slots",
40 "MetricExpr": "4*(( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
41 "MetricGroup": "TopDownL1",
42 "MetricName": "SLOTS"
43 },
44 {
45 "BriefDescription": "Total number of retired Instructions",
46 "MetricExpr": "INST_RETIRED.ANY",
47 "MetricGroup": "Summary",
48 "MetricName": "Instructions"
49 },
50 {
51 "BriefDescription": "Instructions Per Cycle (per physical core)",
52 "MetricExpr": "INST_RETIRED.ANY / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
53 "MetricGroup": "SMT",
54 "MetricName": "CoreIPC"
55 },
56 {
57 "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
58 "MetricExpr": "UOPS_EXECUTED.THREAD / (( cpu@UOPS_EXECUTED.CORE\\,cmask\\=1@ / 2) if #SMT_on else UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC)",
59 "MetricGroup": "Pipeline;Ports_Utilization",
60 "MetricName": "ILP"
61 },
62 {
63 "BriefDescription": "Average Branch Address Clear Cost (fraction of cycles)",
64 "MetricExpr": "2* (( RS_EVENTS.EMPTY_CYCLES - ICACHE.IFETCH_STALL ) / RS_EVENTS.EMPTY_END)",
65 "MetricGroup": "Unknown_Branches",
66 "MetricName": "BAClear_Cost"
67 },
68 {
69 "BriefDescription": "Core actual clocks when any thread is active on the physical core",
70 "MetricExpr": "( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else CPU_CLK_UNHALTED.THREAD",
71 "MetricGroup": "SMT",
72 "MetricName": "CORE_CLKS"
73 },
74 {
75 "BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads",
76 "MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_UOPS_RETIRED.L1_MISS + mem_load_uops_retired.hit_lfb )",
77 "MetricGroup": "Memory_Bound;Memory_Lat",
78 "MetricName": "Load_Miss_Real_Latency"
79 },
80 {
81 "BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least 1 such miss)",
82 "MetricExpr": "L1D_PEND_MISS.PENDING / (( cpu@l1d_pend_miss.pending_cycles\\,any\\=1@ / 2) if #SMT_on else L1D_PEND_MISS.PENDING_CYCLES)",
83 "MetricGroup": "Memory_Bound;Memory_BW",
84 "MetricName": "MLP"
85 },
86 {
87 "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
88 "MetricExpr": "( ITLB_MISSES.WALK_DURATION + DTLB_LOAD_MISSES.WALK_DURATION + DTLB_STORE_MISSES.WALK_DURATION ) / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
89 "MetricGroup": "TLB",
90 "MetricName": "Page_Walks_Utilization"
91 },
92 {
93 "BriefDescription": "Average CPU Utilization",
94 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
95 "MetricGroup": "Summary",
96 "MetricName": "CPU_Utilization"
97 },
98 {
99 "BriefDescription": "Giga Floating Point Operations Per Second",
100 "MetricExpr": "(( 1*( FP_COMP_OPS_EXE.SSE_SCALAR_SINGLE + FP_COMP_OPS_EXE.SSE_SCALAR_DOUBLE ) + 2* FP_COMP_OPS_EXE.SSE_PACKED_DOUBLE + 4*( FP_COMP_OPS_EXE.SSE_PACKED_SINGLE + SIMD_FP_256.PACKED_DOUBLE ) + 8* SIMD_FP_256.PACKED_SINGLE )) / 1000000000 / duration_time",
101 "MetricGroup": "FLOPS;Summary",
102 "MetricName": "GFLOPs"
103 },
104 {
105 "BriefDescription": "Average Frequency Utilization relative nominal frequency",
106 "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC",
107 "MetricGroup": "Power",
108 "MetricName": "Turbo_Utilization"
109 },
110 {
111 "BriefDescription": "Fraction of cycles where both hardware threads were active",
112 "MetricExpr": "1 - CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
113 "MetricGroup": "SMT;Summary",
114 "MetricName": "SMT_2T_Utilization"
115 },
116 {
117 "BriefDescription": "Fraction of cycles spent in Kernel mode",
118 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
119 "MetricGroup": "Summary",
120 "MetricName": "Kernel_Utilization"
121 },
122 {
123 "BriefDescription": "C3 residency percent per core",
124 "MetricExpr": "(cstate_core@c3\\-residency@ / msr@tsc@) * 100",
125 "MetricGroup": "Power",
126 "MetricName": "C3_Core_Residency"
127 },
128 {
129 "BriefDescription": "C6 residency percent per core",
130 "MetricExpr": "(cstate_core@c6\\-residency@ / msr@tsc@) * 100",
131 "MetricGroup": "Power",
132 "MetricName": "C6_Core_Residency"
133 },
134 {
135 "BriefDescription": "C7 residency percent per core",
136 "MetricExpr": "(cstate_core@c7\\-residency@ / msr@tsc@) * 100",
137 "MetricGroup": "Power",
138 "MetricName": "C7_Core_Residency"
139 },
140 {
141 "BriefDescription": "C2 residency percent per package",
142 "MetricExpr": "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100",
143 "MetricGroup": "Power",
144 "MetricName": "C2_Pkg_Residency"
145 },
146 {
147 "BriefDescription": "C3 residency percent per package",
148 "MetricExpr": "(cstate_pkg@c3\\-residency@ / msr@tsc@) * 100",
149 "MetricGroup": "Power",
150 "MetricName": "C3_Pkg_Residency"
151 },
152 {
153 "BriefDescription": "C6 residency percent per package",
154 "MetricExpr": "(cstate_pkg@c6\\-residency@ / msr@tsc@) * 100",
155 "MetricGroup": "Power",
156 "MetricName": "C6_Pkg_Residency"
157 },
158 {
159 "BriefDescription": "C7 residency percent per package",
160 "MetricExpr": "(cstate_pkg@c7\\-residency@ / msr@tsc@) * 100",
161 "MetricGroup": "Power",
162 "MetricName": "C7_Pkg_Residency"
163 }
164]
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/ivt-metrics.json b/tools/perf/pmu-events/arch/x86/ivytown/ivt-metrics.json
new file mode 100644
index 000000000000..7c2679514efb
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivytown/ivt-metrics.json
@@ -0,0 +1,164 @@
1[
2 {
3 "BriefDescription": "Instructions Per Cycle (per logical thread)",
4 "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
5 "MetricGroup": "TopDownL1",
6 "MetricName": "IPC"
7 },
8 {
9 "BriefDescription": "Uops Per Instruction",
10 "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY",
11 "MetricGroup": "Pipeline",
12 "MetricName": "UPI"
13 },
14 {
15 "BriefDescription": "Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions",
16 "MetricExpr": "min( 1 , UOPS_ISSUED.ANY / ( (UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY) * 32 * ( ICACHE.HIT + ICACHE.MISSES ) / 4) )",
17 "MetricGroup": "Frontend",
18 "MetricName": "IFetch_Line_Utilization"
19 },
20 {
21 "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)",
22 "MetricExpr": "IDQ.DSB_UOPS / ( IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS )",
23 "MetricGroup": "DSB; Frontend_Bandwidth",
24 "MetricName": "DSB_Coverage"
25 },
26 {
27 "BriefDescription": "Cycles Per Instruction (threaded)",
28 "MetricExpr": "1 / (INST_RETIRED.ANY / cycles)",
29 "MetricGroup": "Pipeline;Summary",
30 "MetricName": "CPI"
31 },
32 {
33 "BriefDescription": "Per-thread actual clocks when the logical processor is active. This is called 'Clockticks' in VTune.",
34 "MetricExpr": "CPU_CLK_UNHALTED.THREAD",
35 "MetricGroup": "Summary",
36 "MetricName": "CLKS"
37 },
38 {
39 "BriefDescription": "Total issue-pipeline slots",
40 "MetricExpr": "4*(( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
41 "MetricGroup": "TopDownL1",
42 "MetricName": "SLOTS"
43 },
44 {
45 "BriefDescription": "Total number of retired Instructions",
46 "MetricExpr": "INST_RETIRED.ANY",
47 "MetricGroup": "Summary",
48 "MetricName": "Instructions"
49 },
50 {
51 "BriefDescription": "Instructions Per Cycle (per physical core)",
52 "MetricExpr": "INST_RETIRED.ANY / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
53 "MetricGroup": "SMT",
54 "MetricName": "CoreIPC"
55 },
56 {
57 "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
58 "MetricExpr": "UOPS_EXECUTED.THREAD / (( cpu@UOPS_EXECUTED.CORE\\,cmask\\=1@ / 2) if #SMT_on else UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC)",
59 "MetricGroup": "Pipeline;Ports_Utilization",
60 "MetricName": "ILP"
61 },
62 {
63 "BriefDescription": "Average Branch Address Clear Cost (fraction of cycles)",
64 "MetricExpr": "2* (( RS_EVENTS.EMPTY_CYCLES - ICACHE.IFETCH_STALL ) / RS_EVENTS.EMPTY_END)",
65 "MetricGroup": "Unknown_Branches",
66 "MetricName": "BAClear_Cost"
67 },
68 {
69 "BriefDescription": "Core actual clocks when any thread is active on the physical core",
70 "MetricExpr": "( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else CPU_CLK_UNHALTED.THREAD",
71 "MetricGroup": "SMT",
72 "MetricName": "CORE_CLKS"
73 },
74 {
75 "BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads",
76 "MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_UOPS_RETIRED.L1_MISS + mem_load_uops_retired.hit_lfb )",
77 "MetricGroup": "Memory_Bound;Memory_Lat",
78 "MetricName": "Load_Miss_Real_Latency"
79 },
80 {
81 "BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least 1 such miss)",
82 "MetricExpr": "L1D_PEND_MISS.PENDING / (( cpu@l1d_pend_miss.pending_cycles\\,any\\=1@ / 2) if #SMT_on else L1D_PEND_MISS.PENDING_CYCLES)",
83 "MetricGroup": "Memory_Bound;Memory_BW",
84 "MetricName": "MLP"
85 },
86 {
87 "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
88 "MetricExpr": "( ITLB_MISSES.WALK_DURATION + DTLB_LOAD_MISSES.WALK_DURATION + DTLB_STORE_MISSES.WALK_DURATION ) / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
89 "MetricGroup": "TLB",
90 "MetricName": "Page_Walks_Utilization"
91 },
92 {
93 "BriefDescription": "Average CPU Utilization",
94 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
95 "MetricGroup": "Summary",
96 "MetricName": "CPU_Utilization"
97 },
98 {
99 "BriefDescription": "Giga Floating Point Operations Per Second",
100 "MetricExpr": "(( 1*( FP_COMP_OPS_EXE.SSE_SCALAR_SINGLE + FP_COMP_OPS_EXE.SSE_SCALAR_DOUBLE ) + 2* FP_COMP_OPS_EXE.SSE_PACKED_DOUBLE + 4*( FP_COMP_OPS_EXE.SSE_PACKED_SINGLE + SIMD_FP_256.PACKED_DOUBLE ) + 8* SIMD_FP_256.PACKED_SINGLE )) / 1000000000 / duration_time",
101 "MetricGroup": "FLOPS;Summary",
102 "MetricName": "GFLOPs"
103 },
104 {
105 "BriefDescription": "Average Frequency Utilization relative nominal frequency",
106 "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC",
107 "MetricGroup": "Power",
108 "MetricName": "Turbo_Utilization"
109 },
110 {
111 "BriefDescription": "Fraction of cycles where both hardware threads were active",
112 "MetricExpr": "1 - CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
113 "MetricGroup": "SMT;Summary",
114 "MetricName": "SMT_2T_Utilization"
115 },
116 {
117 "BriefDescription": "Fraction of cycles spent in Kernel mode",
118 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
119 "MetricGroup": "Summary",
120 "MetricName": "Kernel_Utilization"
121 },
122 {
123 "BriefDescription": "C3 residency percent per core",
124 "MetricExpr": "(cstate_core@c3\\-residency@ / msr@tsc@) * 100",
125 "MetricGroup": "Power",
126 "MetricName": "C3_Core_Residency"
127 },
128 {
129 "BriefDescription": "C6 residency percent per core",
130 "MetricExpr": "(cstate_core@c6\\-residency@ / msr@tsc@) * 100",
131 "MetricGroup": "Power",
132 "MetricName": "C6_Core_Residency"
133 },
134 {
135 "BriefDescription": "C7 residency percent per core",
136 "MetricExpr": "(cstate_core@c7\\-residency@ / msr@tsc@) * 100",
137 "MetricGroup": "Power",
138 "MetricName": "C7_Core_Residency"
139 },
140 {
141 "BriefDescription": "C2 residency percent per package",
142 "MetricExpr": "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100",
143 "MetricGroup": "Power",
144 "MetricName": "C2_Pkg_Residency"
145 },
146 {
147 "BriefDescription": "C3 residency percent per package",
148 "MetricExpr": "(cstate_pkg@c3\\-residency@ / msr@tsc@) * 100",
149 "MetricGroup": "Power",
150 "MetricName": "C3_Pkg_Residency"
151 },
152 {
153 "BriefDescription": "C6 residency percent per package",
154 "MetricExpr": "(cstate_pkg@c6\\-residency@ / msr@tsc@) * 100",
155 "MetricGroup": "Power",
156 "MetricName": "C6_Pkg_Residency"
157 },
158 {
159 "BriefDescription": "C7 residency percent per package",
160 "MetricExpr": "(cstate_pkg@c7\\-residency@ / msr@tsc@) * 100",
161 "MetricGroup": "Power",
162 "MetricName": "C7_Pkg_Residency"
163 }
164]
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/jkt-metrics.json b/tools/perf/pmu-events/arch/x86/jaketown/jkt-metrics.json
new file mode 100644
index 000000000000..fd7d7c438226
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/jaketown/jkt-metrics.json
@@ -0,0 +1,140 @@
1[
2 {
3 "BriefDescription": "Instructions Per Cycle (per logical thread)",
4 "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
5 "MetricGroup": "TopDownL1",
6 "MetricName": "IPC"
7 },
8 {
9 "BriefDescription": "Uops Per Instruction",
10 "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY",
11 "MetricGroup": "Pipeline",
12 "MetricName": "UPI"
13 },
14 {
15 "BriefDescription": "Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions",
16 "MetricExpr": "min( 1 , UOPS_ISSUED.ANY / ( (UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY) * 32 * ( ICACHE.HIT + ICACHE.MISSES ) / 4) )",
17 "MetricGroup": "Frontend",
18 "MetricName": "IFetch_Line_Utilization"
19 },
20 {
21 "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)",
22 "MetricExpr": "IDQ.DSB_UOPS / ( IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS )",
23 "MetricGroup": "DSB; Frontend_Bandwidth",
24 "MetricName": "DSB_Coverage"
25 },
26 {
27 "BriefDescription": "Cycles Per Instruction (threaded)",
28 "MetricExpr": "1 / (INST_RETIRED.ANY / cycles)",
29 "MetricGroup": "Pipeline;Summary",
30 "MetricName": "CPI"
31 },
32 {
33 "BriefDescription": "Per-thread actual clocks when the logical processor is active. This is called 'Clockticks' in VTune.",
34 "MetricExpr": "CPU_CLK_UNHALTED.THREAD",
35 "MetricGroup": "Summary",
36 "MetricName": "CLKS"
37 },
38 {
39 "BriefDescription": "Total issue-pipeline slots",
40 "MetricExpr": "4*(( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
41 "MetricGroup": "TopDownL1",
42 "MetricName": "SLOTS"
43 },
44 {
45 "BriefDescription": "Total number of retired Instructions",
46 "MetricExpr": "INST_RETIRED.ANY",
47 "MetricGroup": "Summary",
48 "MetricName": "Instructions"
49 },
50 {
51 "BriefDescription": "Instructions Per Cycle (per physical core)",
52 "MetricExpr": "INST_RETIRED.ANY / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
53 "MetricGroup": "SMT",
54 "MetricName": "CoreIPC"
55 },
56 {
57 "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
58 "MetricExpr": "UOPS_DISPATCHED.THREAD / (( cpu@UOPS_DISPATCHED.CORE\\,cmask\\=1@ / 2) if #SMT_on else cpu@UOPS_DISPATCHED.CORE\\,cmask\\=1@)",
59 "MetricGroup": "Pipeline;Ports_Utilization",
60 "MetricName": "ILP"
61 },
62 {
63 "BriefDescription": "Core actual clocks when any thread is active on the physical core",
64 "MetricExpr": "( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else CPU_CLK_UNHALTED.THREAD",
65 "MetricGroup": "SMT",
66 "MetricName": "CORE_CLKS"
67 },
68 {
69 "BriefDescription": "Average CPU Utilization",
70 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
71 "MetricGroup": "Summary",
72 "MetricName": "CPU_Utilization"
73 },
74 {
75 "BriefDescription": "Giga Floating Point Operations Per Second",
76 "MetricExpr": "(( 1*( FP_COMP_OPS_EXE.SSE_SCALAR_SINGLE + FP_COMP_OPS_EXE.SSE_SCALAR_DOUBLE ) + 2* FP_COMP_OPS_EXE.SSE_PACKED_DOUBLE + 4*( FP_COMP_OPS_EXE.SSE_PACKED_SINGLE + SIMD_FP_256.PACKED_DOUBLE ) + 8* SIMD_FP_256.PACKED_SINGLE )) / 1000000000 / duration_time",
77 "MetricGroup": "FLOPS;Summary",
78 "MetricName": "GFLOPs"
79 },
80 {
81 "BriefDescription": "Average Frequency Utilization relative nominal frequency",
82 "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC",
83 "MetricGroup": "Power",
84 "MetricName": "Turbo_Utilization"
85 },
86 {
87 "BriefDescription": "Fraction of cycles where both hardware threads were active",
88 "MetricExpr": "1 - CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
89 "MetricGroup": "SMT;Summary",
90 "MetricName": "SMT_2T_Utilization"
91 },
92 {
93 "BriefDescription": "Fraction of cycles spent in Kernel mode",
94 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
95 "MetricGroup": "Summary",
96 "MetricName": "Kernel_Utilization"
97 },
98 {
99 "BriefDescription": "C3 residency percent per core",
100 "MetricExpr": "(cstate_core@c3\\-residency@ / msr@tsc@) * 100",
101 "MetricGroup": "Power",
102 "MetricName": "C3_Core_Residency"
103 },
104 {
105 "BriefDescription": "C6 residency percent per core",
106 "MetricExpr": "(cstate_core@c6\\-residency@ / msr@tsc@) * 100",
107 "MetricGroup": "Power",
108 "MetricName": "C6_Core_Residency"
109 },
110 {
111 "BriefDescription": "C7 residency percent per core",
112 "MetricExpr": "(cstate_core@c7\\-residency@ / msr@tsc@) * 100",
113 "MetricGroup": "Power",
114 "MetricName": "C7_Core_Residency"
115 },
116 {
117 "BriefDescription": "C2 residency percent per package",
118 "MetricExpr": "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100",
119 "MetricGroup": "Power",
120 "MetricName": "C2_Pkg_Residency"
121 },
122 {
123 "BriefDescription": "C3 residency percent per package",
124 "MetricExpr": "(cstate_pkg@c3\\-residency@ / msr@tsc@) * 100",
125 "MetricGroup": "Power",
126 "MetricName": "C3_Pkg_Residency"
127 },
128 {
129 "BriefDescription": "C6 residency percent per package",
130 "MetricExpr": "(cstate_pkg@c6\\-residency@ / msr@tsc@) * 100",
131 "MetricGroup": "Power",
132 "MetricName": "C6_Pkg_Residency"
133 },
134 {
135 "BriefDescription": "C7 residency percent per package",
136 "MetricExpr": "(cstate_pkg@c7\\-residency@ / msr@tsc@) * 100",
137 "MetricGroup": "Power",
138 "MetricName": "C7_Pkg_Residency"
139 }
140]
diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv
index d1a12e584c1b..fe1a2c47cabf 100644
--- a/tools/perf/pmu-events/arch/x86/mapfile.csv
+++ b/tools/perf/pmu-events/arch/x86/mapfile.csv
@@ -9,6 +9,7 @@ GenuineIntel-6-27,v4,bonnell,core
9GenuineIntel-6-36,v4,bonnell,core 9GenuineIntel-6-36,v4,bonnell,core
10GenuineIntel-6-35,v4,bonnell,core 10GenuineIntel-6-35,v4,bonnell,core
11GenuineIntel-6-5C,v8,goldmont,core 11GenuineIntel-6-5C,v8,goldmont,core
12GenuineIntel-6-7A,v1,goldmontplus,core
12GenuineIntel-6-3C,v24,haswell,core 13GenuineIntel-6-3C,v24,haswell,core
13GenuineIntel-6-45,v24,haswell,core 14GenuineIntel-6-45,v24,haswell,core
14GenuineIntel-6-46,v24,haswell,core 15GenuineIntel-6-46,v24,haswell,core
@@ -34,3 +35,4 @@ GenuineIntel-6-2C,v2,westmereep-dp,core
34GenuineIntel-6-2C,v2,westmereep-dp,core 35GenuineIntel-6-2C,v2,westmereep-dp,core
35GenuineIntel-6-25,v2,westmereep-sp,core 36GenuineIntel-6-25,v2,westmereep-sp,core
36GenuineIntel-6-2F,v2,westmereex,core 37GenuineIntel-6-2F,v2,westmereex,core
38GenuineIntel-6-55,v1,skylakex,core
diff --git a/tools/perf/pmu-events/arch/x86/sandybridge/snb-metrics.json b/tools/perf/pmu-events/arch/x86/sandybridge/snb-metrics.json
new file mode 100644
index 000000000000..fd7d7c438226
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/sandybridge/snb-metrics.json
@@ -0,0 +1,140 @@
1[
2 {
3 "BriefDescription": "Instructions Per Cycle (per logical thread)",
4 "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
5 "MetricGroup": "TopDownL1",
6 "MetricName": "IPC"
7 },
8 {
9 "BriefDescription": "Uops Per Instruction",
10 "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY",
11 "MetricGroup": "Pipeline",
12 "MetricName": "UPI"
13 },
14 {
15 "BriefDescription": "Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions",
16 "MetricExpr": "min( 1 , UOPS_ISSUED.ANY / ( (UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY) * 32 * ( ICACHE.HIT + ICACHE.MISSES ) / 4) )",
17 "MetricGroup": "Frontend",
18 "MetricName": "IFetch_Line_Utilization"
19 },
20 {
21 "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)",
22 "MetricExpr": "IDQ.DSB_UOPS / ( IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS )",
23 "MetricGroup": "DSB; Frontend_Bandwidth",
24 "MetricName": "DSB_Coverage"
25 },
26 {
27 "BriefDescription": "Cycles Per Instruction (threaded)",
28 "MetricExpr": "1 / (INST_RETIRED.ANY / cycles)",
29 "MetricGroup": "Pipeline;Summary",
30 "MetricName": "CPI"
31 },
32 {
33 "BriefDescription": "Per-thread actual clocks when the logical processor is active. This is called 'Clockticks' in VTune.",
34 "MetricExpr": "CPU_CLK_UNHALTED.THREAD",
35 "MetricGroup": "Summary",
36 "MetricName": "CLKS"
37 },
38 {
39 "BriefDescription": "Total issue-pipeline slots",
40 "MetricExpr": "4*(( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
41 "MetricGroup": "TopDownL1",
42 "MetricName": "SLOTS"
43 },
44 {
45 "BriefDescription": "Total number of retired Instructions",
46 "MetricExpr": "INST_RETIRED.ANY",
47 "MetricGroup": "Summary",
48 "MetricName": "Instructions"
49 },
50 {
51 "BriefDescription": "Instructions Per Cycle (per physical core)",
52 "MetricExpr": "INST_RETIRED.ANY / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
53 "MetricGroup": "SMT",
54 "MetricName": "CoreIPC"
55 },
56 {
57 "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
58 "MetricExpr": "UOPS_DISPATCHED.THREAD / (( cpu@UOPS_DISPATCHED.CORE\\,cmask\\=1@ / 2) if #SMT_on else cpu@UOPS_DISPATCHED.CORE\\,cmask\\=1@)",
59 "MetricGroup": "Pipeline;Ports_Utilization",
60 "MetricName": "ILP"
61 },
62 {
63 "BriefDescription": "Core actual clocks when any thread is active on the physical core",
64 "MetricExpr": "( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else CPU_CLK_UNHALTED.THREAD",
65 "MetricGroup": "SMT",
66 "MetricName": "CORE_CLKS"
67 },
68 {
69 "BriefDescription": "Average CPU Utilization",
70 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
71 "MetricGroup": "Summary",
72 "MetricName": "CPU_Utilization"
73 },
74 {
75 "BriefDescription": "Giga Floating Point Operations Per Second",
76 "MetricExpr": "(( 1*( FP_COMP_OPS_EXE.SSE_SCALAR_SINGLE + FP_COMP_OPS_EXE.SSE_SCALAR_DOUBLE ) + 2* FP_COMP_OPS_EXE.SSE_PACKED_DOUBLE + 4*( FP_COMP_OPS_EXE.SSE_PACKED_SINGLE + SIMD_FP_256.PACKED_DOUBLE ) + 8* SIMD_FP_256.PACKED_SINGLE )) / 1000000000 / duration_time",
77 "MetricGroup": "FLOPS;Summary",
78 "MetricName": "GFLOPs"
79 },
80 {
81 "BriefDescription": "Average Frequency Utilization relative nominal frequency",
82 "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC",
83 "MetricGroup": "Power",
84 "MetricName": "Turbo_Utilization"
85 },
86 {
87 "BriefDescription": "Fraction of cycles where both hardware threads were active",
88 "MetricExpr": "1 - CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
89 "MetricGroup": "SMT;Summary",
90 "MetricName": "SMT_2T_Utilization"
91 },
92 {
93 "BriefDescription": "Fraction of cycles spent in Kernel mode",
94 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
95 "MetricGroup": "Summary",
96 "MetricName": "Kernel_Utilization"
97 },
98 {
99 "BriefDescription": "C3 residency percent per core",
100 "MetricExpr": "(cstate_core@c3\\-residency@ / msr@tsc@) * 100",
101 "MetricGroup": "Power",
102 "MetricName": "C3_Core_Residency"
103 },
104 {
105 "BriefDescription": "C6 residency percent per core",
106 "MetricExpr": "(cstate_core@c6\\-residency@ / msr@tsc@) * 100",
107 "MetricGroup": "Power",
108 "MetricName": "C6_Core_Residency"
109 },
110 {
111 "BriefDescription": "C7 residency percent per core",
112 "MetricExpr": "(cstate_core@c7\\-residency@ / msr@tsc@) * 100",
113 "MetricGroup": "Power",
114 "MetricName": "C7_Core_Residency"
115 },
116 {
117 "BriefDescription": "C2 residency percent per package",
118 "MetricExpr": "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100",
119 "MetricGroup": "Power",
120 "MetricName": "C2_Pkg_Residency"
121 },
122 {
123 "BriefDescription": "C3 residency percent per package",
124 "MetricExpr": "(cstate_pkg@c3\\-residency@ / msr@tsc@) * 100",
125 "MetricGroup": "Power",
126 "MetricName": "C3_Pkg_Residency"
127 },
128 {
129 "BriefDescription": "C6 residency percent per package",
130 "MetricExpr": "(cstate_pkg@c6\\-residency@ / msr@tsc@) * 100",
131 "MetricGroup": "Power",
132 "MetricName": "C6_Pkg_Residency"
133 },
134 {
135 "BriefDescription": "C7 residency percent per package",
136 "MetricExpr": "(cstate_pkg@c7\\-residency@ / msr@tsc@) * 100",
137 "MetricGroup": "Power",
138 "MetricName": "C7_Pkg_Residency"
139 }
140]
diff --git a/tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json b/tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json
new file mode 100644
index 000000000000..36c903faed0b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json
@@ -0,0 +1,164 @@
1[
2 {
3 "BriefDescription": "Instructions Per Cycle (per logical thread)",
4 "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
5 "MetricGroup": "TopDownL1",
6 "MetricName": "IPC"
7 },
8 {
9 "BriefDescription": "Uops Per Instruction",
10 "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY",
11 "MetricGroup": "Pipeline",
12 "MetricName": "UPI"
13 },
14 {
15 "BriefDescription": "Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions",
16 "MetricExpr": "min( 1 , UOPS_ISSUED.ANY / ((UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY) * 64 * ( ICACHE_64B.IFTAG_HIT + ICACHE_64B.IFTAG_MISS ) / 4.1) )",
17 "MetricGroup": "Frontend",
18 "MetricName": "IFetch_Line_Utilization"
19 },
20 {
21 "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)",
22 "MetricExpr": "IDQ.DSB_UOPS / ( IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS )",
23 "MetricGroup": "DSB; Frontend_Bandwidth",
24 "MetricName": "DSB_Coverage"
25 },
26 {
27 "BriefDescription": "Cycles Per Instruction (threaded)",
28 "MetricExpr": "1 / (INST_RETIRED.ANY / cycles)",
29 "MetricGroup": "Pipeline;Summary",
30 "MetricName": "CPI"
31 },
32 {
33 "BriefDescription": "Per-thread actual clocks when the logical processor is active. This is called 'Clockticks' in VTune.",
34 "MetricExpr": "CPU_CLK_UNHALTED.THREAD",
35 "MetricGroup": "Summary",
36 "MetricName": "CLKS"
37 },
38 {
39 "BriefDescription": "Total issue-pipeline slots",
40 "MetricExpr": "4*(( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
41 "MetricGroup": "TopDownL1",
42 "MetricName": "SLOTS"
43 },
44 {
45 "BriefDescription": "Total number of retired Instructions",
46 "MetricExpr": "INST_RETIRED.ANY",
47 "MetricGroup": "Summary",
48 "MetricName": "Instructions"
49 },
50 {
51 "BriefDescription": "Instructions Per Cycle (per physical core)",
52 "MetricExpr": "INST_RETIRED.ANY / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
53 "MetricGroup": "SMT",
54 "MetricName": "CoreIPC"
55 },
56 {
57 "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
58 "MetricExpr": "UOPS_EXECUTED.THREAD / (( UOPS_EXECUTED.CORE_CYCLES_GE_1 / 2) if #SMT_on else UOPS_EXECUTED.CORE_CYCLES_GE_1)",
59 "MetricGroup": "Pipeline;Ports_Utilization",
60 "MetricName": "ILP"
61 },
62 {
63 "BriefDescription": "Average Branch Address Clear Cost (fraction of cycles)",
64 "MetricExpr": "2* (( RS_EVENTS.EMPTY_CYCLES - ICACHE_16B.IFDATA_STALL - ICACHE_64B.IFTAG_STALL ) / RS_EVENTS.EMPTY_END)",
65 "MetricGroup": "Unknown_Branches",
66 "MetricName": "BAClear_Cost"
67 },
68 {
69 "BriefDescription": "Core actual clocks when any thread is active on the physical core",
70 "MetricExpr": "( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else CPU_CLK_UNHALTED.THREAD",
71 "MetricGroup": "SMT",
72 "MetricName": "CORE_CLKS"
73 },
74 {
75 "BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads",
76 "MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_RETIRED.L1_MISS_PS + MEM_LOAD_RETIRED.FB_HIT_PS )",
77 "MetricGroup": "Memory_Bound;Memory_Lat",
78 "MetricName": "Load_Miss_Real_Latency"
79 },
80 {
81 "BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least 1 such miss)",
82 "MetricExpr": "L1D_PEND_MISS.PENDING / (( L1D_PEND_MISS.PENDING_CYCLES_ANY / 2) if #SMT_on else L1D_PEND_MISS.PENDING_CYCLES)",
83 "MetricGroup": "Memory_Bound;Memory_BW",
84 "MetricName": "MLP"
85 },
86 {
87 "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
88 "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles) )",
89 "MetricGroup": "TLB",
90 "MetricName": "Page_Walks_Utilization"
91 },
92 {
93 "BriefDescription": "Average CPU Utilization",
94 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
95 "MetricGroup": "Summary",
96 "MetricName": "CPU_Utilization"
97 },
98 {
99 "BriefDescription": "Giga Floating Point Operations Per Second",
100 "MetricExpr": "(( 1*( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2* FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4*( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8* FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE )) / 1000000000 / duration_time",
101 "MetricGroup": "FLOPS;Summary",
102 "MetricName": "GFLOPs"
103 },
104 {
105 "BriefDescription": "Average Frequency Utilization relative nominal frequency",
106 "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC",
107 "MetricGroup": "Power",
108 "MetricName": "Turbo_Utilization"
109 },
110 {
111 "BriefDescription": "Fraction of cycles where both hardware threads were active",
112 "MetricExpr": "1 - CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
113 "MetricGroup": "SMT;Summary",
114 "MetricName": "SMT_2T_Utilization"
115 },
116 {
117 "BriefDescription": "Fraction of cycles spent in Kernel mode",
118 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
119 "MetricGroup": "Summary",
120 "MetricName": "Kernel_Utilization"
121 },
122 {
123 "BriefDescription": "C3 residency percent per core",
124 "MetricExpr": "(cstate_core@c3\\-residency@ / msr@tsc@) * 100",
125 "MetricGroup": "Power",
126 "MetricName": "C3_Core_Residency"
127 },
128 {
129 "BriefDescription": "C6 residency percent per core",
130 "MetricExpr": "(cstate_core@c6\\-residency@ / msr@tsc@) * 100",
131 "MetricGroup": "Power",
132 "MetricName": "C6_Core_Residency"
133 },
134 {
135 "BriefDescription": "C7 residency percent per core",
136 "MetricExpr": "(cstate_core@c7\\-residency@ / msr@tsc@) * 100",
137 "MetricGroup": "Power",
138 "MetricName": "C7_Core_Residency"
139 },
140 {
141 "BriefDescription": "C2 residency percent per package",
142 "MetricExpr": "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100",
143 "MetricGroup": "Power",
144 "MetricName": "C2_Pkg_Residency"
145 },
146 {
147 "BriefDescription": "C3 residency percent per package",
148 "MetricExpr": "(cstate_pkg@c3\\-residency@ / msr@tsc@) * 100",
149 "MetricGroup": "Power",
150 "MetricName": "C3_Pkg_Residency"
151 },
152 {
153 "BriefDescription": "C6 residency percent per package",
154 "MetricExpr": "(cstate_pkg@c6\\-residency@ / msr@tsc@) * 100",
155 "MetricGroup": "Power",
156 "MetricName": "C6_Pkg_Residency"
157 },
158 {
159 "BriefDescription": "C7 residency percent per package",
160 "MetricExpr": "(cstate_pkg@c7\\-residency@ / msr@tsc@) * 100",
161 "MetricGroup": "Power",
162 "MetricName": "C7_Pkg_Residency"
163 }
164]
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/cache.json b/tools/perf/pmu-events/arch/x86/skylakex/cache.json
new file mode 100644
index 000000000000..b5bc742b6fbc
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylakex/cache.json
@@ -0,0 +1,1672 @@
1[
2 {
3 "EventCode": "0x24",
4 "UMask": "0x21",
5 "BriefDescription": "Demand Data Read miss L2, no rejects",
6 "Counter": "0,1,2,3",
7 "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
8 "PublicDescription": "Counts the number of demand Data Read requests that miss L2 cache. Only not rejected loads are counted.",
9 "SampleAfterValue": "200003",
10 "CounterHTOff": "0,1,2,3,4,5,6,7"
11 },
12 {
13 "EventCode": "0x24",
14 "UMask": "0x22",
15 "BriefDescription": "RFO requests that miss L2 cache",
16 "Counter": "0,1,2,3",
17 "EventName": "L2_RQSTS.RFO_MISS",
18 "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that miss L2 cache.",
19 "SampleAfterValue": "200003",
20 "CounterHTOff": "0,1,2,3,4,5,6,7"
21 },
22 {
23 "EventCode": "0x24",
24 "UMask": "0x24",
25 "BriefDescription": "L2 cache misses when fetching instructions",
26 "Counter": "0,1,2,3",
27 "EventName": "L2_RQSTS.CODE_RD_MISS",
28 "PublicDescription": "Counts L2 cache misses when fetching instructions.",
29 "SampleAfterValue": "200003",
30 "CounterHTOff": "0,1,2,3,4,5,6,7"
31 },
32 {
33 "EventCode": "0x24",
34 "UMask": "0x27",
35 "BriefDescription": "Demand requests that miss L2 cache",
36 "Counter": "0,1,2,3",
37 "EventName": "L2_RQSTS.ALL_DEMAND_MISS",
38 "PublicDescription": "Demand requests that miss L2 cache.",
39 "SampleAfterValue": "200003",
40 "CounterHTOff": "0,1,2,3,4,5,6,7"
41 },
42 {
43 "EventCode": "0x24",
44 "UMask": "0x38",
45 "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that miss L2 cache",
46 "Counter": "0,1,2,3",
47 "EventName": "L2_RQSTS.PF_MISS",
48 "PublicDescription": "Counts requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that miss L2 cache.",
49 "SampleAfterValue": "200003",
50 "CounterHTOff": "0,1,2,3,4,5,6,7"
51 },
52 {
53 "EventCode": "0x24",
54 "UMask": "0x3f",
55 "BriefDescription": "All requests that miss L2 cache",
56 "Counter": "0,1,2,3",
57 "EventName": "L2_RQSTS.MISS",
58 "PublicDescription": "All requests that miss L2 cache.",
59 "SampleAfterValue": "200003",
60 "CounterHTOff": "0,1,2,3,4,5,6,7"
61 },
62 {
63 "EventCode": "0x24",
64 "UMask": "0x41",
65 "BriefDescription": "Demand Data Read requests that hit L2 cache",
66 "Counter": "0,1,2,3",
67 "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
68 "PublicDescription": "Counts the number of demand Data Read requests that hit L2 cache. Only non rejected loads are counted.",
69 "SampleAfterValue": "200003",
70 "CounterHTOff": "0,1,2,3,4,5,6,7"
71 },
72 {
73 "EventCode": "0x24",
74 "UMask": "0x42",
75 "BriefDescription": "RFO requests that hit L2 cache",
76 "Counter": "0,1,2,3",
77 "EventName": "L2_RQSTS.RFO_HIT",
78 "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that hit L2 cache.",
79 "SampleAfterValue": "200003",
80 "CounterHTOff": "0,1,2,3,4,5,6,7"
81 },
82 {
83 "EventCode": "0x24",
84 "UMask": "0x44",
85 "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
86 "Counter": "0,1,2,3",
87 "EventName": "L2_RQSTS.CODE_RD_HIT",
88 "PublicDescription": "Counts L2 cache hits when fetching instructions, code reads.",
89 "SampleAfterValue": "200003",
90 "CounterHTOff": "0,1,2,3,4,5,6,7"
91 },
92 {
93 "EventCode": "0x24",
94 "UMask": "0xd8",
95 "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that hit L2 cache",
96 "Counter": "0,1,2,3",
97 "EventName": "L2_RQSTS.PF_HIT",
98 "PublicDescription": "Counts requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that hit L2 cache.",
99 "SampleAfterValue": "200003",
100 "CounterHTOff": "0,1,2,3,4,5,6,7"
101 },
102 {
103 "EventCode": "0x24",
104 "UMask": "0xe1",
105 "BriefDescription": "Demand Data Read requests",
106 "Counter": "0,1,2,3",
107 "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
108 "PublicDescription": "Counts the number of demand Data Read requests (including requests from L1D hardware prefetchers). These loads may hit or miss L2 cache. Only non rejected loads are counted.",
109 "SampleAfterValue": "200003",
110 "CounterHTOff": "0,1,2,3,4,5,6,7"
111 },
112 {
113 "EventCode": "0x24",
114 "UMask": "0xe2",
115 "BriefDescription": "RFO requests to L2 cache",
116 "Counter": "0,1,2,3",
117 "EventName": "L2_RQSTS.ALL_RFO",
118 "PublicDescription": "Counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.",
119 "SampleAfterValue": "200003",
120 "CounterHTOff": "0,1,2,3,4,5,6,7"
121 },
122 {
123 "EventCode": "0x24",
124 "UMask": "0xe4",
125 "BriefDescription": "L2 code requests",
126 "Counter": "0,1,2,3",
127 "EventName": "L2_RQSTS.ALL_CODE_RD",
128 "PublicDescription": "Counts the total number of L2 code requests.",
129 "SampleAfterValue": "200003",
130 "CounterHTOff": "0,1,2,3,4,5,6,7"
131 },
132 {
133 "EventCode": "0x24",
134 "UMask": "0xe7",
135 "BriefDescription": "Demand requests to L2 cache",
136 "Counter": "0,1,2,3",
137 "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES",
138 "PublicDescription": "Demand requests to L2 cache.",
139 "SampleAfterValue": "200003",
140 "CounterHTOff": "0,1,2,3,4,5,6,7"
141 },
142 {
143 "EventCode": "0x24",
144 "UMask": "0xf8",
145 "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches",
146 "Counter": "0,1,2,3",
147 "EventName": "L2_RQSTS.ALL_PF",
148 "PublicDescription": "Counts the total number of requests from the L2 hardware prefetchers.",
149 "SampleAfterValue": "200003",
150 "CounterHTOff": "0,1,2,3,4,5,6,7"
151 },
152 {
153 "EventCode": "0x24",
154 "UMask": "0xff",
155 "BriefDescription": "All L2 requests",
156 "Counter": "0,1,2,3",
157 "EventName": "L2_RQSTS.REFERENCES",
158 "PublicDescription": "All L2 requests.",
159 "SampleAfterValue": "200003",
160 "CounterHTOff": "0,1,2,3,4,5,6,7"
161 },
162 {
163 "EventCode": "0x2E",
164 "UMask": "0x41",
165 "BriefDescription": "Core-originated cacheable demand requests missed L3",
166 "Counter": "0,1,2,3",
167 "EventName": "LONGEST_LAT_CACHE.MISS",
168 "PublicDescription": "Counts core-originated cacheable requests that miss the L3 cache (Longest Latency cache). Requests include data and code reads, Reads-for-Ownership (RFOs), speculative accesses and hardware prefetches from L1 and L2. It does not include all misses to the L3.",
169 "SampleAfterValue": "100003",
170 "CounterHTOff": "0,1,2,3,4,5,6,7"
171 },
172 {
173 "EventCode": "0x2E",
174 "UMask": "0x4f",
175 "BriefDescription": "Core-originated cacheable demand requests that refer to L3",
176 "Counter": "0,1,2,3",
177 "EventName": "LONGEST_LAT_CACHE.REFERENCE",
178 "PublicDescription": "Counts core-originated cacheable requests to the L3 cache (Longest Latency cache). Requests include data and code reads, Reads-for-Ownership (RFOs), speculative accesses and hardware prefetches from L1 and L2. It does not include all accesses to the L3.",
179 "SampleAfterValue": "100003",
180 "CounterHTOff": "0,1,2,3,4,5,6,7"
181 },
182 {
183 "EventCode": "0x48",
184 "UMask": "0x1",
185 "BriefDescription": "L1D miss outstandings duration in cycles",
186 "Counter": "0,1,2,3",
187 "EventName": "L1D_PEND_MISS.PENDING",
188 "PublicDescription": "Counts duration of L1D miss outstanding, that is each cycle number of Fill Buffers (FB) outstanding required by Demand Reads. FB either is held by demand loads, or it is held by non-demand loads and gets hit at least once by demand. The valid outstanding interval is defined until the FB deallocation by one of the following ways: from FB allocation, if FB is allocated by demand from the demand Hit FB, if it is allocated by hardware or software prefetch.Note: In the L1D, a Demand Read contains cacheable or noncacheable demand loads, including ones causing cache-line splits and reads due to page walks resulted from any request type.",
189 "SampleAfterValue": "2000003",
190 "CounterHTOff": "0,1,2,3,4,5,6,7"
191 },
192 {
193 "EventCode": "0x48",
194 "UMask": "0x1",
195 "BriefDescription": "Cycles with L1D load Misses outstanding.",
196 "Counter": "0,1,2,3",
197 "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
198 "CounterMask": "1",
199 "PublicDescription": "Counts duration of L1D miss outstanding in cycles.",
200 "SampleAfterValue": "2000003",
201 "CounterHTOff": "0,1,2,3,4,5,6,7"
202 },
203 {
204 "EventCode": "0x48",
205 "UMask": "0x1",
206 "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
207 "Counter": "0,1,2,3",
208 "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
209 "AnyThread": "1",
210 "CounterMask": "1",
211 "SampleAfterValue": "2000003",
212 "CounterHTOff": "0,1,2,3,4,5,6,7"
213 },
214 {
215 "EventCode": "0x48",
216 "UMask": "0x2",
217 "BriefDescription": "Number of times a request needed a FB entry but there was no entry available for it. That is the FB unavailability was dominant reason for blocking the request. A request includes cacheable/uncacheable demands that is load, store or SW prefetch.",
218 "Counter": "0,1,2,3",
219 "EventName": "L1D_PEND_MISS.FB_FULL",
220 "PublicDescription": "Number of times a request needed a FB (Fill Buffer) entry but there was no entry available for it. A request includes cacheable/uncacheable demands that are load, store or SW prefetch instructions.",
221 "SampleAfterValue": "2000003",
222 "CounterHTOff": "0,1,2,3,4,5,6,7"
223 },
224 {
225 "EventCode": "0x51",
226 "UMask": "0x1",
227 "BriefDescription": "L1D data line replacements",
228 "Counter": "0,1,2,3",
229 "EventName": "L1D.REPLACEMENT",
230 "PublicDescription": "Counts L1D data line replacements including opportunistic replacements, and replacements that require stall-for-replace or block-for-replace.",
231 "SampleAfterValue": "2000003",
232 "CounterHTOff": "0,1,2,3,4,5,6,7"
233 },
234 {
235 "EventCode": "0x60",
236 "UMask": "0x1",
237 "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
238 "Counter": "0,1,2,3",
239 "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
240 "PublicDescription": "Counts the number of offcore outstanding Demand Data Read transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor. See the corresponding Umask under OFFCORE_REQUESTS.Note: A prefetch promoted to Demand is counted from the promotion point.",
241 "SampleAfterValue": "2000003",
242 "CounterHTOff": "0,1,2,3,4,5,6,7"
243 },
244 {
245 "EventCode": "0x60",
246 "UMask": "0x1",
247 "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore",
248 "Counter": "0,1,2,3",
249 "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
250 "CounterMask": "1",
251 "PublicDescription": "Counts cycles when offcore outstanding Demand Data Read transactions are present in the super queue (SQ). A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation).",
252 "SampleAfterValue": "2000003",
253 "CounterHTOff": "0,1,2,3,4,5,6,7"
254 },
255 {
256 "EventCode": "0x60",
257 "UMask": "0x1",
258 "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
259 "Counter": "0,1,2,3",
260 "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
261 "CounterMask": "6",
262 "SampleAfterValue": "2000003",
263 "CounterHTOff": "0,1,2,3,4,5,6,7"
264 },
265 {
266 "EventCode": "0x60",
267 "UMask": "0x2",
268 "BriefDescription": "Offcore outstanding Code Reads transactions in the SuperQueue (SQ), queue to uncore, every cycle. ",
269 "Counter": "0,1,2,3",
270 "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD",
271 "PublicDescription": "Counts the number of offcore outstanding Code Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
272 "SampleAfterValue": "2000003",
273 "CounterHTOff": "0,1,2,3,4,5,6,7"
274 },
275 {
276 "EventCode": "0x60",
277 "UMask": "0x2",
278 "BriefDescription": "Cycles with offcore outstanding Code Reads transactions in the SuperQueue (SQ), queue to uncore.",
279 "Counter": "0,1,2,3",
280 "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_CODE_RD",
281 "CounterMask": "1",
282 "PublicDescription": "Counts the number of offcore outstanding Code Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
283 "SampleAfterValue": "2000003",
284 "CounterHTOff": "0,1,2,3,4,5,6,7"
285 },
286 {
287 "EventCode": "0x60",
288 "UMask": "0x4",
289 "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
290 "Counter": "0,1,2,3",
291 "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
292 "PublicDescription": "Counts the number of offcore outstanding RFO (store) transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
293 "SampleAfterValue": "2000003",
294 "CounterHTOff": "0,1,2,3,4,5,6,7"
295 },
296 {
297 "EventCode": "0x60",
298 "UMask": "0x4",
299 "BriefDescription": "Cycles with offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore.",
300 "Counter": "0,1,2,3",
301 "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
302 "CounterMask": "1",
303 "PublicDescription": "Counts the number of offcore outstanding demand rfo Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
304 "SampleAfterValue": "2000003",
305 "CounterHTOff": "0,1,2,3,4,5,6,7"
306 },
307 {
308 "EventCode": "0x60",
309 "UMask": "0x8",
310 "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
311 "Counter": "0,1,2,3",
312 "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
313 "PublicDescription": "Counts the number of offcore outstanding cacheable Core Data Read transactions in the super queue every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
314 "SampleAfterValue": "2000003",
315 "CounterHTOff": "0,1,2,3,4,5,6,7"
316 },
317 {
318 "EventCode": "0x60",
319 "UMask": "0x8",
320 "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
321 "Counter": "0,1,2,3",
322 "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
323 "CounterMask": "1",
324 "PublicDescription": "Counts cycles when offcore outstanding cacheable Core Data Read transactions are present in the super queue. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
325 "SampleAfterValue": "2000003",
326 "CounterHTOff": "0,1,2,3,4,5,6,7"
327 },
328 {
329 "EventCode": "0xB0",
330 "UMask": "0x1",
331 "BriefDescription": "Demand Data Read requests sent to uncore",
332 "Counter": "0,1,2,3",
333 "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
334 "PublicDescription": "Counts the Demand Data Read requests sent to uncore. Use it in conjunction with OFFCORE_REQUESTS_OUTSTANDING to determine average latency in the uncore.",
335 "SampleAfterValue": "100003",
336 "CounterHTOff": "0,1,2,3,4,5,6,7"
337 },
338 {
339 "EventCode": "0xB0",
340 "UMask": "0x2",
341 "BriefDescription": "Cacheable and noncachaeble code read requests",
342 "Counter": "0,1,2,3",
343 "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
344 "PublicDescription": "Counts both cacheable and non-cacheable code read requests.",
345 "SampleAfterValue": "100003",
346 "CounterHTOff": "0,1,2,3,4,5,6,7"
347 },
348 {
349 "EventCode": "0xB0",
350 "UMask": "0x4",
351 "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
352 "Counter": "0,1,2,3",
353 "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
354 "PublicDescription": "Counts the demand RFO (read for ownership) requests including regular RFOs, locks, ItoM.",
355 "SampleAfterValue": "100003",
356 "CounterHTOff": "0,1,2,3,4,5,6,7"
357 },
358 {
359 "EventCode": "0xB0",
360 "UMask": "0x8",
361 "BriefDescription": "Demand and prefetch data reads",
362 "Counter": "0,1,2,3",
363 "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
364 "PublicDescription": "Counts the demand and prefetch data reads. All Core Data Reads include cacheable 'Demands' and L2 prefetchers (not L3 prefetchers). Counting also covers reads due to page walks resulted from any request type.",
365 "SampleAfterValue": "100003",
366 "CounterHTOff": "0,1,2,3,4,5,6,7"
367 },
368 {
369 "EventCode": "0xB0",
370 "UMask": "0x80",
371 "BriefDescription": "Any memory transaction that reached the SQ.",
372 "Counter": "0,1,2,3",
373 "EventName": "OFFCORE_REQUESTS.ALL_REQUESTS",
374 "PublicDescription": "Counts memory transactions reached the super queue including requests initiated by the core, all L3 prefetches, page walks, etc..",
375 "SampleAfterValue": "100003",
376 "CounterHTOff": "0,1,2,3,4,5,6,7"
377 },
378 {
379 "EventCode": "0xB2",
380 "UMask": "0x1",
381 "BriefDescription": "Offcore requests buffer cannot take more entries for this thread core.",
382 "Counter": "0,1,2,3",
383 "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
384 "PublicDescription": "Counts the number of cases when the offcore requests buffer cannot take more entries for the core. This can happen when the superqueue does not contain eligible entries, or when L1D writeback pending FIFO requests is full.Note: Writeback pending FIFO has six entries.",
385 "SampleAfterValue": "2000003",
386 "CounterHTOff": "0,1,2,3,4,5,6,7"
387 },
388 {
389 "EventCode": "0xB7, 0xBB",
390 "UMask": "0x1",
391 "BriefDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction",
392 "Counter": "0,1,2,3",
393 "EventName": "OFFCORE_RESPONSE",
394 "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
395 "SampleAfterValue": "100003",
396 "CounterHTOff": "0,1,2,3"
397 },
398 {
399 "EventCode": "0xD0",
400 "UMask": "0x11",
401 "BriefDescription": "Retired load instructions that miss the STLB.",
402 "Data_LA": "1",
403 "PEBS": "1",
404 "Counter": "0,1,2,3",
405 "EventName": "MEM_INST_RETIRED.STLB_MISS_LOADS",
406 "SampleAfterValue": "100003",
407 "CounterHTOff": "0,1,2,3"
408 },
409 {
410 "EventCode": "0xD0",
411 "UMask": "0x12",
412 "BriefDescription": "Retired store instructions that miss the STLB.",
413 "Data_LA": "1",
414 "PEBS": "1",
415 "Counter": "0,1,2,3",
416 "EventName": "MEM_INST_RETIRED.STLB_MISS_STORES",
417 "SampleAfterValue": "100003",
418 "L1_Hit_Indication": "1",
419 "CounterHTOff": "0,1,2,3"
420 },
421 {
422 "EventCode": "0xD0",
423 "UMask": "0x21",
424 "BriefDescription": "Retired load instructions with locked access.",
425 "Data_LA": "1",
426 "PEBS": "1",
427 "Counter": "0,1,2,3",
428 "EventName": "MEM_INST_RETIRED.LOCK_LOADS",
429 "SampleAfterValue": "100007",
430 "CounterHTOff": "0,1,2,3"
431 },
432 {
433 "EventCode": "0xD0",
434 "UMask": "0x41",
435 "BriefDescription": "Retired load instructions that split across a cacheline boundary.",
436 "Data_LA": "1",
437 "PEBS": "1",
438 "Counter": "0,1,2,3",
439 "EventName": "MEM_INST_RETIRED.SPLIT_LOADS",
440 "PublicDescription": "Counts retired load instructions that split across a cacheline boundary.",
441 "SampleAfterValue": "100003",
442 "CounterHTOff": "0,1,2,3"
443 },
444 {
445 "EventCode": "0xD0",
446 "UMask": "0x42",
447 "BriefDescription": "Retired store instructions that split across a cacheline boundary.",
448 "Data_LA": "1",
449 "PEBS": "1",
450 "Counter": "0,1,2,3",
451 "EventName": "MEM_INST_RETIRED.SPLIT_STORES",
452 "PublicDescription": "Counts retired store instructions that split across a cacheline boundary.",
453 "SampleAfterValue": "100003",
454 "L1_Hit_Indication": "1",
455 "CounterHTOff": "0,1,2,3"
456 },
457 {
458 "EventCode": "0xD0",
459 "UMask": "0x81",
460 "BriefDescription": "All retired load instructions.",
461 "Data_LA": "1",
462 "PEBS": "1",
463 "Counter": "0,1,2,3",
464 "EventName": "MEM_INST_RETIRED.ALL_LOADS",
465 "SampleAfterValue": "2000003",
466 "CounterHTOff": "0,1,2,3"
467 },
468 {
469 "EventCode": "0xD0",
470 "UMask": "0x82",
471 "BriefDescription": "All retired store instructions.",
472 "Data_LA": "1",
473 "PEBS": "1",
474 "Counter": "0,1,2,3",
475 "EventName": "MEM_INST_RETIRED.ALL_STORES",
476 "SampleAfterValue": "2000003",
477 "L1_Hit_Indication": "1",
478 "CounterHTOff": "0,1,2,3"
479 },
480 {
481 "EventCode": "0xD1",
482 "UMask": "0x1",
483 "BriefDescription": "Retired load instructions with L1 cache hits as data sources",
484 "Data_LA": "1",
485 "PEBS": "1",
486 "Counter": "0,1,2,3",
487 "EventName": "MEM_LOAD_RETIRED.L1_HIT",
488 "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L1 data cache. This event includes all SW prefetches and lock instructions regardless of the data source.",
489 "SampleAfterValue": "2000003",
490 "CounterHTOff": "0,1,2,3"
491 },
492 {
493 "EventCode": "0xD1",
494 "UMask": "0x2",
495 "BriefDescription": "Retired load instructions with L2 cache hits as data sources",
496 "Data_LA": "1",
497 "PEBS": "1",
498 "Counter": "0,1,2,3",
499 "EventName": "MEM_LOAD_RETIRED.L2_HIT",
500 "PublicDescription": "Retired load instructions with L2 cache hits as data sources.",
501 "SampleAfterValue": "100003",
502 "CounterHTOff": "0,1,2,3"
503 },
504 {
505 "EventCode": "0xD1",
506 "UMask": "0x4",
507 "BriefDescription": "Retired load instructions with L3 cache hits as data sources",
508 "Data_LA": "1",
509 "PEBS": "1",
510 "Counter": "0,1,2,3",
511 "EventName": "MEM_LOAD_RETIRED.L3_HIT",
512 "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L3 cache. ",
513 "SampleAfterValue": "50021",
514 "CounterHTOff": "0,1,2,3"
515 },
516 {
517 "EventCode": "0xD1",
518 "UMask": "0x8",
519 "BriefDescription": "Retired load instructions missed L1 cache as data sources",
520 "Data_LA": "1",
521 "PEBS": "1",
522 "Counter": "0,1,2,3",
523 "EventName": "MEM_LOAD_RETIRED.L1_MISS",
524 "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L1 cache.",
525 "SampleAfterValue": "100003",
526 "CounterHTOff": "0,1,2,3"
527 },
528 {
529 "EventCode": "0xD1",
530 "UMask": "0x10",
531 "BriefDescription": "Retired load instructions missed L2 cache as data sources",
532 "Data_LA": "1",
533 "PEBS": "1",
534 "Counter": "0,1,2,3",
535 "EventName": "MEM_LOAD_RETIRED.L2_MISS",
536 "PublicDescription": "Retired load instructions missed L2 cache as data sources.",
537 "SampleAfterValue": "50021",
538 "CounterHTOff": "0,1,2,3"
539 },
540 {
541 "EventCode": "0xD1",
542 "UMask": "0x20",
543 "BriefDescription": "Retired load instructions missed L3 cache as data sources",
544 "Data_LA": "1",
545 "PEBS": "1",
546 "Counter": "0,1,2,3",
547 "EventName": "MEM_LOAD_RETIRED.L3_MISS",
548 "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L3 cache. ",
549 "SampleAfterValue": "100007",
550 "CounterHTOff": "0,1,2,3"
551 },
552 {
553 "EventCode": "0xD1",
554 "UMask": "0x40",
555 "BriefDescription": "Retired load instructions which data sources were load missed L1 but hit FB due to preceding miss to the same cache line with data not ready",
556 "Data_LA": "1",
557 "PEBS": "1",
558 "Counter": "0,1,2,3",
559 "EventName": "MEM_LOAD_RETIRED.FB_HIT",
560 "PublicDescription": "Counts retired load instructions with at least one uop was load missed in L1 but hit FB (Fill Buffers) due to preceding miss to the same cache line with data not ready. ",
561 "SampleAfterValue": "100007",
562 "CounterHTOff": "0,1,2,3"
563 },
564 {
565 "EventCode": "0xD2",
566 "UMask": "0x1",
567 "BriefDescription": "Retired load instructions which data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
568 "Data_LA": "1",
569 "PEBS": "1",
570 "Counter": "0,1,2,3",
571 "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS",
572 "SampleAfterValue": "20011",
573 "CounterHTOff": "0,1,2,3"
574 },
575 {
576 "EventCode": "0xD2",
577 "UMask": "0x2",
578 "BriefDescription": "Retired load instructions which data sources were L3 and cross-core snoop hits in on-pkg core cache",
579 "Data_LA": "1",
580 "PEBS": "1",
581 "Counter": "0,1,2,3",
582 "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HIT",
583 "PublicDescription": "Retired load instructions which data sources were L3 and cross-core snoop hits in on-pkg core cache.",
584 "SampleAfterValue": "20011",
585 "CounterHTOff": "0,1,2,3"
586 },
587 {
588 "EventCode": "0xD2",
589 "UMask": "0x4",
590 "BriefDescription": "Retired load instructions which data sources were HitM responses from shared L3",
591 "Data_LA": "1",
592 "PEBS": "1",
593 "Counter": "0,1,2,3",
594 "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HITM",
595 "PublicDescription": "Retired load instructions which data sources were HitM responses from shared L3.",
596 "SampleAfterValue": "20011",
597 "CounterHTOff": "0,1,2,3"
598 },
599 {
600 "EventCode": "0xD2",
601 "UMask": "0x8",
602 "BriefDescription": "Retired load instructions which data sources were hits in L3 without snoops required",
603 "Data_LA": "1",
604 "PEBS": "1",
605 "Counter": "0,1,2,3",
606 "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_NONE",
607 "PublicDescription": "Retired load instructions which data sources were hits in L3 without snoops required.",
608 "SampleAfterValue": "100003",
609 "CounterHTOff": "0,1,2,3"
610 },
611 {
612 "EventCode": "0xD3",
613 "UMask": "0x1",
614 "BriefDescription": "Retired load instructions which data sources missed L3 but serviced from local dram",
615 "Data_LA": "1",
616 "PEBS": "1",
617 "Counter": "0,1,2,3",
618 "EventName": "MEM_LOAD_L3_MISS_RETIRED.LOCAL_DRAM",
619 "PublicDescription": "Retired load instructions which data sources missed L3 but serviced from local DRAM.",
620 "SampleAfterValue": "100007",
621 "CounterHTOff": "0,1,2,3"
622 },
623 {
624 "EventCode": "0xD3",
625 "UMask": "0x2",
626 "BriefDescription": "Retired load instructions which data sources missed L3 but serviced from remote dram",
627 "Data_LA": "1",
628 "PEBS": "1",
629 "Counter": "0,1,2,3",
630 "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_DRAM",
631 "SampleAfterValue": "100007",
632 "CounterHTOff": "0,1,2,3"
633 },
634 {
635 "EventCode": "0xD3",
636 "UMask": "0x4",
637 "BriefDescription": "Retired load instructions whose data sources was remote HITM",
638 "Data_LA": "1",
639 "PEBS": "1",
640 "Counter": "0,1,2,3",
641 "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_HITM",
642 "PublicDescription": "Retired load instructions whose data sources was remote HITM.",
643 "SampleAfterValue": "100007",
644 "CounterHTOff": "0,1,2,3"
645 },
646 {
647 "EventCode": "0xD3",
648 "UMask": "0x8",
649 "BriefDescription": "Retired load instructions whose data sources was forwarded from a remote cache",
650 "Data_LA": "1",
651 "Counter": "0,1,2,3",
652 "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_FWD",
653 "PublicDescription": "Retired load instructions whose data sources was forwarded from a remote cache.",
654 "SampleAfterValue": "100007",
655 "CounterHTOff": "0,1,2,3"
656 },
657 {
658 "EventCode": "0xD4",
659 "UMask": "0x4",
660 "BriefDescription": "Retired instructions with at least 1 uncacheable load or lock.",
661 "Data_LA": "1",
662 "PEBS": "1",
663 "Counter": "0,1,2,3",
664 "EventName": "MEM_LOAD_MISC_RETIRED.UC",
665 "SampleAfterValue": "100007",
666 "CounterHTOff": "0,1,2,3"
667 },
668 {
669 "EventCode": "0xF0",
670 "UMask": "0x40",
671 "BriefDescription": "L2 writebacks that access L2 cache",
672 "Counter": "0,1,2,3",
673 "EventName": "L2_TRANS.L2_WB",
674 "PublicDescription": "Counts L2 writebacks that access L2 cache.",
675 "SampleAfterValue": "200003",
676 "CounterHTOff": "0,1,2,3,4,5,6,7"
677 },
678 {
679 "EventCode": "0xF1",
680 "UMask": "0x1f",
681 "BriefDescription": "L2 cache lines filling L2",
682 "Counter": "0,1,2,3",
683 "EventName": "L2_LINES_IN.ALL",
684 "PublicDescription": "Counts the number of L2 cache lines filling the L2. Counting does not cover rejects.",
685 "SampleAfterValue": "100003",
686 "CounterHTOff": "0,1,2,3,4,5,6,7"
687 },
688 {
689 "EventCode": "0xF2",
690 "UMask": "0x1",
691 "BriefDescription": "Counts the number of lines that are silently dropped by L2 cache when triggered by an L2 cache fill. These lines are typically in Shared state. A non-threaded event.",
692 "Counter": "0,1,2,3",
693 "EventName": "L2_LINES_OUT.SILENT",
694 "SampleAfterValue": "200003",
695 "CounterHTOff": "0,1,2,3,4,5,6,7"
696 },
697 {
698 "EventCode": "0xF2",
699 "UMask": "0x2",
700 "BriefDescription": "Counts the number of lines that are evicted by L2 cache when triggered by an L2 cache fill. Those lines can be either in modified state or clean state. Modified lines may either be written back to L3 or directly written to memory and not allocated in L3. Clean lines may either be allocated in L3 or dropped ",
701 "Counter": "0,1,2,3",
702 "EventName": "L2_LINES_OUT.NON_SILENT",
703 "PublicDescription": "Counts the number of lines that are evicted by L2 cache when triggered by an L2 cache fill. Those lines can be either in modified state or clean state. Modified lines may either be written back to L3 or directly written to memory and not allocated in L3. Clean lines may either be allocated in L3 or dropped.",
704 "SampleAfterValue": "200003",
705 "CounterHTOff": "0,1,2,3,4,5,6,7"
706 },
707 {
708 "EventCode": "0xF2",
709 "UMask": "0x4",
710 "BriefDescription": "Counts the number of lines that have been hardware prefetched but not used and now evicted by L2 cache",
711 "Counter": "0,1,2,3",
712 "EventName": "L2_LINES_OUT.USELESS_PREF",
713 "PublicDescription": "Counts the number of lines that have been hardware prefetched but not used and now evicted by L2 cache.",
714 "SampleAfterValue": "200003",
715 "CounterHTOff": "0,1,2,3,4,5,6,7"
716 },
717 {
718 "EventCode": "0xF2",
719 "UMask": "0x4",
720 "BriefDescription": "Counts the number of lines that have been hardware prefetched but not used and now evicted by L2 cache",
721 "Counter": "0,1,2,3",
722 "EventName": "L2_LINES_OUT.USELESS_HWPF",
723 "SampleAfterValue": "200003",
724 "CounterHTOff": "0,1,2,3,4,5,6,7"
725 },
726 {
727 "EventCode": "0xF4",
728 "UMask": "0x10",
729 "BriefDescription": "Number of cache line split locks sent to uncore.",
730 "Counter": "0,1,2,3",
731 "EventName": "SQ_MISC.SPLIT_LOCK",
732 "PublicDescription": "Counts the number of cache line split locks sent to the uncore.",
733 "SampleAfterValue": "100003",
734 "CounterHTOff": "0,1,2,3,4,5,6,7"
735 },
736 {
737 "Offcore": "1",
738 "EventCode": "0xB7, 0xBB",
739 "UMask": "0x1",
740 "BriefDescription": "Counts demand data reads that have any response type.",
741 "MSRValue": "0x0000010001 ",
742 "Counter": "0,1,2,3",
743 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
744 "MSRIndex": "0x1a6,0x1a7",
745 "PublicDescription": "Counts demand data reads that have any response type.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
746 "SampleAfterValue": "100003",
747 "CounterHTOff": "0,1,2,3"
748 },
749 {
750 "Offcore": "1",
751 "EventCode": "0xB7, 0xBB",
752 "UMask": "0x1",
753 "BriefDescription": "Counts demand data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
754 "MSRValue": "0x01003c0001 ",
755 "Counter": "0,1,2,3",
756 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
757 "MSRIndex": "0x1a6,0x1a7",
758 "PublicDescription": "Counts demand data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
759 "SampleAfterValue": "100003",
760 "CounterHTOff": "0,1,2,3"
761 },
762 {
763 "Offcore": "1",
764 "EventCode": "0xB7, 0xBB",
765 "UMask": "0x1",
766 "BriefDescription": "Counts demand data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
767 "MSRValue": "0x04003c0001 ",
768 "Counter": "0,1,2,3",
769 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
770 "MSRIndex": "0x1a6,0x1a7",
771 "PublicDescription": "Counts demand data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
772 "SampleAfterValue": "100003",
773 "CounterHTOff": "0,1,2,3"
774 },
775 {
776 "Offcore": "1",
777 "EventCode": "0xB7, 0xBB",
778 "UMask": "0x1",
779 "BriefDescription": "DEMAND_DATA_RD & L3_HIT & SNOOP_HIT_WITH_FWD",
780 "MSRValue": "0x08003c0001 ",
781 "Counter": "0,1,2,3",
782 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
783 "MSRIndex": "0x1a6,0x1a7",
784 "PublicDescription": "tbd; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
785 "SampleAfterValue": "100003",
786 "CounterHTOff": "0,1,2,3"
787 },
788 {
789 "Offcore": "1",
790 "EventCode": "0xB7, 0xBB",
791 "UMask": "0x1",
792 "BriefDescription": "Counts demand data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
793 "MSRValue": "0x10003c0001 ",
794 "Counter": "0,1,2,3",
795 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE",
796 "MSRIndex": "0x1a6,0x1a7",
797 "PublicDescription": "Counts demand data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
798 "SampleAfterValue": "100003",
799 "CounterHTOff": "0,1,2,3"
800 },
801 {
802 "Offcore": "1",
803 "EventCode": "0xB7, 0xBB",
804 "UMask": "0x1",
805 "BriefDescription": "Counts demand data reads that hit in the L3.",
806 "MSRValue": "0x3f803c0001 ",
807 "Counter": "0,1,2,3",
808 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP",
809 "MSRIndex": "0x1a6,0x1a7",
810 "PublicDescription": "Counts demand data reads that hit in the L3.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
811 "SampleAfterValue": "100003",
812 "CounterHTOff": "0,1,2,3"
813 },
814 {
815 "Offcore": "1",
816 "EventCode": "0xB7, 0xBB",
817 "UMask": "0x1",
818 "BriefDescription": "Counts all demand data writes (RFOs) that have any response type.",
819 "MSRValue": "0x0000010002 ",
820 "Counter": "0,1,2,3",
821 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE",
822 "MSRIndex": "0x1a6,0x1a7",
823 "PublicDescription": "Counts all demand data writes (RFOs) that have any response type.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
824 "SampleAfterValue": "100003",
825 "CounterHTOff": "0,1,2,3"
826 },
827 {
828 "Offcore": "1",
829 "EventCode": "0xB7, 0xBB",
830 "UMask": "0x1",
831 "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
832 "MSRValue": "0x01003c0002 ",
833 "Counter": "0,1,2,3",
834 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.NO_SNOOP_NEEDED",
835 "MSRIndex": "0x1a6,0x1a7",
836 "PublicDescription": "Counts all demand data writes (RFOs) that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
837 "SampleAfterValue": "100003",
838 "CounterHTOff": "0,1,2,3"
839 },
840 {
841 "Offcore": "1",
842 "EventCode": "0xB7, 0xBB",
843 "UMask": "0x1",
844 "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
845 "MSRValue": "0x04003c0002 ",
846 "Counter": "0,1,2,3",
847 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
848 "MSRIndex": "0x1a6,0x1a7",
849 "PublicDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
850 "SampleAfterValue": "100003",
851 "CounterHTOff": "0,1,2,3"
852 },
853 {
854 "Offcore": "1",
855 "EventCode": "0xB7, 0xBB",
856 "UMask": "0x1",
857 "BriefDescription": "DEMAND_RFO & L3_HIT & SNOOP_HIT_WITH_FWD",
858 "MSRValue": "0x08003c0002 ",
859 "Counter": "0,1,2,3",
860 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
861 "MSRIndex": "0x1a6,0x1a7",
862 "PublicDescription": "tbd; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
863 "SampleAfterValue": "100003",
864 "CounterHTOff": "0,1,2,3"
865 },
866 {
867 "Offcore": "1",
868 "EventCode": "0xB7, 0xBB",
869 "UMask": "0x1",
870 "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
871 "MSRValue": "0x10003c0002 ",
872 "Counter": "0,1,2,3",
873 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE",
874 "MSRIndex": "0x1a6,0x1a7",
875 "PublicDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
876 "SampleAfterValue": "100003",
877 "CounterHTOff": "0,1,2,3"
878 },
879 {
880 "Offcore": "1",
881 "EventCode": "0xB7, 0xBB",
882 "UMask": "0x1",
883 "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3.",
884 "MSRValue": "0x3f803c0002 ",
885 "Counter": "0,1,2,3",
886 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.ANY_SNOOP",
887 "MSRIndex": "0x1a6,0x1a7",
888 "PublicDescription": "Counts all demand data writes (RFOs) that hit in the L3.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
889 "SampleAfterValue": "100003",
890 "CounterHTOff": "0,1,2,3"
891 },
892 {
893 "Offcore": "1",
894 "EventCode": "0xB7, 0xBB",
895 "UMask": "0x1",
896 "BriefDescription": "Counts all demand code reads that have any response type.",
897 "MSRValue": "0x0000010004 ",
898 "Counter": "0,1,2,3",
899 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
900 "MSRIndex": "0x1a6,0x1a7",
901 "PublicDescription": "Counts all demand code reads that have any response type.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
902 "SampleAfterValue": "100003",
903 "CounterHTOff": "0,1,2,3"
904 },
905 {
906 "Offcore": "1",
907 "EventCode": "0xB7, 0xBB",
908 "UMask": "0x1",
909 "BriefDescription": "Counts all demand code reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
910 "MSRValue": "0x01003c0004 ",
911 "Counter": "0,1,2,3",
912 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED",
913 "MSRIndex": "0x1a6,0x1a7",
914 "PublicDescription": "Counts all demand code reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
915 "SampleAfterValue": "100003",
916 "CounterHTOff": "0,1,2,3"
917 },
918 {
919 "Offcore": "1",
920 "EventCode": "0xB7, 0xBB",
921 "UMask": "0x1",
922 "BriefDescription": "Counts all demand code reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
923 "MSRValue": "0x04003c0004 ",
924 "Counter": "0,1,2,3",
925 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
926 "MSRIndex": "0x1a6,0x1a7",
927 "PublicDescription": "Counts all demand code reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
928 "SampleAfterValue": "100003",
929 "CounterHTOff": "0,1,2,3"
930 },
931 {
932 "Offcore": "1",
933 "EventCode": "0xB7, 0xBB",
934 "UMask": "0x1",
935 "BriefDescription": "DEMAND_CODE_RD & L3_HIT & SNOOP_HIT_WITH_FWD",
936 "MSRValue": "0x08003c0004 ",
937 "Counter": "0,1,2,3",
938 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
939 "MSRIndex": "0x1a6,0x1a7",
940 "PublicDescription": "tbd; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
941 "SampleAfterValue": "100003",
942 "CounterHTOff": "0,1,2,3"
943 },
944 {
945 "Offcore": "1",
946 "EventCode": "0xB7, 0xBB",
947 "UMask": "0x1",
948 "BriefDescription": "Counts all demand code reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
949 "MSRValue": "0x10003c0004 ",
950 "Counter": "0,1,2,3",
951 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE",
952 "MSRIndex": "0x1a6,0x1a7",
953 "PublicDescription": "Counts all demand code reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
954 "SampleAfterValue": "100003",
955 "CounterHTOff": "0,1,2,3"
956 },
957 {
958 "Offcore": "1",
959 "EventCode": "0xB7, 0xBB",
960 "UMask": "0x1",
961 "BriefDescription": "Counts all demand code reads that hit in the L3.",
962 "MSRValue": "0x3f803c0004 ",
963 "Counter": "0,1,2,3",
964 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP",
965 "MSRIndex": "0x1a6,0x1a7",
966 "PublicDescription": "Counts all demand code reads that hit in the L3.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
967 "SampleAfterValue": "100003",
968 "CounterHTOff": "0,1,2,3"
969 },
970 {
971 "Offcore": "1",
972 "EventCode": "0xB7, 0xBB",
973 "UMask": "0x1",
974 "BriefDescription": "Counts prefetch (that bring data to L2) data reads that have any response type.",
975 "MSRValue": "0x0000010010 ",
976 "Counter": "0,1,2,3",
977 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.ANY_RESPONSE",
978 "MSRIndex": "0x1a6,0x1a7",
979 "PublicDescription": "Counts prefetch (that bring data to L2) data reads that have any response type.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
980 "SampleAfterValue": "100003",
981 "CounterHTOff": "0,1,2,3"
982 },
983 {
984 "Offcore": "1",
985 "EventCode": "0xB7, 0xBB",
986 "UMask": "0x1",
987 "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
988 "MSRValue": "0x01003c0010 ",
989 "Counter": "0,1,2,3",
990 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
991 "MSRIndex": "0x1a6,0x1a7",
992 "PublicDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
993 "SampleAfterValue": "100003",
994 "CounterHTOff": "0,1,2,3"
995 },
996 {
997 "Offcore": "1",
998 "EventCode": "0xB7, 0xBB",
999 "UMask": "0x1",
1000 "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1001 "MSRValue": "0x04003c0010 ",
1002 "Counter": "0,1,2,3",
1003 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
1004 "MSRIndex": "0x1a6,0x1a7",
1005 "PublicDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1006 "SampleAfterValue": "100003",
1007 "CounterHTOff": "0,1,2,3"
1008 },
1009 {
1010 "Offcore": "1",
1011 "EventCode": "0xB7, 0xBB",
1012 "UMask": "0x1",
1013 "BriefDescription": "PF_L2_DATA_RD & L3_HIT & SNOOP_HIT_WITH_FWD",
1014 "MSRValue": "0x08003c0010 ",
1015 "Counter": "0,1,2,3",
1016 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
1017 "MSRIndex": "0x1a6,0x1a7",
1018 "PublicDescription": "tbd; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1019 "SampleAfterValue": "100003",
1020 "CounterHTOff": "0,1,2,3"
1021 },
1022 {
1023 "Offcore": "1",
1024 "EventCode": "0xB7, 0xBB",
1025 "UMask": "0x1",
1026 "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1027 "MSRValue": "0x10003c0010 ",
1028 "Counter": "0,1,2,3",
1029 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.HITM_OTHER_CORE",
1030 "MSRIndex": "0x1a6,0x1a7",
1031 "PublicDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1032 "SampleAfterValue": "100003",
1033 "CounterHTOff": "0,1,2,3"
1034 },
1035 {
1036 "Offcore": "1",
1037 "EventCode": "0xB7, 0xBB",
1038 "UMask": "0x1",
1039 "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3.",
1040 "MSRValue": "0x3f803c0010 ",
1041 "Counter": "0,1,2,3",
1042 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP",
1043 "MSRIndex": "0x1a6,0x1a7",
1044 "PublicDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1045 "SampleAfterValue": "100003",
1046 "CounterHTOff": "0,1,2,3"
1047 },
1048 {
1049 "Offcore": "1",
1050 "EventCode": "0xB7, 0xBB",
1051 "UMask": "0x1",
1052 "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that have any response type.",
1053 "MSRValue": "0x0000010020 ",
1054 "Counter": "0,1,2,3",
1055 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.ANY_RESPONSE",
1056 "MSRIndex": "0x1a6,0x1a7",
1057 "PublicDescription": "Counts all prefetch (that bring data to L2) RFOs that have any response type.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1058 "SampleAfterValue": "100003",
1059 "CounterHTOff": "0,1,2,3"
1060 },
1061 {
1062 "Offcore": "1",
1063 "EventCode": "0xB7, 0xBB",
1064 "UMask": "0x1",
1065 "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
1066 "MSRValue": "0x01003c0020 ",
1067 "Counter": "0,1,2,3",
1068 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED",
1069 "MSRIndex": "0x1a6,0x1a7",
1070 "PublicDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1071 "SampleAfterValue": "100003",
1072 "CounterHTOff": "0,1,2,3"
1073 },
1074 {
1075 "Offcore": "1",
1076 "EventCode": "0xB7, 0xBB",
1077 "UMask": "0x1",
1078 "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1079 "MSRValue": "0x04003c0020 ",
1080 "Counter": "0,1,2,3",
1081 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
1082 "MSRIndex": "0x1a6,0x1a7",
1083 "PublicDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1084 "SampleAfterValue": "100003",
1085 "CounterHTOff": "0,1,2,3"
1086 },
1087 {
1088 "Offcore": "1",
1089 "EventCode": "0xB7, 0xBB",
1090 "UMask": "0x1",
1091 "BriefDescription": "PF_L2_RFO & L3_HIT & SNOOP_HIT_WITH_FWD",
1092 "MSRValue": "0x08003c0020 ",
1093 "Counter": "0,1,2,3",
1094 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
1095 "MSRIndex": "0x1a6,0x1a7",
1096 "PublicDescription": "tbd; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1097 "SampleAfterValue": "100003",
1098 "CounterHTOff": "0,1,2,3"
1099 },
1100 {
1101 "Offcore": "1",
1102 "EventCode": "0xB7, 0xBB",
1103 "UMask": "0x1",
1104 "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1105 "MSRValue": "0x10003c0020 ",
1106 "Counter": "0,1,2,3",
1107 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.HITM_OTHER_CORE",
1108 "MSRIndex": "0x1a6,0x1a7",
1109 "PublicDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1110 "SampleAfterValue": "100003",
1111 "CounterHTOff": "0,1,2,3"
1112 },
1113 {
1114 "Offcore": "1",
1115 "EventCode": "0xB7, 0xBB",
1116 "UMask": "0x1",
1117 "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3.",
1118 "MSRValue": "0x3f803c0020 ",
1119 "Counter": "0,1,2,3",
1120 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.ANY_SNOOP",
1121 "MSRIndex": "0x1a6,0x1a7",
1122 "PublicDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1123 "SampleAfterValue": "100003",
1124 "CounterHTOff": "0,1,2,3"
1125 },
1126 {
1127 "Offcore": "1",
1128 "EventCode": "0xB7, 0xBB",
1129 "UMask": "0x1",
1130 "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that have any response type.",
1131 "MSRValue": "0x0000010080 ",
1132 "Counter": "0,1,2,3",
1133 "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.ANY_RESPONSE",
1134 "MSRIndex": "0x1a6,0x1a7",
1135 "PublicDescription": "Counts all prefetch (that bring data to LLC only) data reads that have any response type.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1136 "SampleAfterValue": "100003",
1137 "CounterHTOff": "0,1,2,3"
1138 },
1139 {
1140 "Offcore": "1",
1141 "EventCode": "0xB7, 0xBB",
1142 "UMask": "0x1",
1143 "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
1144 "MSRValue": "0x01003c0080 ",
1145 "Counter": "0,1,2,3",
1146 "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
1147 "MSRIndex": "0x1a6,0x1a7",
1148 "PublicDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1149 "SampleAfterValue": "100003",
1150 "CounterHTOff": "0,1,2,3"
1151 },
1152 {
1153 "Offcore": "1",
1154 "EventCode": "0xB7, 0xBB",
1155 "UMask": "0x1",
1156 "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1157 "MSRValue": "0x04003c0080 ",
1158 "Counter": "0,1,2,3",
1159 "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
1160 "MSRIndex": "0x1a6,0x1a7",
1161 "PublicDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1162 "SampleAfterValue": "100003",
1163 "CounterHTOff": "0,1,2,3"
1164 },
1165 {
1166 "Offcore": "1",
1167 "EventCode": "0xB7, 0xBB",
1168 "UMask": "0x1",
1169 "BriefDescription": "PF_L3_DATA_RD & L3_HIT & SNOOP_HIT_WITH_FWD",
1170 "MSRValue": "0x08003c0080 ",
1171 "Counter": "0,1,2,3",
1172 "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
1173 "MSRIndex": "0x1a6,0x1a7",
1174 "PublicDescription": "tbd; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1175 "SampleAfterValue": "100003",
1176 "CounterHTOff": "0,1,2,3"
1177 },
1178 {
1179 "Offcore": "1",
1180 "EventCode": "0xB7, 0xBB",
1181 "UMask": "0x1",
1182 "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1183 "MSRValue": "0x10003c0080 ",
1184 "Counter": "0,1,2,3",
1185 "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.HITM_OTHER_CORE",
1186 "MSRIndex": "0x1a6,0x1a7",
1187 "PublicDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1188 "SampleAfterValue": "100003",
1189 "CounterHTOff": "0,1,2,3"
1190 },
1191 {
1192 "Offcore": "1",
1193 "EventCode": "0xB7, 0xBB",
1194 "UMask": "0x1",
1195 "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3.",
1196 "MSRValue": "0x3f803c0080 ",
1197 "Counter": "0,1,2,3",
1198 "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP",
1199 "MSRIndex": "0x1a6,0x1a7",
1200 "PublicDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1201 "SampleAfterValue": "100003",
1202 "CounterHTOff": "0,1,2,3"
1203 },
1204 {
1205 "Offcore": "1",
1206 "EventCode": "0xB7, 0xBB",
1207 "UMask": "0x1",
1208 "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that have any response type.",
1209 "MSRValue": "0x0000010100 ",
1210 "Counter": "0,1,2,3",
1211 "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.ANY_RESPONSE",
1212 "MSRIndex": "0x1a6,0x1a7",
1213 "PublicDescription": "Counts all prefetch (that bring data to LLC only) RFOs that have any response type.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1214 "SampleAfterValue": "100003",
1215 "CounterHTOff": "0,1,2,3"
1216 },
1217 {
1218 "Offcore": "1",
1219 "EventCode": "0xB7, 0xBB",
1220 "UMask": "0x1",
1221 "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
1222 "MSRValue": "0x01003c0100 ",
1223 "Counter": "0,1,2,3",
1224 "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED",
1225 "MSRIndex": "0x1a6,0x1a7",
1226 "PublicDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1227 "SampleAfterValue": "100003",
1228 "CounterHTOff": "0,1,2,3"
1229 },
1230 {
1231 "Offcore": "1",
1232 "EventCode": "0xB7, 0xBB",
1233 "UMask": "0x1",
1234 "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1235 "MSRValue": "0x04003c0100 ",
1236 "Counter": "0,1,2,3",
1237 "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
1238 "MSRIndex": "0x1a6,0x1a7",
1239 "PublicDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1240 "SampleAfterValue": "100003",
1241 "CounterHTOff": "0,1,2,3"
1242 },
1243 {
1244 "Offcore": "1",
1245 "EventCode": "0xB7, 0xBB",
1246 "UMask": "0x1",
1247 "BriefDescription": "PF_L3_RFO & L3_HIT & SNOOP_HIT_WITH_FWD",
1248 "MSRValue": "0x08003c0100 ",
1249 "Counter": "0,1,2,3",
1250 "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
1251 "MSRIndex": "0x1a6,0x1a7",
1252 "PublicDescription": "tbd; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1253 "SampleAfterValue": "100003",
1254 "CounterHTOff": "0,1,2,3"
1255 },
1256 {
1257 "Offcore": "1",
1258 "EventCode": "0xB7, 0xBB",
1259 "UMask": "0x1",
1260 "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1261 "MSRValue": "0x10003c0100 ",
1262 "Counter": "0,1,2,3",
1263 "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.HITM_OTHER_CORE",
1264 "MSRIndex": "0x1a6,0x1a7",
1265 "PublicDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1266 "SampleAfterValue": "100003",
1267 "CounterHTOff": "0,1,2,3"
1268 },
1269 {
1270 "Offcore": "1",
1271 "EventCode": "0xB7, 0xBB",
1272 "UMask": "0x1",
1273 "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3.",
1274 "MSRValue": "0x3f803c0100 ",
1275 "Counter": "0,1,2,3",
1276 "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.ANY_SNOOP",
1277 "MSRIndex": "0x1a6,0x1a7",
1278 "PublicDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1279 "SampleAfterValue": "100003",
1280 "CounterHTOff": "0,1,2,3"
1281 },
1282 {
1283 "Offcore": "1",
1284 "EventCode": "0xB7, 0xBB",
1285 "UMask": "0x1",
1286 "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that have any response type.",
1287 "MSRValue": "0x0000010400 ",
1288 "Counter": "0,1,2,3",
1289 "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.ANY_RESPONSE",
1290 "MSRIndex": "0x1a6,0x1a7",
1291 "PublicDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that have any response type.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1292 "SampleAfterValue": "100003",
1293 "CounterHTOff": "0,1,2,3"
1294 },
1295 {
1296 "Offcore": "1",
1297 "EventCode": "0xB7, 0xBB",
1298 "UMask": "0x1",
1299 "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
1300 "MSRValue": "0x01003c0400 ",
1301 "Counter": "0,1,2,3",
1302 "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED",
1303 "MSRIndex": "0x1a6,0x1a7",
1304 "PublicDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1305 "SampleAfterValue": "100003",
1306 "CounterHTOff": "0,1,2,3"
1307 },
1308 {
1309 "Offcore": "1",
1310 "EventCode": "0xB7, 0xBB",
1311 "UMask": "0x1",
1312 "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1313 "MSRValue": "0x04003c0400 ",
1314 "Counter": "0,1,2,3",
1315 "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD",
1316 "MSRIndex": "0x1a6,0x1a7",
1317 "PublicDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1318 "SampleAfterValue": "100003",
1319 "CounterHTOff": "0,1,2,3"
1320 },
1321 {
1322 "Offcore": "1",
1323 "EventCode": "0xB7, 0xBB",
1324 "UMask": "0x1",
1325 "BriefDescription": "PF_L1D_AND_SW & L3_HIT & SNOOP_HIT_WITH_FWD",
1326 "MSRValue": "0x08003c0400 ",
1327 "Counter": "0,1,2,3",
1328 "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.SNOOP_HIT_WITH_FWD",
1329 "MSRIndex": "0x1a6,0x1a7",
1330 "PublicDescription": "tbd; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1331 "SampleAfterValue": "100003",
1332 "CounterHTOff": "0,1,2,3"
1333 },
1334 {
1335 "Offcore": "1",
1336 "EventCode": "0xB7, 0xBB",
1337 "UMask": "0x1",
1338 "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1339 "MSRValue": "0x10003c0400 ",
1340 "Counter": "0,1,2,3",
1341 "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.HITM_OTHER_CORE",
1342 "MSRIndex": "0x1a6,0x1a7",
1343 "PublicDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1344 "SampleAfterValue": "100003",
1345 "CounterHTOff": "0,1,2,3"
1346 },
1347 {
1348 "Offcore": "1",
1349 "EventCode": "0xB7, 0xBB",
1350 "UMask": "0x1",
1351 "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3.",
1352 "MSRValue": "0x3f803c0400 ",
1353 "Counter": "0,1,2,3",
1354 "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.ANY_SNOOP",
1355 "MSRIndex": "0x1a6,0x1a7",
1356 "PublicDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1357 "SampleAfterValue": "100003",
1358 "CounterHTOff": "0,1,2,3"
1359 },
1360 {
1361 "Offcore": "1",
1362 "EventCode": "0xB7, 0xBB",
1363 "UMask": "0x1",
1364 "BriefDescription": "Counts all prefetch data reads that have any response type.",
1365 "MSRValue": "0x0000010490 ",
1366 "Counter": "0,1,2,3",
1367 "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.ANY_RESPONSE",
1368 "MSRIndex": "0x1a6,0x1a7",
1369 "PublicDescription": "Counts all prefetch data reads that have any response type.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1370 "SampleAfterValue": "100003",
1371 "CounterHTOff": "0,1,2,3"
1372 },
1373 {
1374 "Offcore": "1",
1375 "EventCode": "0xB7, 0xBB",
1376 "UMask": "0x1",
1377 "BriefDescription": "Counts all prefetch data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
1378 "MSRValue": "0x01003c0490 ",
1379 "Counter": "0,1,2,3",
1380 "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
1381 "MSRIndex": "0x1a6,0x1a7",
1382 "PublicDescription": "Counts all prefetch data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1383 "SampleAfterValue": "100003",
1384 "CounterHTOff": "0,1,2,3"
1385 },
1386 {
1387 "Offcore": "1",
1388 "EventCode": "0xB7, 0xBB",
1389 "UMask": "0x1",
1390 "BriefDescription": "Counts all prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1391 "MSRValue": "0x04003c0490 ",
1392 "Counter": "0,1,2,3",
1393 "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
1394 "MSRIndex": "0x1a6,0x1a7",
1395 "PublicDescription": "Counts all prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1396 "SampleAfterValue": "100003",
1397 "CounterHTOff": "0,1,2,3"
1398 },
1399 {
1400 "Offcore": "1",
1401 "EventCode": "0xB7, 0xBB",
1402 "UMask": "0x1",
1403 "BriefDescription": "ALL_PF_DATA_RD & L3_HIT & SNOOP_HIT_WITH_FWD",
1404 "MSRValue": "0x08003c0490 ",
1405 "Counter": "0,1,2,3",
1406 "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
1407 "MSRIndex": "0x1a6,0x1a7",
1408 "PublicDescription": "tbd; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1409 "SampleAfterValue": "100003",
1410 "CounterHTOff": "0,1,2,3"
1411 },
1412 {
1413 "Offcore": "1",
1414 "EventCode": "0xB7, 0xBB",
1415 "UMask": "0x1",
1416 "BriefDescription": "Counts all prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1417 "MSRValue": "0x10003c0490 ",
1418 "Counter": "0,1,2,3",
1419 "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE",
1420 "MSRIndex": "0x1a6,0x1a7",
1421 "PublicDescription": "Counts all prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1422 "SampleAfterValue": "100003",
1423 "CounterHTOff": "0,1,2,3"
1424 },
1425 {
1426 "Offcore": "1",
1427 "EventCode": "0xB7, 0xBB",
1428 "UMask": "0x1",
1429 "BriefDescription": "Counts all prefetch data reads that hit in the L3.",
1430 "MSRValue": "0x3f803c0490 ",
1431 "Counter": "0,1,2,3",
1432 "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP",
1433 "MSRIndex": "0x1a6,0x1a7",
1434 "PublicDescription": "Counts all prefetch data reads that hit in the L3.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1435 "SampleAfterValue": "100003",
1436 "CounterHTOff": "0,1,2,3"
1437 },
1438 {
1439 "Offcore": "1",
1440 "EventCode": "0xB7, 0xBB",
1441 "UMask": "0x1",
1442 "BriefDescription": "Counts prefetch RFOs that have any response type.",
1443 "MSRValue": "0x0000010120 ",
1444 "Counter": "0,1,2,3",
1445 "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.ANY_RESPONSE",
1446 "MSRIndex": "0x1a6,0x1a7",
1447 "PublicDescription": "Counts prefetch RFOs that have any response type.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1448 "SampleAfterValue": "100003",
1449 "CounterHTOff": "0,1,2,3"
1450 },
1451 {
1452 "Offcore": "1",
1453 "EventCode": "0xB7, 0xBB",
1454 "UMask": "0x1",
1455 "BriefDescription": "Counts prefetch RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
1456 "MSRValue": "0x01003c0120 ",
1457 "Counter": "0,1,2,3",
1458 "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED",
1459 "MSRIndex": "0x1a6,0x1a7",
1460 "PublicDescription": "Counts prefetch RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1461 "SampleAfterValue": "100003",
1462 "CounterHTOff": "0,1,2,3"
1463 },
1464 {
1465 "Offcore": "1",
1466 "EventCode": "0xB7, 0xBB",
1467 "UMask": "0x1",
1468 "BriefDescription": "Counts prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1469 "MSRValue": "0x04003c0120 ",
1470 "Counter": "0,1,2,3",
1471 "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
1472 "MSRIndex": "0x1a6,0x1a7",
1473 "PublicDescription": "Counts prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1474 "SampleAfterValue": "100003",
1475 "CounterHTOff": "0,1,2,3"
1476 },
1477 {
1478 "Offcore": "1",
1479 "EventCode": "0xB7, 0xBB",
1480 "UMask": "0x1",
1481 "BriefDescription": "ALL_PF_RFO & L3_HIT & SNOOP_HIT_WITH_FWD",
1482 "MSRValue": "0x08003c0120 ",
1483 "Counter": "0,1,2,3",
1484 "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
1485 "MSRIndex": "0x1a6,0x1a7",
1486 "PublicDescription": "tbd; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1487 "SampleAfterValue": "100003",
1488 "CounterHTOff": "0,1,2,3"
1489 },
1490 {
1491 "Offcore": "1",
1492 "EventCode": "0xB7, 0xBB",
1493 "UMask": "0x1",
1494 "BriefDescription": "Counts prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1495 "MSRValue": "0x10003c0120 ",
1496 "Counter": "0,1,2,3",
1497 "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.HITM_OTHER_CORE",
1498 "MSRIndex": "0x1a6,0x1a7",
1499 "PublicDescription": "Counts prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1500 "SampleAfterValue": "100003",
1501 "CounterHTOff": "0,1,2,3"
1502 },
1503 {
1504 "Offcore": "1",
1505 "EventCode": "0xB7, 0xBB",
1506 "UMask": "0x1",
1507 "BriefDescription": "Counts prefetch RFOs that hit in the L3.",
1508 "MSRValue": "0x3f803c0120 ",
1509 "Counter": "0,1,2,3",
1510 "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.ANY_SNOOP",
1511 "MSRIndex": "0x1a6,0x1a7",
1512 "PublicDescription": "Counts prefetch RFOs that hit in the L3.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1513 "SampleAfterValue": "100003",
1514 "CounterHTOff": "0,1,2,3"
1515 },
1516 {
1517 "Offcore": "1",
1518 "EventCode": "0xB7, 0xBB",
1519 "UMask": "0x1",
1520 "BriefDescription": "Counts all demand & prefetch data reads that have any response type.",
1521 "MSRValue": "0x0000010491 ",
1522 "Counter": "0,1,2,3",
1523 "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.ANY_RESPONSE",
1524 "MSRIndex": "0x1a6,0x1a7",
1525 "PublicDescription": "Counts all demand & prefetch data reads that have any response type.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1526 "SampleAfterValue": "100003",
1527 "CounterHTOff": "0,1,2,3"
1528 },
1529 {
1530 "Offcore": "1",
1531 "EventCode": "0xB7, 0xBB",
1532 "UMask": "0x1",
1533 "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
1534 "MSRValue": "0x01003c0491 ",
1535 "Counter": "0,1,2,3",
1536 "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
1537 "MSRIndex": "0x1a6,0x1a7",
1538 "PublicDescription": "Counts all demand & prefetch data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1539 "SampleAfterValue": "100003",
1540 "CounterHTOff": "0,1,2,3"
1541 },
1542 {
1543 "Offcore": "1",
1544 "EventCode": "0xB7, 0xBB",
1545 "UMask": "0x1",
1546 "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1547 "MSRValue": "0x04003c0491 ",
1548 "Counter": "0,1,2,3",
1549 "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
1550 "MSRIndex": "0x1a6,0x1a7",
1551 "PublicDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1552 "SampleAfterValue": "100003",
1553 "CounterHTOff": "0,1,2,3"
1554 },
1555 {
1556 "Offcore": "1",
1557 "EventCode": "0xB7, 0xBB",
1558 "UMask": "0x1",
1559 "BriefDescription": "ALL_DATA_RD & L3_HIT & SNOOP_HIT_WITH_FWD",
1560 "MSRValue": "0x08003c0491 ",
1561 "Counter": "0,1,2,3",
1562 "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
1563 "MSRIndex": "0x1a6,0x1a7",
1564 "PublicDescription": "tbd; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1565 "SampleAfterValue": "100003",
1566 "CounterHTOff": "0,1,2,3"
1567 },
1568 {
1569 "Offcore": "1",
1570 "EventCode": "0xB7, 0xBB",
1571 "UMask": "0x1",
1572 "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1573 "MSRValue": "0x10003c0491 ",
1574 "Counter": "0,1,2,3",
1575 "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE",
1576 "MSRIndex": "0x1a6,0x1a7",
1577 "PublicDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1578 "SampleAfterValue": "100003",
1579 "CounterHTOff": "0,1,2,3"
1580 },
1581 {
1582 "Offcore": "1",
1583 "EventCode": "0xB7, 0xBB",
1584 "UMask": "0x1",
1585 "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3.",
1586 "MSRValue": "0x3f803c0491 ",
1587 "Counter": "0,1,2,3",
1588 "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.ANY_SNOOP",
1589 "MSRIndex": "0x1a6,0x1a7",
1590 "PublicDescription": "Counts all demand & prefetch data reads that hit in the L3.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1591 "SampleAfterValue": "100003",
1592 "CounterHTOff": "0,1,2,3"
1593 },
1594 {
1595 "Offcore": "1",
1596 "EventCode": "0xB7, 0xBB",
1597 "UMask": "0x1",
1598 "BriefDescription": "Counts all demand & prefetch RFOs that have any response type.",
1599 "MSRValue": "0x0000010122 ",
1600 "Counter": "0,1,2,3",
1601 "EventName": "OFFCORE_RESPONSE.ALL_RFO.ANY_RESPONSE",
1602 "MSRIndex": "0x1a6,0x1a7",
1603 "PublicDescription": "Counts all demand & prefetch RFOs that have any response type.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1604 "SampleAfterValue": "100003",
1605 "CounterHTOff": "0,1,2,3"
1606 },
1607 {
1608 "Offcore": "1",
1609 "EventCode": "0xB7, 0xBB",
1610 "UMask": "0x1",
1611 "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
1612 "MSRValue": "0x01003c0122 ",
1613 "Counter": "0,1,2,3",
1614 "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED",
1615 "MSRIndex": "0x1a6,0x1a7",
1616 "PublicDescription": "Counts all demand & prefetch RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1617 "SampleAfterValue": "100003",
1618 "CounterHTOff": "0,1,2,3"
1619 },
1620 {
1621 "Offcore": "1",
1622 "EventCode": "0xB7, 0xBB",
1623 "UMask": "0x1",
1624 "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1625 "MSRValue": "0x04003c0122 ",
1626 "Counter": "0,1,2,3",
1627 "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
1628 "MSRIndex": "0x1a6,0x1a7",
1629 "PublicDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1630 "SampleAfterValue": "100003",
1631 "CounterHTOff": "0,1,2,3"
1632 },
1633 {
1634 "Offcore": "1",
1635 "EventCode": "0xB7, 0xBB",
1636 "UMask": "0x1",
1637 "BriefDescription": "ALL_RFO & L3_HIT & SNOOP_HIT_WITH_FWD",
1638 "MSRValue": "0x08003c0122 ",
1639 "Counter": "0,1,2,3",
1640 "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
1641 "MSRIndex": "0x1a6,0x1a7",
1642 "PublicDescription": "tbd; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1643 "SampleAfterValue": "100003",
1644 "CounterHTOff": "0,1,2,3"
1645 },
1646 {
1647 "Offcore": "1",
1648 "EventCode": "0xB7, 0xBB",
1649 "UMask": "0x1",
1650 "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
1651 "MSRValue": "0x10003c0122 ",
1652 "Counter": "0,1,2,3",
1653 "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.HITM_OTHER_CORE",
1654 "MSRIndex": "0x1a6,0x1a7",
1655 "PublicDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1656 "SampleAfterValue": "100003",
1657 "CounterHTOff": "0,1,2,3"
1658 },
1659 {
1660 "Offcore": "1",
1661 "EventCode": "0xB7, 0xBB",
1662 "UMask": "0x1",
1663 "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3.",
1664 "MSRValue": "0x3f803c0122 ",
1665 "Counter": "0,1,2,3",
1666 "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.ANY_SNOOP",
1667 "MSRIndex": "0x1a6,0x1a7",
1668 "PublicDescription": "Counts all demand & prefetch RFOs that hit in the L3.; Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
1669 "SampleAfterValue": "100003",
1670 "CounterHTOff": "0,1,2,3"
1671 }
1672] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/floating-point.json b/tools/perf/pmu-events/arch/x86/skylakex/floating-point.json
new file mode 100644
index 000000000000..1c09a328df36
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylakex/floating-point.json
@@ -0,0 +1,88 @@
1[
2 {
3 "EventCode": "0xC7",
4 "UMask": "0x1",
5 "BriefDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired. Each count represents 1 computation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
6 "Counter": "0,1,2,3",
7 "EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
8 "SampleAfterValue": "2000003",
9 "CounterHTOff": "0,1,2,3,4,5,6,7"
10 },
11 {
12 "EventCode": "0xC7",
13 "UMask": "0x2",
14 "BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired. Each count represents 1 computation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
15 "Counter": "0,1,2,3",
16 "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
17 "SampleAfterValue": "2000003",
18 "CounterHTOff": "0,1,2,3,4,5,6,7"
19 },
20 {
21 "EventCode": "0xC7",
22 "UMask": "0x4",
23 "BriefDescription": "Number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired. Each count represents 2 computations. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
24 "Counter": "0,1,2,3",
25 "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE",
26 "SampleAfterValue": "2000003",
27 "CounterHTOff": "0,1,2,3,4,5,6,7"
28 },
29 {
30 "EventCode": "0xC7",
31 "UMask": "0x8",
32 "BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element. ",
33 "Counter": "0,1,2,3",
34 "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE",
35 "PublicDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
36 "SampleAfterValue": "2000003",
37 "CounterHTOff": "0,1,2,3,4,5,6,7"
38 },
39 {
40 "EventCode": "0xC7",
41 "UMask": "0x10",
42 "BriefDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
43 "Counter": "0,1,2,3",
44 "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE",
45 "SampleAfterValue": "2000003",
46 "CounterHTOff": "0,1,2,3,4,5,6,7"
47 },
48 {
49 "EventCode": "0xC7",
50 "UMask": "0x20",
51 "BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired. Each count represents 8 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
52 "Counter": "0,1,2,3",
53 "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE",
54 "SampleAfterValue": "2000003",
55 "CounterHTOff": "0,1,2,3,4,5,6,7"
56 },
57 {
58 "EventCode": "0xC7",
59 "UMask": "0x40",
60 "BriefDescription": "Number of Packed Double-Precision FP arithmetic instructions (Use operation multiplier of 8)",
61 "Counter": "0,1,2,3",
62 "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE",
63 "PublicDescription": "Number of Packed Double-Precision FP arithmetic instructions (Use operation multiplier of 8).",
64 "SampleAfterValue": "2000003",
65 "CounterHTOff": "0,1,2,3,4,5,6,7"
66 },
67 {
68 "EventCode": "0xC7",
69 "UMask": "0x80",
70 "BriefDescription": "Number of Packed Single-Precision FP arithmetic instructions (Use operation multiplier of 16)",
71 "Counter": "0,1,2,3",
72 "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE",
73 "PublicDescription": "Number of Packed Single-Precision FP arithmetic instructions (Use operation multiplier of 16).",
74 "SampleAfterValue": "2000003",
75 "CounterHTOff": "0,1,2,3,4,5,6,7"
76 },
77 {
78 "EventCode": "0xCA",
79 "UMask": "0x1e",
80 "BriefDescription": "Cycles with any input/output SSE or FP assist",
81 "Counter": "0,1,2,3",
82 "EventName": "FP_ASSIST.ANY",
83 "CounterMask": "1",
84 "PublicDescription": "Counts cycles with any input and output SSE or x87 FP assist. If an input and output assist are detected on the same cycle the event increments by 1.",
85 "SampleAfterValue": "100003",
86 "CounterHTOff": "0,1,2,3,4,5,6,7"
87 }
88] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/frontend.json b/tools/perf/pmu-events/arch/x86/skylakex/frontend.json
new file mode 100644
index 000000000000..40abc0852cd6
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylakex/frontend.json
@@ -0,0 +1,482 @@
1[
2 {
3 "EventCode": "0x79",
4 "UMask": "0x4",
5 "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
6 "Counter": "0,1,2,3",
7 "EventName": "IDQ.MITE_UOPS",
8 "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
9 "SampleAfterValue": "2000003",
10 "CounterHTOff": "0,1,2,3,4,5,6,7"
11 },
12 {
13 "EventCode": "0x79",
14 "UMask": "0x4",
15 "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path",
16 "Counter": "0,1,2,3",
17 "EventName": "IDQ.MITE_CYCLES",
18 "CounterMask": "1",
19 "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ.",
20 "SampleAfterValue": "2000003",
21 "CounterHTOff": "0,1,2,3,4,5,6,7"
22 },
23 {
24 "EventCode": "0x79",
25 "UMask": "0x8",
26 "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
27 "Counter": "0,1,2,3",
28 "EventName": "IDQ.DSB_UOPS",
29 "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
30 "SampleAfterValue": "2000003",
31 "CounterHTOff": "0,1,2,3,4,5,6,7"
32 },
33 {
34 "EventCode": "0x79",
35 "UMask": "0x8",
36 "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path",
37 "Counter": "0,1,2,3",
38 "EventName": "IDQ.DSB_CYCLES",
39 "CounterMask": "1",
40 "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
41 "SampleAfterValue": "2000003",
42 "CounterHTOff": "0,1,2,3,4,5,6,7"
43 },
44 {
45 "EventCode": "0x79",
46 "UMask": "0x10",
47 "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
48 "Counter": "0,1,2,3",
49 "EventName": "IDQ.MS_DSB_CYCLES",
50 "CounterMask": "1",
51 "PublicDescription": "Counts cycles during which uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ.",
52 "SampleAfterValue": "2000003",
53 "CounterHTOff": "0,1,2,3,4,5,6,7"
54 },
55 {
56 "EventCode": "0x79",
57 "UMask": "0x18",
58 "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops",
59 "Counter": "0,1,2,3",
60 "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
61 "CounterMask": "4",
62 "PublicDescription": "Counts the number of cycles 4 uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Count includes uops that may 'bypass' the IDQ.",
63 "SampleAfterValue": "2000003",
64 "CounterHTOff": "0,1,2,3,4,5,6,7"
65 },
66 {
67 "EventCode": "0x79",
68 "UMask": "0x18",
69 "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
70 "Counter": "0,1,2,3",
71 "EventName": "IDQ.ALL_DSB_CYCLES_ANY_UOPS",
72 "CounterMask": "1",
73 "PublicDescription": "Counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Count includes uops that may 'bypass' the IDQ.",
74 "SampleAfterValue": "2000003",
75 "CounterHTOff": "0,1,2,3,4,5,6,7"
76 },
77 {
78 "EventCode": "0x79",
79 "UMask": "0x20",
80 "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
81 "Counter": "0,1,2,3",
82 "EventName": "IDQ.MS_MITE_UOPS",
83 "PublicDescription": "Counts the number of uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ.",
84 "SampleAfterValue": "2000003",
85 "CounterHTOff": "0,1,2,3,4,5,6,7"
86 },
87 {
88 "EventCode": "0x79",
89 "UMask": "0x24",
90 "BriefDescription": "Cycles MITE is delivering 4 Uops",
91 "Counter": "0,1,2,3",
92 "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
93 "CounterMask": "4",
94 "PublicDescription": "Counts the number of cycles 4 uops were delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. Counting includes uops that may 'bypass' the IDQ. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
95 "SampleAfterValue": "2000003",
96 "CounterHTOff": "0,1,2,3,4,5,6,7"
97 },
98 {
99 "EventCode": "0x79",
100 "UMask": "0x24",
101 "BriefDescription": "Cycles MITE is delivering any Uop",
102 "Counter": "0,1,2,3",
103 "EventName": "IDQ.ALL_MITE_CYCLES_ANY_UOPS",
104 "CounterMask": "1",
105 "PublicDescription": "Counts the number of cycles uops were delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. Counting includes uops that may 'bypass' the IDQ. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
106 "SampleAfterValue": "2000003",
107 "CounterHTOff": "0,1,2,3,4,5,6,7"
108 },
109 {
110 "EventCode": "0x79",
111 "UMask": "0x30",
112 "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
113 "Counter": "0,1,2,3",
114 "EventName": "IDQ.MS_CYCLES",
115 "CounterMask": "1",
116 "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
117 "SampleAfterValue": "2000003",
118 "CounterHTOff": "0,1,2,3,4,5,6,7"
119 },
120 {
121 "EdgeDetect": "1",
122 "EventCode": "0x79",
123 "UMask": "0x30",
124 "BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer",
125 "Counter": "0,1,2,3",
126 "EventName": "IDQ.MS_SWITCHES",
127 "CounterMask": "1",
128 "PublicDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
129 "SampleAfterValue": "2000003",
130 "CounterHTOff": "0,1,2,3,4,5,6,7"
131 },
132 {
133 "EventCode": "0x79",
134 "UMask": "0x30",
135 "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
136 "Counter": "0,1,2,3",
137 "EventName": "IDQ.MS_UOPS",
138 "PublicDescription": "Counts the total number of uops delivered by the Microcode Sequencer (MS). Any instruction over 4 uops will be delivered by the MS. Some instructions such as transcendentals may additionally generate uops from the MS.",
139 "SampleAfterValue": "2000003",
140 "CounterHTOff": "0,1,2,3,4,5,6,7"
141 },
142 {
143 "EventCode": "0x80",
144 "UMask": "0x4",
145 "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache miss.",
146 "Counter": "0,1,2,3",
147 "EventName": "ICACHE_16B.IFDATA_STALL",
148 "PublicDescription": "Cycles where a code line fetch is stalled due to an L1 instruction cache miss. The legacy decode pipeline works at a 16 Byte granularity.",
149 "SampleAfterValue": "2000003",
150 "CounterHTOff": "0,1,2,3,4,5,6,7"
151 },
152 {
153 "EventCode": "0x83",
154 "UMask": "0x1",
155 "BriefDescription": "Instruction fetch tag lookups that hit in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
156 "Counter": "0,1,2,3",
157 "EventName": "ICACHE_64B.IFTAG_HIT",
158 "SampleAfterValue": "200003",
159 "CounterHTOff": "0,1,2,3,4,5,6,7"
160 },
161 {
162 "EventCode": "0x83",
163 "UMask": "0x2",
164 "BriefDescription": "Instruction fetch tag lookups that miss in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
165 "Counter": "0,1,2,3",
166 "EventName": "ICACHE_64B.IFTAG_MISS",
167 "SampleAfterValue": "200003",
168 "CounterHTOff": "0,1,2,3,4,5,6,7"
169 },
170 {
171 "EventCode": "0x83",
172 "UMask": "0x4",
173 "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache tag miss.",
174 "Counter": "0,1,2,3",
175 "EventName": "ICACHE_64B.IFTAG_STALL",
176 "SampleAfterValue": "200003",
177 "CounterHTOff": "0,1,2,3,4,5,6,7"
178 },
179 {
180 "EventCode": "0x9C",
181 "UMask": "0x1",
182 "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled",
183 "Counter": "0,1,2,3",
184 "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
185 "PublicDescription": "Counts the number of uops not delivered to Resource Allocation Table (RAT) per thread adding \u201c4 \u2013 x\u201d when Resource Allocation Table (RAT) is not stalled and Instruction Decode Queue (IDQ) delivers x uops to Resource Allocation Table (RAT) (where x belongs to {0,1,2,3}). Counting does not cover cases when: a. IDQ-Resource Allocation Table (RAT) pipe serves the other thread. b. Resource Allocation Table (RAT) is stalled for the thread (including uop drops and clear BE conditions). c. Instruction Decode Queue (IDQ) delivers four uops.",
186 "SampleAfterValue": "2000003",
187 "CounterHTOff": "0,1,2,3,4,5,6,7"
188 },
189 {
190 "EventCode": "0x9C",
191 "UMask": "0x1",
192 "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
193 "Counter": "0,1,2,3",
194 "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
195 "CounterMask": "4",
196 "PublicDescription": "Counts, on the per-thread basis, cycles when no uops are delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core =4.",
197 "SampleAfterValue": "2000003",
198 "CounterHTOff": "0,1,2,3,4,5,6,7"
199 },
200 {
201 "EventCode": "0x9C",
202 "UMask": "0x1",
203 "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
204 "Counter": "0,1,2,3",
205 "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
206 "CounterMask": "3",
207 "PublicDescription": "Counts, on the per-thread basis, cycles when less than 1 uop is delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core >= 3.",
208 "SampleAfterValue": "2000003",
209 "CounterHTOff": "0,1,2,3,4,5,6,7"
210 },
211 {
212 "EventCode": "0x9C",
213 "UMask": "0x1",
214 "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
215 "Counter": "0,1,2,3",
216 "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
217 "CounterMask": "2",
218 "PublicDescription": "Cycles with less than 2 uops delivered by the front-end.",
219 "SampleAfterValue": "2000003",
220 "CounterHTOff": "0,1,2,3,4,5,6,7"
221 },
222 {
223 "EventCode": "0x9C",
224 "UMask": "0x1",
225 "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
226 "Counter": "0,1,2,3",
227 "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
228 "CounterMask": "1",
229 "PublicDescription": "Cycles with less than 3 uops delivered by the front-end.",
230 "SampleAfterValue": "2000003",
231 "CounterHTOff": "0,1,2,3,4,5,6,7"
232 },
233 {
234 "Invert": "1",
235 "EventCode": "0x9C",
236 "UMask": "0x1",
237 "BriefDescription": "Counts cycles FE delivered 4 uops or Resource Allocation Table (RAT) was stalling FE.",
238 "Counter": "0,1,2,3",
239 "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
240 "CounterMask": "1",
241 "SampleAfterValue": "2000003",
242 "CounterHTOff": "0,1,2,3,4,5,6,7"
243 },
244 {
245 "EventCode": "0xAB",
246 "UMask": "0x2",
247 "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles.",
248 "Counter": "0,1,2,3",
249 "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
250 "PublicDescription": "Counts Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles. These cycles do not include uops routed through because of the switch itself, for example, when Instruction Decode Queue (IDQ) pre-allocation is unavailable, or Instruction Decode Queue (IDQ) is full. SBD-to-MITE switch true penalty cycles happen after the merge mux (MM) receives Decode Stream Buffer (DSB) Sync-indication until receiving the first MITE uop. MM is placed before Instruction Decode Queue (IDQ) to merge uops being fed from the MITE and Decode Stream Buffer (DSB) paths. Decode Stream Buffer (DSB) inserts the Sync-indication whenever a Decode Stream Buffer (DSB)-to-MITE switch occurs.Penalty: A Decode Stream Buffer (DSB) hit followed by a Decode Stream Buffer (DSB) miss can cost up to six cycles in which no uops are delivered to the IDQ. Most often, such switches from the Decode Stream Buffer (DSB) to the legacy pipeline cost 0\u20132 cycles.",
251 "SampleAfterValue": "2000003",
252 "CounterHTOff": "0,1,2,3,4,5,6,7"
253 },
254 {
255 "EventCode": "0xC6",
256 "UMask": "0x1",
257 "BriefDescription": "Retired Instructions who experienced decode stream buffer (DSB - the decoded instruction-cache) miss.",
258 "PEBS": "1",
259 "MSRValue": "0x11",
260 "Counter": "0,1,2,3",
261 "EventName": "FRONTEND_RETIRED.DSB_MISS",
262 "MSRIndex": "0x3F7",
263 "PublicDescription": "Counts retired Instructions that experienced DSB (Decode stream buffer i.e. the decoded instruction-cache) miss. ",
264 "TakenAlone": "1",
265 "SampleAfterValue": "100007",
266 "CounterHTOff": "0,1,2,3"
267 },
268 {
269 "EventCode": "0xC6",
270 "UMask": "0x1",
271 "BriefDescription": "Retired Instructions who experienced Instruction L1 Cache true miss.",
272 "PEBS": "1",
273 "MSRValue": "0x12",
274 "Counter": "0,1,2,3",
275 "EventName": "FRONTEND_RETIRED.L1I_MISS",
276 "MSRIndex": "0x3F7",
277 "TakenAlone": "1",
278 "SampleAfterValue": "100007",
279 "CounterHTOff": "0,1,2,3"
280 },
281 {
282 "EventCode": "0xC6",
283 "UMask": "0x1",
284 "BriefDescription": "Retired Instructions who experienced Instruction L2 Cache true miss.",
285 "PEBS": "1",
286 "MSRValue": "0x13",
287 "Counter": "0,1,2,3",
288 "EventName": "FRONTEND_RETIRED.L2_MISS",
289 "MSRIndex": "0x3F7",
290 "TakenAlone": "1",
291 "SampleAfterValue": "100007",
292 "CounterHTOff": "0,1,2,3"
293 },
294 {
295 "EventCode": "0xC6",
296 "UMask": "0x1",
297 "BriefDescription": "Retired Instructions who experienced iTLB true miss.",
298 "PEBS": "1",
299 "MSRValue": "0x14",
300 "Counter": "0,1,2,3",
301 "EventName": "FRONTEND_RETIRED.ITLB_MISS",
302 "MSRIndex": "0x3F7",
303 "PublicDescription": "Counts retired Instructions that experienced iTLB (Instruction TLB) true miss.",
304 "TakenAlone": "1",
305 "SampleAfterValue": "100007",
306 "CounterHTOff": "0,1,2,3"
307 },
308 {
309 "EventCode": "0xC6",
310 "UMask": "0x1",
311 "BriefDescription": "Retired Instructions who experienced STLB (2nd level TLB) true miss.",
312 "PEBS": "1",
313 "MSRValue": "0x15",
314 "Counter": "0,1,2,3",
315 "EventName": "FRONTEND_RETIRED.STLB_MISS",
316 "MSRIndex": "0x3F7",
317 "PublicDescription": "Counts retired Instructions that experienced STLB (2nd level TLB) true miss. ",
318 "TakenAlone": "1",
319 "SampleAfterValue": "100007",
320 "CounterHTOff": "0,1,2,3"
321 },
322 {
323 "EventCode": "0xC6",
324 "UMask": "0x1",
325 "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 2 cycles which was not interrupted by a back-end stall.",
326 "PEBS": "1",
327 "MSRValue": "0x400206",
328 "Counter": "0,1,2,3",
329 "EventName": "FRONTEND_RETIRED.LATENCY_GE_2",
330 "MSRIndex": "0x3F7",
331 "TakenAlone": "1",
332 "SampleAfterValue": "100007",
333 "CounterHTOff": "0,1,2,3"
334 },
335 {
336 "EventCode": "0xC6",
337 "UMask": "0x1",
338 "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 2 bubble-slots for a period of 2 cycles which was not interrupted by a back-end stall.",
339 "PEBS": "1",
340 "MSRValue": "0x200206",
341 "Counter": "0,1,2,3",
342 "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_2",
343 "MSRIndex": "0x3F7",
344 "TakenAlone": "1",
345 "SampleAfterValue": "100007",
346 "CounterHTOff": "0,1,2,3"
347 },
348 {
349 "EventCode": "0xC6",
350 "UMask": "0x1",
351 "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.",
352 "PEBS": "1",
353 "MSRValue": "0x400406",
354 "Counter": "0,1,2,3",
355 "EventName": "FRONTEND_RETIRED.LATENCY_GE_4",
356 "MSRIndex": "0x3F7",
357 "TakenAlone": "1",
358 "SampleAfterValue": "100007",
359 "CounterHTOff": "0,1,2,3"
360 },
361 {
362 "EventCode": "0xC6",
363 "UMask": "0x1",
364 "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 8 cycles which was not interrupted by a back-end stall.",
365 "PEBS": "1",
366 "MSRValue": "0x400806",
367 "Counter": "0,1,2,3",
368 "EventName": "FRONTEND_RETIRED.LATENCY_GE_8",
369 "MSRIndex": "0x3F7",
370 "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 8 cycles. During this period the front-end delivered no uops.",
371 "TakenAlone": "1",
372 "SampleAfterValue": "100007",
373 "CounterHTOff": "0,1,2,3"
374 },
375 {
376 "EventCode": "0xC6",
377 "UMask": "0x1",
378 "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 16 cycles which was not interrupted by a back-end stall.",
379 "PEBS": "1",
380 "MSRValue": "0x401006",
381 "Counter": "0,1,2,3",
382 "EventName": "FRONTEND_RETIRED.LATENCY_GE_16",
383 "MSRIndex": "0x3F7",
384 "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 16 cycles. During this period the front-end delivered no uops.",
385 "TakenAlone": "1",
386 "SampleAfterValue": "100007",
387 "CounterHTOff": "0,1,2,3"
388 },
389 {
390 "EventCode": "0xC6",
391 "UMask": "0x1",
392 "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 32 cycles which was not interrupted by a back-end stall.",
393 "PEBS": "1",
394 "MSRValue": "0x402006",
395 "Counter": "0,1,2,3",
396 "EventName": "FRONTEND_RETIRED.LATENCY_GE_32",
397 "MSRIndex": "0x3F7",
398 "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 32 cycles. During this period the front-end delivered no uops.",
399 "TakenAlone": "1",
400 "SampleAfterValue": "100007",
401 "CounterHTOff": "0,1,2,3"
402 },
403 {
404 "EventCode": "0xC6",
405 "UMask": "0x1",
406 "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 64 cycles which was not interrupted by a back-end stall.",
407 "PEBS": "1",
408 "MSRValue": "0x404006",
409 "Counter": "0,1,2,3",
410 "EventName": "FRONTEND_RETIRED.LATENCY_GE_64",
411 "MSRIndex": "0x3F7",
412 "TakenAlone": "1",
413 "SampleAfterValue": "100007",
414 "CounterHTOff": "0,1,2,3"
415 },
416 {
417 "EventCode": "0xC6",
418 "UMask": "0x1",
419 "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.",
420 "PEBS": "1",
421 "MSRValue": "0x408006",
422 "Counter": "0,1,2,3",
423 "EventName": "FRONTEND_RETIRED.LATENCY_GE_128",
424 "MSRIndex": "0x3F7",
425 "TakenAlone": "1",
426 "SampleAfterValue": "100007",
427 "CounterHTOff": "0,1,2,3"
428 },
429 {
430 "EventCode": "0xC6",
431 "UMask": "0x1",
432 "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.",
433 "PEBS": "1",
434 "MSRValue": "0x410006",
435 "Counter": "0,1,2,3",
436 "EventName": "FRONTEND_RETIRED.LATENCY_GE_256",
437 "MSRIndex": "0x3F7",
438 "TakenAlone": "1",
439 "SampleAfterValue": "100007",
440 "CounterHTOff": "0,1,2,3"
441 },
442 {
443 "EventCode": "0xC6",
444 "UMask": "0x1",
445 "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.",
446 "PEBS": "1",
447 "MSRValue": "0x420006",
448 "Counter": "0,1,2,3",
449 "EventName": "FRONTEND_RETIRED.LATENCY_GE_512",
450 "MSRIndex": "0x3F7",
451 "TakenAlone": "1",
452 "SampleAfterValue": "100007",
453 "CounterHTOff": "0,1,2,3"
454 },
455 {
456 "EventCode": "0xC6",
457 "UMask": "0x1",
458 "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 1 bubble-slot for a period of 2 cycles which was not interrupted by a back-end stall.",
459 "PEBS": "1",
460 "MSRValue": "0x100206",
461 "Counter": "0,1,2,3",
462 "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1",
463 "MSRIndex": "0x3F7",
464 "PublicDescription": "Counts retired instructions that are delivered to the back-end after the front-end had at least 1 bubble-slot for a period of 2 cycles. A bubble-slot is an empty issue-pipeline slot while there was no RAT stall.",
465 "TakenAlone": "1",
466 "SampleAfterValue": "100007",
467 "CounterHTOff": "0,1,2,3"
468 },
469 {
470 "EventCode": "0xC6",
471 "UMask": "0x1",
472 "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 3 bubble-slots for a period of 2 cycles which was not interrupted by a back-end stall.",
473 "PEBS": "1",
474 "MSRValue": "0x300206",
475 "Counter": "0,1,2,3",
476 "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_3",
477 "MSRIndex": "0x3F7",
478 "TakenAlone": "1",
479 "SampleAfterValue": "100007",
480 "CounterHTOff": "0,1,2,3"
481 }
482] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/memory.json b/tools/perf/pmu-events/arch/x86/skylakex/memory.json
new file mode 100644
index 000000000000..ca22a22c1abd
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylakex/memory.json
@@ -0,0 +1,1396 @@
1[
2 {
3 "EventCode": "0x54",
4 "UMask": "0x1",
5 "BriefDescription": "Number of times a transactional abort was signaled due to a data conflict on a transactionally accessed address",
6 "Counter": "0,1,2,3",
7 "EventName": "TX_MEM.ABORT_CONFLICT",
8 "PublicDescription": "Number of times a TSX line had a cache conflict.",
9 "SampleAfterValue": "2000003",
10 "CounterHTOff": "0,1,2,3,4,5,6,7"
11 },
12 {
13 "EventCode": "0x54",
14 "UMask": "0x2",
15 "BriefDescription": "Number of times a transactional abort was signaled due to a data capacity limitation for transactional reads or writes.",
16 "Counter": "0,1,2,3",
17 "EventName": "TX_MEM.ABORT_CAPACITY",
18 "SampleAfterValue": "2000003",
19 "CounterHTOff": "0,1,2,3,4,5,6,7"
20 },
21 {
22 "EventCode": "0x54",
23 "UMask": "0x4",
24 "BriefDescription": "Number of times a HLE transactional region aborted due to a non XRELEASE prefixed instruction writing to an elided lock in the elision buffer",
25 "Counter": "0,1,2,3",
26 "EventName": "TX_MEM.ABORT_HLE_STORE_TO_ELIDED_LOCK",
27 "PublicDescription": "Number of times a TSX Abort was triggered due to a non-release/commit store to lock.",
28 "SampleAfterValue": "2000003",
29 "CounterHTOff": "0,1,2,3,4,5,6,7"
30 },
31 {
32 "EventCode": "0x54",
33 "UMask": "0x8",
34 "BriefDescription": "Number of times an HLE transactional execution aborted due to NoAllocatedElisionBuffer being non-zero.",
35 "Counter": "0,1,2,3",
36 "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_NOT_EMPTY",
37 "PublicDescription": "Number of times a TSX Abort was triggered due to commit but Lock Buffer not empty.",
38 "SampleAfterValue": "2000003",
39 "CounterHTOff": "0,1,2,3,4,5,6,7"
40 },
41 {
42 "EventCode": "0x54",
43 "UMask": "0x10",
44 "BriefDescription": "Number of times an HLE transactional execution aborted due to XRELEASE lock not satisfying the address and value requirements in the elision buffer",
45 "Counter": "0,1,2,3",
46 "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_MISMATCH",
47 "PublicDescription": "Number of times a TSX Abort was triggered due to release/commit but data and address mismatch.",
48 "SampleAfterValue": "2000003",
49 "CounterHTOff": "0,1,2,3,4,5,6,7"
50 },
51 {
52 "EventCode": "0x54",
53 "UMask": "0x20",
54 "BriefDescription": "Number of times an HLE transactional execution aborted due to an unsupported read alignment from the elision buffer.",
55 "Counter": "0,1,2,3",
56 "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_UNSUPPORTED_ALIGNMENT",
57 "PublicDescription": "Number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer.",
58 "SampleAfterValue": "2000003",
59 "CounterHTOff": "0,1,2,3,4,5,6,7"
60 },
61 {
62 "EventCode": "0x54",
63 "UMask": "0x40",
64 "BriefDescription": "Number of times HLE lock could not be elided due to ElisionBufferAvailable being zero.",
65 "Counter": "0,1,2,3",
66 "EventName": "TX_MEM.HLE_ELISION_BUFFER_FULL",
67 "PublicDescription": "Number of times we could not allocate Lock Buffer.",
68 "SampleAfterValue": "2000003",
69 "CounterHTOff": "0,1,2,3,4,5,6,7"
70 },
71 {
72 "EventCode": "0x5d",
73 "UMask": "0x1",
74 "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed. Since this is the count of execution, it may not always cause a transactional abort.",
75 "Counter": "0,1,2,3",
76 "EventName": "TX_EXEC.MISC1",
77 "SampleAfterValue": "2000003",
78 "CounterHTOff": "0,1,2,3,4,5,6,7"
79 },
80 {
81 "EventCode": "0x5d",
82 "UMask": "0x2",
83 "BriefDescription": "Counts the number of times a class of instructions (e.g., vzeroupper) that may cause a transactional abort was executed inside a transactional region",
84 "Counter": "0,1,2,3",
85 "EventName": "TX_EXEC.MISC2",
86 "PublicDescription": "Unfriendly TSX abort triggered by a vzeroupper instruction.",
87 "SampleAfterValue": "2000003",
88 "CounterHTOff": "0,1,2,3,4,5,6,7"
89 },
90 {
91 "EventCode": "0x5d",
92 "UMask": "0x4",
93 "BriefDescription": "Counts the number of times an instruction execution caused the transactional nest count supported to be exceeded",
94 "Counter": "0,1,2,3",
95 "EventName": "TX_EXEC.MISC3",
96 "PublicDescription": "Unfriendly TSX abort triggered by a nest count that is too deep.",
97 "SampleAfterValue": "2000003",
98 "CounterHTOff": "0,1,2,3,4,5,6,7"
99 },
100 {
101 "EventCode": "0x5d",
102 "UMask": "0x8",
103 "BriefDescription": "Counts the number of times a XBEGIN instruction was executed inside an HLE transactional region.",
104 "Counter": "0,1,2,3",
105 "EventName": "TX_EXEC.MISC4",
106 "PublicDescription": "RTM region detected inside HLE.",
107 "SampleAfterValue": "2000003",
108 "CounterHTOff": "0,1,2,3,4,5,6,7"
109 },
110 {
111 "EventCode": "0x5d",
112 "UMask": "0x10",
113 "BriefDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region",
114 "Counter": "0,1,2,3",
115 "EventName": "TX_EXEC.MISC5",
116 "PublicDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region.",
117 "SampleAfterValue": "2000003",
118 "CounterHTOff": "0,1,2,3,4,5,6,7"
119 },
120 {
121 "EventCode": "0x60",
122 "UMask": "0x10",
123 "BriefDescription": "Counts number of Offcore outstanding Demand Data Read requests that miss L3 cache in the superQ every cycle.",
124 "Counter": "0,1,2,3",
125 "EventName": "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD",
126 "SampleAfterValue": "2000003",
127 "CounterHTOff": "0,1,2,3,4,5,6,7"
128 },
129 {
130 "EventCode": "0x60",
131 "UMask": "0x10",
132 "BriefDescription": "Cycles with at least 1 Demand Data Read requests who miss L3 cache in the superQ.",
133 "Counter": "0,1,2,3",
134 "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_L3_MISS_DEMAND_DATA_RD",
135 "CounterMask": "1",
136 "SampleAfterValue": "2000003",
137 "CounterHTOff": "0,1,2,3,4,5,6,7"
138 },
139 {
140 "EventCode": "0x60",
141 "UMask": "0x10",
142 "BriefDescription": "Cycles with at least 6 Demand Data Read requests that miss L3 cache in the superQ.",
143 "Counter": "0,1,2,3",
144 "EventName": "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD_GE_6",
145 "CounterMask": "6",
146 "SampleAfterValue": "2000003",
147 "CounterHTOff": "0,1,2,3,4,5,6,7"
148 },
149 {
150 "EventCode": "0xA3",
151 "UMask": "0x2",
152 "BriefDescription": "Cycles while L3 cache miss demand load is outstanding.",
153 "Counter": "0,1,2,3",
154 "EventName": "CYCLE_ACTIVITY.CYCLES_L3_MISS",
155 "CounterMask": "2",
156 "SampleAfterValue": "2000003",
157 "CounterHTOff": "0,1,2,3,4,5,6,7"
158 },
159 {
160 "EventCode": "0xA3",
161 "UMask": "0x6",
162 "BriefDescription": "Execution stalls while L3 cache miss demand load is outstanding.",
163 "Counter": "0,1,2,3",
164 "EventName": "CYCLE_ACTIVITY.STALLS_L3_MISS",
165 "CounterMask": "6",
166 "SampleAfterValue": "2000003",
167 "CounterHTOff": "0,1,2,3,4,5,6,7"
168 },
169 {
170 "EventCode": "0xB0",
171 "UMask": "0x10",
172 "BriefDescription": "Demand Data Read requests who miss L3 cache",
173 "Counter": "0,1,2,3",
174 "EventName": "OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD",
175 "PublicDescription": "Demand Data Read requests who miss L3 cache.",
176 "SampleAfterValue": "100003",
177 "CounterHTOff": "0,1,2,3,4,5,6,7"
178 },
179 {
180 "EventCode": "0xC3",
181 "UMask": "0x2",
182 "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
183 "Counter": "0,1,2,3",
184 "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
185 "Errata": "SKL089",
186 "PublicDescription": "Counts the number of memory ordering Machine Clears detected. Memory Ordering Machine Clears can result from one of the following:a. memory disambiguation,b. external snoop, orc. cross SMT-HW-thread snoop (stores) hitting load buffer.",
187 "SampleAfterValue": "100003",
188 "CounterHTOff": "0,1,2,3,4,5,6,7"
189 },
190 {
191 "EventCode": "0xC8",
192 "UMask": "0x1",
193 "BriefDescription": "Number of times an HLE execution started.",
194 "Counter": "0,1,2,3",
195 "EventName": "HLE_RETIRED.START",
196 "PublicDescription": "Number of times we entered an HLE region. Does not count nested transactions.",
197 "SampleAfterValue": "2000003",
198 "CounterHTOff": "0,1,2,3,4,5,6,7"
199 },
200 {
201 "EventCode": "0xC8",
202 "UMask": "0x2",
203 "BriefDescription": "Number of times an HLE execution successfully committed",
204 "Counter": "0,1,2,3",
205 "EventName": "HLE_RETIRED.COMMIT",
206 "PublicDescription": "Number of times HLE commit succeeded.",
207 "SampleAfterValue": "2000003",
208 "CounterHTOff": "0,1,2,3,4,5,6,7"
209 },
210 {
211 "EventCode": "0xC8",
212 "UMask": "0x4",
213 "BriefDescription": "Number of times an HLE execution aborted due to any reasons (multiple categories may count as one). ",
214 "PEBS": "1",
215 "Counter": "0,1,2,3",
216 "EventName": "HLE_RETIRED.ABORTED",
217 "PublicDescription": "Number of times HLE abort was triggered.",
218 "SampleAfterValue": "2000003",
219 "CounterHTOff": "0,1,2,3,4,5,6,7"
220 },
221 {
222 "EventCode": "0xC8",
223 "UMask": "0x8",
224 "BriefDescription": "Number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
225 "Counter": "0,1,2,3",
226 "EventName": "HLE_RETIRED.ABORTED_MEM",
227 "SampleAfterValue": "2000003",
228 "CounterHTOff": "0,1,2,3,4,5,6,7"
229 },
230 {
231 "EventCode": "0xC8",
232 "UMask": "0x10",
233 "BriefDescription": "Number of times an HLE execution aborted due to hardware timer expiration.",
234 "Counter": "0,1,2,3",
235 "EventName": "HLE_RETIRED.ABORTED_TIMER",
236 "SampleAfterValue": "2000003",
237 "CounterHTOff": "0,1,2,3,4,5,6,7"
238 },
239 {
240 "EventCode": "0xC8",
241 "UMask": "0x20",
242 "BriefDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions and certain unfriendly events (such as AD assists etc.). ",
243 "Counter": "0,1,2,3",
244 "EventName": "HLE_RETIRED.ABORTED_UNFRIENDLY",
245 "PublicDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions and certain unfriendly events (such as AD assists etc.).",
246 "SampleAfterValue": "2000003",
247 "CounterHTOff": "0,1,2,3,4,5,6,7"
248 },
249 {
250 "EventCode": "0xC8",
251 "UMask": "0x40",
252 "BriefDescription": "Number of times an HLE execution aborted due to incompatible memory type",
253 "Counter": "0,1,2,3",
254 "EventName": "HLE_RETIRED.ABORTED_MEMTYPE",
255 "PublicDescription": "Number of times an HLE execution aborted due to incompatible memory type.",
256 "SampleAfterValue": "2000003",
257 "CounterHTOff": "0,1,2,3,4,5,6,7"
258 },
259 {
260 "EventCode": "0xC8",
261 "UMask": "0x80",
262 "BriefDescription": "Number of times an HLE execution aborted due to unfriendly events (such as interrupts).",
263 "Counter": "0,1,2,3",
264 "EventName": "HLE_RETIRED.ABORTED_EVENTS",
265 "SampleAfterValue": "2000003",
266 "CounterHTOff": "0,1,2,3,4,5,6,7"
267 },
268 {
269 "EventCode": "0xC9",
270 "UMask": "0x1",
271 "BriefDescription": "Number of times an RTM execution started.",
272 "Counter": "0,1,2,3",
273 "EventName": "RTM_RETIRED.START",
274 "PublicDescription": "Number of times we entered an RTM region. Does not count nested transactions.",
275 "SampleAfterValue": "2000003",
276 "CounterHTOff": "0,1,2,3,4,5,6,7"
277 },
278 {
279 "EventCode": "0xC9",
280 "UMask": "0x2",
281 "BriefDescription": "Number of times an RTM execution successfully committed",
282 "Counter": "0,1,2,3",
283 "EventName": "RTM_RETIRED.COMMIT",
284 "PublicDescription": "Number of times RTM commit succeeded.",
285 "SampleAfterValue": "2000003",
286 "CounterHTOff": "0,1,2,3,4,5,6,7"
287 },
288 {
289 "EventCode": "0xC9",
290 "UMask": "0x4",
291 "BriefDescription": "Number of times an RTM execution aborted due to any reasons (multiple categories may count as one). ",
292 "PEBS": "1",
293 "Counter": "0,1,2,3",
294 "EventName": "RTM_RETIRED.ABORTED",
295 "PublicDescription": "Number of times RTM abort was triggered.",
296 "SampleAfterValue": "2000003",
297 "CounterHTOff": "0,1,2,3,4,5,6,7"
298 },
299 {
300 "EventCode": "0xC9",
301 "UMask": "0x8",
302 "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)",
303 "Counter": "0,1,2,3",
304 "EventName": "RTM_RETIRED.ABORTED_MEM",
305 "PublicDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts).",
306 "SampleAfterValue": "2000003",
307 "CounterHTOff": "0,1,2,3,4,5,6,7"
308 },
309 {
310 "EventCode": "0xC9",
311 "UMask": "0x10",
312 "BriefDescription": "Number of times an RTM execution aborted due to uncommon conditions.",
313 "Counter": "0,1,2,3",
314 "EventName": "RTM_RETIRED.ABORTED_TIMER",
315 "SampleAfterValue": "2000003",
316 "CounterHTOff": "0,1,2,3,4,5,6,7"
317 },
318 {
319 "EventCode": "0xC9",
320 "UMask": "0x20",
321 "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions",
322 "Counter": "0,1,2,3",
323 "EventName": "RTM_RETIRED.ABORTED_UNFRIENDLY",
324 "PublicDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions.",
325 "SampleAfterValue": "2000003",
326 "CounterHTOff": "0,1,2,3,4,5,6,7"
327 },
328 {
329 "EventCode": "0xC9",
330 "UMask": "0x40",
331 "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type",
332 "Counter": "0,1,2,3",
333 "EventName": "RTM_RETIRED.ABORTED_MEMTYPE",
334 "PublicDescription": "Number of times an RTM execution aborted due to incompatible memory type.",
335 "SampleAfterValue": "2000003",
336 "CounterHTOff": "0,1,2,3,4,5,6,7"
337 },
338 {
339 "EventCode": "0xC9",
340 "UMask": "0x80",
341 "BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)",
342 "Counter": "0,1,2,3",
343 "EventName": "RTM_RETIRED.ABORTED_EVENTS",
344 "PublicDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt).",
345 "SampleAfterValue": "2000003",
346 "CounterHTOff": "0,1,2,3,4,5,6,7"
347 },
348 {
349 "EventCode": "0xCD",
350 "UMask": "0x1",
351 "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 4 cycles.",
352 "PEBS": "2",
353 "MSRValue": "0x4",
354 "Counter": "0,1,2,3",
355 "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
356 "MSRIndex": "0x3F6",
357 "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 4 cycles. Reported latency may be longer than just the memory latency.",
358 "TakenAlone": "1",
359 "SampleAfterValue": "100003",
360 "CounterHTOff": "0,1,2,3"
361 },
362 {
363 "EventCode": "0xCD",
364 "UMask": "0x1",
365 "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 8 cycles.",
366 "PEBS": "2",
367 "MSRValue": "0x8",
368 "Counter": "0,1,2,3",
369 "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
370 "MSRIndex": "0x3F6",
371 "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 8 cycles. Reported latency may be longer than just the memory latency.",
372 "TakenAlone": "1",
373 "SampleAfterValue": "50021",
374 "CounterHTOff": "0,1,2,3"
375 },
376 {
377 "EventCode": "0xCD",
378 "UMask": "0x1",
379 "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 16 cycles.",
380 "PEBS": "2",
381 "MSRValue": "0x10",
382 "Counter": "0,1,2,3",
383 "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
384 "MSRIndex": "0x3F6",
385 "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 16 cycles. Reported latency may be longer than just the memory latency.",
386 "TakenAlone": "1",
387 "SampleAfterValue": "20011",
388 "CounterHTOff": "0,1,2,3"
389 },
390 {
391 "EventCode": "0xCD",
392 "UMask": "0x1",
393 "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 32 cycles.",
394 "PEBS": "2",
395 "MSRValue": "0x20",
396 "Counter": "0,1,2,3",
397 "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
398 "MSRIndex": "0x3F6",
399 "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 32 cycles. Reported latency may be longer than just the memory latency.",
400 "TakenAlone": "1",
401 "SampleAfterValue": "100007",
402 "CounterHTOff": "0,1,2,3"
403 },
404 {
405 "EventCode": "0xCD",
406 "UMask": "0x1",
407 "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 64 cycles.",
408 "PEBS": "2",
409 "MSRValue": "0x40",
410 "Counter": "0,1,2,3",
411 "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
412 "MSRIndex": "0x3F6",
413 "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 64 cycles. Reported latency may be longer than just the memory latency.",
414 "TakenAlone": "1",
415 "SampleAfterValue": "2003",
416 "CounterHTOff": "0,1,2,3"
417 },
418 {
419 "EventCode": "0xCD",
420 "UMask": "0x1",
421 "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 128 cycles.",
422 "PEBS": "2",
423 "MSRValue": "0x80",
424 "Counter": "0,1,2,3",
425 "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
426 "MSRIndex": "0x3F6",
427 "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 128 cycles. Reported latency may be longer than just the memory latency.",
428 "TakenAlone": "1",
429 "SampleAfterValue": "1009",
430 "CounterHTOff": "0,1,2,3"
431 },
432 {
433 "EventCode": "0xCD",
434 "UMask": "0x1",
435 "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 256 cycles.",
436 "PEBS": "2",
437 "MSRValue": "0x100",
438 "Counter": "0,1,2,3",
439 "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
440 "MSRIndex": "0x3F6",
441 "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 256 cycles. Reported latency may be longer than just the memory latency.",
442 "TakenAlone": "1",
443 "SampleAfterValue": "503",
444 "CounterHTOff": "0,1,2,3"
445 },
446 {
447 "EventCode": "0xCD",
448 "UMask": "0x1",
449 "BriefDescription": "Counts loads when the latency from first dispatch to completion is greater than 512 cycles.",
450 "PEBS": "2",
451 "MSRValue": "0x200",
452 "Counter": "0,1,2,3",
453 "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
454 "MSRIndex": "0x3F6",
455 "PublicDescription": "Counts loads when the latency from first dispatch to completion is greater than 512 cycles. Reported latency may be longer than just the memory latency.",
456 "TakenAlone": "1",
457 "SampleAfterValue": "101",
458 "CounterHTOff": "0,1,2,3"
459 },
460 {
461 "Offcore": "1",
462 "EventCode": "0xB7, 0xBB",
463 "UMask": "0x1",
464 "BriefDescription": "Counts demand data reads that miss in the L3.",
465 "MSRValue": "0x3fbc000001 ",
466 "Counter": "0,1,2,3",
467 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP",
468 "MSRIndex": "0x1a6,0x1a7",
469 "PublicDescription": "Counts demand data reads that miss in the L3. ",
470 "SampleAfterValue": "100003",
471 "CounterHTOff": "0,1,2,3"
472 },
473 {
474 "Offcore": "1",
475 "EventCode": "0xB7, 0xBB",
476 "UMask": "0x1",
477 "BriefDescription": "Counts demand data reads that miss the L3 and clean or shared data is transferred from remote cache.",
478 "MSRValue": "0x083fc00001 ",
479 "Counter": "0,1,2,3",
480 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
481 "MSRIndex": "0x1a6,0x1a7",
482 "PublicDescription": "Counts demand data reads that miss the L3 and clean or shared data is transferred from remote cache. ",
483 "SampleAfterValue": "100003",
484 "CounterHTOff": "0,1,2,3"
485 },
486 {
487 "Offcore": "1",
488 "EventCode": "0xB7, 0xBB",
489 "UMask": "0x1",
490 "BriefDescription": "Counts demand data reads that miss the L3 and the modified data is transferred from remote cache.",
491 "MSRValue": "0x103fc00001 ",
492 "Counter": "0,1,2,3",
493 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.REMOTE_HITM",
494 "MSRIndex": "0x1a6,0x1a7",
495 "PublicDescription": "Counts demand data reads that miss the L3 and the modified data is transferred from remote cache. ",
496 "SampleAfterValue": "100003",
497 "CounterHTOff": "0,1,2,3"
498 },
499 {
500 "Offcore": "1",
501 "EventCode": "0xB7, 0xBB",
502 "UMask": "0x1",
503 "BriefDescription": "Counts demand data reads that miss the L3 and the data is returned from local or remote dram.",
504 "MSRValue": "0x063fc00001 ",
505 "Counter": "0,1,2,3",
506 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
507 "MSRIndex": "0x1a6,0x1a7",
508 "PublicDescription": "Counts demand data reads that miss the L3 and the data is returned from local or remote dram. ",
509 "SampleAfterValue": "100003",
510 "CounterHTOff": "0,1,2,3"
511 },
512 {
513 "Offcore": "1",
514 "EventCode": "0xB7, 0xBB",
515 "UMask": "0x1",
516 "BriefDescription": "Counts demand data reads that miss the L3 and the data is returned from remote dram.",
517 "MSRValue": "0x063b800001 ",
518 "Counter": "0,1,2,3",
519 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
520 "MSRIndex": "0x1a6,0x1a7",
521 "PublicDescription": "Counts demand data reads that miss the L3 and the data is returned from remote dram. ",
522 "SampleAfterValue": "100003",
523 "CounterHTOff": "0,1,2,3"
524 },
525 {
526 "Offcore": "1",
527 "EventCode": "0xB7, 0xBB",
528 "UMask": "0x1",
529 "BriefDescription": "Counts demand data reads that miss the L3 and the data is returned from local dram.",
530 "MSRValue": "0x0604000001 ",
531 "Counter": "0,1,2,3",
532 "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
533 "MSRIndex": "0x1a6,0x1a7",
534 "PublicDescription": "Counts demand data reads that miss the L3 and the data is returned from local dram. ",
535 "SampleAfterValue": "100003",
536 "CounterHTOff": "0,1,2,3"
537 },
538 {
539 "Offcore": "1",
540 "EventCode": "0xB7, 0xBB",
541 "UMask": "0x1",
542 "BriefDescription": "Counts all demand data writes (RFOs) that miss in the L3.",
543 "MSRValue": "0x3fbc000002 ",
544 "Counter": "0,1,2,3",
545 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.ANY_SNOOP",
546 "MSRIndex": "0x1a6,0x1a7",
547 "PublicDescription": "Counts all demand data writes (RFOs) that miss in the L3. ",
548 "SampleAfterValue": "100003",
549 "CounterHTOff": "0,1,2,3"
550 },
551 {
552 "Offcore": "1",
553 "EventCode": "0xB7, 0xBB",
554 "UMask": "0x1",
555 "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and clean or shared data is transferred from remote cache.",
556 "MSRValue": "0x083fc00002 ",
557 "Counter": "0,1,2,3",
558 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.REMOTE_HIT_FORWARD",
559 "MSRIndex": "0x1a6,0x1a7",
560 "PublicDescription": "Counts all demand data writes (RFOs) that miss the L3 and clean or shared data is transferred from remote cache. ",
561 "SampleAfterValue": "100003",
562 "CounterHTOff": "0,1,2,3"
563 },
564 {
565 "Offcore": "1",
566 "EventCode": "0xB7, 0xBB",
567 "UMask": "0x1",
568 "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the modified data is transferred from remote cache.",
569 "MSRValue": "0x103fc00002 ",
570 "Counter": "0,1,2,3",
571 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.REMOTE_HITM",
572 "MSRIndex": "0x1a6,0x1a7",
573 "PublicDescription": "Counts all demand data writes (RFOs) that miss the L3 and the modified data is transferred from remote cache. ",
574 "SampleAfterValue": "100003",
575 "CounterHTOff": "0,1,2,3"
576 },
577 {
578 "Offcore": "1",
579 "EventCode": "0xB7, 0xBB",
580 "UMask": "0x1",
581 "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from local or remote dram.",
582 "MSRValue": "0x063fc00002 ",
583 "Counter": "0,1,2,3",
584 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
585 "MSRIndex": "0x1a6,0x1a7",
586 "PublicDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from local or remote dram. ",
587 "SampleAfterValue": "100003",
588 "CounterHTOff": "0,1,2,3"
589 },
590 {
591 "Offcore": "1",
592 "EventCode": "0xB7, 0xBB",
593 "UMask": "0x1",
594 "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from remote dram.",
595 "MSRValue": "0x063b800002 ",
596 "Counter": "0,1,2,3",
597 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
598 "MSRIndex": "0x1a6,0x1a7",
599 "PublicDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from remote dram. ",
600 "SampleAfterValue": "100003",
601 "CounterHTOff": "0,1,2,3"
602 },
603 {
604 "Offcore": "1",
605 "EventCode": "0xB7, 0xBB",
606 "UMask": "0x1",
607 "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from local dram.",
608 "MSRValue": "0x0604000002 ",
609 "Counter": "0,1,2,3",
610 "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
611 "MSRIndex": "0x1a6,0x1a7",
612 "PublicDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from local dram. ",
613 "SampleAfterValue": "100003",
614 "CounterHTOff": "0,1,2,3"
615 },
616 {
617 "Offcore": "1",
618 "EventCode": "0xB7, 0xBB",
619 "UMask": "0x1",
620 "BriefDescription": "Counts all demand code reads that miss in the L3.",
621 "MSRValue": "0x3fbc000004 ",
622 "Counter": "0,1,2,3",
623 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP",
624 "MSRIndex": "0x1a6,0x1a7",
625 "PublicDescription": "Counts all demand code reads that miss in the L3. ",
626 "SampleAfterValue": "100003",
627 "CounterHTOff": "0,1,2,3"
628 },
629 {
630 "Offcore": "1",
631 "EventCode": "0xB7, 0xBB",
632 "UMask": "0x1",
633 "BriefDescription": "Counts all demand code reads that miss the L3 and clean or shared data is transferred from remote cache.",
634 "MSRValue": "0x083fc00004 ",
635 "Counter": "0,1,2,3",
636 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.REMOTE_HIT_FORWARD",
637 "MSRIndex": "0x1a6,0x1a7",
638 "PublicDescription": "Counts all demand code reads that miss the L3 and clean or shared data is transferred from remote cache. ",
639 "SampleAfterValue": "100003",
640 "CounterHTOff": "0,1,2,3"
641 },
642 {
643 "Offcore": "1",
644 "EventCode": "0xB7, 0xBB",
645 "UMask": "0x1",
646 "BriefDescription": "Counts all demand code reads that miss the L3 and the modified data is transferred from remote cache.",
647 "MSRValue": "0x103fc00004 ",
648 "Counter": "0,1,2,3",
649 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.REMOTE_HITM",
650 "MSRIndex": "0x1a6,0x1a7",
651 "PublicDescription": "Counts all demand code reads that miss the L3 and the modified data is transferred from remote cache. ",
652 "SampleAfterValue": "100003",
653 "CounterHTOff": "0,1,2,3"
654 },
655 {
656 "Offcore": "1",
657 "EventCode": "0xB7, 0xBB",
658 "UMask": "0x1",
659 "BriefDescription": "Counts all demand code reads that miss the L3 and the data is returned from local or remote dram.",
660 "MSRValue": "0x063fc00004 ",
661 "Counter": "0,1,2,3",
662 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
663 "MSRIndex": "0x1a6,0x1a7",
664 "PublicDescription": "Counts all demand code reads that miss the L3 and the data is returned from local or remote dram. ",
665 "SampleAfterValue": "100003",
666 "CounterHTOff": "0,1,2,3"
667 },
668 {
669 "Offcore": "1",
670 "EventCode": "0xB7, 0xBB",
671 "UMask": "0x1",
672 "BriefDescription": "Counts all demand code reads that miss the L3 and the data is returned from remote dram.",
673 "MSRValue": "0x063b800004 ",
674 "Counter": "0,1,2,3",
675 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
676 "MSRIndex": "0x1a6,0x1a7",
677 "PublicDescription": "Counts all demand code reads that miss the L3 and the data is returned from remote dram. ",
678 "SampleAfterValue": "100003",
679 "CounterHTOff": "0,1,2,3"
680 },
681 {
682 "Offcore": "1",
683 "EventCode": "0xB7, 0xBB",
684 "UMask": "0x1",
685 "BriefDescription": "Counts all demand code reads that miss the L3 and the data is returned from local dram.",
686 "MSRValue": "0x0604000004 ",
687 "Counter": "0,1,2,3",
688 "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
689 "MSRIndex": "0x1a6,0x1a7",
690 "PublicDescription": "Counts all demand code reads that miss the L3 and the data is returned from local dram. ",
691 "SampleAfterValue": "100003",
692 "CounterHTOff": "0,1,2,3"
693 },
694 {
695 "Offcore": "1",
696 "EventCode": "0xB7, 0xBB",
697 "UMask": "0x1",
698 "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss in the L3.",
699 "MSRValue": "0x3fbc000010 ",
700 "Counter": "0,1,2,3",
701 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.ANY_SNOOP",
702 "MSRIndex": "0x1a6,0x1a7",
703 "PublicDescription": "Counts prefetch (that bring data to L2) data reads that miss in the L3. ",
704 "SampleAfterValue": "100003",
705 "CounterHTOff": "0,1,2,3"
706 },
707 {
708 "Offcore": "1",
709 "EventCode": "0xB7, 0xBB",
710 "UMask": "0x1",
711 "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and clean or shared data is transferred from remote cache.",
712 "MSRValue": "0x083fc00010 ",
713 "Counter": "0,1,2,3",
714 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
715 "MSRIndex": "0x1a6,0x1a7",
716 "PublicDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and clean or shared data is transferred from remote cache. ",
717 "SampleAfterValue": "100003",
718 "CounterHTOff": "0,1,2,3"
719 },
720 {
721 "Offcore": "1",
722 "EventCode": "0xB7, 0xBB",
723 "UMask": "0x1",
724 "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the modified data is transferred from remote cache.",
725 "MSRValue": "0x103fc00010 ",
726 "Counter": "0,1,2,3",
727 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.REMOTE_HITM",
728 "MSRIndex": "0x1a6,0x1a7",
729 "PublicDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the modified data is transferred from remote cache. ",
730 "SampleAfterValue": "100003",
731 "CounterHTOff": "0,1,2,3"
732 },
733 {
734 "Offcore": "1",
735 "EventCode": "0xB7, 0xBB",
736 "UMask": "0x1",
737 "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the data is returned from local or remote dram.",
738 "MSRValue": "0x063fc00010 ",
739 "Counter": "0,1,2,3",
740 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
741 "MSRIndex": "0x1a6,0x1a7",
742 "PublicDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the data is returned from local or remote dram. ",
743 "SampleAfterValue": "100003",
744 "CounterHTOff": "0,1,2,3"
745 },
746 {
747 "Offcore": "1",
748 "EventCode": "0xB7, 0xBB",
749 "UMask": "0x1",
750 "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the data is returned from remote dram.",
751 "MSRValue": "0x063b800010 ",
752 "Counter": "0,1,2,3",
753 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
754 "MSRIndex": "0x1a6,0x1a7",
755 "PublicDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the data is returned from remote dram. ",
756 "SampleAfterValue": "100003",
757 "CounterHTOff": "0,1,2,3"
758 },
759 {
760 "Offcore": "1",
761 "EventCode": "0xB7, 0xBB",
762 "UMask": "0x1",
763 "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the data is returned from local dram.",
764 "MSRValue": "0x0604000010 ",
765 "Counter": "0,1,2,3",
766 "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
767 "MSRIndex": "0x1a6,0x1a7",
768 "PublicDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the data is returned from local dram. ",
769 "SampleAfterValue": "100003",
770 "CounterHTOff": "0,1,2,3"
771 },
772 {
773 "Offcore": "1",
774 "EventCode": "0xB7, 0xBB",
775 "UMask": "0x1",
776 "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss in the L3.",
777 "MSRValue": "0x3fbc000020 ",
778 "Counter": "0,1,2,3",
779 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.ANY_SNOOP",
780 "MSRIndex": "0x1a6,0x1a7",
781 "PublicDescription": "Counts all prefetch (that bring data to L2) RFOs that miss in the L3. ",
782 "SampleAfterValue": "100003",
783 "CounterHTOff": "0,1,2,3"
784 },
785 {
786 "Offcore": "1",
787 "EventCode": "0xB7, 0xBB",
788 "UMask": "0x1",
789 "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and clean or shared data is transferred from remote cache.",
790 "MSRValue": "0x083fc00020 ",
791 "Counter": "0,1,2,3",
792 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.REMOTE_HIT_FORWARD",
793 "MSRIndex": "0x1a6,0x1a7",
794 "PublicDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and clean or shared data is transferred from remote cache. ",
795 "SampleAfterValue": "100003",
796 "CounterHTOff": "0,1,2,3"
797 },
798 {
799 "Offcore": "1",
800 "EventCode": "0xB7, 0xBB",
801 "UMask": "0x1",
802 "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the modified data is transferred from remote cache.",
803 "MSRValue": "0x103fc00020 ",
804 "Counter": "0,1,2,3",
805 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.REMOTE_HITM",
806 "MSRIndex": "0x1a6,0x1a7",
807 "PublicDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the modified data is transferred from remote cache. ",
808 "SampleAfterValue": "100003",
809 "CounterHTOff": "0,1,2,3"
810 },
811 {
812 "Offcore": "1",
813 "EventCode": "0xB7, 0xBB",
814 "UMask": "0x1",
815 "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the data is returned from local or remote dram.",
816 "MSRValue": "0x063fc00020 ",
817 "Counter": "0,1,2,3",
818 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
819 "MSRIndex": "0x1a6,0x1a7",
820 "PublicDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the data is returned from local or remote dram. ",
821 "SampleAfterValue": "100003",
822 "CounterHTOff": "0,1,2,3"
823 },
824 {
825 "Offcore": "1",
826 "EventCode": "0xB7, 0xBB",
827 "UMask": "0x1",
828 "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the data is returned from remote dram.",
829 "MSRValue": "0x063b800020 ",
830 "Counter": "0,1,2,3",
831 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
832 "MSRIndex": "0x1a6,0x1a7",
833 "PublicDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the data is returned from remote dram. ",
834 "SampleAfterValue": "100003",
835 "CounterHTOff": "0,1,2,3"
836 },
837 {
838 "Offcore": "1",
839 "EventCode": "0xB7, 0xBB",
840 "UMask": "0x1",
841 "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the data is returned from local dram.",
842 "MSRValue": "0x0604000020 ",
843 "Counter": "0,1,2,3",
844 "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
845 "MSRIndex": "0x1a6,0x1a7",
846 "PublicDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the data is returned from local dram. ",
847 "SampleAfterValue": "100003",
848 "CounterHTOff": "0,1,2,3"
849 },
850 {
851 "Offcore": "1",
852 "EventCode": "0xB7, 0xBB",
853 "UMask": "0x1",
854 "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss in the L3.",
855 "MSRValue": "0x3fbc000080 ",
856 "Counter": "0,1,2,3",
857 "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP",
858 "MSRIndex": "0x1a6,0x1a7",
859 "PublicDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss in the L3. ",
860 "SampleAfterValue": "100003",
861 "CounterHTOff": "0,1,2,3"
862 },
863 {
864 "Offcore": "1",
865 "EventCode": "0xB7, 0xBB",
866 "UMask": "0x1",
867 "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and clean or shared data is transferred from remote cache.",
868 "MSRValue": "0x083fc00080 ",
869 "Counter": "0,1,2,3",
870 "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
871 "MSRIndex": "0x1a6,0x1a7",
872 "PublicDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and clean or shared data is transferred from remote cache. ",
873 "SampleAfterValue": "100003",
874 "CounterHTOff": "0,1,2,3"
875 },
876 {
877 "Offcore": "1",
878 "EventCode": "0xB7, 0xBB",
879 "UMask": "0x1",
880 "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the modified data is transferred from remote cache.",
881 "MSRValue": "0x103fc00080 ",
882 "Counter": "0,1,2,3",
883 "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.REMOTE_HITM",
884 "MSRIndex": "0x1a6,0x1a7",
885 "PublicDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the modified data is transferred from remote cache. ",
886 "SampleAfterValue": "100003",
887 "CounterHTOff": "0,1,2,3"
888 },
889 {
890 "Offcore": "1",
891 "EventCode": "0xB7, 0xBB",
892 "UMask": "0x1",
893 "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the data is returned from local or remote dram.",
894 "MSRValue": "0x063fc00080 ",
895 "Counter": "0,1,2,3",
896 "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
897 "MSRIndex": "0x1a6,0x1a7",
898 "PublicDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the data is returned from local or remote dram. ",
899 "SampleAfterValue": "100003",
900 "CounterHTOff": "0,1,2,3"
901 },
902 {
903 "Offcore": "1",
904 "EventCode": "0xB7, 0xBB",
905 "UMask": "0x1",
906 "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the data is returned from remote dram.",
907 "MSRValue": "0x063b800080 ",
908 "Counter": "0,1,2,3",
909 "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
910 "MSRIndex": "0x1a6,0x1a7",
911 "PublicDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the data is returned from remote dram. ",
912 "SampleAfterValue": "100003",
913 "CounterHTOff": "0,1,2,3"
914 },
915 {
916 "Offcore": "1",
917 "EventCode": "0xB7, 0xBB",
918 "UMask": "0x1",
919 "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the data is returned from local dram.",
920 "MSRValue": "0x0604000080 ",
921 "Counter": "0,1,2,3",
922 "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
923 "MSRIndex": "0x1a6,0x1a7",
924 "PublicDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the data is returned from local dram. ",
925 "SampleAfterValue": "100003",
926 "CounterHTOff": "0,1,2,3"
927 },
928 {
929 "Offcore": "1",
930 "EventCode": "0xB7, 0xBB",
931 "UMask": "0x1",
932 "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss in the L3.",
933 "MSRValue": "0x3fbc000100 ",
934 "Counter": "0,1,2,3",
935 "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.ANY_SNOOP",
936 "MSRIndex": "0x1a6,0x1a7",
937 "PublicDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss in the L3. ",
938 "SampleAfterValue": "100003",
939 "CounterHTOff": "0,1,2,3"
940 },
941 {
942 "Offcore": "1",
943 "EventCode": "0xB7, 0xBB",
944 "UMask": "0x1",
945 "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and clean or shared data is transferred from remote cache.",
946 "MSRValue": "0x083fc00100 ",
947 "Counter": "0,1,2,3",
948 "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.REMOTE_HIT_FORWARD",
949 "MSRIndex": "0x1a6,0x1a7",
950 "PublicDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and clean or shared data is transferred from remote cache. ",
951 "SampleAfterValue": "100003",
952 "CounterHTOff": "0,1,2,3"
953 },
954 {
955 "Offcore": "1",
956 "EventCode": "0xB7, 0xBB",
957 "UMask": "0x1",
958 "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the modified data is transferred from remote cache.",
959 "MSRValue": "0x103fc00100 ",
960 "Counter": "0,1,2,3",
961 "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.REMOTE_HITM",
962 "MSRIndex": "0x1a6,0x1a7",
963 "PublicDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the modified data is transferred from remote cache. ",
964 "SampleAfterValue": "100003",
965 "CounterHTOff": "0,1,2,3"
966 },
967 {
968 "Offcore": "1",
969 "EventCode": "0xB7, 0xBB",
970 "UMask": "0x1",
971 "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the data is returned from local or remote dram.",
972 "MSRValue": "0x063fc00100 ",
973 "Counter": "0,1,2,3",
974 "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
975 "MSRIndex": "0x1a6,0x1a7",
976 "PublicDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the data is returned from local or remote dram. ",
977 "SampleAfterValue": "100003",
978 "CounterHTOff": "0,1,2,3"
979 },
980 {
981 "Offcore": "1",
982 "EventCode": "0xB7, 0xBB",
983 "UMask": "0x1",
984 "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the data is returned from remote dram.",
985 "MSRValue": "0x063b800100 ",
986 "Counter": "0,1,2,3",
987 "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
988 "MSRIndex": "0x1a6,0x1a7",
989 "PublicDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the data is returned from remote dram. ",
990 "SampleAfterValue": "100003",
991 "CounterHTOff": "0,1,2,3"
992 },
993 {
994 "Offcore": "1",
995 "EventCode": "0xB7, 0xBB",
996 "UMask": "0x1",
997 "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the data is returned from local dram.",
998 "MSRValue": "0x0604000100 ",
999 "Counter": "0,1,2,3",
1000 "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
1001 "MSRIndex": "0x1a6,0x1a7",
1002 "PublicDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the data is returned from local dram. ",
1003 "SampleAfterValue": "100003",
1004 "CounterHTOff": "0,1,2,3"
1005 },
1006 {
1007 "Offcore": "1",
1008 "EventCode": "0xB7, 0xBB",
1009 "UMask": "0x1",
1010 "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss in the L3.",
1011 "MSRValue": "0x3fbc000400 ",
1012 "Counter": "0,1,2,3",
1013 "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.ANY_SNOOP",
1014 "MSRIndex": "0x1a6,0x1a7",
1015 "PublicDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss in the L3. ",
1016 "SampleAfterValue": "100003",
1017 "CounterHTOff": "0,1,2,3"
1018 },
1019 {
1020 "Offcore": "1",
1021 "EventCode": "0xB7, 0xBB",
1022 "UMask": "0x1",
1023 "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and clean or shared data is transferred from remote cache.",
1024 "MSRValue": "0x083fc00400 ",
1025 "Counter": "0,1,2,3",
1026 "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.REMOTE_HIT_FORWARD",
1027 "MSRIndex": "0x1a6,0x1a7",
1028 "PublicDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and clean or shared data is transferred from remote cache. ",
1029 "SampleAfterValue": "100003",
1030 "CounterHTOff": "0,1,2,3"
1031 },
1032 {
1033 "Offcore": "1",
1034 "EventCode": "0xB7, 0xBB",
1035 "UMask": "0x1",
1036 "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the modified data is transferred from remote cache.",
1037 "MSRValue": "0x103fc00400 ",
1038 "Counter": "0,1,2,3",
1039 "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.REMOTE_HITM",
1040 "MSRIndex": "0x1a6,0x1a7",
1041 "PublicDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the modified data is transferred from remote cache. ",
1042 "SampleAfterValue": "100003",
1043 "CounterHTOff": "0,1,2,3"
1044 },
1045 {
1046 "Offcore": "1",
1047 "EventCode": "0xB7, 0xBB",
1048 "UMask": "0x1",
1049 "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the data is returned from local or remote dram.",
1050 "MSRValue": "0x063fc00400 ",
1051 "Counter": "0,1,2,3",
1052 "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.SNOOP_MISS_OR_NO_FWD",
1053 "MSRIndex": "0x1a6,0x1a7",
1054 "PublicDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the data is returned from local or remote dram. ",
1055 "SampleAfterValue": "100003",
1056 "CounterHTOff": "0,1,2,3"
1057 },
1058 {
1059 "Offcore": "1",
1060 "EventCode": "0xB7, 0xBB",
1061 "UMask": "0x1",
1062 "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the data is returned from remote dram.",
1063 "MSRValue": "0x063b800400 ",
1064 "Counter": "0,1,2,3",
1065 "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
1066 "MSRIndex": "0x1a6,0x1a7",
1067 "PublicDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the data is returned from remote dram. ",
1068 "SampleAfterValue": "100003",
1069 "CounterHTOff": "0,1,2,3"
1070 },
1071 {
1072 "Offcore": "1",
1073 "EventCode": "0xB7, 0xBB",
1074 "UMask": "0x1",
1075 "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the data is returned from local dram.",
1076 "MSRValue": "0x0604000400 ",
1077 "Counter": "0,1,2,3",
1078 "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
1079 "MSRIndex": "0x1a6,0x1a7",
1080 "PublicDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the data is returned from local dram. ",
1081 "SampleAfterValue": "100003",
1082 "CounterHTOff": "0,1,2,3"
1083 },
1084 {
1085 "Offcore": "1",
1086 "EventCode": "0xB7, 0xBB",
1087 "UMask": "0x1",
1088 "BriefDescription": "Counts all prefetch data reads that miss in the L3.",
1089 "MSRValue": "0x3fbc000490 ",
1090 "Counter": "0,1,2,3",
1091 "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP",
1092 "MSRIndex": "0x1a6,0x1a7",
1093 "PublicDescription": "Counts all prefetch data reads that miss in the L3. ",
1094 "SampleAfterValue": "100003",
1095 "CounterHTOff": "0,1,2,3"
1096 },
1097 {
1098 "Offcore": "1",
1099 "EventCode": "0xB7, 0xBB",
1100 "UMask": "0x1",
1101 "BriefDescription": "Counts all prefetch data reads that miss the L3 and clean or shared data is transferred from remote cache.",
1102 "MSRValue": "0x083fc00490 ",
1103 "Counter": "0,1,2,3",
1104 "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
1105 "MSRIndex": "0x1a6,0x1a7",
1106 "PublicDescription": "Counts all prefetch data reads that miss the L3 and clean or shared data is transferred from remote cache. ",
1107 "SampleAfterValue": "100003",
1108 "CounterHTOff": "0,1,2,3"
1109 },
1110 {
1111 "Offcore": "1",
1112 "EventCode": "0xB7, 0xBB",
1113 "UMask": "0x1",
1114 "BriefDescription": "Counts all prefetch data reads that miss the L3 and the modified data is transferred from remote cache.",
1115 "MSRValue": "0x103fc00490 ",
1116 "Counter": "0,1,2,3",
1117 "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.REMOTE_HITM",
1118 "MSRIndex": "0x1a6,0x1a7",
1119 "PublicDescription": "Counts all prefetch data reads that miss the L3 and the modified data is transferred from remote cache. ",
1120 "SampleAfterValue": "100003",
1121 "CounterHTOff": "0,1,2,3"
1122 },
1123 {
1124 "Offcore": "1",
1125 "EventCode": "0xB7, 0xBB",
1126 "UMask": "0x1",
1127 "BriefDescription": "Counts all prefetch data reads that miss the L3 and the data is returned from local or remote dram.",
1128 "MSRValue": "0x063fc00490 ",
1129 "Counter": "0,1,2,3",
1130 "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
1131 "MSRIndex": "0x1a6,0x1a7",
1132 "PublicDescription": "Counts all prefetch data reads that miss the L3 and the data is returned from local or remote dram. ",
1133 "SampleAfterValue": "100003",
1134 "CounterHTOff": "0,1,2,3"
1135 },
1136 {
1137 "Offcore": "1",
1138 "EventCode": "0xB7, 0xBB",
1139 "UMask": "0x1",
1140 "BriefDescription": "Counts all prefetch data reads that miss the L3 and the data is returned from remote dram.",
1141 "MSRValue": "0x063b800490 ",
1142 "Counter": "0,1,2,3",
1143 "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
1144 "MSRIndex": "0x1a6,0x1a7",
1145 "PublicDescription": "Counts all prefetch data reads that miss the L3 and the data is returned from remote dram. ",
1146 "SampleAfterValue": "100003",
1147 "CounterHTOff": "0,1,2,3"
1148 },
1149 {
1150 "Offcore": "1",
1151 "EventCode": "0xB7, 0xBB",
1152 "UMask": "0x1",
1153 "BriefDescription": "Counts all prefetch data reads that miss the L3 and the data is returned from local dram.",
1154 "MSRValue": "0x0604000490 ",
1155 "Counter": "0,1,2,3",
1156 "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
1157 "MSRIndex": "0x1a6,0x1a7",
1158 "PublicDescription": "Counts all prefetch data reads that miss the L3 and the data is returned from local dram. ",
1159 "SampleAfterValue": "100003",
1160 "CounterHTOff": "0,1,2,3"
1161 },
1162 {
1163 "Offcore": "1",
1164 "EventCode": "0xB7, 0xBB",
1165 "UMask": "0x1",
1166 "BriefDescription": "Counts prefetch RFOs that miss in the L3.",
1167 "MSRValue": "0x3fbc000120 ",
1168 "Counter": "0,1,2,3",
1169 "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.ANY_SNOOP",
1170 "MSRIndex": "0x1a6,0x1a7",
1171 "PublicDescription": "Counts prefetch RFOs that miss in the L3. ",
1172 "SampleAfterValue": "100003",
1173 "CounterHTOff": "0,1,2,3"
1174 },
1175 {
1176 "Offcore": "1",
1177 "EventCode": "0xB7, 0xBB",
1178 "UMask": "0x1",
1179 "BriefDescription": "Counts prefetch RFOs that miss the L3 and clean or shared data is transferred from remote cache.",
1180 "MSRValue": "0x083fc00120 ",
1181 "Counter": "0,1,2,3",
1182 "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD",
1183 "MSRIndex": "0x1a6,0x1a7",
1184 "PublicDescription": "Counts prefetch RFOs that miss the L3 and clean or shared data is transferred from remote cache. ",
1185 "SampleAfterValue": "100003",
1186 "CounterHTOff": "0,1,2,3"
1187 },
1188 {
1189 "Offcore": "1",
1190 "EventCode": "0xB7, 0xBB",
1191 "UMask": "0x1",
1192 "BriefDescription": "Counts prefetch RFOs that miss the L3 and the modified data is transferred from remote cache.",
1193 "MSRValue": "0x103fc00120 ",
1194 "Counter": "0,1,2,3",
1195 "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.REMOTE_HITM",
1196 "MSRIndex": "0x1a6,0x1a7",
1197 "PublicDescription": "Counts prefetch RFOs that miss the L3 and the modified data is transferred from remote cache. ",
1198 "SampleAfterValue": "100003",
1199 "CounterHTOff": "0,1,2,3"
1200 },
1201 {
1202 "Offcore": "1",
1203 "EventCode": "0xB7, 0xBB",
1204 "UMask": "0x1",
1205 "BriefDescription": "Counts prefetch RFOs that miss the L3 and the data is returned from local or remote dram.",
1206 "MSRValue": "0x063fc00120 ",
1207 "Counter": "0,1,2,3",
1208 "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
1209 "MSRIndex": "0x1a6,0x1a7",
1210 "PublicDescription": "Counts prefetch RFOs that miss the L3 and the data is returned from local or remote dram. ",
1211 "SampleAfterValue": "100003",
1212 "CounterHTOff": "0,1,2,3"
1213 },
1214 {
1215 "Offcore": "1",
1216 "EventCode": "0xB7, 0xBB",
1217 "UMask": "0x1",
1218 "BriefDescription": "Counts prefetch RFOs that miss the L3 and the data is returned from remote dram.",
1219 "MSRValue": "0x063b800120 ",
1220 "Counter": "0,1,2,3",
1221 "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
1222 "MSRIndex": "0x1a6,0x1a7",
1223 "PublicDescription": "Counts prefetch RFOs that miss the L3 and the data is returned from remote dram. ",
1224 "SampleAfterValue": "100003",
1225 "CounterHTOff": "0,1,2,3"
1226 },
1227 {
1228 "Offcore": "1",
1229 "EventCode": "0xB7, 0xBB",
1230 "UMask": "0x1",
1231 "BriefDescription": "Counts prefetch RFOs that miss the L3 and the data is returned from local dram.",
1232 "MSRValue": "0x0604000120 ",
1233 "Counter": "0,1,2,3",
1234 "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
1235 "MSRIndex": "0x1a6,0x1a7",
1236 "PublicDescription": "Counts prefetch RFOs that miss the L3 and the data is returned from local dram. ",
1237 "SampleAfterValue": "100003",
1238 "CounterHTOff": "0,1,2,3"
1239 },
1240 {
1241 "Offcore": "1",
1242 "EventCode": "0xB7, 0xBB",
1243 "UMask": "0x1",
1244 "BriefDescription": "Counts all demand & prefetch data reads that miss in the L3.",
1245 "MSRValue": "0x3fbc000491 ",
1246 "Counter": "0,1,2,3",
1247 "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.ANY_SNOOP",
1248 "MSRIndex": "0x1a6,0x1a7",
1249 "PublicDescription": "Counts all demand & prefetch data reads that miss in the L3. ",
1250 "SampleAfterValue": "100003",
1251 "CounterHTOff": "0,1,2,3"
1252 },
1253 {
1254 "Offcore": "1",
1255 "EventCode": "0xB7, 0xBB",
1256 "UMask": "0x1",
1257 "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and clean or shared data is transferred from remote cache.",
1258 "MSRValue": "0x083fc00491 ",
1259 "Counter": "0,1,2,3",
1260 "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
1261 "MSRIndex": "0x1a6,0x1a7",
1262 "PublicDescription": "Counts all demand & prefetch data reads that miss the L3 and clean or shared data is transferred from remote cache. ",
1263 "SampleAfterValue": "100003",
1264 "CounterHTOff": "0,1,2,3"
1265 },
1266 {
1267 "Offcore": "1",
1268 "EventCode": "0xB7, 0xBB",
1269 "UMask": "0x1",
1270 "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the modified data is transferred from remote cache.",
1271 "MSRValue": "0x103fc00491 ",
1272 "Counter": "0,1,2,3",
1273 "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.REMOTE_HITM",
1274 "MSRIndex": "0x1a6,0x1a7",
1275 "PublicDescription": "Counts all demand & prefetch data reads that miss the L3 and the modified data is transferred from remote cache. ",
1276 "SampleAfterValue": "100003",
1277 "CounterHTOff": "0,1,2,3"
1278 },
1279 {
1280 "Offcore": "1",
1281 "EventCode": "0xB7, 0xBB",
1282 "UMask": "0x1",
1283 "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from local or remote dram.",
1284 "MSRValue": "0x063fc00491 ",
1285 "Counter": "0,1,2,3",
1286 "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
1287 "MSRIndex": "0x1a6,0x1a7",
1288 "PublicDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from local or remote dram. ",
1289 "SampleAfterValue": "100003",
1290 "CounterHTOff": "0,1,2,3"
1291 },
1292 {
1293 "Offcore": "1",
1294 "EventCode": "0xB7, 0xBB",
1295 "UMask": "0x1",
1296 "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from remote dram.",
1297 "MSRValue": "0x063b800491 ",
1298 "Counter": "0,1,2,3",
1299 "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
1300 "MSRIndex": "0x1a6,0x1a7",
1301 "PublicDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from remote dram. ",
1302 "SampleAfterValue": "100003",
1303 "CounterHTOff": "0,1,2,3"
1304 },
1305 {
1306 "Offcore": "1",
1307 "EventCode": "0xB7, 0xBB",
1308 "UMask": "0x1",
1309 "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from local dram.",
1310 "MSRValue": "0x0604000491 ",
1311 "Counter": "0,1,2,3",
1312 "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
1313 "MSRIndex": "0x1a6,0x1a7",
1314 "PublicDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from local dram. ",
1315 "SampleAfterValue": "100003",
1316 "CounterHTOff": "0,1,2,3"
1317 },
1318 {
1319 "Offcore": "1",
1320 "EventCode": "0xB7, 0xBB",
1321 "UMask": "0x1",
1322 "BriefDescription": "Counts all demand & prefetch RFOs that miss in the L3.",
1323 "MSRValue": "0x3fbc000122 ",
1324 "Counter": "0,1,2,3",
1325 "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.ANY_SNOOP",
1326 "MSRIndex": "0x1a6,0x1a7",
1327 "PublicDescription": "Counts all demand & prefetch RFOs that miss in the L3. ",
1328 "SampleAfterValue": "100003",
1329 "CounterHTOff": "0,1,2,3"
1330 },
1331 {
1332 "Offcore": "1",
1333 "EventCode": "0xB7, 0xBB",
1334 "UMask": "0x1",
1335 "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and clean or shared data is transferred from remote cache.",
1336 "MSRValue": "0x083fc00122 ",
1337 "Counter": "0,1,2,3",
1338 "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD",
1339 "MSRIndex": "0x1a6,0x1a7",
1340 "PublicDescription": "Counts all demand & prefetch RFOs that miss the L3 and clean or shared data is transferred from remote cache. ",
1341 "SampleAfterValue": "100003",
1342 "CounterHTOff": "0,1,2,3"
1343 },
1344 {
1345 "Offcore": "1",
1346 "EventCode": "0xB7, 0xBB",
1347 "UMask": "0x1",
1348 "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the modified data is transferred from remote cache.",
1349 "MSRValue": "0x103fc00122 ",
1350 "Counter": "0,1,2,3",
1351 "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.REMOTE_HITM",
1352 "MSRIndex": "0x1a6,0x1a7",
1353 "PublicDescription": "Counts all demand & prefetch RFOs that miss the L3 and the modified data is transferred from remote cache. ",
1354 "SampleAfterValue": "100003",
1355 "CounterHTOff": "0,1,2,3"
1356 },
1357 {
1358 "Offcore": "1",
1359 "EventCode": "0xB7, 0xBB",
1360 "UMask": "0x1",
1361 "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from local or remote dram.",
1362 "MSRValue": "0x063fc00122 ",
1363 "Counter": "0,1,2,3",
1364 "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
1365 "MSRIndex": "0x1a6,0x1a7",
1366 "PublicDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from local or remote dram. ",
1367 "SampleAfterValue": "100003",
1368 "CounterHTOff": "0,1,2,3"
1369 },
1370 {
1371 "Offcore": "1",
1372 "EventCode": "0xB7, 0xBB",
1373 "UMask": "0x1",
1374 "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from remote dram.",
1375 "MSRValue": "0x063b800122 ",
1376 "Counter": "0,1,2,3",
1377 "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
1378 "MSRIndex": "0x1a6,0x1a7",
1379 "PublicDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from remote dram. ",
1380 "SampleAfterValue": "100003",
1381 "CounterHTOff": "0,1,2,3"
1382 },
1383 {
1384 "Offcore": "1",
1385 "EventCode": "0xB7, 0xBB",
1386 "UMask": "0x1",
1387 "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from local dram.",
1388 "MSRValue": "0x0604000122 ",
1389 "Counter": "0,1,2,3",
1390 "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
1391 "MSRIndex": "0x1a6,0x1a7",
1392 "PublicDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from local dram.",
1393 "SampleAfterValue": "100003",
1394 "CounterHTOff": "0,1,2,3"
1395 }
1396]
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/other.json b/tools/perf/pmu-events/arch/x86/skylakex/other.json
new file mode 100644
index 000000000000..70243b0b0586
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylakex/other.json
@@ -0,0 +1,72 @@
1[
2 {
3 "EventCode": "0x28",
4 "UMask": "0x7",
5 "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the Non-AVX turbo schedule.",
6 "Counter": "0,1,2,3",
7 "EventName": "CORE_POWER.LVL0_TURBO_LICENSE",
8 "PublicDescription": "Core cycles where the core was running with power-delivery for baseline license level 0. This includes non-AVX codes, SSE, AVX 128-bit, and low-current AVX 256-bit codes.",
9 "SampleAfterValue": "200003",
10 "CounterHTOff": "0,1,2,3,4,5,6,7"
11 },
12 {
13 "EventCode": "0x28",
14 "UMask": "0x18",
15 "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX2 turbo schedule.",
16 "Counter": "0,1,2,3",
17 "EventName": "CORE_POWER.LVL1_TURBO_LICENSE",
18 "PublicDescription": "Core cycles where the core was running with power-delivery for license level 1. This includes high current AVX 256-bit instructions as well as low current AVX 512-bit instructions.",
19 "SampleAfterValue": "200003",
20 "CounterHTOff": "0,1,2,3,4,5,6,7"
21 },
22 {
23 "EventCode": "0x28",
24 "UMask": "0x20",
25 "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX512 turbo schedule.",
26 "Counter": "0,1,2,3",
27 "EventName": "CORE_POWER.LVL2_TURBO_LICENSE",
28 "PublicDescription": "Core cycles where the core was running with power-delivery for license level 2 (introduced in Skylake Server michroarchtecture). This includes high current AVX 512-bit instructions.",
29 "SampleAfterValue": "200003",
30 "CounterHTOff": "0,1,2,3,4,5,6,7"
31 },
32 {
33 "EventCode": "0x28",
34 "UMask": "0x40",
35 "BriefDescription": "Core cycles the core was throttled due to a pending power level request.",
36 "Counter": "0,1,2,3",
37 "EventName": "CORE_POWER.THROTTLE",
38 "PublicDescription": "Core cycles the out-of-order engine was throttled due to a pending power level request.",
39 "SampleAfterValue": "200003",
40 "CounterHTOff": "0,1,2,3,4,5,6,7"
41 },
42 {
43 "EventCode": "0xCB",
44 "UMask": "0x1",
45 "BriefDescription": "Number of hardware interrupts received by the processor.",
46 "Counter": "0,1,2,3",
47 "EventName": "HW_INTERRUPTS.RECEIVED",
48 "PublicDescription": "Counts the number of hardware interruptions received by the processor.",
49 "SampleAfterValue": "203",
50 "CounterHTOff": "0,1,2,3,4,5,6,7"
51 },
52 {
53 "EventCode": "0xFE",
54 "UMask": "0x2",
55 "BriefDescription": "Counts number of cache lines that are allocated and written back to L3 with the intention that they are more likely to be reused shortly",
56 "Counter": "0,1,2,3",
57 "EventName": "IDI_MISC.WB_UPGRADE",
58 "PublicDescription": "Counts number of cache lines that are allocated and written back to L3 with the intention that they are more likely to be reused shortly.",
59 "SampleAfterValue": "100003",
60 "CounterHTOff": "0,1,2,3,4,5,6,7"
61 },
62 {
63 "EventCode": "0xFE",
64 "UMask": "0x4",
65 "BriefDescription": "Counts number of cache lines that are dropped and not written back to L3 as they are deemed to be less likely to be reused shortly",
66 "Counter": "0,1,2,3",
67 "EventName": "IDI_MISC.WB_DOWNGRADE",
68 "PublicDescription": "Counts number of cache lines that are dropped and not written back to L3 as they are deemed to be less likely to be reused shortly.",
69 "SampleAfterValue": "100003",
70 "CounterHTOff": "0,1,2,3,4,5,6,7"
71 }
72]
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/pipeline.json b/tools/perf/pmu-events/arch/x86/skylakex/pipeline.json
new file mode 100644
index 000000000000..0895d1e52a4a
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylakex/pipeline.json
@@ -0,0 +1,950 @@
1[
2 {
3 "EventCode": "0x00",
4 "UMask": "0x1",
5 "BriefDescription": "Instructions retired from execution.",
6 "Counter": "Fixed counter 1",
7 "EventName": "INST_RETIRED.ANY",
8 "PublicDescription": "Counts the number of instructions retired from execution. For instructions that consist of multiple micro-ops, Counts the retirement of the last micro-op of the instruction. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. INST_RETIRED.ANY_P is counted by a programmable counter and it is an architectural performance event. Counting: Faulting executions of GETSEC/VM entry/VM Exit/MWait will not count as retired instructions.",
9 "SampleAfterValue": "2000003",
10 "CounterHTOff": "Fixed counter 1"
11 },
12 {
13 "EventCode": "0x00",
14 "UMask": "0x2",
15 "BriefDescription": "Core cycles when the thread is not in halt state",
16 "Counter": "Fixed counter 2",
17 "EventName": "CPU_CLK_UNHALTED.THREAD",
18 "PublicDescription": "Counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events.",
19 "SampleAfterValue": "2000003",
20 "CounterHTOff": "Fixed counter 2"
21 },
22 {
23 "EventCode": "0x00",
24 "UMask": "0x2",
25 "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
26 "Counter": "Fixed counter 2",
27 "EventName": "CPU_CLK_UNHALTED.THREAD_ANY",
28 "AnyThread": "1",
29 "SampleAfterValue": "2000003",
30 "CounterHTOff": "Fixed counter 2"
31 },
32 {
33 "EventCode": "0x00",
34 "UMask": "0x3",
35 "BriefDescription": "Reference cycles when the core is not in halt state.",
36 "Counter": "Fixed counter 3",
37 "EventName": "CPU_CLK_UNHALTED.REF_TSC",
38 "PublicDescription": "Counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. Note: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.",
39 "SampleAfterValue": "2000003",
40 "CounterHTOff": "Fixed counter 3"
41 },
42 {
43 "EventCode": "0x03",
44 "UMask": "0x2",
45 "BriefDescription": "Loads blocked by overlapping with store buffer that cannot be forwarded .",
46 "Counter": "0,1,2,3",
47 "EventName": "LD_BLOCKS.STORE_FORWARD",
48 "PublicDescription": "Counts how many times the load operation got the true Block-on-Store blocking code preventing store forwarding. This includes cases when:a. preceding store conflicts with the load (incomplete overlap),b. store forwarding is impossible due to u-arch limitations,c. preceding lock RMW operations are not forwarded,d. store has the no-forward bit set (uncacheable/page-split/masked stores),e. all-blocking stores are used (mostly, fences and port I/O), and others.The most common case is a load blocked due to its address range overlapping with a preceding smaller uncompleted store. Note: This event does not take into account cases of out-of-SW-control (for example, SbTailHit), unknown physical STA, and cases of blocking loads on store due to being non-WB memory type or a lock. These cases are covered by other events. See the table of not supported store forwards in the Optimization Guide.",
49 "SampleAfterValue": "100003",
50 "CounterHTOff": "0,1,2,3,4,5,6,7"
51 },
52 {
53 "EventCode": "0x03",
54 "UMask": "0x8",
55 "BriefDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use",
56 "Counter": "0,1,2,3",
57 "EventName": "LD_BLOCKS.NO_SR",
58 "PublicDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
59 "SampleAfterValue": "100003",
60 "CounterHTOff": "0,1,2,3,4,5,6,7"
61 },
62 {
63 "EventCode": "0x07",
64 "UMask": "0x1",
65 "BriefDescription": "False dependencies in MOB due to partial compare on address.",
66 "Counter": "0,1,2,3",
67 "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
68 "PublicDescription": "Counts false dependencies in MOB when the partial comparison upon loose net check and dependency was resolved by the Enhanced Loose net mechanism. This may not result in high performance penalties. Loose net checks can fail when loads and stores are 4k aliased.",
69 "SampleAfterValue": "100003",
70 "CounterHTOff": "0,1,2,3,4,5,6,7"
71 },
72 {
73 "EventCode": "0x0D",
74 "UMask": "0x1",
75 "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for this thread (e.g. misprediction or memory nuke)",
76 "Counter": "0,1,2,3",
77 "EventName": "INT_MISC.RECOVERY_CYCLES",
78 "PublicDescription": "Core cycles the Resource allocator was stalled due to recovery from an earlier branch misprediction or machine clear event.",
79 "SampleAfterValue": "2000003",
80 "CounterHTOff": "0,1,2,3,4,5,6,7"
81 },
82 {
83 "EventCode": "0x0D",
84 "UMask": "0x1",
85 "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
86 "Counter": "0,1,2,3",
87 "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
88 "AnyThread": "1",
89 "SampleAfterValue": "2000003",
90 "CounterHTOff": "0,1,2,3,4,5,6,7"
91 },
92 {
93 "EventCode": "0x0D",
94 "UMask": "0x80",
95 "BriefDescription": "Cycles the issue-stage is waiting for front-end to fetch from resteered path following branch misprediction or machine clear events.",
96 "Counter": "0,1,2,3",
97 "EventName": "INT_MISC.CLEAR_RESTEER_CYCLES",
98 "SampleAfterValue": "2000003",
99 "CounterHTOff": "0,1,2,3,4,5,6,7"
100 },
101 {
102 "EventCode": "0x0E",
103 "UMask": "0x1",
104 "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS)",
105 "Counter": "0,1,2,3",
106 "EventName": "UOPS_ISSUED.ANY",
107 "PublicDescription": "Counts the number of uops that the Resource Allocation Table (RAT) issues to the Reservation Station (RS).",
108 "SampleAfterValue": "2000003",
109 "CounterHTOff": "0,1,2,3,4,5,6,7"
110 },
111 {
112 "Invert": "1",
113 "EventCode": "0x0E",
114 "UMask": "0x1",
115 "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread",
116 "Counter": "0,1,2,3",
117 "EventName": "UOPS_ISSUED.STALL_CYCLES",
118 "CounterMask": "1",
119 "PublicDescription": "Counts cycles during which the Resource Allocation Table (RAT) does not issue any Uops to the reservation station (RS) for the current thread.",
120 "SampleAfterValue": "2000003",
121 "CounterHTOff": "0,1,2,3,4,5,6,7"
122 },
123 {
124 "EventCode": "0x0E",
125 "UMask": "0x2",
126 "BriefDescription": "Uops inserted at issue-stage in order to preserve upper bits of vector registers.",
127 "Counter": "0,1,2,3",
128 "EventName": "UOPS_ISSUED.VECTOR_WIDTH_MISMATCH",
129 "PublicDescription": "Counts the number of Blend Uops issued by the Resource Allocation Table (RAT) to the reservation station (RS) in order to preserve upper bits of vector registers. Starting with the Skylake microarchitecture, these Blend uops are needed since every Intel SSE instruction executed in Dirty Upper State needs to preserve bits 128-255 of the destination register. For more information, refer to \u201cMixing Intel AVX and Intel SSE Code\u201d section of the Optimization Guide.",
130 "SampleAfterValue": "2000003",
131 "CounterHTOff": "0,1,2,3,4,5,6,7"
132 },
133 {
134 "EventCode": "0x0E",
135 "UMask": "0x20",
136 "BriefDescription": "Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
137 "Counter": "0,1,2,3",
138 "EventName": "UOPS_ISSUED.SLOW_LEA",
139 "SampleAfterValue": "2000003",
140 "CounterHTOff": "0,1,2,3,4,5,6,7"
141 },
142 {
143 "EventCode": "0x14",
144 "UMask": "0x1",
145 "BriefDescription": "Cycles when divide unit is busy executing divide or square root operations. Accounts for integer and floating-point operations.",
146 "Counter": "0,1,2,3",
147 "EventName": "ARITH.DIVIDER_ACTIVE",
148 "CounterMask": "1",
149 "SampleAfterValue": "2000003",
150 "CounterHTOff": "0,1,2,3,4,5,6,7"
151 },
152 {
153 "EventCode": "0x3C",
154 "UMask": "0x0",
155 "BriefDescription": "Thread cycles when thread is not in halt state",
156 "Counter": "0,1,2,3",
157 "EventName": "CPU_CLK_UNHALTED.THREAD_P",
158 "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.",
159 "SampleAfterValue": "2000003",
160 "CounterHTOff": "0,1,2,3,4,5,6,7"
161 },
162 {
163 "EventCode": "0x3C",
164 "UMask": "0x0",
165 "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
166 "Counter": "0,1,2,3",
167 "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
168 "AnyThread": "1",
169 "SampleAfterValue": "2000003",
170 "CounterHTOff": "0,1,2,3,4,5,6,7"
171 },
172 {
173 "EdgeDetect": "1",
174 "EventCode": "0x3C",
175 "UMask": "0x0",
176 "BriefDescription": "Counts when there is a transition from ring 1, 2 or 3 to ring 0.",
177 "Counter": "0,1,2,3",
178 "EventName": "CPU_CLK_UNHALTED.RING0_TRANS",
179 "CounterMask": "1",
180 "PublicDescription": "Counts when the Current Privilege Level (CPL) transitions from ring 1, 2 or 3 to ring 0 (Kernel).",
181 "SampleAfterValue": "100007",
182 "CounterHTOff": "0,1,2,3,4,5,6,7"
183 },
184 {
185 "EventCode": "0x3C",
186 "UMask": "0x1",
187 "BriefDescription": "Core crystal clock cycles when the thread is unhalted.",
188 "Counter": "0,1,2,3",
189 "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
190 "SampleAfterValue": "2503",
191 "CounterHTOff": "0,1,2,3,4,5,6,7"
192 },
193 {
194 "EventCode": "0x3C",
195 "UMask": "0x1",
196 "BriefDescription": "Core crystal clock cycles when at least one thread on the physical core is unhalted.",
197 "Counter": "0,1,2,3",
198 "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
199 "AnyThread": "1",
200 "SampleAfterValue": "2503",
201 "CounterHTOff": "0,1,2,3,4,5,6,7"
202 },
203 {
204 "EventCode": "0x3C",
205 "UMask": "0x1",
206 "BriefDescription": "Core crystal clock cycles when the thread is unhalted.",
207 "Counter": "0,1,2,3",
208 "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
209 "SampleAfterValue": "2503",
210 "CounterHTOff": "0,1,2,3,4,5,6,7"
211 },
212 {
213 "EventCode": "0x3C",
214 "UMask": "0x1",
215 "BriefDescription": "Core crystal clock cycles when at least one thread on the physical core is unhalted.",
216 "Counter": "0,1,2,3",
217 "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
218 "AnyThread": "1",
219 "SampleAfterValue": "2503",
220 "CounterHTOff": "0,1,2,3,4,5,6,7"
221 },
222 {
223 "EventCode": "0x3C",
224 "UMask": "0x2",
225 "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.",
226 "Counter": "0,1,2,3",
227 "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
228 "SampleAfterValue": "2000003",
229 "CounterHTOff": "0,1,2,3,4,5,6,7"
230 },
231 {
232 "EventCode": "0x3C",
233 "UMask": "0x2",
234 "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.",
235 "Counter": "0,1,2,3",
236 "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
237 "SampleAfterValue": "2503",
238 "CounterHTOff": "0,1,2,3,4,5,6,7"
239 },
240 {
241 "EventCode": "0x4C",
242 "UMask": "0x1",
243 "BriefDescription": "Demand load dispatches that hit L1D fill buffer (FB) allocated for software prefetch.",
244 "Counter": "0,1,2,3",
245 "EventName": "LOAD_HIT_PRE.SW_PF",
246 "PublicDescription": "Counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the software prefetch. It can also be incremented by some lock instructions. So it should only be used with profiling so that the locks can be excluded by ASM (Assembly File) inspection of the nearby instructions.",
247 "SampleAfterValue": "100003",
248 "CounterHTOff": "0,1,2,3,4,5,6,7"
249 },
250 {
251 "EventCode": "0x5E",
252 "UMask": "0x1",
253 "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
254 "Counter": "0,1,2,3",
255 "EventName": "RS_EVENTS.EMPTY_CYCLES",
256 "PublicDescription": "Counts cycles during which the reservation station (RS) is empty for the thread.; Note: In ST-mode, not active thread should drive 0. This is usually caused by severely costly branch mispredictions, or allocator/FE issues.",
257 "SampleAfterValue": "2000003",
258 "CounterHTOff": "0,1,2,3,4,5,6,7"
259 },
260 {
261 "EdgeDetect": "1",
262 "Invert": "1",
263 "EventCode": "0x5E",
264 "UMask": "0x1",
265 "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
266 "Counter": "0,1,2,3",
267 "EventName": "RS_EVENTS.EMPTY_END",
268 "CounterMask": "1",
269 "PublicDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate front-end Latency Bound issues.",
270 "SampleAfterValue": "2000003",
271 "CounterHTOff": "0,1,2,3,4,5,6,7"
272 },
273 {
274 "EventCode": "0x87",
275 "UMask": "0x1",
276 "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
277 "Counter": "0,1,2,3",
278 "EventName": "ILD_STALL.LCP",
279 "PublicDescription": "Counts cycles that the Instruction Length decoder (ILD) stalls occurred due to dynamically changing prefix length of the decoded instruction (by operand size prefix instruction 0x66, address size prefix instruction 0x67 or REX.W for Intel64). Count is proportional to the number of prefixes in a 16B-line. This may result in a three-cycle penalty for each LCP (Length changing prefix) in a 16-byte chunk.",
280 "SampleAfterValue": "2000003",
281 "CounterHTOff": "0,1,2,3,4,5,6,7"
282 },
283 {
284 "EventCode": "0xA1",
285 "UMask": "0x1",
286 "BriefDescription": "Cycles per thread when uops are executed in port 0",
287 "Counter": "0,1,2,3",
288 "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
289 "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 0.",
290 "SampleAfterValue": "2000003",
291 "CounterHTOff": "0,1,2,3,4,5,6,7"
292 },
293 {
294 "EventCode": "0xA1",
295 "UMask": "0x2",
296 "BriefDescription": "Cycles per thread when uops are executed in port 1",
297 "Counter": "0,1,2,3",
298 "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
299 "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 1.",
300 "SampleAfterValue": "2000003",
301 "CounterHTOff": "0,1,2,3,4,5,6,7"
302 },
303 {
304 "EventCode": "0xA1",
305 "UMask": "0x4",
306 "BriefDescription": "Cycles per thread when uops are executed in port 2",
307 "Counter": "0,1,2,3",
308 "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
309 "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 2.",
310 "SampleAfterValue": "2000003",
311 "CounterHTOff": "0,1,2,3,4,5,6,7"
312 },
313 {
314 "EventCode": "0xA1",
315 "UMask": "0x8",
316 "BriefDescription": "Cycles per thread when uops are executed in port 3",
317 "Counter": "0,1,2,3",
318 "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
319 "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 3.",
320 "SampleAfterValue": "2000003",
321 "CounterHTOff": "0,1,2,3,4,5,6,7"
322 },
323 {
324 "EventCode": "0xA1",
325 "UMask": "0x10",
326 "BriefDescription": "Cycles per thread when uops are executed in port 4",
327 "Counter": "0,1,2,3",
328 "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
329 "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 4.",
330 "SampleAfterValue": "2000003",
331 "CounterHTOff": "0,1,2,3,4,5,6,7"
332 },
333 {
334 "EventCode": "0xA1",
335 "UMask": "0x20",
336 "BriefDescription": "Cycles per thread when uops are executed in port 5",
337 "Counter": "0,1,2,3",
338 "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
339 "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 5.",
340 "SampleAfterValue": "2000003",
341 "CounterHTOff": "0,1,2,3,4,5,6,7"
342 },
343 {
344 "EventCode": "0xA1",
345 "UMask": "0x40",
346 "BriefDescription": "Cycles per thread when uops are executed in port 6",
347 "Counter": "0,1,2,3",
348 "EventName": "UOPS_DISPATCHED_PORT.PORT_6",
349 "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 6.",
350 "SampleAfterValue": "2000003",
351 "CounterHTOff": "0,1,2,3,4,5,6,7"
352 },
353 {
354 "EventCode": "0xA1",
355 "UMask": "0x80",
356 "BriefDescription": "Cycles per thread when uops are executed in port 7",
357 "Counter": "0,1,2,3",
358 "EventName": "UOPS_DISPATCHED_PORT.PORT_7",
359 "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 7.",
360 "SampleAfterValue": "2000003",
361 "CounterHTOff": "0,1,2,3,4,5,6,7"
362 },
363 {
364 "EventCode": "0xA2",
365 "UMask": "0x1",
366 "BriefDescription": "Resource-related stall cycles",
367 "Counter": "0,1,2,3",
368 "EventName": "RESOURCE_STALLS.ANY",
369 "PublicDescription": "Counts resource-related stall cycles. Reasons for stalls can be as follows:a. *any* u-arch structure got full (LB, SB, RS, ROB, BOB, LM, Physical Register Reclaim Table (PRRT), or Physical History Table (PHT) slots).b. *any* u-arch structure got empty (like INT/SIMD FreeLists).c. FPU control word (FPCW), MXCSR.and others. This counts cycles that the pipeline back-end blocked uop delivery from the front-end.",
370 "SampleAfterValue": "2000003",
371 "CounterHTOff": "0,1,2,3,4,5,6,7"
372 },
373 {
374 "EventCode": "0xA2",
375 "UMask": "0x8",
376 "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
377 "Counter": "0,1,2,3",
378 "EventName": "RESOURCE_STALLS.SB",
379 "PublicDescription": "Counts allocation stall cycles caused by the store buffer (SB) being full. This counts cycles that the pipeline back-end blocked uop delivery from the front-end.",
380 "SampleAfterValue": "2000003",
381 "CounterHTOff": "0,1,2,3,4,5,6,7"
382 },
383 {
384 "EventCode": "0xA3",
385 "UMask": "0x1",
386 "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
387 "Counter": "0,1,2,3",
388 "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS",
389 "CounterMask": "1",
390 "SampleAfterValue": "2000003",
391 "CounterHTOff": "0,1,2,3,4,5,6,7"
392 },
393 {
394 "EventCode": "0xA3",
395 "UMask": "0x4",
396 "BriefDescription": "Total execution stalls.",
397 "Counter": "0,1,2,3",
398 "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL",
399 "CounterMask": "4",
400 "SampleAfterValue": "2000003",
401 "CounterHTOff": "0,1,2,3,4,5,6,7"
402 },
403 {
404 "EventCode": "0xA3",
405 "UMask": "0x5",
406 "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
407 "Counter": "0,1,2,3",
408 "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS",
409 "CounterMask": "5",
410 "SampleAfterValue": "2000003",
411 "CounterHTOff": "0,1,2,3,4,5,6,7"
412 },
413 {
414 "EventCode": "0xA3",
415 "UMask": "0x8",
416 "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
417 "Counter": "0,1,2,3",
418 "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS",
419 "CounterMask": "8",
420 "SampleAfterValue": "2000003",
421 "CounterHTOff": "0,1,2,3,4,5,6,7"
422 },
423 {
424 "EventCode": "0xA3",
425 "UMask": "0xc",
426 "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
427 "Counter": "0,1,2,3",
428 "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS",
429 "CounterMask": "12",
430 "SampleAfterValue": "2000003",
431 "CounterHTOff": "0,1,2,3,4,5,6,7"
432 },
433 {
434 "EventCode": "0xA3",
435 "UMask": "0x10",
436 "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
437 "Counter": "0,1,2,3",
438 "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY",
439 "CounterMask": "16",
440 "SampleAfterValue": "2000003",
441 "CounterHTOff": "0,1,2,3,4,5,6,7"
442 },
443 {
444 "EventCode": "0xA3",
445 "UMask": "0x14",
446 "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
447 "Counter": "0,1,2,3",
448 "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY",
449 "CounterMask": "20",
450 "SampleAfterValue": "2000003",
451 "CounterHTOff": "0,1,2,3"
452 },
453 {
454 "EventCode": "0xA6",
455 "UMask": "0x1",
456 "BriefDescription": "Cycles where no uops were executed, the Reservation Station was not empty, the Store Buffer was full and there was no outstanding load.",
457 "Counter": "0,1,2,3",
458 "EventName": "EXE_ACTIVITY.EXE_BOUND_0_PORTS",
459 "PublicDescription": "Counts cycles during which no uops were executed on all ports and Reservation Station (RS) was not empty.",
460 "SampleAfterValue": "2000003",
461 "CounterHTOff": "0,1,2,3,4,5,6,7"
462 },
463 {
464 "EventCode": "0xA6",
465 "UMask": "0x2",
466 "BriefDescription": "Cycles total of 1 uop is executed on all ports and Reservation Station was not empty.",
467 "Counter": "0,1,2,3",
468 "EventName": "EXE_ACTIVITY.1_PORTS_UTIL",
469 "PublicDescription": "Counts cycles during which a total of 1 uop was executed on all ports and Reservation Station (RS) was not empty.",
470 "SampleAfterValue": "2000003",
471 "CounterHTOff": "0,1,2,3,4,5,6,7"
472 },
473 {
474 "EventCode": "0xA6",
475 "UMask": "0x4",
476 "BriefDescription": "Cycles total of 2 uops are executed on all ports and Reservation Station was not empty.",
477 "Counter": "0,1,2,3",
478 "EventName": "EXE_ACTIVITY.2_PORTS_UTIL",
479 "PublicDescription": "Counts cycles during which a total of 2 uops were executed on all ports and Reservation Station (RS) was not empty.",
480 "SampleAfterValue": "2000003",
481 "CounterHTOff": "0,1,2,3,4,5,6,7"
482 },
483 {
484 "EventCode": "0xA6",
485 "UMask": "0x8",
486 "BriefDescription": "Cycles total of 3 uops are executed on all ports and Reservation Station was not empty.",
487 "Counter": "0,1,2,3",
488 "EventName": "EXE_ACTIVITY.3_PORTS_UTIL",
489 "PublicDescription": "Cycles total of 3 uops are executed on all ports and Reservation Station (RS) was not empty.",
490 "SampleAfterValue": "2000003",
491 "CounterHTOff": "0,1,2,3,4,5,6,7"
492 },
493 {
494 "EventCode": "0xA6",
495 "UMask": "0x10",
496 "BriefDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station was not empty.",
497 "Counter": "0,1,2,3",
498 "EventName": "EXE_ACTIVITY.4_PORTS_UTIL",
499 "PublicDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station (RS) was not empty.",
500 "SampleAfterValue": "2000003",
501 "CounterHTOff": "0,1,2,3,4,5,6,7"
502 },
503 {
504 "EventCode": "0xA6",
505 "UMask": "0x40",
506 "BriefDescription": "Cycles where the Store Buffer was full and no outstanding load.",
507 "Counter": "0,1,2,3",
508 "EventName": "EXE_ACTIVITY.BOUND_ON_STORES",
509 "SampleAfterValue": "2000003",
510 "CounterHTOff": "0,1,2,3,4,5,6,7"
511 },
512 {
513 "EventCode": "0xA8",
514 "UMask": "0x1",
515 "BriefDescription": "Number of Uops delivered by the LSD.",
516 "Counter": "0,1,2,3",
517 "EventName": "LSD.UOPS",
518 "PublicDescription": "Number of uops delivered to the back-end by the LSD(Loop Stream Detector).",
519 "SampleAfterValue": "2000003",
520 "CounterHTOff": "0,1,2,3,4,5,6,7"
521 },
522 {
523 "EventCode": "0xA8",
524 "UMask": "0x1",
525 "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
526 "Counter": "0,1,2,3",
527 "EventName": "LSD.CYCLES_ACTIVE",
528 "CounterMask": "1",
529 "PublicDescription": "Counts the cycles when at least one uop is delivered by the LSD (Loop-stream detector).",
530 "SampleAfterValue": "2000003",
531 "CounterHTOff": "0,1,2,3,4,5,6,7"
532 },
533 {
534 "EventCode": "0xA8",
535 "UMask": "0x1",
536 "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
537 "Counter": "0,1,2,3",
538 "EventName": "LSD.CYCLES_4_UOPS",
539 "CounterMask": "4",
540 "PublicDescription": "Counts the cycles when 4 uops are delivered by the LSD (Loop-stream detector).",
541 "SampleAfterValue": "2000003",
542 "CounterHTOff": "0,1,2,3,4,5,6,7"
543 },
544 {
545 "EventCode": "0xB1",
546 "UMask": "0x1",
547 "BriefDescription": "Counts the number of uops to be executed per-thread each cycle.",
548 "Counter": "0,1,2,3",
549 "EventName": "UOPS_EXECUTED.THREAD",
550 "PublicDescription": "Number of uops to be executed per-thread each cycle.",
551 "SampleAfterValue": "2000003",
552 "CounterHTOff": "0,1,2,3,4,5,6,7"
553 },
554 {
555 "Invert": "1",
556 "EventCode": "0xB1",
557 "UMask": "0x1",
558 "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
559 "Counter": "0,1,2,3",
560 "EventName": "UOPS_EXECUTED.STALL_CYCLES",
561 "CounterMask": "1",
562 "PublicDescription": "Counts cycles during which no uops were dispatched from the Reservation Station (RS) per thread.",
563 "SampleAfterValue": "2000003",
564 "CounterHTOff": "0,1,2,3,4,5,6,7"
565 },
566 {
567 "EventCode": "0xB1",
568 "UMask": "0x1",
569 "BriefDescription": "Cycles where at least 1 uop was executed per-thread",
570 "Counter": "0,1,2,3",
571 "EventName": "UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
572 "CounterMask": "1",
573 "PublicDescription": "Cycles where at least 1 uop was executed per-thread.",
574 "SampleAfterValue": "2000003",
575 "CounterHTOff": "0,1,2,3,4,5,6,7"
576 },
577 {
578 "EventCode": "0xB1",
579 "UMask": "0x1",
580 "BriefDescription": "Cycles where at least 2 uops were executed per-thread",
581 "Counter": "0,1,2,3",
582 "EventName": "UOPS_EXECUTED.CYCLES_GE_2_UOPS_EXEC",
583 "CounterMask": "2",
584 "PublicDescription": "Cycles where at least 2 uops were executed per-thread.",
585 "SampleAfterValue": "2000003",
586 "CounterHTOff": "0,1,2,3,4,5,6,7"
587 },
588 {
589 "EventCode": "0xB1",
590 "UMask": "0x1",
591 "BriefDescription": "Cycles where at least 3 uops were executed per-thread",
592 "Counter": "0,1,2,3",
593 "EventName": "UOPS_EXECUTED.CYCLES_GE_3_UOPS_EXEC",
594 "CounterMask": "3",
595 "PublicDescription": "Cycles where at least 3 uops were executed per-thread.",
596 "SampleAfterValue": "2000003",
597 "CounterHTOff": "0,1,2,3,4,5,6,7"
598 },
599 {
600 "EventCode": "0xB1",
601 "UMask": "0x1",
602 "BriefDescription": "Cycles where at least 4 uops were executed per-thread",
603 "Counter": "0,1,2,3",
604 "EventName": "UOPS_EXECUTED.CYCLES_GE_4_UOPS_EXEC",
605 "CounterMask": "4",
606 "PublicDescription": "Cycles where at least 4 uops were executed per-thread.",
607 "SampleAfterValue": "2000003",
608 "CounterHTOff": "0,1,2,3,4,5,6,7"
609 },
610 {
611 "EventCode": "0xB1",
612 "UMask": "0x2",
613 "BriefDescription": "Number of uops executed on the core.",
614 "Counter": "0,1,2,3",
615 "EventName": "UOPS_EXECUTED.CORE",
616 "PublicDescription": "Number of uops executed from any thread.",
617 "SampleAfterValue": "2000003",
618 "CounterHTOff": "0,1,2,3,4,5,6,7"
619 },
620 {
621 "EventCode": "0xB1",
622 "UMask": "0x2",
623 "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
624 "Counter": "0,1,2,3",
625 "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
626 "CounterMask": "1",
627 "SampleAfterValue": "2000003",
628 "CounterHTOff": "0,1,2,3,4,5,6,7"
629 },
630 {
631 "EventCode": "0xB1",
632 "UMask": "0x2",
633 "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
634 "Counter": "0,1,2,3",
635 "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
636 "CounterMask": "2",
637 "SampleAfterValue": "2000003",
638 "CounterHTOff": "0,1,2,3,4,5,6,7"
639 },
640 {
641 "EventCode": "0xB1",
642 "UMask": "0x2",
643 "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
644 "Counter": "0,1,2,3",
645 "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
646 "CounterMask": "3",
647 "SampleAfterValue": "2000003",
648 "CounterHTOff": "0,1,2,3,4,5,6,7"
649 },
650 {
651 "EventCode": "0xB1",
652 "UMask": "0x2",
653 "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
654 "Counter": "0,1,2,3",
655 "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
656 "CounterMask": "4",
657 "SampleAfterValue": "2000003",
658 "CounterHTOff": "0,1,2,3,4,5,6,7"
659 },
660 {
661 "Invert": "1",
662 "EventCode": "0xB1",
663 "UMask": "0x2",
664 "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core.",
665 "Counter": "0,1,2,3",
666 "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
667 "CounterMask": "1",
668 "SampleAfterValue": "2000003",
669 "CounterHTOff": "0,1,2,3,4,5,6,7"
670 },
671 {
672 "EventCode": "0xB1",
673 "UMask": "0x10",
674 "BriefDescription": "Counts the number of x87 uops dispatched.",
675 "Counter": "0,1,2,3",
676 "EventName": "UOPS_EXECUTED.X87",
677 "PublicDescription": "Counts the number of x87 uops executed.",
678 "SampleAfterValue": "2000003",
679 "CounterHTOff": "0,1,2,3,4,5,6,7"
680 },
681 {
682 "EventCode": "0xC0",
683 "UMask": "0x0",
684 "BriefDescription": "Number of instructions retired. General Counter - architectural event",
685 "Counter": "0,1,2,3",
686 "EventName": "INST_RETIRED.ANY_P",
687 "Errata": "SKL091, SKL044",
688 "PublicDescription": "Counts the number of instructions (EOMs) retired. Counting covers macro-fused instructions individually (that is, increments by two).",
689 "SampleAfterValue": "2000003",
690 "CounterHTOff": "0,1,2,3,4,5,6,7"
691 },
692 {
693 "EventCode": "0xC0",
694 "UMask": "0x1",
695 "BriefDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution",
696 "PEBS": "2",
697 "Counter": "1",
698 "EventName": "INST_RETIRED.PREC_DIST",
699 "Errata": "SKL091, SKL044",
700 "PublicDescription": "A version of INST_RETIRED that allows for a more unbiased distribution of samples across instructions retired. It utilizes the Precise Distribution of Instructions Retired (PDIR) feature to mitigate some bias in how retired instructions get sampled.",
701 "SampleAfterValue": "2000003",
702 "CounterHTOff": "1"
703 },
704 {
705 "Invert": "1",
706 "EventCode": "0xC0",
707 "UMask": "0x1",
708 "BriefDescription": "Number of cycles using always true condition applied to PEBS instructions retired event.",
709 "PEBS": "2",
710 "Counter": "0,2,3",
711 "EventName": "INST_RETIRED.TOTAL_CYCLES_PS",
712 "CounterMask": "10",
713 "Errata": "SKL091, SKL044",
714 "PublicDescription": "Number of cycles using an always true condition applied to PEBS instructions retired event. (inst_ret< 16)",
715 "SampleAfterValue": "2000003",
716 "CounterHTOff": "0,2,3"
717 },
718 {
719 "EventCode": "0xC1",
720 "UMask": "0x3f",
721 "BriefDescription": "Number of times a microcode assist is invoked by HW other than FP-assist. Examples include AD (page Access Dirty) and AVX* related assists.",
722 "Counter": "0,1,2,3",
723 "EventName": "OTHER_ASSISTS.ANY",
724 "SampleAfterValue": "100003",
725 "CounterHTOff": "0,1,2,3,4,5,6,7"
726 },
727 {
728 "EventCode": "0xC2",
729 "UMask": "0x2",
730 "BriefDescription": "Retirement slots used.",
731 "Counter": "0,1,2,3",
732 "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
733 "PublicDescription": "Counts the retirement slots used.",
734 "SampleAfterValue": "2000003",
735 "CounterHTOff": "0,1,2,3,4,5,6,7"
736 },
737 {
738 "Invert": "1",
739 "EventCode": "0xC2",
740 "UMask": "0x2",
741 "BriefDescription": "Cycles without actually retired uops.",
742 "Counter": "0,1,2,3",
743 "EventName": "UOPS_RETIRED.STALL_CYCLES",
744 "CounterMask": "1",
745 "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts cycles without actually retired uops.",
746 "SampleAfterValue": "2000003",
747 "CounterHTOff": "0,1,2,3,4,5,6,7"
748 },
749 {
750 "Invert": "1",
751 "EventCode": "0xC2",
752 "UMask": "0x2",
753 "BriefDescription": "Cycles with less than 10 actually retired uops.",
754 "Counter": "0,1,2,3",
755 "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
756 "CounterMask": "10",
757 "PublicDescription": "Number of cycles using always true condition (uops_ret < 16) applied to non PEBS uops retired event.",
758 "SampleAfterValue": "2000003",
759 "CounterHTOff": "0,1,2,3,4,5,6,7"
760 },
761 {
762 "EdgeDetect": "1",
763 "EventCode": "0xC3",
764 "UMask": "0x1",
765 "BriefDescription": "Number of machine clears (nukes) of any type. ",
766 "Counter": "0,1,2,3",
767 "EventName": "MACHINE_CLEARS.COUNT",
768 "CounterMask": "1",
769 "PublicDescription": "Number of machine clears (nukes) of any type.",
770 "SampleAfterValue": "100003",
771 "CounterHTOff": "0,1,2,3,4,5,6,7"
772 },
773 {
774 "EventCode": "0xC3",
775 "UMask": "0x4",
776 "BriefDescription": "Self-modifying code (SMC) detected.",
777 "Counter": "0,1,2,3",
778 "EventName": "MACHINE_CLEARS.SMC",
779 "PublicDescription": "Counts self-modifying code (SMC) detected, which causes a machine clear.",
780 "SampleAfterValue": "100003",
781 "CounterHTOff": "0,1,2,3,4,5,6,7"
782 },
783 {
784 "EventCode": "0xC4",
785 "UMask": "0x0",
786 "BriefDescription": "All (macro) branch instructions retired.",
787 "Counter": "0,1,2,3",
788 "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
789 "Errata": "SKL091",
790 "PublicDescription": "Counts all (macro) branch instructions retired.",
791 "SampleAfterValue": "400009",
792 "CounterHTOff": "0,1,2,3,4,5,6,7"
793 },
794 {
795 "EventCode": "0xC4",
796 "UMask": "0x1",
797 "BriefDescription": "Conditional branch instructions retired.",
798 "PEBS": "1",
799 "Counter": "0,1,2,3",
800 "EventName": "BR_INST_RETIRED.CONDITIONAL",
801 "Errata": "SKL091",
802 "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts conditional branch instructions retired.",
803 "SampleAfterValue": "400009",
804 "CounterHTOff": "0,1,2,3,4,5,6,7"
805 },
806 {
807 "EventCode": "0xC4",
808 "UMask": "0x2",
809 "BriefDescription": "Direct and indirect near call instructions retired.",
810 "PEBS": "1",
811 "Counter": "0,1,2,3",
812 "EventName": "BR_INST_RETIRED.NEAR_CALL",
813 "Errata": "SKL091",
814 "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts both direct and indirect near call instructions retired.",
815 "SampleAfterValue": "100007",
816 "CounterHTOff": "0,1,2,3,4,5,6,7"
817 },
818 {
819 "EventCode": "0xC4",
820 "UMask": "0x4",
821 "BriefDescription": "All (macro) branch instructions retired. ",
822 "PEBS": "2",
823 "Counter": "0,1,2,3",
824 "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
825 "Errata": "SKL091",
826 "PublicDescription": "This is a precise version of BR_INST_RETIRED.ALL_BRANCHES that counts all (macro) branch instructions retired.",
827 "SampleAfterValue": "400009",
828 "CounterHTOff": "0,1,2,3"
829 },
830 {
831 "EventCode": "0xC4",
832 "UMask": "0x8",
833 "BriefDescription": "Return instructions retired.",
834 "PEBS": "1",
835 "Counter": "0,1,2,3",
836 "EventName": "BR_INST_RETIRED.NEAR_RETURN",
837 "Errata": "SKL091",
838 "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts return instructions retired.",
839 "SampleAfterValue": "100007",
840 "CounterHTOff": "0,1,2,3,4,5,6,7"
841 },
842 {
843 "EventCode": "0xC4",
844 "UMask": "0x10",
845 "BriefDescription": "Not taken branch instructions retired.",
846 "Counter": "0,1,2,3",
847 "EventName": "BR_INST_RETIRED.NOT_TAKEN",
848 "Errata": "SKL091",
849 "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts not taken branch instructions retired.",
850 "SampleAfterValue": "400009",
851 "CounterHTOff": "0,1,2,3,4,5,6,7"
852 },
853 {
854 "EventCode": "0xC4",
855 "UMask": "0x20",
856 "BriefDescription": "Taken branch instructions retired.",
857 "PEBS": "1",
858 "Counter": "0,1,2,3",
859 "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
860 "Errata": "SKL091",
861 "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts taken branch instructions retired.",
862 "SampleAfterValue": "400009",
863 "CounterHTOff": "0,1,2,3,4,5,6,7"
864 },
865 {
866 "EventCode": "0xC4",
867 "UMask": "0x40",
868 "BriefDescription": "Far branch instructions retired.",
869 "PEBS": "1",
870 "Counter": "0,1,2,3",
871 "EventName": "BR_INST_RETIRED.FAR_BRANCH",
872 "Errata": "SKL091",
873 "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts far branch instructions retired.",
874 "SampleAfterValue": "100007",
875 "CounterHTOff": "0,1,2,3,4,5,6,7"
876 },
877 {
878 "EventCode": "0xC5",
879 "UMask": "0x0",
880 "BriefDescription": "All mispredicted macro branch instructions retired.",
881 "Counter": "0,1,2,3",
882 "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
883 "PublicDescription": "Counts all the retired branch instructions that were mispredicted by the processor. A branch misprediction occurs when the processor incorrectly predicts the destination of the branch. When the misprediction is discovered at execution, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.",
884 "SampleAfterValue": "400009",
885 "CounterHTOff": "0,1,2,3,4,5,6,7"
886 },
887 {
888 "EventCode": "0xC5",
889 "UMask": "0x1",
890 "BriefDescription": "Mispredicted conditional branch instructions retired.",
891 "PEBS": "1",
892 "Counter": "0,1,2,3",
893 "EventName": "BR_MISP_RETIRED.CONDITIONAL",
894 "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts mispredicted conditional branch instructions retired.",
895 "SampleAfterValue": "400009",
896 "CounterHTOff": "0,1,2,3,4,5,6,7"
897 },
898 {
899 "EventCode": "0xC5",
900 "UMask": "0x2",
901 "BriefDescription": "Mispredicted direct and indirect near call instructions retired.",
902 "PEBS": "1",
903 "Counter": "0,1,2,3",
904 "EventName": "BR_MISP_RETIRED.NEAR_CALL",
905 "PublicDescription": "Counts both taken and not taken retired mispredicted direct and indirect near calls, including both register and memory indirect.",
906 "SampleAfterValue": "400009",
907 "CounterHTOff": "0,1,2,3,4,5,6,7"
908 },
909 {
910 "EventCode": "0xC5",
911 "UMask": "0x4",
912 "BriefDescription": "Mispredicted macro branch instructions retired. ",
913 "PEBS": "2",
914 "Counter": "0,1,2,3",
915 "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
916 "PublicDescription": "This is a precise version of BR_MISP_RETIRED.ALL_BRANCHES that counts all mispredicted macro branch instructions retired.",
917 "SampleAfterValue": "400009",
918 "CounterHTOff": "0,1,2,3"
919 },
920 {
921 "EventCode": "0xC5",
922 "UMask": "0x20",
923 "BriefDescription": "Number of near branch instructions retired that were mispredicted and taken.",
924 "PEBS": "1",
925 "Counter": "0,1,2,3",
926 "EventName": "BR_MISP_RETIRED.NEAR_TAKEN",
927 "SampleAfterValue": "400009",
928 "CounterHTOff": "0,1,2,3,4,5,6,7"
929 },
930 {
931 "EventCode": "0xCC",
932 "UMask": "0x20",
933 "BriefDescription": "Increments whenever there is an update to the LBR array.",
934 "Counter": "0,1,2,3",
935 "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
936 "PublicDescription": "Increments when an entry is added to the Last Branch Record (LBR) array (or removed from the array in case of RETURNs in call stack mode). The event requires LBR enable via IA32_DEBUGCTL MSR and branch type selection via MSR_LBR_SELECT.",
937 "SampleAfterValue": "2000003",
938 "CounterHTOff": "0,1,2,3,4,5,6,7"
939 },
940 {
941 "EventCode": "0xE6",
942 "UMask": "0x1",
943 "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
944 "Counter": "0,1,2,3",
945 "EventName": "BACLEARS.ANY",
946 "PublicDescription": "Counts the number of times the front-end is resteered when it finds a branch instruction in a fetch line. This occurs for the first time a branch instruction is fetched or when the branch is not tracked by the BPU (Branch Prediction Unit) anymore.",
947 "SampleAfterValue": "100003",
948 "CounterHTOff": "0,1,2,3,4,5,6,7"
949 }
950] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json b/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json
new file mode 100644
index 000000000000..36c903faed0b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json
@@ -0,0 +1,164 @@
1[
2 {
3 "BriefDescription": "Instructions Per Cycle (per logical thread)",
4 "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
5 "MetricGroup": "TopDownL1",
6 "MetricName": "IPC"
7 },
8 {
9 "BriefDescription": "Uops Per Instruction",
10 "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY",
11 "MetricGroup": "Pipeline",
12 "MetricName": "UPI"
13 },
14 {
15 "BriefDescription": "Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions",
16 "MetricExpr": "min( 1 , UOPS_ISSUED.ANY / ((UOPS_RETIRED.RETIRE_SLOTS / INST_RETIRED.ANY) * 64 * ( ICACHE_64B.IFTAG_HIT + ICACHE_64B.IFTAG_MISS ) / 4.1) )",
17 "MetricGroup": "Frontend",
18 "MetricName": "IFetch_Line_Utilization"
19 },
20 {
21 "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)",
22 "MetricExpr": "IDQ.DSB_UOPS / ( IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS )",
23 "MetricGroup": "DSB; Frontend_Bandwidth",
24 "MetricName": "DSB_Coverage"
25 },
26 {
27 "BriefDescription": "Cycles Per Instruction (threaded)",
28 "MetricExpr": "1 / (INST_RETIRED.ANY / cycles)",
29 "MetricGroup": "Pipeline;Summary",
30 "MetricName": "CPI"
31 },
32 {
33 "BriefDescription": "Per-thread actual clocks when the logical processor is active. This is called 'Clockticks' in VTune.",
34 "MetricExpr": "CPU_CLK_UNHALTED.THREAD",
35 "MetricGroup": "Summary",
36 "MetricName": "CLKS"
37 },
38 {
39 "BriefDescription": "Total issue-pipeline slots",
40 "MetricExpr": "4*(( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
41 "MetricGroup": "TopDownL1",
42 "MetricName": "SLOTS"
43 },
44 {
45 "BriefDescription": "Total number of retired Instructions",
46 "MetricExpr": "INST_RETIRED.ANY",
47 "MetricGroup": "Summary",
48 "MetricName": "Instructions"
49 },
50 {
51 "BriefDescription": "Instructions Per Cycle (per physical core)",
52 "MetricExpr": "INST_RETIRED.ANY / (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles)",
53 "MetricGroup": "SMT",
54 "MetricName": "CoreIPC"
55 },
56 {
57 "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
58 "MetricExpr": "UOPS_EXECUTED.THREAD / (( UOPS_EXECUTED.CORE_CYCLES_GE_1 / 2) if #SMT_on else UOPS_EXECUTED.CORE_CYCLES_GE_1)",
59 "MetricGroup": "Pipeline;Ports_Utilization",
60 "MetricName": "ILP"
61 },
62 {
63 "BriefDescription": "Average Branch Address Clear Cost (fraction of cycles)",
64 "MetricExpr": "2* (( RS_EVENTS.EMPTY_CYCLES - ICACHE_16B.IFDATA_STALL - ICACHE_64B.IFTAG_STALL ) / RS_EVENTS.EMPTY_END)",
65 "MetricGroup": "Unknown_Branches",
66 "MetricName": "BAClear_Cost"
67 },
68 {
69 "BriefDescription": "Core actual clocks when any thread is active on the physical core",
70 "MetricExpr": "( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else CPU_CLK_UNHALTED.THREAD",
71 "MetricGroup": "SMT",
72 "MetricName": "CORE_CLKS"
73 },
74 {
75 "BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads",
76 "MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_RETIRED.L1_MISS_PS + MEM_LOAD_RETIRED.FB_HIT_PS )",
77 "MetricGroup": "Memory_Bound;Memory_Lat",
78 "MetricName": "Load_Miss_Real_Latency"
79 },
80 {
81 "BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least 1 such miss)",
82 "MetricExpr": "L1D_PEND_MISS.PENDING / (( L1D_PEND_MISS.PENDING_CYCLES_ANY / 2) if #SMT_on else L1D_PEND_MISS.PENDING_CYCLES)",
83 "MetricGroup": "Memory_Bound;Memory_BW",
84 "MetricName": "MLP"
85 },
86 {
87 "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
88 "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles) )",
89 "MetricGroup": "TLB",
90 "MetricName": "Page_Walks_Utilization"
91 },
92 {
93 "BriefDescription": "Average CPU Utilization",
94 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
95 "MetricGroup": "Summary",
96 "MetricName": "CPU_Utilization"
97 },
98 {
99 "BriefDescription": "Giga Floating Point Operations Per Second",
100 "MetricExpr": "(( 1*( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2* FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4*( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8* FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE )) / 1000000000 / duration_time",
101 "MetricGroup": "FLOPS;Summary",
102 "MetricName": "GFLOPs"
103 },
104 {
105 "BriefDescription": "Average Frequency Utilization relative nominal frequency",
106 "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC",
107 "MetricGroup": "Power",
108 "MetricName": "Turbo_Utilization"
109 },
110 {
111 "BriefDescription": "Fraction of cycles where both hardware threads were active",
112 "MetricExpr": "1 - CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
113 "MetricGroup": "SMT;Summary",
114 "MetricName": "SMT_2T_Utilization"
115 },
116 {
117 "BriefDescription": "Fraction of cycles spent in Kernel mode",
118 "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
119 "MetricGroup": "Summary",
120 "MetricName": "Kernel_Utilization"
121 },
122 {
123 "BriefDescription": "C3 residency percent per core",
124 "MetricExpr": "(cstate_core@c3\\-residency@ / msr@tsc@) * 100",
125 "MetricGroup": "Power",
126 "MetricName": "C3_Core_Residency"
127 },
128 {
129 "BriefDescription": "C6 residency percent per core",
130 "MetricExpr": "(cstate_core@c6\\-residency@ / msr@tsc@) * 100",
131 "MetricGroup": "Power",
132 "MetricName": "C6_Core_Residency"
133 },
134 {
135 "BriefDescription": "C7 residency percent per core",
136 "MetricExpr": "(cstate_core@c7\\-residency@ / msr@tsc@) * 100",
137 "MetricGroup": "Power",
138 "MetricName": "C7_Core_Residency"
139 },
140 {
141 "BriefDescription": "C2 residency percent per package",
142 "MetricExpr": "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100",
143 "MetricGroup": "Power",
144 "MetricName": "C2_Pkg_Residency"
145 },
146 {
147 "BriefDescription": "C3 residency percent per package",
148 "MetricExpr": "(cstate_pkg@c3\\-residency@ / msr@tsc@) * 100",
149 "MetricGroup": "Power",
150 "MetricName": "C3_Pkg_Residency"
151 },
152 {
153 "BriefDescription": "C6 residency percent per package",
154 "MetricExpr": "(cstate_pkg@c6\\-residency@ / msr@tsc@) * 100",
155 "MetricGroup": "Power",
156 "MetricName": "C6_Pkg_Residency"
157 },
158 {
159 "BriefDescription": "C7 residency percent per package",
160 "MetricExpr": "(cstate_pkg@c7\\-residency@ / msr@tsc@) * 100",
161 "MetricGroup": "Power",
162 "MetricName": "C7_Pkg_Residency"
163 }
164]
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/uncore-memory.json b/tools/perf/pmu-events/arch/x86/skylakex/uncore-memory.json
new file mode 100644
index 000000000000..9c7e5f8beee2
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylakex/uncore-memory.json
@@ -0,0 +1,172 @@
1[
2 {
3 "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
4 "Counter": "0,1,2,3",
5 "EventCode": "0x4",
6 "EventName": "LLC_MISSES.MEM_READ",
7 "PerPkg": "1",
8 "ScaleUnit": "64Bytes",
9 "UMask": "0x3",
10 "Unit": "iMC"
11 },
12 {
13 "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
14 "Counter": "0,1,2,3",
15 "EventCode": "0x4",
16 "EventName": "LLC_MISSES.MEM_WRITE",
17 "PerPkg": "1",
18 "ScaleUnit": "64Bytes",
19 "UMask": "0xC",
20 "Unit": "iMC"
21 },
22 {
23 "BriefDescription": "Memory controller clock ticks",
24 "Counter": "0,1,2,3",
25 "EventName": "UNC_M_CLOCKTICKS",
26 "PerPkg": "1",
27 "Unit": "iMC"
28 },
29 {
30 "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode",
31 "Counter": "0,1,2,3",
32 "EventCode": "0x85",
33 "EventName": "UNC_M_POWER_CHANNEL_PPD",
34 "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
35 "MetricName": "power_channel_ppd %",
36 "PerPkg": "1",
37 "Unit": "iMC"
38 },
39 {
40 "BriefDescription": "Cycles Memory is in self refresh power mode",
41 "Counter": "0,1,2,3",
42 "EventCode": "0x43",
43 "EventName": "UNC_M_POWER_SELF_REFRESH",
44 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
45 "MetricName": "power_self_refresh %",
46 "PerPkg": "1",
47 "Unit": "iMC"
48 },
49 {
50 "BriefDescription": "Pre-charges due to page misses",
51 "Counter": "0,1,2,3",
52 "EventCode": "0x2",
53 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
54 "PerPkg": "1",
55 "UMask": "0x1",
56 "Unit": "iMC"
57 },
58 {
59 "BriefDescription": "Pre-charge for reads",
60 "Counter": "0,1,2,3",
61 "EventCode": "0x2",
62 "EventName": "UNC_M_PRE_COUNT.RD",
63 "PerPkg": "1",
64 "UMask": "0x4",
65 "Unit": "iMC"
66 },
67 {
68 "BriefDescription": "Pre-charge for writes",
69 "Counter": "0,1,2,3",
70 "EventCode": "0x2",
71 "EventName": "UNC_M_PRE_COUNT.WR",
72 "PerPkg": "1",
73 "UMask": "0x8",
74 "Unit": "iMC"
75 },
76 {
77 "BriefDescription": "DRAM Page Activate commands sent due to a write request",
78 "Counter": "0,1,2,3",
79 "EventCode": "0x1",
80 "EventName": "UNC_M_ACT_COUNT.WR",
81 "PerPkg": "1",
82 "PublicDescription": "Counts DRAM Page Activate commands sent on this channel due to a write request to the iMC (Memory Controller). Activate commands are issued to open up a page on the DRAM devices so that it can be read or written to with a CAS (Column Access Select) command.",
83 "UMask": "0x2",
84 "Unit": "iMC"
85 },
86 {
87 "BriefDescription": "All DRAM CAS Commands issued",
88 "Counter": "0,1,2,3",
89 "EventCode": "0x4",
90 "EventName": "UNC_M_CAS_COUNT.ALL",
91 "PerPkg": "1",
92 "PublicDescription": "Counts all CAS (Column Address Select) commands issued to DRAM per memory channel. CAS commands are issued to specify the address to read or write on DRAM, so this event increments for every read and write. This event counts whether AutoPrecharge (which closes the DRAM Page automatically after a read/write) is enabled or not.",
93 "UMask": "0xF",
94 "Unit": "iMC"
95 },
96 {
97 "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
98 "Counter": "0,1,2,3",
99 "EventCode": "0x4",
100 "EventName": "LLC_MISSES.MEM_READ",
101 "PerPkg": "1",
102 "ScaleUnit": "64Bytes",
103 "UMask": "0x3",
104 "Unit": "iMC"
105 },
106 {
107 "BriefDescription": "All DRAM Read CAS Commands issued (does not include underfills) ",
108 "Counter": "0,1,2,3",
109 "EventCode": "0x4",
110 "EventName": "UNC_M_CAS_COUNT.RD_REG",
111 "PerPkg": "1",
112 "PublicDescription": "Counts CAS (Column Access Select) regular read commands issued to DRAM on a per channel basis. CAS commands are issued to specify the address to read or write on DRAM, and this event increments for every regular read. This event only counts regular reads and does not includes underfill reads due to partial write requests. This event counts whether AutoPrecharge (which closes the DRAM Page automatically after a read/write) is enabled or not.",
113 "UMask": "0x1",
114 "Unit": "iMC"
115 },
116 {
117 "BriefDescription": "DRAM Underfill Read CAS Commands issued",
118 "Counter": "0,1,2,3",
119 "EventCode": "0x4",
120 "EventName": "UNC_M_CAS_COUNT.RD_UNDERFILL",
121 "PerPkg": "1",
122 "PublicDescription": "Counts CAS (Column Access Select) underfill read commands issued to DRAM due to a partial write, on a per channel basis. CAS commands are issued to specify the address to read or write on DRAM, and this command counts underfill reads. Partial writes must be completed by first reading in the underfill from DRAM and then merging in the partial write data before writing the full line back to DRAM. This event will generally count about the same as the number of partial writes, but may be slightly less because of partials hitting in the WPQ (due to a previous write request). ",
123 "UMask": "0x2",
124 "Unit": "iMC"
125 },
126 {
127 "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
128 "Counter": "0,1,2,3",
129 "EventCode": "0x4",
130 "EventName": "LLC_MISSES.MEM_WRITE",
131 "PerPkg": "1",
132 "ScaleUnit": "64Bytes",
133 "UMask": "0xC",
134 "Unit": "iMC"
135 },
136 {
137 "BriefDescription": "Read Pending Queue Allocations",
138 "Counter": "0,1,2,3",
139 "EventCode": "0x10",
140 "EventName": "UNC_M_RPQ_INSERTS",
141 "PerPkg": "1",
142 "PublicDescription": "Counts the number of read requests allocated into the Read Pending Queue (RPQ). This queue is used to schedule reads out to the memory controller and to track the requests. Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the CHA to the iMC. The requests deallocate after the read CAS command has been issued to DRAM. This event counts both Isochronous and non-Isochronous requests which were issued to the RPQ. ",
143 "Unit": "iMC"
144 },
145 {
146 "BriefDescription": "Read Pending Queue Occupancy",
147 "Counter": "0,1,2,3",
148 "EventCode": "0x80",
149 "EventName": "UNC_M_RPQ_OCCUPANCY",
150 "PerPkg": "1",
151 "PublicDescription": "Counts the number of entries in the Read Pending Queue (RPQ) at each cycle. This can then be used to calculate both the average occupancy of the queue (in conjunction with the number of cycles not empty) and the average latency in the queue (in conjunction with the number of allocations). The RPQ is used to schedule reads out to the memory controller and to track the requests. Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the CHA to the iMC. They deallocate from the RPQ after the CAS command has been issued to memory.",
152 "Unit": "iMC"
153 },
154 {
155 "BriefDescription": "Write Pending Queue Allocations",
156 "Counter": "0,1,2,3",
157 "EventCode": "0x20",
158 "EventName": "UNC_M_WPQ_INSERTS",
159 "PerPkg": "1",
160 "PublicDescription": "Counts the number of writes requests allocated into the Write Pending Queue (WPQ). The WPQ is used to schedule writes out to the memory controller and to track the requests. Requests allocate into the WPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the CHA to the iMC (Memory Controller). The write requests deallocate after being issued to DRAM. Write requests themselves are able to complete (from the perspective of the rest of the system) as soon they have 'posted' to the iMC.",
161 "Unit": "iMC"
162 },
163 {
164 "BriefDescription": "Write Pending Queue Occupancy",
165 "Counter": "0,1,2,3",
166 "EventCode": "0x81",
167 "EventName": "UNC_M_WPQ_OCCUPANCY",
168 "PerPkg": "1",
169 "PublicDescription": "Counts the number of entries in the Write Pending Queue (WPQ) at each cycle. This can then be used to calculate both the average queue occupancy (in conjunction with the number of cycles not empty) and the average latency (in conjunction with the number of allocations). The WPQ is used to schedule writes out to the memory controller and to track the requests.",
170 "Unit": "iMC"
171 }
172]
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/uncore-other.json b/tools/perf/pmu-events/arch/x86/skylakex/uncore-other.json
new file mode 100644
index 000000000000..de6e70e552e2
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylakex/uncore-other.json
@@ -0,0 +1,1156 @@
1[
2 {
3 "BriefDescription": "Uncore cache clock ticks",
4 "Counter": "0,1,2,3",
5 "EventName": "UNC_CHA_CLOCKTICKS",
6 "PerPkg": "1",
7 "Unit": "CHA"
8 },
9 {
10 "BriefDescription": "LLC misses - Uncacheable reads (from cpu) . Derived from unc_cha_tor_inserts.ia_miss",
11 "Counter": "0,1,2,3",
12 "EventCode": "0x35",
13 "EventName": "LLC_MISSES.UNCACHEABLE",
14 "Filter": "config1=0x40e33",
15 "PerPkg": "1",
16 "UMask": "0x21",
17 "Unit": "CHA"
18 },
19 {
20 "BriefDescription": "MMIO reads. Derived from unc_cha_tor_inserts.ia_miss",
21 "Counter": "0,1,2,3",
22 "EventCode": "0x35",
23 "EventName": "LLC_MISSES.MMIO_READ",
24 "Filter": "config1=0x40040e33",
25 "PerPkg": "1",
26 "UMask": "0x21",
27 "Unit": "CHA"
28 },
29 {
30 "BriefDescription": "MMIO writes. Derived from unc_cha_tor_inserts.ia_miss",
31 "Counter": "0,1,2,3",
32 "EventCode": "0x35",
33 "EventName": "LLC_MISSES.MMIO_WRITE",
34 "Filter": "config1=0x40041e33",
35 "PerPkg": "1",
36 "UMask": "0x21",
37 "Unit": "CHA"
38 },
39 {
40 "BriefDescription": "Streaming stores (full cache line). Derived from unc_cha_tor_inserts.ia_miss",
41 "Counter": "0,1,2,3",
42 "EventCode": "0x35",
43 "EventName": "LLC_REFERENCES.STREAMING_FULL",
44 "Filter": "config1=0x41833",
45 "PerPkg": "1",
46 "ScaleUnit": "64Bytes",
47 "UMask": "0x21",
48 "Unit": "CHA"
49 },
50 {
51 "BriefDescription": "Streaming stores (partial cache line). Derived from unc_cha_tor_inserts.ia_miss",
52 "Counter": "0,1,2,3",
53 "EventCode": "0x35",
54 "EventName": "LLC_REFERENCES.STREAMING_PARTIAL",
55 "Filter": "config1=0x41a33",
56 "PerPkg": "1",
57 "ScaleUnit": "64Bytes",
58 "UMask": "0x21",
59 "Unit": "CHA"
60 },
61 {
62 "BriefDescription": "read requests from home agent",
63 "Counter": "0,1,2,3",
64 "EventCode": "0x50",
65 "EventName": "UNC_CHA_REQUESTS.READS",
66 "PerPkg": "1",
67 "UMask": "0x03",
68 "Unit": "CHA"
69 },
70 {
71 "BriefDescription": "read requests from local home agent",
72 "Counter": "0,1,2,3",
73 "EventCode": "0x50",
74 "EventName": "UNC_CHA_REQUESTS.READS_LOCAL",
75 "PerPkg": "1",
76 "UMask": "0x01",
77 "Unit": "CHA"
78 },
79 {
80 "BriefDescription": "read requests from remote home agent",
81 "Counter": "0,1,2,3",
82 "EventCode": "0x50",
83 "EventName": "UNC_CHA_REQUESTS.READS_REMOTE",
84 "PerPkg": "1",
85 "UMask": "0x02",
86 "Unit": "CHA"
87 },
88 {
89 "BriefDescription": "write requests from home agent",
90 "Counter": "0,1,2,3",
91 "EventCode": "0x50",
92 "EventName": "UNC_CHA_REQUESTS.WRITES",
93 "PerPkg": "1",
94 "UMask": "0x0C",
95 "Unit": "CHA"
96 },
97 {
98 "BriefDescription": "write requests from local home agent",
99 "Counter": "0,1,2,3",
100 "EventCode": "0x50",
101 "EventName": "UNC_CHA_REQUESTS.WRITES_LOCAL",
102 "PerPkg": "1",
103 "UMask": "0x04",
104 "Unit": "CHA"
105 },
106 {
107 "BriefDescription": "write requests from remote home agent",
108 "Counter": "0,1,2,3",
109 "EventCode": "0x50",
110 "EventName": "UNC_CHA_REQUESTS.WRITES_REMOTE",
111 "PerPkg": "1",
112 "UMask": "0x08",
113 "Unit": "CHA"
114 },
115 {
116 "BriefDescription": "UPI interconnect send bandwidth for payload. Derived from unc_upi_txl_flits.all_data",
117 "Counter": "0,1,2,3",
118 "EventCode": "0x2",
119 "EventName": "UPI_DATA_BANDWIDTH_TX",
120 "PerPkg": "1",
121 "ScaleUnit": "7.11E-06Bytes",
122 "UMask": "0x0F",
123 "Unit": "UPI LL"
124 },
125 {
126 "BriefDescription": "PCI Express bandwidth reading at IIO. Derived from unc_iio_data_req_of_cpu.mem_read.part0",
127 "Counter": "0,1",
128 "EventCode": "0x83",
129 "EventName": "LLC_MISSES.PCIE_READ",
130 "FCMask": "0x07",
131 "Filter": "ch_mask=0x1f",
132 "MetricExpr": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART0 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART1 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART2 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART3",
133 "MetricName": "LLC_MISSES.PCIE_READ",
134 "PerPkg": "1",
135 "PortMask": "0x01",
136 "ScaleUnit": "4Bytes",
137 "UMask": "0x04",
138 "Unit": "IIO"
139 },
140 {
141 "BriefDescription": "PCI Express bandwidth writing at IIO. Derived from unc_iio_data_req_of_cpu.mem_write.part0",
142 "Counter": "0,1",
143 "EventCode": "0x83",
144 "EventName": "LLC_MISSES.PCIE_WRITE",
145 "FCMask": "0x07",
146 "Filter": "ch_mask=0x1f",
147 "MetricExpr": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART0 +UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART1 +UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART2 +UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART3",
148 "MetricName": "LLC_MISSES.PCIE_WRITE",
149 "PerPkg": "1",
150 "PortMask": "0x01",
151 "ScaleUnit": "4Bytes",
152 "UMask": "0x01",
153 "Unit": "IIO"
154 },
155 {
156 "BriefDescription": "PCI Express bandwidth writing at IIO, part 0",
157 "Counter": "0,1",
158 "EventCode": "0x83",
159 "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART0",
160 "FCMask": "0x07",
161 "MetricExpr": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART0 +UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART1 +UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART2 +UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART3",
162 "MetricName": "LLC_MISSES.PCIE_WRITE",
163 "PerPkg": "1",
164 "PortMask": "0x01",
165 "ScaleUnit": "4Bytes",
166 "UMask": "0x01",
167 "Unit": "IIO"
168 },
169 {
170 "BriefDescription": "PCI Express bandwidth writing at IIO, part 1",
171 "Counter": "0,1",
172 "EventCode": "0x83",
173 "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART1",
174 "FCMask": "0x07",
175 "PerPkg": "1",
176 "PortMask": "0x02",
177 "ScaleUnit": "4Bytes",
178 "UMask": "0x01",
179 "Unit": "IIO"
180 },
181 {
182 "BriefDescription": "PCI Express bandwidth writing at IIO, part 2",
183 "Counter": "0,1",
184 "EventCode": "0x83",
185 "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART2",
186 "FCMask": "0x07",
187 "PerPkg": "1",
188 "PortMask": "0x04",
189 "ScaleUnit": "4Bytes",
190 "UMask": "0x01",
191 "Unit": "IIO"
192 },
193 {
194 "BriefDescription": "PCI Express bandwidth writing at IIO, part 3",
195 "Counter": "0,1",
196 "EventCode": "0x83",
197 "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART3",
198 "FCMask": "0x07",
199 "PerPkg": "1",
200 "PortMask": "0x08",
201 "ScaleUnit": "4Bytes",
202 "UMask": "0x01",
203 "Unit": "IIO"
204 },
205 {
206 "BriefDescription": "PCI Express bandwidth reading at IIO, part 0",
207 "Counter": "0,1",
208 "EventCode": "0x83",
209 "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART0",
210 "FCMask": "0x07",
211 "MetricExpr": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART0 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART1 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART2 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART3",
212 "MetricName": "LLC_MISSES.PCIE_READ",
213 "PerPkg": "1",
214 "PortMask": "0x01",
215 "ScaleUnit": "4Bytes",
216 "UMask": "0x04",
217 "Unit": "IIO"
218 },
219 {
220 "BriefDescription": "PCI Express bandwidth reading at IIO, part 1",
221 "Counter": "0,1",
222 "EventCode": "0x83",
223 "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART1",
224 "FCMask": "0x07",
225 "PerPkg": "1",
226 "PortMask": "0x02",
227 "ScaleUnit": "4Bytes",
228 "UMask": "0x04",
229 "Unit": "IIO"
230 },
231 {
232 "BriefDescription": "PCI Express bandwidth reading at IIO, part 2",
233 "Counter": "0,1",
234 "EventCode": "0x83",
235 "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART2",
236 "FCMask": "0x07",
237 "PerPkg": "1",
238 "PortMask": "0x04",
239 "ScaleUnit": "4Bytes",
240 "UMask": "0x04",
241 "Unit": "IIO"
242 },
243 {
244 "BriefDescription": "PCI Express bandwidth reading at IIO, part 3",
245 "Counter": "0,1",
246 "EventCode": "0x83",
247 "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART3",
248 "FCMask": "0x07",
249 "PerPkg": "1",
250 "PortMask": "0x08",
251 "ScaleUnit": "4Bytes",
252 "UMask": "0x04",
253 "Unit": "IIO"
254 },
255 {
256 "BriefDescription": "Core Cross Snoops Issued; Multiple Core Requests",
257 "Counter": "0,1,2,3",
258 "EventCode": "0x33",
259 "EventName": "UNC_CHA_CORE_SNP.CORE_GTONE",
260 "PerPkg": "1",
261 "PublicDescription": "Counts the number of transactions that trigger a configurable number of cross snoops. Cores are snooped if the transaction looks up the cache and determines that it is necessary based on the operation type and what CoreValid bits are set. For example, if 2 CV bits are set on a data read, the cores must have the data in S state so it is not necessary to snoop them. However, if only 1 CV bit is set the core my have modified the data. If the transaction was an RFO, it would need to invalidate the lines. This event can be filtered based on who triggered the initial snoop(s).",
262 "UMask": "0x42",
263 "Unit": "CHA"
264 },
265 {
266 "BriefDescription": "Core Cross Snoops Issued; Multiple Eviction",
267 "Counter": "0,1,2,3",
268 "EventCode": "0x33",
269 "EventName": "UNC_CHA_CORE_SNP.EVICT_GTONE",
270 "PerPkg": "1",
271 "PublicDescription": "Counts the number of transactions that trigger a configurable number of cross snoops. Cores are snooped if the transaction looks up the cache and determines that it is necessary based on the operation type and what CoreValid bits are set. For example, if 2 CV bits are set on a data read, the cores must have the data in S state so it is not necessary to snoop them. However, if only 1 CV bit is set the core my have modified the data. If the transaction was an RFO, it would need to invalidate the lines. This event can be filtered based on who triggered the initial snoop(s).",
272 "UMask": "0x82",
273 "Unit": "CHA"
274 },
275 {
276 "BriefDescription": "Multi-socket cacheline Directory state lookups; Snoop Not Needed",
277 "Counter": "0,1,2,3",
278 "EventCode": "0x53",
279 "EventName": "UNC_CHA_DIR_LOOKUP.NO_SNP",
280 "PerPkg": "1",
281 "PublicDescription": "Counts transactions that looked into the multi-socket cacheline Directory state, and therefore did not send a snoop because the Directory indicated it was not needed",
282 "UMask": "0x02",
283 "Unit": "CHA"
284 },
285 {
286 "BriefDescription": "Multi-socket cacheline Directory state lookups; Snoop Needed",
287 "Counter": "0,1,2,3",
288 "EventCode": "0x53",
289 "EventName": "UNC_CHA_DIR_LOOKUP.SNP",
290 "PerPkg": "1",
291 "PublicDescription": "Counts transactions that looked into the multi-socket cacheline Directory state, and sent one or more snoops, because the Directory indicated it was needed",
292 "UMask": "0x01",
293 "Unit": "CHA"
294 },
295 {
296 "BriefDescription": "Multi-socket cacheline Directory state updates; Directory Updated memory write from the HA pipe",
297 "Counter": "0,1,2,3",
298 "EventCode": "0x54",
299 "EventName": "UNC_CHA_DIR_UPDATE.HA",
300 "PerPkg": "1",
301 "PublicDescription": "Counts only multi-socket cacheline Directory state updates memory writes issued from the HA pipe. This does not include memory write requests which are for I (Invalid) or E (Exclusive) cachelines.",
302 "UMask": "0x01",
303 "Unit": "CHA"
304 },
305 {
306 "BriefDescription": "Multi-socket cacheline Directory state updates; Directory Updated memory write from TOR pipe",
307 "Counter": "0,1,2,3",
308 "EventCode": "0x54",
309 "EventName": "UNC_CHA_DIR_UPDATE.TOR",
310 "PerPkg": "1",
311 "PublicDescription": "Counts only multi-socket cacheline Directory state updates due to memory writes issued from the TOR pipe which are the result of remote transaction hitting the SF/LLC and returning data Core2Core. This does not include memory write requests which are for I (Invalid) or E (Exclusive) cachelines.",
312 "UMask": "0x02",
313 "Unit": "CHA"
314 },
315 {
316 "BriefDescription": "Read request from a remote socket which hit in the HitMe Cache to a line In the E state",
317 "Counter": "0,1,2,3",
318 "EventCode": "0x5F",
319 "EventName": "UNC_CHA_HITME_HIT.EX_RDS",
320 "PerPkg": "1",
321 "PublicDescription": "Counts read requests from a remote socket which hit in the HitME cache (used to cache the multi-socket Directory state) to a line in the E(Exclusive) state. This includes the following read opcodes (RdCode, RdData, RdDataMigratory, RdCur, RdInv*, Inv*)",
322 "UMask": "0x01",
323 "Unit": "CHA"
324 },
325 {
326 "BriefDescription": "Normal priority reads issued to the memory controller from the CHA",
327 "Counter": "0,1,2,3",
328 "EventCode": "0x59",
329 "EventName": "UNC_CHA_IMC_READS_COUNT.NORMAL",
330 "PerPkg": "1",
331 "PublicDescription": "Counts when a normal (Non-Isochronous) read is issued to any of the memory controller channels from the CHA.",
332 "UMask": "0x01",
333 "Unit": "CHA"
334 },
335 {
336 "BriefDescription": "CHA to iMC Full Line Writes Issued; Full Line Non-ISOCH",
337 "Counter": "0,1,2,3",
338 "EventCode": "0x5B",
339 "EventName": "UNC_CHA_IMC_WRITES_COUNT.FULL",
340 "PerPkg": "1",
341 "PublicDescription": "Counts when a normal (Non-Isochronous) full line write is issued from the CHA to the any of the memory controller channels.",
342 "UMask": "0x01",
343 "Unit": "CHA"
344 },
345 {
346 "BriefDescription": "Number of times that an RFO hit in S state.",
347 "Counter": "0,1,2,3",
348 "EventCode": "0x39",
349 "EventName": "UNC_CHA_MISC.RFO_HIT_S",
350 "PerPkg": "1",
351 "PublicDescription": "Counts when a RFO (the Read for Ownership issued before a write) request hit a cacheline in the S (Shared) state.",
352 "UMask": "0x08",
353 "Unit": "CHA"
354 },
355 {
356 "BriefDescription": "Local requests for exclusive ownership of a cache line without receiving data",
357 "Counter": "0,1,2,3",
358 "EventCode": "0x50",
359 "EventName": "UNC_CHA_REQUESTS.INVITOE_LOCAL",
360 "PerPkg": "1",
361 "PublicDescription": "Counts the total number of requests coming from a unit on this socket for exclusive ownership of a cache line without receiving data (INVITOE) to the CHA.",
362 "UMask": "0x10",
363 "Unit": "CHA"
364 },
365 {
366 "BriefDescription": "Local requests for exclusive ownership of a cache line without receiving data",
367 "Counter": "0,1,2,3",
368 "EventCode": "0x50",
369 "EventName": "UNC_CHA_REQUESTS.INVITOE_REMOTE",
370 "PerPkg": "1",
371 "PublicDescription": "Counts the total number of requests coming from a remote socket for exclusive ownership of a cache line without receiving data (INVITOE) to the CHA.",
372 "UMask": "0x20",
373 "Unit": "CHA"
374 },
375 {
376 "BriefDescription": "RspCnflct* Snoop Responses Received",
377 "Counter": "0,1,2,3",
378 "EventCode": "0x5C",
379 "EventName": "UNC_CHA_SNOOP_RESP.RSPCNFLCTS",
380 "PerPkg": "1",
381 "PublicDescription": "Counts when a a transaction with the opcode type RspCnflct* Snoop Response was received. This is returned when a snoop finds an existing outstanding transaction in a remote caching agent. This triggers conflict resolution hardware. This covers both the opcode RspCnflct and RspCnflctWbI.",
382 "UMask": "0x40",
383 "Unit": "CHA"
384 },
385 {
386 "BriefDescription": "RspI Snoop Responses Received",
387 "Counter": "0,1,2,3",
388 "EventCode": "0x5C",
389 "EventName": "UNC_CHA_SNOOP_RESP.RSPI",
390 "PerPkg": "1",
391 "PublicDescription": "Counts when a transaction with the opcode type RspI Snoop Response was received which indicates the remote cache does not have the data, or when the remote cache silently evicts data (such as when an RFO: the Read for Ownership issued before a write hits non-modified data).",
392 "UMask": "0x01",
393 "Unit": "CHA"
394 },
395 {
396 "BriefDescription": "RspIFwd Snoop Responses Received",
397 "Counter": "0,1,2,3",
398 "EventCode": "0x5C",
399 "EventName": "UNC_CHA_SNOOP_RESP.RSPIFWD",
400 "PerPkg": "1",
401 "PublicDescription": "Counts when a a transaction with the opcode type RspIFwd Snoop Response was received which indicates a remote caching agent forwarded the data and the requesting agent is able to acquire the data in E (Exclusive) or M (modified) states. This is commonly returned with RFO (the Read for Ownership issued before a write) transactions. The snoop could have either been to a cacheline in the M,E,F (Modified, Exclusive or Forward) states.",
402 "UMask": "0x04",
403 "Unit": "CHA"
404 },
405 {
406 "BriefDescription": "RspSFwd Snoop Responses Received",
407 "Counter": "0,1,2,3",
408 "EventCode": "0x5C",
409 "EventName": "UNC_CHA_SNOOP_RESP.RSPSFWD",
410 "PerPkg": "1",
411 "PublicDescription": "Counts when a a transaction with the opcode type RspSFwd Snoop Response was received which indicates a remote caching agent forwarded the data but held on to its current copy. This is common for data and code reads that hit in a remote socket in E (Exclusive) or F (Forward) state.",
412 "UMask": "0x08",
413 "Unit": "CHA"
414 },
415 {
416 "BriefDescription": "Rsp*Fwd*WB Snoop Responses Received",
417 "Counter": "0,1,2,3",
418 "EventCode": "0x5C",
419 "EventName": "UNC_CHA_SNOOP_RESP.RSP_FWD_WB",
420 "PerPkg": "1",
421 "PublicDescription": "Counts when a transaction with the opcode type Rsp*Fwd*WB Snoop Response was received which indicates the data was written back to it's home socket, and the cacheline was forwarded to the requestor socket. This snoop response is only used in >= 4 socket systems. It is used when a snoop HITM's in a remote caching agent and it directly forwards data to a requestor, and simultaneously returns data to it's home socket to be written back to memory.",
422 "UMask": "0x20",
423 "Unit": "CHA"
424 },
425 {
426 "BriefDescription": "Rsp*WB Snoop Responses Received",
427 "Counter": "0,1,2,3",
428 "EventCode": "0x5C",
429 "EventName": "UNC_CHA_SNOOP_RESP.RSP_WBWB",
430 "PerPkg": "1",
431 "PublicDescription": "Counts when a transaction with the opcode type Rsp*WB Snoop Response was received which indicates which indicates the data was written back to it's home. This is returned when a non-RFO request hits a cacheline in the Modified state. The Cache can either downgrade the cacheline to a S (Shared) or I (Invalid) state depending on how the system has been configured. This reponse will also be sent when a cache requests E (Exclusive) ownership of a cache line without receiving data, because the cache must acquire ownership.",
432 "UMask": "0x10",
433 "Unit": "CHA"
434 },
435 {
436 "BriefDescription": "Clockticks of the IIO Traffic Controller",
437 "Counter": "0,1,2,3",
438 "EventCode": "0x1",
439 "EventName": "UNC_IIO_CLOCKTICKS",
440 "PerPkg": "1",
441 "PublicDescription": "Counts clockticks of the 1GHz trafiic controller clock in the IIO unit.",
442 "Unit": "IIO"
443 },
444 {
445 "BriefDescription": "Read request for 4 bytes made by the CPU to IIO Part0",
446 "Counter": "2,3",
447 "EventCode": "0xC0",
448 "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART0",
449 "FCMask": "0x07",
450 "PerPkg": "1",
451 "PortMask": "0x01",
452 "PublicDescription": "Counts every read request for 4 bytes of data made by a unit on the main die (generally a core) to the MMIO space of a card on IIO Part0. In the general case, Part0 refers to a standard PCIe card of any size (x16,x8,x4) that is plugged directly into one of the PCIe slots. Part0 could also refer to any device plugged into the first slot of a PCIe riser card or to a device attached to the IIO unit which starts its use of the bus using lane 0 of the 16 lanes supported by the bus.",
453 "UMask": "0x04",
454 "Unit": "IIO"
455 },
456 {
457 "BriefDescription": "Read request for 4 bytes made by the CPU to IIO Part1",
458 "Counter": "2,3",
459 "EventCode": "0xC0",
460 "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART1",
461 "FCMask": "0x07",
462 "PerPkg": "1",
463 "PortMask": "0x02",
464 "PublicDescription": "Counts every read request for 4 bytes of data made by a unit on the main die (generally a core) to the MMIO space of a card on IIO Part1. In the general case, Part1 refers to a x4 PCIe card plugged into the second slot of a PCIe riser card, but it could refer to any x4 device attached to the IIO unit using lanes starting at lane 4 of the 16 lanes supported by the bus.",
465 "UMask": "0x04",
466 "Unit": "IIO"
467 },
468 {
469 "BriefDescription": "Read request for 4 bytes made by the CPU to IIO Part2",
470 "Counter": "2,3",
471 "EventCode": "0xC0",
472 "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART2",
473 "FCMask": "0x07",
474 "PerPkg": "1",
475 "PortMask": "0x04",
476 "PublicDescription": "Counts every read request for 4 bytes of data made by a unit on the main die (generally a core) to the MMIO space of a card on IIO Part2. In the general case, Part2 refers to a x4 or x8 PCIe card plugged into the third slot of a PCIe riser card, but it could refer to any x4 or x8 device attached to the IIO unit and using lanes starting at lane 8 of the 16 lanes supported by the bus.",
477 "UMask": "0x04",
478 "Unit": "IIO"
479 },
480 {
481 "BriefDescription": "Read request for 4 bytes made by the CPU to IIO Part3",
482 "Counter": "2,3",
483 "EventCode": "0xC0",
484 "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART3",
485 "FCMask": "0x07",
486 "PerPkg": "1",
487 "PortMask": "0x08",
488 "PublicDescription": "Counts every read request for 4 bytes of data made by a unit on the main die (generally a core) to the MMIO space of a card on IIO Part3. In the general case, Part3 refers to a x4 PCIe card plugged into the fourth slot of a PCIe riser card, but it could brefer to any device attached to the IIO unit using the lanes starting at lane 12 of the 16 lanes supported by the bus.",
489 "UMask": "0x04",
490 "Unit": "IIO"
491 },
492 {
493 "BriefDescription": "Write request of 4 bytes made to IIO Part0 by the CPU",
494 "Counter": "2,3",
495 "EventCode": "0xC0",
496 "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART0",
497 "FCMask": "0x07",
498 "PerPkg": "1",
499 "PortMask": "0x01",
500 "PublicDescription": "Counts every write request of 4 bytes of data made to the MMIO space of a card on IIO Part0 by a unit on the main die (generally a core). In the general case, Part0 refers to a standard PCIe card of any size (x16,x8,x4) that is plugged directly into one of the PCIe slots. Part0 could also refer to any device plugged into the first slot of a PCIe riser card or to a device attached to the IIO unit which starts its use of the bus using lane 0 of the 16 lanes supported by the bus.",
501 "UMask": "0x01",
502 "Unit": "IIO"
503 },
504 {
505 "BriefDescription": "Write request of 4 bytes made to IIO Part1 by the CPU",
506 "Counter": "2,3",
507 "EventCode": "0xC0",
508 "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART1",
509 "FCMask": "0x07",
510 "PerPkg": "1",
511 "PortMask": "0x02",
512 "PublicDescription": "Counts every write request of 4 bytes of data made to the MMIO space of a card on IIO Part1 by a unit on the main die (generally a core). In the general case, Part1 refers to a x4 PCIe card plugged into the second slot of a PCIe riser card, but it could refer to any x4 device attached to the IIO unit using lanes starting at lane 4 of the 16 lanes supported by the bus.",
513 "UMask": "0x01",
514 "Unit": "IIO"
515 },
516 {
517 "BriefDescription": "Write request of 4 bytes made to IIO Part2 by the CPU ",
518 "Counter": "2,3",
519 "EventCode": "0xC0",
520 "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART2",
521 "FCMask": "0x07",
522 "PerPkg": "1",
523 "PortMask": "0x04",
524 "PublicDescription": "Counts every write request of 4 bytes of data made to the MMIO space of a card on IIO Part2 by a unit on the main die (generally a core). In the general case, Part2 refers to a x4 or x8 PCIe card plugged into the third slot of a PCIe riser card, but it could refer to any x4 or x8 device attached to the IIO unit and using lanes starting at lane 8 of the 16 lanes supported by the bus.",
525 "UMask": "0x01",
526 "Unit": "IIO"
527 },
528 {
529 "BriefDescription": "Write request of 4 bytes made to IIO Part3 by the CPU ",
530 "Counter": "2,3",
531 "EventCode": "0xC0",
532 "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART3",
533 "FCMask": "0x07",
534 "PerPkg": "1",
535 "PortMask": "0x08",
536 "PublicDescription": "Counts every write request of 4 bytes of data made to the MMIO space of a card on IIO Part3 by a unit on the main die (generally a core). In the general case, Part3 refers to a x4 PCIe card plugged into the fourth slot of a PCIe riser card, but it could brefer to any device attached to the IIO unit using the lanes starting at lane 12 of the 16 lanes supported by the bus.",
537 "UMask": "0x01",
538 "Unit": "IIO"
539 },
540 {
541 "BriefDescription": "Read request for up to a 64 byte transaction is made by the CPU to IIO Part0",
542 "Counter": "0,1,2,3",
543 "EventCode": "0xC1",
544 "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART0",
545 "FCMask": "0x07",
546 "PerPkg": "1",
547 "PortMask": "0x01",
548 "PublicDescription": "Counts every read request for up to a 64 byte transaction of data made by a unit on the main die (generally a core) to the MMIO space of a card on IIO Part0. In the general case, part0 refers to a standard PCIe card of any size (x16,x8,x4) that is plugged directly into one of the PCIe slots. Part0 could also refer to any device plugged into the first slot of a PCIe riser card or to a device attached to the IIO unit which starts its use of the bus using lane 0 of the 16 lanes supported by the bus.",
549 "UMask": "0x04",
550 "Unit": "IIO"
551 },
552 {
553 "BriefDescription": "Read request for up to a 64 byte transaction is made by the CPU to IIO Part1",
554 "Counter": "0,1,2,3",
555 "EventCode": "0xC1",
556 "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART1",
557 "FCMask": "0x07",
558 "PerPkg": "1",
559 "PortMask": "0x02",
560 "PublicDescription": "Counts every read request for up to a 64 byte transaction of data made by a unit on the main die (generally a core) to the MMIO space of a card on IIO Part1. In the general case, Part1 refers to a x4 PCIe card plugged into the second slot of a PCIe riser card, but it could refer to any x4 device attached to the IIO unit using lanes starting at lane 4 of the 16 lanes supported by the bus.",
561 "UMask": "0x04",
562 "Unit": "IIO"
563 },
564 {
565 "BriefDescription": "Read request for up to a 64 byte transaction is made by the CPU to IIO Part2",
566 "Counter": "0,1,2,3",
567 "EventCode": "0xC1",
568 "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART2",
569 "FCMask": "0x07",
570 "PerPkg": "1",
571 "PortMask": "0x04",
572 "PublicDescription": "Counts every read request for up to a 64 byte transaction of data made by a unit on the main die (generally a core) to the MMIO space of a card on IIO Part2. In the general case, Part2 refers to a x4 or x8 PCIe card plugged into the third slot of a PCIe riser card, but it could refer to any x4 or x8 device attached to the IIO unit and using lanes starting at lane 8 of the 16 lanes supported by the bus.",
573 "UMask": "0x04",
574 "Unit": "IIO"
575 },
576 {
577 "BriefDescription": "Read request for up to a 64 byte transaction is made by the CPU to IIO Part3",
578 "Counter": "0,1,2,3",
579 "EventCode": "0xC1",
580 "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART3",
581 "FCMask": "0x07",
582 "PerPkg": "1",
583 "PortMask": "0x08",
584 "PublicDescription": "Counts every read request for up to a 64 byte transaction of data made by a unit on the main die (generally a core) to the MMIO space of a card on IIO Part3. In the general case, Part3 refers to a x4 PCIe card plugged into the fourth slot of a PCIe riser card, but it could brefer to any device attached to the IIO unit using the lanes starting at lane 12 of the 16 lanes supported by the bus.",
585 "UMask": "0x04",
586 "Unit": "IIO"
587 },
588 {
589 "BriefDescription": "Write request of up to a 64 byte transaction is made to IIO Part0 by the CPU",
590 "Counter": "0,1,2,3",
591 "EventCode": "0xC1",
592 "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART0",
593 "FCMask": "0x07",
594 "PerPkg": "1",
595 "PortMask": "0x01",
596 "PublicDescription": "Counts every write request of up to a 64 byte transaction of data made to the MMIO space of a card on IIO Part0 by a unit on the main die (generally a core). In the general case, Part0 refers to a standard PCIe card of any size (x16,x8,x4) that is plugged directly into one of the PCIe slots. Part0 could also refer to any device plugged into the first slot of a PCIe riser card or to a device attached to the IIO unit which starts its use of the bus using lane 0 of the 16 lanes supported by the bus.",
597 "UMask": "0x01",
598 "Unit": "IIO"
599 },
600 {
601 "BriefDescription": "Write request of up to a 64 byte transaction is made to IIO Part1 by the CPU",
602 "Counter": "0,1,2,3",
603 "EventCode": "0xC1",
604 "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART1",
605 "FCMask": "0x07",
606 "PerPkg": "1",
607 "PortMask": "0x02",
608 "PublicDescription": "Counts every write request of up to a 64 byte transaction of data made to the MMIO space of a card on IIO Part1 by a unit on the main die (generally a core). In the general case, Part1 refers to a x4 PCIe card plugged into the second slot of a PCIe riser card, but it could refer to any x4 device attached to the IIO unit using lanes starting at lane 4 of the 16 lanes supported by the bus.",
609 "UMask": "0x01",
610 "Unit": "IIO"
611 },
612 {
613 "BriefDescription": "Write request of up to a 64 byte transaction is made to IIO Part2 by the CPU ",
614 "Counter": "0,1,2,3",
615 "EventCode": "0xC1",
616 "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART2",
617 "FCMask": "0x07",
618 "PerPkg": "1",
619 "PortMask": "0x04",
620 "PublicDescription": "Counts every write request of up to a 64 byte transaction of data made to the MMIO space of a card on IIO Part2 by a unit on the main die (generally a core). In the general case, Part2 refers to a x4 or x8 PCIe card plugged into the third slot of a PCIe riser card, but it could refer to any x4 or x8 device attached to the IIO unit and using lanes starting at lane 8 of the 16 lanes supported by the bus.",
621 "UMask": "0x01",
622 "Unit": "IIO"
623 },
624 {
625 "BriefDescription": "Write request of up to a 64 byte transaction is made to IIO Part3 by the CPU ",
626 "Counter": "0,1,2,3",
627 "EventCode": "0xC1",
628 "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART3",
629 "FCMask": "0x07",
630 "PerPkg": "1",
631 "PortMask": "0x08",
632 "PublicDescription": "Counts every write request of up to a 64 byte transaction of data made to the MMIO space of a card on IIO Part3 by a unit on the main die (generally a core). In the general case, Part3 refers to a x4 PCIe card plugged into the fourth slot of a PCIe riser card, but it could brefer to any device attached to the IIO unit using the lanes starting at lane 12 of the 16 lanes supported by the bus.",
633 "UMask": "0x01",
634 "Unit": "IIO"
635 },
636 {
637 "BriefDescription": "Read request for up to a 64 byte transaction is made by IIO Part0 to Memory",
638 "Counter": "0,1,2,3",
639 "EventCode": "0x84",
640 "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART0",
641 "FCMask": "0x07",
642 "PerPkg": "1",
643 "PortMask": "0x01",
644 "PublicDescription": "Counts every read request for up to a 64 byte transaction of data made by IIO Part0 to a unit on the main die (generally memory). In the general case, Part0 refers to a standard PCIe card of any size (x16,x8,x4) that is plugged directly into one of the PCIe slots. Part0 could also refer to any device plugged into the first slot of a PCIe riser card or to a device attached to the IIO unit which starts its use of the bus using lane 0 of the 16 lanes supported by the bus.",
645 "UMask": "0x04",
646 "Unit": "IIO"
647 },
648 {
649 "BriefDescription": "Read request for up to a 64 byte transaction is made by IIO Part1 to Memory",
650 "Counter": "0,1,2,3",
651 "EventCode": "0x84",
652 "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART1",
653 "FCMask": "0x07",
654 "PerPkg": "1",
655 "PortMask": "0x02",
656 "PublicDescription": "Counts every read request for up to a 64 byte transaction of data made by IIO Part1 to a unit on the main die (generally memory). In the general case, Part1 refers to a x4 PCIe card plugged into the second slot of a PCIe riser card, but it could refer to any x4 device attached to the IIO unit using lanes starting at lane 4 of the 16 lanes supported by the bus.",
657 "UMask": "0x04",
658 "Unit": "IIO"
659 },
660 {
661 "BriefDescription": "Read request for up to a 64 byte transaction is made by IIO Part2 to Memory",
662 "Counter": "0,1,2,3",
663 "EventCode": "0x84",
664 "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART2",
665 "FCMask": "0x07",
666 "PerPkg": "1",
667 "PortMask": "0x04",
668 "PublicDescription": "Counts every read request for up to a 64 byte transaction of data made by IIO Part2 to a unit on the main die (generally memory). In the general case, Part2 refers to a x4 or x8 PCIe card plugged into the third slot of a PCIe riser card, but it could refer to any x4 or x8 device attached to the IIO unit and using lanes starting at lane 8 of the 16 lanes supported by the bus.",
669 "UMask": "0x04",
670 "Unit": "IIO"
671 },
672 {
673 "BriefDescription": "Read request for up to a 64 byte transaction is made by IIO Part3 to Memory",
674 "Counter": "0,1,2,3",
675 "EventCode": "0x84",
676 "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART3",
677 "FCMask": "0x07",
678 "PerPkg": "1",
679 "PortMask": "0x08",
680 "PublicDescription": "Counts every read request for up to a 64 byte transaction of data made by IIO Part3 to a unit on the main die (generally memory). In the general case, Part3 refers to a x4 PCIe card plugged into the fourth slot of a PCIe riser card, but it could brefer to any device attached to the IIO unit using the lanes starting at lane 12 of the 16 lanes supported by the bus.",
681 "UMask": "0x04",
682 "Unit": "IIO"
683 },
684 {
685 "BriefDescription": "Write request of up to a 64 byte transaction is made by IIO Part0 to Memory",
686 "Counter": "0,1,2,3",
687 "EventCode": "0x84",
688 "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART0",
689 "FCMask": "0x07",
690 "PerPkg": "1",
691 "PortMask": "0x01",
692 "PublicDescription": "Counts every write request of up to a 64 byte transaction of data made by IIO Part0 to a unit on the main die (generally memory). In the general case, Part0 refers to a standard PCIe card of any size (x16,x8,x4) that is plugged directly into one of the PCIe slots. Part0 could also refer to any device plugged into the first slot of a PCIe riser card or to a device attached to the IIO unit which starts its use of the bus using lane 0 of the 16 lanes supported by the bus.",
693 "UMask": "0x01",
694 "Unit": "IIO"
695 },
696 {
697 "BriefDescription": "Write request of up to a 64 byte transaction is made by IIO Part1 to Memory",
698 "Counter": "0,1,2,3",
699 "EventCode": "0x84",
700 "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART1",
701 "FCMask": "0x07",
702 "PerPkg": "1",
703 "PortMask": "0x02",
704 "PublicDescription": "Counts every write request of up to a 64 byte transaction of data made by IIO Part1 to a unit on the main die (generally memory). In the general case, Part1 refers to a x4 PCIe card plugged into the second slot of a PCIe riser card, but it could refer to any x4 device attached to the IIO unit using lanes starting at lane 4 of the 16 lanes supported by the bus.",
705 "UMask": "0x01",
706 "Unit": "IIO"
707 },
708 {
709 "BriefDescription": "Write request of up to a 64 byte transaction is made by IIO Part2 to Memory",
710 "Counter": "0,1,2,3",
711 "EventCode": "0x84",
712 "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART2",
713 "FCMask": "0x07",
714 "PerPkg": "1",
715 "PortMask": "0x04",
716 "PublicDescription": "Counts every write request of up to a 64 byte transaction of data made by IIO Part2 to a unit on the main die (generally memory). In the general case, Part2 refers to a x4 or x8 PCIe card plugged into the third slot of a PCIe riser card, but it could refer to any x4 or x8 device attached to the IIO unit and using lanes starting at lane 8 of the 16 lanes supported by the bus.",
717 "UMask": "0x01",
718 "Unit": "IIO"
719 },
720 {
721 "BriefDescription": "Write request of up to a 64 byte transaction is made by IIO Part3 to Memory",
722 "Counter": "0,1,2,3",
723 "EventCode": "0x84",
724 "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART3",
725 "FCMask": "0x07",
726 "PerPkg": "1",
727 "PortMask": "0x08",
728 "PublicDescription": "Counts every write request of up to a 64 byte transaction of data made by IIO Part3 to a unit on the main die (generally memory). In the general case, Part3 refers to a x4 PCIe card plugged into the fourth slot of a PCIe riser card, but it could brefer to any device attached to the IIO unit using the lanes starting at lane 12 of the 16 lanes supported by the bus.",
729 "UMask": "0x01",
730 "Unit": "IIO"
731 },
732 {
733 "BriefDescription": "Traffic in which the M2M to iMC Bypass was not taken",
734 "Counter": "0,1,2,3",
735 "EventCode": "0x22",
736 "EventName": "UNC_M2M_BYPASS_M2M_Egress.NOT_TAKEN",
737 "PerPkg": "1",
738 "PublicDescription": "Counts traffic in which the M2M (Mesh to Memory) to iMC (Memory Controller) bypass was not taken",
739 "UMask": "0x2",
740 "Unit": "M2M"
741 },
742 {
743 "BriefDescription": "Cycles when direct to core mode (which bypasses the CHA) was disabled",
744 "Counter": "0,1,2,3",
745 "EventCode": "0x24",
746 "EventName": "UNC_M2M_DIRECT2CORE_NOT_TAKEN_DIRSTATE",
747 "PerPkg": "1",
748 "PublicDescription": "Counts cycles when direct to core mode (which bypasses the CHA) was disabled",
749 "Unit": "M2M"
750 },
751 {
752 "BriefDescription": "Messages sent direct to core (bypassing the CHA)",
753 "Counter": "0,1,2,3",
754 "EventCode": "0x23",
755 "EventName": "UNC_M2M_DIRECT2CORE_TAKEN",
756 "PerPkg": "1",
757 "PublicDescription": "Counts when messages were sent direct to core (bypassing the CHA)",
758 "Unit": "M2M"
759 },
760 {
761 "BriefDescription": "Number of reads in which direct to core transaction were overridden",
762 "Counter": "0,1,2,3",
763 "EventCode": "0x25",
764 "EventName": "UNC_M2M_DIRECT2CORE_TXN_OVERRIDE",
765 "PerPkg": "1",
766 "PublicDescription": "Counts reads in which direct to core transactions (which would have bypassed the CHA) were overridden",
767 "Unit": "M2M"
768 },
769 {
770 "BriefDescription": "Number of reads in which direct to Intel UPI transactions were overridden",
771 "Counter": "0,1,2,3",
772 "EventCode": "0x28",
773 "EventName": "UNC_M2M_DIRECT2UPI_NOT_TAKEN_CREDITS",
774 "PerPkg": "1",
775 "PublicDescription": "Counts reads in which direct to Intel Ultra Path Interconnect (UPI) transactions (which would have bypassed the CHA) were overridden",
776 "Unit": "M2M"
777 },
778 {
779 "BriefDescription": "Cycles when direct to Intel UPI was disabled",
780 "Counter": "0,1,2,3",
781 "EventCode": "0x27",
782 "EventName": "UNC_M2M_DIRECT2UPI_NOT_TAKEN_DIRSTATE",
783 "PerPkg": "1",
784 "PublicDescription": "Counts cycles when the ability to send messages direct to the Intel Ultra Path Interconnect (bypassing the CHA) was disabled",
785 "Unit": "M2M"
786 },
787 {
788 "BriefDescription": "Messages sent direct to the Intel UPI",
789 "Counter": "0,1,2,3",
790 "EventCode": "0x26",
791 "EventName": "UNC_M2M_DIRECT2UPI_TAKEN",
792 "PerPkg": "1",
793 "PublicDescription": "Counts when messages were sent direct to the Intel Ultra Path Interconnect (bypassing the CHA)",
794 "Unit": "M2M"
795 },
796 {
797 "BriefDescription": "Number of reads that a message sent direct2 Intel UPI was overridden",
798 "Counter": "0,1,2,3",
799 "EventCode": "0x29",
800 "EventName": "UNC_M2M_DIRECT2UPI_TXN_OVERRIDE",
801 "PerPkg": "1",
802 "PublicDescription": "Counts when a read message that was sent direct to the Intel Ultra Path Interconnect (bypassing the CHA) was overridden",
803 "Unit": "M2M"
804 },
805 {
806 "BriefDescription": "Multi-socket cacheline Directory lookups (any state found)",
807 "Counter": "0,1,2,3",
808 "EventCode": "0x2D",
809 "EventName": "UNC_M2M_DIRECTORY_LOOKUP.ANY",
810 "PerPkg": "1",
811 "PublicDescription": "Counts when the M2M (Mesh to Memory) looks into the multi-socket cacheline Directory state, and found the cacheline marked in Any State (A, I, S or unused)",
812 "UMask": "0x1",
813 "Unit": "M2M"
814 },
815 {
816 "BriefDescription": "Multi-socket cacheline Directory lookups (cacheline found in A state) ",
817 "Counter": "0,1,2,3",
818 "EventCode": "0x2D",
819 "EventName": "UNC_M2M_DIRECTORY_LOOKUP.STATE_A",
820 "PerPkg": "1",
821 "PublicDescription": "Counts when the M2M (Mesh to Memory) looks into the multi-socket cacheline Directory state, and found the cacheline marked in the A (SnoopAll) state, indicating the cacheline is stored in another socket in any state, and we must snoop the other sockets to make sure we get the latest data. The data may be stored in any state in the local socket.",
822 "UMask": "0x8",
823 "Unit": "M2M"
824 },
825 {
826 "BriefDescription": "Multi-socket cacheline Directory lookup (cacheline found in I state) ",
827 "Counter": "0,1,2,3",
828 "EventCode": "0x2D",
829 "EventName": "UNC_M2M_DIRECTORY_LOOKUP.STATE_I",
830 "PerPkg": "1",
831 "PublicDescription": "Counts when the M2M (Mesh to Memory) looks into the multi-socket cacheline Directory state , and found the cacheline marked in the I (Invalid) state indicating the cacheline is not stored in another socket, and so there is no need to snoop the other sockets for the latest data. The data may be stored in any state in the local socket.",
832 "UMask": "0x2",
833 "Unit": "M2M"
834 },
835 {
836 "BriefDescription": "Multi-socket cacheline Directory lookup (cacheline found in S state) ",
837 "Counter": "0,1,2,3",
838 "EventCode": "0x2D",
839 "EventName": "UNC_M2M_DIRECTORY_LOOKUP.STATE_S",
840 "PerPkg": "1",
841 "PublicDescription": "Counts when the M2M (Mesh to Memory) looks into the multi-socket cacheline Directory state , and found the cacheline marked in the S (Shared) state indicating the cacheline is either stored in another socket in the S(hared) state , and so there is no need to snoop the other sockets for the latest data. The data may be stored in any state in the local socket.",
842 "UMask": "0x4",
843 "Unit": "M2M"
844 },
845 {
846 "BriefDescription": "Multi-socket cacheline Directory update from A to I",
847 "Counter": "0,1,2,3",
848 "EventCode": "0x2E",
849 "EventName": "UNC_M2M_DIRECTORY_UPDATE.A2I",
850 "PerPkg": "1",
851 "PublicDescription": "Counts when the M2M (Mesh to Memory) updates the multi-socket cacheline Directory state from from A (SnoopAll) to I (Invalid)",
852 "UMask": "0x20",
853 "Unit": "M2M"
854 },
855 {
856 "BriefDescription": "Multi-socket cacheline Directory update from A to S",
857 "Counter": "0,1,2,3",
858 "EventCode": "0x2E",
859 "EventName": "UNC_M2M_DIRECTORY_UPDATE.A2S",
860 "PerPkg": "1",
861 "PublicDescription": "Counts when the M2M (Mesh to Memory) updates the multi-socket cacheline Directory state from from A (SnoopAll) to S (Shared)",
862 "UMask": "0x40",
863 "Unit": "M2M"
864 },
865 {
866 "BriefDescription": "Multi-socket cacheline Directory update from/to Any state ",
867 "Counter": "0,1,2,3",
868 "EventCode": "0x2E",
869 "EventName": "UNC_M2M_DIRECTORY_UPDATE.ANY",
870 "PerPkg": "1",
871 "PublicDescription": "Counts when the M2M (Mesh to Memory) updates the multi-socket cacheline Directory to a new state",
872 "UMask": "0x1",
873 "Unit": "M2M"
874 },
875 {
876 "BriefDescription": "Multi-socket cacheline Directory update from I to A",
877 "Counter": "0,1,2,3",
878 "EventCode": "0x2E",
879 "EventName": "UNC_M2M_DIRECTORY_UPDATE.I2A",
880 "PerPkg": "1",
881 "PublicDescription": "Counts when the M2M (Mesh to Memory) updates the multi-socket cacheline Directory state from from I (Invalid) to A (SnoopAll)",
882 "UMask": "0x4",
883 "Unit": "M2M"
884 },
885 {
886 "BriefDescription": "Multi-socket cacheline Directory update from I to S",
887 "Counter": "0,1,2,3",
888 "EventCode": "0x2E",
889 "EventName": "UNC_M2M_DIRECTORY_UPDATE.I2S",
890 "PerPkg": "1",
891 "PublicDescription": "Counts when the M2M (Mesh to Memory) updates the multi-socket cacheline Directory state from from I (Invalid) to S (Shared)",
892 "UMask": "0x2",
893 "Unit": "M2M"
894 },
895 {
896 "BriefDescription": "Multi-socket cacheline Directory update from S to A",
897 "Counter": "0,1,2,3",
898 "EventCode": "0x2E",
899 "EventName": "UNC_M2M_DIRECTORY_UPDATE.S2A",
900 "PerPkg": "1",
901 "PublicDescription": "Counts when the M2M (Mesh to Memory) updates the multi-socket cacheline Directory state from from S (Shared) to A (SnoopAll)",
902 "UMask": "0x10",
903 "Unit": "M2M"
904 },
905 {
906 "BriefDescription": "Multi-socket cacheline Directory update from S to I",
907 "Counter": "0,1,2,3",
908 "EventCode": "0x2E",
909 "EventName": "UNC_M2M_DIRECTORY_UPDATE.S2I",
910 "PerPkg": "1",
911 "PublicDescription": "Counts when the M2M (Mesh to Memory) updates the multi-socket cacheline Directory state from from S (Shared) to I (Invalid)",
912 "UMask": "0x8",
913 "Unit": "M2M"
914 },
915 {
916 "BriefDescription": "Reads to iMC issued",
917 "Counter": "0,1,2,3",
918 "EventCode": "0x37",
919 "EventName": "UNC_M2M_IMC_READS.ALL",
920 "PerPkg": "1",
921 "PublicDescription": "Counts when the M2M (Mesh to Memory) issues reads to the iMC (Memory Controller). ",
922 "UMask": "0x4",
923 "Unit": "M2M"
924 },
925 {
926 "BriefDescription": "Reads to iMC issued at Normal Priority (Non-Isochronous)",
927 "Counter": "0,1,2,3",
928 "EventCode": "0x37",
929 "EventName": "UNC_M2M_IMC_READS.NORMAL",
930 "PerPkg": "1",
931 "PublicDescription": "Counts when the M2M (Mesh to Memory) issues reads to the iMC (Memory Controller). It only counts normal priority non-isochronous reads.",
932 "UMask": "0x1",
933 "Unit": "M2M"
934 },
935 {
936 "BriefDescription": "Writes to iMC issued",
937 "Counter": "0,1,2,3",
938 "EventCode": "0x38",
939 "EventName": "UNC_M2M_IMC_WRITES.ALL",
940 "PerPkg": "1",
941 "PublicDescription": "Counts when the M2M (Mesh to Memory) issues writes to the iMC (Memory Controller).",
942 "UMask": "0x10",
943 "Unit": "M2M"
944 },
945 {
946 "BriefDescription": "Partial Non-Isochronous writes to the iMC",
947 "Counter": "0,1,2,3",
948 "EventCode": "0x38",
949 "EventName": "UNC_M2M_IMC_WRITES.PARTIAL",
950 "PerPkg": "1",
951 "PublicDescription": "Counts when the M2M (Mesh to Memory) issues partial writes to the iMC (Memory Controller). It only counts normal priority non-isochronous writes.",
952 "UMask": "0x2",
953 "Unit": "M2M"
954 },
955 {
956 "BriefDescription": "Prefecth requests that got turn into a demand request",
957 "Counter": "0,1,2,3",
958 "EventCode": "0x56",
959 "EventName": "UNC_M2M_PREFCAM_DEMAND_PROMOTIONS",
960 "PerPkg": "1",
961 "PublicDescription": "Counts when the M2M (Mesh to Memory) promotes a outstanding request in the prefetch queue due to a subsequent demand read request that entered the M2M with the same address. Explanatory Side Note: The Prefecth queue is made of CAM (Content Addressable Memory)",
962 "Unit": "M2M"
963 },
964 {
965 "BriefDescription": "Inserts into the Memory Controller Prefetch Queue",
966 "Counter": "0,1,2,3",
967 "EventCode": "0x57",
968 "EventName": "UNC_M2M_PREFCAM_INSERTS",
969 "PerPkg": "1",
970 "PublicDescription": "Counts when the M2M (Mesh to Memory) recieves a prefetch request and inserts it into its outstanding prefetch queue. Explanatory Side Note: the prefect queue is made from CAM: Content Addressable Memory",
971 "Unit": "M2M"
972 },
973 {
974 "BriefDescription": "AD Ingress (from CMS) Queue Inserts",
975 "Counter": "0,1,2,3",
976 "EventCode": "0x1",
977 "EventName": "UNC_M2M_RxC_AD_INSERTS",
978 "PerPkg": "1",
979 "PublicDescription": "Counts when the a new entry is Received(RxC) and then added to the AD (Address Ring) Ingress Queue from the CMS (Common Mesh Stop). This is generally used for reads, and ",
980 "Unit": "M2M"
981 },
982 {
983 "BriefDescription": "Prefetches generated by the flow control queue of the M3UPI unit.",
984 "Counter": "0,1,2,3",
985 "EventCode": "0x29",
986 "EventName": "UNC_M3UPI_UPI_PREFETCH_SPAWN",
987 "PerPkg": "1",
988 "PublicDescription": "Count cases where flow control queue that sits between the Intel Ultra Path Interconnect (UPI) and the mesh spawns a prefetch to the iMC (Memory Controller)",
989 "Unit": "M3UPI"
990 },
991 {
992 "BriefDescription": "Clocks of the Intel Ultra Path Interconnect (UPI)",
993 "Counter": "0,1,2,3",
994 "EventCode": "0x1",
995 "EventName": "UNC_UPI_CLOCKTICKS",
996 "PerPkg": "1",
997 "PublicDescription": "Counts clockticks of the fixed frequency clock controlling the Intel Ultra Path Interconnect (UPI). This clock runs at1/8th the 'GT/s' speed of the UPI link. For example, a 9.6GT/s link will have a fixed Frequency of 1.2 Ghz.",
998 "Unit": "UPI LL"
999 },
1000 {
1001 "BriefDescription": "Data Response packets that go direct to core",
1002 "Counter": "0,1,2,3",
1003 "EventCode": "0x12",
1004 "EventName": "UNC_UPI_DIRECT_ATTEMPTS.D2C",
1005 "PerPkg": "1",
1006 "PublicDescription": "Counts Data Response (DRS) packets that attempted to go direct to core bypassing the CHA.",
1007 "UMask": "0x1",
1008 "Unit": "UPI LL"
1009 },
1010 {
1011 "BriefDescription": "Data Response packets that go direct to Intel UPI",
1012 "Counter": "0,1,2,3",
1013 "EventCode": "0x12",
1014 "EventName": "UNC_UPI_DIRECT_ATTEMPTS.D2U",
1015 "PerPkg": "1",
1016 "PublicDescription": "Counts Data Response (DRS) packets that attempted to go direct to Intel Ultra Path Interconnect (UPI) bypassing the CHA .",
1017 "UMask": "0x2",
1018 "Unit": "UPI LL"
1019 },
1020 {
1021 "BriefDescription": "Cycles Intel UPI is in L1 power mode (shutdown)",
1022 "Counter": "0,1,2,3",
1023 "EventCode": "0x21",
1024 "EventName": "UNC_UPI_L1_POWER_CYCLES",
1025 "PerPkg": "1",
1026 "PublicDescription": "Counts cycles when the Intel Ultra Path Interconnect (UPI) is in L1 power mode. L1 is a mode that totally shuts down the UPI link. Link power states are per link and per direction, so for example the Tx direction could be in one state while Rx was in another, this event only coutns when both links are shutdown.",
1027 "Unit": "UPI LL"
1028 },
1029 {
1030 "BriefDescription": "Cycles the Rx of the Intel UPI is in L0p power mode",
1031 "Counter": "0,1,2,3",
1032 "EventCode": "0x25",
1033 "EventName": "UNC_UPI_RxL0P_POWER_CYCLES",
1034 "PerPkg": "1",
1035 "PublicDescription": "Counts cycles when the the receive side (Rx) of the Intel Ultra Path Interconnect(UPI) is in L0p power mode. L0p is a mode where we disable 60% of the UPI lanes, decreasing our bandwidth in order to save power.",
1036 "Unit": "UPI LL"
1037 },
1038 {
1039 "BriefDescription": "FLITs received which bypassed the Slot0 Receive Buffer",
1040 "Counter": "0,1,2,3",
1041 "EventCode": "0x31",
1042 "EventName": "UNC_UPI_RxL_BYPASSED.SLOT0",
1043 "PerPkg": "1",
1044 "PublicDescription": "Counts incoming FLITs (FLow control unITs) which bypassed the slot0 RxQ buffer (Receive Queue) and passed directly to the Egress. This is a latency optimization, and should generally be the common case. If this value is less than the number of FLITs transfered, it implies that there was queueing getting onto the ring, and thus the transactions saw higher latency.",
1045 "UMask": "0x1",
1046 "Unit": "UPI LL"
1047 },
1048 {
1049 "BriefDescription": "FLITs received which bypassed the Slot0 Receive Buffer",
1050 "Counter": "0,1,2,3",
1051 "EventCode": "0x31",
1052 "EventName": "UNC_UPI_RxL_BYPASSED.SLOT1",
1053 "PerPkg": "1",
1054 "PublicDescription": "Counts incoming FLITs (FLow control unITs) which bypassed the slot1 RxQ buffer (Receive Queue) and passed directly across the BGF and into the Egress. This is a latency optimization, and should generally be the common case. If this value is less than the number of FLITs transfered, it implies that there was queueing getting onto the ring, and thus the transactions saw higher latency.",
1055 "UMask": "0x2",
1056 "Unit": "UPI LL"
1057 },
1058 {
1059 "BriefDescription": "FLITs received which bypassed the Slot0 Recieve Buffer",
1060 "Counter": "0,1,2,3",
1061 "EventCode": "0x31",
1062 "EventName": "UNC_UPI_RxL_BYPASSED.SLOT2",
1063 "PerPkg": "1",
1064 "PublicDescription": "Counts incoming FLITs (FLow control unITs) whcih bypassed the slot2 RxQ buffer (Receive Queue) and passed directly to the Egress. This is a latency optimization, and should generally be the common case. If this value is less than the number of FLITs transfered, it implies that there was queueing getting onto the ring, and thus the transactions saw higher latency.",
1065 "UMask": "0x4",
1066 "Unit": "UPI LL"
1067 },
1068 {
1069 "BriefDescription": "Valid data FLITs received from any slot",
1070 "Counter": "0,1,2,3",
1071 "EventCode": "0x3",
1072 "EventName": "UNC_UPI_RxL_FLITS.ALL_DATA",
1073 "PerPkg": "1",
1074 "PublicDescription": "Counts valid data FLITs (80 bit FLow control unITs: 64bits of data) received from any of the 3 Intel Ultra Path Interconnect (UPI) Receive Queue slots on this UPI unit.",
1075 "UMask": "0x0F",
1076 "Unit": "UPI LL"
1077 },
1078 {
1079 "BriefDescription": "Null FLITs received from any slot",
1080 "Counter": "0,1,2,3",
1081 "EventCode": "0x3",
1082 "EventName": "UNC_UPI_RxL_FLITS.ALL_NULL",
1083 "PerPkg": "1",
1084 "PublicDescription": "Counts null FLITs (80 bit FLow control unITs) received from any of the 3 Intel Ultra Path Interconnect (UPI) Receive Queue slots on this UPI unit.",
1085 "UMask": "0x27",
1086 "Unit": "UPI LL"
1087 },
1088 {
1089 "BriefDescription": "Protocol header and credit FLITs received from any slot",
1090 "Counter": "0,1,2,3",
1091 "EventCode": "0x3",
1092 "EventName": "UNC_UPI_RxL_FLITS.NON_DATA",
1093 "PerPkg": "1",
1094 "PublicDescription": "Counts protocol header and credit FLITs (80 bit FLow control unITs) received from any of the 3 UPI slots on this UPI unit.",
1095 "UMask": "0x97",
1096 "Unit": "UPI LL"
1097 },
1098 {
1099 "BriefDescription": "Cycles in which the Tx of the Intel Ultra Path Interconnect (UPI) is in L0p power mode",
1100 "Counter": "0,1,2,3",
1101 "EventCode": "0x27",
1102 "EventName": "UNC_UPI_TxL0P_POWER_CYCLES",
1103 "PerPkg": "1",
1104 "PublicDescription": "Counts cycles when the transmit side (Tx) of the Intel Ultra Path Interconnect(UPI) is in L0p power mode. L0p is a mode where we disable 60% of the UPI lanes, decreasing our bandwidth in order to save power.",
1105 "Unit": "UPI LL"
1106 },
1107 {
1108 "BriefDescription": "FLITs that bypassed the TxL Buffer",
1109 "Counter": "0,1,2,3",
1110 "EventCode": "0x41",
1111 "EventName": "UNC_UPI_TxL_BYPASSED",
1112 "PerPkg": "1",
1113 "PublicDescription": "Counts incoming FLITs (FLow control unITs) which bypassed the TxL(transmit) FLIT buffer and pass directly out the UPI Link. Generally, when data is transmitted across the Intel Ultra Path Interconnect (UPI), it will bypass the TxQ and pass directly to the link. However, the TxQ will be used in L0p (Low Power) mode and (Link Layer Retry) LLR mode, increasing latency to transfer out to the link.",
1114 "Unit": "UPI LL"
1115 },
1116 {
1117 "BriefDescription": "UPI interconnect send bandwidth for payload. Derived from unc_upi_txl_flits.all_data",
1118 "Counter": "0,1,2,3",
1119 "EventCode": "0x2",
1120 "EventName": "UPI_DATA_BANDWIDTH_TX",
1121 "PerPkg": "1",
1122 "ScaleUnit": "7.11E-06Bytes",
1123 "UMask": "0x0F",
1124 "Unit": "UPI LL"
1125 },
1126 {
1127 "BriefDescription": "Null FLITs transmitted from any slot",
1128 "Counter": "0,1,2,3",
1129 "EventCode": "0x2",
1130 "EventName": "UNC_UPI_TxL_FLITS.ALL_NULL",
1131 "PerPkg": "1",
1132 "PublicDescription": "Counts null FLITs (80 bit FLow control unITs) transmitted via any of the 3 Intel Ulra Path Interconnect (UPI) slots on this UPI unit.",
1133 "UMask": "0x27",
1134 "Unit": "UPI LL"
1135 },
1136 {
1137 "BriefDescription": "Idle FLITs transmitted",
1138 "Counter": "0,1,2,3",
1139 "EventCode": "0x2",
1140 "EventName": "UNC_UPI_TxL_FLITS.IDLE",
1141 "PerPkg": "1",
1142 "PublicDescription": "Counts when the Intel Ultra Path Interconnect(UPI) transmits an idle FLIT(80 bit FLow control unITs). Every UPI cycle must be sending either data FLITs, protocol/credit FLITs or idle FLITs.",
1143 "UMask": "0x47",
1144 "Unit": "UPI LL"
1145 },
1146 {
1147 "BriefDescription": "Protocol header and credit FLITs transmitted across any slot",
1148 "Counter": "0,1,2,3",
1149 "EventCode": "0x2",
1150 "EventName": "UNC_UPI_TxL_FLITS.NON_DATA",
1151 "PerPkg": "1",
1152 "PublicDescription": "Counts protocol header and credit FLITs (80 bit FLow control unITs) transmitted across any of the 3 UPI (Ultra Path Interconnect) slots on this UPI unit.",
1153 "UMask": "0x97",
1154 "Unit": "UPI LL"
1155 }
1156]
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/virtual-memory.json b/tools/perf/pmu-events/arch/x86/skylakex/virtual-memory.json
new file mode 100644
index 000000000000..70750dab7ead
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylakex/virtual-memory.json
@@ -0,0 +1,284 @@
1[
2 {
3 "EventCode": "0x08",
4 "UMask": "0x1",
5 "BriefDescription": "Load misses in all DTLB levels that cause page walks",
6 "Counter": "0,1,2,3",
7 "EventName": "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK",
8 "PublicDescription": "Counts demand data loads that caused a page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels, but the walk need not have completed.",
9 "SampleAfterValue": "100003",
10 "CounterHTOff": "0,1,2,3,4,5,6,7"
11 },
12 {
13 "EventCode": "0x08",
14 "UMask": "0x2",
15 "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (4K).",
16 "Counter": "0,1,2,3",
17 "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
18 "PublicDescription": "Counts demand data loads that caused a completed page walk (4K page size). This implies it missed in all TLB levels. The page walk can end with or without a fault.",
19 "SampleAfterValue": "2000003",
20 "CounterHTOff": "0,1,2,3,4,5,6,7"
21 },
22 {
23 "EventCode": "0x08",
24 "UMask": "0x4",
25 "BriefDescription": "Demand load Miss in all translation lookaside buffer (TLB) levels causes a page walk that completes (2M/4M).",
26 "Counter": "0,1,2,3",
27 "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
28 "PublicDescription": "Counts demand data loads that caused a completed page walk (2M and 4M page sizes). This implies it missed in all TLB levels. The page walk can end with or without a fault.",
29 "SampleAfterValue": "2000003",
30 "CounterHTOff": "0,1,2,3,4,5,6,7"
31 },
32 {
33 "EventCode": "0x08",
34 "UMask": "0x8",
35 "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (1G)",
36 "Counter": "0,1,2,3",
37 "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1G",
38 "PublicDescription": "Counts load misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
39 "SampleAfterValue": "2000003",
40 "CounterHTOff": "0,1,2,3,4,5,6,7"
41 },
42 {
43 "EventCode": "0x08",
44 "UMask": "0xe",
45 "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (All page sizes)",
46 "Counter": "0,1,2,3",
47 "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
48 "PublicDescription": "Counts demand data loads that caused a completed page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels. The page walk can end with or without a fault.",
49 "SampleAfterValue": "100003",
50 "CounterHTOff": "0,1,2,3,4,5,6,7"
51 },
52 {
53 "EventCode": "0x08",
54 "UMask": "0x10",
55 "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a load. EPT page walk duration are excluded in Skylake. ",
56 "Counter": "0,1,2,3",
57 "EventName": "DTLB_LOAD_MISSES.WALK_PENDING",
58 "PublicDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a load. EPT page walk duration are excluded in Skylake microarchitecture. ",
59 "SampleAfterValue": "2000003",
60 "CounterHTOff": "0,1,2,3,4,5,6,7"
61 },
62 {
63 "EventCode": "0x08",
64 "UMask": "0x10",
65 "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a load. EPT page walk duration are excluded in Skylake. ",
66 "Counter": "0,1,2,3",
67 "EventName": "DTLB_LOAD_MISSES.WALK_ACTIVE",
68 "CounterMask": "1",
69 "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a load.",
70 "SampleAfterValue": "100003",
71 "CounterHTOff": "0,1,2,3,4,5,6,7"
72 },
73 {
74 "EventCode": "0x08",
75 "UMask": "0x20",
76 "BriefDescription": "Loads that miss the DTLB and hit the STLB.",
77 "Counter": "0,1,2,3",
78 "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
79 "PublicDescription": "Counts loads that miss the DTLB (Data TLB) and hit the STLB (Second level TLB).",
80 "SampleAfterValue": "2000003",
81 "CounterHTOff": "0,1,2,3,4,5,6,7"
82 },
83 {
84 "EventCode": "0x49",
85 "UMask": "0x1",
86 "BriefDescription": "Store misses in all DTLB levels that cause page walks",
87 "Counter": "0,1,2,3",
88 "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
89 "PublicDescription": "Counts demand data stores that caused a page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels, but the walk need not have completed.",
90 "SampleAfterValue": "100003",
91 "CounterHTOff": "0,1,2,3,4,5,6,7"
92 },
93 {
94 "EventCode": "0x49",
95 "UMask": "0x2",
96 "BriefDescription": "Store miss in all TLB levels causes a page walk that completes. (4K)",
97 "Counter": "0,1,2,3",
98 "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
99 "PublicDescription": "Counts demand data stores that caused a completed page walk (4K page size). This implies it missed in all TLB levels. The page walk can end with or without a fault.",
100 "SampleAfterValue": "100003",
101 "CounterHTOff": "0,1,2,3,4,5,6,7"
102 },
103 {
104 "EventCode": "0x49",
105 "UMask": "0x4",
106 "BriefDescription": "Store misses in all DTLB levels that cause completed page walks (2M/4M)",
107 "Counter": "0,1,2,3",
108 "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
109 "PublicDescription": "Counts demand data stores that caused a completed page walk (2M and 4M page sizes). This implies it missed in all TLB levels. The page walk can end with or without a fault.",
110 "SampleAfterValue": "100003",
111 "CounterHTOff": "0,1,2,3,4,5,6,7"
112 },
113 {
114 "EventCode": "0x49",
115 "UMask": "0x8",
116 "BriefDescription": "Store misses in all DTLB levels that cause completed page walks (1G)",
117 "Counter": "0,1,2,3",
118 "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1G",
119 "PublicDescription": "Counts store misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
120 "SampleAfterValue": "100003",
121 "CounterHTOff": "0,1,2,3,4,5,6,7"
122 },
123 {
124 "EventCode": "0x49",
125 "UMask": "0xe",
126 "BriefDescription": "Store misses in all TLB levels causes a page walk that completes. (All page sizes)",
127 "Counter": "0,1,2,3",
128 "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
129 "PublicDescription": "Counts demand data stores that caused a completed page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels. The page walk can end with or without a fault.",
130 "SampleAfterValue": "100003",
131 "CounterHTOff": "0,1,2,3,4,5,6,7"
132 },
133 {
134 "EventCode": "0x49",
135 "UMask": "0x10",
136 "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a store. EPT page walk duration are excluded in Skylake. ",
137 "Counter": "0,1,2,3",
138 "EventName": "DTLB_STORE_MISSES.WALK_PENDING",
139 "PublicDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a store. EPT page walk duration are excluded in Skylake microarchitecture. ",
140 "SampleAfterValue": "2000003",
141 "CounterHTOff": "0,1,2,3,4,5,6,7"
142 },
143 {
144 "EventCode": "0x49",
145 "UMask": "0x10",
146 "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a store. EPT page walk duration are excluded in Skylake. ",
147 "Counter": "0,1,2,3",
148 "EventName": "DTLB_STORE_MISSES.WALK_ACTIVE",
149 "CounterMask": "1",
150 "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a store.",
151 "SampleAfterValue": "100003",
152 "CounterHTOff": "0,1,2,3,4,5,6,7"
153 },
154 {
155 "EventCode": "0x49",
156 "UMask": "0x20",
157 "BriefDescription": "Stores that miss the DTLB and hit the STLB.",
158 "Counter": "0,1,2,3",
159 "EventName": "DTLB_STORE_MISSES.STLB_HIT",
160 "PublicDescription": "Stores that miss the DTLB (Data TLB) and hit the STLB (2nd Level TLB).",
161 "SampleAfterValue": "100003",
162 "CounterHTOff": "0,1,2,3,4,5,6,7"
163 },
164 {
165 "EventCode": "0x4F",
166 "UMask": "0x10",
167 "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a EPT (Extended Page Table) walk for any request type.",
168 "Counter": "0,1,2,3",
169 "EventName": "EPT.WALK_PENDING",
170 "PublicDescription": "Counts cycles for each PMH (Page Miss Handler) that is busy with an EPT (Extended Page Table) walk for any request type.",
171 "SampleAfterValue": "2000003",
172 "CounterHTOff": "0,1,2,3,4,5,6,7"
173 },
174 {
175 "EventCode": "0x85",
176 "UMask": "0x1",
177 "BriefDescription": "Misses at all ITLB levels that cause page walks",
178 "Counter": "0,1,2,3",
179 "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
180 "PublicDescription": "Counts page walks of any page size (4K/2M/4M/1G) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB, but the walk need not have completed.",
181 "SampleAfterValue": "100003",
182 "CounterHTOff": "0,1,2,3,4,5,6,7"
183 },
184 {
185 "EventCode": "0x85",
186 "UMask": "0x2",
187 "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)",
188 "Counter": "0,1,2,3",
189 "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
190 "PublicDescription": "Counts completed page walks (4K page size) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB. The page walk can end with or without a fault.",
191 "SampleAfterValue": "100003",
192 "CounterHTOff": "0,1,2,3,4,5,6,7"
193 },
194 {
195 "EventCode": "0x85",
196 "UMask": "0x4",
197 "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (2M/4M)",
198 "Counter": "0,1,2,3",
199 "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
200 "PublicDescription": "Counts completed page walks of any page size (4K/2M/4M/1G) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB. The page walk can end with or without a fault.",
201 "SampleAfterValue": "100003",
202 "CounterHTOff": "0,1,2,3,4,5,6,7"
203 },
204 {
205 "EventCode": "0x85",
206 "UMask": "0x8",
207 "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (1G)",
208 "Counter": "0,1,2,3",
209 "EventName": "ITLB_MISSES.WALK_COMPLETED_1G",
210 "PublicDescription": "Counts store misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
211 "SampleAfterValue": "100003",
212 "CounterHTOff": "0,1,2,3,4,5,6,7"
213 },
214 {
215 "EventCode": "0x85",
216 "UMask": "0xe",
217 "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (All page sizes)",
218 "Counter": "0,1,2,3",
219 "EventName": "ITLB_MISSES.WALK_COMPLETED",
220 "PublicDescription": "Counts completed page walks (2M and 4M page sizes) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB. The page walk can end with or without a fault.",
221 "SampleAfterValue": "100003",
222 "CounterHTOff": "0,1,2,3,4,5,6,7"
223 },
224 {
225 "EventCode": "0x85",
226 "UMask": "0x10",
227 "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for an instruction fetch request. EPT page walk duration are excluded in Skylake. ",
228 "Counter": "0,1,2,3",
229 "EventName": "ITLB_MISSES.WALK_PENDING",
230 "PublicDescription": "Counts 1 per cycle for each PMH (Page Miss Handler) that is busy with a page walk for an instruction fetch request. EPT page walk duration are excluded in Skylake michroarchitecture. ",
231 "SampleAfterValue": "100003",
232 "CounterHTOff": "0,1,2,3,4,5,6,7"
233 },
234 {
235 "EventCode": "0x85",
236 "UMask": "0x10",
237 "BriefDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request. EPT page walk duration are excluded in Skylake.",
238 "Counter": "0,1,2,3",
239 "EventName": "ITLB_MISSES.WALK_ACTIVE",
240 "CounterMask": "1",
241 "PublicDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request. EPT page walk duration are excluded in Skylake microarchitecture.",
242 "SampleAfterValue": "100003",
243 "CounterHTOff": "0,1,2,3,4,5,6,7"
244 },
245 {
246 "EventCode": "0x85",
247 "UMask": "0x20",
248 "BriefDescription": "Instruction fetch requests that miss the ITLB and hit the STLB.",
249 "Counter": "0,1,2,3",
250 "EventName": "ITLB_MISSES.STLB_HIT",
251 "SampleAfterValue": "100003",
252 "CounterHTOff": "0,1,2,3,4,5,6,7"
253 },
254 {
255 "EventCode": "0xAE",
256 "UMask": "0x1",
257 "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
258 "Counter": "0,1,2,3",
259 "EventName": "ITLB.ITLB_FLUSH",
260 "PublicDescription": "Counts the number of flushes of the big or small ITLB pages. Counting include both TLB Flush (covering all sets) and TLB Set Clear (set-specific).",
261 "SampleAfterValue": "100007",
262 "CounterHTOff": "0,1,2,3,4,5,6,7"
263 },
264 {
265 "EventCode": "0xBD",
266 "UMask": "0x1",
267 "BriefDescription": "DTLB flush attempts of the thread-specific entries",
268 "Counter": "0,1,2,3",
269 "EventName": "TLB_FLUSH.DTLB_THREAD",
270 "PublicDescription": "Counts the number of DTLB flush attempts of the thread-specific entries.",
271 "SampleAfterValue": "100007",
272 "CounterHTOff": "0,1,2,3,4,5,6,7"
273 },
274 {
275 "EventCode": "0xBD",
276 "UMask": "0x20",
277 "BriefDescription": "STLB flush attempts",
278 "Counter": "0,1,2,3",
279 "EventName": "TLB_FLUSH.STLB_ANY",
280 "PublicDescription": "Counts the number of any STLB flush attempts (such as entire, VPID, PCID, InvPage, CR3 write, etc.).",
281 "SampleAfterValue": "100007",
282 "CounterHTOff": "0,1,2,3,4,5,6,7"
283 }
284] \ No newline at end of file
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
index bd0aabb2bd0f..9eb7047bafe4 100644
--- a/tools/perf/pmu-events/jevents.c
+++ b/tools/perf/pmu-events/jevents.c
@@ -137,6 +137,8 @@ static struct field {
137 { "AnyThread", "any=" }, 137 { "AnyThread", "any=" },
138 { "EdgeDetect", "edge=" }, 138 { "EdgeDetect", "edge=" },
139 { "SampleAfterValue", "period=" }, 139 { "SampleAfterValue", "period=" },
140 { "FCMask", "fc_mask=" },
141 { "PortMask", "ch_mask=" },
140 { NULL, NULL } 142 { NULL, NULL }
141}; 143};
142 144
@@ -290,7 +292,7 @@ static int print_events_table_entry(void *data, char *name, char *event,
290 char *desc, char *long_desc, 292 char *desc, char *long_desc,
291 char *pmu, char *unit, char *perpkg, 293 char *pmu, char *unit, char *perpkg,
292 char *metric_expr, 294 char *metric_expr,
293 char *metric_name) 295 char *metric_name, char *metric_group)
294{ 296{
295 struct perf_entry_data *pd = data; 297 struct perf_entry_data *pd = data;
296 FILE *outfp = pd->outfp; 298 FILE *outfp = pd->outfp;
@@ -302,8 +304,10 @@ static int print_events_table_entry(void *data, char *name, char *event,
302 */ 304 */
303 fprintf(outfp, "{\n"); 305 fprintf(outfp, "{\n");
304 306
305 fprintf(outfp, "\t.name = \"%s\",\n", name); 307 if (name)
306 fprintf(outfp, "\t.event = \"%s\",\n", event); 308 fprintf(outfp, "\t.name = \"%s\",\n", name);
309 if (event)
310 fprintf(outfp, "\t.event = \"%s\",\n", event);
307 fprintf(outfp, "\t.desc = \"%s\",\n", desc); 311 fprintf(outfp, "\t.desc = \"%s\",\n", desc);
308 fprintf(outfp, "\t.topic = \"%s\",\n", topic); 312 fprintf(outfp, "\t.topic = \"%s\",\n", topic);
309 if (long_desc && long_desc[0]) 313 if (long_desc && long_desc[0])
@@ -318,6 +322,8 @@ static int print_events_table_entry(void *data, char *name, char *event,
318 fprintf(outfp, "\t.metric_expr = \"%s\",\n", metric_expr); 322 fprintf(outfp, "\t.metric_expr = \"%s\",\n", metric_expr);
319 if (metric_name) 323 if (metric_name)
320 fprintf(outfp, "\t.metric_name = \"%s\",\n", metric_name); 324 fprintf(outfp, "\t.metric_name = \"%s\",\n", metric_name);
325 if (metric_group)
326 fprintf(outfp, "\t.metric_group = \"%s\",\n", metric_group);
321 fprintf(outfp, "},\n"); 327 fprintf(outfp, "},\n");
322 328
323 return 0; 329 return 0;
@@ -355,6 +361,9 @@ static char *real_event(const char *name, char *event)
355{ 361{
356 int i; 362 int i;
357 363
364 if (!name)
365 return NULL;
366
358 for (i = 0; fixed[i].name; i++) 367 for (i = 0; fixed[i].name; i++)
359 if (!strcasecmp(name, fixed[i].name)) 368 if (!strcasecmp(name, fixed[i].name))
360 return (char *)fixed[i].event; 369 return (char *)fixed[i].event;
@@ -367,7 +376,7 @@ int json_events(const char *fn,
367 char *long_desc, 376 char *long_desc,
368 char *pmu, char *unit, char *perpkg, 377 char *pmu, char *unit, char *perpkg,
369 char *metric_expr, 378 char *metric_expr,
370 char *metric_name), 379 char *metric_name, char *metric_group),
371 void *data) 380 void *data)
372{ 381{
373 int err = -EIO; 382 int err = -EIO;
@@ -395,6 +404,7 @@ int json_events(const char *fn,
395 char *unit = NULL; 404 char *unit = NULL;
396 char *metric_expr = NULL; 405 char *metric_expr = NULL;
397 char *metric_name = NULL; 406 char *metric_name = NULL;
407 char *metric_group = NULL;
398 unsigned long long eventcode = 0; 408 unsigned long long eventcode = 0;
399 struct msrmap *msr = NULL; 409 struct msrmap *msr = NULL;
400 jsmntok_t *msrval = NULL; 410 jsmntok_t *msrval = NULL;
@@ -474,6 +484,8 @@ int json_events(const char *fn,
474 addfield(map, &perpkg, "", "", val); 484 addfield(map, &perpkg, "", "", val);
475 } else if (json_streq(map, field, "MetricName")) { 485 } else if (json_streq(map, field, "MetricName")) {
476 addfield(map, &metric_name, "", "", val); 486 addfield(map, &metric_name, "", "", val);
487 } else if (json_streq(map, field, "MetricGroup")) {
488 addfield(map, &metric_group, "", "", val);
477 } else if (json_streq(map, field, "MetricExpr")) { 489 } else if (json_streq(map, field, "MetricExpr")) {
478 addfield(map, &metric_expr, "", "", val); 490 addfield(map, &metric_expr, "", "", val);
479 for (s = metric_expr; *s; s++) 491 for (s = metric_expr; *s; s++)
@@ -499,10 +511,11 @@ int json_events(const char *fn,
499 addfield(map, &event, ",", filter, NULL); 511 addfield(map, &event, ",", filter, NULL);
500 if (msr != NULL) 512 if (msr != NULL)
501 addfield(map, &event, ",", msr->pname, msrval); 513 addfield(map, &event, ",", msr->pname, msrval);
502 fixname(name); 514 if (name)
515 fixname(name);
503 516
504 err = func(data, name, real_event(name, event), desc, long_desc, 517 err = func(data, name, real_event(name, event), desc, long_desc,
505 pmu, unit, perpkg, metric_expr, metric_name); 518 pmu, unit, perpkg, metric_expr, metric_name, metric_group);
506 free(event); 519 free(event);
507 free(desc); 520 free(desc);
508 free(name); 521 free(name);
@@ -514,6 +527,7 @@ int json_events(const char *fn,
514 free(unit); 527 free(unit);
515 free(metric_expr); 528 free(metric_expr);
516 free(metric_name); 529 free(metric_name);
530 free(metric_group);
517 if (err) 531 if (err)
518 break; 532 break;
519 tok += j; 533 tok += j;
@@ -822,10 +836,6 @@ static int process_one_file(const char *fpath, const struct stat *sb,
822 * PMU event tables (see struct pmu_events_map). 836 * PMU event tables (see struct pmu_events_map).
823 * 837 *
824 * Write out the PMU events tables and the mapping table to pmu-event.c. 838 * Write out the PMU events tables and the mapping table to pmu-event.c.
825 *
826 * If unable to process the JSON or arch files, create an empty mapping
827 * table so we can continue to build/use perf even if we cannot use the
828 * PMU event aliases.
829 */ 839 */
830int main(int argc, char *argv[]) 840int main(int argc, char *argv[])
831{ 841{
@@ -836,6 +846,7 @@ int main(int argc, char *argv[])
836 const char *arch; 846 const char *arch;
837 const char *output_file; 847 const char *output_file;
838 const char *start_dirname; 848 const char *start_dirname;
849 struct stat stbuf;
839 850
840 prog = basename(argv[0]); 851 prog = basename(argv[0]);
841 if (argc < 4) { 852 if (argc < 4) {
@@ -857,11 +868,17 @@ int main(int argc, char *argv[])
857 return 2; 868 return 2;
858 } 869 }
859 870
871 sprintf(ldirname, "%s/%s", start_dirname, arch);
872
873 /* If architecture does not have any event lists, bail out */
874 if (stat(ldirname, &stbuf) < 0) {
875 pr_info("%s: Arch %s has no PMU event lists\n", prog, arch);
876 goto empty_map;
877 }
878
860 /* Include pmu-events.h first */ 879 /* Include pmu-events.h first */
861 fprintf(eventsfp, "#include \"../../pmu-events/pmu-events.h\"\n"); 880 fprintf(eventsfp, "#include \"../../pmu-events/pmu-events.h\"\n");
862 881
863 sprintf(ldirname, "%s/%s", start_dirname, arch);
864
865 /* 882 /*
866 * The mapfile allows multiple CPUids to point to the same JSON file, 883 * The mapfile allows multiple CPUids to point to the same JSON file,
867 * so, not sure if there is a need for symlinks within the pmu-events 884 * so, not sure if there is a need for symlinks within the pmu-events
@@ -878,6 +895,9 @@ int main(int argc, char *argv[])
878 if (rc && verbose) { 895 if (rc && verbose) {
879 pr_info("%s: Error walking file tree %s\n", prog, ldirname); 896 pr_info("%s: Error walking file tree %s\n", prog, ldirname);
880 goto empty_map; 897 goto empty_map;
898 } else if (rc < 0) {
899 /* Make build fail */
900 return 1;
881 } else if (rc) { 901 } else if (rc) {
882 goto empty_map; 902 goto empty_map;
883 } 903 }
@@ -892,7 +912,8 @@ int main(int argc, char *argv[])
892 912
893 if (process_mapfile(eventsfp, mapfile)) { 913 if (process_mapfile(eventsfp, mapfile)) {
894 pr_info("%s: Error processing mapfile %s\n", prog, mapfile); 914 pr_info("%s: Error processing mapfile %s\n", prog, mapfile);
895 goto empty_map; 915 /* Make build fail */
916 return 1;
896 } 917 }
897 918
898 return 0; 919 return 0;
diff --git a/tools/perf/pmu-events/jevents.h b/tools/perf/pmu-events/jevents.h
index 611fac01913d..4684c673c445 100644
--- a/tools/perf/pmu-events/jevents.h
+++ b/tools/perf/pmu-events/jevents.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef JEVENTS_H 2#ifndef JEVENTS_H
2#define JEVENTS_H 1 3#define JEVENTS_H 1
3 4
@@ -6,7 +7,7 @@ int json_events(const char *fn,
6 char *long_desc, 7 char *long_desc,
7 char *pmu, 8 char *pmu,
8 char *unit, char *perpkg, char *metric_expr, 9 char *unit, char *perpkg, char *metric_expr,
9 char *metric_name), 10 char *metric_name, char *metric_group),
10 void *data); 11 void *data);
11char *get_cpu_str(void); 12char *get_cpu_str(void);
12 13
diff --git a/tools/perf/pmu-events/jsmn.h b/tools/perf/pmu-events/jsmn.h
index d666b10cf25b..c7b0f6ea2a31 100644
--- a/tools/perf/pmu-events/jsmn.h
+++ b/tools/perf/pmu-events/jsmn.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __JSMN_H_ 2#ifndef __JSMN_H_
2#define __JSMN_H_ 3#define __JSMN_H_
3 4
diff --git a/tools/perf/pmu-events/json.h b/tools/perf/pmu-events/json.h
index 278ebd32cfb6..fbcd5a0590ad 100644
--- a/tools/perf/pmu-events/json.h
+++ b/tools/perf/pmu-events/json.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef JSON_H 2#ifndef JSON_H
2#define JSON_H 1 3#define JSON_H 1
3 4
diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h
index 569eab3688dd..92a4d15ee0b9 100644
--- a/tools/perf/pmu-events/pmu-events.h
+++ b/tools/perf/pmu-events/pmu-events.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PMU_EVENTS_H 2#ifndef PMU_EVENTS_H
2#define PMU_EVENTS_H 3#define PMU_EVENTS_H
3 4
@@ -15,6 +16,7 @@ struct pmu_event {
15 const char *perpkg; 16 const char *perpkg;
16 const char *metric_expr; 17 const char *metric_expr;
17 const char *metric_name; 18 const char *metric_name;
19 const char *metric_group;
18}; 20};
19 21
20/* 22/*
diff --git a/tools/perf/python/tracepoint.py b/tools/perf/python/tracepoint.py
index eb4dbed57de7..eb76f6516247 100755
--- a/tools/perf/python/tracepoint.py
+++ b/tools/perf/python/tracepoint.py
@@ -1,4 +1,5 @@
1#! /usr/bin/python 1#! /usr/bin/python
2# SPDX-License-Identifier: GPL-2.0
2# -*- python -*- 3# -*- python -*-
3# -*- coding: utf-8 -*- 4# -*- coding: utf-8 -*-
4 5
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Makefile.PL b/tools/perf/scripts/perl/Perf-Trace-Util/Makefile.PL
index decdeb0f6789..e8994332d7dc 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Makefile.PL
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Makefile.PL
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1use 5.010000; 2use 5.010000;
2use ExtUtils::MakeMaker; 3use ExtUtils::MakeMaker;
3# See lib/ExtUtils/MakeMaker.pm for details of how to influence 4# See lib/ExtUtils/MakeMaker.pm for details of how to influence
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py
index 9e0985794e20..81a56cd2b3c1 100755
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py
@@ -1,4 +1,5 @@
1# EventClass.py 1# EventClass.py
2# SPDX-License-Identifier: GPL-2.0
2# 3#
3# This is a library defining some events types classes, which could 4# This is a library defining some events types classes, which could
4# be used by other scripts to analyzing the perf samples. 5# be used by other scripts to analyzing the perf samples.
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
index 1d95009592eb..f6c84966e4f8 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
@@ -57,6 +57,7 @@ try:
57 'ia64' : audit.MACH_IA64, 57 'ia64' : audit.MACH_IA64,
58 'ppc' : audit.MACH_PPC, 58 'ppc' : audit.MACH_PPC,
59 'ppc64' : audit.MACH_PPC64, 59 'ppc64' : audit.MACH_PPC64,
60 'ppc64le' : audit.MACH_PPC64LE,
60 's390' : audit.MACH_S390, 61 's390' : audit.MACH_S390,
61 's390x' : audit.MACH_S390X, 62 's390x' : audit.MACH_S390X,
62 'i386' : audit.MACH_X86, 63 'i386' : audit.MACH_X86,
diff --git a/tools/perf/scripts/python/bin/export-to-sqlite-record b/tools/perf/scripts/python/bin/export-to-sqlite-record
new file mode 100644
index 000000000000..070204fd6d00
--- /dev/null
+++ b/tools/perf/scripts/python/bin/export-to-sqlite-record
@@ -0,0 +1,8 @@
1#!/bin/bash
2
3#
4# export perf data to a sqlite3 database. Can cover
5# perf ip samples (excluding the tracepoints). No special
6# record requirements, just record what you want to export.
7#
8perf record $@
diff --git a/tools/perf/scripts/python/bin/export-to-sqlite-report b/tools/perf/scripts/python/bin/export-to-sqlite-report
new file mode 100644
index 000000000000..5ff6033e70ba
--- /dev/null
+++ b/tools/perf/scripts/python/bin/export-to-sqlite-report
@@ -0,0 +1,29 @@
1#!/bin/bash
2# description: export perf data to a sqlite3 database
3# args: [database name] [columns] [calls]
4n_args=0
5for i in "$@"
6do
7 if expr match "$i" "-" > /dev/null ; then
8 break
9 fi
10 n_args=$(( $n_args + 1 ))
11done
12if [ "$n_args" -gt 3 ] ; then
13 echo "usage: export-to-sqlite-report [database name] [columns] [calls]"
14 exit
15fi
16if [ "$n_args" -gt 2 ] ; then
17 dbname=$1
18 columns=$2
19 calls=$3
20 shift 3
21elif [ "$n_args" -gt 1 ] ; then
22 dbname=$1
23 columns=$2
24 shift 2
25elif [ "$n_args" -gt 0 ] ; then
26 dbname=$1
27 shift
28fi
29perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/export-to-sqlite.py $dbname $columns $calls
diff --git a/tools/perf/scripts/python/call-graph-from-postgresql.py b/tools/perf/scripts/python/call-graph-from-sql.py
index e78fdc2a5a9d..b494a67a1c67 100644
--- a/tools/perf/scripts/python/call-graph-from-postgresql.py
+++ b/tools/perf/scripts/python/call-graph-from-sql.py
@@ -1,6 +1,6 @@
1#!/usr/bin/python2 1#!/usr/bin/python2
2# call-graph-from-postgresql.py: create call-graph from postgresql database 2# call-graph-from-sql.py: create call-graph from sql database
3# Copyright (c) 2014, Intel Corporation. 3# Copyright (c) 2014-2017, Intel Corporation.
4# 4#
5# This program is free software; you can redistribute it and/or modify it 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, 6# under the terms and conditions of the GNU General Public License,
@@ -11,18 +11,19 @@
11# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12# more details. 12# more details.
13 13
14# To use this script you will need to have exported data using the 14# To use this script you will need to have exported data using either the
15# export-to-postgresql.py script. Refer to that script for details. 15# export-to-sqlite.py or the export-to-postgresql.py script. Refer to those
16# scripts for details.
16# 17#
17# Following on from the example in the export-to-postgresql.py script, a 18# Following on from the example in the export scripts, a
18# call-graph can be displayed for the pt_example database like this: 19# call-graph can be displayed for the pt_example database like this:
19# 20#
20# python tools/perf/scripts/python/call-graph-from-postgresql.py pt_example 21# python tools/perf/scripts/python/call-graph-from-sql.py pt_example
21# 22#
22# Note this script supports connecting to remote databases by setting hostname, 23# Note that for PostgreSQL, this script supports connecting to remote databases
23# port, username, password, and dbname e.g. 24# by setting hostname, port, username, password, and dbname e.g.
24# 25#
25# python tools/perf/scripts/python/call-graph-from-postgresql.py "hostname=myhost username=myuser password=mypassword dbname=pt_example" 26# python tools/perf/scripts/python/call-graph-from-sql.py "hostname=myhost username=myuser password=mypassword dbname=pt_example"
26# 27#
27# The result is a GUI window with a tree representing a context-sensitive 28# The result is a GUI window with a tree representing a context-sensitive
28# call-graph. Expanding a couple of levels of the tree and adjusting column 29# call-graph. Expanding a couple of levels of the tree and adjusting column
@@ -160,7 +161,7 @@ class TreeItem():
160 '( SELECT short_name FROM dsos WHERE id = ( SELECT dso_id FROM symbols WHERE id = ( SELECT symbol_id FROM call_paths WHERE id = call_path_id ) ) ), ' 161 '( SELECT short_name FROM dsos WHERE id = ( SELECT dso_id FROM symbols WHERE id = ( SELECT symbol_id FROM call_paths WHERE id = call_path_id ) ) ), '
161 '( SELECT ip FROM call_paths where id = call_path_id ) ' 162 '( SELECT ip FROM call_paths where id = call_path_id ) '
162 'FROM calls WHERE parent_call_path_id = ' + str(self.call_path_id) + ' AND comm_id = ' + str(self.comm_id) + ' AND thread_id = ' + str(self.thread_id) + 163 'FROM calls WHERE parent_call_path_id = ' + str(self.call_path_id) + ' AND comm_id = ' + str(self.comm_id) + ' AND thread_id = ' + str(self.thread_id) +
163 'ORDER BY call_path_id') 164 ' ORDER BY call_path_id')
164 if not ret: 165 if not ret:
165 raise Exception("Query failed: " + query.lastError().text()) 166 raise Exception("Query failed: " + query.lastError().text())
166 last_call_path_id = 0 167 last_call_path_id = 0
@@ -291,29 +292,40 @@ class MainWindow(QMainWindow):
291 292
292if __name__ == '__main__': 293if __name__ == '__main__':
293 if (len(sys.argv) < 2): 294 if (len(sys.argv) < 2):
294 print >> sys.stderr, "Usage is: call-graph-from-postgresql.py <database name>" 295 print >> sys.stderr, "Usage is: call-graph-from-sql.py <database name>"
295 raise Exception("Too few arguments") 296 raise Exception("Too few arguments")
296 297
297 dbname = sys.argv[1] 298 dbname = sys.argv[1]
298 299
299 db = QSqlDatabase.addDatabase('QPSQL') 300 is_sqlite3 = False
300 301 try:
301 opts = dbname.split() 302 f = open(dbname)
302 for opt in opts: 303 if f.read(15) == "SQLite format 3":
303 if '=' in opt: 304 is_sqlite3 = True
304 opt = opt.split('=') 305 f.close()
305 if opt[0] == 'hostname': 306 except:
306 db.setHostName(opt[1]) 307 pass
307 elif opt[0] == 'port': 308
308 db.setPort(int(opt[1])) 309 if is_sqlite3:
309 elif opt[0] == 'username': 310 db = QSqlDatabase.addDatabase('QSQLITE')
310 db.setUserName(opt[1]) 311 else:
311 elif opt[0] == 'password': 312 db = QSqlDatabase.addDatabase('QPSQL')
312 db.setPassword(opt[1]) 313 opts = dbname.split()
313 elif opt[0] == 'dbname': 314 for opt in opts:
314 dbname = opt[1] 315 if '=' in opt:
315 else: 316 opt = opt.split('=')
316 dbname = opt 317 if opt[0] == 'hostname':
318 db.setHostName(opt[1])
319 elif opt[0] == 'port':
320 db.setPort(int(opt[1]))
321 elif opt[0] == 'username':
322 db.setUserName(opt[1])
323 elif opt[0] == 'password':
324 db.setPassword(opt[1])
325 elif opt[0] == 'dbname':
326 dbname = opt[1]
327 else:
328 dbname = opt
317 329
318 db.setDatabaseName(dbname) 330 db.setDatabaseName(dbname)
319 if not db.open(): 331 if not db.open():
diff --git a/tools/perf/scripts/python/event_analyzing_sample.py b/tools/perf/scripts/python/event_analyzing_sample.py
index 163c39fa12d9..4e843b9864ec 100644
--- a/tools/perf/scripts/python/event_analyzing_sample.py
+++ b/tools/perf/scripts/python/event_analyzing_sample.py
@@ -1,4 +1,5 @@
1# event_analyzing_sample.py: general event handler in python 1# event_analyzing_sample.py: general event handler in python
2# SPDX-License-Identifier: GPL-2.0
2# 3#
3# Current perf report is already very powerful with the annotation integrated, 4# Current perf report is already very powerful with the annotation integrated,
4# and this script is not trying to be as powerful as perf report, but 5# and this script is not trying to be as powerful as perf report, but
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index 7656ff8aa066..efcaf6cac2eb 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -59,7 +59,7 @@ import datetime
59# pt_example=# \q 59# pt_example=# \q
60# 60#
61# An example of using the database is provided by the script 61# An example of using the database is provided by the script
62# call-graph-from-postgresql.py. Refer to that script for details. 62# call-graph-from-sql.py. Refer to that script for details.
63# 63#
64# Tables: 64# Tables:
65# 65#
@@ -340,7 +340,8 @@ if branches:
340 'to_sym_offset bigint,' 340 'to_sym_offset bigint,'
341 'to_ip bigint,' 341 'to_ip bigint,'
342 'branch_type integer,' 342 'branch_type integer,'
343 'in_tx boolean)') 343 'in_tx boolean,'
344 'call_path_id bigint)')
344else: 345else:
345 do_query(query, 'CREATE TABLE samples (' 346 do_query(query, 'CREATE TABLE samples ('
346 'id bigint NOT NULL,' 347 'id bigint NOT NULL,'
diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py
new file mode 100644
index 000000000000..f827bf77e9d2
--- /dev/null
+++ b/tools/perf/scripts/python/export-to-sqlite.py
@@ -0,0 +1,451 @@
1# export-to-sqlite.py: export perf data to a sqlite3 database
2# Copyright (c) 2017, 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
13import os
14import sys
15import struct
16import datetime
17
18# To use this script you will need to have installed package python-pyside which
19# provides LGPL-licensed Python bindings for Qt. You will also need the package
20# libqt4-sql-sqlite for Qt sqlite3 support.
21#
22# An example of using this script with Intel PT:
23#
24# $ perf record -e intel_pt//u ls
25# $ perf script -s ~/libexec/perf-core/scripts/python/export-to-sqlite.py pt_example branches calls
26# 2017-07-31 14:26:07.326913 Creating database...
27# 2017-07-31 14:26:07.538097 Writing records...
28# 2017-07-31 14:26:09.889292 Adding indexes
29# 2017-07-31 14:26:09.958746 Done
30#
31# To browse the database, sqlite3 can be used e.g.
32#
33# $ sqlite3 pt_example
34# sqlite> .header on
35# sqlite> select * from samples_view where id < 10;
36# sqlite> .mode column
37# sqlite> select * from samples_view where id < 10;
38# sqlite> .tables
39# sqlite> .schema samples_view
40# sqlite> .quit
41#
42# An example of using the database is provided by the script
43# call-graph-from-sql.py. Refer to that script for details.
44#
45# The database structure is practically the same as created by the script
46# export-to-postgresql.py. Refer to that script for details. A notable
47# difference is the 'transaction' column of the 'samples' table which is
48# renamed 'transaction_' in sqlite because 'transaction' is a reserved word.
49
50from PySide.QtSql import *
51
52sys.path.append(os.environ['PERF_EXEC_PATH'] + \
53 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
54
55# These perf imports are not used at present
56#from perf_trace_context import *
57#from Core import *
58
59perf_db_export_mode = True
60perf_db_export_calls = False
61perf_db_export_callchains = False
62
63def usage():
64 print >> sys.stderr, "Usage is: export-to-sqlite.py <database name> [<columns>] [<calls>] [<callchains>]"
65 print >> sys.stderr, "where: columns 'all' or 'branches'"
66 print >> sys.stderr, " calls 'calls' => create calls and call_paths table"
67 print >> sys.stderr, " callchains 'callchains' => create call_paths table"
68 raise Exception("Too few arguments")
69
70if (len(sys.argv) < 2):
71 usage()
72
73dbname = sys.argv[1]
74
75if (len(sys.argv) >= 3):
76 columns = sys.argv[2]
77else:
78 columns = "all"
79
80if columns not in ("all", "branches"):
81 usage()
82
83branches = (columns == "branches")
84
85for i in range(3,len(sys.argv)):
86 if (sys.argv[i] == "calls"):
87 perf_db_export_calls = True
88 elif (sys.argv[i] == "callchains"):
89 perf_db_export_callchains = True
90 else:
91 usage()
92
93def do_query(q, s):
94 if (q.exec_(s)):
95 return
96 raise Exception("Query failed: " + q.lastError().text())
97
98def do_query_(q):
99 if (q.exec_()):
100 return
101 raise Exception("Query failed: " + q.lastError().text())
102
103print datetime.datetime.today(), "Creating database..."
104
105db_exists = False
106try:
107 f = open(dbname)
108 f.close()
109 db_exists = True
110except:
111 pass
112
113if db_exists:
114 raise Exception(dbname + " already exists")
115
116db = QSqlDatabase.addDatabase('QSQLITE')
117db.setDatabaseName(dbname)
118db.open()
119
120query = QSqlQuery(db)
121
122do_query(query, 'PRAGMA journal_mode = OFF')
123do_query(query, 'BEGIN TRANSACTION')
124
125do_query(query, 'CREATE TABLE selected_events ('
126 'id integer NOT NULL PRIMARY KEY,'
127 'name varchar(80))')
128do_query(query, 'CREATE TABLE machines ('
129 'id integer NOT NULL PRIMARY KEY,'
130 'pid integer,'
131 'root_dir varchar(4096))')
132do_query(query, 'CREATE TABLE threads ('
133 'id integer NOT NULL PRIMARY KEY,'
134 'machine_id bigint,'
135 'process_id bigint,'
136 'pid integer,'
137 'tid integer)')
138do_query(query, 'CREATE TABLE comms ('
139 'id integer NOT NULL PRIMARY KEY,'
140 'comm varchar(16))')
141do_query(query, 'CREATE TABLE comm_threads ('
142 'id integer NOT NULL PRIMARY KEY,'
143 'comm_id bigint,'
144 'thread_id bigint)')
145do_query(query, 'CREATE TABLE dsos ('
146 'id integer NOT NULL PRIMARY KEY,'
147 'machine_id bigint,'
148 'short_name varchar(256),'
149 'long_name varchar(4096),'
150 'build_id varchar(64))')
151do_query(query, 'CREATE TABLE symbols ('
152 'id integer NOT NULL PRIMARY KEY,'
153 'dso_id bigint,'
154 'sym_start bigint,'
155 'sym_end bigint,'
156 'binding integer,'
157 'name varchar(2048))')
158do_query(query, 'CREATE TABLE branch_types ('
159 'id integer NOT NULL PRIMARY KEY,'
160 'name varchar(80))')
161
162if branches:
163 do_query(query, 'CREATE TABLE samples ('
164 'id integer NOT NULL PRIMARY KEY,'
165 'evsel_id bigint,'
166 'machine_id bigint,'
167 'thread_id bigint,'
168 'comm_id bigint,'
169 'dso_id bigint,'
170 'symbol_id bigint,'
171 'sym_offset bigint,'
172 'ip bigint,'
173 'time bigint,'
174 'cpu integer,'
175 'to_dso_id bigint,'
176 'to_symbol_id bigint,'
177 'to_sym_offset bigint,'
178 'to_ip bigint,'
179 'branch_type integer,'
180 'in_tx boolean,'
181 'call_path_id bigint)')
182else:
183 do_query(query, 'CREATE TABLE samples ('
184 'id integer NOT NULL PRIMARY KEY,'
185 'evsel_id bigint,'
186 'machine_id bigint,'
187 'thread_id bigint,'
188 'comm_id bigint,'
189 'dso_id bigint,'
190 'symbol_id bigint,'
191 'sym_offset bigint,'
192 'ip bigint,'
193 'time bigint,'
194 'cpu integer,'
195 'to_dso_id bigint,'
196 'to_symbol_id bigint,'
197 'to_sym_offset bigint,'
198 'to_ip bigint,'
199 'period bigint,'
200 'weight bigint,'
201 'transaction_ bigint,'
202 'data_src bigint,'
203 'branch_type integer,'
204 'in_tx boolean,'
205 'call_path_id bigint)')
206
207if perf_db_export_calls or perf_db_export_callchains:
208 do_query(query, 'CREATE TABLE call_paths ('
209 'id integer NOT NULL PRIMARY KEY,'
210 'parent_id bigint,'
211 'symbol_id bigint,'
212 'ip bigint)')
213if perf_db_export_calls:
214 do_query(query, 'CREATE TABLE calls ('
215 'id integer NOT NULL PRIMARY KEY,'
216 'thread_id bigint,'
217 'comm_id bigint,'
218 'call_path_id bigint,'
219 'call_time bigint,'
220 'return_time bigint,'
221 'branch_count bigint,'
222 'call_id bigint,'
223 'return_id bigint,'
224 'parent_call_path_id bigint,'
225 'flags integer)')
226
227# printf was added to sqlite in version 3.8.3
228sqlite_has_printf = False
229try:
230 do_query(query, 'SELECT printf("") FROM machines')
231 sqlite_has_printf = True
232except:
233 pass
234
235def emit_to_hex(x):
236 if sqlite_has_printf:
237 return 'printf("%x", ' + x + ')'
238 else:
239 return x
240
241do_query(query, 'CREATE VIEW machines_view AS '
242 'SELECT '
243 'id,'
244 'pid,'
245 'root_dir,'
246 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest'
247 ' FROM machines')
248
249do_query(query, 'CREATE VIEW dsos_view AS '
250 'SELECT '
251 'id,'
252 'machine_id,'
253 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
254 'short_name,'
255 'long_name,'
256 'build_id'
257 ' FROM dsos')
258
259do_query(query, 'CREATE VIEW symbols_view AS '
260 'SELECT '
261 'id,'
262 'name,'
263 '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,'
264 'dso_id,'
265 'sym_start,'
266 'sym_end,'
267 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding'
268 ' FROM symbols')
269
270do_query(query, 'CREATE VIEW threads_view AS '
271 'SELECT '
272 'id,'
273 'machine_id,'
274 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
275 'process_id,'
276 'pid,'
277 'tid'
278 ' FROM threads')
279
280do_query(query, 'CREATE VIEW comm_threads_view AS '
281 'SELECT '
282 'comm_id,'
283 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
284 'thread_id,'
285 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
286 '(SELECT tid FROM threads WHERE id = thread_id) AS tid'
287 ' FROM comm_threads')
288
289if perf_db_export_calls or perf_db_export_callchains:
290 do_query(query, 'CREATE VIEW call_paths_view AS '
291 'SELECT '
292 'c.id,'
293 + emit_to_hex('c.ip') + ' AS ip,'
294 'c.symbol_id,'
295 '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,'
296 '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,'
297 '(SELECT dso FROM symbols_view WHERE id = c.symbol_id) AS dso_short_name,'
298 'c.parent_id,'
299 + emit_to_hex('p.ip') + ' AS parent_ip,'
300 'p.symbol_id AS parent_symbol_id,'
301 '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,'
302 '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'
303 '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name'
304 ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')
305if perf_db_export_calls:
306 do_query(query, 'CREATE VIEW calls_view AS '
307 'SELECT '
308 'calls.id,'
309 'thread_id,'
310 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
311 '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
312 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
313 'call_path_id,'
314 + emit_to_hex('ip') + ' AS ip,'
315 'symbol_id,'
316 '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
317 'call_time,'
318 'return_time,'
319 'return_time - call_time AS elapsed_time,'
320 'branch_count,'
321 'call_id,'
322 'return_id,'
323 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,'
324 'parent_call_path_id'
325 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
326
327do_query(query, 'CREATE VIEW samples_view AS '
328 'SELECT '
329 'id,'
330 'time,'
331 'cpu,'
332 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
333 '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
334 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
335 '(SELECT name FROM selected_events WHERE id = evsel_id) AS event,'
336 + emit_to_hex('ip') + ' AS ip_hex,'
337 '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
338 'sym_offset,'
339 '(SELECT short_name FROM dsos WHERE id = dso_id) AS dso_short_name,'
340 + emit_to_hex('to_ip') + ' AS to_ip_hex,'
341 '(SELECT name FROM symbols WHERE id = to_symbol_id) AS to_symbol,'
342 'to_sym_offset,'
343 '(SELECT short_name FROM dsos WHERE id = to_dso_id) AS to_dso_short_name,'
344 '(SELECT name FROM branch_types WHERE id = branch_type) AS branch_type_name,'
345 'in_tx'
346 ' FROM samples')
347
348do_query(query, 'END TRANSACTION')
349
350evsel_query = QSqlQuery(db)
351evsel_query.prepare("INSERT INTO selected_events VALUES (?, ?)")
352machine_query = QSqlQuery(db)
353machine_query.prepare("INSERT INTO machines VALUES (?, ?, ?)")
354thread_query = QSqlQuery(db)
355thread_query.prepare("INSERT INTO threads VALUES (?, ?, ?, ?, ?)")
356comm_query = QSqlQuery(db)
357comm_query.prepare("INSERT INTO comms VALUES (?, ?)")
358comm_thread_query = QSqlQuery(db)
359comm_thread_query.prepare("INSERT INTO comm_threads VALUES (?, ?, ?)")
360dso_query = QSqlQuery(db)
361dso_query.prepare("INSERT INTO dsos VALUES (?, ?, ?, ?, ?)")
362symbol_query = QSqlQuery(db)
363symbol_query.prepare("INSERT INTO symbols VALUES (?, ?, ?, ?, ?, ?)")
364branch_type_query = QSqlQuery(db)
365branch_type_query.prepare("INSERT INTO branch_types VALUES (?, ?)")
366sample_query = QSqlQuery(db)
367if branches:
368 sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
369else:
370 sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
371if perf_db_export_calls or perf_db_export_callchains:
372 call_path_query = QSqlQuery(db)
373 call_path_query.prepare("INSERT INTO call_paths VALUES (?, ?, ?, ?)")
374if perf_db_export_calls:
375 call_query = QSqlQuery(db)
376 call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
377
378def trace_begin():
379 print datetime.datetime.today(), "Writing records..."
380 do_query(query, 'BEGIN TRANSACTION')
381 # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs
382 evsel_table(0, "unknown")
383 machine_table(0, 0, "unknown")
384 thread_table(0, 0, 0, -1, -1)
385 comm_table(0, "unknown")
386 dso_table(0, 0, "unknown", "unknown", "")
387 symbol_table(0, 0, 0, 0, 0, "unknown")
388 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
389 if perf_db_export_calls or perf_db_export_callchains:
390 call_path_table(0, 0, 0, 0)
391
392unhandled_count = 0
393
394def trace_end():
395 do_query(query, 'END TRANSACTION')
396
397 print datetime.datetime.today(), "Adding indexes"
398 if perf_db_export_calls:
399 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
400
401 if (unhandled_count):
402 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events"
403 print datetime.datetime.today(), "Done"
404
405def trace_unhandled(event_name, context, event_fields_dict):
406 global unhandled_count
407 unhandled_count += 1
408
409def sched__sched_switch(*x):
410 pass
411
412def bind_exec(q, n, x):
413 for xx in x[0:n]:
414 q.addBindValue(str(xx))
415 do_query_(q)
416
417def evsel_table(*x):
418 bind_exec(evsel_query, 2, x)
419
420def machine_table(*x):
421 bind_exec(machine_query, 3, x)
422
423def thread_table(*x):
424 bind_exec(thread_query, 5, x)
425
426def comm_table(*x):
427 bind_exec(comm_query, 2, x)
428
429def comm_thread_table(*x):
430 bind_exec(comm_thread_query, 3, x)
431
432def dso_table(*x):
433 bind_exec(dso_query, 5, x)
434
435def symbol_table(*x):
436 bind_exec(symbol_query, 6, x)
437
438def branch_type_table(*x):
439 bind_exec(branch_type_query, 2, x)
440
441def sample_table(*x):
442 if branches:
443 bind_exec(sample_query, 18, x)
444 else:
445 bind_exec(sample_query, 22, x)
446
447def call_path_table(*x):
448 bind_exec(call_path_query, 4, x)
449
450def call_return_table(*x):
451 bind_exec(call_query, 11, x)
diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
index 0b6ce8c253e8..a150164b44a3 100755
--- a/tools/perf/scripts/python/net_dropmonitor.py
+++ b/tools/perf/scripts/python/net_dropmonitor.py
@@ -1,4 +1,5 @@
1# Monitor the system for dropped packets and proudce a report of drop locations and counts 1# Monitor the system for dropped packets and proudce a report of drop locations and counts
2# SPDX-License-Identifier: GPL-2.0
2 3
3import os 4import os
4import sys 5import sys
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
index 4c6f09ac7d12..9b2050f778f1 100644
--- a/tools/perf/scripts/python/netdev-times.py
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -1,4 +1,5 @@
1# Display a process of packets and processed time. 1# Display a process of packets and processed time.
2# SPDX-License-Identifier: GPL-2.0
2# It helps us to investigate networking or network device. 3# It helps us to investigate networking or network device.
3# 4#
4# options 5# options
diff --git a/tools/perf/scripts/python/stackcollapse.py b/tools/perf/scripts/python/stackcollapse.py
index 5a605f70ef32..1697b5e18c96 100755
--- a/tools/perf/scripts/python/stackcollapse.py
+++ b/tools/perf/scripts/python/stackcollapse.py
@@ -1,4 +1,5 @@
1# stackcollapse.py - format perf samples with one line per distinct call stack 1# stackcollapse.py - format perf samples with one line per distinct call stack
2# SPDX-License-Identifier: GPL-2.0
2# 3#
3# This script's output has two space-separated fields. The first is a semicolon 4# 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# separated stack including the program name (from the "comm" field) and the
diff --git a/tools/perf/scripts/python/stat-cpi.py b/tools/perf/scripts/python/stat-cpi.py
index 8b60f343dd07..8410672efb8b 100644
--- a/tools/perf/scripts/python/stat-cpi.py
+++ b/tools/perf/scripts/python/stat-cpi.py
@@ -1,4 +1,5 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2# SPDX-License-Identifier: GPL-2.0
2 3
3data = {} 4data = {}
4times = [] 5times = []
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 84222bdb8689..87bf3edb037c 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -34,6 +34,7 @@ perf-y += thread-map.o
34perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o llvm-src-relocation.o 34perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o llvm-src-relocation.o
35perf-y += bpf.o 35perf-y += bpf.o
36perf-y += topology.o 36perf-y += topology.o
37perf-y += mem.o
37perf-y += cpumap.o 38perf-y += cpumap.o
38perf-y += stat.o 39perf-y += stat.o
39perf-y += event_update.o 40perf-y += event_update.o
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index 0e77b2cf61ec..0e1367f90af5 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * The struct perf_event_attr test support. 3 * The struct perf_event_attr test support.
3 * 4 *
@@ -36,6 +37,7 @@
36#define ENV "PERF_TEST_ATTR" 37#define ENV "PERF_TEST_ATTR"
37 38
38static char *dir; 39static char *dir;
40static bool ready;
39 41
40void test_attr__init(void) 42void test_attr__init(void)
41{ 43{
@@ -67,6 +69,9 @@ static int store_event(struct perf_event_attr *attr, pid_t pid, int cpu,
67 FILE *file; 69 FILE *file;
68 char path[PATH_MAX]; 70 char path[PATH_MAX];
69 71
72 if (!ready)
73 return 0;
74
70 snprintf(path, PATH_MAX, "%s/event-%d-%llu-%d", dir, 75 snprintf(path, PATH_MAX, "%s/event-%d-%llu-%d", dir,
71 attr->type, attr->config, fd); 76 attr->type, attr->config, fd);
72 77
@@ -136,7 +141,7 @@ void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
136{ 141{
137 int errno_saved = errno; 142 int errno_saved = errno;
138 143
139 if (store_event(attr, pid, cpu, fd, group_fd, flags)) { 144 if ((fd != -1) && store_event(attr, pid, cpu, fd, group_fd, flags)) {
140 pr_err("test attr FAILED"); 145 pr_err("test attr FAILED");
141 exit(128); 146 exit(128);
142 } 147 }
@@ -144,6 +149,12 @@ void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
144 errno = errno_saved; 149 errno = errno_saved;
145} 150}
146 151
152void test_attr__ready(void)
153{
154 if (unlikely(test_attr__enabled) && !ready)
155 ready = true;
156}
157
147static int run_dir(const char *d, const char *perf) 158static int run_dir(const char *d, const char *perf)
148{ 159{
149 char v[] = "-vvvvv"; 160 char v[] = "-vvvvv";
@@ -156,10 +167,10 @@ static int run_dir(const char *d, const char *perf)
156 snprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s", 167 snprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s",
157 d, d, perf, vcnt, v); 168 d, d, perf, vcnt, v);
158 169
159 return system(cmd); 170 return system(cmd) ? TEST_FAIL : TEST_OK;
160} 171}
161 172
162int test__attr(int subtest __maybe_unused) 173int test__attr(struct test *test __maybe_unused, int subtest __maybe_unused)
163{ 174{
164 struct stat st; 175 struct stat st;
165 char path_perf[PATH_MAX]; 176 char path_perf[PATH_MAX];
diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py
index cdf21a9d0c35..ff9b60b99f52 100644
--- a/tools/perf/tests/attr.py
+++ b/tools/perf/tests/attr.py
@@ -1,4 +1,5 @@
1#! /usr/bin/python 1#! /usr/bin/python
2# SPDX-License-Identifier: GPL-2.0
2 3
3import os 4import os
4import sys 5import sys
@@ -9,6 +10,20 @@ import logging
9import shutil 10import shutil
10import ConfigParser 11import ConfigParser
11 12
13def data_equal(a, b):
14 # Allow multiple values in assignment separated by '|'
15 a_list = a.split('|')
16 b_list = b.split('|')
17
18 for a_item in a_list:
19 for b_item in b_list:
20 if (a_item == b_item):
21 return True
22 elif (a_item == '*') or (b_item == '*'):
23 return True
24
25 return False
26
12class Fail(Exception): 27class Fail(Exception):
13 def __init__(self, test, msg): 28 def __init__(self, test, msg):
14 self.msg = msg 29 self.msg = msg
@@ -82,34 +97,25 @@ class Event(dict):
82 self.add(base) 97 self.add(base)
83 self.add(data) 98 self.add(data)
84 99
85 def compare_data(self, a, b):
86 # Allow multiple values in assignment separated by '|'
87 a_list = a.split('|')
88 b_list = b.split('|')
89
90 for a_item in a_list:
91 for b_item in b_list:
92 if (a_item == b_item):
93 return True
94 elif (a_item == '*') or (b_item == '*'):
95 return True
96
97 return False
98
99 def equal(self, other): 100 def equal(self, other):
100 for t in Event.terms: 101 for t in Event.terms:
101 log.debug(" [%s] %s %s" % (t, self[t], other[t])); 102 log.debug(" [%s] %s %s" % (t, self[t], other[t]));
102 if not self.has_key(t) or not other.has_key(t): 103 if not self.has_key(t) or not other.has_key(t):
103 return False 104 return False
104 if not self.compare_data(self[t], other[t]): 105 if not data_equal(self[t], other[t]):
105 return False 106 return False
106 return True 107 return True
107 108
109 def optional(self):
110 if self.has_key('optional') and self['optional'] == '1':
111 return True
112 return False
113
108 def diff(self, other): 114 def diff(self, other):
109 for t in Event.terms: 115 for t in Event.terms:
110 if not self.has_key(t) or not other.has_key(t): 116 if not self.has_key(t) or not other.has_key(t):
111 continue 117 continue
112 if not self.compare_data(self[t], other[t]): 118 if not data_equal(self[t], other[t]):
113 log.warning("expected %s=%s, got %s" % (t, self[t], other[t])) 119 log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
114 120
115# Test file description needs to have following sections: 121# Test file description needs to have following sections:
@@ -218,9 +224,9 @@ class Test(object):
218 self.perf, self.command, tempdir, self.args) 224 self.perf, self.command, tempdir, self.args)
219 ret = os.WEXITSTATUS(os.system(cmd)) 225 ret = os.WEXITSTATUS(os.system(cmd))
220 226
221 log.info(" '%s' ret %d " % (cmd, ret)) 227 log.info(" '%s' ret '%s', expected '%s'" % (cmd, str(ret), str(self.ret)))
222 228
223 if ret != int(self.ret): 229 if not data_equal(str(ret), str(self.ret)):
224 raise Unsup(self) 230 raise Unsup(self)
225 231
226 def compare(self, expect, result): 232 def compare(self, expect, result):
@@ -232,6 +238,7 @@ class Test(object):
232 # events in result. Fail if there's not any. 238 # events in result. Fail if there's not any.
233 for exp_name, exp_event in expect.items(): 239 for exp_name, exp_event in expect.items():
234 exp_list = [] 240 exp_list = []
241 res_event = {}
235 log.debug(" matching [%s]" % exp_name) 242 log.debug(" matching [%s]" % exp_name)
236 for res_name, res_event in result.items(): 243 for res_name, res_event in result.items():
237 log.debug(" to [%s]" % res_name) 244 log.debug(" to [%s]" % res_name)
@@ -244,9 +251,15 @@ class Test(object):
244 log.debug(" match: [%s] matches %s" % (exp_name, str(exp_list))) 251 log.debug(" match: [%s] matches %s" % (exp_name, str(exp_list)))
245 252
246 # we did not any matching event - fail 253 # we did not any matching event - fail
247 if (not exp_list): 254 if not exp_list:
248 exp_event.diff(res_event) 255 if exp_event.optional():
249 raise Fail(self, 'match failure'); 256 log.debug(" %s does not match, but is optional" % exp_name)
257 else:
258 if not res_event:
259 log.debug(" res_event is empty");
260 else:
261 exp_event.diff(res_event)
262 raise Fail(self, 'match failure');
250 263
251 match[exp_name] = exp_list 264 match[exp_name] = exp_list
252 265
diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record
index 7e6d74946e04..37940665f736 100644
--- a/tools/perf/tests/attr/base-record
+++ b/tools/perf/tests/attr/base-record
@@ -7,7 +7,7 @@ cpu=*
7type=0|1 7type=0|1
8size=112 8size=112
9config=0 9config=0
10sample_period=4000 10sample_period=*
11sample_type=263 11sample_type=263
12read_format=0 12read_format=0
13disabled=1 13disabled=1
@@ -15,7 +15,7 @@ inherit=1
15pinned=0 15pinned=0
16exclusive=0 16exclusive=0
17exclude_user=0 17exclude_user=0
18exclude_kernel=0 18exclude_kernel=0|1
19exclude_hv=0 19exclude_hv=0
20exclude_idle=0 20exclude_idle=0
21mmap=1 21mmap=1
@@ -23,9 +23,9 @@ comm=1
23freq=1 23freq=1
24inherit_stat=0 24inherit_stat=0
25enable_on_exec=1 25enable_on_exec=1
26task=0 26task=1
27watermark=0 27watermark=0
28precise_ip=0 28precise_ip=0|1|2|3
29mmap_data=0 29mmap_data=0
30sample_id_all=1 30sample_id_all=1
31exclude_host=0|1 31exclude_host=0|1
diff --git a/tools/perf/tests/attr/base-stat b/tools/perf/tests/attr/base-stat
index f4cf148f14cb..4d0c2e42b64e 100644
--- a/tools/perf/tests/attr/base-stat
+++ b/tools/perf/tests/attr/base-stat
@@ -8,14 +8,14 @@ type=0
8size=112 8size=112
9config=0 9config=0
10sample_period=0 10sample_period=0
11sample_type=0 11sample_type=65536
12read_format=3 12read_format=3
13disabled=1 13disabled=1
14inherit=1 14inherit=1
15pinned=0 15pinned=0
16exclusive=0 16exclusive=0
17exclude_user=0 17exclude_user=0
18exclude_kernel=0 18exclude_kernel=0|1
19exclude_hv=0 19exclude_hv=0
20exclude_idle=0 20exclude_idle=0
21mmap=0 21mmap=0
diff --git a/tools/perf/tests/attr/test-record-C0 b/tools/perf/tests/attr/test-record-C0
index d6a7e43f61b3..cb0a3138fa54 100644
--- a/tools/perf/tests/attr/test-record-C0
+++ b/tools/perf/tests/attr/test-record-C0
@@ -1,6 +1,7 @@
1[config] 1[config]
2command = record 2command = record
3args = -C 0 kill >/dev/null 2>&1 3args = -C 0 kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6cpu=0 7cpu=0
diff --git a/tools/perf/tests/attr/test-record-basic b/tools/perf/tests/attr/test-record-basic
index 55c0428370ca..85a23cf35ba1 100644
--- a/tools/perf/tests/attr/test-record-basic
+++ b/tools/perf/tests/attr/test-record-basic
@@ -1,5 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = kill >/dev/null 2>&1 3args = kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-branch-any b/tools/perf/tests/attr/test-record-branch-any
index 1421960ed4e9..81f839e2fad0 100644
--- a/tools/perf/tests/attr/test-record-branch-any
+++ b/tools/perf/tests/attr/test-record-branch-any
@@ -1,8 +1,8 @@
1[config] 1[config]
2command = record 2command = record
3args = -b kill >/dev/null 2>&1 3args = -b kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=4000
7sample_type=2311 7sample_type=2311
8branch_sample_type=8 8branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any b/tools/perf/tests/attr/test-record-branch-filter-any
index 915c4df0e0c2..357421f4dfce 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-any
+++ b/tools/perf/tests/attr/test-record-branch-filter-any
@@ -1,8 +1,8 @@
1[config] 1[config]
2command = record 2command = record
3args = -j any kill >/dev/null 2>&1 3args = -j any kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=4000
7sample_type=2311 7sample_type=2311
8branch_sample_type=8 8branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_call b/tools/perf/tests/attr/test-record-branch-filter-any_call
index 8708dbd4f373..dbc55f2ab845 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-any_call
+++ b/tools/perf/tests/attr/test-record-branch-filter-any_call
@@ -1,8 +1,8 @@
1[config] 1[config]
2command = record 2command = record
3args = -j any_call kill >/dev/null 2>&1 3args = -j any_call kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=4000
7sample_type=2311 7sample_type=2311
8branch_sample_type=16 8branch_sample_type=16
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_ret b/tools/perf/tests/attr/test-record-branch-filter-any_ret
index 0d3607a6dcbe..a0824ff8e131 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-any_ret
+++ b/tools/perf/tests/attr/test-record-branch-filter-any_ret
@@ -1,8 +1,8 @@
1[config] 1[config]
2command = record 2command = record
3args = -j any_ret kill >/dev/null 2>&1 3args = -j any_ret kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=4000
7sample_type=2311 7sample_type=2311
8branch_sample_type=32 8branch_sample_type=32
diff --git a/tools/perf/tests/attr/test-record-branch-filter-hv b/tools/perf/tests/attr/test-record-branch-filter-hv
index f25526740cec..f34d6f120181 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-hv
+++ b/tools/perf/tests/attr/test-record-branch-filter-hv
@@ -1,8 +1,8 @@
1[config] 1[config]
2command = record 2command = record
3args = -j hv kill >/dev/null 2>&1 3args = -j hv kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=4000
7sample_type=2311 7sample_type=2311
8branch_sample_type=8 8branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-branch-filter-ind_call b/tools/perf/tests/attr/test-record-branch-filter-ind_call
index e862dd179128..b86a35232248 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-ind_call
+++ b/tools/perf/tests/attr/test-record-branch-filter-ind_call
@@ -1,8 +1,8 @@
1[config] 1[config]
2command = record 2command = record
3args = -j ind_call kill >/dev/null 2>&1 3args = -j ind_call kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=4000
7sample_type=2311 7sample_type=2311
8branch_sample_type=64 8branch_sample_type=64
diff --git a/tools/perf/tests/attr/test-record-branch-filter-k b/tools/perf/tests/attr/test-record-branch-filter-k
index 182971e898f5..d3fbc5e1858a 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-k
+++ b/tools/perf/tests/attr/test-record-branch-filter-k
@@ -1,8 +1,8 @@
1[config] 1[config]
2command = record 2command = record
3args = -j k kill >/dev/null 2>&1 3args = -j k kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=4000
7sample_type=2311 7sample_type=2311
8branch_sample_type=8 8branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-branch-filter-u b/tools/perf/tests/attr/test-record-branch-filter-u
index 83449ef9e687..a318f0dda173 100644
--- a/tools/perf/tests/attr/test-record-branch-filter-u
+++ b/tools/perf/tests/attr/test-record-branch-filter-u
@@ -1,8 +1,8 @@
1[config] 1[config]
2command = record 2command = record
3args = -j u kill >/dev/null 2>&1 3args = -j u kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=4000
7sample_type=2311 7sample_type=2311
8branch_sample_type=8 8branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-count b/tools/perf/tests/attr/test-record-count
index 2f841de56f6b..34f6cc577263 100644
--- a/tools/perf/tests/attr/test-record-count
+++ b/tools/perf/tests/attr/test-record-count
@@ -1,6 +1,7 @@
1[config] 1[config]
2command = record 2command = record
3args = -c 123 kill >/dev/null 2>&1 3args = -c 123 kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=123 7sample_period=123
diff --git a/tools/perf/tests/attr/test-record-data b/tools/perf/tests/attr/test-record-data
index 716e143b5291..a9cf2233b0ce 100644
--- a/tools/perf/tests/attr/test-record-data
+++ b/tools/perf/tests/attr/test-record-data
@@ -1,10 +1,9 @@
1[config] 1[config]
2command = record 2command = record
3args = -d kill >/dev/null 2>&1 3args = -d kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=4000
7
8# sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | 7# sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME |
9# PERF_SAMPLE_ADDR | PERF_SAMPLE_PERIOD | PERF_SAMPLE_DATA_SRC 8# PERF_SAMPLE_ADDR | PERF_SAMPLE_PERIOD | PERF_SAMPLE_DATA_SRC
10sample_type=33039 9sample_type=33039
diff --git a/tools/perf/tests/attr/test-record-freq b/tools/perf/tests/attr/test-record-freq
index 600d0f8f2583..bf4cb459f0d5 100644
--- a/tools/perf/tests/attr/test-record-freq
+++ b/tools/perf/tests/attr/test-record-freq
@@ -1,6 +1,7 @@
1[config] 1[config]
2command = record 2command = record
3args = -F 100 kill >/dev/null 2>&1 3args = -F 100 kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=100 7sample_period=100
diff --git a/tools/perf/tests/attr/test-record-graph-default b/tools/perf/tests/attr/test-record-graph-default
index 853597a9a8f6..0b216e69760c 100644
--- a/tools/perf/tests/attr/test-record-graph-default
+++ b/tools/perf/tests/attr/test-record-graph-default
@@ -1,6 +1,7 @@
1[config] 1[config]
2command = record 2command = record
3args = -g kill >/dev/null 2>&1 3args = -g kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_type=295 7sample_type=295
diff --git a/tools/perf/tests/attr/test-record-graph-dwarf b/tools/perf/tests/attr/test-record-graph-dwarf
index d6f324ea578c..da2fa73bd0a2 100644
--- a/tools/perf/tests/attr/test-record-graph-dwarf
+++ b/tools/perf/tests/attr/test-record-graph-dwarf
@@ -1,10 +1,12 @@
1[config] 1[config]
2command = record 2command = record
3args = --call-graph dwarf -- kill >/dev/null 2>&1 3args = --call-graph dwarf -- kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_type=12583 7sample_type=45359
7exclude_callchain_user=1 8exclude_callchain_user=1
8sample_stack_user=8192 9sample_stack_user=8192
9# TODO different for each arch, no support for that now 10# TODO different for each arch, no support for that now
10sample_regs_user=* 11sample_regs_user=*
12mmap_data=1
diff --git a/tools/perf/tests/attr/test-record-graph-fp b/tools/perf/tests/attr/test-record-graph-fp
index 055e3bee7993..625d190bb798 100644
--- a/tools/perf/tests/attr/test-record-graph-fp
+++ b/tools/perf/tests/attr/test-record-graph-fp
@@ -1,6 +1,7 @@
1[config] 1[config]
2command = record 2command = record
3args = --call-graph fp kill >/dev/null 2>&1 3args = --call-graph fp kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_type=295 7sample_type=295
diff --git a/tools/perf/tests/attr/test-record-group b/tools/perf/tests/attr/test-record-group
index 57739cacdb2a..618ba1c17474 100644
--- a/tools/perf/tests/attr/test-record-group
+++ b/tools/perf/tests/attr/test-record-group
@@ -1,6 +1,7 @@
1[config] 1[config]
2command = record 2command = record
3args = --group -e cycles,instructions kill >/dev/null 2>&1 3args = --group -e cycles,instructions kill >/dev/null 2>&1
4ret = 1
4 5
5[event-1:base-record] 6[event-1:base-record]
6fd=1 7fd=1
@@ -16,5 +17,6 @@ sample_type=327
16read_format=4 17read_format=4
17mmap=0 18mmap=0
18comm=0 19comm=0
20task=0
19enable_on_exec=0 21enable_on_exec=0
20disabled=0 22disabled=0
diff --git a/tools/perf/tests/attr/test-record-group-sampling b/tools/perf/tests/attr/test-record-group-sampling
index 658f5d60c873..f906b793196f 100644
--- a/tools/perf/tests/attr/test-record-group-sampling
+++ b/tools/perf/tests/attr/test-record-group-sampling
@@ -1,6 +1,7 @@
1[config] 1[config]
2command = record 2command = record
3args = -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1 3args = -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1
4ret = 1
4 5
5[event-1:base-record] 6[event-1:base-record]
6fd=1 7fd=1
@@ -22,7 +23,7 @@ sample_type=343
22 23
23# PERF_FORMAT_ID | PERF_FORMAT_GROUP 24# PERF_FORMAT_ID | PERF_FORMAT_GROUP
24read_format=12 25read_format=12
25 26task=0
26mmap=0 27mmap=0
27comm=0 28comm=0
28enable_on_exec=0 29enable_on_exec=0
diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1
index c5548d054aff..48e8bd12fe46 100644
--- a/tools/perf/tests/attr/test-record-group1
+++ b/tools/perf/tests/attr/test-record-group1
@@ -1,6 +1,7 @@
1[config] 1[config]
2command = record 2command = record
3args = -e '{cycles,instructions}' kill >/dev/null 2>&1 3args = -e '{cycles,instructions}' kill >/dev/null 2>&1
4ret = 1
4 5
5[event-1:base-record] 6[event-1:base-record]
6fd=1 7fd=1
@@ -17,5 +18,6 @@ sample_type=327
17read_format=4 18read_format=4
18mmap=0 19mmap=0
19comm=0 20comm=0
21task=0
20enable_on_exec=0 22enable_on_exec=0
21disabled=0 23disabled=0
diff --git a/tools/perf/tests/attr/test-record-no-delay b/tools/perf/tests/attr/test-record-no-buffering
index f253b78cdbf2..aa3956d8fe20 100644
--- a/tools/perf/tests/attr/test-record-no-delay
+++ b/tools/perf/tests/attr/test-record-no-buffering
@@ -1,9 +1,9 @@
1[config] 1[config]
2command = record 2command = record
3args = -D kill >/dev/null 2>&1 3args = --no-buffering kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=4000
7sample_type=263 7sample_type=263
8watermark=0 8watermark=0
9wakeup_events=1 9wakeup_events=1
diff --git a/tools/perf/tests/attr/test-record-no-inherit b/tools/perf/tests/attr/test-record-no-inherit
index 44edcb2edcd5..560943decb87 100644
--- a/tools/perf/tests/attr/test-record-no-inherit
+++ b/tools/perf/tests/attr/test-record-no-inherit
@@ -1,6 +1,7 @@
1[config] 1[config]
2command = record 2command = record
3args = -i kill >/dev/null 2>&1 3args = -i kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_type=263 7sample_type=263
diff --git a/tools/perf/tests/attr/test-record-no-samples b/tools/perf/tests/attr/test-record-no-samples
index d0141b2418b5..8eb73ab639e0 100644
--- a/tools/perf/tests/attr/test-record-no-samples
+++ b/tools/perf/tests/attr/test-record-no-samples
@@ -1,6 +1,7 @@
1[config] 1[config]
2command = record 2command = record
3args = -n kill >/dev/null 2>&1 3args = -n kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=0 7sample_period=0
diff --git a/tools/perf/tests/attr/test-record-period b/tools/perf/tests/attr/test-record-period
index 8abc5314fc52..69bc748f0f27 100644
--- a/tools/perf/tests/attr/test-record-period
+++ b/tools/perf/tests/attr/test-record-period
@@ -1,6 +1,7 @@
1[config] 1[config]
2command = record 2command = record
3args = -c 100 -P kill >/dev/null 2>&1 3args = -c 100 -P kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=100 7sample_period=100
diff --git a/tools/perf/tests/attr/test-record-raw b/tools/perf/tests/attr/test-record-raw
index 4a8ef25b5f49..a188a614a44c 100644
--- a/tools/perf/tests/attr/test-record-raw
+++ b/tools/perf/tests/attr/test-record-raw
@@ -1,7 +1,7 @@
1[config] 1[config]
2command = record 2command = record
3args = -R kill >/dev/null 2>&1 3args = -R kill >/dev/null 2>&1
4ret = 1
4 5
5[event:base-record] 6[event:base-record]
6sample_period=4000
7sample_type=1415 7sample_type=1415
diff --git a/tools/perf/tests/attr/test-stat-C0 b/tools/perf/tests/attr/test-stat-C0
index aa835950751f..a2c76d10b2bb 100644
--- a/tools/perf/tests/attr/test-stat-C0
+++ b/tools/perf/tests/attr/test-stat-C0
@@ -4,6 +4,7 @@ args = -e cycles -C 0 kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-stat] 6[event:base-stat]
7# events are enabled by default when attached to cpu 7# events are disabled by default when attached to cpu
8disabled=0 8disabled=1
9enable_on_exec=0 9enable_on_exec=0
10optional=1
diff --git a/tools/perf/tests/attr/test-stat-basic b/tools/perf/tests/attr/test-stat-basic
index 74e17881f2ba..69867d049fda 100644
--- a/tools/perf/tests/attr/test-stat-basic
+++ b/tools/perf/tests/attr/test-stat-basic
@@ -4,3 +4,4 @@ args = -e cycles kill >/dev/null 2>&1
4ret = 1 4ret = 1
5 5
6[event:base-stat] 6[event:base-stat]
7optional=1
diff --git a/tools/perf/tests/attr/test-stat-default b/tools/perf/tests/attr/test-stat-default
index 19270f54c96e..d9e99b3f77e6 100644
--- a/tools/perf/tests/attr/test-stat-default
+++ b/tools/perf/tests/attr/test-stat-default
@@ -32,33 +32,39 @@ config=2
32fd=5 32fd=5
33type=0 33type=0
34config=0 34config=0
35optional=1
35 36
36# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND 37# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
37[event6:base-stat] 38[event6:base-stat]
38fd=6 39fd=6
39type=0 40type=0
40config=7 41config=7
42optional=1
41 43
42# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 44# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
43[event7:base-stat] 45[event7:base-stat]
44fd=7 46fd=7
45type=0 47type=0
46config=8 48config=8
49optional=1
47 50
48# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 51# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
49[event8:base-stat] 52[event8:base-stat]
50fd=8 53fd=8
51type=0 54type=0
52config=1 55config=1
56optional=1
53 57
54# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS 58# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS
55[event9:base-stat] 59[event9:base-stat]
56fd=9 60fd=9
57type=0 61type=0
58config=4 62config=4
63optional=1
59 64
60# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES 65# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES
61[event10:base-stat] 66[event10:base-stat]
62fd=10 67fd=10
63type=0 68type=0
64config=5 69config=5
70optional=1
diff --git a/tools/perf/tests/attr/test-stat-detailed-1 b/tools/perf/tests/attr/test-stat-detailed-1
index 51426b87153b..8b04a055d154 100644
--- a/tools/perf/tests/attr/test-stat-detailed-1
+++ b/tools/perf/tests/attr/test-stat-detailed-1
@@ -33,36 +33,42 @@ config=2
33fd=5 33fd=5
34type=0 34type=0
35config=0 35config=0
36optional=1
36 37
37# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND 38# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
38[event6:base-stat] 39[event6:base-stat]
39fd=6 40fd=6
40type=0 41type=0
41config=7 42config=7
43optional=1
42 44
43# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 45# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
44[event7:base-stat] 46[event7:base-stat]
45fd=7 47fd=7
46type=0 48type=0
47config=8 49config=8
50optional=1
48 51
49# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 52# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
50[event8:base-stat] 53[event8:base-stat]
51fd=8 54fd=8
52type=0 55type=0
53config=1 56config=1
57optional=1
54 58
55# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS 59# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS
56[event9:base-stat] 60[event9:base-stat]
57fd=9 61fd=9
58type=0 62type=0
59config=4 63config=4
64optional=1
60 65
61# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES 66# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES
62[event10:base-stat] 67[event10:base-stat]
63fd=10 68fd=10
64type=0 69type=0
65config=5 70config=5
71optional=1
66 72
67# PERF_TYPE_HW_CACHE / 73# PERF_TYPE_HW_CACHE /
68# PERF_COUNT_HW_CACHE_L1D << 0 | 74# PERF_COUNT_HW_CACHE_L1D << 0 |
@@ -72,6 +78,7 @@ config=5
72fd=11 78fd=11
73type=3 79type=3
74config=0 80config=0
81optional=1
75 82
76# PERF_TYPE_HW_CACHE / 83# PERF_TYPE_HW_CACHE /
77# PERF_COUNT_HW_CACHE_L1D << 0 | 84# PERF_COUNT_HW_CACHE_L1D << 0 |
@@ -81,6 +88,7 @@ config=0
81fd=12 88fd=12
82type=3 89type=3
83config=65536 90config=65536
91optional=1
84 92
85# PERF_TYPE_HW_CACHE / 93# PERF_TYPE_HW_CACHE /
86# PERF_COUNT_HW_CACHE_LL << 0 | 94# PERF_COUNT_HW_CACHE_LL << 0 |
@@ -90,6 +98,7 @@ config=65536
90fd=13 98fd=13
91type=3 99type=3
92config=2 100config=2
101optional=1
93 102
94# PERF_TYPE_HW_CACHE, 103# PERF_TYPE_HW_CACHE,
95# PERF_COUNT_HW_CACHE_LL << 0 | 104# PERF_COUNT_HW_CACHE_LL << 0 |
@@ -99,3 +108,4 @@ config=2
99fd=14 108fd=14
100type=3 109type=3
101config=65538 110config=65538
111optional=1
diff --git a/tools/perf/tests/attr/test-stat-detailed-2 b/tools/perf/tests/attr/test-stat-detailed-2
index 8de5acc31c27..4fca9f1bfbf8 100644
--- a/tools/perf/tests/attr/test-stat-detailed-2
+++ b/tools/perf/tests/attr/test-stat-detailed-2
@@ -33,36 +33,42 @@ config=2
33fd=5 33fd=5
34type=0 34type=0
35config=0 35config=0
36optional=1
36 37
37# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND 38# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
38[event6:base-stat] 39[event6:base-stat]
39fd=6 40fd=6
40type=0 41type=0
41config=7 42config=7
43optional=1
42 44
43# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 45# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
44[event7:base-stat] 46[event7:base-stat]
45fd=7 47fd=7
46type=0 48type=0
47config=8 49config=8
50optional=1
48 51
49# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 52# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
50[event8:base-stat] 53[event8:base-stat]
51fd=8 54fd=8
52type=0 55type=0
53config=1 56config=1
57optional=1
54 58
55# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS 59# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS
56[event9:base-stat] 60[event9:base-stat]
57fd=9 61fd=9
58type=0 62type=0
59config=4 63config=4
64optional=1
60 65
61# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES 66# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES
62[event10:base-stat] 67[event10:base-stat]
63fd=10 68fd=10
64type=0 69type=0
65config=5 70config=5
71optional=1
66 72
67# PERF_TYPE_HW_CACHE / 73# PERF_TYPE_HW_CACHE /
68# PERF_COUNT_HW_CACHE_L1D << 0 | 74# PERF_COUNT_HW_CACHE_L1D << 0 |
@@ -72,6 +78,7 @@ config=5
72fd=11 78fd=11
73type=3 79type=3
74config=0 80config=0
81optional=1
75 82
76# PERF_TYPE_HW_CACHE / 83# PERF_TYPE_HW_CACHE /
77# PERF_COUNT_HW_CACHE_L1D << 0 | 84# PERF_COUNT_HW_CACHE_L1D << 0 |
@@ -81,6 +88,7 @@ config=0
81fd=12 88fd=12
82type=3 89type=3
83config=65536 90config=65536
91optional=1
84 92
85# PERF_TYPE_HW_CACHE / 93# PERF_TYPE_HW_CACHE /
86# PERF_COUNT_HW_CACHE_LL << 0 | 94# PERF_COUNT_HW_CACHE_LL << 0 |
@@ -90,6 +98,7 @@ config=65536
90fd=13 98fd=13
91type=3 99type=3
92config=2 100config=2
101optional=1
93 102
94# PERF_TYPE_HW_CACHE, 103# PERF_TYPE_HW_CACHE,
95# PERF_COUNT_HW_CACHE_LL << 0 | 104# PERF_COUNT_HW_CACHE_LL << 0 |
@@ -99,6 +108,7 @@ config=2
99fd=14 108fd=14
100type=3 109type=3
101config=65538 110config=65538
111optional=1
102 112
103# PERF_TYPE_HW_CACHE, 113# PERF_TYPE_HW_CACHE,
104# PERF_COUNT_HW_CACHE_L1I << 0 | 114# PERF_COUNT_HW_CACHE_L1I << 0 |
@@ -108,6 +118,7 @@ config=65538
108fd=15 118fd=15
109type=3 119type=3
110config=1 120config=1
121optional=1
111 122
112# PERF_TYPE_HW_CACHE, 123# PERF_TYPE_HW_CACHE,
113# PERF_COUNT_HW_CACHE_L1I << 0 | 124# PERF_COUNT_HW_CACHE_L1I << 0 |
@@ -117,6 +128,7 @@ config=1
117fd=16 128fd=16
118type=3 129type=3
119config=65537 130config=65537
131optional=1
120 132
121# PERF_TYPE_HW_CACHE, 133# PERF_TYPE_HW_CACHE,
122# PERF_COUNT_HW_CACHE_DTLB << 0 | 134# PERF_COUNT_HW_CACHE_DTLB << 0 |
@@ -126,6 +138,7 @@ config=65537
126fd=17 138fd=17
127type=3 139type=3
128config=3 140config=3
141optional=1
129 142
130# PERF_TYPE_HW_CACHE, 143# PERF_TYPE_HW_CACHE,
131# PERF_COUNT_HW_CACHE_DTLB << 0 | 144# PERF_COUNT_HW_CACHE_DTLB << 0 |
@@ -135,6 +148,7 @@ config=3
135fd=18 148fd=18
136type=3 149type=3
137config=65539 150config=65539
151optional=1
138 152
139# PERF_TYPE_HW_CACHE, 153# PERF_TYPE_HW_CACHE,
140# PERF_COUNT_HW_CACHE_ITLB << 0 | 154# PERF_COUNT_HW_CACHE_ITLB << 0 |
@@ -144,6 +158,7 @@ config=65539
144fd=19 158fd=19
145type=3 159type=3
146config=4 160config=4
161optional=1
147 162
148# PERF_TYPE_HW_CACHE, 163# PERF_TYPE_HW_CACHE,
149# PERF_COUNT_HW_CACHE_ITLB << 0 | 164# PERF_COUNT_HW_CACHE_ITLB << 0 |
@@ -153,3 +168,4 @@ config=4
153fd=20 168fd=20
154type=3 169type=3
155config=65540 170config=65540
171optional=1
diff --git a/tools/perf/tests/attr/test-stat-detailed-3 b/tools/perf/tests/attr/test-stat-detailed-3
index 0a1f45bf7d79..4bb58e1c82a6 100644
--- a/tools/perf/tests/attr/test-stat-detailed-3
+++ b/tools/perf/tests/attr/test-stat-detailed-3
@@ -33,36 +33,42 @@ config=2
33fd=5 33fd=5
34type=0 34type=0
35config=0 35config=0
36optional=1
36 37
37# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND 38# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
38[event6:base-stat] 39[event6:base-stat]
39fd=6 40fd=6
40type=0 41type=0
41config=7 42config=7
43optional=1
42 44
43# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 45# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
44[event7:base-stat] 46[event7:base-stat]
45fd=7 47fd=7
46type=0 48type=0
47config=8 49config=8
50optional=1
48 51
49# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 52# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
50[event8:base-stat] 53[event8:base-stat]
51fd=8 54fd=8
52type=0 55type=0
53config=1 56config=1
57optional=1
54 58
55# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS 59# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS
56[event9:base-stat] 60[event9:base-stat]
57fd=9 61fd=9
58type=0 62type=0
59config=4 63config=4
64optional=1
60 65
61# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES 66# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES
62[event10:base-stat] 67[event10:base-stat]
63fd=10 68fd=10
64type=0 69type=0
65config=5 70config=5
71optional=1
66 72
67# PERF_TYPE_HW_CACHE / 73# PERF_TYPE_HW_CACHE /
68# PERF_COUNT_HW_CACHE_L1D << 0 | 74# PERF_COUNT_HW_CACHE_L1D << 0 |
@@ -72,6 +78,7 @@ config=5
72fd=11 78fd=11
73type=3 79type=3
74config=0 80config=0
81optional=1
75 82
76# PERF_TYPE_HW_CACHE / 83# PERF_TYPE_HW_CACHE /
77# PERF_COUNT_HW_CACHE_L1D << 0 | 84# PERF_COUNT_HW_CACHE_L1D << 0 |
@@ -81,6 +88,7 @@ config=0
81fd=12 88fd=12
82type=3 89type=3
83config=65536 90config=65536
91optional=1
84 92
85# PERF_TYPE_HW_CACHE / 93# PERF_TYPE_HW_CACHE /
86# PERF_COUNT_HW_CACHE_LL << 0 | 94# PERF_COUNT_HW_CACHE_LL << 0 |
@@ -90,6 +98,7 @@ config=65536
90fd=13 98fd=13
91type=3 99type=3
92config=2 100config=2
101optional=1
93 102
94# PERF_TYPE_HW_CACHE, 103# PERF_TYPE_HW_CACHE,
95# PERF_COUNT_HW_CACHE_LL << 0 | 104# PERF_COUNT_HW_CACHE_LL << 0 |
@@ -99,6 +108,7 @@ config=2
99fd=14 108fd=14
100type=3 109type=3
101config=65538 110config=65538
111optional=1
102 112
103# PERF_TYPE_HW_CACHE, 113# PERF_TYPE_HW_CACHE,
104# PERF_COUNT_HW_CACHE_L1I << 0 | 114# PERF_COUNT_HW_CACHE_L1I << 0 |
@@ -108,6 +118,7 @@ config=65538
108fd=15 118fd=15
109type=3 119type=3
110config=1 120config=1
121optional=1
111 122
112# PERF_TYPE_HW_CACHE, 123# PERF_TYPE_HW_CACHE,
113# PERF_COUNT_HW_CACHE_L1I << 0 | 124# PERF_COUNT_HW_CACHE_L1I << 0 |
@@ -117,6 +128,7 @@ config=1
117fd=16 128fd=16
118type=3 129type=3
119config=65537 130config=65537
131optional=1
120 132
121# PERF_TYPE_HW_CACHE, 133# PERF_TYPE_HW_CACHE,
122# PERF_COUNT_HW_CACHE_DTLB << 0 | 134# PERF_COUNT_HW_CACHE_DTLB << 0 |
@@ -126,6 +138,7 @@ config=65537
126fd=17 138fd=17
127type=3 139type=3
128config=3 140config=3
141optional=1
129 142
130# PERF_TYPE_HW_CACHE, 143# PERF_TYPE_HW_CACHE,
131# PERF_COUNT_HW_CACHE_DTLB << 0 | 144# PERF_COUNT_HW_CACHE_DTLB << 0 |
@@ -135,6 +148,7 @@ config=3
135fd=18 148fd=18
136type=3 149type=3
137config=65539 150config=65539
151optional=1
138 152
139# PERF_TYPE_HW_CACHE, 153# PERF_TYPE_HW_CACHE,
140# PERF_COUNT_HW_CACHE_ITLB << 0 | 154# PERF_COUNT_HW_CACHE_ITLB << 0 |
@@ -144,6 +158,7 @@ config=65539
144fd=19 158fd=19
145type=3 159type=3
146config=4 160config=4
161optional=1
147 162
148# PERF_TYPE_HW_CACHE, 163# PERF_TYPE_HW_CACHE,
149# PERF_COUNT_HW_CACHE_ITLB << 0 | 164# PERF_COUNT_HW_CACHE_ITLB << 0 |
@@ -153,6 +168,7 @@ config=4
153fd=20 168fd=20
154type=3 169type=3
155config=65540 170config=65540
171optional=1
156 172
157# PERF_TYPE_HW_CACHE, 173# PERF_TYPE_HW_CACHE,
158# PERF_COUNT_HW_CACHE_L1D << 0 | 174# PERF_COUNT_HW_CACHE_L1D << 0 |
@@ -162,6 +178,7 @@ config=65540
162fd=21 178fd=21
163type=3 179type=3
164config=512 180config=512
181optional=1
165 182
166# PERF_TYPE_HW_CACHE, 183# PERF_TYPE_HW_CACHE,
167# PERF_COUNT_HW_CACHE_L1D << 0 | 184# PERF_COUNT_HW_CACHE_L1D << 0 |
@@ -171,3 +188,4 @@ config=512
171fd=22 188fd=22
172type=3 189type=3
173config=66048 190config=66048
191optional=1
diff --git a/tools/perf/tests/attr/test-stat-group b/tools/perf/tests/attr/test-stat-group
index fdc1596a8862..e15d6946e9b3 100644
--- a/tools/perf/tests/attr/test-stat-group
+++ b/tools/perf/tests/attr/test-stat-group
@@ -6,6 +6,7 @@ ret = 1
6[event-1:base-stat] 6[event-1:base-stat]
7fd=1 7fd=1
8group_fd=-1 8group_fd=-1
9read_format=3|15
9 10
10[event-2:base-stat] 11[event-2:base-stat]
11fd=2 12fd=2
@@ -13,3 +14,4 @@ group_fd=1
13config=1 14config=1
14disabled=0 15disabled=0
15enable_on_exec=0 16enable_on_exec=0
17read_format=3|15
diff --git a/tools/perf/tests/attr/test-stat-group1 b/tools/perf/tests/attr/test-stat-group1
index 2a1f86e4a904..1746751123dc 100644
--- a/tools/perf/tests/attr/test-stat-group1
+++ b/tools/perf/tests/attr/test-stat-group1
@@ -6,6 +6,7 @@ ret = 1
6[event-1:base-stat] 6[event-1:base-stat]
7fd=1 7fd=1
8group_fd=-1 8group_fd=-1
9read_format=3|15
9 10
10[event-2:base-stat] 11[event-2:base-stat]
11fd=2 12fd=2
@@ -13,3 +14,4 @@ group_fd=1
13config=1 14config=1
14disabled=0 15disabled=0
15enable_on_exec=0 16enable_on_exec=0
17read_format=3|15
diff --git a/tools/perf/tests/attr/test-stat-no-inherit b/tools/perf/tests/attr/test-stat-no-inherit
index d54b2a1e3e28..924fbb9300d1 100644
--- a/tools/perf/tests/attr/test-stat-no-inherit
+++ b/tools/perf/tests/attr/test-stat-no-inherit
@@ -5,3 +5,4 @@ ret = 1
5 5
6[event:base-stat] 6[event:base-stat]
7inherit=0 7inherit=0
8optional=1
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index 50f6d7afee58..71b9a0b613d2 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Test backward bit in event attribute, read ring buffer from end to 3 * Test backward bit in event attribute, read ring buffer from end to
3 * beginning 4 * beginning
@@ -75,7 +76,7 @@ static int do_test(struct perf_evlist *evlist, int mmap_pages,
75} 76}
76 77
77 78
78int test__backward_ring_buffer(int subtest __maybe_unused) 79int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __maybe_unused)
79{ 80{
80 int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0; 81 int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0;
81 char pid[16], sbuf[STRERR_BUFSIZE]; 82 char pid[16], sbuf[STRERR_BUFSIZE];
diff --git a/tools/perf/tests/bitmap.c b/tools/perf/tests/bitmap.c
index 9abe6c13090f..47bedf25ba69 100644
--- a/tools/perf/tests/bitmap.c
+++ b/tools/perf/tests/bitmap.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include <linux/bitmap.h> 3#include <linux/bitmap.h>
3#include "tests.h" 4#include "tests.h"
@@ -40,7 +41,7 @@ static int test_bitmap(const char *str)
40 return ret; 41 return ret;
41} 42}
42 43
43int test__bitmap_print(int subtest __maybe_unused) 44int test__bitmap_print(struct test *test __maybe_unused, int subtest __maybe_unused)
44{ 45{
45 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1")); 46 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,5"));
diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c
index 39bbb97cd30a..335b695f4970 100644
--- a/tools/perf/tests/bp_signal.c
+++ b/tools/perf/tests/bp_signal.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Inspired by breakpoint overflow test done by 3 * Inspired by breakpoint overflow test done by
3 * Vince Weaver <vincent.weaver@maine.edu> for perf_event_tests 4 * Vince Weaver <vincent.weaver@maine.edu> for perf_event_tests
@@ -164,7 +165,7 @@ static long long bp_count(int fd)
164 return count; 165 return count;
165} 166}
166 167
167int test__bp_signal(int subtest __maybe_unused) 168int test__bp_signal(struct test *test __maybe_unused, int subtest __maybe_unused)
168{ 169{
169 struct sigaction sa; 170 struct sigaction sa;
170 long long count1, count2, count3; 171 long long count1, count2, count3;
diff --git a/tools/perf/tests/bp_signal_overflow.c b/tools/perf/tests/bp_signal_overflow.c
index 3b1ac6f31b15..ca962559e845 100644
--- a/tools/perf/tests/bp_signal_overflow.c
+++ b/tools/perf/tests/bp_signal_overflow.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Originally done by Vince Weaver <vincent.weaver@maine.edu> for 3 * Originally done by Vince Weaver <vincent.weaver@maine.edu> for
3 * perf_event_tests (git://github.com/deater/perf_event_tests) 4 * perf_event_tests (git://github.com/deater/perf_event_tests)
@@ -57,7 +58,7 @@ static long long bp_count(int fd)
57#define EXECUTIONS 10000 58#define EXECUTIONS 10000
58#define THRESHOLD 100 59#define THRESHOLD 100
59 60
60int test__bp_signal_overflow(int subtest __maybe_unused) 61int test__bp_signal_overflow(struct test *test __maybe_unused, int subtest __maybe_unused)
61{ 62{
62 struct perf_event_attr pe; 63 struct perf_event_attr pe;
63 struct sigaction sa; 64 struct sigaction sa;
diff --git a/tools/perf/tests/bpf-script-test-prologue.c b/tools/perf/tests/bpf-script-test-prologue.c
index b4ebc75e25ae..43f1e16486f4 100644
--- a/tools/perf/tests/bpf-script-test-prologue.c
+++ b/tools/perf/tests/bpf-script-test-prologue.c
@@ -26,9 +26,11 @@ static void (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
26 (void *) 6; 26 (void *) 6;
27 27
28SEC("func=null_lseek file->f_mode offset orig") 28SEC("func=null_lseek file->f_mode offset orig")
29int bpf_func__null_lseek(void *ctx, int err, unsigned long f_mode, 29int bpf_func__null_lseek(void *ctx, int err, unsigned long _f_mode,
30 unsigned long offset, unsigned long orig) 30 unsigned long offset, unsigned long orig)
31{ 31{
32 fmode_t f_mode = (fmode_t)_f_mode;
33
32 if (err) 34 if (err)
33 return 0; 35 return 0;
34 if (f_mode & FMODE_WRITE) 36 if (f_mode & FMODE_WRITE)
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index 5876da126b58..34c22cdf4d5d 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -124,16 +124,16 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
124 struct perf_evlist *evlist; 124 struct perf_evlist *evlist;
125 int i, ret = TEST_FAIL, err = 0, count = 0; 125 int i, ret = TEST_FAIL, err = 0, count = 0;
126 126
127 struct parse_events_evlist parse_evlist; 127 struct parse_events_state parse_state;
128 struct parse_events_error parse_error; 128 struct parse_events_error parse_error;
129 129
130 bzero(&parse_error, sizeof(parse_error)); 130 bzero(&parse_error, sizeof(parse_error));
131 bzero(&parse_evlist, sizeof(parse_evlist)); 131 bzero(&parse_state, sizeof(parse_state));
132 parse_evlist.error = &parse_error; 132 parse_state.error = &parse_error;
133 INIT_LIST_HEAD(&parse_evlist.list); 133 INIT_LIST_HEAD(&parse_state.list);
134 134
135 err = parse_events_load_bpf_obj(&parse_evlist, &parse_evlist.list, obj, NULL); 135 err = parse_events_load_bpf_obj(&parse_state, &parse_state.list, obj, NULL);
136 if (err || list_empty(&parse_evlist.list)) { 136 if (err || list_empty(&parse_state.list)) {
137 pr_debug("Failed to add events selected by BPF\n"); 137 pr_debug("Failed to add events selected by BPF\n");
138 return TEST_FAIL; 138 return TEST_FAIL;
139 } 139 }
@@ -155,8 +155,8 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
155 goto out_delete_evlist; 155 goto out_delete_evlist;
156 } 156 }
157 157
158 perf_evlist__splice_list_tail(evlist, &parse_evlist.list); 158 perf_evlist__splice_list_tail(evlist, &parse_state.list);
159 evlist->nr_groups = parse_evlist.nr_groups; 159 evlist->nr_groups = parse_state.nr_groups;
160 160
161 perf_evlist__config(evlist, &opts, NULL); 161 perf_evlist__config(evlist, &opts, NULL);
162 162
@@ -321,7 +321,7 @@ static int check_env(void)
321 return 0; 321 return 0;
322} 322}
323 323
324int test__bpf(int i) 324int test__bpf(struct test *test __maybe_unused, int i)
325{ 325{
326 int err; 326 int err;
327 327
@@ -351,7 +351,7 @@ const char *test__bpf_subtest_get_desc(int i __maybe_unused)
351 return NULL; 351 return NULL;
352} 352}
353 353
354int test__bpf(int i __maybe_unused) 354int test__bpf(struct test *test __maybe_unused, int i __maybe_unused)
355{ 355{
356 pr_debug("Skip BPF test because BPF support is not compiled\n"); 356 pr_debug("Skip BPF test because BPF support is not compiled\n");
357 return TEST_SKIP; 357 return TEST_SKIP;
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 3ccfd58a8c3c..766573e236e4 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -1,12 +1,17 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * builtin-test.c 3 * builtin-test.c
3 * 4 *
4 * Builtin regression testing command: ever growing number of sanity tests 5 * Builtin regression testing command: ever growing number of sanity tests
5 */ 6 */
7#include <fcntl.h>
6#include <errno.h> 8#include <errno.h>
7#include <unistd.h> 9#include <unistd.h>
8#include <string.h> 10#include <string.h>
11#include <sys/types.h>
12#include <dirent.h>
9#include <sys/wait.h> 13#include <sys/wait.h>
14#include <sys/stat.h>
10#include "builtin.h" 15#include "builtin.h"
11#include "hist.h" 16#include "hist.h"
12#include "intlist.h" 17#include "intlist.h"
@@ -14,8 +19,10 @@
14#include "debug.h" 19#include "debug.h"
15#include "color.h" 20#include "color.h"
16#include <subcmd/parse-options.h> 21#include <subcmd/parse-options.h>
22#include "string2.h"
17#include "symbol.h" 23#include "symbol.h"
18#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <subcmd/exec-cmd.h>
19 26
20static bool dont_fork; 27static bool dont_fork;
21 28
@@ -43,6 +50,10 @@ static struct test generic_tests[] = {
43 .func = test__basic_mmap, 50 .func = test__basic_mmap,
44 }, 51 },
45 { 52 {
53 .desc = "Test data source output",
54 .func = test__mem,
55 },
56 {
46 .desc = "Parse event definition strings", 57 .desc = "Parse event definition strings",
47 .func = test__parse_events, 58 .func = test__parse_events,
48 }, 59 },
@@ -179,7 +190,7 @@ static struct test generic_tests[] = {
179 }, 190 },
180 { 191 {
181 .desc = "Session topology", 192 .desc = "Session topology",
182 .func = test_session_topology, 193 .func = test__session_topology,
183 }, 194 },
184 { 195 {
185 .desc = "BPF filter", 196 .desc = "BPF filter",
@@ -325,7 +336,7 @@ static int run_test(struct test *test, int subtest)
325 } 336 }
326 } 337 }
327 338
328 err = test->func(subtest); 339 err = test->func(test, subtest);
329 if (!dont_fork) 340 if (!dont_fork)
330 exit(err); 341 exit(err);
331 } 342 }
@@ -383,12 +394,143 @@ static int test_and_print(struct test *t, bool force_skip, int subtest)
383 return err; 394 return err;
384} 395}
385 396
397static const char *shell_test__description(char *description, size_t size,
398 const char *path, const char *name)
399{
400 FILE *fp;
401 char filename[PATH_MAX];
402
403 path__join(filename, sizeof(filename), path, name);
404 fp = fopen(filename, "r");
405 if (!fp)
406 return NULL;
407
408 description = fgets(description, size, fp);
409 fclose(fp);
410
411 return description ? trim(description + 1) : NULL;
412}
413
414#define for_each_shell_test(dir, ent) \
415 while ((ent = readdir(dir)) != NULL) \
416 if (ent->d_type == DT_REG && ent->d_name[0] != '.')
417
418static const char *shell_tests__dir(char *path, size_t size)
419{
420 const char *devel_dirs[] = { "./tools/perf/tests", "./tests", };
421 char *exec_path;
422 unsigned int i;
423
424 for (i = 0; i < ARRAY_SIZE(devel_dirs); ++i) {
425 struct stat st;
426 if (!lstat(devel_dirs[i], &st)) {
427 scnprintf(path, size, "%s/shell", devel_dirs[i]);
428 if (!lstat(devel_dirs[i], &st))
429 return path;
430 }
431 }
432
433 /* Then installed path. */
434 exec_path = get_argv_exec_path();
435 scnprintf(path, size, "%s/tests/shell", exec_path);
436 free(exec_path);
437 return path;
438}
439
440static int shell_tests__max_desc_width(void)
441{
442 DIR *dir;
443 struct dirent *ent;
444 char path_dir[PATH_MAX];
445 const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
446 int width = 0;
447
448 if (path == NULL)
449 return -1;
450
451 dir = opendir(path);
452 if (!dir)
453 return -1;
454
455 for_each_shell_test(dir, ent) {
456 char bf[256];
457 const char *desc = shell_test__description(bf, sizeof(bf), path, ent->d_name);
458
459 if (desc) {
460 int len = strlen(desc);
461
462 if (width < len)
463 width = len;
464 }
465 }
466
467 closedir(dir);
468 return width;
469}
470
471struct shell_test {
472 const char *dir;
473 const char *file;
474};
475
476static int shell_test__run(struct test *test, int subdir __maybe_unused)
477{
478 int err;
479 char script[PATH_MAX];
480 struct shell_test *st = test->priv;
481
482 path__join(script, sizeof(script), st->dir, st->file);
483
484 err = system(script);
485 if (!err)
486 return TEST_OK;
487
488 return WEXITSTATUS(err) == 2 ? TEST_SKIP : TEST_FAIL;
489}
490
491static int run_shell_tests(int argc, const char *argv[], int i, int width)
492{
493 DIR *dir;
494 struct dirent *ent;
495 char path_dir[PATH_MAX];
496 struct shell_test st = {
497 .dir = shell_tests__dir(path_dir, sizeof(path_dir)),
498 };
499
500 if (st.dir == NULL)
501 return -1;
502
503 dir = opendir(st.dir);
504 if (!dir)
505 return -1;
506
507 for_each_shell_test(dir, ent) {
508 int curr = i++;
509 char desc[256];
510 struct test test = {
511 .desc = shell_test__description(desc, sizeof(desc), st.dir, ent->d_name),
512 .func = shell_test__run,
513 .priv = &st,
514 };
515
516 if (!perf_test__matches(&test, curr, argc, argv))
517 continue;
518
519 st.file = ent->d_name;
520 pr_info("%2d: %-*s:", i, width, test.desc);
521 test_and_print(&test, false, -1);
522 }
523
524 closedir(dir);
525 return 0;
526}
527
386static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) 528static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
387{ 529{
388 struct test *t; 530 struct test *t;
389 unsigned int j; 531 unsigned int j;
390 int i = 0; 532 int i = 0;
391 int width = 0; 533 int width = shell_tests__max_desc_width();
392 534
393 for_each_test(j, t) { 535 for_each_test(j, t) {
394 int len = strlen(t->desc); 536 int len = strlen(t->desc);
@@ -455,6 +597,37 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
455 } 597 }
456 } 598 }
457 599
600 return run_shell_tests(argc, argv, i, width);
601}
602
603static int perf_test__list_shell(int argc, const char **argv, int i)
604{
605 DIR *dir;
606 struct dirent *ent;
607 char path_dir[PATH_MAX];
608 const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
609
610 if (path == NULL)
611 return -1;
612
613 dir = opendir(path);
614 if (!dir)
615 return -1;
616
617 for_each_shell_test(dir, ent) {
618 int curr = i++;
619 char bf[256];
620 struct test t = {
621 .desc = shell_test__description(bf, sizeof(bf), path, ent->d_name),
622 };
623
624 if (!perf_test__matches(&t, curr, argc, argv))
625 continue;
626
627 pr_info("%2d: %s\n", i, t.desc);
628 }
629
630 closedir(dir);
458 return 0; 631 return 0;
459} 632}
460 633
@@ -465,12 +638,17 @@ static int perf_test__list(int argc, const char **argv)
465 int i = 0; 638 int i = 0;
466 639
467 for_each_test(j, t) { 640 for_each_test(j, t) {
468 if (argc > 1 && !strstr(t->desc, argv[1])) 641 int curr = i++;
642
643 if (!perf_test__matches(t, curr, argc, argv) ||
644 (t->is_supported && !t->is_supported()))
469 continue; 645 continue;
470 646
471 pr_info("%2d: %s\n", ++i, t->desc); 647 pr_info("%2d: %s\n", i, t->desc);
472 } 648 }
473 649
650 perf_test__list_shell(argc, argv, i);
651
474 return 0; 652 return 0;
475} 653}
476 654
@@ -498,7 +676,7 @@ int cmd_test(int argc, const char **argv)
498 676
499 argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0); 677 argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0);
500 if (argc >= 1 && !strcmp(argv[0], "list")) 678 if (argc >= 1 && !strcmp(argv[0], "list"))
501 return perf_test__list(argc, argv); 679 return perf_test__list(argc - 1, argv + 1);
502 680
503 symbol_conf.priv_size = sizeof(int); 681 symbol_conf.priv_size = sizeof(int);
504 symbol_conf.sort_by_name = true; 682 symbol_conf.sort_by_name = true;
diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
index c5bb2203f5a9..f45fe11dcf50 100644
--- a/tools/perf/tests/clang.c
+++ b/tools/perf/tests/clang.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "tests.h" 2#include "tests.h"
2#include "debug.h" 3#include "debug.h"
3#include "util.h" 4#include "util.h"
@@ -33,12 +34,12 @@ const char *test__clang_subtest_get_desc(int i)
33} 34}
34 35
35#ifndef HAVE_LIBCLANGLLVM_SUPPORT 36#ifndef HAVE_LIBCLANGLLVM_SUPPORT
36int test__clang(int i __maybe_unused) 37int test__clang(struct test *test __maybe_unused, int i __maybe_unused)
37{ 38{
38 return TEST_SKIP; 39 return TEST_SKIP;
39} 40}
40#else 41#else
41int test__clang(int i) 42int test__clang(struct test *test __maybe_unused, int i)
42{ 43{
43 if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table)) 44 if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
44 return TEST_FAIL; 45 return TEST_FAIL;
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 94b7c7b02bde..fcc8984bc329 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <linux/kernel.h> 3#include <linux/kernel.h>
3#include <linux/types.h> 4#include <linux/types.h>
@@ -237,6 +238,11 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
237 238
238 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al); 239 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al);
239 if (!al.map || !al.map->dso) { 240 if (!al.map || !al.map->dso) {
241 if (cpumode == PERF_RECORD_MISC_HYPERVISOR) {
242 pr_debug("Hypervisor address can not be resolved - skipping\n");
243 return 0;
244 }
245
240 pr_debug("thread__find_addr_map failed\n"); 246 pr_debug("thread__find_addr_map failed\n");
241 return -1; 247 return -1;
242 } 248 }
@@ -673,7 +679,7 @@ out_err:
673 return err; 679 return err;
674} 680}
675 681
676int test__code_reading(int subtest __maybe_unused) 682int test__code_reading(struct test *test __maybe_unused, int subtest __maybe_unused)
677{ 683{
678 int ret; 684 int ret;
679 685
diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c
index 4478773cdb97..e78b897677bd 100644
--- a/tools/perf/tests/cpumap.c
+++ b/tools/perf/tests/cpumap.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "tests.h" 2#include "tests.h"
2#include <stdio.h> 3#include <stdio.h>
3#include "cpumap.h" 4#include "cpumap.h"
@@ -72,7 +73,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
72} 73}
73 74
74 75
75int test__cpu_map_synthesize(int subtest __maybe_unused) 76int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __maybe_unused)
76{ 77{
77 struct cpu_map *cpus; 78 struct cpu_map *cpus;
78 79
@@ -106,7 +107,7 @@ static int cpu_map_print(const char *str)
106 return !strcmp(buf, str); 107 return !strcmp(buf, str);
107} 108}
108 109
109int test__cpu_map_print(int subtest __maybe_unused) 110int test__cpu_map_print(struct test *test __maybe_unused, int subtest __maybe_unused)
110{ 111{
111 TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1")); 112 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,5"));
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index 8f08df5861cb..7f6c52021e41 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <dirent.h> 2#include <dirent.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <linux/kernel.h> 4#include <linux/kernel.h>
@@ -112,7 +113,7 @@ static int dso__data_fd(struct dso *dso, struct machine *machine)
112 return fd; 113 return fd;
113} 114}
114 115
115int test__dso_data(int subtest __maybe_unused) 116int test__dso_data(struct test *test __maybe_unused, int subtest __maybe_unused)
116{ 117{
117 struct machine machine; 118 struct machine machine;
118 struct dso *dso; 119 struct dso *dso;
@@ -247,7 +248,7 @@ static int set_fd_limit(int n)
247 return setrlimit(RLIMIT_NOFILE, &rlim); 248 return setrlimit(RLIMIT_NOFILE, &rlim);
248} 249}
249 250
250int test__dso_data_cache(int subtest __maybe_unused) 251int test__dso_data_cache(struct test *test __maybe_unused, int subtest __maybe_unused)
251{ 252{
252 struct machine machine; 253 struct machine machine;
253 long nr_end, nr = open_files_cnt(); 254 long nr_end, nr = open_files_cnt();
@@ -307,7 +308,7 @@ int test__dso_data_cache(int subtest __maybe_unused)
307 return 0; 308 return 0;
308} 309}
309 310
310int test__dso_data_reopen(int subtest __maybe_unused) 311int test__dso_data_reopen(struct test *test __maybe_unused, int subtest __maybe_unused)
311{ 312{
312 struct machine machine; 313 struct machine machine;
313 long nr_end, nr = open_files_cnt(); 314 long nr_end, nr = open_files_cnt();
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 3e56d08f7995..ac40e05bcab4 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include <linux/types.h> 3#include <linux/types.h>
3#include <inttypes.h> 4#include <inttypes.h>
@@ -6,7 +7,7 @@
6#include "debug.h" 7#include "debug.h"
7#include "machine.h" 8#include "machine.h"
8#include "event.h" 9#include "event.h"
9#include "unwind.h" 10#include "../util/unwind.h"
10#include "perf_regs.h" 11#include "perf_regs.h"
11#include "map.h" 12#include "map.h"
12#include "thread.h" 13#include "thread.h"
@@ -154,7 +155,7 @@ static noinline int krava_1(struct thread *thread)
154 return krava_2(thread); 155 return krava_2(thread);
155} 156}
156 157
157int test__dwarf_unwind(int subtest __maybe_unused) 158int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unused)
158{ 159{
159 struct machine *machine; 160 struct machine *machine;
160 struct thread *thread; 161 struct thread *thread;
diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c
index 634f20c631d8..1a2686f1fcf0 100644
--- a/tools/perf/tests/event-times.c
+++ b/tools/perf/tests/event-times.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include <errno.h> 3#include <errno.h>
3#include <inttypes.h> 4#include <inttypes.h>
@@ -213,7 +214,7 @@ out_err:
213 * and checks that enabled and running times 214 * and checks that enabled and running times
214 * match. 215 * match.
215 */ 216 */
216int test__event_times(int subtest __maybe_unused) 217int test__event_times(struct test *test __maybe_unused, int subtest __maybe_unused)
217{ 218{
218 int err, ret = 0; 219 int err, ret = 0;
219 220
diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c
index 63ecf21750eb..f14dcd613438 100644
--- a/tools/perf/tests/event_update.c
+++ b/tools/perf/tests/event_update.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include "evlist.h" 3#include "evlist.h"
3#include "evsel.h" 4#include "evsel.h"
@@ -76,7 +77,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
76 return 0; 77 return 0;
77} 78}
78 79
79int test__event_update(int subtest __maybe_unused) 80int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unused)
80{ 81{
81 struct perf_evlist *evlist; 82 struct perf_evlist *evlist;
82 struct perf_evsel *evsel; 83 struct perf_evsel *evsel;
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c
index d2bea6f780f8..a104728ebf25 100644
--- a/tools/perf/tests/evsel-roundtrip-name.c
+++ b/tools/perf/tests/evsel-roundtrip-name.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "evlist.h" 2#include "evlist.h"
2#include "evsel.h" 3#include "evsel.h"
3#include "parse-events.h" 4#include "parse-events.h"
@@ -97,7 +98,7 @@ out_delete_evlist:
97#define perf_evsel__name_array_test(names) \ 98#define perf_evsel__name_array_test(names) \
98 __perf_evsel__name_array_test(names, ARRAY_SIZE(names)) 99 __perf_evsel__name_array_test(names, ARRAY_SIZE(names))
99 100
100int test__perf_evsel__roundtrip_name_test(int subtest __maybe_unused) 101int test__perf_evsel__roundtrip_name_test(struct test *test __maybe_unused, int subtest __maybe_unused)
101{ 102{
102 int err = 0, ret = 0; 103 int err = 0, ret = 0;
103 104
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
index 1984b3bbfe15..699561fa512c 100644
--- a/tools/perf/tests/evsel-tp-sched.c
+++ b/tools/perf/tests/evsel-tp-sched.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/err.h> 2#include <linux/err.h>
2#include <traceevent/event-parse.h> 3#include <traceevent/event-parse.h>
3#include "evsel.h" 4#include "evsel.h"
@@ -32,7 +33,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
32 return ret; 33 return ret;
33} 34}
34 35
35int test__perf_evsel__tp_sched_test(int subtest __maybe_unused) 36int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtest __maybe_unused)
36{ 37{
37 struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch"); 38 struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch");
38 int ret = 0; 39 int ret = 0;
diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
index 6c6a3749aaf6..01f0706995a9 100644
--- a/tools/perf/tests/expr.c
+++ b/tools/perf/tests/expr.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "util/debug.h" 2#include "util/debug.h"
2#include "util/expr.h" 3#include "util/expr.h"
3#include "tests.h" 4#include "tests.h"
@@ -13,7 +14,7 @@ static int test(struct parse_ctx *ctx, const char *e, double val2)
13 return 0; 14 return 0;
14} 15}
15 16
16int test__expr(int subtest __maybe_unused) 17int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused)
17{ 18{
18 const char *p; 19 const char *p;
19 const char **other; 20 const char **other;
@@ -31,6 +32,11 @@ int test__expr(int subtest __maybe_unused)
31 ret |= test(&ctx, "(BAR/2)%2", 1); 32 ret |= test(&ctx, "(BAR/2)%2", 1);
32 ret |= test(&ctx, "1 - -4", 5); 33 ret |= test(&ctx, "1 - -4", 5);
33 ret |= test(&ctx, "(FOO-1)*2 + (BAR/2)%2 - -4", 5); 34 ret |= test(&ctx, "(FOO-1)*2 + (BAR/2)%2 - -4", 5);
35 ret |= test(&ctx, "1-1 | 1", 1);
36 ret |= test(&ctx, "1-1 & 1", 0);
37 ret |= test(&ctx, "min(1,2) + 1", 2);
38 ret |= test(&ctx, "max(1,2) + 1", 3);
39 ret |= test(&ctx, "1+1 if 3*4 else 0", 2);
34 40
35 if (ret) 41 if (ret)
36 return ret; 42 return ret;
diff --git a/tools/perf/tests/fdarray.c b/tools/perf/tests/fdarray.c
index bc5982f42dc3..c7c81c4a5b2b 100644
--- a/tools/perf/tests/fdarray.c
+++ b/tools/perf/tests/fdarray.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <api/fd/array.h> 2#include <api/fd/array.h>
2#include <poll.h> 3#include <poll.h>
3#include "util/debug.h" 4#include "util/debug.h"
@@ -26,7 +27,7 @@ static int fdarray__fprintf_prefix(struct fdarray *fda, const char *prefix, FILE
26 return printed + fdarray__fprintf(fda, fp); 27 return printed + fdarray__fprintf(fda, fp);
27} 28}
28 29
29int test__fdarray__filter(int subtest __maybe_unused) 30int test__fdarray__filter(struct test *test __maybe_unused, int subtest __maybe_unused)
30{ 31{
31 int nr_fds, expected_fd[2], fd, err = TEST_FAIL; 32 int nr_fds, expected_fd[2], fd, err = TEST_FAIL;
32 struct fdarray *fda = fdarray__new(5, 5); 33 struct fdarray *fda = fdarray__new(5, 5);
@@ -104,7 +105,7 @@ out:
104 return err; 105 return err;
105} 106}
106 107
107int test__fdarray__add(int subtest __maybe_unused) 108int test__fdarray__add(struct test *test __maybe_unused, int subtest __maybe_unused)
108{ 109{
109 int err = TEST_FAIL; 110 int err = TEST_FAIL;
110 struct fdarray *fda = fdarray__new(2, 2); 111 struct fdarray *fda = fdarray__new(2, 2);
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c
index 00b8dc50f3db..f7c5b613d667 100644
--- a/tools/perf/tests/hists_common.c
+++ b/tools/perf/tests/hists_common.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <inttypes.h> 2#include <inttypes.h>
2#include "perf.h" 3#include "perf.h"
3#include "util/debug.h" 4#include "util/debug.h"
diff --git a/tools/perf/tests/hists_common.h b/tools/perf/tests/hists_common.h
index 888254e8665c..a2de0ff0ce3a 100644
--- a/tools/perf/tests/hists_common.h
+++ b/tools/perf/tests/hists_common.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_TESTS__HISTS_COMMON_H__ 2#ifndef __PERF_TESTS__HISTS_COMMON_H__
2#define __PERF_TESTS__HISTS_COMMON_H__ 3#define __PERF_TESTS__HISTS_COMMON_H__
3 4
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index d549a9f2c41b..65fe02bebbee 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "perf.h" 2#include "perf.h"
2#include "util/debug.h" 3#include "util/debug.h"
3#include "util/event.h" 4#include "util/event.h"
@@ -687,7 +688,7 @@ out:
687 return err; 688 return err;
688} 689}
689 690
690int test__hists_cumulate(int subtest __maybe_unused) 691int test__hists_cumulate(struct test *test __maybe_unused, int subtest __maybe_unused)
691{ 692{
692 int err = TEST_FAIL; 693 int err = TEST_FAIL;
693 struct machines machines; 694 struct machines machines;
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index df9c91f49af1..1c5bedab3c2c 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "perf.h" 2#include "perf.h"
2#include "util/debug.h" 3#include "util/debug.h"
3#include "util/symbol.h" 4#include "util/symbol.h"
@@ -101,7 +102,7 @@ out:
101 return TEST_FAIL; 102 return TEST_FAIL;
102} 103}
103 104
104int test__hists_filter(int subtest __maybe_unused) 105int test__hists_filter(struct test *test __maybe_unused, int subtest __maybe_unused)
105{ 106{
106 int err = TEST_FAIL; 107 int err = TEST_FAIL;
107 struct machines machines; 108 struct machines machines;
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index a26cbb79e988..9a9d06cb0222 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "perf.h" 2#include "perf.h"
2#include "tests.h" 3#include "tests.h"
3#include "debug.h" 4#include "debug.h"
@@ -264,7 +265,7 @@ static int validate_link(struct hists *leader, struct hists *other)
264 return __validate_link(leader, 0) || __validate_link(other, 1); 265 return __validate_link(leader, 0) || __validate_link(other, 1);
265} 266}
266 267
267int test__hists_link(int subtest __maybe_unused) 268int test__hists_link(struct test *test __maybe_unused, int subtest __maybe_unused)
268{ 269{
269 int err = -1; 270 int err = -1;
270 struct hists *hists, *first_hists; 271 struct hists *hists, *first_hists;
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index 06e5080182d3..faacb4f41460 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "perf.h" 2#include "perf.h"
2#include "util/debug.h" 3#include "util/debug.h"
3#include "util/event.h" 4#include "util/event.h"
@@ -573,7 +574,7 @@ out:
573 return err; 574 return err;
574} 575}
575 576
576int test__hists_output(int subtest __maybe_unused) 577int test__hists_output(struct test *test __maybe_unused, int subtest __maybe_unused)
577{ 578{
578 int err = TEST_FAIL; 579 int err = TEST_FAIL;
579 struct machines machines; 580 struct machines machines;
diff --git a/tools/perf/tests/is_printable_array.c b/tools/perf/tests/is_printable_array.c
index a5192f6a20d7..9c7b3baca4fe 100644
--- a/tools/perf/tests/is_printable_array.c
+++ b/tools/perf/tests/is_printable_array.c
@@ -1,10 +1,11 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include <linux/kernel.h> 3#include <linux/kernel.h>
3#include "tests.h" 4#include "tests.h"
4#include "debug.h" 5#include "debug.h"
5#include "print_binary.h" 6#include "print_binary.h"
6 7
7int test__is_printable_array(int subtest __maybe_unused) 8int test__is_printable_array(struct test *test __maybe_unused, int subtest __maybe_unused)
8{ 9{
9 char buf1[] = { 'k', 'r', 4, 'v', 'a', 0 }; 10 char buf1[] = { 'k', 'r', 4, 'v', 'a', 0 };
10 char buf2[] = { 'k', 'r', 'a', 'v', 4, 0 }; 11 char buf2[] = { 'k', 'r', 'a', 'v', 4, 0 };
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index 614e45a3c603..842d33637a18 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/types.h> 2#include <linux/types.h>
2#include <unistd.h> 3#include <unistd.h>
3#include <sys/prctl.h> 4#include <sys/prctl.h>
@@ -49,7 +50,7 @@ static int find_comm(struct perf_evlist *evlist, const char *comm)
49 * when an event is disabled but a dummy software event is not disabled. If the 50 * when an event is disabled but a dummy software event is not disabled. If the
50 * test passes %0 is returned, otherwise %-1 is returned. 51 * test passes %0 is returned, otherwise %-1 is returned.
51 */ 52 */
52int test__keep_tracking(int subtest __maybe_unused) 53int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_unused)
53{ 54{
54 struct record_opts opts = { 55 struct record_opts opts = {
55 .mmap_pages = UINT_MAX, 56 .mmap_pages = UINT_MAX,
diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c
index 6cd9e5107f77..8e57d46109de 100644
--- a/tools/perf/tests/kmod-path.c
+++ b/tools/perf/tests/kmod-path.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdbool.h> 2#include <stdbool.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include "tests.h" 4#include "tests.h"
@@ -50,7 +51,7 @@ static int test_is_kernel_module(const char *path, int cpumode, bool expect)
50#define M(path, c, e) \ 51#define M(path, c, e) \
51 TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e)) 52 TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e))
52 53
53int test__kmod_path__parse(int subtest __maybe_unused) 54int test__kmod_path__parse(struct test *t __maybe_unused, int subtest __maybe_unused)
54{ 55{
55 /* path alloc_name alloc_ext kmod comp name ext */ 56 /* path alloc_name alloc_ext kmod comp name ext */
56 T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL); 57 T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL);
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index 482b5365e68d..a039f93199e5 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <bpf/libbpf.h> 3#include <bpf/libbpf.h>
3#include <util/llvm-utils.h> 4#include <util/llvm-utils.h>
@@ -132,7 +133,7 @@ out:
132 return ret; 133 return ret;
133} 134}
134 135
135int test__llvm(int subtest) 136int test__llvm(struct test *test __maybe_unused, int subtest)
136{ 137{
137 int ret; 138 int ret;
138 void *obj_buf = NULL; 139 void *obj_buf = NULL;
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
index b83571758d83..f68b0d9b8ae2 100644
--- a/tools/perf/tests/llvm.h
+++ b/tools/perf/tests/llvm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PERF_TEST_LLVM_H 2#ifndef PERF_TEST_LLVM_H
2#define PERF_TEST_LLVM_H 3#define PERF_TEST_LLVM_H
3 4
diff --git a/tools/perf/tests/mem.c b/tools/perf/tests/mem.c
new file mode 100644
index 000000000000..21952e1e6e6d
--- /dev/null
+++ b/tools/perf/tests/mem.c
@@ -0,0 +1,56 @@
1#include "util/mem-events.h"
2#include "util/symbol.h"
3#include "linux/perf_event.h"
4#include "util/debug.h"
5#include "tests.h"
6#include <string.h>
7
8static int check(union perf_mem_data_src data_src,
9 const char *string)
10{
11 char out[100];
12 char failure[100];
13 struct mem_info mi = { .data_src = data_src };
14
15 int n;
16
17 n = perf_mem__snp_scnprintf(out, sizeof out, &mi);
18 n += perf_mem__lvl_scnprintf(out + n, sizeof out - n, &mi);
19 snprintf(failure, sizeof failure, "unexpected %s", out);
20 TEST_ASSERT_VAL(failure, !strcmp(string, out));
21 return 0;
22}
23
24int test__mem(struct test *text __maybe_unused, int subtest __maybe_unused)
25{
26 int ret = 0;
27 union perf_mem_data_src src;
28
29 memset(&src, 0, sizeof(src));
30
31 src.mem_lvl = PERF_MEM_LVL_HIT;
32 src.mem_lvl_num = 4;
33
34 ret |= check(src, "N/AL4 hit");
35
36 src.mem_remote = 1;
37
38 ret |= check(src, "N/ARemote L4 hit");
39
40 src.mem_lvl = PERF_MEM_LVL_MISS;
41 src.mem_lvl_num = PERF_MEM_LVLNUM_PMEM;
42 src.mem_remote = 0;
43
44 ret |= check(src, "N/APMEM miss");
45
46 src.mem_remote = 1;
47
48 ret |= check(src, "N/ARemote PMEM miss");
49
50 src.mem_snoopx = PERF_MEM_SNOOPX_FWD;
51 src.mem_lvl_num = PERF_MEM_LVLNUM_RAM;
52
53 ret |= check(src , "FwdRemote RAM miss");
54
55 return ret;
56}
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 15c770856aac..5a8bf318f8a7 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <inttypes.h> 3#include <inttypes.h>
3/* For the CLR_() macros */ 4/* For the CLR_() macros */
@@ -22,7 +23,7 @@
22 * Then it checks if the number of syscalls reported as perf events by 23 * Then it checks if the number of syscalls reported as perf events by
23 * the kernel corresponds to the number of syscalls made. 24 * the kernel corresponds to the number of syscalls made.
24 */ 25 */
25int test__basic_mmap(int subtest __maybe_unused) 26int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unused)
26{ 27{
27 int err = -1; 28 int err = -1;
28 union perf_event *event; 29 union perf_event *event;
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c
index 6ea4d8a5d26b..868d82b501f4 100644
--- a/tools/perf/tests/mmap-thread-lookup.c
+++ b/tools/perf/tests/mmap-thread-lookup.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <inttypes.h> 2#include <inttypes.h>
2#include <unistd.h> 3#include <unistd.h>
3#include <sys/syscall.h> 4#include <sys/syscall.h>
@@ -131,7 +132,7 @@ static int synth_all(struct machine *machine)
131{ 132{
132 return perf_event__synthesize_threads(NULL, 133 return perf_event__synthesize_threads(NULL,
133 perf_event__process, 134 perf_event__process,
134 machine, 0, 500); 135 machine, 0, 500, 1);
135} 136}
136 137
137static int synth_process(struct machine *machine) 138static int synth_process(struct machine *machine)
@@ -221,7 +222,7 @@ static int mmap_events(synth_cb synth)
221 * 222 *
222 * by using all thread objects. 223 * by using all thread objects.
223 */ 224 */
224int test__mmap_thread_lookup(int subtest __maybe_unused) 225int test__mmap_thread_lookup(struct test *test __maybe_unused, int subtest __maybe_unused)
225{ 226{
226 /* perf_event__synthesize_threads synthesize */ 227 /* perf_event__synthesize_threads synthesize */
227 TEST_ASSERT_VAL("failed with sythesizing all", 228 TEST_ASSERT_VAL("failed with sythesizing all",
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index 1a74dd9fd067..c531e6deb104 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <inttypes.h> 3#include <inttypes.h>
3/* For the CPU_* macros */ 4/* For the CPU_* macros */
@@ -16,7 +17,7 @@
16#include "debug.h" 17#include "debug.h"
17#include "stat.h" 18#include "stat.h"
18 19
19int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused) 20int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int subtest __maybe_unused)
20{ 21{
21 int err = -1, fd, cpu; 22 int err = -1, fd, cpu;
22 struct cpu_map *cpus; 23 struct cpu_map *cpus;
@@ -115,7 +116,7 @@ int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused)
115 116
116 perf_evsel__free_counts(evsel); 117 perf_evsel__free_counts(evsel);
117out_close_fd: 118out_close_fd:
118 perf_evsel__close_fd(evsel, 1, threads->nr); 119 perf_evsel__close_fd(evsel);
119out_evsel_delete: 120out_evsel_delete:
120 perf_evsel__delete(evsel); 121 perf_evsel__delete(evsel);
121out_thread_map_delete: 122out_thread_map_delete:
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index 9788fac91095..d9619d265314 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/err.h> 2#include <linux/err.h>
2#include "perf.h" 3#include "perf.h"
3#include "evlist.h" 4#include "evlist.h"
@@ -14,7 +15,7 @@
14#define AT_FDCWD -100 15#define AT_FDCWD -100
15#endif 16#endif
16 17
17int test__syscall_openat_tp_fields(int subtest __maybe_unused) 18int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest __maybe_unused)
18{ 19{
19 struct record_opts opts = { 20 struct record_opts opts = {
20 .target = { 21 .target = {
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
index e44506e21ee7..00cd63f90b92 100644
--- a/tools/perf/tests/openat-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <inttypes.h> 3#include <inttypes.h>
3#include <api/fs/tracing_path.h> 4#include <api/fs/tracing_path.h>
@@ -10,7 +11,7 @@
10#include "debug.h" 11#include "debug.h"
11#include "tests.h" 12#include "tests.h"
12 13
13int test__openat_syscall_event(int subtest __maybe_unused) 14int test__openat_syscall_event(struct test *test __maybe_unused, int subtest __maybe_unused)
14{ 15{
15 int err = -1, fd; 16 int err = -1, fd;
16 struct perf_evsel *evsel; 17 struct perf_evsel *evsel;
@@ -56,7 +57,7 @@ int test__openat_syscall_event(int subtest __maybe_unused)
56 57
57 err = 0; 58 err = 0;
58out_close_fd: 59out_close_fd:
59 perf_evsel__close_fd(evsel, 1, threads->nr); 60 perf_evsel__close_fd(evsel);
60out_evsel_delete: 61out_evsel_delete:
61 perf_evsel__delete(evsel); 62 perf_evsel__delete(evsel);
62out_thread_map_delete: 63out_thread_map_delete:
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 812a053d1941..f0679613bd18 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "parse-events.h" 2#include "parse-events.h"
2#include "evsel.h" 3#include "evsel.h"
3#include "evlist.h" 4#include "evlist.h"
@@ -1810,7 +1811,7 @@ static int test_pmu_events(void)
1810 return ret; 1811 return ret;
1811} 1812}
1812 1813
1813int test__parse_events(int subtest __maybe_unused) 1814int test__parse_events(struct test *test __maybe_unused, int subtest __maybe_unused)
1814{ 1815{
1815 int ret1, ret2 = 0; 1816 int ret1, ret2 = 0;
1816 1817
diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c
index c6207db09f12..2196d1497c0c 100644
--- a/tools/perf/tests/parse-no-sample-id-all.c
+++ b/tools/perf/tests/parse-no-sample-id-all.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/kernel.h> 2#include <linux/kernel.h>
2#include <linux/types.h> 3#include <linux/types.h>
3#include <stddef.h> 4#include <stddef.h>
@@ -68,7 +69,7 @@ struct test_attr_event {
68 * 69 *
69 * Return: %0 on success, %-1 if the test fails. 70 * Return: %0 on success, %-1 if the test fails.
70 */ 71 */
71int test__parse_no_sample_id_all(int subtest __maybe_unused) 72int test__parse_no_sample_id_all(struct test *test __maybe_unused, int subtest __maybe_unused)
72{ 73{
73 int err; 74 int err;
74 75
diff --git a/tools/perf/tests/perf-hooks.c b/tools/perf/tests/perf-hooks.c
index 665ecc19671c..a693bcf017ea 100644
--- a/tools/perf/tests/perf-hooks.c
+++ b/tools/perf/tests/perf-hooks.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <signal.h> 2#include <signal.h>
2#include <stdlib.h> 3#include <stdlib.h>
3 4
@@ -27,7 +28,7 @@ static void the_hook(void *_hook_flags)
27 *p = 0; 28 *p = 0;
28} 29}
29 30
30int test__perf_hooks(int subtest __maybe_unused) 31int test__perf_hooks(struct test *test __maybe_unused, int subtest __maybe_unused)
31{ 32{
32 int hook_flags = 0; 33 int hook_flags = 0;
33 34
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index d37cd9588cc0..c34904d37705 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <inttypes.h> 3#include <inttypes.h>
3/* For the CLR_() macros */ 4/* For the CLR_() macros */
@@ -37,7 +38,7 @@ realloc:
37 return cpu; 38 return cpu;
38} 39}
39 40
40int test__PERF_RECORD(int subtest __maybe_unused) 41int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unused)
41{ 42{
42 struct record_opts opts = { 43 struct record_opts opts = {
43 .target = { 44 .target = {
diff --git a/tools/perf/tests/perf-targz-src-pkg b/tools/perf/tests/perf-targz-src-pkg
index f2d9c5fe58e0..fae26b1cf08f 100755
--- a/tools/perf/tests/perf-targz-src-pkg
+++ b/tools/perf/tests/perf-targz-src-pkg
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# Test one of the main kernel Makefile targets to generate a perf sources tarball 3# Test one of the main kernel Makefile targets to generate a perf sources tarball
3# suitable for build outside the full kernel sources. 4# suitable for build outside the full kernel sources.
4# 5#
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index a6d7aef30030..9abca267afa9 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "parse-events.h" 2#include "parse-events.h"
2#include "pmu.h" 3#include "pmu.h"
3#include "util.h" 4#include "util.h"
@@ -135,7 +136,7 @@ static struct list_head *test_terms_list(void)
135 return &terms; 136 return &terms;
136} 137}
137 138
138int test__pmu(int subtest __maybe_unused) 139int test__pmu(struct test *test __maybe_unused, int subtest __maybe_unused)
139{ 140{
140 char *format = test_format_dir_get(); 141 char *format = test_format_dir_get();
141 LIST_HEAD(formats); 142 LIST_HEAD(formats);
diff --git a/tools/perf/tests/python-use.c b/tools/perf/tests/python-use.c
index fa79509da535..5d2df65ada6a 100644
--- a/tools/perf/tests/python-use.c
+++ b/tools/perf/tests/python-use.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Just test if we can load the python binding. 3 * Just test if we can load the python binding.
3 */ 4 */
@@ -9,7 +10,7 @@
9 10
10extern int verbose; 11extern int verbose;
11 12
12int test__python_use(int subtest __maybe_unused) 13int test__python_use(struct test *test __maybe_unused, int subtest __maybe_unused)
13{ 14{
14 char *cmd; 15 char *cmd;
15 int ret; 16 int ret;
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index bac5c3885b3b..3ec6302b6498 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdbool.h> 2#include <stdbool.h>
2#include <inttypes.h> 3#include <inttypes.h>
3#include <linux/kernel.h> 4#include <linux/kernel.h>
@@ -141,6 +142,9 @@ static bool samples_same(const struct perf_sample *s1,
141 } 142 }
142 } 143 }
143 144
145 if (type & PERF_SAMPLE_PHYS_ADDR)
146 COMP(phys_addr);
147
144 return true; 148 return true;
145} 149}
146 150
@@ -206,6 +210,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
206 .mask = sample_regs, 210 .mask = sample_regs,
207 .regs = regs, 211 .regs = regs,
208 }, 212 },
213 .phys_addr = 113,
209 }; 214 };
210 struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},}; 215 struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},};
211 struct perf_sample sample_out; 216 struct perf_sample sample_out;
@@ -292,7 +297,7 @@ out_free:
292 * checks sample format bits separately and together. If the test passes %0 is 297 * checks sample format bits separately and together. If the test passes %0 is
293 * returned, otherwise %-1 is returned. 298 * returned, otherwise %-1 is returned.
294 */ 299 */
295int test__sample_parsing(int subtest __maybe_unused) 300int test__sample_parsing(struct test *test __maybe_unused, int subtest __maybe_unused)
296{ 301{
297 const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15}; 302 const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15};
298 u64 sample_type; 303 u64 sample_type;
@@ -305,7 +310,7 @@ int test__sample_parsing(int subtest __maybe_unused)
305 * were added. Please actually update the test rather than just change 310 * were added. Please actually update the test rather than just change
306 * the condition below. 311 * the condition below.
307 */ 312 */
308 if (PERF_SAMPLE_MAX > PERF_SAMPLE_REGS_INTR << 1) { 313 if (PERF_SAMPLE_MAX > PERF_SAMPLE_PHYS_ADDR << 1) {
309 pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n"); 314 pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n");
310 return -1; 315 return -1;
311 } 316 }
diff --git a/tools/perf/tests/sdt.c b/tools/perf/tests/sdt.c
index 06eda675ae2c..5059452d27dd 100644
--- a/tools/perf/tests/sdt.c
+++ b/tools/perf/tests/sdt.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <sys/epoll.h> 4#include <sys/epoll.h>
@@ -33,7 +34,7 @@ static int build_id_cache__add_file(const char *filename)
33 } 34 }
34 35
35 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 36 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
36 err = build_id_cache__add_s(sbuild_id, filename, false, false); 37 err = build_id_cache__add_s(sbuild_id, filename, NULL, false, false);
37 if (err < 0) 38 if (err < 0)
38 pr_debug("Failed to add build id cache of %s\n", filename); 39 pr_debug("Failed to add build id cache of %s\n", filename);
39 return err; 40 return err;
@@ -54,7 +55,7 @@ static char *get_self_path(void)
54static int search_cached_probe(const char *target, 55static int search_cached_probe(const char *target,
55 const char *group, const char *event) 56 const char *group, const char *event)
56{ 57{
57 struct probe_cache *cache = probe_cache__new(target); 58 struct probe_cache *cache = probe_cache__new(target, NULL);
58 int ret = 0; 59 int ret = 0;
59 60
60 if (!cache) { 61 if (!cache) {
@@ -71,7 +72,7 @@ static int search_cached_probe(const char *target,
71 return ret; 72 return ret;
72} 73}
73 74
74int test__sdt_event(int subtests __maybe_unused) 75int test__sdt_event(struct test *test __maybe_unused, int subtests __maybe_unused)
75{ 76{
76 int ret = TEST_FAIL; 77 int ret = TEST_FAIL;
77 char __tempdir[] = "./test-buildid-XXXXXX"; 78 char __tempdir[] = "./test-buildid-XXXXXX";
@@ -83,6 +84,8 @@ int test__sdt_event(int subtests __maybe_unused)
83 } 84 }
84 /* Note that buildid_dir must be an absolute path */ 85 /* Note that buildid_dir must be an absolute path */
85 tempdir = realpath(__tempdir, NULL); 86 tempdir = realpath(__tempdir, NULL);
87 if (tempdir == NULL)
88 goto error_rmdir;
86 89
87 /* At first, scan itself */ 90 /* At first, scan itself */
88 set_buildid_dir(tempdir); 91 set_buildid_dir(tempdir);
@@ -100,14 +103,14 @@ int test__sdt_event(int subtests __maybe_unused)
100 103
101error_rmdir: 104error_rmdir:
102 /* Cleanup temporary buildid dir */ 105 /* Cleanup temporary buildid dir */
103 rm_rf(tempdir); 106 rm_rf(__tempdir);
104error: 107error:
105 free(tempdir); 108 free(tempdir);
106 free(myself); 109 free(myself);
107 return ret; 110 return ret;
108} 111}
109#else 112#else
110int test__sdt_event(int subtests __maybe_unused) 113int test__sdt_event(struct test *test __maybe_unused, int subtests __maybe_unused)
111{ 114{
112 pr_debug("Skip SDT event test because SDT support is not compiled\n"); 115 pr_debug("Skip SDT event test because SDT support is not compiled\n");
113 return TEST_SKIP; 116 return TEST_SKIP;
diff --git a/tools/perf/tests/shell/lib/probe.sh b/tools/perf/tests/shell/lib/probe.sh
new file mode 100644
index 000000000000..6293cc660947
--- /dev/null
+++ b/tools/perf/tests/shell/lib/probe.sh
@@ -0,0 +1,6 @@
1# Arnaldo Carvalho de Melo <acme@kernel.org>, 2017
2
3skip_if_no_perf_probe() {
4 perf probe 2>&1 | grep -q 'is not a perf-command' && return 2
5 return 0
6}
diff --git a/tools/perf/tests/shell/lib/probe_vfs_getname.sh b/tools/perf/tests/shell/lib/probe_vfs_getname.sh
new file mode 100644
index 000000000000..30a950c9d407
--- /dev/null
+++ b/tools/perf/tests/shell/lib/probe_vfs_getname.sh
@@ -0,0 +1,23 @@
1# Arnaldo Carvalho de Melo <acme@kernel.org>, 2017
2
3perf probe -l 2>&1 | grep -q probe:vfs_getname
4had_vfs_getname=$?
5
6cleanup_probe_vfs_getname() {
7 if [ $had_vfs_getname -eq 1 ] ; then
8 perf probe -q -d probe:vfs_getname
9 fi
10}
11
12add_probe_vfs_getname() {
13 local verbose=$1
14 if [ $had_vfs_getname -eq 1 ] ; then
15 line=$(perf probe -L getname_flags 2>&1 | egrep 'result.*=.*filename;' | sed -r 's/[[:space:]]+([[:digit:]]+)[[:space:]]+result->uptr.*/\1/')
16 perf probe $verbose "vfs_getname=getname_flags:${line} pathname=result->name:string"
17 fi
18}
19
20skip_if_no_debuginfo() {
21 add_probe_vfs_getname -v 2>&1 | egrep -q "^(Failed to find the path for kernel|Debuginfo-analysis is not supported)" && return 2
22 return 1
23}
diff --git a/tools/perf/tests/shell/probe_vfs_getname.sh b/tools/perf/tests/shell/probe_vfs_getname.sh
new file mode 100755
index 000000000000..9b7635184dc2
--- /dev/null
+++ b/tools/perf/tests/shell/probe_vfs_getname.sh
@@ -0,0 +1,14 @@
1# Add vfs_getname probe to get syscall args filenames
2#
3# Arnaldo Carvalho de Melo <acme@kernel.org>, 2017
4
5. $(dirname $0)/lib/probe.sh
6
7skip_if_no_perf_probe || exit 2
8
9. $(dirname $0)/lib/probe_vfs_getname.sh
10
11add_probe_vfs_getname || skip_if_no_debuginfo
12err=$?
13cleanup_probe_vfs_getname
14exit $err
diff --git a/tools/perf/tests/shell/record+script_probe_vfs_getname.sh b/tools/perf/tests/shell/record+script_probe_vfs_getname.sh
new file mode 100755
index 000000000000..ba29535b8580
--- /dev/null
+++ b/tools/perf/tests/shell/record+script_probe_vfs_getname.sh
@@ -0,0 +1,41 @@
1# Use vfs_getname probe to get syscall args filenames
2
3# Uses the 'perf test shell' library to add probe:vfs_getname to the system
4# then use it with 'perf record' using 'touch' to write to a temp file, then
5# checks that that was captured by the vfs_getname probe in the generated
6# perf.data file, with the temp file name as the pathname argument.
7
8# Arnaldo Carvalho de Melo <acme@kernel.org>, 2017
9
10. $(dirname $0)/lib/probe.sh
11
12skip_if_no_perf_probe || exit 2
13
14. $(dirname $0)/lib/probe_vfs_getname.sh
15
16perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX)
17file=$(mktemp /tmp/temporary_file.XXXXX)
18
19record_open_file() {
20 echo "Recording open file:"
21 perf record -o ${perfdata} -e probe:vfs_getname touch $file
22}
23
24perf_script_filenames() {
25 echo "Looking at perf.data file for vfs_getname records for the file we touched:"
26 perf script -i ${perfdata} | \
27 egrep " +touch +[0-9]+ +\[[0-9]+\] +[0-9]+\.[0-9]+: +probe:vfs_getname: +\([[:xdigit:]]+\) +pathname=\"${file}\""
28}
29
30add_probe_vfs_getname || skip_if_no_debuginfo
31err=$?
32if [ $err -ne 0 ] ; then
33 exit $err
34fi
35
36record_open_file && perf_script_filenames
37err=$?
38rm -f ${perfdata}
39rm -f ${file}
40cleanup_probe_vfs_getname
41exit $err
diff --git a/tools/perf/tests/shell/trace+probe_libc_inet_pton.sh b/tools/perf/tests/shell/trace+probe_libc_inet_pton.sh
new file mode 100755
index 000000000000..7a84d73324e3
--- /dev/null
+++ b/tools/perf/tests/shell/trace+probe_libc_inet_pton.sh
@@ -0,0 +1,46 @@
1# probe libc's inet_pton & backtrace it with ping
2
3# Installs a probe on libc's inet_pton function, that will use uprobes,
4# then use 'perf trace' on a ping to localhost asking for just one packet
5# with the a backtrace 3 levels deep, check that it is what we expect.
6# This needs no debuginfo package, all is done using the libc ELF symtab
7# and the CFI info in the binaries.
8
9# Arnaldo Carvalho de Melo <acme@kernel.org>, 2017
10
11. $(dirname $0)/lib/probe.sh
12
13ld=$(realpath /lib64/ld*.so.* | uniq)
14libc=$(echo $ld | sed 's/ld/libc/g')
15
16trace_libc_inet_pton_backtrace() {
17 idx=0
18 expected[0]="PING.*bytes"
19 expected[1]="64 bytes from ::1.*"
20 expected[2]=".*ping statistics.*"
21 expected[3]=".*packets transmitted.*"
22 expected[4]="rtt min.*"
23 expected[5]="[0-9]+\.[0-9]+[[:space:]]+probe_libc:inet_pton:\([[:xdigit:]]+\)"
24 expected[6]=".*inet_pton[[:space:]]\($libc\)$"
25 expected[7]="getaddrinfo[[:space:]]\($libc\)$"
26 expected[8]=".*\(.*/bin/ping.*\)$"
27
28 perf trace --no-syscalls -e probe_libc:inet_pton/max-stack=3/ ping -6 -c 1 ::1 2>&1 | grep -v ^$ | while read line ; do
29 echo $line
30 echo "$line" | egrep -q "${expected[$idx]}"
31 if [ $? -ne 0 ] ; then
32 printf "FAIL: expected backtrace entry %d \"%s\" got \"%s\"\n" $idx "${expected[$idx]}" "$line"
33 exit 1
34 fi
35 let idx+=1
36 [ $idx -eq 9 ] && break
37 done
38}
39
40skip_if_no_perf_probe && \
41perf probe -q $libc inet_pton && \
42trace_libc_inet_pton_backtrace
43err=$?
44rm -f ${file}
45perf probe -q -d probe_libc:inet_pton
46exit $err
diff --git a/tools/perf/tests/shell/trace+probe_vfs_getname.sh b/tools/perf/tests/shell/trace+probe_vfs_getname.sh
new file mode 100755
index 000000000000..2e68c5f120da
--- /dev/null
+++ b/tools/perf/tests/shell/trace+probe_vfs_getname.sh
@@ -0,0 +1,35 @@
1# Check open filename arg using perf trace + vfs_getname
2
3# Uses the 'perf test shell' library to add probe:vfs_getname to the system
4# then use it with 'perf trace' using 'touch' to write to a temp file, then
5# checks that that was captured by the vfs_getname was used by 'perf trace',
6# that already handles "probe:vfs_getname" if present, and used in the
7# "open" syscall "filename" argument beautifier.
8
9# Arnaldo Carvalho de Melo <acme@kernel.org>, 2017
10
11. $(dirname $0)/lib/probe.sh
12
13skip_if_no_perf_probe || exit 2
14
15. $(dirname $0)/lib/probe_vfs_getname.sh
16
17file=$(mktemp /tmp/temporary_file.XXXXX)
18
19trace_open_vfs_getname() {
20 perf trace -e open touch $file 2>&1 | \
21 egrep " +[0-9]+\.[0-9]+ +\( +[0-9]+\.[0-9]+ ms\): +touch\/[0-9]+ open\(filename: +${file}, +flags: CREAT\|NOCTTY\|NONBLOCK\|WRONLY, +mode: +IRUGO\|IWUGO\) += +[0-9]+$"
22}
23
24
25add_probe_vfs_getname || skip_if_no_debuginfo
26err=$?
27if [ $err -ne 0 ] ; then
28 exit $err
29fi
30
31trace_open_vfs_getname
32err=$?
33rm -f ${file}
34cleanup_probe_vfs_getname
35exit $err
diff --git a/tools/perf/tests/stat.c b/tools/perf/tests/stat.c
index 6a20ff2326bb..94250024684a 100644
--- a/tools/perf/tests/stat.c
+++ b/tools/perf/tests/stat.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include "event.h" 3#include "event.h"
3#include "tests.h" 4#include "tests.h"
@@ -45,7 +46,7 @@ static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
45 return 0; 46 return 0;
46} 47}
47 48
48int test__synthesize_stat_config(int subtest __maybe_unused) 49int test__synthesize_stat_config(struct test *test __maybe_unused, int subtest __maybe_unused)
49{ 50{
50 struct perf_stat_config stat_config = { 51 struct perf_stat_config stat_config = {
51 .aggr_mode = AGGR_CORE, 52 .aggr_mode = AGGR_CORE,
@@ -75,7 +76,7 @@ static int process_stat_event(struct perf_tool *tool __maybe_unused,
75 return 0; 76 return 0;
76} 77}
77 78
78int test__synthesize_stat(int subtest __maybe_unused) 79int test__synthesize_stat(struct test *test __maybe_unused, int subtest __maybe_unused)
79{ 80{
80 struct perf_counts_values count; 81 struct perf_counts_values count;
81 82
@@ -101,7 +102,7 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
101 return 0; 102 return 0;
102} 103}
103 104
104int test__synthesize_stat_round(int subtest __maybe_unused) 105int test__synthesize_stat_round(struct test *test __maybe_unused, int subtest __maybe_unused)
105{ 106{
106 TEST_ASSERT_VAL("failed to synthesize stat_config", 107 TEST_ASSERT_VAL("failed to synthesize stat_config",
107 !perf_event__synthesize_stat_round(NULL, 0xdeadbeef, PERF_STAT_ROUND_TYPE__INTERVAL, 108 !perf_event__synthesize_stat_round(NULL, 0xdeadbeef, PERF_STAT_ROUND_TYPE__INTERVAL,
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 828494db4a19..725a196991a8 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <inttypes.h> 3#include <inttypes.h>
3#include <unistd.h> 4#include <unistd.h>
@@ -124,7 +125,7 @@ out_delete_evlist:
124 return err; 125 return err;
125} 126}
126 127
127int test__sw_clock_freq(int subtest __maybe_unused) 128int test__sw_clock_freq(struct test *test __maybe_unused, int subtest __maybe_unused)
128{ 129{
129 int ret; 130 int ret;
130 131
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index 65474fd80da7..7d3f4bf9534f 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/time.h> 2#include <sys/time.h>
2#include <sys/prctl.h> 3#include <sys/prctl.h>
3#include <errno.h> 4#include <errno.h>
@@ -306,7 +307,7 @@ out_free_nodes:
306 * evsel->system_wide and evsel->tracking flags (respectively) with other events 307 * evsel->system_wide and evsel->tracking flags (respectively) with other events
307 * sometimes enabled or disabled. 308 * sometimes enabled or disabled.
308 */ 309 */
309int test__switch_tracking(int subtest __maybe_unused) 310int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_unused)
310{ 311{
311 const char *sched_switch = "sched:sched_switch"; 312 const char *sched_switch = "sched:sched_switch";
312 struct switch_tracking switch_tracking = { .tids = NULL, }; 313 struct switch_tracking switch_tracking = { .tids = NULL, };
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index cf00ebad2ef5..bc4a7344e274 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "evlist.h" 2#include "evlist.h"
2#include "evsel.h" 3#include "evsel.h"
3#include "thread_map.h" 4#include "thread_map.h"
@@ -32,7 +33,7 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
32 * if the number of exit event reported by the kernel is 1 or not 33 * if the number of exit event reported by the kernel is 1 or not
33 * in order to check the kernel returns correct number of event. 34 * in order to check the kernel returns correct number of event.
34 */ 35 */
35int test__task_exit(int subtest __maybe_unused) 36int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused)
36{ 37{
37 int err = -1; 38 int err = -1;
38 union perf_event *event; 39 union perf_event *event;
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 577363809c9b..2862b80bc288 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef TESTS_H 2#ifndef TESTS_H
2#define TESTS_H 3#define TESTS_H
3 4
@@ -28,77 +29,79 @@ enum {
28 29
29struct test { 30struct test {
30 const char *desc; 31 const char *desc;
31 int (*func)(int subtest); 32 int (*func)(struct test *test, int subtest);
32 struct { 33 struct {
33 bool skip_if_fail; 34 bool skip_if_fail;
34 int (*get_nr)(void); 35 int (*get_nr)(void);
35 const char *(*get_desc)(int subtest); 36 const char *(*get_desc)(int subtest);
36 } subtest; 37 } subtest;
37 bool (*is_supported)(void); 38 bool (*is_supported)(void);
39 void *priv;
38}; 40};
39 41
40/* Tests */ 42/* Tests */
41int test__vmlinux_matches_kallsyms(int subtest); 43int test__vmlinux_matches_kallsyms(struct test *test, int subtest);
42int test__openat_syscall_event(int subtest); 44int test__openat_syscall_event(struct test *test, int subtest);
43int test__openat_syscall_event_on_all_cpus(int subtest); 45int test__openat_syscall_event_on_all_cpus(struct test *test, int subtest);
44int test__basic_mmap(int subtest); 46int test__basic_mmap(struct test *test, int subtest);
45int test__PERF_RECORD(int subtest); 47int test__PERF_RECORD(struct test *test, int subtest);
46int test__perf_evsel__roundtrip_name_test(int subtest); 48int test__perf_evsel__roundtrip_name_test(struct test *test, int subtest);
47int test__perf_evsel__tp_sched_test(int subtest); 49int test__perf_evsel__tp_sched_test(struct test *test, int subtest);
48int test__syscall_openat_tp_fields(int subtest); 50int test__syscall_openat_tp_fields(struct test *test, int subtest);
49int test__pmu(int subtest); 51int test__pmu(struct test *test, int subtest);
50int test__attr(int subtest); 52int test__attr(struct test *test, int subtest);
51int test__dso_data(int subtest); 53int test__dso_data(struct test *test, int subtest);
52int test__dso_data_cache(int subtest); 54int test__dso_data_cache(struct test *test, int subtest);
53int test__dso_data_reopen(int subtest); 55int test__dso_data_reopen(struct test *test, int subtest);
54int test__parse_events(int subtest); 56int test__parse_events(struct test *test, int subtest);
55int test__hists_link(int subtest); 57int test__hists_link(struct test *test, int subtest);
56int test__python_use(int subtest); 58int test__python_use(struct test *test, int subtest);
57int test__bp_signal(int subtest); 59int test__bp_signal(struct test *test, int subtest);
58int test__bp_signal_overflow(int subtest); 60int test__bp_signal_overflow(struct test *test, int subtest);
59int test__task_exit(int subtest); 61int test__task_exit(struct test *test, int subtest);
60int test__sw_clock_freq(int subtest); 62int test__mem(struct test *test, int subtest);
61int test__code_reading(int subtest); 63int test__sw_clock_freq(struct test *test, int subtest);
62int test__sample_parsing(int subtest); 64int test__code_reading(struct test *test, int subtest);
63int test__keep_tracking(int subtest); 65int test__sample_parsing(struct test *test, int subtest);
64int test__parse_no_sample_id_all(int subtest); 66int test__keep_tracking(struct test *test, int subtest);
65int test__dwarf_unwind(int subtest); 67int test__parse_no_sample_id_all(struct test *test, int subtest);
66int test__expr(int subtest); 68int test__dwarf_unwind(struct test *test, int subtest);
67int test__hists_filter(int subtest); 69int test__expr(struct test *test, int subtest);
68int test__mmap_thread_lookup(int subtest); 70int test__hists_filter(struct test *test, int subtest);
69int test__thread_mg_share(int subtest); 71int test__mmap_thread_lookup(struct test *test, int subtest);
70int test__hists_output(int subtest); 72int test__thread_mg_share(struct test *test, int subtest);
71int test__hists_cumulate(int subtest); 73int test__hists_output(struct test *test, int subtest);
72int test__switch_tracking(int subtest); 74int test__hists_cumulate(struct test *test, int subtest);
73int test__fdarray__filter(int subtest); 75int test__switch_tracking(struct test *test, int subtest);
74int test__fdarray__add(int subtest); 76int test__fdarray__filter(struct test *test, int subtest);
75int test__kmod_path__parse(int subtest); 77int test__fdarray__add(struct test *test, int subtest);
76int test__thread_map(int subtest); 78int test__kmod_path__parse(struct test *test, int subtest);
77int test__llvm(int subtest); 79int test__thread_map(struct test *test, int subtest);
80int test__llvm(struct test *test, int subtest);
78const char *test__llvm_subtest_get_desc(int subtest); 81const char *test__llvm_subtest_get_desc(int subtest);
79int test__llvm_subtest_get_nr(void); 82int test__llvm_subtest_get_nr(void);
80int test__bpf(int subtest); 83int test__bpf(struct test *test, int subtest);
81const char *test__bpf_subtest_get_desc(int subtest); 84const char *test__bpf_subtest_get_desc(int subtest);
82int test__bpf_subtest_get_nr(void); 85int test__bpf_subtest_get_nr(void);
83int test_session_topology(int subtest); 86int test__session_topology(struct test *test, int subtest);
84int test__thread_map_synthesize(int subtest); 87int test__thread_map_synthesize(struct test *test, int subtest);
85int test__thread_map_remove(int subtest); 88int test__thread_map_remove(struct test *test, int subtest);
86int test__cpu_map_synthesize(int subtest); 89int test__cpu_map_synthesize(struct test *test, int subtest);
87int test__synthesize_stat_config(int subtest); 90int test__synthesize_stat_config(struct test *test, int subtest);
88int test__synthesize_stat(int subtest); 91int test__synthesize_stat(struct test *test, int subtest);
89int test__synthesize_stat_round(int subtest); 92int test__synthesize_stat_round(struct test *test, int subtest);
90int test__event_update(int subtest); 93int test__event_update(struct test *test, int subtest);
91int test__event_times(int subtest); 94int test__event_times(struct test *test, int subtest);
92int test__backward_ring_buffer(int subtest); 95int test__backward_ring_buffer(struct test *test, int subtest);
93int test__cpu_map_print(int subtest); 96int test__cpu_map_print(struct test *test, int subtest);
94int test__sdt_event(int subtest); 97int test__sdt_event(struct test *test, int subtest);
95int test__is_printable_array(int subtest); 98int test__is_printable_array(struct test *test, int subtest);
96int test__bitmap_print(int subtest); 99int test__bitmap_print(struct test *test, int subtest);
97int test__perf_hooks(int subtest); 100int test__perf_hooks(struct test *test, int subtest);
98int test__clang(int subtest); 101int test__clang(struct test *test, int subtest);
99const char *test__clang_subtest_get_desc(int subtest); 102const char *test__clang_subtest_get_desc(int subtest);
100int test__clang_subtest_get_nr(void); 103int test__clang_subtest_get_nr(void);
101int test__unit_number__scnprint(int subtest); 104int test__unit_number__scnprint(struct test *test, int subtest);
102 105
103bool test__bp_signal_is_supported(void); 106bool test__bp_signal_is_supported(void);
104 107
diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index a63d6945807b..dbcb6a19b375 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdlib.h> 2#include <stdlib.h>
2#include <sys/types.h> 3#include <sys/types.h>
3#include <unistd.h> 4#include <unistd.h>
@@ -9,7 +10,7 @@
9#define NAME (const char *) "perf" 10#define NAME (const char *) "perf"
10#define NAMEUL (unsigned long) NAME 11#define NAMEUL (unsigned long) NAME
11 12
12int test__thread_map(int subtest __maybe_unused) 13int test__thread_map(struct test *test __maybe_unused, int subtest __maybe_unused)
13{ 14{
14 struct thread_map *map; 15 struct thread_map *map;
15 16
@@ -76,7 +77,7 @@ static int process_event(struct perf_tool *tool __maybe_unused,
76 return 0; 77 return 0;
77} 78}
78 79
79int test__thread_map_synthesize(int subtest __maybe_unused) 80int test__thread_map_synthesize(struct test *test __maybe_unused, int subtest __maybe_unused)
80{ 81{
81 struct thread_map *threads; 82 struct thread_map *threads;
82 83
@@ -95,7 +96,7 @@ int test__thread_map_synthesize(int subtest __maybe_unused)
95 return 0; 96 return 0;
96} 97}
97 98
98int test__thread_map_remove(int subtest __maybe_unused) 99int test__thread_map_remove(struct test *test __maybe_unused, int subtest __maybe_unused)
99{ 100{
100 struct thread_map *threads; 101 struct thread_map *threads;
101 char *str; 102 char *str;
diff --git a/tools/perf/tests/thread-mg-share.c b/tools/perf/tests/thread-mg-share.c
index 76686dd6f5ec..b1d1bbafe7ae 100644
--- a/tools/perf/tests/thread-mg-share.c
+++ b/tools/perf/tests/thread-mg-share.c
@@ -1,10 +1,11 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "tests.h" 2#include "tests.h"
2#include "machine.h" 3#include "machine.h"
3#include "thread.h" 4#include "thread.h"
4#include "map.h" 5#include "map.h"
5#include "debug.h" 6#include "debug.h"
6 7
7int test__thread_mg_share(int subtest __maybe_unused) 8int test__thread_mg_share(struct test *test __maybe_unused, int subtest __maybe_unused)
8{ 9{
9 struct machines machines; 10 struct machines machines;
10 struct machine *machine; 11 struct machine *machine;
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
index 803f893550d6..17cb1bb3448c 100644
--- a/tools/perf/tests/topology.c
+++ b/tools/perf/tests/topology.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <string.h> 2#include <string.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <stdio.h> 4#include <stdio.h>
@@ -29,12 +30,14 @@ static int get_temp(char *path)
29static int session_write_header(char *path) 30static int session_write_header(char *path)
30{ 31{
31 struct perf_session *session; 32 struct perf_session *session;
32 struct perf_data_file file = { 33 struct perf_data data = {
33 .path = path, 34 .file = {
34 .mode = PERF_DATA_MODE_WRITE, 35 .path = path,
36 },
37 .mode = PERF_DATA_MODE_WRITE,
35 }; 38 };
36 39
37 session = perf_session__new(&file, false, NULL); 40 session = perf_session__new(&data, false, NULL);
38 TEST_ASSERT_VAL("can't get session", session); 41 TEST_ASSERT_VAL("can't get session", session);
39 42
40 session->evlist = perf_evlist__new_default(); 43 session->evlist = perf_evlist__new_default();
@@ -46,7 +49,7 @@ static int session_write_header(char *path)
46 session->header.data_size += DATA_SIZE; 49 session->header.data_size += DATA_SIZE;
47 50
48 TEST_ASSERT_VAL("failed to write header", 51 TEST_ASSERT_VAL("failed to write header",
49 !perf_session__write_header(session, session->evlist, file.fd, true)); 52 !perf_session__write_header(session, session->evlist, data.file.fd, true));
50 53
51 perf_session__delete(session); 54 perf_session__delete(session);
52 55
@@ -56,13 +59,15 @@ static int session_write_header(char *path)
56static int check_cpu_topology(char *path, struct cpu_map *map) 59static int check_cpu_topology(char *path, struct cpu_map *map)
57{ 60{
58 struct perf_session *session; 61 struct perf_session *session;
59 struct perf_data_file file = { 62 struct perf_data data = {
60 .path = path, 63 .file = {
61 .mode = PERF_DATA_MODE_READ, 64 .path = path,
65 },
66 .mode = PERF_DATA_MODE_READ,
62 }; 67 };
63 int i; 68 int i;
64 69
65 session = perf_session__new(&file, false, NULL); 70 session = perf_session__new(&data, false, NULL);
66 TEST_ASSERT_VAL("can't get session", session); 71 TEST_ASSERT_VAL("can't get session", session);
67 72
68 for (i = 0; i < session->header.env.nr_cpus_avail; i++) { 73 for (i = 0; i < session->header.env.nr_cpus_avail; i++) {
@@ -86,7 +91,7 @@ static int check_cpu_topology(char *path, struct cpu_map *map)
86 return 0; 91 return 0;
87} 92}
88 93
89int test_session_topology(int subtest __maybe_unused) 94int test__session_topology(struct test *test __maybe_unused, int subtest __maybe_unused)
90{ 95{
91 char path[PATH_MAX]; 96 char path[PATH_MAX];
92 struct cpu_map *map; 97 struct cpu_map *map;
diff --git a/tools/perf/tests/unit_number__scnprintf.c b/tools/perf/tests/unit_number__scnprintf.c
index 44589de084b8..2bb8cb0039c1 100644
--- a/tools/perf/tests/unit_number__scnprintf.c
+++ b/tools/perf/tests/unit_number__scnprintf.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <inttypes.h> 2#include <inttypes.h>
2#include <linux/compiler.h> 3#include <linux/compiler.h>
3#include <linux/types.h> 4#include <linux/types.h>
@@ -5,7 +6,7 @@
5#include "units.h" 6#include "units.h"
6#include "debug.h" 7#include "debug.h"
7 8
8int test__unit_number__scnprint(int subtest __maybe_unused) 9int test__unit_number__scnprint(struct test *t __maybe_unused, int subtest __maybe_unused)
9{ 10{
10 struct { 11 struct {
11 u64 n; 12 u64 n;
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index 8456175fc234..f6789fb029d6 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include <linux/rbtree.h> 3#include <linux/rbtree.h>
3#include <inttypes.h> 4#include <inttypes.h>
@@ -11,7 +12,7 @@
11 12
12#define UM(x) kallsyms_map->unmap_ip(kallsyms_map, (x)) 13#define UM(x) kallsyms_map->unmap_ip(kallsyms_map, (x))
13 14
14int test__vmlinux_matches_kallsyms(int subtest __maybe_unused) 15int test__vmlinux_matches_kallsyms(struct test *test __maybe_unused, int subtest __maybe_unused)
15{ 16{
16 int err = -1; 17 int err = -1;
17 struct rb_node *nd; 18 struct rb_node *nd;
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build
index be95ac6ce845..066bbf0f4a74 100644
--- a/tools/perf/trace/beauty/Build
+++ b/tools/perf/trace/beauty/Build
@@ -1 +1,9 @@
1libperf-y += clone.o
2libperf-y += fcntl.o
3ifeq ($(SRCARCH),$(filter $(SRCARCH),x86))
4libperf-y += ioctl.o
5endif
6libperf-y += kcmp.o
7libperf-y += pkey_alloc.o
8libperf-y += prctl.o
1libperf-y += statx.o 9libperf-y += statx.o
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index cf50be3f17a4..a6dfd04beaee 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -1,13 +1,48 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_TRACE_BEAUTY_H 2#ifndef _PERF_TRACE_BEAUTY_H
2#define _PERF_TRACE_BEAUTY_H 3#define _PERF_TRACE_BEAUTY_H
3 4
5#include <linux/kernel.h>
4#include <linux/types.h> 6#include <linux/types.h>
7#include <sys/types.h>
8
9struct strarray {
10 int offset;
11 int nr_entries;
12 const char **entries;
13};
14
15#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
16 .nr_entries = ARRAY_SIZE(array), \
17 .entries = array, \
18}
19
20#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
21 .offset = off, \
22 .nr_entries = ARRAY_SIZE(array), \
23 .entries = array, \
24}
25
26size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val);
5 27
6struct trace; 28struct trace;
7struct thread; 29struct thread;
8 30
31size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size);
32
33/**
34 * @val: value of syscall argument being formatted
35 * @args: All the args, use syscall_args__val(arg, nth) to access one
36 * @thread: tid state (maps, pid, tid, etc)
37 * @trace: 'perf trace' internals: all threads, etc
38 * @parm: private area, may be an strarray, for instance
39 * @idx: syscall arg idx (is this the first?)
40 * @mask: a syscall arg may mask another arg, see syscall_arg__scnprintf_futex_op
41 */
42
9struct syscall_arg { 43struct syscall_arg {
10 unsigned long val; 44 unsigned long val;
45 unsigned char *args;
11 struct thread *thread; 46 struct thread *thread;
12 struct trace *trace; 47 struct trace *trace;
13 void *parm; 48 void *parm;
@@ -15,10 +50,68 @@ struct syscall_arg {
15 u8 mask; 50 u8 mask;
16}; 51};
17 52
53unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx);
54
55size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
56#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays
57
58size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg);
59#define SCA_FD syscall_arg__scnprintf_fd
60
61size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg);
62#define SCA_HEX syscall_arg__scnprintf_hex
63
64size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg);
65#define SCA_INT syscall_arg__scnprintf_int
66
67size_t syscall_arg__scnprintf_long(char *bf, size_t size, struct syscall_arg *arg);
68#define SCA_LONG syscall_arg__scnprintf_long
69
70size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg);
71#define SCA_PID syscall_arg__scnprintf_pid
72
73size_t syscall_arg__scnprintf_clone_flags(char *bf, size_t size, struct syscall_arg *arg);
74#define SCA_CLONE_FLAGS syscall_arg__scnprintf_clone_flags
75
76size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg);
77#define SCA_FCNTL_CMD syscall_arg__scnprintf_fcntl_cmd
78
79size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_arg *arg);
80#define SCA_FCNTL_ARG syscall_arg__scnprintf_fcntl_arg
81
82size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg);
83#define SCA_IOCTL_CMD syscall_arg__scnprintf_ioctl_cmd
84
85size_t syscall_arg__scnprintf_kcmp_type(char *bf, size_t size, struct syscall_arg *arg);
86#define SCA_KCMP_TYPE syscall_arg__scnprintf_kcmp_type
87
88size_t syscall_arg__scnprintf_kcmp_idx(char *bf, size_t size, struct syscall_arg *arg);
89#define SCA_KCMP_IDX syscall_arg__scnprintf_kcmp_idx
90
91size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg);
92#define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights
93
94size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg);
95#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
96
97size_t syscall_arg__scnprintf_prctl_option(char *bf, size_t size, struct syscall_arg *arg);
98#define SCA_PRCTL_OPTION syscall_arg__scnprintf_prctl_option
99
100size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_arg *arg);
101#define SCA_PRCTL_ARG2 syscall_arg__scnprintf_prctl_arg2
102
103size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg);
104#define SCA_PRCTL_ARG3 syscall_arg__scnprintf_prctl_arg3
105
18size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg); 106size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg);
19#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags 107#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags
20 108
21size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_arg *arg); 109size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_arg *arg);
22#define SCA_STATX_MASK syscall_arg__scnprintf_statx_mask 110#define SCA_STATX_MASK syscall_arg__scnprintf_statx_mask
23 111
112size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size);
113
114void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
115 size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg));
116
24#endif /* _PERF_TRACE_BEAUTY_H */ 117#endif /* _PERF_TRACE_BEAUTY_H */
diff --git a/tools/perf/trace/beauty/clone.c b/tools/perf/trace/beauty/clone.c
new file mode 100644
index 000000000000..d64d049ab991
--- /dev/null
+++ b/tools/perf/trace/beauty/clone.c
@@ -0,0 +1,75 @@
1/*
2 * trace/beauty/cone.c
3 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */
8
9#include "trace/beauty/beauty.h"
10#include <linux/kernel.h>
11#include <sys/types.h>
12#include <uapi/linux/sched.h>
13
14static size_t clone__scnprintf_flags(unsigned long flags, char *bf, size_t size)
15{
16 int printed = 0;
17
18#define P_FLAG(n) \
19 if (flags & CLONE_##n) { \
20 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
21 flags &= ~CLONE_##n; \
22 }
23
24 P_FLAG(VM);
25 P_FLAG(FS);
26 P_FLAG(FILES);
27 P_FLAG(SIGHAND);
28 P_FLAG(PTRACE);
29 P_FLAG(VFORK);
30 P_FLAG(PARENT);
31 P_FLAG(THREAD);
32 P_FLAG(NEWNS);
33 P_FLAG(SYSVSEM);
34 P_FLAG(SETTLS);
35 P_FLAG(PARENT_SETTID);
36 P_FLAG(CHILD_CLEARTID);
37 P_FLAG(DETACHED);
38 P_FLAG(UNTRACED);
39 P_FLAG(CHILD_SETTID);
40 P_FLAG(NEWCGROUP);
41 P_FLAG(NEWUTS);
42 P_FLAG(NEWIPC);
43 P_FLAG(NEWUSER);
44 P_FLAG(NEWPID);
45 P_FLAG(NEWNET);
46 P_FLAG(IO);
47#undef P_FLAG
48
49 if (flags)
50 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
51
52 return printed;
53}
54
55size_t syscall_arg__scnprintf_clone_flags(char *bf, size_t size, struct syscall_arg *arg)
56{
57 unsigned long flags = arg->val;
58 enum syscall_clone_args {
59 SCC_FLAGS = (1 << 0),
60 SCC_CHILD_STACK = (1 << 1),
61 SCC_PARENT_TIDPTR = (1 << 2),
62 SCC_CHILD_TIDPTR = (1 << 3),
63 SCC_TLS = (1 << 4),
64 };
65 if (!(flags & CLONE_PARENT_SETTID))
66 arg->mask |= SCC_PARENT_TIDPTR;
67
68 if (!(flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)))
69 arg->mask |= SCC_CHILD_TIDPTR;
70
71 if (!(flags & CLONE_SETTLS))
72 arg->mask |= SCC_TLS;
73
74 return clone__scnprintf_flags(flags, bf, size);
75}
diff --git a/tools/perf/trace/beauty/drm_ioctl.sh b/tools/perf/trace/beauty/drm_ioctl.sh
new file mode 100755
index 000000000000..2149d3a98e42
--- /dev/null
+++ b/tools/perf/trace/beauty/drm_ioctl.sh
@@ -0,0 +1,13 @@
1#!/bin/sh
2
3drm_header_dir=$1
4printf "#ifndef DRM_COMMAND_BASE\n"
5grep "#define DRM_COMMAND_BASE" $drm_header_dir/drm.h
6printf "#endif\n"
7
8printf "static const char *drm_ioctl_cmds[] = {\n"
9grep "^#define DRM_IOCTL.*DRM_IO" $drm_header_dir/drm.h | \
10 sed -r 's/^#define +DRM_IOCTL_([A-Z0-9_]+)[ ]+DRM_IO[A-Z]* *\( *(0x[[:xdigit:]]+),*.*/ [\2] = "\1",/g'
11grep "^#define DRM_I915_[A-Z_0-9]\+[ ]\+0x" $drm_header_dir/i915_drm.h | \
12 sed -r 's/^#define +DRM_I915_([A-Z0-9_]+)[ ]+(0x[[:xdigit:]]+)/\t[DRM_COMMAND_BASE + \2] = "I915_\1",/g'
13printf "};\n"
diff --git a/tools/perf/trace/beauty/eventfd.c b/tools/perf/trace/beauty/eventfd.c
index b08f21eb6f4d..5d6a477a6400 100644
--- a/tools/perf/trace/beauty/eventfd.c
+++ b/tools/perf/trace/beauty/eventfd.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#ifndef EFD_SEMAPHORE 2#ifndef EFD_SEMAPHORE
2#define EFD_SEMAPHORE 1 3#define EFD_SEMAPHORE 1
3#endif 4#endif
diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
new file mode 100644
index 000000000000..9e8900c13cb1
--- /dev/null
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -0,0 +1,100 @@
1/*
2 * trace/beauty/fcntl.c
3 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */
8
9#include "trace/beauty/beauty.h"
10#include <linux/kernel.h>
11#include <uapi/linux/fcntl.h>
12
13static size_t fcntl__scnprintf_getfd(unsigned long val, char *bf, size_t size)
14{
15 return scnprintf(bf, size, "%s", val ? "CLOEXEC" : "0");
16}
17
18static size_t syscall_arg__scnprintf_fcntl_getfd(char *bf, size_t size, struct syscall_arg *arg)
19{
20 return fcntl__scnprintf_getfd(arg->val, bf, size);
21}
22
23static size_t fcntl__scnprintf_getlease(unsigned long val, char *bf, size_t size)
24{
25 static const char *fcntl_setlease[] = { "RDLCK", "WRLCK", "UNLCK", };
26 static DEFINE_STRARRAY(fcntl_setlease);
27
28 return strarray__scnprintf(&strarray__fcntl_setlease, bf, size, "%x", val);
29}
30
31static size_t syscall_arg__scnprintf_fcntl_getlease(char *bf, size_t size, struct syscall_arg *arg)
32{
33 return fcntl__scnprintf_getlease(arg->val, bf, size);
34}
35
36size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg)
37{
38 if (arg->val == F_GETFL) {
39 syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_open_flags);
40 goto mask_arg;
41 }
42 if (arg->val == F_GETFD) {
43 syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fcntl_getfd);
44 goto mask_arg;
45 }
46 if (arg->val == F_DUPFD_CLOEXEC || arg->val == F_DUPFD) {
47 syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fd);
48 goto out;
49 }
50 if (arg->val == F_GETOWN) {
51 syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_pid);
52 goto mask_arg;
53 }
54 if (arg->val == F_GETLEASE) {
55 syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fcntl_getlease);
56 goto mask_arg;
57 }
58 /*
59 * Some commands ignore the third fcntl argument, "arg", so mask it
60 */
61 if (arg->val == F_GET_SEALS ||
62 arg->val == F_GETSIG) {
63mask_arg:
64 arg->mask |= (1 << 2);
65 }
66out:
67 return syscall_arg__scnprintf_strarrays(bf, size, arg);
68}
69
70size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_arg *arg)
71{
72 int cmd = syscall_arg__val(arg, 1);
73
74 if (cmd == F_DUPFD)
75 return syscall_arg__scnprintf_fd(bf, size, arg);
76
77 if (cmd == F_SETFD)
78 return fcntl__scnprintf_getfd(arg->val, bf, size);
79
80 if (cmd == F_SETFL)
81 return open__scnprintf_flags(arg->val, bf, size);
82
83 if (cmd == F_SETOWN)
84 return syscall_arg__scnprintf_pid(bf, size, arg);
85
86 if (cmd == F_SETLEASE)
87 return fcntl__scnprintf_getlease(arg->val, bf, size);
88 /*
89 * We still don't grab the contents of pointers on entry or exit,
90 * so just print them as hex numbers
91 */
92 if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK ||
93 cmd == F_OFD_SETLK || cmd == F_OFD_SETLKW || cmd == F_OFD_GETLK ||
94 cmd == F_GETOWN_EX || cmd == F_SETOWN_EX ||
95 cmd == F_GET_RW_HINT || cmd == F_SET_RW_HINT ||
96 cmd == F_GET_FILE_RW_HINT || cmd == F_SET_FILE_RW_HINT)
97 return syscall_arg__scnprintf_hex(bf, size, arg);
98
99 return syscall_arg__scnprintf_long(bf, size, arg);
100}
diff --git a/tools/perf/trace/beauty/flock.c b/tools/perf/trace/beauty/flock.c
index 74613703a14e..f9707f57566c 100644
--- a/tools/perf/trace/beauty/flock.c
+++ b/tools/perf/trace/beauty/flock.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <fcntl.h> 2#include <fcntl.h>
2 3
3#ifndef LOCK_MAND 4#ifndef LOCK_MAND
diff --git a/tools/perf/trace/beauty/futex_op.c b/tools/perf/trace/beauty/futex_op.c
index bfd3359b09b6..61850fbc85ff 100644
--- a/tools/perf/trace/beauty/futex_op.c
+++ b/tools/perf/trace/beauty/futex_op.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/futex.h> 2#include <linux/futex.h>
2 3
3#ifndef FUTEX_WAIT_BITSET 4#ifndef FUTEX_WAIT_BITSET
diff --git a/tools/perf/trace/beauty/ioctl.c b/tools/perf/trace/beauty/ioctl.c
new file mode 100644
index 000000000000..1be3b4cf0827
--- /dev/null
+++ b/tools/perf/trace/beauty/ioctl.c
@@ -0,0 +1,162 @@
1/*
2 * trace/beauty/ioctl.c
3 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */
8
9#include "trace/beauty/beauty.h"
10#include <linux/kernel.h>
11
12/*
13 * FIXME: to support all arches we have to improve this, for
14 * now, to build on older systems without things like TIOCGEXCL,
15 * get it directly from our copy.
16 *
17 * Right now only x86 is being supported for beautifying ioctl args
18 * in 'perf trace', see tools/perf/trace/beauty/Build and builtin-trace.c
19 */
20#include <uapi/asm-generic/ioctls.h>
21
22static size_t ioctl__scnprintf_tty_cmd(int nr, int dir, char *bf, size_t size)
23{
24 static const char *ioctl_tty_cmd[] = {
25 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
26 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL", "TIOCSCTTY",
27 "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI", "TIOCGWINSZ", "TIOCSWINSZ",
28 "TIOCMGET", "TIOCMBIS", "TIOCMBIC", "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR",
29 "FIONREAD", "TIOCLINUX", "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT",
30 "FIONBIO", "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP",
31 [_IOC_NR(TIOCSBRK)] = "TIOCSBRK", "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2",
32 "TCSETSW2", "TCSETSF2", "TIOCGRS48", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
33 "TIOCGDEV", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG", "TIOCVHANGUP", "TIOCGPKT",
34 "TIOCGPTLCK", [_IOC_NR(TIOCGEXCL)] = "TIOCGEXCL", "TIOCGPTPEER",
35 [_IOC_NR(FIONCLEX)] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
36 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
37 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
38 "TIOCMIWAIT", "TIOCGICOUNT", };
39 static DEFINE_STRARRAY(ioctl_tty_cmd);
40
41 if (nr < strarray__ioctl_tty_cmd.nr_entries && strarray__ioctl_tty_cmd.entries[nr] != NULL)
42 return scnprintf(bf, size, "%s", strarray__ioctl_tty_cmd.entries[nr]);
43
44 return scnprintf(bf, size, "(%#x, %#x, %#x)", 'T', nr, dir);
45}
46
47static size_t ioctl__scnprintf_drm_cmd(int nr, int dir, char *bf, size_t size)
48{
49#include "trace/beauty/generated/ioctl/drm_ioctl_array.c"
50 static DEFINE_STRARRAY(drm_ioctl_cmds);
51
52 if (nr < strarray__drm_ioctl_cmds.nr_entries && strarray__drm_ioctl_cmds.entries[nr] != NULL)
53 return scnprintf(bf, size, "DRM_%s", strarray__drm_ioctl_cmds.entries[nr]);
54
55 return scnprintf(bf, size, "(%#x, %#x, %#x)", 'd', nr, dir);
56}
57
58static size_t ioctl__scnprintf_sndrv_pcm_cmd(int nr, int dir, char *bf, size_t size)
59{
60#include "trace/beauty/generated/ioctl/sndrv_pcm_ioctl_array.c"
61 static DEFINE_STRARRAY(sndrv_pcm_ioctl_cmds);
62
63 if (nr < strarray__sndrv_pcm_ioctl_cmds.nr_entries && strarray__sndrv_pcm_ioctl_cmds.entries[nr] != NULL)
64 return scnprintf(bf, size, "SNDRV_PCM_%s", strarray__sndrv_pcm_ioctl_cmds.entries[nr]);
65
66 return scnprintf(bf, size, "(%#x, %#x, %#x)", 'A', nr, dir);
67}
68
69static size_t ioctl__scnprintf_sndrv_ctl_cmd(int nr, int dir, char *bf, size_t size)
70{
71#include "trace/beauty/generated/ioctl/sndrv_ctl_ioctl_array.c"
72 static DEFINE_STRARRAY(sndrv_ctl_ioctl_cmds);
73
74 if (nr < strarray__sndrv_ctl_ioctl_cmds.nr_entries && strarray__sndrv_ctl_ioctl_cmds.entries[nr] != NULL)
75 return scnprintf(bf, size, "SNDRV_CTL_%s", strarray__sndrv_ctl_ioctl_cmds.entries[nr]);
76
77 return scnprintf(bf, size, "(%#x, %#x, %#x)", 'U', nr, dir);
78}
79
80static size_t ioctl__scnprintf_kvm_cmd(int nr, int dir, char *bf, size_t size)
81{
82#include "trace/beauty/generated/ioctl/kvm_ioctl_array.c"
83 static DEFINE_STRARRAY(kvm_ioctl_cmds);
84
85 if (nr < strarray__kvm_ioctl_cmds.nr_entries && strarray__kvm_ioctl_cmds.entries[nr] != NULL)
86 return scnprintf(bf, size, "KVM_%s", strarray__kvm_ioctl_cmds.entries[nr]);
87
88 return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir);
89}
90
91static size_t ioctl__scnprintf_vhost_virtio_cmd(int nr, int dir, char *bf, size_t size)
92{
93#include "trace/beauty/generated/ioctl/vhost_virtio_ioctl_array.c"
94 static DEFINE_STRARRAY(vhost_virtio_ioctl_cmds);
95 static DEFINE_STRARRAY(vhost_virtio_ioctl_read_cmds);
96 struct strarray *s = (dir & _IOC_READ) ? &strarray__vhost_virtio_ioctl_read_cmds : &strarray__vhost_virtio_ioctl_cmds;
97
98 if (nr < s->nr_entries && s->entries[nr] != NULL)
99 return scnprintf(bf, size, "VHOST_%s", s->entries[nr]);
100
101 return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAF, nr, dir);
102}
103
104static size_t ioctl__scnprintf_perf_cmd(int nr, int dir, char *bf, size_t size)
105{
106#include "trace/beauty/generated/ioctl/perf_ioctl_array.c"
107 static DEFINE_STRARRAY(perf_ioctl_cmds);
108
109 if (nr < strarray__perf_ioctl_cmds.nr_entries && strarray__perf_ioctl_cmds.entries[nr] != NULL)
110 return scnprintf(bf, size, "PERF_%s", strarray__perf_ioctl_cmds.entries[nr]);
111
112 return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir);
113}
114
115static size_t ioctl__scnprintf_cmd(unsigned long cmd, char *bf, size_t size)
116{
117 int dir = _IOC_DIR(cmd),
118 type = _IOC_TYPE(cmd),
119 nr = _IOC_NR(cmd),
120 sz = _IOC_SIZE(cmd);
121 int printed = 0;
122 static const struct ioctl_type {
123 int type;
124 size_t (*scnprintf)(int nr, int dir, char *bf, size_t size);
125 } ioctl_types[] = { /* Must be ordered by type */
126 { .type = '$', .scnprintf = ioctl__scnprintf_perf_cmd, },
127 ['A' - '$'] = { .type = 'A', .scnprintf = ioctl__scnprintf_sndrv_pcm_cmd, },
128 ['T' - '$'] = { .type = 'T', .scnprintf = ioctl__scnprintf_tty_cmd, },
129 ['U' - '$'] = { .type = 'U', .scnprintf = ioctl__scnprintf_sndrv_ctl_cmd, },
130 ['d' - '$'] = { .type = 'd', .scnprintf = ioctl__scnprintf_drm_cmd, },
131 [0xAE - '$'] = { .type = 0xAE, .scnprintf = ioctl__scnprintf_kvm_cmd, },
132 [0xAF - '$'] = { .type = 0xAF, .scnprintf = ioctl__scnprintf_vhost_virtio_cmd, },
133 };
134 const int nr_types = ARRAY_SIZE(ioctl_types);
135
136 if (type >= ioctl_types[0].type && type <= ioctl_types[nr_types - 1].type) {
137 const int index = type - ioctl_types[0].type;
138
139 if (ioctl_types[index].scnprintf != NULL)
140 return ioctl_types[index].scnprintf(nr, dir, bf, size);
141 }
142
143 printed += scnprintf(bf + printed, size - printed, "%c", '(');
144
145 if (dir == _IOC_NONE) {
146 printed += scnprintf(bf + printed, size - printed, "%s", "NONE");
147 } else {
148 if (dir & _IOC_READ)
149 printed += scnprintf(bf + printed, size - printed, "%s", "READ");
150 if (dir & _IOC_WRITE)
151 printed += scnprintf(bf + printed, size - printed, "%s%s", dir & _IOC_READ ? "|" : "", "WRITE");
152 }
153
154 return printed + scnprintf(bf + printed, size - printed, ", %#x, %#x, %#x)", type, nr, sz);
155}
156
157size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg)
158{
159 unsigned long cmd = arg->val;
160
161 return ioctl__scnprintf_cmd(cmd, bf, size);
162}
diff --git a/tools/perf/trace/beauty/kcmp.c b/tools/perf/trace/beauty/kcmp.c
new file mode 100644
index 000000000000..f62040eb9d5c
--- /dev/null
+++ b/tools/perf/trace/beauty/kcmp.c
@@ -0,0 +1,44 @@
1/*
2 * trace/beauty/kcmp.c
3 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */
8
9#include "trace/beauty/beauty.h"
10#include <linux/kernel.h>
11#include <sys/types.h>
12#include <machine.h>
13#include <uapi/linux/kcmp.h>
14
15#include "trace/beauty/generated/kcmp_type_array.c"
16
17size_t syscall_arg__scnprintf_kcmp_idx(char *bf, size_t size, struct syscall_arg *arg)
18{
19 unsigned long fd = arg->val;
20 int type = syscall_arg__val(arg, 2);
21 pid_t pid;
22
23 if (type != KCMP_FILE)
24 return syscall_arg__scnprintf_long(bf, size, arg);
25
26 pid = syscall_arg__val(arg, arg->idx == 3 ? 0 : 1); /* idx1 -> pid1, idx2 -> pid2 */
27 return pid__scnprintf_fd(arg->trace, pid, fd, bf, size);
28}
29
30static size_t kcmp__scnprintf_type(int type, char *bf, size_t size)
31{
32 static DEFINE_STRARRAY(kcmp_types);
33 return strarray__scnprintf(&strarray__kcmp_types, bf, size, "%d", type);
34}
35
36size_t syscall_arg__scnprintf_kcmp_type(char *bf, size_t size, struct syscall_arg *arg)
37{
38 unsigned long type = arg->val;
39
40 if (type != KCMP_FILE)
41 arg->mask |= (1 << 3) | (1 << 4); /* Ignore idx1 and idx2 */
42
43 return kcmp__scnprintf_type(type, bf, size);
44}
diff --git a/tools/perf/trace/beauty/kcmp_type.sh b/tools/perf/trace/beauty/kcmp_type.sh
new file mode 100755
index 000000000000..40d063b8c082
--- /dev/null
+++ b/tools/perf/trace/beauty/kcmp_type.sh
@@ -0,0 +1,10 @@
1#!/bin/sh
2
3header_dir=$1
4
5printf "static const char *kcmp_types[] = {\n"
6regex='^[[:space:]]+(KCMP_(\w+)),'
7egrep $regex ${header_dir}/kcmp.h | grep -v KCMP_TYPES, | \
8 sed -r "s/$regex/\1 \2/g" | \
9 xargs printf "\t[%s]\t= \"%s\",\n"
10printf "};\n"
diff --git a/tools/perf/trace/beauty/kvm_ioctl.sh b/tools/perf/trace/beauty/kvm_ioctl.sh
new file mode 100755
index 000000000000..bd28817afced
--- /dev/null
+++ b/tools/perf/trace/beauty/kvm_ioctl.sh
@@ -0,0 +1,11 @@
1#!/bin/sh
2
3kvm_header_dir=$1
4
5printf "static const char *kvm_ioctl_cmds[] = {\n"
6regex='^#[[:space:]]*define[[:space:]]+KVM_(\w+)[[:space:]]+_IO[RW]*\([[:space:]]*KVMIO[[:space:]]*,[[:space:]]*(0x[[:xdigit:]]+).*'
7egrep $regex ${kvm_header_dir}/kvm.h | \
8 sed -r "s/$regex/\2 \1/g" | \
9 egrep -v " ((ARM|PPC|S390)_|[GS]ET_(DEBUGREGS|PIT2|XSAVE|TSC_KHZ)|CREATE_SPAPR_TCE_64)" | \
10 sort | xargs printf "\t[%s] = \"%s\",\n"
11printf "};\n"
diff --git a/tools/perf/trace/beauty/madvise_behavior.sh b/tools/perf/trace/beauty/madvise_behavior.sh
new file mode 100755
index 000000000000..60ef8640ee70
--- /dev/null
+++ b/tools/perf/trace/beauty/madvise_behavior.sh
@@ -0,0 +1,10 @@
1#!/bin/sh
2
3header_dir=$1
4
5printf "static const char *madvise_advices[] = {\n"
6regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MADV_([[:alnum:]_]+)[[:space:]]+([[:digit:]]+)[[:space:]]*.*'
7egrep $regex ${header_dir}/mman-common.h | \
8 sed -r "s/$regex/\2 \1/g" | \
9 sort -n | xargs printf "\t[%s] = \"%s\",\n"
10printf "};\n"
diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c
index af1cfde6b97b..9e1668b2c5d7 100644
--- a/tools/perf/trace/beauty/mmap.c
+++ b/tools/perf/trace/beauty/mmap.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <uapi/linux/mman.h> 2#include <uapi/linux/mman.h>
2 3
3static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, 4static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
@@ -34,6 +35,9 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
34{ 35{
35 int printed = 0, flags = arg->val; 36 int printed = 0, flags = arg->val;
36 37
38 if (flags & MAP_ANONYMOUS)
39 arg->mask |= (1 << 4) | (1 << 5); /* Mask 4th ('fd') and 5th ('offset') args, ignored */
40
37#define P_MMAP_FLAG(n) \ 41#define P_MMAP_FLAG(n) \
38 if (flags & MAP_##n) { \ 42 if (flags & MAP_##n) { \
39 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ 43 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
@@ -91,35 +95,21 @@ static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
91 95
92#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags 96#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
93 97
98static size_t madvise__scnprintf_behavior(int behavior, char *bf, size_t size)
99{
100#include "trace/beauty/generated/madvise_behavior_array.c"
101 static DEFINE_STRARRAY(madvise_advices);
102
103 if (behavior < strarray__madvise_advices.nr_entries && strarray__madvise_advices.entries[behavior] != NULL)
104 return scnprintf(bf, size, "MADV_%s", strarray__madvise_advices.entries[behavior]);
105
106 return scnprintf(bf, size, "%#", behavior);
107}
108
94static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, 109static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
95 struct syscall_arg *arg) 110 struct syscall_arg *arg)
96{ 111{
97 int behavior = arg->val; 112 return madvise__scnprintf_behavior(arg->val, bf, size);
98
99 switch (behavior) {
100#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
101 P_MADV_BHV(NORMAL);
102 P_MADV_BHV(RANDOM);
103 P_MADV_BHV(SEQUENTIAL);
104 P_MADV_BHV(WILLNEED);
105 P_MADV_BHV(DONTNEED);
106 P_MADV_BHV(FREE);
107 P_MADV_BHV(REMOVE);
108 P_MADV_BHV(DONTFORK);
109 P_MADV_BHV(DOFORK);
110 P_MADV_BHV(HWPOISON);
111 P_MADV_BHV(SOFT_OFFLINE);
112 P_MADV_BHV(MERGEABLE);
113 P_MADV_BHV(UNMERGEABLE);
114 P_MADV_BHV(HUGEPAGE);
115 P_MADV_BHV(NOHUGEPAGE);
116 P_MADV_BHV(DONTDUMP);
117 P_MADV_BHV(DODUMP);
118#undef P_MADV_BHV
119 default: break;
120 }
121
122 return scnprintf(bf, size, "%#x", behavior);
123} 113}
124 114
125#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior 115#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
diff --git a/tools/perf/trace/beauty/mode_t.c b/tools/perf/trace/beauty/mode_t.c
index 930d8fef2400..d929ad7dd97b 100644
--- a/tools/perf/trace/beauty/mode_t.c
+++ b/tools/perf/trace/beauty/mode_t.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/types.h> 2#include <sys/types.h>
2#include <sys/stat.h> 3#include <sys/stat.h>
3#include <unistd.h> 4#include <unistd.h>
diff --git a/tools/perf/trace/beauty/msg_flags.c b/tools/perf/trace/beauty/msg_flags.c
index 1106c8960cc4..c064d6aae659 100644
--- a/tools/perf/trace/beauty/msg_flags.c
+++ b/tools/perf/trace/beauty/msg_flags.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/types.h> 2#include <sys/types.h>
2#include <sys/socket.h> 3#include <sys/socket.h>
3 4
diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
index f55a4597fc38..6aec6178a99d 100644
--- a/tools/perf/trace/beauty/open_flags.c
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/types.h> 2#include <sys/types.h>
2#include <sys/stat.h> 3#include <sys/stat.h>
3#include <fcntl.h> 4#include <fcntl.h>
@@ -14,13 +15,16 @@
14#define O_NOATIME 01000000 15#define O_NOATIME 01000000
15#endif 16#endif
16 17
17static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, 18#ifndef O_TMPFILE
18 struct syscall_arg *arg) 19#define O_TMPFILE 020000000
19{ 20#endif
20 int printed = 0, flags = arg->val;
21 21
22 if (!(flags & O_CREAT)) 22#undef O_LARGEFILE
23 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */ 23#define O_LARGEFILE 00100000
24
25size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size)
26{
27 int printed = 0;
24 28
25 if (flags == 0) 29 if (flags == 0)
26 return scnprintf(bf, size, "RDONLY"); 30 return scnprintf(bf, size, "RDONLY");
@@ -30,6 +34,7 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
30 flags &= ~O_##n; \ 34 flags &= ~O_##n; \
31 } 35 }
32 36
37 P_FLAG(RDWR);
33 P_FLAG(APPEND); 38 P_FLAG(APPEND);
34 P_FLAG(ASYNC); 39 P_FLAG(ASYNC);
35 P_FLAG(CLOEXEC); 40 P_FLAG(CLOEXEC);
@@ -38,6 +43,8 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
38 P_FLAG(DIRECTORY); 43 P_FLAG(DIRECTORY);
39 P_FLAG(EXCL); 44 P_FLAG(EXCL);
40 P_FLAG(LARGEFILE); 45 P_FLAG(LARGEFILE);
46 P_FLAG(NOFOLLOW);
47 P_FLAG(TMPFILE);
41 P_FLAG(NOATIME); 48 P_FLAG(NOATIME);
42 P_FLAG(NOCTTY); 49 P_FLAG(NOCTTY);
43#ifdef O_NONBLOCK 50#ifdef O_NONBLOCK
@@ -48,7 +55,6 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
48#ifdef O_PATH 55#ifdef O_PATH
49 P_FLAG(PATH); 56 P_FLAG(PATH);
50#endif 57#endif
51 P_FLAG(RDWR);
52#ifdef O_DSYNC 58#ifdef O_DSYNC
53 if ((flags & O_SYNC) == O_SYNC) 59 if ((flags & O_SYNC) == O_SYNC)
54 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC"); 60 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
@@ -68,4 +74,12 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
68 return printed; 74 return printed;
69} 75}
70 76
71#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags 77size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg)
78{
79 int flags = arg->val;
80
81 if (!(flags & O_CREAT))
82 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
83
84 return open__scnprintf_flags(flags, bf, size);
85}
diff --git a/tools/perf/trace/beauty/perf_event_open.c b/tools/perf/trace/beauty/perf_event_open.c
index 311f09dd718d..2bafd7c995ff 100644
--- a/tools/perf/trace/beauty/perf_event_open.c
+++ b/tools/perf/trace/beauty/perf_event_open.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#ifndef PERF_FLAG_FD_NO_GROUP 2#ifndef PERF_FLAG_FD_NO_GROUP
2# define PERF_FLAG_FD_NO_GROUP (1UL << 0) 3# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
3#endif 4#endif
diff --git a/tools/perf/trace/beauty/perf_ioctl.sh b/tools/perf/trace/beauty/perf_ioctl.sh
new file mode 100755
index 000000000000..faea4237c793
--- /dev/null
+++ b/tools/perf/trace/beauty/perf_ioctl.sh
@@ -0,0 +1,10 @@
1#!/bin/sh
2
3header_dir=$1
4
5printf "static const char *perf_ioctl_cmds[] = {\n"
6regex='^#[[:space:]]*define[[:space:]]+PERF_EVENT_IOC_(\w+)[[:space:]]+_IO[RW]*[[:space:]]*\([[:space:]]*.\$.[[:space:]]*,[[:space:]]*([[:digit:]]+).*'
7egrep $regex ${header_dir}/perf_event.h | \
8 sed -r "s/$regex/\2 \1/g" | \
9 sort | xargs printf "\t[%s] = \"%s\",\n"
10printf "};\n"
diff --git a/tools/perf/trace/beauty/pid.c b/tools/perf/trace/beauty/pid.c
index 07486ea65ae3..0313df342830 100644
--- a/tools/perf/trace/beauty/pid.c
+++ b/tools/perf/trace/beauty/pid.c
@@ -1,4 +1,5 @@
1static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg) 1// SPDX-License-Identifier: GPL-2.0
2size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
2{ 3{
3 int pid = arg->val; 4 int pid = arg->val;
4 struct trace *trace = arg->trace; 5 struct trace *trace = arg->trace;
@@ -17,5 +18,3 @@ static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_a
17 18
18 return printed; 19 return printed;
19} 20}
20
21#define SCA_PID syscall_arg__scnprintf_pid
diff --git a/tools/perf/trace/beauty/pkey_alloc.c b/tools/perf/trace/beauty/pkey_alloc.c
new file mode 100644
index 000000000000..2ba784a3734a
--- /dev/null
+++ b/tools/perf/trace/beauty/pkey_alloc.c
@@ -0,0 +1,50 @@
1/*
2 * trace/beauty/pkey_alloc.c
3 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */
8
9#include "trace/beauty/beauty.h"
10#include <linux/kernel.h>
11#include <linux/log2.h>
12
13static size_t pkey_alloc__scnprintf_access_rights(int access_rights, char *bf, size_t size)
14{
15 int i, printed = 0;
16
17#include "trace/beauty/generated/pkey_alloc_access_rights_array.c"
18 static DEFINE_STRARRAY(pkey_alloc_access_rights);
19
20 if (access_rights == 0) {
21 const char *s = strarray__pkey_alloc_access_rights.entries[0];
22 if (s)
23 return scnprintf(bf, size, "%s", s);
24 return scnprintf(bf, size, "%d", 0);
25 }
26
27 for (i = 1; i < strarray__pkey_alloc_access_rights.nr_entries; ++i) {
28 int bit = 1 << (i - 1);
29
30 if (!(access_rights & bit))
31 continue;
32
33 if (printed != 0)
34 printed += scnprintf(bf + printed, size - printed, "|");
35
36 if (strarray__pkey_alloc_access_rights.entries[i] != NULL)
37 printed += scnprintf(bf + printed, size - printed, "%s", strarray__pkey_alloc_access_rights.entries[i]);
38 else
39 printed += scnprintf(bf + printed, size - printed, "0x%#", bit);
40 }
41
42 return printed;
43}
44
45size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg)
46{
47 unsigned long cmd = arg->val;
48
49 return pkey_alloc__scnprintf_access_rights(cmd, bf, size);
50}
diff --git a/tools/perf/trace/beauty/pkey_alloc_access_rights.sh b/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
new file mode 100755
index 000000000000..62e51a02b839
--- /dev/null
+++ b/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
@@ -0,0 +1,10 @@
1#!/bin/sh
2
3header_dir=$1
4
5printf "static const char *pkey_alloc_access_rights[] = {\n"
6regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+PKEY_([[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*'
7egrep $regex ${header_dir}/mman-common.h | \
8 sed -r "s/$regex/\2 \2 \1/g" | \
9 sort | xargs printf "\t[%s ? (ilog2(%s) + 1) : 0] = \"%s\",\n"
10printf "};\n"
diff --git a/tools/perf/trace/beauty/prctl.c b/tools/perf/trace/beauty/prctl.c
new file mode 100644
index 000000000000..246130dad6c4
--- /dev/null
+++ b/tools/perf/trace/beauty/prctl.c
@@ -0,0 +1,82 @@
1/*
2 * trace/beauty/prctl.c
3 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */
8
9#include "trace/beauty/beauty.h"
10#include <linux/kernel.h>
11#include <uapi/linux/prctl.h>
12
13#include "trace/beauty/generated/prctl_option_array.c"
14
15static size_t prctl__scnprintf_option(int option, char *bf, size_t size)
16{
17 static DEFINE_STRARRAY(prctl_options);
18 return strarray__scnprintf(&strarray__prctl_options, bf, size, "%d", option);
19}
20
21static size_t prctl__scnprintf_set_mm(int option, char *bf, size_t size)
22{
23 static DEFINE_STRARRAY(prctl_set_mm_options);
24 return strarray__scnprintf(&strarray__prctl_set_mm_options, bf, size, "%d", option);
25}
26
27size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_arg *arg)
28{
29 int option = syscall_arg__val(arg, 0);
30
31 if (option == PR_SET_MM)
32 return prctl__scnprintf_set_mm(arg->val, bf, size);
33 /*
34 * We still don't grab the contents of pointers on entry or exit,
35 * so just print them as hex numbers
36 */
37 if (option == PR_SET_NAME)
38 return syscall_arg__scnprintf_hex(bf, size, arg);
39
40 return syscall_arg__scnprintf_long(bf, size, arg);
41}
42
43size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg)
44{
45 int option = syscall_arg__val(arg, 0);
46
47 if (option == PR_SET_MM)
48 return syscall_arg__scnprintf_hex(bf, size, arg);
49
50 return syscall_arg__scnprintf_long(bf, size, arg);
51}
52
53size_t syscall_arg__scnprintf_prctl_option(char *bf, size_t size, struct syscall_arg *arg)
54{
55 unsigned long option = arg->val;
56 enum {
57 SPO_ARG2 = (1 << 1),
58 SPO_ARG3 = (1 << 2),
59 SPO_ARG4 = (1 << 3),
60 SPO_ARG5 = (1 << 4),
61 SPO_ARG6 = (1 << 5),
62 };
63 const u8 all_but2 = SPO_ARG3 | SPO_ARG4 | SPO_ARG5 | SPO_ARG6;
64 const u8 all = SPO_ARG2 | all_but2;
65 const u8 masks[] = {
66 [PR_GET_DUMPABLE] = all,
67 [PR_SET_DUMPABLE] = all_but2,
68 [PR_SET_NAME] = all_but2,
69 [PR_GET_CHILD_SUBREAPER] = all_but2,
70 [PR_SET_CHILD_SUBREAPER] = all_but2,
71 [PR_GET_SECUREBITS] = all,
72 [PR_SET_SECUREBITS] = all_but2,
73 [PR_SET_MM] = SPO_ARG4 | SPO_ARG5 | SPO_ARG6,
74 [PR_GET_PDEATHSIG] = all,
75 [PR_SET_PDEATHSIG] = all_but2,
76 };
77
78 if (option < ARRAY_SIZE(masks))
79 arg->mask |= masks[option];
80
81 return prctl__scnprintf_option(option, bf, size);
82}
diff --git a/tools/perf/trace/beauty/prctl_option.sh b/tools/perf/trace/beauty/prctl_option.sh
new file mode 100755
index 000000000000..0be4138fbe71
--- /dev/null
+++ b/tools/perf/trace/beauty/prctl_option.sh
@@ -0,0 +1,17 @@
1#!/bin/sh
2
3header_dir=$1
4
5printf "static const char *prctl_options[] = {\n"
6regex='^#define[[:space:]]+PR_([GS]ET\w+)[[:space:]]*([[:xdigit:]]+).*'
7egrep $regex ${header_dir}/prctl.h | grep -v PR_SET_PTRACER | \
8 sed -r "s/$regex/\2 \1/g" | \
9 sort -n | xargs printf "\t[%s] = \"%s\",\n"
10printf "};\n"
11
12printf "static const char *prctl_set_mm_options[] = {\n"
13regex='^#[[:space:]]+define[[:space:]]+PR_SET_MM_(\w+)[[:space:]]*([[:digit:]]+).*'
14egrep $regex ${header_dir}/prctl.h | \
15 sed -r "s/$regex/\2 \1/g" | \
16 sort -n | xargs printf "\t[%s] = \"%s\",\n"
17printf "};\n"
diff --git a/tools/perf/trace/beauty/sched_policy.c b/tools/perf/trace/beauty/sched_policy.c
index 34775295b9b3..ba5096ae76b6 100644
--- a/tools/perf/trace/beauty/sched_policy.c
+++ b/tools/perf/trace/beauty/sched_policy.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sched.h> 2#include <sched.h>
2 3
3/* 4/*
diff --git a/tools/perf/trace/beauty/seccomp.c b/tools/perf/trace/beauty/seccomp.c
index 356441bce27d..b7097fd5fed9 100644
--- a/tools/perf/trace/beauty/seccomp.c
+++ b/tools/perf/trace/beauty/seccomp.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#ifndef SECCOMP_SET_MODE_STRICT 2#ifndef SECCOMP_SET_MODE_STRICT
2#define SECCOMP_SET_MODE_STRICT 0 3#define SECCOMP_SET_MODE_STRICT 0
3#endif 4#endif
diff --git a/tools/perf/trace/beauty/signum.c b/tools/perf/trace/beauty/signum.c
index fde8f2fc6558..bde18a53f090 100644
--- a/tools/perf/trace/beauty/signum.c
+++ b/tools/perf/trace/beauty/signum.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <signal.h> 2#include <signal.h>
2 3
3static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg) 4static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
diff --git a/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh b/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh
new file mode 100755
index 000000000000..aad5ab130539
--- /dev/null
+++ b/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh
@@ -0,0 +1,8 @@
1#!/bin/sh
2
3sound_header_dir=$1
4
5printf "static const char *sndrv_ctl_ioctl_cmds[] = {\n"
6grep "^#define[\t ]\+SNDRV_CTL_IOCTL_" $sound_header_dir/asound.h | \
7 sed -r 's/^#define +SNDRV_CTL_IOCTL_([A-Z0-9_]+)[\t ]+_IO[RW]*\( *.U., *(0x[[:xdigit:]]+),?.*/\t[\2] = \"\1\",/g'
8printf "};\n"
diff --git a/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh b/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
new file mode 100755
index 000000000000..b7e9ef6b2f55
--- /dev/null
+++ b/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
@@ -0,0 +1,8 @@
1#!/bin/sh
2
3sound_header_dir=$1
4
5printf "static const char *sndrv_pcm_ioctl_cmds[] = {\n"
6grep "^#define[\t ]\+SNDRV_PCM_IOCTL_" $sound_header_dir/asound.h | \
7 sed -r 's/^#define +SNDRV_PCM_IOCTL_([A-Z0-9_]+)[\t ]+_IO[RW]*\( *.A., *(0x[[:xdigit:]]+),?.*/\t[\2] = \"\1\",/g'
8printf "};\n"
diff --git a/tools/perf/trace/beauty/socket_type.c b/tools/perf/trace/beauty/socket_type.c
index 0a5ce818131c..bca26aef4a77 100644
--- a/tools/perf/trace/beauty/socket_type.c
+++ b/tools/perf/trace/beauty/socket_type.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/types.h> 2#include <sys/types.h>
2#include <sys/socket.h> 3#include <sys/socket.h>
3 4
diff --git a/tools/perf/trace/beauty/vhost_virtio_ioctl.sh b/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
new file mode 100755
index 000000000000..76f1de697787
--- /dev/null
+++ b/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
@@ -0,0 +1,17 @@
1#!/bin/sh
2
3vhost_virtio_header_dir=$1
4
5printf "static const char *vhost_virtio_ioctl_cmds[] = {\n"
6regex='^#[[:space:]]*define[[:space:]]+VHOST_(\w+)[[:space:]]+_IOW?\([[:space:]]*VHOST_VIRTIO[[:space:]]*,[[:space:]]*(0x[[:xdigit:]]+).*'
7egrep $regex ${vhost_virtio_header_dir}/vhost.h | \
8 sed -r "s/$regex/\2 \1/g" | \
9 sort | xargs printf "\t[%s] = \"%s\",\n"
10printf "};\n"
11
12printf "static const char *vhost_virtio_ioctl_read_cmds[] = {\n"
13regex='^#[[:space:]]*define[[:space:]]+VHOST_(\w+)[[:space:]]+_IOW?R\([[:space:]]*VHOST_VIRTIO[[:space:]]*,[[:space:]]*(0x[[:xdigit:]]+).*'
14egrep $regex ${vhost_virtio_header_dir}/vhost.h | \
15 sed -r "s/$regex/\2 \1/g" | \
16 sort | xargs printf "\t[%s] = \"%s\",\n"
17printf "};\n"
diff --git a/tools/perf/trace/beauty/waitid_options.c b/tools/perf/trace/beauty/waitid_options.c
index 7942724adec8..8465281a093d 100644
--- a/tools/perf/trace/beauty/waitid_options.c
+++ b/tools/perf/trace/beauty/waitid_options.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/types.h> 2#include <sys/types.h>
2#include <sys/wait.h> 3#include <sys/wait.h>
3 4
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index 83874b0e266c..63399af3049f 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "../util.h" 2#include "../util.h"
2#include "../string2.h" 3#include "../string2.h"
3#include "../config.h" 4#include "../config.h"
@@ -8,6 +9,7 @@
8#include <linux/compiler.h> 9#include <linux/compiler.h>
9#include <linux/list.h> 10#include <linux/list.h>
10#include <linux/rbtree.h> 11#include <linux/rbtree.h>
12#include <linux/string.h>
11#include <stdlib.h> 13#include <stdlib.h>
12#include <sys/ttydefaults.h> 14#include <sys/ttydefaults.h>
13#include "browser.h" 15#include "browser.h"
@@ -563,7 +565,7 @@ static int ui_browser__color_config(const char *var, const char *value,
563 int i; 565 int i;
564 566
565 /* same dir for all commands */ 567 /* same dir for all commands */
566 if (prefixcmp(var, "colors.") != 0) 568 if (!strstarts(var, "colors.") != 0)
567 return 0; 569 return 0;
568 570
569 for (i = 0; ui_browser__colorsets[i].name != NULL; ++i) { 571 for (i = 0; ui_browser__colorsets[i].name != NULL; ++i) {
@@ -738,6 +740,35 @@ void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
738 __ui_browser__line_arrow_down(browser, column, start, end); 740 __ui_browser__line_arrow_down(browser, column, start, end);
739} 741}
740 742
743void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column,
744 unsigned int row, bool arrow_down)
745{
746 unsigned int end_row;
747
748 if (row >= browser->top_idx)
749 end_row = row - browser->top_idx;
750 else
751 return;
752
753 SLsmg_set_char_set(1);
754
755 if (arrow_down) {
756 ui_browser__gotorc(browser, end_row, column - 1);
757 SLsmg_write_char(SLSMG_ULCORN_CHAR);
758 ui_browser__gotorc(browser, end_row, column);
759 SLsmg_draw_hline(2);
760 ui_browser__gotorc(browser, end_row + 1, column - 1);
761 SLsmg_write_char(SLSMG_LTEE_CHAR);
762 } else {
763 ui_browser__gotorc(browser, end_row, column - 1);
764 SLsmg_write_char(SLSMG_LTEE_CHAR);
765 ui_browser__gotorc(browser, end_row, column);
766 SLsmg_draw_hline(2);
767 }
768
769 SLsmg_set_char_set(0);
770}
771
741void ui_browser__init(void) 772void ui_browser__init(void)
742{ 773{
743 int i = 0; 774 int i = 0;
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index be3b70eb5fca..03e1734412b9 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_UI_BROWSER_H_ 2#ifndef _PERF_UI_BROWSER_H_
2#define _PERF_UI_BROWSER_H_ 1 3#define _PERF_UI_BROWSER_H_ 1
3 4
@@ -43,6 +44,8 @@ void ui_browser__printf(struct ui_browser *browser, const char *fmt, ...);
43void ui_browser__write_graph(struct ui_browser *browser, int graph); 44void ui_browser__write_graph(struct ui_browser *browser, int graph);
44void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column, 45void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
45 u64 start, u64 end); 46 u64 start, u64 end);
47void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column,
48 unsigned int row, bool arrow_down);
46void __ui_browser__show_title(struct ui_browser *browser, const char *title); 49void __ui_browser__show_title(struct ui_browser *browser, const char *title);
47void ui_browser__show_title(struct ui_browser *browser, const char *title); 50void ui_browser__show_title(struct ui_browser *browser, const char *title);
48int ui_browser__show(struct ui_browser *browser, const char *title, 51int ui_browser__show(struct ui_browser *browser, const char *title,
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 27f41f28dcb4..8f7f59d1a2b5 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "../../util/util.h" 2#include "../../util/util.h"
2#include "../browser.h" 3#include "../browser.h"
3#include "../helpline.h" 4#include "../helpline.h"
@@ -9,14 +10,16 @@
9#include "../../util/symbol.h" 10#include "../../util/symbol.h"
10#include "../../util/evsel.h" 11#include "../../util/evsel.h"
11#include "../../util/config.h" 12#include "../../util/config.h"
13#include "../../util/evlist.h"
12#include <inttypes.h> 14#include <inttypes.h>
13#include <pthread.h> 15#include <pthread.h>
14#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/string.h>
15#include <sys/ttydefaults.h> 18#include <sys/ttydefaults.h>
16 19
17struct disasm_line_samples { 20struct disasm_line_samples {
18 double percent; 21 double percent;
19 u64 nr; 22 struct sym_hist_entry he;
20}; 23};
21 24
22#define IPC_WIDTH 6 25#define IPC_WIDTH 6
@@ -40,6 +43,7 @@ static struct annotate_browser_opt {
40 jump_arrows, 43 jump_arrows,
41 show_linenr, 44 show_linenr,
42 show_nr_jumps, 45 show_nr_jumps,
46 show_nr_samples,
43 show_total_period; 47 show_total_period;
44} annotate_browser__opts = { 48} annotate_browser__opts = {
45 .use_offset = true, 49 .use_offset = true,
@@ -108,11 +112,12 @@ static int annotate_browser__set_jumps_percent_color(struct annotate_browser *br
108 112
109static int annotate_browser__pcnt_width(struct annotate_browser *ab) 113static int annotate_browser__pcnt_width(struct annotate_browser *ab)
110{ 114{
111 int w = 7 * ab->nr_events; 115 return (annotate_browser__opts.show_total_period ? 12 : 7) * ab->nr_events;
116}
112 117
113 if (ab->have_cycles) 118static int annotate_browser__cycles_width(struct annotate_browser *ab)
114 w += IPC_WIDTH + CYCLES_WIDTH; 119{
115 return w; 120 return ab->have_cycles ? IPC_WIDTH + CYCLES_WIDTH : 0;
116} 121}
117 122
118static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 123static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
@@ -125,7 +130,8 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
125 (!current_entry || (browser->use_navkeypressed && 130 (!current_entry || (browser->use_navkeypressed &&
126 !browser->navkeypressed))); 131 !browser->navkeypressed)));
127 int width = browser->width, printed; 132 int width = browser->width, printed;
128 int i, pcnt_width = annotate_browser__pcnt_width(ab); 133 int i, pcnt_width = annotate_browser__pcnt_width(ab),
134 cycles_width = annotate_browser__cycles_width(ab);
129 double percent_max = 0.0; 135 double percent_max = 0.0;
130 char bf[256]; 136 char bf[256];
131 bool show_title = false; 137 bool show_title = false;
@@ -149,8 +155,11 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
149 bdl->samples[i].percent, 155 bdl->samples[i].percent,
150 current_entry); 156 current_entry);
151 if (annotate_browser__opts.show_total_period) { 157 if (annotate_browser__opts.show_total_period) {
158 ui_browser__printf(browser, "%11" PRIu64 " ",
159 bdl->samples[i].he.period);
160 } else if (annotate_browser__opts.show_nr_samples) {
152 ui_browser__printf(browser, "%6" PRIu64 " ", 161 ui_browser__printf(browser, "%6" PRIu64 " ",
153 bdl->samples[i].nr); 162 bdl->samples[i].he.nr_samples);
154 } else { 163 } else {
155 ui_browser__printf(browser, "%6.2f ", 164 ui_browser__printf(browser, "%6.2f ",
156 bdl->samples[i].percent); 165 bdl->samples[i].percent);
@@ -160,9 +169,12 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
160 ui_browser__set_percent_color(browser, 0, current_entry); 169 ui_browser__set_percent_color(browser, 0, current_entry);
161 170
162 if (!show_title) 171 if (!show_title)
163 ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); 172 ui_browser__write_nstring(browser, " ", pcnt_width);
164 else 173 else {
165 ui_browser__printf(browser, "%*s", 7, "Percent"); 174 ui_browser__printf(browser, "%*s", pcnt_width,
175 annotate_browser__opts.show_total_period ? "Period" :
176 annotate_browser__opts.show_nr_samples ? "Samples" : "Percent");
177 }
166 } 178 }
167 if (ab->have_cycles) { 179 if (ab->have_cycles) {
168 if (dl->ipc) 180 if (dl->ipc)
@@ -188,7 +200,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
188 width += 1; 200 width += 1;
189 201
190 if (!*dl->line) 202 if (!*dl->line)
191 ui_browser__write_nstring(browser, " ", width - pcnt_width); 203 ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width);
192 else if (dl->offset == -1) { 204 else if (dl->offset == -1) {
193 if (dl->line_nr && annotate_browser__opts.show_linenr) 205 if (dl->line_nr && annotate_browser__opts.show_linenr)
194 printed = scnprintf(bf, sizeof(bf), "%-*d ", 206 printed = scnprintf(bf, sizeof(bf), "%-*d ",
@@ -197,7 +209,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
197 printed = scnprintf(bf, sizeof(bf), "%*s ", 209 printed = scnprintf(bf, sizeof(bf), "%*s ",
198 ab->addr_width, " "); 210 ab->addr_width, " ");
199 ui_browser__write_nstring(browser, bf, printed); 211 ui_browser__write_nstring(browser, bf, printed);
200 ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width + 1); 212 ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width - cycles_width + 1);
201 } else { 213 } else {
202 u64 addr = dl->offset; 214 u64 addr = dl->offset;
203 int color = -1; 215 int color = -1;
@@ -254,7 +266,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
254 } 266 }
255 267
256 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 268 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset);
257 ui_browser__write_nstring(browser, bf, width - pcnt_width - 3 - printed); 269 ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed);
258 } 270 }
259 271
260 if (current_entry) 272 if (current_entry)
@@ -272,6 +284,25 @@ static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sy
272 return true; 284 return true;
273} 285}
274 286
287static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
288{
289 struct disasm_line *pos = list_prev_entry(cursor, node);
290 const char *name;
291
292 if (!pos)
293 return false;
294
295 if (ins__is_lock(&pos->ins))
296 name = pos->ops.locked.ins.name;
297 else
298 name = pos->ins.name;
299
300 if (!name || !cursor->ins.name)
301 return false;
302
303 return ins__is_fused(ab->arch, name, cursor->ins.name);
304}
305
275static void annotate_browser__draw_current_jump(struct ui_browser *browser) 306static void annotate_browser__draw_current_jump(struct ui_browser *browser)
276{ 307{
277 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 308 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
@@ -307,6 +338,13 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
307 ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 338 ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
308 __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, 339 __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width,
309 from, to); 340 from, to);
341
342 if (is_fused(ab, cursor)) {
343 ui_browser__mark_fused(browser,
344 pcnt_width + 3 + ab->addr_width,
345 from - 1,
346 to > from ? true : false);
347 }
310} 348}
311 349
312static unsigned int annotate_browser__refresh(struct ui_browser *browser) 350static unsigned int annotate_browser__refresh(struct ui_browser *browser)
@@ -422,14 +460,14 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
422 next = disasm__get_next_ip_line(&notes->src->source, pos); 460 next = disasm__get_next_ip_line(&notes->src->source, pos);
423 461
424 for (i = 0; i < browser->nr_events; i++) { 462 for (i = 0; i < browser->nr_events; i++) {
425 u64 nr_samples; 463 struct sym_hist_entry sample;
426 464
427 bpos->samples[i].percent = disasm__calc_percent(notes, 465 bpos->samples[i].percent = disasm__calc_percent(notes,
428 evsel->idx + i, 466 evsel->idx + i,
429 pos->offset, 467 pos->offset,
430 next ? next->offset : len, 468 next ? next->offset : len,
431 &path, &nr_samples); 469 &path, &sample);
432 bpos->samples[i].nr = nr_samples; 470 bpos->samples[i].he = sample;
433 471
434 if (max_percent < bpos->samples[i].percent) 472 if (max_percent < bpos->samples[i].percent)
435 max_percent = bpos->samples[i].percent; 473 max_percent = bpos->samples[i].percent;
@@ -792,13 +830,14 @@ static int annotate_browser__run(struct annotate_browser *browser,
792 "q/ESC/CTRL+C Exit\n\n" 830 "q/ESC/CTRL+C Exit\n\n"
793 "ENTER Go to target\n" 831 "ENTER Go to target\n"
794 "ESC Exit\n" 832 "ESC Exit\n"
795 "H Cycle thru hottest instructions\n" 833 "H Go to hottest instruction\n"
834 "TAB/shift+TAB Cycle thru hottest instructions\n"
796 "j Toggle showing jump to target arrows\n" 835 "j Toggle showing jump to target arrows\n"
797 "J Toggle showing number of jump sources on targets\n" 836 "J Toggle showing number of jump sources on targets\n"
798 "n Search next string\n" 837 "n Search next string\n"
799 "o Toggle disassembler output/simplified view\n" 838 "o Toggle disassembler output/simplified view\n"
800 "s Toggle source code view\n" 839 "s Toggle source code view\n"
801 "t Toggle total period view\n" 840 "t Circulate percent, total period, samples view\n"
802 "/ Search string\n" 841 "/ Search string\n"
803 "k Toggle line numbers\n" 842 "k Toggle line numbers\n"
804 "r Run available scripts\n" 843 "r Run available scripts\n"
@@ -875,8 +914,13 @@ show_sup_ins:
875 } 914 }
876 continue; 915 continue;
877 case 't': 916 case 't':
878 annotate_browser__opts.show_total_period = 917 if (annotate_browser__opts.show_total_period) {
879 !annotate_browser__opts.show_total_period; 918 annotate_browser__opts.show_total_period = false;
919 annotate_browser__opts.show_nr_samples = true;
920 } else if (annotate_browser__opts.show_nr_samples)
921 annotate_browser__opts.show_nr_samples = false;
922 else
923 annotate_browser__opts.show_total_period = true;
880 annotate_browser__update_addr_width(browser); 924 annotate_browser__update_addr_width(browser);
881 continue; 925 continue;
882 case K_LEFT: 926 case K_LEFT:
@@ -899,9 +943,11 @@ out:
899int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 943int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
900 struct hist_browser_timer *hbt) 944 struct hist_browser_timer *hbt)
901{ 945{
902 /* Set default value for show_total_period. */ 946 /* Set default value for show_total_period and show_nr_samples */
903 annotate_browser__opts.show_total_period = 947 annotate_browser__opts.show_total_period =
904 symbol_conf.show_total_period; 948 symbol_conf.show_total_period;
949 annotate_browser__opts.show_nr_samples =
950 symbol_conf.show_nr_samples;
905 951
906 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 952 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt);
907} 953}
@@ -1074,7 +1120,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1074 } 1120 }
1075 1121
1076 err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 1122 err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
1077 sizeof_bdl, &browser.arch); 1123 sizeof_bdl, &browser.arch,
1124 perf_evsel__env_cpuid(evsel));
1078 if (err) { 1125 if (err) {
1079 char msg[BUFSIZ]; 1126 char msg[BUFSIZ];
1080 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 1127 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
@@ -1151,6 +1198,7 @@ static struct annotate_config {
1151 ANNOTATE_CFG(jump_arrows), 1198 ANNOTATE_CFG(jump_arrows),
1152 ANNOTATE_CFG(show_linenr), 1199 ANNOTATE_CFG(show_linenr),
1153 ANNOTATE_CFG(show_nr_jumps), 1200 ANNOTATE_CFG(show_nr_jumps),
1201 ANNOTATE_CFG(show_nr_samples),
1154 ANNOTATE_CFG(show_total_period), 1202 ANNOTATE_CFG(show_total_period),
1155 ANNOTATE_CFG(use_offset), 1203 ANNOTATE_CFG(use_offset),
1156}; 1204};
@@ -1170,7 +1218,7 @@ static int annotate__config(const char *var, const char *value,
1170 struct annotate_config *cfg; 1218 struct annotate_config *cfg;
1171 const char *name; 1219 const char *name;
1172 1220
1173 if (prefixcmp(var, "annotate.") != 0) 1221 if (!strstarts(var, "annotate."))
1174 return 0; 1222 return 0;
1175 1223
1176 name = var + 9; 1224 name = var + 9;
diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c
index e2c9390ff4c5..d75492189acb 100644
--- a/tools/perf/ui/browsers/header.c
+++ b/tools/perf/ui/browsers/header.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "util/cache.h" 2#include "util/cache.h"
2#include "util/debug.h" 3#include "util/debug.h"
3#include "ui/browser.h" 4#include "ui/browser.h"
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 69f4570bd4f9..68146f4620a5 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <dirent.h> 2#include <dirent.h>
2#include <errno.h> 3#include <errno.h>
3#include <inttypes.h> 4#include <inttypes.h>
@@ -154,60 +155,9 @@ static void callchain_list__set_folding(struct callchain_list *cl, bool unfold)
154 cl->unfolded = unfold ? cl->has_children : false; 155 cl->unfolded = unfold ? cl->has_children : false;
155} 156}
156 157
157static struct inline_node *inline_node__create(struct map *map, u64 ip)
158{
159 struct dso *dso;
160 struct inline_node *node;
161
162 if (map == NULL)
163 return NULL;
164
165 dso = map->dso;
166 if (dso == NULL)
167 return NULL;
168
169 if (dso->kernel != DSO_TYPE_USER)
170 return NULL;
171
172 node = dso__parse_addr_inlines(dso,
173 map__rip_2objdump(map, ip));
174
175 return node;
176}
177
178static int inline__count_rows(struct inline_node *node)
179{
180 struct inline_list *ilist;
181 int i = 0;
182
183 if (node == NULL)
184 return 0;
185
186 list_for_each_entry(ilist, &node->val, list) {
187 if ((ilist->filename != NULL) || (ilist->funcname != NULL))
188 i++;
189 }
190
191 return i;
192}
193
194static int callchain_list__inline_rows(struct callchain_list *chain)
195{
196 struct inline_node *node;
197 int rows;
198
199 node = inline_node__create(chain->ms.map, chain->ip);
200 if (node == NULL)
201 return 0;
202
203 rows = inline__count_rows(node);
204 inline_node__delete(node);
205 return rows;
206}
207
208static int callchain_node__count_rows_rb_tree(struct callchain_node *node) 158static int callchain_node__count_rows_rb_tree(struct callchain_node *node)
209{ 159{
210 int n = 0, inline_rows; 160 int n = 0;
211 struct rb_node *nd; 161 struct rb_node *nd;
212 162
213 for (nd = rb_first(&node->rb_root); nd; nd = rb_next(nd)) { 163 for (nd = rb_first(&node->rb_root); nd; nd = rb_next(nd)) {
@@ -218,12 +168,6 @@ static int callchain_node__count_rows_rb_tree(struct callchain_node *node)
218 list_for_each_entry(chain, &child->val, list) { 168 list_for_each_entry(chain, &child->val, list) {
219 ++n; 169 ++n;
220 170
221 if (symbol_conf.inline_name) {
222 inline_rows =
223 callchain_list__inline_rows(chain);
224 n += inline_rows;
225 }
226
227 /* We need this because we may not have children */ 171 /* We need this because we may not have children */
228 folded_sign = callchain_list__folded(chain); 172 folded_sign = callchain_list__folded(chain);
229 if (folded_sign == '+') 173 if (folded_sign == '+')
@@ -275,7 +219,7 @@ static int callchain_node__count_rows(struct callchain_node *node)
275{ 219{
276 struct callchain_list *chain; 220 struct callchain_list *chain;
277 bool unfolded = false; 221 bool unfolded = false;
278 int n = 0, inline_rows; 222 int n = 0;
279 223
280 if (callchain_param.mode == CHAIN_FLAT) 224 if (callchain_param.mode == CHAIN_FLAT)
281 return callchain_node__count_flat_rows(node); 225 return callchain_node__count_flat_rows(node);
@@ -284,10 +228,6 @@ static int callchain_node__count_rows(struct callchain_node *node)
284 228
285 list_for_each_entry(chain, &node->val, list) { 229 list_for_each_entry(chain, &node->val, list) {
286 ++n; 230 ++n;
287 if (symbol_conf.inline_name) {
288 inline_rows = callchain_list__inline_rows(chain);
289 n += inline_rows;
290 }
291 231
292 unfolded = chain->unfolded; 232 unfolded = chain->unfolded;
293 } 233 }
@@ -435,19 +375,6 @@ static void hist_entry__init_have_children(struct hist_entry *he)
435 he->init_have_children = true; 375 he->init_have_children = true;
436} 376}
437 377
438static void hist_entry_init_inline_node(struct hist_entry *he)
439{
440 if (he->inline_node)
441 return;
442
443 he->inline_node = inline_node__create(he->ms.map, he->ip);
444
445 if (he->inline_node == NULL)
446 return;
447
448 he->has_children = true;
449}
450
451static bool hist_browser__toggle_fold(struct hist_browser *browser) 378static bool hist_browser__toggle_fold(struct hist_browser *browser)
452{ 379{
453 struct hist_entry *he = browser->he_selection; 380 struct hist_entry *he = browser->he_selection;
@@ -479,12 +406,8 @@ static bool hist_browser__toggle_fold(struct hist_browser *browser)
479 406
480 if (he->unfolded) { 407 if (he->unfolded) {
481 if (he->leaf) 408 if (he->leaf)
482 if (he->inline_node) 409 he->nr_rows = callchain__count_rows(
483 he->nr_rows = inline__count_rows( 410 &he->sorted_chain);
484 he->inline_node);
485 else
486 he->nr_rows = callchain__count_rows(
487 &he->sorted_chain);
488 else 411 else
489 he->nr_rows = hierarchy_count_rows(browser, he, false); 412 he->nr_rows = hierarchy_count_rows(browser, he, false);
490 413
@@ -844,71 +767,6 @@ static bool hist_browser__check_dump_full(struct hist_browser *browser __maybe_u
844 767
845#define LEVEL_OFFSET_STEP 3 768#define LEVEL_OFFSET_STEP 3
846 769
847static int hist_browser__show_inline(struct hist_browser *browser,
848 struct inline_node *node,
849 unsigned short row,
850 int offset)
851{
852 struct inline_list *ilist;
853 char buf[1024];
854 int color, width, first_row;
855
856 first_row = row;
857 width = browser->b.width - (LEVEL_OFFSET_STEP + 2);
858 list_for_each_entry(ilist, &node->val, list) {
859 if ((ilist->filename != NULL) || (ilist->funcname != NULL)) {
860 color = HE_COLORSET_NORMAL;
861 if (ui_browser__is_current_entry(&browser->b, row))
862 color = HE_COLORSET_SELECTED;
863
864 if (callchain_param.key == CCKEY_ADDRESS ||
865 callchain_param.key == CCKEY_SRCLINE) {
866 if (ilist->filename != NULL)
867 scnprintf(buf, sizeof(buf),
868 "%s:%d (inline)",
869 ilist->filename,
870 ilist->line_nr);
871 else
872 scnprintf(buf, sizeof(buf), "??");
873 } else if (ilist->funcname != NULL)
874 scnprintf(buf, sizeof(buf), "%s (inline)",
875 ilist->funcname);
876 else if (ilist->filename != NULL)
877 scnprintf(buf, sizeof(buf),
878 "%s:%d (inline)",
879 ilist->filename,
880 ilist->line_nr);
881 else
882 scnprintf(buf, sizeof(buf), "??");
883
884 ui_browser__set_color(&browser->b, color);
885 hist_browser__gotorc(browser, row, 0);
886 ui_browser__write_nstring(&browser->b, " ",
887 LEVEL_OFFSET_STEP + offset);
888 ui_browser__write_nstring(&browser->b, buf, width);
889 row++;
890 }
891 }
892
893 return row - first_row;
894}
895
896static size_t show_inline_list(struct hist_browser *browser, struct map *map,
897 u64 ip, int row, int offset)
898{
899 struct inline_node *node;
900 int ret;
901
902 node = inline_node__create(map, ip);
903 if (node == NULL)
904 return 0;
905
906 ret = hist_browser__show_inline(browser, node, row, offset);
907
908 inline_node__delete(node);
909 return ret;
910}
911
912static int hist_browser__show_callchain_list(struct hist_browser *browser, 770static int hist_browser__show_callchain_list(struct hist_browser *browser,
913 struct callchain_node *node, 771 struct callchain_node *node,
914 struct callchain_list *chain, 772 struct callchain_list *chain,
@@ -920,7 +778,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
920 char bf[1024], *alloc_str; 778 char bf[1024], *alloc_str;
921 char buf[64], *alloc_str2; 779 char buf[64], *alloc_str2;
922 const char *str; 780 const char *str;
923 int inline_rows = 0, ret = 1; 781 int ret = 1;
924 782
925 if (arg->row_offset != 0) { 783 if (arg->row_offset != 0) {
926 arg->row_offset--; 784 arg->row_offset--;
@@ -934,12 +792,8 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
934 browser->show_dso); 792 browser->show_dso);
935 793
936 if (symbol_conf.show_branchflag_count) { 794 if (symbol_conf.show_branchflag_count) {
937 if (need_percent) 795 callchain_list_counts__printf_value(chain, NULL,
938 callchain_list_counts__printf_value(node, chain, NULL, 796 buf, sizeof(buf));
939 buf, sizeof(buf));
940 else
941 callchain_list_counts__printf_value(NULL, chain, NULL,
942 buf, sizeof(buf));
943 797
944 if (asprintf(&alloc_str2, "%s%s", str, buf) < 0) 798 if (asprintf(&alloc_str2, "%s%s", str, buf) < 0)
945 str = "Not enough memory!"; 799 str = "Not enough memory!";
@@ -961,12 +815,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
961 free(alloc_str); 815 free(alloc_str);
962 free(alloc_str2); 816 free(alloc_str2);
963 817
964 if (symbol_conf.inline_name) { 818 return ret;
965 inline_rows = show_inline_list(browser, chain->ms.map,
966 chain->ip, row + 1, offset);
967 }
968
969 return ret + inline_rows;
970} 819}
971 820
972static bool check_percent_display(struct rb_node *node, u64 parent_total) 821static bool check_percent_display(struct rb_node *node, u64 parent_total)
@@ -1390,12 +1239,6 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1390 folded_sign = hist_entry__folded(entry); 1239 folded_sign = hist_entry__folded(entry);
1391 } 1240 }
1392 1241
1393 if (symbol_conf.inline_name &&
1394 (!entry->has_children)) {
1395 hist_entry_init_inline_node(entry);
1396 folded_sign = hist_entry__folded(entry);
1397 }
1398
1399 if (row_offset == 0) { 1242 if (row_offset == 0) {
1400 struct hpp_arg arg = { 1243 struct hpp_arg arg = {
1401 .b = &browser->b, 1244 .b = &browser->b,
@@ -1427,8 +1270,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1427 } 1270 }
1428 1271
1429 if (first) { 1272 if (first) {
1430 if (symbol_conf.use_callchain || 1273 if (symbol_conf.use_callchain) {
1431 symbol_conf.inline_name) {
1432 ui_browser__printf(&browser->b, "%c ", folded_sign); 1274 ui_browser__printf(&browser->b, "%c ", folded_sign);
1433 width -= 2; 1275 width -= 2;
1434 } 1276 }
@@ -1470,15 +1312,11 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1470 .is_current_entry = current_entry, 1312 .is_current_entry = current_entry,
1471 }; 1313 };
1472 1314
1473 if (entry->inline_node) 1315 printed += hist_browser__show_callchain(browser,
1474 printed += hist_browser__show_inline(browser, 1316 entry, 1, row,
1475 entry->inline_node, row, 0); 1317 hist_browser__show_callchain_entry,
1476 else 1318 &arg,
1477 printed += hist_browser__show_callchain(browser, 1319 hist_browser__check_output_full);
1478 entry, 1, row,
1479 hist_browser__show_callchain_entry,
1480 &arg,
1481 hist_browser__check_output_full);
1482 } 1320 }
1483 1321
1484 return printed; 1322 return printed;
diff --git a/tools/perf/ui/browsers/hists.h b/tools/perf/ui/browsers/hists.h
index 23d6acb84800..ba431777f559 100644
--- a/tools/perf/ui/browsers/hists.h
+++ b/tools/perf/ui/browsers/hists.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_UI_BROWSER_HISTS_H_ 2#ifndef _PERF_UI_BROWSER_HISTS_H_
2#define _PERF_UI_BROWSER_HISTS_H_ 1 3#define _PERF_UI_BROWSER_HISTS_H_ 1
3 4
diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c
index ffa5addf631d..e03fa75f108a 100644
--- a/tools/perf/ui/browsers/map.c
+++ b/tools/perf/ui/browsers/map.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <elf.h> 2#include <elf.h>
2#include <inttypes.h> 3#include <inttypes.h>
3#include <sys/ttydefaults.h> 4#include <sys/ttydefaults.h>
diff --git a/tools/perf/ui/browsers/map.h b/tools/perf/ui/browsers/map.h
index 2d58e4b3eb6f..0ed7dbb3a373 100644
--- a/tools/perf/ui/browsers/map.h
+++ b/tools/perf/ui/browsers/map.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_UI_MAP_BROWSER_H_ 2#ifndef _PERF_UI_MAP_BROWSER_H_
2#define _PERF_UI_MAP_BROWSER_H_ 1 3#define _PERF_UI_MAP_BROWSER_H_ 1
3struct map; 4struct map;
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c
index ad6b6ee3770e..90a32ac69e76 100644
--- a/tools/perf/ui/browsers/scripts.c
+++ b/tools/perf/ui/browsers/scripts.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <elf.h> 2#include <elf.h>
2#include <inttypes.h> 3#include <inttypes.h>
3#include <sys/ttydefaults.h> 4#include <sys/ttydefaults.h>
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index d903fd493416..fc7a2e105bfd 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "gtk.h" 2#include "gtk.h"
2#include "util/debug.h" 3#include "util/debug.h"
3#include "util/annotate.h" 4#include "util/annotate.h"
@@ -34,10 +35,10 @@ static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym,
34 return 0; 35 return 0;
35 36
36 symhist = annotation__histogram(symbol__annotation(sym), evidx); 37 symhist = annotation__histogram(symbol__annotation(sym), evidx);
37 if (!symbol_conf.event_group && !symhist->addr[dl->offset]) 38 if (!symbol_conf.event_group && !symhist->addr[dl->offset].nr_samples)
38 return 0; 39 return 0;
39 40
40 percent = 100.0 * symhist->addr[dl->offset] / symhist->sum; 41 percent = 100.0 * symhist->addr[dl->offset].nr_samples / symhist->nr_samples;
41 42
42 markup = perf_gtk__get_percent_color(percent); 43 markup = perf_gtk__get_percent_color(percent);
43 if (markup) 44 if (markup)
@@ -169,7 +170,7 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
169 return -1; 170 return -1;
170 171
171 err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 172 err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
172 0, NULL); 173 0, NULL, NULL);
173 if (err) { 174 if (err) {
174 char msg[BUFSIZ]; 175 char msg[BUFSIZ];
175 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 176 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index c24d91221290..4820e25ac68d 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "../evlist.h" 2#include "../evlist.h"
2#include "../cache.h" 3#include "../cache.h"
3#include "../evsel.h" 4#include "../evsel.h"
diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h
index 0a9173ff9a61..9846ea5c831b 100644
--- a/tools/perf/ui/gtk/gtk.h
+++ b/tools/perf/ui/gtk/gtk.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_GTK_H_ 2#ifndef _PERF_GTK_H_
2#define _PERF_GTK_H_ 1 3#define _PERF_GTK_H_ 1
3 4
diff --git a/tools/perf/ui/gtk/helpline.c b/tools/perf/ui/gtk/helpline.c
index 3388cbd12186..fbf1ea9ce9a2 100644
--- a/tools/perf/ui/gtk/helpline.c
+++ b/tools/perf/ui/gtk/helpline.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <string.h> 3#include <string.h>
3 4
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index e24f83957705..24e1ec201ffd 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "../evlist.h" 2#include "../evlist.h"
2#include "../cache.h" 3#include "../cache.h"
3#include "../evsel.h" 4#include "../evsel.h"
diff --git a/tools/perf/ui/gtk/progress.c b/tools/perf/ui/gtk/progress.c
index b656655fbc39..b6ad8857da78 100644
--- a/tools/perf/ui/gtk/progress.c
+++ b/tools/perf/ui/gtk/progress.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <inttypes.h> 2#include <inttypes.h>
2 3
3#include "gtk.h" 4#include "gtk.h"
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c
index 1d57676f8212..506e73b3834c 100644
--- a/tools/perf/ui/gtk/setup.c
+++ b/tools/perf/ui/gtk/setup.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "gtk.h" 2#include "gtk.h"
2#include "../../util/cache.h" 3#include "../../util/cache.h"
3#include "../../util/debug.h" 4#include "../../util/debug.h"
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index 00b91921edb1..7250d8101c8f 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "../util.h" 2#include "../util.h"
2#include "../../util/util.h" 3#include "../../util/util.h"
3#include "../../util/debug.h" 4#include "../../util/debug.h"
diff --git a/tools/perf/ui/helpline.c b/tools/perf/ui/helpline.c
index 379039ab00d8..b3c421429ed4 100644
--- a/tools/perf/ui/helpline.c
+++ b/tools/perf/ui/helpline.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <string.h> 4#include <string.h>
diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h
index d52d0a1a881b..8f775a053ca3 100644
--- a/tools/perf/ui/helpline.h
+++ b/tools/perf/ui/helpline.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_UI_HELPLINE_H_ 2#ifndef _PERF_UI_HELPLINE_H_
2#define _PERF_UI_HELPLINE_H_ 1 3#define _PERF_UI_HELPLINE_H_ 1
3 4
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index ddb2c6fbdf91..706f6f1e9c7d 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <inttypes.h> 2#include <inttypes.h>
2#include <math.h> 3#include <math.h>
3#include <linux/compiler.h> 4#include <linux/compiler.h>
@@ -532,7 +533,7 @@ void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,
532 533
533void perf_hpp__column_unregister(struct perf_hpp_fmt *format) 534void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
534{ 535{
535 list_del(&format->list); 536 list_del_init(&format->list);
536} 537}
537 538
538void perf_hpp__cancel_cumulate(void) 539void perf_hpp__cancel_cumulate(void)
@@ -606,6 +607,13 @@ next:
606 607
607static void fmt_free(struct perf_hpp_fmt *fmt) 608static void fmt_free(struct perf_hpp_fmt *fmt)
608{ 609{
610 /*
611 * At this point fmt should be completely
612 * unhooked, if not it's a bug.
613 */
614 BUG_ON(!list_empty(&fmt->list));
615 BUG_ON(!list_empty(&fmt->sort_list));
616
609 if (fmt->free) 617 if (fmt->free)
610 fmt->free(fmt); 618 fmt->free(fmt);
611} 619}
diff --git a/tools/perf/ui/keysyms.h b/tools/perf/ui/keysyms.h
index 65092d576b4e..fbfac29077f2 100644
--- a/tools/perf/ui/keysyms.h
+++ b/tools/perf/ui/keysyms.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_KEYSYMS_H_ 2#ifndef _PERF_KEYSYMS_H_
2#define _PERF_KEYSYMS_H_ 1 3#define _PERF_KEYSYMS_H_ 1
3 4
diff --git a/tools/perf/ui/libslang.h b/tools/perf/ui/libslang.h
index db816695ad97..c0686cda39a5 100644
--- a/tools/perf/ui/libslang.h
+++ b/tools/perf/ui/libslang.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_UI_SLANG_H_ 2#ifndef _PERF_UI_SLANG_H_
2#define _PERF_UI_SLANG_H_ 1 3#define _PERF_UI_SLANG_H_ 1
3/* 4/*
diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c
index a0f24c7115c5..bbfbc91a0fa4 100644
--- a/tools/perf/ui/progress.c
+++ b/tools/perf/ui/progress.c
@@ -1,3 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/kernel.h>
1#include "../cache.h" 3#include "../cache.h"
2#include "progress.h" 4#include "progress.h"
3 5
@@ -14,21 +16,29 @@ struct ui_progress_ops *ui_progress__ops = &null_progress__ops;
14 16
15void ui_progress__update(struct ui_progress *p, u64 adv) 17void ui_progress__update(struct ui_progress *p, u64 adv)
16{ 18{
19 u64 last = p->curr;
20
17 p->curr += adv; 21 p->curr += adv;
18 22
19 if (p->curr >= p->next) { 23 if (p->curr >= p->next) {
20 p->next += p->step; 24 u64 nr = DIV_ROUND_UP(p->curr - last, p->step);
25
26 p->next += nr * p->step;
21 ui_progress__ops->update(p); 27 ui_progress__ops->update(p);
22 } 28 }
23} 29}
24 30
25void ui_progress__init(struct ui_progress *p, u64 total, const char *title) 31void __ui_progress__init(struct ui_progress *p, u64 total,
32 const char *title, bool size)
26{ 33{
27 p->curr = 0; 34 p->curr = 0;
28 p->next = p->step = total / 16; 35 p->next = p->step = total / 16 ?: 1;
29 p->total = total; 36 p->total = total;
30 p->title = title; 37 p->title = title;
38 p->size = size;
31 39
40 if (ui_progress__ops->init)
41 ui_progress__ops->init(p);
32} 42}
33 43
34void ui_progress__finish(void) 44void ui_progress__finish(void)
diff --git a/tools/perf/ui/progress.h b/tools/perf/ui/progress.h
index 717d39d3052b..4f52c37b2f09 100644
--- a/tools/perf/ui/progress.h
+++ b/tools/perf/ui/progress.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_UI_PROGRESS_H_ 2#ifndef _PERF_UI_PROGRESS_H_
2#define _PERF_UI_PROGRESS_H_ 1 3#define _PERF_UI_PROGRESS_H_ 1
3 4
@@ -8,12 +9,22 @@ void ui_progress__finish(void);
8struct ui_progress { 9struct ui_progress {
9 const char *title; 10 const char *title;
10 u64 curr, next, step, total; 11 u64 curr, next, step, total;
12 bool size;
11}; 13};
12 14
13void ui_progress__init(struct ui_progress *p, u64 total, const char *title); 15void __ui_progress__init(struct ui_progress *p, u64 total,
16 const char *title, bool size);
17
18#define ui_progress__init(p, total, title) \
19 __ui_progress__init(p, total, title, false)
20
21#define ui_progress__init_size(p, total, title) \
22 __ui_progress__init(p, total, title, true)
23
14void ui_progress__update(struct ui_progress *p, u64 adv); 24void ui_progress__update(struct ui_progress *p, u64 adv);
15 25
16struct ui_progress_ops { 26struct ui_progress_ops {
27 void (*init)(struct ui_progress *p);
17 void (*update)(struct ui_progress *p); 28 void (*update)(struct ui_progress *p);
18 void (*finish)(void); 29 void (*finish)(void);
19}; 30};
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index caf1ce6f5152..44fe824e96cd 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <pthread.h> 2#include <pthread.h>
2#include <dlfcn.h> 3#include <dlfcn.h>
3 4
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 42e432bd2eb4..25dd1e0ecc58 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -1,4 +1,6 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
3#include <linux/string.h>
2 4
3#include "../../util/util.h" 5#include "../../util/util.h"
4#include "../../util/hist.h" 6#include "../../util/hist.h"
@@ -20,67 +22,6 @@ static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
20 return ret; 22 return ret;
21} 23}
22 24
23static size_t inline__fprintf(struct map *map, u64 ip, int left_margin,
24 int depth, int depth_mask, FILE *fp)
25{
26 struct dso *dso;
27 struct inline_node *node;
28 struct inline_list *ilist;
29 int ret = 0, i;
30
31 if (map == NULL)
32 return 0;
33
34 dso = map->dso;
35 if (dso == NULL)
36 return 0;
37
38 if (dso->kernel != DSO_TYPE_USER)
39 return 0;
40
41 node = dso__parse_addr_inlines(dso,
42 map__rip_2objdump(map, ip));
43 if (node == NULL)
44 return 0;
45
46 list_for_each_entry(ilist, &node->val, list) {
47 if ((ilist->filename != NULL) || (ilist->funcname != NULL)) {
48 ret += callchain__fprintf_left_margin(fp, left_margin);
49
50 for (i = 0; i < depth; i++) {
51 if (depth_mask & (1 << i))
52 ret += fprintf(fp, "|");
53 else
54 ret += fprintf(fp, " ");
55 ret += fprintf(fp, " ");
56 }
57
58 if (callchain_param.key == CCKEY_ADDRESS ||
59 callchain_param.key == CCKEY_SRCLINE) {
60 if (ilist->filename != NULL)
61 ret += fprintf(fp, "%s:%d (inline)",
62 ilist->filename,
63 ilist->line_nr);
64 else
65 ret += fprintf(fp, "??");
66 } else if (ilist->funcname != NULL)
67 ret += fprintf(fp, "%s (inline)",
68 ilist->funcname);
69 else if (ilist->filename != NULL)
70 ret += fprintf(fp, "%s:%d (inline)",
71 ilist->filename,
72 ilist->line_nr);
73 else
74 ret += fprintf(fp, "??");
75
76 ret += fprintf(fp, "\n");
77 }
78 }
79
80 inline_node__delete(node);
81 return ret;
82}
83
84static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, 25static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
85 int left_margin) 26 int left_margin)
86{ 27{
@@ -126,12 +67,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
126 str = callchain_list__sym_name(chain, bf, sizeof(bf), false); 67 str = callchain_list__sym_name(chain, bf, sizeof(bf), false);
127 68
128 if (symbol_conf.show_branchflag_count) { 69 if (symbol_conf.show_branchflag_count) {
129 if (!period) 70 callchain_list_counts__printf_value(chain, NULL,
130 callchain_list_counts__printf_value(node, chain, NULL, 71 buf, sizeof(buf));
131 buf, sizeof(buf));
132 else
133 callchain_list_counts__printf_value(NULL, chain, NULL,
134 buf, sizeof(buf));
135 72
136 if (asprintf(&alloc_str, "%s%s", str, buf) < 0) 73 if (asprintf(&alloc_str, "%s%s", str, buf) < 0)
137 str = "Not enough memory!"; 74 str = "Not enough memory!";
@@ -143,9 +80,6 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
143 fputc('\n', fp); 80 fputc('\n', fp);
144 free(alloc_str); 81 free(alloc_str);
145 82
146 if (symbol_conf.inline_name)
147 ret += inline__fprintf(chain->ms.map, chain->ip,
148 left_margin, depth, depth_mask, fp);
149 return ret; 83 return ret;
150} 84}
151 85
@@ -295,7 +229,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
295 * displayed twice. 229 * displayed twice.
296 */ 230 */
297 if (!i++ && field_order == NULL && 231 if (!i++ && field_order == NULL &&
298 sort_order && !prefixcmp(sort_order, "sym")) 232 sort_order && strstarts(sort_order, "sym"))
299 continue; 233 continue;
300 234
301 if (!printed) { 235 if (!printed) {
@@ -315,18 +249,11 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
315 249
316 if (symbol_conf.show_branchflag_count) 250 if (symbol_conf.show_branchflag_count)
317 ret += callchain_list_counts__printf_value( 251 ret += callchain_list_counts__printf_value(
318 NULL, chain, fp, NULL, 0); 252 chain, fp, NULL, 0);
319 ret += fprintf(fp, "\n"); 253 ret += fprintf(fp, "\n");
320 254
321 if (++entries_printed == callchain_param.print_limit) 255 if (++entries_printed == callchain_param.print_limit)
322 break; 256 break;
323
324 if (symbol_conf.inline_name)
325 ret += inline__fprintf(chain->ms.map,
326 chain->ip,
327 left_margin,
328 0, 0,
329 fp);
330 } 257 }
331 root = &cnode->rb_root; 258 root = &cnode->rb_root;
332 } 259 }
@@ -606,7 +533,6 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
606{ 533{
607 int ret; 534 int ret;
608 int callchain_ret = 0; 535 int callchain_ret = 0;
609 int inline_ret = 0;
610 struct perf_hpp hpp = { 536 struct perf_hpp hpp = {
611 .buf = bf, 537 .buf = bf,
612 .size = size, 538 .size = size,
@@ -628,13 +554,7 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
628 callchain_ret = hist_entry_callchain__fprintf(he, total_period, 554 callchain_ret = hist_entry_callchain__fprintf(he, total_period,
629 0, fp); 555 0, fp);
630 556
631 if (callchain_ret == 0 && symbol_conf.inline_name) { 557 ret += callchain_ret;
632 inline_ret = inline__fprintf(he->ms.map, he->ip, 0, 0, 0, fp);
633 ret += inline_ret;
634 if (inline_ret > 0)
635 ret += fprintf(fp, "\n");
636 } else
637 ret += callchain_ret;
638 558
639 return ret; 559 return ret;
640} 560}
diff --git a/tools/perf/ui/tui/helpline.c b/tools/perf/ui/tui/helpline.c
index 88f5143a5981..4ca799aadb4e 100644
--- a/tools/perf/ui/tui/helpline.c
+++ b/tools/perf/ui/tui/helpline.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <string.h> 4#include <string.h>
diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c
index c4b99008e2c9..bc134b82829d 100644
--- a/tools/perf/ui/tui/progress.c
+++ b/tools/perf/ui/tui/progress.c
@@ -1,12 +1,34 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/kernel.h>
1#include "../cache.h" 3#include "../cache.h"
2#include "../progress.h" 4#include "../progress.h"
3#include "../libslang.h" 5#include "../libslang.h"
4#include "../ui.h" 6#include "../ui.h"
5#include "tui.h" 7#include "tui.h"
8#include "units.h"
6#include "../browser.h" 9#include "../browser.h"
7 10
11static void __tui_progress__init(struct ui_progress *p)
12{
13 p->next = p->step = p->total / (SLtt_Screen_Cols - 2) ?: 1;
14}
15
16static int get_title(struct ui_progress *p, char *buf, size_t size)
17{
18 char buf_cur[20];
19 char buf_tot[20];
20 int ret;
21
22 ret = unit_number__scnprintf(buf_cur, sizeof(buf_cur), p->curr);
23 ret += unit_number__scnprintf(buf_tot, sizeof(buf_tot), p->total);
24
25 return ret + scnprintf(buf, size, "%s [%s/%s]",
26 p->title, buf_cur, buf_tot);
27}
28
8static void tui_progress__update(struct ui_progress *p) 29static void tui_progress__update(struct ui_progress *p)
9{ 30{
31 char buf[100], *title = (char *) p->title;
10 int bar, y; 32 int bar, y;
11 /* 33 /*
12 * FIXME: We should have a per UI backend way of showing progress, 34 * FIXME: We should have a per UI backend way of showing progress,
@@ -18,13 +40,18 @@ static void tui_progress__update(struct ui_progress *p)
18 if (p->total == 0) 40 if (p->total == 0)
19 return; 41 return;
20 42
43 if (p->size) {
44 get_title(p, buf, sizeof(buf));
45 title = buf;
46 }
47
21 ui__refresh_dimensions(false); 48 ui__refresh_dimensions(false);
22 pthread_mutex_lock(&ui__lock); 49 pthread_mutex_lock(&ui__lock);
23 y = SLtt_Screen_Rows / 2 - 2; 50 y = SLtt_Screen_Rows / 2 - 2;
24 SLsmg_set_color(0); 51 SLsmg_set_color(0);
25 SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols); 52 SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols);
26 SLsmg_gotorc(y++, 1); 53 SLsmg_gotorc(y++, 1);
27 SLsmg_write_string((char *)p->title); 54 SLsmg_write_string(title);
28 SLsmg_fill_region(y, 1, 1, SLtt_Screen_Cols - 2, ' '); 55 SLsmg_fill_region(y, 1, 1, SLtt_Screen_Cols - 2, ' ');
29 SLsmg_set_color(HE_COLORSET_SELECTED); 56 SLsmg_set_color(HE_COLORSET_SELECTED);
30 bar = ((SLtt_Screen_Cols - 2) * p->curr) / p->total; 57 bar = ((SLtt_Screen_Cols - 2) * p->curr) / p->total;
@@ -49,8 +76,8 @@ static void tui_progress__finish(void)
49 pthread_mutex_unlock(&ui__lock); 76 pthread_mutex_unlock(&ui__lock);
50} 77}
51 78
52static struct ui_progress_ops tui_progress__ops = 79static struct ui_progress_ops tui_progress__ops = {
53{ 80 .init = __tui_progress__init,
54 .update = tui_progress__update, 81 .update = tui_progress__update,
55 .finish = tui_progress__finish, 82 .finish = tui_progress__finish,
56}; 83};
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index d9350a1da48b..d4ac41679721 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <signal.h> 3#include <signal.h>
3#include <stdbool.h> 4#include <stdbool.h>
diff --git a/tools/perf/ui/tui/tui.h b/tools/perf/ui/tui/tui.h
index 18961c7b6ec5..8de06f634c56 100644
--- a/tools/perf/ui/tui/tui.h
+++ b/tools/perf/ui/tui/tui.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_TUI_H_ 2#ifndef _PERF_TUI_H_
2#define _PERF_TUI_H_ 1 3#define _PERF_TUI_H_ 1
3 4
diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c
index d96ad7c8325d..b9794d6185af 100644
--- a/tools/perf/ui/tui/util.c
+++ b/tools/perf/ui/tui/util.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "../../util/util.h" 2#include "../../util/util.h"
2#include <signal.h> 3#include <signal.h>
3#include <stdbool.h> 4#include <stdbool.h>
diff --git a/tools/perf/ui/ui.h b/tools/perf/ui/ui.h
index 4b6fb6c7a542..9b6fdf06e1d2 100644
--- a/tools/perf/ui/ui.h
+++ b/tools/perf/ui/ui.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_UI_H_ 2#ifndef _PERF_UI_H_
2#define _PERF_UI_H_ 1 3#define _PERF_UI_H_ 1
3 4
diff --git a/tools/perf/ui/util.c b/tools/perf/ui/util.c
index e3e0a963d03a..63bf06e80ab9 100644
--- a/tools/perf/ui/util.c
+++ b/tools/perf/ui/util.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "util.h" 2#include "util.h"
2#include "../debug.h" 3#include "../debug.h"
3 4
diff --git a/tools/perf/ui/util.h b/tools/perf/ui/util.h
index 361f08c52d37..5e44223b56fa 100644
--- a/tools/perf/ui/util.h
+++ b/tools/perf/ui/util.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_UI_UTIL_H_ 2#ifndef _PERF_UI_UTIL_H_
2#define _PERF_UI_UTIL_H_ 1 3#define _PERF_UI_UTIL_H_ 1
3 4
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 79dea95a7f68..a3de7916fe63 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -13,6 +13,7 @@ libperf-y += find_bit.o
13libperf-y += kallsyms.o 13libperf-y += kallsyms.o
14libperf-y += levenshtein.o 14libperf-y += levenshtein.o
15libperf-y += llvm-utils.o 15libperf-y += llvm-utils.o
16libperf-y += mmap.o
16libperf-y += memswap.o 17libperf-y += memswap.o
17libperf-y += parse-events.o 18libperf-y += parse-events.o
18libperf-y += perf_regs.o 19libperf-y += perf_regs.o
@@ -22,6 +23,7 @@ libperf-y += rbtree.o
22libperf-y += libstring.o 23libperf-y += libstring.o
23libperf-y += bitmap.o 24libperf-y += bitmap.o
24libperf-y += hweight.o 25libperf-y += hweight.o
26libperf-y += smt.o
25libperf-y += quote.o 27libperf-y += quote.o
26libperf-y += strbuf.o 28libperf-y += strbuf.o
27libperf-y += string.o 29libperf-y += string.o
@@ -33,6 +35,7 @@ libperf-y += dso.o
33libperf-y += symbol.o 35libperf-y += symbol.o
34libperf-y += symbol_fprintf.o 36libperf-y += symbol_fprintf.o
35libperf-y += color.o 37libperf-y += color.o
38libperf-y += metricgroup.o
36libperf-y += header.o 39libperf-y += header.o
37libperf-y += callchain.o 40libperf-y += callchain.o
38libperf-y += values.o 41libperf-y += values.o
@@ -77,6 +80,7 @@ libperf-y += data.o
77libperf-y += tsc.o 80libperf-y += tsc.o
78libperf-y += cloexec.o 81libperf-y += cloexec.o
79libperf-y += call-path.o 82libperf-y += call-path.o
83libperf-y += rwsem.o
80libperf-y += thread-stack.o 84libperf-y += thread-stack.o
81libperf-$(CONFIG_AUXTRACE) += auxtrace.o 85libperf-$(CONFIG_AUXTRACE) += auxtrace.o
82libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/ 86libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/
@@ -93,6 +97,7 @@ libperf-y += drv_configs.o
93libperf-y += units.o 97libperf-y += units.o
94libperf-y += time-utils.o 98libperf-y += time-utils.o
95libperf-y += expr-bison.o 99libperf-y += expr-bison.o
100libperf-y += branch.o
96 101
97libperf-$(CONFIG_LIBBPF) += bpf-loader.o 102libperf-$(CONFIG_LIBBPF) += bpf-loader.o
98libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o 103libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
@@ -104,6 +109,10 @@ ifndef CONFIG_LIBELF
104libperf-y += symbol-minimal.o 109libperf-y += symbol-minimal.o
105endif 110endif
106 111
112ifndef CONFIG_SETNS
113libperf-y += setns.o
114endif
115
107libperf-$(CONFIG_DWARF) += probe-finder.o 116libperf-$(CONFIG_DWARF) += probe-finder.o
108libperf-$(CONFIG_DWARF) += dwarf-aux.o 117libperf-$(CONFIG_DWARF) += dwarf-aux.o
109libperf-$(CONFIG_DWARF) += dwarf-regs.o 118libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN
index 39f17507578d..3802cee5e188 100755
--- a/tools/perf/util/PERF-VERSION-GEN
+++ b/tools/perf/util/PERF-VERSION-GEN
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2 3
3if [ $# -eq 1 ] ; then 4if [ $# -eq 1 ] ; then
4 OUTPUT=$1 5 OUTPUT=$1
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index be1caabb9290..da1c4c4a0dd8 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -47,7 +47,11 @@ struct arch {
47 bool sorted_instructions; 47 bool sorted_instructions;
48 bool initialized; 48 bool initialized;
49 void *priv; 49 void *priv;
50 int (*init)(struct arch *arch); 50 unsigned int model;
51 unsigned int family;
52 int (*init)(struct arch *arch, char *cpuid);
53 bool (*ins_is_fused)(struct arch *arch, const char *ins1,
54 const char *ins2);
51 struct { 55 struct {
52 char comment_char; 56 char comment_char;
53 char skip_functions_char; 57 char skip_functions_char;
@@ -127,8 +131,10 @@ static struct arch architectures[] = {
127 }, 131 },
128 { 132 {
129 .name = "x86", 133 .name = "x86",
134 .init = x86__annotate_init,
130 .instructions = x86__instructions, 135 .instructions = x86__instructions,
131 .nr_instructions = ARRAY_SIZE(x86__instructions), 136 .nr_instructions = ARRAY_SIZE(x86__instructions),
137 .ins_is_fused = x86__ins_is_fused,
132 .objdump = { 138 .objdump = {
133 .comment_char = '#', 139 .comment_char = '#',
134 }, 140 },
@@ -171,6 +177,14 @@ int ins__scnprintf(struct ins *ins, char *bf, size_t size,
171 return ins__raw_scnprintf(ins, bf, size, ops); 177 return ins__raw_scnprintf(ins, bf, size, ops);
172} 178}
173 179
180bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
181{
182 if (!arch || !arch->ins_is_fused)
183 return false;
184
185 return arch->ins_is_fused(arch, ins1, ins2);
186}
187
174static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map) 188static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map)
175{ 189{
176 char *endptr, *tok, *name; 190 char *endptr, *tok, *name;
@@ -502,6 +516,11 @@ bool ins__is_ret(const struct ins *ins)
502 return ins->ops == &ret_ops; 516 return ins->ops == &ret_ops;
503} 517}
504 518
519bool ins__is_lock(const struct ins *ins)
520{
521 return ins->ops == &lock_ops;
522}
523
505static int ins__key_cmp(const void *name, const void *insp) 524static int ins__key_cmp(const void *name, const void *insp)
506{ 525{
507 const struct ins *ins = insp; 526 const struct ins *ins = insp;
@@ -586,14 +605,24 @@ static struct arch *arch__find(const char *name)
586int symbol__alloc_hist(struct symbol *sym) 605int symbol__alloc_hist(struct symbol *sym)
587{ 606{
588 struct annotation *notes = symbol__annotation(sym); 607 struct annotation *notes = symbol__annotation(sym);
589 const size_t size = symbol__size(sym); 608 size_t size = symbol__size(sym);
590 size_t sizeof_sym_hist; 609 size_t sizeof_sym_hist;
591 610
611 /*
612 * Add buffer of one element for zero length symbol.
613 * When sample is taken from first instruction of
614 * zero length symbol, perf still resolves it and
615 * shows symbol name in perf report and allows to
616 * annotate it.
617 */
618 if (size == 0)
619 size = 1;
620
592 /* Check for overflow when calculating sizeof_sym_hist */ 621 /* Check for overflow when calculating sizeof_sym_hist */
593 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(u64)) 622 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(struct sym_hist_entry))
594 return -1; 623 return -1;
595 624
596 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64)); 625 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(struct sym_hist_entry));
597 626
598 /* Check for overflow in zalloc argument */ 627 /* Check for overflow in zalloc argument */
599 if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src)) 628 if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src))
@@ -677,7 +706,8 @@ static int __symbol__account_cycles(struct annotation *notes,
677} 706}
678 707
679static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, 708static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
680 struct annotation *notes, int evidx, u64 addr) 709 struct annotation *notes, int evidx, u64 addr,
710 struct perf_sample *sample)
681{ 711{
682 unsigned offset; 712 unsigned offset;
683 struct sym_hist *h; 713 struct sym_hist *h;
@@ -693,12 +723,15 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
693 723
694 offset = addr - sym->start; 724 offset = addr - sym->start;
695 h = annotation__histogram(notes, evidx); 725 h = annotation__histogram(notes, evidx);
696 h->sum++; 726 h->nr_samples++;
697 h->addr[offset]++; 727 h->addr[offset].nr_samples++;
728 h->period += sample->period;
729 h->addr[offset].period += sample->period;
698 730
699 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64 731 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
700 ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name, 732 ", evidx=%d] => nr_samples: %" PRIu64 ", period: %" PRIu64 "\n",
701 addr, addr - sym->start, evidx, h->addr[offset]); 733 sym->start, sym->name, addr, addr - sym->start, evidx,
734 h->addr[offset].nr_samples, h->addr[offset].period);
702 return 0; 735 return 0;
703} 736}
704 737
@@ -718,7 +751,8 @@ static struct annotation *symbol__get_annotation(struct symbol *sym, bool cycles
718} 751}
719 752
720static int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 753static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
721 int evidx, u64 addr) 754 int evidx, u64 addr,
755 struct perf_sample *sample)
722{ 756{
723 struct annotation *notes; 757 struct annotation *notes;
724 758
@@ -727,7 +761,7 @@ static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
727 notes = symbol__get_annotation(sym, false); 761 notes = symbol__get_annotation(sym, false);
728 if (notes == NULL) 762 if (notes == NULL)
729 return -ENOMEM; 763 return -ENOMEM;
730 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr); 764 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr, sample);
731} 765}
732 766
733static int symbol__account_cycles(u64 addr, u64 start, 767static int symbol__account_cycles(u64 addr, u64 start,
@@ -791,14 +825,16 @@ int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
791 return err; 825 return err;
792} 826}
793 827
794int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx) 828int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
829 int evidx)
795{ 830{
796 return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr); 831 return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr, sample);
797} 832}
798 833
799int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip) 834int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
835 int evidx, u64 ip)
800{ 836{
801 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); 837 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip, sample);
802} 838}
803 839
804static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map) 840static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map)
@@ -908,11 +944,12 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa
908} 944}
909 945
910double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset, 946double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
911 s64 end, const char **path, u64 *nr_samples) 947 s64 end, const char **path, struct sym_hist_entry *sample)
912{ 948{
913 struct source_line *src_line = notes->src->lines; 949 struct source_line *src_line = notes->src->lines;
914 double percent = 0.0; 950 double percent = 0.0;
915 *nr_samples = 0; 951
952 sample->nr_samples = sample->period = 0;
916 953
917 if (src_line) { 954 if (src_line) {
918 size_t sizeof_src_line = sizeof(*src_line) + 955 size_t sizeof_src_line = sizeof(*src_line) +
@@ -926,19 +963,24 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
926 *path = src_line->path; 963 *path = src_line->path;
927 964
928 percent += src_line->samples[evidx].percent; 965 percent += src_line->samples[evidx].percent;
929 *nr_samples += src_line->samples[evidx].nr; 966 sample->nr_samples += src_line->samples[evidx].nr;
930 offset++; 967 offset++;
931 } 968 }
932 } else { 969 } else {
933 struct sym_hist *h = annotation__histogram(notes, evidx); 970 struct sym_hist *h = annotation__histogram(notes, evidx);
934 unsigned int hits = 0; 971 unsigned int hits = 0;
972 u64 period = 0;
935 973
936 while (offset < end) 974 while (offset < end) {
937 hits += h->addr[offset++]; 975 hits += h->addr[offset].nr_samples;
976 period += h->addr[offset].period;
977 ++offset;
978 }
938 979
939 if (h->sum) { 980 if (h->nr_samples) {
940 *nr_samples = hits; 981 sample->period = period;
941 percent = 100.0 * hits / h->sum; 982 sample->nr_samples = hits;
983 percent = 100.0 * hits / h->nr_samples;
942 } 984 }
943 } 985 }
944 986
@@ -1037,10 +1079,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1037 1079
1038 if (dl->offset != -1) { 1080 if (dl->offset != -1) {
1039 const char *path = NULL; 1081 const char *path = NULL;
1040 u64 nr_samples;
1041 double percent, max_percent = 0.0; 1082 double percent, max_percent = 0.0;
1042 double *ppercents = &percent; 1083 double *ppercents = &percent;
1043 u64 *psamples = &nr_samples; 1084 struct sym_hist_entry sample;
1085 struct sym_hist_entry *psamples = &sample;
1044 int i, nr_percent = 1; 1086 int i, nr_percent = 1;
1045 const char *color; 1087 const char *color;
1046 struct annotation *notes = symbol__annotation(sym); 1088 struct annotation *notes = symbol__annotation(sym);
@@ -1054,7 +1096,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1054 if (perf_evsel__is_group_event(evsel)) { 1096 if (perf_evsel__is_group_event(evsel)) {
1055 nr_percent = evsel->nr_members; 1097 nr_percent = evsel->nr_members;
1056 ppercents = calloc(nr_percent, sizeof(double)); 1098 ppercents = calloc(nr_percent, sizeof(double));
1057 psamples = calloc(nr_percent, sizeof(u64)); 1099 psamples = calloc(nr_percent, sizeof(struct sym_hist_entry));
1058 if (ppercents == NULL || psamples == NULL) { 1100 if (ppercents == NULL || psamples == NULL) {
1059 return -1; 1101 return -1;
1060 } 1102 }
@@ -1065,10 +1107,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1065 notes->src->lines ? i : evsel->idx + i, 1107 notes->src->lines ? i : evsel->idx + i,
1066 offset, 1108 offset,
1067 next ? next->offset : (s64) len, 1109 next ? next->offset : (s64) len,
1068 &path, &nr_samples); 1110 &path, &sample);
1069 1111
1070 ppercents[i] = percent; 1112 ppercents[i] = percent;
1071 psamples[i] = nr_samples; 1113 psamples[i] = sample;
1072 if (percent > max_percent) 1114 if (percent > max_percent)
1073 max_percent = percent; 1115 max_percent = percent;
1074 } 1116 }
@@ -1106,12 +1148,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1106 1148
1107 for (i = 0; i < nr_percent; i++) { 1149 for (i = 0; i < nr_percent; i++) {
1108 percent = ppercents[i]; 1150 percent = ppercents[i];
1109 nr_samples = psamples[i]; 1151 sample = psamples[i];
1110 color = get_percent_color(percent); 1152 color = get_percent_color(percent);
1111 1153
1112 if (symbol_conf.show_total_period) 1154 if (symbol_conf.show_total_period)
1155 color_fprintf(stdout, color, " %11" PRIu64,
1156 sample.period);
1157 else if (symbol_conf.show_nr_samples)
1113 color_fprintf(stdout, color, " %7" PRIu64, 1158 color_fprintf(stdout, color, " %7" PRIu64,
1114 nr_samples); 1159 sample.nr_samples);
1115 else 1160 else
1116 color_fprintf(stdout, color, " %7.2f", percent); 1161 color_fprintf(stdout, color, " %7.2f", percent);
1117 } 1162 }
@@ -1127,13 +1172,13 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1127 if (ppercents != &percent) 1172 if (ppercents != &percent)
1128 free(ppercents); 1173 free(ppercents);
1129 1174
1130 if (psamples != &nr_samples) 1175 if (psamples != &sample)
1131 free(psamples); 1176 free(psamples);
1132 1177
1133 } else if (max_lines && printed >= max_lines) 1178 } else if (max_lines && printed >= max_lines)
1134 return 1; 1179 return 1;
1135 else { 1180 else {
1136 int width = 8; 1181 int width = symbol_conf.show_total_period ? 12 : 8;
1137 1182
1138 if (queue) 1183 if (queue)
1139 return -1; 1184 return -1;
@@ -1327,7 +1372,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
1327 !dso__is_kcore(dso)) 1372 !dso__is_kcore(dso))
1328 return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX; 1373 return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
1329 1374
1330 build_id_filename = dso__build_id_filename(dso, NULL, 0); 1375 build_id_filename = dso__build_id_filename(dso, NULL, 0, false);
1331 if (build_id_filename) { 1376 if (build_id_filename) {
1332 __symbol__join_symfs(filename, filename_size, build_id_filename); 1377 __symbol__join_symfs(filename, filename_size, build_id_filename);
1333 free(build_id_filename); 1378 free(build_id_filename);
@@ -1381,7 +1426,7 @@ static const char *annotate__norm_arch(const char *arch_name)
1381 1426
1382int symbol__disassemble(struct symbol *sym, struct map *map, 1427int symbol__disassemble(struct symbol *sym, struct map *map,
1383 const char *arch_name, size_t privsize, 1428 const char *arch_name, size_t privsize,
1384 struct arch **parch) 1429 struct arch **parch, char *cpuid)
1385{ 1430{
1386 struct dso *dso = map->dso; 1431 struct dso *dso = map->dso;
1387 char command[PATH_MAX * 2]; 1432 char command[PATH_MAX * 2];
@@ -1411,7 +1456,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map,
1411 *parch = arch; 1456 *parch = arch;
1412 1457
1413 if (arch->init) { 1458 if (arch->init) {
1414 err = arch->init(arch); 1459 err = arch->init(arch, cpuid);
1415 if (err) { 1460 if (err) {
1416 pr_err("%s: failed to initialize %s arch priv area\n", __func__, arch->name); 1461 pr_err("%s: failed to initialize %s arch priv area\n", __func__, arch->name);
1417 return err; 1462 return err;
@@ -1648,19 +1693,19 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1648 struct sym_hist *h = annotation__histogram(notes, evidx); 1693 struct sym_hist *h = annotation__histogram(notes, evidx);
1649 struct rb_root tmp_root = RB_ROOT; 1694 struct rb_root tmp_root = RB_ROOT;
1650 int nr_pcnt = 1; 1695 int nr_pcnt = 1;
1651 u64 h_sum = h->sum; 1696 u64 nr_samples = h->nr_samples;
1652 size_t sizeof_src_line = sizeof(struct source_line); 1697 size_t sizeof_src_line = sizeof(struct source_line);
1653 1698
1654 if (perf_evsel__is_group_event(evsel)) { 1699 if (perf_evsel__is_group_event(evsel)) {
1655 for (i = 1; i < evsel->nr_members; i++) { 1700 for (i = 1; i < evsel->nr_members; i++) {
1656 h = annotation__histogram(notes, evidx + i); 1701 h = annotation__histogram(notes, evidx + i);
1657 h_sum += h->sum; 1702 nr_samples += h->nr_samples;
1658 } 1703 }
1659 nr_pcnt = evsel->nr_members; 1704 nr_pcnt = evsel->nr_members;
1660 sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples); 1705 sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples);
1661 } 1706 }
1662 1707
1663 if (!h_sum) 1708 if (!nr_samples)
1664 return 0; 1709 return 0;
1665 1710
1666 src_line = notes->src->lines = calloc(len, sizeof_src_line); 1711 src_line = notes->src->lines = calloc(len, sizeof_src_line);
@@ -1670,7 +1715,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1670 start = map__rip_2objdump(map, sym->start); 1715 start = map__rip_2objdump(map, sym->start);
1671 1716
1672 for (i = 0; i < len; i++) { 1717 for (i = 0; i < len; i++) {
1673 u64 offset, nr_samples; 1718 u64 offset;
1674 double percent_max = 0.0; 1719 double percent_max = 0.0;
1675 1720
1676 src_line->nr_pcnt = nr_pcnt; 1721 src_line->nr_pcnt = nr_pcnt;
@@ -1679,9 +1724,9 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1679 double percent = 0.0; 1724 double percent = 0.0;
1680 1725
1681 h = annotation__histogram(notes, evidx + k); 1726 h = annotation__histogram(notes, evidx + k);
1682 nr_samples = h->addr[i]; 1727 nr_samples = h->addr[i].nr_samples;
1683 if (h->sum) 1728 if (h->nr_samples)
1684 percent = 100.0 * nr_samples / h->sum; 1729 percent = 100.0 * nr_samples / h->nr_samples;
1685 1730
1686 if (percent > percent_max) 1731 if (percent > percent_max)
1687 percent_max = percent; 1732 percent_max = percent;
@@ -1750,10 +1795,10 @@ static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
1750 u64 len = symbol__size(sym), offset; 1795 u64 len = symbol__size(sym), offset;
1751 1796
1752 for (offset = 0; offset < len; ++offset) 1797 for (offset = 0; offset < len; ++offset)
1753 if (h->addr[offset] != 0) 1798 if (h->addr[offset].nr_samples != 0)
1754 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2, 1799 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
1755 sym->start + offset, h->addr[offset]); 1800 sym->start + offset, h->addr[offset].nr_samples);
1756 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum); 1801 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->nr_samples", h->nr_samples);
1757} 1802}
1758 1803
1759int symbol__annotate_printf(struct symbol *sym, struct map *map, 1804int symbol__annotate_printf(struct symbol *sym, struct map *map,
@@ -1771,7 +1816,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1771 int printed = 2, queue_len = 0; 1816 int printed = 2, queue_len = 0;
1772 int more = 0; 1817 int more = 0;
1773 u64 len; 1818 u64 len;
1774 int width = 8; 1819 int width = symbol_conf.show_total_period ? 12 : 8;
1775 int graph_dotted_len; 1820 int graph_dotted_len;
1776 1821
1777 filename = strdup(dso->long_name); 1822 filename = strdup(dso->long_name);
@@ -1789,7 +1834,9 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1789 width *= evsel->nr_members; 1834 width *= evsel->nr_members;
1790 1835
1791 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n", 1836 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n",
1792 width, width, "Percent", d_filename, evsel_name, h->sum); 1837 width, width, symbol_conf.show_total_period ? "Period" :
1838 symbol_conf.show_nr_samples ? "Samples" : "Percent",
1839 d_filename, evsel_name, h->nr_samples);
1793 1840
1794 printf("%-*.*s----\n", 1841 printf("%-*.*s----\n",
1795 graph_dotted_len, graph_dotted_len, graph_dotted_line); 1842 graph_dotted_len, graph_dotted_len, graph_dotted_line);
@@ -1853,10 +1900,10 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
1853 struct sym_hist *h = annotation__histogram(notes, evidx); 1900 struct sym_hist *h = annotation__histogram(notes, evidx);
1854 int len = symbol__size(sym), offset; 1901 int len = symbol__size(sym), offset;
1855 1902
1856 h->sum = 0; 1903 h->nr_samples = 0;
1857 for (offset = 0; offset < len; ++offset) { 1904 for (offset = 0; offset < len; ++offset) {
1858 h->addr[offset] = h->addr[offset] * 7 / 8; 1905 h->addr[offset].nr_samples = h->addr[offset].nr_samples * 7 / 8;
1859 h->sum += h->addr[offset]; 1906 h->nr_samples += h->addr[offset].nr_samples;
1860 } 1907 }
1861} 1908}
1862 1909
@@ -1907,7 +1954,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1907 u64 len; 1954 u64 len;
1908 1955
1909 if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 1956 if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
1910 0, NULL) < 0) 1957 0, NULL, NULL) < 0)
1911 return -1; 1958 return -1;
1912 1959
1913 len = symbol__size(sym); 1960 len = symbol__size(sym);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 21055034aedd..f6ba3560de5e 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_ANNOTATE_H 2#ifndef __PERF_ANNOTATE_H
2#define __PERF_ANNOTATE_H 3#define __PERF_ANNOTATE_H
3 4
@@ -52,7 +53,9 @@ struct ins_ops {
52bool ins__is_jump(const struct ins *ins); 53bool ins__is_jump(const struct ins *ins);
53bool ins__is_call(const struct ins *ins); 54bool ins__is_call(const struct ins *ins);
54bool ins__is_ret(const struct ins *ins); 55bool ins__is_ret(const struct ins *ins);
56bool ins__is_lock(const struct ins *ins);
55int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops); 57int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops);
58bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);
56 59
57struct annotation; 60struct annotation;
58 61
@@ -72,16 +75,22 @@ static inline bool disasm_line__has_offset(const struct disasm_line *dl)
72 return dl->ops.target.offset_avail; 75 return dl->ops.target.offset_avail;
73} 76}
74 77
78struct sym_hist_entry {
79 u64 nr_samples;
80 u64 period;
81};
82
75void disasm_line__free(struct disasm_line *dl); 83void disasm_line__free(struct disasm_line *dl);
76struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos); 84struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos);
77int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 85int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
78size_t disasm__fprintf(struct list_head *head, FILE *fp); 86size_t disasm__fprintf(struct list_head *head, FILE *fp);
79double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset, 87double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
80 s64 end, const char **path, u64 *nr_samples); 88 s64 end, const char **path, struct sym_hist_entry *sample);
81 89
82struct sym_hist { 90struct sym_hist {
83 u64 sum; 91 u64 nr_samples;
84 u64 addr[0]; 92 u64 period;
93 struct sym_hist_entry addr[0];
85}; 94};
86 95
87struct cyc_hist { 96struct cyc_hist {
@@ -147,20 +156,22 @@ static inline struct annotation *symbol__annotation(struct symbol *sym)
147 return (void *)sym - symbol_conf.priv_size; 156 return (void *)sym - symbol_conf.priv_size;
148} 157}
149 158
150int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx); 159int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
160 int evidx);
151 161
152int addr_map_symbol__account_cycles(struct addr_map_symbol *ams, 162int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
153 struct addr_map_symbol *start, 163 struct addr_map_symbol *start,
154 unsigned cycles); 164 unsigned cycles);
155 165
156int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); 166int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
167 int evidx, u64 addr);
157 168
158int symbol__alloc_hist(struct symbol *sym); 169int symbol__alloc_hist(struct symbol *sym);
159void symbol__annotate_zero_histograms(struct symbol *sym); 170void symbol__annotate_zero_histograms(struct symbol *sym);
160 171
161int symbol__disassemble(struct symbol *sym, struct map *map, 172int symbol__disassemble(struct symbol *sym, struct map *map,
162 const char *arch_name, size_t privsize, 173 const char *arch_name, size_t privsize,
163 struct arch **parch); 174 struct arch **parch, char *cpuid);
164 175
165enum symbol_disassemble_errno { 176enum symbol_disassemble_errno {
166 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, 177 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 5547457566a7..a33491416400 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -208,7 +208,7 @@ static int auxtrace_queues__grow(struct auxtrace_queues *queues,
208 208
209static void *auxtrace_copy_data(u64 size, struct perf_session *session) 209static void *auxtrace_copy_data(u64 size, struct perf_session *session)
210{ 210{
211 int fd = perf_data_file__fd(session->file); 211 int fd = perf_data__fd(session->data);
212 void *p; 212 void *p;
213 ssize_t ret; 213 ssize_t ret;
214 214
@@ -305,7 +305,7 @@ static int auxtrace_queues__add_event_buffer(struct auxtrace_queues *queues,
305 if (session->one_mmap) { 305 if (session->one_mmap) {
306 buffer->data = buffer->data_offset - session->one_mmap_offset + 306 buffer->data = buffer->data_offset - session->one_mmap_offset +
307 session->one_mmap_addr; 307 session->one_mmap_addr;
308 } else if (perf_data_file__is_pipe(session->file)) { 308 } else if (perf_data__is_pipe(session->data)) {
309 buffer->data = auxtrace_copy_data(buffer->size, session); 309 buffer->data = auxtrace_copy_data(buffer->size, session);
310 if (!buffer->data) 310 if (!buffer->data)
311 return -ENOMEM; 311 return -ENOMEM;
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 33b5e6cdf38c..d19e11b68de7 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -378,7 +378,7 @@ struct addr_filters {
378static inline u64 auxtrace_mmap__read_snapshot_head(struct auxtrace_mmap *mm) 378static inline u64 auxtrace_mmap__read_snapshot_head(struct auxtrace_mmap *mm)
379{ 379{
380 struct perf_event_mmap_page *pc = mm->userpg; 380 struct perf_event_mmap_page *pc = mm->userpg;
381 u64 head = ACCESS_ONCE(pc->aux_head); 381 u64 head = READ_ONCE(pc->aux_head);
382 382
383 /* Ensure all reads are done after we read the head */ 383 /* Ensure all reads are done after we read the head */
384 rmb(); 384 rmb();
@@ -389,7 +389,7 @@ static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm)
389{ 389{
390 struct perf_event_mmap_page *pc = mm->userpg; 390 struct perf_event_mmap_page *pc = mm->userpg;
391#if BITS_PER_LONG == 64 || !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT) 391#if BITS_PER_LONG == 64 || !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
392 u64 head = ACCESS_ONCE(pc->aux_head); 392 u64 head = READ_ONCE(pc->aux_head);
393#else 393#else
394 u64 head = __sync_val_compare_and_swap(&pc->aux_head, 0, 0); 394 u64 head = __sync_val_compare_and_swap(&pc->aux_head, 0, 0);
395#endif 395#endif
diff --git a/tools/perf/util/block-range.c b/tools/perf/util/block-range.c
index 7b3e1d75d803..f1451c987eec 100644
--- a/tools/perf/util/block-range.c
+++ b/tools/perf/util/block-range.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "block-range.h" 2#include "block-range.h"
2#include "annotate.h" 3#include "annotate.h"
3 4
diff --git a/tools/perf/util/block-range.h b/tools/perf/util/block-range.h
index a8c841381131..a5ba719d69fb 100644
--- a/tools/perf/util/block-range.h
+++ b/tools/perf/util/block-range.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_BLOCK_RANGE_H 2#ifndef __PERF_BLOCK_RANGE_H
2#define __PERF_BLOCK_RANGE_H 3#define __PERF_BLOCK_RANGE_H
3 4
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 4bd2d1d882af..72c107fcbc5a 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * bpf-loader.c 3 * bpf-loader.c
3 * 4 *
@@ -1246,7 +1247,7 @@ int bpf__config_obj(struct bpf_object *obj,
1246 if (!obj || !term || !term->config) 1247 if (!obj || !term || !term->config)
1247 return -EINVAL; 1248 return -EINVAL;
1248 1249
1249 if (!prefixcmp(term->config, "map:")) { 1250 if (strstarts(term->config, "map:")) {
1250 key_scan_pos = sizeof("map:") - 1; 1251 key_scan_pos = sizeof("map:") - 1;
1251 err = bpf__obj_config_map(obj, term, evlist, &key_scan_pos); 1252 err = bpf__obj_config_map(obj, term, evlist, &key_scan_pos);
1252 goto out; 1253 goto out;
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 48863867878b..5d3aefd6fae7 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Copyright (C) 2015, Wang Nan <wangnan0@huawei.com> 3 * Copyright (C) 2015, Wang Nan <wangnan0@huawei.com>
3 * Copyright (C) 2015, Huawei Inc. 4 * Copyright (C) 2015, Huawei Inc.
diff --git a/tools/perf/util/bpf-prologue.c b/tools/perf/util/bpf-prologue.c
index 1356220a9f1b..29347756b0af 100644
--- a/tools/perf/util/bpf-prologue.c
+++ b/tools/perf/util/bpf-prologue.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * bpf-prologue.c 3 * bpf-prologue.c
3 * 4 *
@@ -58,6 +59,46 @@ check_pos(struct bpf_insn_pos *pos)
58 return 0; 59 return 0;
59} 60}
60 61
62/*
63 * Convert type string (u8/u16/u32/u64/s8/s16/s32/s64 ..., see
64 * Documentation/trace/kprobetrace.txt) to size field of BPF_LDX_MEM
65 * instruction (BPF_{B,H,W,DW}).
66 */
67static int
68argtype_to_ldx_size(const char *type)
69{
70 int arg_size = type ? atoi(&type[1]) : 64;
71
72 switch (arg_size) {
73 case 8:
74 return BPF_B;
75 case 16:
76 return BPF_H;
77 case 32:
78 return BPF_W;
79 case 64:
80 default:
81 return BPF_DW;
82 }
83}
84
85static const char *
86insn_sz_to_str(int insn_sz)
87{
88 switch (insn_sz) {
89 case BPF_B:
90 return "BPF_B";
91 case BPF_H:
92 return "BPF_H";
93 case BPF_W:
94 return "BPF_W";
95 case BPF_DW:
96 return "BPF_DW";
97 default:
98 return "UNKNOWN";
99 }
100}
101
61/* Give it a shorter name */ 102/* Give it a shorter name */
62#define ins(i, p) append_insn((i), (p)) 103#define ins(i, p) append_insn((i), (p))
63 104
@@ -258,9 +299,14 @@ gen_prologue_slowpath(struct bpf_insn_pos *pos,
258 } 299 }
259 300
260 /* Final pass: read to registers */ 301 /* Final pass: read to registers */
261 for (i = 0; i < nargs; i++) 302 for (i = 0; i < nargs; i++) {
262 ins(BPF_LDX_MEM(BPF_DW, BPF_PROLOGUE_START_ARG_REG + i, 303 int insn_sz = (args[i].ref) ? argtype_to_ldx_size(args[i].type) : BPF_DW;
304
305 pr_debug("prologue: load arg %d, insn_sz is %s\n",
306 i, insn_sz_to_str(insn_sz));
307 ins(BPF_LDX_MEM(insn_sz, BPF_PROLOGUE_START_ARG_REG + i,
263 BPF_REG_FP, -BPF_REG_SIZE * (i + 1)), pos); 308 BPF_REG_FP, -BPF_REG_SIZE * (i + 1)), pos);
309 }
264 310
265 ins(BPF_JMP_IMM(BPF_JA, BPF_REG_0, 0, JMP_TO_SUCCESS_CODE), pos); 311 ins(BPF_JMP_IMM(BPF_JA, BPF_REG_0, 0, JMP_TO_SUCCESS_CODE), pos);
266 312
diff --git a/tools/perf/util/bpf-prologue.h b/tools/perf/util/bpf-prologue.h
index ba564838375f..c50c7358009f 100644
--- a/tools/perf/util/bpf-prologue.h
+++ b/tools/perf/util/bpf-prologue.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Copyright (C) 2015, He Kuang <hekuang@huawei.com> 3 * Copyright (C) 2015, He Kuang <hekuang@huawei.com>
3 * Copyright (C) 2015, Huawei Inc. 4 * Copyright (C) 2015, Huawei Inc.
diff --git a/tools/perf/util/branch.c b/tools/perf/util/branch.c
new file mode 100644
index 000000000000..a4fce2729e50
--- /dev/null
+++ b/tools/perf/util/branch.c
@@ -0,0 +1,147 @@
1#include "perf.h"
2#include "util/util.h"
3#include "util/debug.h"
4#include "util/branch.h"
5
6static bool cross_area(u64 addr1, u64 addr2, int size)
7{
8 u64 align1, align2;
9
10 align1 = addr1 & ~(size - 1);
11 align2 = addr2 & ~(size - 1);
12
13 return (align1 != align2) ? true : false;
14}
15
16#define AREA_4K 4096
17#define AREA_2M (2 * 1024 * 1024)
18
19void branch_type_count(struct branch_type_stat *st, struct branch_flags *flags,
20 u64 from, u64 to)
21{
22 if (flags->type == PERF_BR_UNKNOWN || from == 0)
23 return;
24
25 st->counts[flags->type]++;
26
27 if (flags->type == PERF_BR_COND) {
28 if (to > from)
29 st->cond_fwd++;
30 else
31 st->cond_bwd++;
32 }
33
34 if (cross_area(from, to, AREA_2M))
35 st->cross_2m++;
36 else if (cross_area(from, to, AREA_4K))
37 st->cross_4k++;
38}
39
40const char *branch_type_name(int type)
41{
42 const char *branch_names[PERF_BR_MAX] = {
43 "N/A",
44 "COND",
45 "UNCOND",
46 "IND",
47 "CALL",
48 "IND_CALL",
49 "RET",
50 "SYSCALL",
51 "SYSRET",
52 "COND_CALL",
53 "COND_RET"
54 };
55
56 if (type >= 0 && type < PERF_BR_MAX)
57 return branch_names[type];
58
59 return NULL;
60}
61
62void branch_type_stat_display(FILE *fp, struct branch_type_stat *st)
63{
64 u64 total = 0;
65 int i;
66
67 for (i = 0; i < PERF_BR_MAX; i++)
68 total += st->counts[i];
69
70 if (total == 0)
71 return;
72
73 fprintf(fp, "\n#");
74 fprintf(fp, "\n# Branch Statistics:");
75 fprintf(fp, "\n#");
76
77 if (st->cond_fwd > 0) {
78 fprintf(fp, "\n%8s: %5.1f%%",
79 "COND_FWD",
80 100.0 * (double)st->cond_fwd / (double)total);
81 }
82
83 if (st->cond_bwd > 0) {
84 fprintf(fp, "\n%8s: %5.1f%%",
85 "COND_BWD",
86 100.0 * (double)st->cond_bwd / (double)total);
87 }
88
89 if (st->cross_4k > 0) {
90 fprintf(fp, "\n%8s: %5.1f%%",
91 "CROSS_4K",
92 100.0 * (double)st->cross_4k / (double)total);
93 }
94
95 if (st->cross_2m > 0) {
96 fprintf(fp, "\n%8s: %5.1f%%",
97 "CROSS_2M",
98 100.0 * (double)st->cross_2m / (double)total);
99 }
100
101 for (i = 0; i < PERF_BR_MAX; i++) {
102 if (st->counts[i] > 0)
103 fprintf(fp, "\n%8s: %5.1f%%",
104 branch_type_name(i),
105 100.0 *
106 (double)st->counts[i] / (double)total);
107 }
108}
109
110static int count_str_scnprintf(int idx, const char *str, char *bf, int size)
111{
112 return scnprintf(bf, size, "%s%s", (idx) ? " " : " (", str);
113}
114
115int branch_type_str(struct branch_type_stat *st, char *bf, int size)
116{
117 int i, j = 0, printed = 0;
118 u64 total = 0;
119
120 for (i = 0; i < PERF_BR_MAX; i++)
121 total += st->counts[i];
122
123 if (total == 0)
124 return 0;
125
126 if (st->cond_fwd > 0)
127 printed += count_str_scnprintf(j++, "COND_FWD", bf + printed, size - printed);
128
129 if (st->cond_bwd > 0)
130 printed += count_str_scnprintf(j++, "COND_BWD", bf + printed, size - printed);
131
132 for (i = 0; i < PERF_BR_MAX; i++) {
133 if (i == PERF_BR_COND)
134 continue;
135
136 if (st->counts[i] > 0)
137 printed += count_str_scnprintf(j++, branch_type_name(i), bf + printed, size - printed);
138 }
139
140 if (st->cross_4k > 0)
141 printed += count_str_scnprintf(j++, "CROSS_4K", bf + printed, size - printed);
142
143 if (st->cross_2m > 0)
144 printed += count_str_scnprintf(j++, "CROSS_2M", bf + printed, size - printed);
145
146 return printed;
147}
diff --git a/tools/perf/util/branch.h b/tools/perf/util/branch.h
new file mode 100644
index 000000000000..1e3c7c5cdc63
--- /dev/null
+++ b/tools/perf/util/branch.h
@@ -0,0 +1,25 @@
1#ifndef _PERF_BRANCH_H
2#define _PERF_BRANCH_H 1
3
4#include <stdint.h>
5#include "../perf.h"
6
7struct branch_type_stat {
8 bool branch_to;
9 u64 counts[PERF_BR_MAX];
10 u64 cond_fwd;
11 u64 cond_bwd;
12 u64 cross_4k;
13 u64 cross_2m;
14};
15
16struct branch_flags;
17
18void branch_type_count(struct branch_type_stat *st, struct branch_flags *flags,
19 u64 from, u64 to);
20
21const char *branch_type_name(int type);
22void branch_type_stat_display(FILE *fp, struct branch_type_stat *st);
23int branch_type_str(struct branch_type_stat *st, char *bf, int bfsize);
24
25#endif /* _PERF_BRANCH_H */
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index e0148b081bdf..7f8553630c4d 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * build-id.c 3 * build-id.c
3 * 4 *
@@ -243,12 +244,15 @@ static bool build_id_cache__valid_id(char *sbuild_id)
243 return result; 244 return result;
244} 245}
245 246
246static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso) 247static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso,
248 bool is_debug)
247{ 249{
248 return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf"); 250 return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : (is_debug ?
251 "debug" : "elf"));
249} 252}
250 253
251char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) 254char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size,
255 bool is_debug)
252{ 256{
253 bool is_kallsyms = dso__is_kallsyms((struct dso *)dso); 257 bool is_kallsyms = dso__is_kallsyms((struct dso *)dso);
254 bool is_vdso = dso__is_vdso((struct dso *)dso); 258 bool is_vdso = dso__is_vdso((struct dso *)dso);
@@ -270,7 +274,8 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
270 ret = asnprintf(&bf, size, "%s", linkname); 274 ret = asnprintf(&bf, size, "%s", linkname);
271 else 275 else
272 ret = asnprintf(&bf, size, "%s/%s", linkname, 276 ret = asnprintf(&bf, size, "%s/%s", linkname,
273 build_id_cache__basename(is_kallsyms, is_vdso)); 277 build_id_cache__basename(is_kallsyms, is_vdso,
278 is_debug));
274 if (ret < 0 || (!alloc && size < (unsigned int)ret)) 279 if (ret < 0 || (!alloc && size < (unsigned int)ret))
275 bf = NULL; 280 bf = NULL;
276 free(linkname); 281 free(linkname);
@@ -285,7 +290,7 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
285 else 290 else
286 291
287static int write_buildid(const char *name, size_t name_len, u8 *build_id, 292static int write_buildid(const char *name, size_t name_len, u8 *build_id,
288 pid_t pid, u16 misc, int fd) 293 pid_t pid, u16 misc, struct feat_fd *fd)
289{ 294{
290 int err; 295 int err;
291 struct build_id_event b; 296 struct build_id_event b;
@@ -300,14 +305,15 @@ static int write_buildid(const char *name, size_t name_len, u8 *build_id,
300 b.header.misc = misc; 305 b.header.misc = misc;
301 b.header.size = sizeof(b) + len; 306 b.header.size = sizeof(b) + len;
302 307
303 err = writen(fd, &b, sizeof(b)); 308 err = do_write(fd, &b, sizeof(b));
304 if (err < 0) 309 if (err < 0)
305 return err; 310 return err;
306 311
307 return write_padded(fd, name, name_len + 1, len); 312 return write_padded(fd, name, name_len + 1, len);
308} 313}
309 314
310static int machine__write_buildid_table(struct machine *machine, int fd) 315static int machine__write_buildid_table(struct machine *machine,
316 struct feat_fd *fd)
311{ 317{
312 int err = 0; 318 int err = 0;
313 char nm[PATH_MAX]; 319 char nm[PATH_MAX];
@@ -352,7 +358,8 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
352 return err; 358 return err;
353} 359}
354 360
355int perf_session__write_buildid_table(struct perf_session *session, int fd) 361int perf_session__write_buildid_table(struct perf_session *session,
362 struct feat_fd *fd)
356{ 363{
357 struct rb_node *nd; 364 struct rb_node *nd;
358 int err = machine__write_buildid_table(&session->machines.host, fd); 365 int err = machine__write_buildid_table(&session->machines.host, fd);
@@ -534,13 +541,14 @@ char *build_id_cache__complement(const char *incomplete_sbuild_id)
534} 541}
535 542
536char *build_id_cache__cachedir(const char *sbuild_id, const char *name, 543char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
537 bool is_kallsyms, bool is_vdso) 544 struct nsinfo *nsi, bool is_kallsyms,
545 bool is_vdso)
538{ 546{
539 char *realname = (char *)name, *filename; 547 char *realname = (char *)name, *filename;
540 bool slash = is_kallsyms || is_vdso; 548 bool slash = is_kallsyms || is_vdso;
541 549
542 if (!slash) { 550 if (!slash) {
543 realname = realpath(name, NULL); 551 realname = nsinfo__realpath(name, nsi);
544 if (!realname) 552 if (!realname)
545 return NULL; 553 return NULL;
546 } 554 }
@@ -556,13 +564,13 @@ char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
556 return filename; 564 return filename;
557} 565}
558 566
559int build_id_cache__list_build_ids(const char *pathname, 567int build_id_cache__list_build_ids(const char *pathname, struct nsinfo *nsi,
560 struct strlist **result) 568 struct strlist **result)
561{ 569{
562 char *dir_name; 570 char *dir_name;
563 int ret = 0; 571 int ret = 0;
564 572
565 dir_name = build_id_cache__cachedir(NULL, pathname, false, false); 573 dir_name = build_id_cache__cachedir(NULL, pathname, nsi, false, false);
566 if (!dir_name) 574 if (!dir_name)
567 return -ENOMEM; 575 return -ENOMEM;
568 576
@@ -576,16 +584,20 @@ int build_id_cache__list_build_ids(const char *pathname,
576 584
577#if defined(HAVE_LIBELF_SUPPORT) && defined(HAVE_GELF_GETNOTE_SUPPORT) 585#if defined(HAVE_LIBELF_SUPPORT) && defined(HAVE_GELF_GETNOTE_SUPPORT)
578static int build_id_cache__add_sdt_cache(const char *sbuild_id, 586static int build_id_cache__add_sdt_cache(const char *sbuild_id,
579 const char *realname) 587 const char *realname,
588 struct nsinfo *nsi)
580{ 589{
581 struct probe_cache *cache; 590 struct probe_cache *cache;
582 int ret; 591 int ret;
592 struct nscookie nsc;
583 593
584 cache = probe_cache__new(sbuild_id); 594 cache = probe_cache__new(sbuild_id, nsi);
585 if (!cache) 595 if (!cache)
586 return -1; 596 return -1;
587 597
598 nsinfo__mountns_enter(nsi, &nsc);
588 ret = probe_cache__scan_sdt(cache, realname); 599 ret = probe_cache__scan_sdt(cache, realname);
600 nsinfo__mountns_exit(&nsc);
589 if (ret >= 0) { 601 if (ret >= 0) {
590 pr_debug4("Found %d SDTs in %s\n", ret, realname); 602 pr_debug4("Found %d SDTs in %s\n", ret, realname);
591 if (probe_cache__commit(cache) < 0) 603 if (probe_cache__commit(cache) < 0)
@@ -595,25 +607,56 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id,
595 return ret; 607 return ret;
596} 608}
597#else 609#else
598#define build_id_cache__add_sdt_cache(sbuild_id, realname) (0) 610#define build_id_cache__add_sdt_cache(sbuild_id, realname, nsi) (0)
599#endif 611#endif
600 612
613static char *build_id_cache__find_debug(const char *sbuild_id,
614 struct nsinfo *nsi)
615{
616 char *realname = NULL;
617 char *debugfile;
618 struct nscookie nsc;
619 size_t len = 0;
620
621 debugfile = calloc(1, PATH_MAX);
622 if (!debugfile)
623 goto out;
624
625 len = __symbol__join_symfs(debugfile, PATH_MAX,
626 "/usr/lib/debug/.build-id/");
627 snprintf(debugfile + len, PATH_MAX - len, "%.2s/%s.debug", sbuild_id,
628 sbuild_id + 2);
629
630 nsinfo__mountns_enter(nsi, &nsc);
631 realname = realpath(debugfile, NULL);
632 if (realname && access(realname, R_OK))
633 zfree(&realname);
634 nsinfo__mountns_exit(&nsc);
635out:
636 free(debugfile);
637 return realname;
638}
639
601int build_id_cache__add_s(const char *sbuild_id, const char *name, 640int build_id_cache__add_s(const char *sbuild_id, const char *name,
602 bool is_kallsyms, bool is_vdso) 641 struct nsinfo *nsi, bool is_kallsyms, bool is_vdso)
603{ 642{
604 const size_t size = PATH_MAX; 643 const size_t size = PATH_MAX;
605 char *realname = NULL, *filename = NULL, *dir_name = NULL, 644 char *realname = NULL, *filename = NULL, *dir_name = NULL,
606 *linkname = zalloc(size), *tmp; 645 *linkname = zalloc(size), *tmp;
646 char *debugfile = NULL;
607 int err = -1; 647 int err = -1;
608 648
609 if (!is_kallsyms) { 649 if (!is_kallsyms) {
610 realname = realpath(name, NULL); 650 if (!is_vdso)
651 realname = nsinfo__realpath(name, nsi);
652 else
653 realname = realpath(name, NULL);
611 if (!realname) 654 if (!realname)
612 goto out_free; 655 goto out_free;
613 } 656 }
614 657
615 dir_name = build_id_cache__cachedir(sbuild_id, name, 658 dir_name = build_id_cache__cachedir(sbuild_id, name, nsi, is_kallsyms,
616 is_kallsyms, is_vdso); 659 is_vdso);
617 if (!dir_name) 660 if (!dir_name)
618 goto out_free; 661 goto out_free;
619 662
@@ -627,20 +670,52 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
627 670
628 /* Save the allocated buildid dirname */ 671 /* Save the allocated buildid dirname */
629 if (asprintf(&filename, "%s/%s", dir_name, 672 if (asprintf(&filename, "%s/%s", dir_name,
630 build_id_cache__basename(is_kallsyms, is_vdso)) < 0) { 673 build_id_cache__basename(is_kallsyms, is_vdso,
674 false)) < 0) {
631 filename = NULL; 675 filename = NULL;
632 goto out_free; 676 goto out_free;
633 } 677 }
634 678
635 if (access(filename, F_OK)) { 679 if (access(filename, F_OK)) {
636 if (is_kallsyms) { 680 if (is_kallsyms) {
637 if (copyfile("/proc/kallsyms", filename)) 681 if (copyfile("/proc/kallsyms", filename))
682 goto out_free;
683 } else if (nsi && nsi->need_setns) {
684 if (copyfile_ns(name, filename, nsi))
638 goto out_free; 685 goto out_free;
639 } else if (link(realname, filename) && errno != EEXIST && 686 } else if (link(realname, filename) && errno != EEXIST &&
640 copyfile(name, filename)) 687 copyfile(name, filename))
641 goto out_free; 688 goto out_free;
642 } 689 }
643 690
691 /* Some binaries are stripped, but have .debug files with their symbol
692 * table. Check to see if we can locate one of those, since the elf
693 * file itself may not be very useful to users of our tools without a
694 * symtab.
695 */
696 if (!is_kallsyms && !is_vdso &&
697 strncmp(".ko", name + strlen(name) - 3, 3)) {
698 debugfile = build_id_cache__find_debug(sbuild_id, nsi);
699 if (debugfile) {
700 zfree(&filename);
701 if (asprintf(&filename, "%s/%s", dir_name,
702 build_id_cache__basename(false, false, true)) < 0) {
703 filename = NULL;
704 goto out_free;
705 }
706 if (access(filename, F_OK)) {
707 if (nsi && nsi->need_setns) {
708 if (copyfile_ns(debugfile, filename,
709 nsi))
710 goto out_free;
711 } else if (link(debugfile, filename) &&
712 errno != EEXIST &&
713 copyfile(debugfile, filename))
714 goto out_free;
715 }
716 }
717 }
718
644 if (!build_id_cache__linkname(sbuild_id, linkname, size)) 719 if (!build_id_cache__linkname(sbuild_id, linkname, size))
645 goto out_free; 720 goto out_free;
646 tmp = strrchr(linkname, '/'); 721 tmp = strrchr(linkname, '/');
@@ -657,27 +732,30 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
657 err = 0; 732 err = 0;
658 733
659 /* Update SDT cache : error is just warned */ 734 /* Update SDT cache : error is just warned */
660 if (realname && build_id_cache__add_sdt_cache(sbuild_id, realname) < 0) 735 if (realname &&
736 build_id_cache__add_sdt_cache(sbuild_id, realname, nsi) < 0)
661 pr_debug4("Failed to update/scan SDT cache for %s\n", realname); 737 pr_debug4("Failed to update/scan SDT cache for %s\n", realname);
662 738
663out_free: 739out_free:
664 if (!is_kallsyms) 740 if (!is_kallsyms)
665 free(realname); 741 free(realname);
666 free(filename); 742 free(filename);
743 free(debugfile);
667 free(dir_name); 744 free(dir_name);
668 free(linkname); 745 free(linkname);
669 return err; 746 return err;
670} 747}
671 748
672static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, 749static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
673 const char *name, bool is_kallsyms, 750 const char *name, struct nsinfo *nsi,
674 bool is_vdso) 751 bool is_kallsyms, bool is_vdso)
675{ 752{
676 char sbuild_id[SBUILD_ID_SIZE]; 753 char sbuild_id[SBUILD_ID_SIZE];
677 754
678 build_id__sprintf(build_id, build_id_size, sbuild_id); 755 build_id__sprintf(build_id, build_id_size, sbuild_id);
679 756
680 return build_id_cache__add_s(sbuild_id, name, is_kallsyms, is_vdso); 757 return build_id_cache__add_s(sbuild_id, name, nsi, is_kallsyms,
758 is_vdso);
681} 759}
682 760
683bool build_id_cache__cached(const char *sbuild_id) 761bool build_id_cache__cached(const char *sbuild_id)
@@ -743,7 +821,7 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine)
743 name = nm; 821 name = nm;
744 } 822 }
745 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, 823 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
746 is_kallsyms, is_vdso); 824 dso->nsinfo, is_kallsyms, is_vdso);
747} 825}
748 826
749static int __dsos__cache_build_ids(struct list_head *head, 827static int __dsos__cache_build_ids(struct list_head *head,
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 96690a55c62c..f0c565164a97 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PERF_BUILD_ID_H_ 2#ifndef PERF_BUILD_ID_H_
2#define PERF_BUILD_ID_H_ 1 3#define PERF_BUILD_ID_H_ 1
3 4
@@ -5,10 +6,12 @@
5#define SBUILD_ID_SIZE (BUILD_ID_SIZE * 2 + 1) 6#define SBUILD_ID_SIZE (BUILD_ID_SIZE * 2 + 1)
6 7
7#include "tool.h" 8#include "tool.h"
9#include "namespaces.h"
8#include <linux/types.h> 10#include <linux/types.h>
9 11
10extern struct perf_tool build_id__mark_dso_hit_ops; 12extern struct perf_tool build_id__mark_dso_hit_ops;
11struct dso; 13struct dso;
14struct feat_fd;
12 15
13int build_id__sprintf(const u8 *build_id, int len, char *bf); 16int build_id__sprintf(const u8 *build_id, int len, char *bf);
14int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id); 17int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id);
@@ -16,7 +19,8 @@ int filename__sprintf_build_id(const char *pathname, char *sbuild_id);
16char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf, 19char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
17 size_t size); 20 size_t size);
18 21
19char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); 22char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size,
23 bool is_debug);
20 24
21int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, 25int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
22 struct perf_sample *sample, struct perf_evsel *evsel, 26 struct perf_sample *sample, struct perf_evsel *evsel,
@@ -25,23 +29,26 @@ int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
25int dsos__hit_all(struct perf_session *session); 29int dsos__hit_all(struct perf_session *session);
26 30
27bool perf_session__read_build_ids(struct perf_session *session, bool with_hits); 31bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
28int perf_session__write_buildid_table(struct perf_session *session, int fd); 32int perf_session__write_buildid_table(struct perf_session *session,
33 struct feat_fd *fd);
29int perf_session__cache_build_ids(struct perf_session *session); 34int perf_session__cache_build_ids(struct perf_session *session);
30 35
31char *build_id_cache__origname(const char *sbuild_id); 36char *build_id_cache__origname(const char *sbuild_id);
32char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size); 37char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size);
33char *build_id_cache__cachedir(const char *sbuild_id, const char *name, 38char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
34 bool is_kallsyms, bool is_vdso); 39 struct nsinfo *nsi, bool is_kallsyms,
40 bool is_vdso);
35 41
36struct strlist; 42struct strlist;
37 43
38struct strlist *build_id_cache__list_all(bool validonly); 44struct strlist *build_id_cache__list_all(bool validonly);
39char *build_id_cache__complement(const char *incomplete_sbuild_id); 45char *build_id_cache__complement(const char *incomplete_sbuild_id);
40int build_id_cache__list_build_ids(const char *pathname, 46int build_id_cache__list_build_ids(const char *pathname, struct nsinfo *nsi,
41 struct strlist **result); 47 struct strlist **result);
42bool build_id_cache__cached(const char *sbuild_id); 48bool build_id_cache__cached(const char *sbuild_id);
43int build_id_cache__add_s(const char *sbuild_id, 49int build_id_cache__add_s(const char *sbuild_id,
44 const char *name, bool is_kallsyms, bool is_vdso); 50 const char *name, struct nsinfo *nsi,
51 bool is_kallsyms, bool is_vdso);
45int build_id_cache__remove_s(const char *sbuild_id); 52int build_id_cache__remove_s(const char *sbuild_id);
46 53
47extern char buildid_dir[]; 54extern char buildid_dir[];
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index ccafcf72b37a..e513366f2ee0 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PERF_UTIL_CLANG_C_H 2#ifndef PERF_UTIL_CLANG_C_H
2#define PERF_UTIL_CLANG_C_H 3#define PERF_UTIL_CLANG_C_H
3 4
diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
index 9b11e8c82798..a4014d786676 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "clang.h" 2#include "clang.h"
2#include "clang-c.h" 3#include "clang-c.h"
3#include "llvm/IR/Function.h" 4#include "llvm/IR/Function.h"
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 1e974152cac2..1bfc946e37dc 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * llvm C frontend for perf. Support dynamically compile C file 3 * llvm C frontend for perf. Support dynamically compile C file
3 * 4 *
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index dd8b0427550d..6ce33e22f23c 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PERF_UTIL_CLANG_H 2#ifndef PERF_UTIL_CLANG_H
2#define PERF_UTIL_CLANG_H 3#define PERF_UTIL_CLANG_H
3 4
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 0175765c05b9..9f2e36ef5072 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_CACHE_H 2#ifndef __PERF_CACHE_H
2#define __PERF_CACHE_H 3#define __PERF_CACHE_H
3 4
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index b4204b43ed58..082505d08d72 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright (C) 2009-2011, Frederic Weisbecker <fweisbec@gmail.com> 3 * Copyright (C) 2009-2011, Frederic Weisbecker <fweisbec@gmail.com>
3 * 4 *
@@ -23,6 +24,7 @@
23#include "sort.h" 24#include "sort.h"
24#include "machine.h" 25#include "machine.h"
25#include "callchain.h" 26#include "callchain.h"
27#include "branch.h"
26 28
27#define CALLCHAIN_PARAM_DEFAULT \ 29#define CALLCHAIN_PARAM_DEFAULT \
28 .mode = CHAIN_GRAPH_ABS, \ 30 .mode = CHAIN_GRAPH_ABS, \
@@ -64,8 +66,6 @@ static int parse_callchain_mode(const char *value)
64 callchain_param.mode = CHAIN_FOLDED; 66 callchain_param.mode = CHAIN_FOLDED;
65 return 0; 67 return 0;
66 } 68 }
67
68 pr_err("Invalid callchain mode: %s\n", value);
69 return -1; 69 return -1;
70} 70}
71 71
@@ -81,8 +81,6 @@ static int parse_callchain_order(const char *value)
81 callchain_param.order_set = true; 81 callchain_param.order_set = true;
82 return 0; 82 return 0;
83 } 83 }
84
85 pr_err("Invalid callchain order: %s\n", value);
86 return -1; 84 return -1;
87} 85}
88 86
@@ -104,8 +102,6 @@ static int parse_callchain_sort_key(const char *value)
104 callchain_param.branch_callstack = 1; 102 callchain_param.branch_callstack = 1;
105 return 0; 103 return 0;
106 } 104 }
107
108 pr_err("Invalid callchain sort key: %s\n", value);
109 return -1; 105 return -1;
110} 106}
111 107
@@ -123,8 +119,6 @@ static int parse_callchain_value(const char *value)
123 callchain_param.value = CCVAL_COUNT; 119 callchain_param.value = CCVAL_COUNT;
124 return 0; 120 return 0;
125 } 121 }
126
127 pr_err("Invalid callchain config key: %s\n", value);
128 return -1; 122 return -1;
129} 123}
130 124
@@ -303,7 +297,7 @@ int perf_callchain_config(const char *var, const char *value)
303{ 297{
304 char *endptr; 298 char *endptr;
305 299
306 if (prefixcmp(var, "call-graph.")) 300 if (!strstarts(var, "call-graph."))
307 return 0; 301 return 0;
308 var += sizeof("call-graph.") - 1; 302 var += sizeof("call-graph.") - 1;
309 303
@@ -318,12 +312,27 @@ int perf_callchain_config(const char *var, const char *value)
318 312
319 return ret; 313 return ret;
320 } 314 }
321 if (!strcmp(var, "print-type")) 315 if (!strcmp(var, "print-type")){
322 return parse_callchain_mode(value); 316 int ret;
323 if (!strcmp(var, "order")) 317 ret = parse_callchain_mode(value);
324 return parse_callchain_order(value); 318 if (ret == -1)
325 if (!strcmp(var, "sort-key")) 319 pr_err("Invalid callchain mode: %s\n", value);
326 return parse_callchain_sort_key(value); 320 return ret;
321 }
322 if (!strcmp(var, "order")){
323 int ret;
324 ret = parse_callchain_order(value);
325 if (ret == -1)
326 pr_err("Invalid callchain order: %s\n", value);
327 return ret;
328 }
329 if (!strcmp(var, "sort-key")){
330 int ret;
331 ret = parse_callchain_sort_key(value);
332 if (ret == -1)
333 pr_err("Invalid callchain sort key: %s\n", value);
334 return ret;
335 }
327 if (!strcmp(var, "threshold")) { 336 if (!strcmp(var, "threshold")) {
328 callchain_param.min_percent = strtod(value, &endptr); 337 callchain_param.min_percent = strtod(value, &endptr);
329 if (value == endptr) { 338 if (value == endptr) {
@@ -558,19 +567,38 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
558 call->ip = cursor_node->ip; 567 call->ip = cursor_node->ip;
559 call->ms.sym = cursor_node->sym; 568 call->ms.sym = cursor_node->sym;
560 call->ms.map = map__get(cursor_node->map); 569 call->ms.map = map__get(cursor_node->map);
570 call->srcline = cursor_node->srcline;
561 571
562 if (cursor_node->branch) { 572 if (cursor_node->branch) {
563 call->branch_count = 1; 573 call->branch_count = 1;
564 574
565 if (cursor_node->branch_flags.predicted) 575 if (cursor_node->branch_from) {
566 call->predicted_count = 1; 576 /*
567 577 * branch_from is set with value somewhere else
568 if (cursor_node->branch_flags.abort) 578 * to imply it's "to" of a branch.
569 call->abort_count = 1; 579 */
570 580 call->brtype_stat.branch_to = true;
571 call->cycles_count = cursor_node->branch_flags.cycles; 581
572 call->iter_count = cursor_node->nr_loop_iter; 582 if (cursor_node->branch_flags.predicted)
573 call->samples_count = cursor_node->samples; 583 call->predicted_count = 1;
584
585 if (cursor_node->branch_flags.abort)
586 call->abort_count = 1;
587
588 branch_type_count(&call->brtype_stat,
589 &cursor_node->branch_flags,
590 cursor_node->branch_from,
591 cursor_node->ip);
592 } else {
593 /*
594 * It's "from" of a branch
595 */
596 call->brtype_stat.branch_to = false;
597 call->cycles_count =
598 cursor_node->branch_flags.cycles;
599 call->iter_count = cursor_node->nr_loop_iter;
600 call->iter_cycles = cursor_node->iter_cycles;
601 }
574 } 602 }
575 603
576 list_add_tail(&call->list, &node->val); 604 list_add_tail(&call->list, &node->val);
@@ -618,66 +646,97 @@ enum match_result {
618 MATCH_GT, 646 MATCH_GT,
619}; 647};
620 648
621static enum match_result match_chain_srcline(struct callchain_cursor_node *node, 649static enum match_result match_chain_strings(const char *left,
622 struct callchain_list *cnode) 650 const char *right)
623{ 651{
624 char *left = NULL;
625 char *right = NULL;
626 enum match_result ret = MATCH_EQ; 652 enum match_result ret = MATCH_EQ;
627 int cmp; 653 int cmp;
628 654
629 if (cnode->ms.map)
630 left = get_srcline(cnode->ms.map->dso,
631 map__rip_2objdump(cnode->ms.map, cnode->ip),
632 cnode->ms.sym, true, false);
633 if (node->map)
634 right = get_srcline(node->map->dso,
635 map__rip_2objdump(node->map, node->ip),
636 node->sym, true, false);
637
638 if (left && right) 655 if (left && right)
639 cmp = strcmp(left, right); 656 cmp = strcmp(left, right);
640 else if (!left && right) 657 else if (!left && right)
641 cmp = 1; 658 cmp = 1;
642 else if (left && !right) 659 else if (left && !right)
643 cmp = -1; 660 cmp = -1;
644 else if (cnode->ip == node->ip)
645 cmp = 0;
646 else 661 else
647 cmp = (cnode->ip < node->ip) ? -1 : 1; 662 return MATCH_ERROR;
648 663
649 if (cmp != 0) 664 if (cmp != 0)
650 ret = cmp < 0 ? MATCH_LT : MATCH_GT; 665 ret = cmp < 0 ? MATCH_LT : MATCH_GT;
651 666
652 free_srcline(left);
653 free_srcline(right);
654 return ret; 667 return ret;
655} 668}
656 669
670/*
671 * We need to always use relative addresses because we're aggregating
672 * callchains from multiple threads, i.e. different address spaces, so
673 * comparing absolute addresses make no sense as a symbol in a DSO may end up
674 * in a different address when used in a different binary or even the same
675 * binary but with some sort of address randomization technique, thus we need
676 * to compare just relative addresses. -acme
677 */
678static enum match_result match_chain_dso_addresses(struct map *left_map, u64 left_ip,
679 struct map *right_map, u64 right_ip)
680{
681 struct dso *left_dso = left_map ? left_map->dso : NULL;
682 struct dso *right_dso = right_map ? right_map->dso : NULL;
683
684 if (left_dso != right_dso)
685 return left_dso < right_dso ? MATCH_LT : MATCH_GT;
686
687 if (left_ip != right_ip)
688 return left_ip < right_ip ? MATCH_LT : MATCH_GT;
689
690 return MATCH_EQ;
691}
692
657static enum match_result match_chain(struct callchain_cursor_node *node, 693static enum match_result match_chain(struct callchain_cursor_node *node,
658 struct callchain_list *cnode) 694 struct callchain_list *cnode)
659{ 695{
660 struct symbol *sym = node->sym; 696 enum match_result match = MATCH_ERROR;
661 u64 left, right;
662
663 if (callchain_param.key == CCKEY_SRCLINE) {
664 enum match_result match = match_chain_srcline(node, cnode);
665 697
698 switch (callchain_param.key) {
699 case CCKEY_SRCLINE:
700 match = match_chain_strings(cnode->srcline, node->srcline);
666 if (match != MATCH_ERROR) 701 if (match != MATCH_ERROR)
667 return match; 702 break;
703 /* otherwise fall-back to symbol-based comparison below */
704 __fallthrough;
705 case CCKEY_FUNCTION:
706 if (node->sym && cnode->ms.sym) {
707 /*
708 * Compare inlined frames based on their symbol name
709 * because different inlined frames will have the same
710 * symbol start. Otherwise do a faster comparison based
711 * on the symbol start address.
712 */
713 if (cnode->ms.sym->inlined || node->sym->inlined) {
714 match = match_chain_strings(cnode->ms.sym->name,
715 node->sym->name);
716 if (match != MATCH_ERROR)
717 break;
718 } else {
719 match = match_chain_dso_addresses(cnode->ms.map, cnode->ms.sym->start,
720 node->map, node->sym->start);
721 break;
722 }
723 }
724 /* otherwise fall-back to IP-based comparison below */
725 __fallthrough;
726 case CCKEY_ADDRESS:
727 default:
728 match = match_chain_dso_addresses(cnode->ms.map, cnode->ip, node->map, node->ip);
729 break;
668 } 730 }
669 731
670 if (cnode->ms.sym && sym && callchain_param.key == CCKEY_FUNCTION) { 732 if (match == MATCH_EQ && node->branch) {
671 left = cnode->ms.sym->start; 733 cnode->branch_count++;
672 right = sym->start;
673 } else {
674 left = cnode->ip;
675 right = node->ip;
676 }
677 734
678 if (left == right) { 735 if (node->branch_from) {
679 if (node->branch) { 736 /*
680 cnode->branch_count++; 737 * It's "to" of a branch
738 */
739 cnode->brtype_stat.branch_to = true;
681 740
682 if (node->branch_flags.predicted) 741 if (node->branch_flags.predicted)
683 cnode->predicted_count++; 742 cnode->predicted_count++;
@@ -685,15 +744,22 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
685 if (node->branch_flags.abort) 744 if (node->branch_flags.abort)
686 cnode->abort_count++; 745 cnode->abort_count++;
687 746
747 branch_type_count(&cnode->brtype_stat,
748 &node->branch_flags,
749 node->branch_from,
750 node->ip);
751 } else {
752 /*
753 * It's "from" of a branch
754 */
755 cnode->brtype_stat.branch_to = false;
688 cnode->cycles_count += node->branch_flags.cycles; 756 cnode->cycles_count += node->branch_flags.cycles;
689 cnode->iter_count += node->nr_loop_iter; 757 cnode->iter_count += node->nr_loop_iter;
690 cnode->samples_count += node->samples; 758 cnode->iter_cycles += node->iter_cycles;
691 } 759 }
692
693 return MATCH_EQ;
694 } 760 }
695 761
696 return left > right ? MATCH_GT : MATCH_LT; 762 return match;
697} 763}
698 764
699/* 765/*
@@ -922,7 +988,7 @@ merge_chain_branch(struct callchain_cursor *cursor,
922 list_for_each_entry_safe(list, next_list, &src->val, list) { 988 list_for_each_entry_safe(list, next_list, &src->val, list) {
923 callchain_cursor_append(cursor, list->ip, 989 callchain_cursor_append(cursor, list->ip,
924 list->ms.map, list->ms.sym, 990 list->ms.map, list->ms.sym,
925 false, NULL, 0, 0); 991 false, NULL, 0, 0, 0, list->srcline);
926 list_del(&list->list); 992 list_del(&list->list);
927 map__zput(list->ms.map); 993 map__zput(list->ms.map);
928 free(list); 994 free(list);
@@ -962,7 +1028,8 @@ int callchain_merge(struct callchain_cursor *cursor,
962int callchain_cursor_append(struct callchain_cursor *cursor, 1028int callchain_cursor_append(struct callchain_cursor *cursor,
963 u64 ip, struct map *map, struct symbol *sym, 1029 u64 ip, struct map *map, struct symbol *sym,
964 bool branch, struct branch_flags *flags, 1030 bool branch, struct branch_flags *flags,
965 int nr_loop_iter, int samples) 1031 int nr_loop_iter, u64 iter_cycles, u64 branch_from,
1032 const char *srcline)
966{ 1033{
967 struct callchain_cursor_node *node = *cursor->last; 1034 struct callchain_cursor_node *node = *cursor->last;
968 1035
@@ -980,12 +1047,14 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
980 node->sym = sym; 1047 node->sym = sym;
981 node->branch = branch; 1048 node->branch = branch;
982 node->nr_loop_iter = nr_loop_iter; 1049 node->nr_loop_iter = nr_loop_iter;
983 node->samples = samples; 1050 node->iter_cycles = iter_cycles;
1051 node->srcline = srcline;
984 1052
985 if (flags) 1053 if (flags)
986 memcpy(&node->branch_flags, flags, 1054 memcpy(&node->branch_flags, flags,
987 sizeof(struct branch_flags)); 1055 sizeof(struct branch_flags));
988 1056
1057 node->branch_from = branch_from;
989 cursor->nr++; 1058 cursor->nr++;
990 1059
991 cursor->last = &node->next; 1060 cursor->last = &node->next;
@@ -998,11 +1067,11 @@ int sample__resolve_callchain(struct perf_sample *sample,
998 struct perf_evsel *evsel, struct addr_location *al, 1067 struct perf_evsel *evsel, struct addr_location *al,
999 int max_stack) 1068 int max_stack)
1000{ 1069{
1001 if (sample->callchain == NULL) 1070 if (sample->callchain == NULL && !symbol_conf.show_branchflag_count)
1002 return 0; 1071 return 0;
1003 1072
1004 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain || 1073 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
1005 perf_hpp_list.parent) { 1074 perf_hpp_list.parent || symbol_conf.show_branchflag_count) {
1006 return thread__resolve_callchain(al->thread, cursor, evsel, sample, 1075 return thread__resolve_callchain(al->thread, cursor, evsel, sample,
1007 parent, al, max_stack); 1076 parent, al, max_stack);
1008 } 1077 }
@@ -1011,7 +1080,8 @@ int sample__resolve_callchain(struct perf_sample *sample,
1011 1080
1012int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample) 1081int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
1013{ 1082{
1014 if (!symbol_conf.use_callchain || sample->callchain == NULL) 1083 if ((!symbol_conf.use_callchain || sample->callchain == NULL) &&
1084 !symbol_conf.show_branchflag_count)
1015 return 0; 1085 return 0;
1016 return callchain_append(he->callchain, &callchain_cursor, sample->period); 1086 return callchain_append(he->callchain, &callchain_cursor, sample->period);
1017} 1087}
@@ -1021,10 +1091,8 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
1021{ 1091{
1022 al->map = node->map; 1092 al->map = node->map;
1023 al->sym = node->sym; 1093 al->sym = node->sym;
1024 if (node->map) 1094 al->srcline = node->srcline;
1025 al->addr = node->map->map_ip(node->map, node->ip); 1095 al->addr = node->ip;
1026 else
1027 al->addr = node->ip;
1028 1096
1029 if (al->sym == NULL) { 1097 if (al->sym == NULL) {
1030 if (hide_unresolved) 1098 if (hide_unresolved)
@@ -1066,16 +1134,15 @@ char *callchain_list__sym_name(struct callchain_list *cl,
1066 int printed; 1134 int printed;
1067 1135
1068 if (cl->ms.sym) { 1136 if (cl->ms.sym) {
1069 if (show_srcline && cl->ms.map && !cl->srcline) 1137 const char *inlined = cl->ms.sym->inlined ? " (inlined)" : "";
1070 cl->srcline = get_srcline(cl->ms.map->dso, 1138
1071 map__rip_2objdump(cl->ms.map, 1139 if (show_srcline && cl->srcline)
1072 cl->ip), 1140 printed = scnprintf(bf, bfsize, "%s %s%s",
1073 cl->ms.sym, false, show_addr); 1141 cl->ms.sym->name, cl->srcline,
1074 if (cl->srcline) 1142 inlined);
1075 printed = scnprintf(bf, bfsize, "%s %s",
1076 cl->ms.sym->name, cl->srcline);
1077 else 1143 else
1078 printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name); 1144 printed = scnprintf(bf, bfsize, "%s%s",
1145 cl->ms.sym->name, inlined);
1079 } else 1146 } else
1080 printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip); 1147 printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
1081 1148
@@ -1214,95 +1281,124 @@ int callchain_branch_counts(struct callchain_root *root,
1214 cycles_count); 1281 cycles_count);
1215} 1282}
1216 1283
1217static int counts_str_build(char *bf, int bfsize, 1284static int count_pri64_printf(int idx, const char *str, u64 value, char *bf, int bfsize)
1218 u64 branch_count, u64 predicted_count,
1219 u64 abort_count, u64 cycles_count,
1220 u64 iter_count, u64 samples_count)
1221{ 1285{
1222 double predicted_percent = 0.0; 1286 int printed;
1223 const char *null_str = "";
1224 char iter_str[32];
1225 char cycle_str[32];
1226 char *istr, *cstr;
1227 u64 cycles;
1228 1287
1229 if (branch_count == 0) 1288 printed = scnprintf(bf, bfsize, "%s%s:%" PRId64 "", (idx) ? " " : " (", str, value);
1230 return scnprintf(bf, bfsize, " (calltrace)");
1231 1289
1232 cycles = cycles_count / branch_count; 1290 return printed;
1291}
1233 1292
1234 if (iter_count && samples_count) { 1293static int count_float_printf(int idx, const char *str, float value,
1235 if (cycles > 0) 1294 char *bf, int bfsize, float threshold)
1236 scnprintf(iter_str, sizeof(iter_str), 1295{
1237 " iterations:%" PRId64 "", 1296 int printed;
1238 iter_count / samples_count);
1239 else
1240 scnprintf(iter_str, sizeof(iter_str),
1241 "iterations:%" PRId64 "",
1242 iter_count / samples_count);
1243 istr = iter_str;
1244 } else
1245 istr = (char *)null_str;
1246 1297
1247 if (cycles > 0) { 1298 if (threshold != 0.0 && value < threshold)
1248 scnprintf(cycle_str, sizeof(cycle_str), 1299 return 0;
1249 "cycles:%" PRId64 "", cycles);
1250 cstr = cycle_str;
1251 } else
1252 cstr = (char *)null_str;
1253 1300
1254 predicted_percent = predicted_count * 100.0 / branch_count; 1301 printed = scnprintf(bf, bfsize, "%s%s:%.1f%%", (idx) ? " " : " (", str, value);
1255 1302
1256 if ((predicted_count == branch_count) && (abort_count == 0)) { 1303 return printed;
1257 if ((cycles > 0) || (istr != (char *)null_str)) 1304}
1258 return scnprintf(bf, bfsize, " (%s%s)", cstr, istr); 1305
1259 else 1306static int branch_to_str(char *bf, int bfsize,
1260 return scnprintf(bf, bfsize, "%s", (char *)null_str); 1307 u64 branch_count, u64 predicted_count,
1261 } 1308 u64 abort_count,
1262 1309 struct branch_type_stat *brtype_stat)
1263 if ((predicted_count < branch_count) && (abort_count == 0)) { 1310{
1264 if ((cycles > 0) || (istr != (char *)null_str)) 1311 int printed, i = 0;
1265 return scnprintf(bf, bfsize, 1312
1266 " (predicted:%.1f%% %s%s)", 1313 printed = branch_type_str(brtype_stat, bf, bfsize);
1267 predicted_percent, cstr, istr); 1314 if (printed)
1268 else { 1315 i++;
1269 return scnprintf(bf, bfsize, 1316
1270 " (predicted:%.1f%%)", 1317 if (predicted_count < branch_count) {
1271 predicted_percent); 1318 printed += count_float_printf(i++, "predicted",
1272 } 1319 predicted_count * 100.0 / branch_count,
1320 bf + printed, bfsize - printed, 0.0);
1273 } 1321 }
1274 1322
1275 if ((predicted_count == branch_count) && (abort_count > 0)) { 1323 if (abort_count) {
1276 if ((cycles > 0) || (istr != (char *)null_str)) 1324 printed += count_float_printf(i++, "abort",
1277 return scnprintf(bf, bfsize, 1325 abort_count * 100.0 / branch_count,
1278 " (abort:%" PRId64 " %s%s)", 1326 bf + printed, bfsize - printed, 0.1);
1279 abort_count, cstr, istr);
1280 else
1281 return scnprintf(bf, bfsize,
1282 " (abort:%" PRId64 ")",
1283 abort_count);
1284 } 1327 }
1285 1328
1286 if ((cycles > 0) || (istr != (char *)null_str)) 1329 if (i)
1287 return scnprintf(bf, bfsize, 1330 printed += scnprintf(bf + printed, bfsize - printed, ")");
1288 " (predicted:%.1f%% abort:%" PRId64 " %s%s)",
1289 predicted_percent, abort_count, cstr, istr);
1290 1331
1291 return scnprintf(bf, bfsize, 1332 return printed;
1292 " (predicted:%.1f%% abort:%" PRId64 ")", 1333}
1293 predicted_percent, abort_count); 1334
1335static int branch_from_str(char *bf, int bfsize,
1336 u64 branch_count,
1337 u64 cycles_count, u64 iter_count,
1338 u64 iter_cycles)
1339{
1340 int printed = 0, i = 0;
1341 u64 cycles;
1342
1343 cycles = cycles_count / branch_count;
1344 if (cycles) {
1345 printed += count_pri64_printf(i++, "cycles",
1346 cycles,
1347 bf + printed, bfsize - printed);
1348 }
1349
1350 if (iter_count) {
1351 printed += count_pri64_printf(i++, "iter",
1352 iter_count,
1353 bf + printed, bfsize - printed);
1354
1355 printed += count_pri64_printf(i++, "avg_cycles",
1356 iter_cycles / iter_count,
1357 bf + printed, bfsize - printed);
1358 }
1359
1360 if (i)
1361 printed += scnprintf(bf + printed, bfsize - printed, ")");
1362
1363 return printed;
1364}
1365
1366static int counts_str_build(char *bf, int bfsize,
1367 u64 branch_count, u64 predicted_count,
1368 u64 abort_count, u64 cycles_count,
1369 u64 iter_count, u64 iter_cycles,
1370 struct branch_type_stat *brtype_stat)
1371{
1372 int printed;
1373
1374 if (branch_count == 0)
1375 return scnprintf(bf, bfsize, " (calltrace)");
1376
1377 if (brtype_stat->branch_to) {
1378 printed = branch_to_str(bf, bfsize, branch_count,
1379 predicted_count, abort_count, brtype_stat);
1380 } else {
1381 printed = branch_from_str(bf, bfsize, branch_count,
1382 cycles_count, iter_count, iter_cycles);
1383 }
1384
1385 if (!printed)
1386 bf[0] = 0;
1387
1388 return printed;
1294} 1389}
1295 1390
1296static int callchain_counts_printf(FILE *fp, char *bf, int bfsize, 1391static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
1297 u64 branch_count, u64 predicted_count, 1392 u64 branch_count, u64 predicted_count,
1298 u64 abort_count, u64 cycles_count, 1393 u64 abort_count, u64 cycles_count,
1299 u64 iter_count, u64 samples_count) 1394 u64 iter_count, u64 iter_cycles,
1395 struct branch_type_stat *brtype_stat)
1300{ 1396{
1301 char str[128]; 1397 char str[256];
1302 1398
1303 counts_str_build(str, sizeof(str), branch_count, 1399 counts_str_build(str, sizeof(str), branch_count,
1304 predicted_count, abort_count, cycles_count, 1400 predicted_count, abort_count, cycles_count,
1305 iter_count, samples_count); 1401 iter_count, iter_cycles, brtype_stat);
1306 1402
1307 if (fp) 1403 if (fp)
1308 return fprintf(fp, "%s", str); 1404 return fprintf(fp, "%s", str);
@@ -1310,31 +1406,24 @@ static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
1310 return scnprintf(bf, bfsize, "%s", str); 1406 return scnprintf(bf, bfsize, "%s", str);
1311} 1407}
1312 1408
1313int callchain_list_counts__printf_value(struct callchain_node *node, 1409int callchain_list_counts__printf_value(struct callchain_list *clist,
1314 struct callchain_list *clist,
1315 FILE *fp, char *bf, int bfsize) 1410 FILE *fp, char *bf, int bfsize)
1316{ 1411{
1317 u64 branch_count, predicted_count; 1412 u64 branch_count, predicted_count;
1318 u64 abort_count, cycles_count; 1413 u64 abort_count, cycles_count;
1319 u64 iter_count = 0, samples_count = 0; 1414 u64 iter_count, iter_cycles;
1320 1415
1321 branch_count = clist->branch_count; 1416 branch_count = clist->branch_count;
1322 predicted_count = clist->predicted_count; 1417 predicted_count = clist->predicted_count;
1323 abort_count = clist->abort_count; 1418 abort_count = clist->abort_count;
1324 cycles_count = clist->cycles_count; 1419 cycles_count = clist->cycles_count;
1325 1420 iter_count = clist->iter_count;
1326 if (node) { 1421 iter_cycles = clist->iter_cycles;
1327 struct callchain_list *call;
1328
1329 list_for_each_entry(call, &node->val, list) {
1330 iter_count += call->iter_count;
1331 samples_count += call->samples_count;
1332 }
1333 }
1334 1422
1335 return callchain_counts_printf(fp, bf, bfsize, branch_count, 1423 return callchain_counts_printf(fp, bf, bfsize, branch_count,
1336 predicted_count, abort_count, 1424 predicted_count, abort_count,
1337 cycles_count, iter_count, samples_count); 1425 cycles_count, iter_count, iter_cycles,
1426 &clist->brtype_stat);
1338} 1427}
1339 1428
1340static void free_callchain_node(struct callchain_node *node) 1429static void free_callchain_node(struct callchain_node *node)
@@ -1459,7 +1548,9 @@ int callchain_cursor__copy(struct callchain_cursor *dst,
1459 1548
1460 rc = callchain_cursor_append(dst, node->ip, node->map, node->sym, 1549 rc = callchain_cursor_append(dst, node->ip, node->map, node->sym,
1461 node->branch, &node->branch_flags, 1550 node->branch, &node->branch_flags,
1462 node->nr_loop_iter, node->samples); 1551 node->nr_loop_iter,
1552 node->iter_cycles,
1553 node->branch_from, node->srcline);
1463 if (rc) 1554 if (rc)
1464 break; 1555 break;
1465 1556
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index c56c23dbbf72..b79ef2478a57 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_CALLCHAIN_H 2#ifndef __PERF_CALLCHAIN_H
2#define __PERF_CALLCHAIN_H 3#define __PERF_CALLCHAIN_H
3 4
@@ -7,6 +8,7 @@
7#include "event.h" 8#include "event.h"
8#include "map.h" 9#include "map.h"
9#include "symbol.h" 10#include "symbol.h"
11#include "branch.h"
10 12
11#define HELP_PAD "\t\t\t\t" 13#define HELP_PAD "\t\t\t\t"
12 14
@@ -118,8 +120,9 @@ struct callchain_list {
118 u64 abort_count; 120 u64 abort_count;
119 u64 cycles_count; 121 u64 cycles_count;
120 u64 iter_count; 122 u64 iter_count;
121 u64 samples_count; 123 u64 iter_cycles;
122 char *srcline; 124 struct branch_type_stat brtype_stat;
125 const char *srcline;
123 struct list_head list; 126 struct list_head list;
124}; 127};
125 128
@@ -133,10 +136,12 @@ struct callchain_cursor_node {
133 u64 ip; 136 u64 ip;
134 struct map *map; 137 struct map *map;
135 struct symbol *sym; 138 struct symbol *sym;
139 const char *srcline;
136 bool branch; 140 bool branch;
137 struct branch_flags branch_flags; 141 struct branch_flags branch_flags;
142 u64 branch_from;
138 int nr_loop_iter; 143 int nr_loop_iter;
139 int samples; 144 u64 iter_cycles;
140 struct callchain_cursor_node *next; 145 struct callchain_cursor_node *next;
141}; 146};
142 147
@@ -198,7 +203,8 @@ static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
198int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip, 203int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
199 struct map *map, struct symbol *sym, 204 struct map *map, struct symbol *sym,
200 bool branch, struct branch_flags *flags, 205 bool branch, struct branch_flags *flags,
201 int nr_loop_iter, int samples); 206 int nr_loop_iter, u64 iter_cycles, u64 branch_from,
207 const char *srcline);
202 208
203/* Close a cursor writing session. Initialize for the reader */ 209/* Close a cursor writing session. Initialize for the reader */
204static inline void callchain_cursor_commit(struct callchain_cursor *cursor) 210static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
@@ -279,8 +285,7 @@ char *callchain_node__scnprintf_value(struct callchain_node *node,
279int callchain_node__fprintf_value(struct callchain_node *node, 285int callchain_node__fprintf_value(struct callchain_node *node,
280 FILE *fp, u64 total); 286 FILE *fp, u64 total);
281 287
282int callchain_list_counts__printf_value(struct callchain_node *node, 288int callchain_list_counts__printf_value(struct callchain_list *clist,
283 struct callchain_list *clist,
284 FILE *fp, char *bf, int bfsize); 289 FILE *fp, char *bf, int bfsize);
285 290
286void free_callchain(struct callchain_root *root); 291void free_callchain(struct callchain_root *root);
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 03347748f3fa..d9ffc1e6eb39 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "util.h" 2#include "util.h"
2#include "../perf.h" 3#include "../perf.h"
3#include <subcmd/parse-options.h> 4#include <subcmd/parse-options.h>
@@ -98,8 +99,10 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
98 cgrp = counter->cgrp; 99 cgrp = counter->cgrp;
99 if (!cgrp) 100 if (!cgrp)
100 continue; 101 continue;
101 if (!strcmp(cgrp->name, str)) 102 if (!strcmp(cgrp->name, str)) {
103 refcount_inc(&cgrp->refcnt);
102 break; 104 break;
105 }
103 106
104 cgrp = NULL; 107 cgrp = NULL;
105 } 108 }
@@ -110,6 +113,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
110 return -1; 113 return -1;
111 114
112 cgrp->name = str; 115 cgrp->name = str;
116 refcount_set(&cgrp->refcnt, 1);
113 117
114 cgrp->fd = open_cgroup(str); 118 cgrp->fd = open_cgroup(str);
115 if (cgrp->fd == -1) { 119 if (cgrp->fd == -1) {
@@ -128,12 +132,11 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
128 goto found; 132 goto found;
129 n++; 133 n++;
130 } 134 }
131 if (refcount_read(&cgrp->refcnt) == 0) 135 if (refcount_dec_and_test(&cgrp->refcnt))
132 free(cgrp); 136 free(cgrp);
133 137
134 return -1; 138 return -1;
135found: 139found:
136 refcount_inc(&cgrp->refcnt);
137 counter->cgrp = cgrp; 140 counter->cgrp = cgrp;
138 return 0; 141 return 0;
139} 142}
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h
index d91966b97cbd..afafc87e9201 100644
--- a/tools/perf/util/cgroup.h
+++ b/tools/perf/util/cgroup.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __CGROUP_H__ 2#ifndef __CGROUP_H__
2#define __CGROUP_H__ 3#define __CGROUP_H__
3 4
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index 4b4f00df58a8..ca0fff6272be 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <sched.h> 3#include <sched.h>
3#include "util.h" 4#include "util.h"
diff --git a/tools/perf/util/cloexec.h b/tools/perf/util/cloexec.h
index 94a5a7d829d5..78216b1015c4 100644
--- a/tools/perf/util/cloexec.h
+++ b/tools/perf/util/cloexec.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_CLOEXEC_H 2#ifndef __PERF_CLOEXEC_H
2#define __PERF_CLOEXEC_H 3#define __PERF_CLOEXEC_H
3 4
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index dbbf89b050a5..39e628b8938e 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/kernel.h> 2#include <linux/kernel.h>
2#include "cache.h" 3#include "cache.h"
3#include "config.h" 4#include "config.h"
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 52122bcc3170..22777b1812ee 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_COLOR_H 2#ifndef __PERF_COLOR_H
2#define __PERF_COLOR_H 3#define __PERF_COLOR_H
3 4
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index 7bc981b6bf29..7798a2cc8a86 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "comm.h" 2#include "comm.h"
2#include "util.h" 3#include "util.h"
3#include <errno.h> 4#include <errno.h>
@@ -5,6 +6,7 @@
5#include <stdio.h> 6#include <stdio.h>
6#include <string.h> 7#include <string.h>
7#include <linux/refcount.h> 8#include <linux/refcount.h>
9#include "rwsem.h"
8 10
9struct comm_str { 11struct comm_str {
10 char *str; 12 char *str;
@@ -14,6 +16,7 @@ struct comm_str {
14 16
15/* Should perhaps be moved to struct machine */ 17/* Should perhaps be moved to struct machine */
16static struct rb_root comm_str_root; 18static struct rb_root comm_str_root;
19static struct rw_semaphore comm_str_lock = {.lock = PTHREAD_RWLOCK_INITIALIZER,};
17 20
18static struct comm_str *comm_str__get(struct comm_str *cs) 21static struct comm_str *comm_str__get(struct comm_str *cs)
19{ 22{
@@ -25,7 +28,9 @@ static struct comm_str *comm_str__get(struct comm_str *cs)
25static void comm_str__put(struct comm_str *cs) 28static void comm_str__put(struct comm_str *cs)
26{ 29{
27 if (cs && refcount_dec_and_test(&cs->refcnt)) { 30 if (cs && refcount_dec_and_test(&cs->refcnt)) {
31 down_write(&comm_str_lock);
28 rb_erase(&cs->rb_node, &comm_str_root); 32 rb_erase(&cs->rb_node, &comm_str_root);
33 up_write(&comm_str_lock);
29 zfree(&cs->str); 34 zfree(&cs->str);
30 free(cs); 35 free(cs);
31 } 36 }
@@ -50,7 +55,8 @@ static struct comm_str *comm_str__alloc(const char *str)
50 return cs; 55 return cs;
51} 56}
52 57
53static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root) 58static
59struct comm_str *__comm_str__findnew(const char *str, struct rb_root *root)
54{ 60{
55 struct rb_node **p = &root->rb_node; 61 struct rb_node **p = &root->rb_node;
56 struct rb_node *parent = NULL; 62 struct rb_node *parent = NULL;
@@ -81,6 +87,17 @@ static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
81 return new; 87 return new;
82} 88}
83 89
90static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
91{
92 struct comm_str *cs;
93
94 down_write(&comm_str_lock);
95 cs = __comm_str__findnew(str, root);
96 up_write(&comm_str_lock);
97
98 return cs;
99}
100
84struct comm *comm__new(const char *str, u64 timestamp, bool exec) 101struct comm *comm__new(const char *str, u64 timestamp, bool exec)
85{ 102{
86 struct comm *comm = zalloc(sizeof(*comm)); 103 struct comm *comm = zalloc(sizeof(*comm));
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
index 71c9c39340d4..3e5c438fe85e 100644
--- a/tools/perf/util/comm.h
+++ b/tools/perf/util/comm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_COMM_H 2#ifndef __PERF_COMM_H
2#define __PERF_COMM_H 3#define __PERF_COMM_H
3 4
diff --git a/tools/perf/util/compress.h b/tools/perf/util/compress.h
index 67fd1bb7c2b7..ecca688a25fb 100644
--- a/tools/perf/util/compress.h
+++ b/tools/perf/util/compress.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PERF_COMPRESS_H 2#ifndef PERF_COMPRESS_H
2#define PERF_COMPRESS_H 3#define PERF_COMPRESS_H
3 4
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 31a7dea248d0..84eb9393c7db 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * config.c 3 * config.c
3 * 4 *
@@ -19,6 +20,7 @@
19#include <sys/types.h> 20#include <sys/types.h>
20#include <sys/stat.h> 21#include <sys/stat.h>
21#include <unistd.h> 22#include <unistd.h>
23#include <linux/string.h>
22 24
23#include "sane_ctype.h" 25#include "sane_ctype.h"
24 26
@@ -433,22 +435,22 @@ static int perf_ui_config(const char *var, const char *value)
433int perf_default_config(const char *var, const char *value, 435int perf_default_config(const char *var, const char *value,
434 void *dummy __maybe_unused) 436 void *dummy __maybe_unused)
435{ 437{
436 if (!prefixcmp(var, "core.")) 438 if (strstarts(var, "core."))
437 return perf_default_core_config(var, value); 439 return perf_default_core_config(var, value);
438 440
439 if (!prefixcmp(var, "hist.")) 441 if (strstarts(var, "hist."))
440 return perf_hist_config(var, value); 442 return perf_hist_config(var, value);
441 443
442 if (!prefixcmp(var, "ui.")) 444 if (strstarts(var, "ui."))
443 return perf_ui_config(var, value); 445 return perf_ui_config(var, value);
444 446
445 if (!prefixcmp(var, "call-graph.")) 447 if (strstarts(var, "call-graph."))
446 return perf_callchain_config(var, value); 448 return perf_callchain_config(var, value);
447 449
448 if (!prefixcmp(var, "llvm.")) 450 if (strstarts(var, "llvm."))
449 return perf_llvm_config(var, value); 451 return perf_llvm_config(var, value);
450 452
451 if (!prefixcmp(var, "buildid.")) 453 if (strstarts(var, "buildid."))
452 return perf_buildid_config(var, value); 454 return perf_buildid_config(var, value);
453 455
454 /* Add other config variables here. */ 456 /* Add other config variables here. */
@@ -699,10 +701,7 @@ struct perf_config_set *perf_config_set__new(void)
699 701
700 if (set) { 702 if (set) {
701 INIT_LIST_HEAD(&set->sections); 703 INIT_LIST_HEAD(&set->sections);
702 if (perf_config_set__init(set) < 0) { 704 perf_config_set__init(set);
703 perf_config_set__delete(set);
704 set = NULL;
705 }
706 } 705 }
707 706
708 return set; 707 return set;
diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h
index b6bb11f3f165..baf82bf227ac 100644
--- a/tools/perf/util/config.h
+++ b/tools/perf/util/config.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_CONFIG_H 2#ifndef __PERF_CONFIG_H
2#define __PERF_CONFIG_H 3#define __PERF_CONFIG_H
3 4
diff --git a/tools/perf/util/counts.c b/tools/perf/util/counts.c
index c4af82ab7808..03032b410c29 100644
--- a/tools/perf/util/counts.c
+++ b/tools/perf/util/counts.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include "evsel.h" 4#include "evsel.h"
diff --git a/tools/perf/util/counts.h b/tools/perf/util/counts.h
index 34d8baaf558a..0d1050ccc586 100644
--- a/tools/perf/util/counts.h
+++ b/tools/perf/util/counts.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_COUNTS_H 2#ifndef __PERF_COUNTS_H
2#define __PERF_COUNTS_H 3#define __PERF_COUNTS_H
3 4
@@ -12,6 +13,7 @@ struct perf_counts_values {
12 }; 13 };
13 u64 values[3]; 14 u64 values[3];
14 }; 15 };
16 bool loaded;
15}; 17};
16 18
17struct perf_counts { 19struct perf_counts {
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 37b3bb79ee08..1ccbd3342069 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "util.h" 2#include "util.h"
2#include <api/fs/fs.h> 3#include <api/fs/fs.h>
3#include "../perf.h" 4#include "../perf.h"
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 6b8bff87481d..ed8999d1a640 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_CPUMAP_H 2#ifndef __PERF_CPUMAP_H
2#define __PERF_CPUMAP_H 3#define __PERF_CPUMAP_H
3 4
diff --git a/tools/perf/util/ctype.c b/tools/perf/util/ctype.c
index 4b261c2ec0f1..ee4c1e8ed54b 100644
--- a/tools/perf/util/ctype.c
+++ b/tools/perf/util/ctype.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Sane locale-independent, ASCII ctype. 3 * Sane locale-independent, ASCII ctype.
3 * 4 *
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 3149b70799fd..5744c12641a5 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -76,6 +76,8 @@ struct ctf_writer {
76 struct bt_ctf_event_class *comm_class; 76 struct bt_ctf_event_class *comm_class;
77 struct bt_ctf_event_class *exit_class; 77 struct bt_ctf_event_class *exit_class;
78 struct bt_ctf_event_class *fork_class; 78 struct bt_ctf_event_class *fork_class;
79 struct bt_ctf_event_class *mmap_class;
80 struct bt_ctf_event_class *mmap2_class;
79}; 81};
80 82
81struct convert { 83struct convert {
@@ -506,6 +508,81 @@ put_len_type:
506 return ret; 508 return ret;
507} 509}
508 510
511static int
512add_callchain_output_values(struct bt_ctf_event_class *event_class,
513 struct bt_ctf_event *event,
514 struct ip_callchain *callchain)
515{
516 struct bt_ctf_field_type *len_type, *seq_type;
517 struct bt_ctf_field *len_field, *seq_field;
518 unsigned int nr_elements = callchain->nr;
519 unsigned int i;
520 int ret;
521
522 len_type = bt_ctf_event_class_get_field_by_name(
523 event_class, "perf_callchain_size");
524 len_field = bt_ctf_field_create(len_type);
525 if (!len_field) {
526 pr_err("failed to create 'perf_callchain_size' for callchain output event\n");
527 ret = -1;
528 goto put_len_type;
529 }
530
531 ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
532 if (ret) {
533 pr_err("failed to set field value for perf_callchain_size\n");
534 goto put_len_field;
535 }
536 ret = bt_ctf_event_set_payload(event, "perf_callchain_size", len_field);
537 if (ret) {
538 pr_err("failed to set payload to perf_callchain_size\n");
539 goto put_len_field;
540 }
541
542 seq_type = bt_ctf_event_class_get_field_by_name(
543 event_class, "perf_callchain");
544 seq_field = bt_ctf_field_create(seq_type);
545 if (!seq_field) {
546 pr_err("failed to create 'perf_callchain' for callchain output event\n");
547 ret = -1;
548 goto put_seq_type;
549 }
550
551 ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
552 if (ret) {
553 pr_err("failed to set length of 'perf_callchain'\n");
554 goto put_seq_field;
555 }
556
557 for (i = 0; i < nr_elements; i++) {
558 struct bt_ctf_field *elem_field =
559 bt_ctf_field_sequence_get_field(seq_field, i);
560
561 ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
562 ((u64 *)(callchain->ips))[i]);
563
564 bt_ctf_field_put(elem_field);
565 if (ret) {
566 pr_err("failed to set callchain[%d]\n", i);
567 goto put_seq_field;
568 }
569 }
570
571 ret = bt_ctf_event_set_payload(event, "perf_callchain", seq_field);
572 if (ret)
573 pr_err("failed to set payload for raw_data\n");
574
575put_seq_field:
576 bt_ctf_field_put(seq_field);
577put_seq_type:
578 bt_ctf_field_type_put(seq_type);
579put_len_field:
580 bt_ctf_field_put(len_field);
581put_len_type:
582 bt_ctf_field_type_put(len_type);
583 return ret;
584}
585
509static int add_generic_values(struct ctf_writer *cw, 586static int add_generic_values(struct ctf_writer *cw,
510 struct bt_ctf_event *event, 587 struct bt_ctf_event *event,
511 struct perf_evsel *evsel, 588 struct perf_evsel *evsel,
@@ -519,7 +596,6 @@ static int add_generic_values(struct ctf_writer *cw,
519 * PERF_SAMPLE_TIME - not needed as we have it in 596 * PERF_SAMPLE_TIME - not needed as we have it in
520 * ctf event header 597 * ctf event header
521 * PERF_SAMPLE_READ - TODO 598 * PERF_SAMPLE_READ - TODO
522 * PERF_SAMPLE_CALLCHAIN - TODO
523 * PERF_SAMPLE_RAW - tracepoint fields are handled separately 599 * PERF_SAMPLE_RAW - tracepoint fields are handled separately
524 * PERF_SAMPLE_BRANCH_STACK - TODO 600 * PERF_SAMPLE_BRANCH_STACK - TODO
525 * PERF_SAMPLE_REGS_USER - TODO 601 * PERF_SAMPLE_REGS_USER - TODO
@@ -720,6 +796,7 @@ static int process_sample_event(struct perf_tool *tool,
720 struct bt_ctf_event_class *event_class; 796 struct bt_ctf_event_class *event_class;
721 struct bt_ctf_event *event; 797 struct bt_ctf_event *event;
722 int ret; 798 int ret;
799 unsigned long type = evsel->attr.sample_type;
723 800
724 if (WARN_ONCE(!priv, "Failed to setup all events.\n")) 801 if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
725 return 0; 802 return 0;
@@ -751,6 +828,13 @@ static int process_sample_event(struct perf_tool *tool,
751 return -1; 828 return -1;
752 } 829 }
753 830
831 if (type & PERF_SAMPLE_CALLCHAIN) {
832 ret = add_callchain_output_values(event_class,
833 event, sample->callchain);
834 if (ret)
835 return -1;
836 }
837
754 if (perf_evsel__is_bpf_output(evsel)) { 838 if (perf_evsel__is_bpf_output(evsel)) {
755 ret = add_bpf_output_values(event_class, event, sample); 839 ret = add_bpf_output_values(event_class, event, sample);
756 if (ret) 840 if (ret)
@@ -833,6 +917,18 @@ __FUNC_PROCESS_NON_SAMPLE(exit,
833 __NON_SAMPLE_SET_FIELD(fork, u32, ptid); 917 __NON_SAMPLE_SET_FIELD(fork, u32, ptid);
834 __NON_SAMPLE_SET_FIELD(fork, u64, time); 918 __NON_SAMPLE_SET_FIELD(fork, u64, time);
835) 919)
920__FUNC_PROCESS_NON_SAMPLE(mmap,
921 __NON_SAMPLE_SET_FIELD(mmap, u32, pid);
922 __NON_SAMPLE_SET_FIELD(mmap, u32, tid);
923 __NON_SAMPLE_SET_FIELD(mmap, u64_hex, start);
924 __NON_SAMPLE_SET_FIELD(mmap, string, filename);
925)
926__FUNC_PROCESS_NON_SAMPLE(mmap2,
927 __NON_SAMPLE_SET_FIELD(mmap2, u32, pid);
928 __NON_SAMPLE_SET_FIELD(mmap2, u32, tid);
929 __NON_SAMPLE_SET_FIELD(mmap2, u64_hex, start);
930 __NON_SAMPLE_SET_FIELD(mmap2, string, filename);
931)
836#undef __NON_SAMPLE_SET_FIELD 932#undef __NON_SAMPLE_SET_FIELD
837#undef __FUNC_PROCESS_NON_SAMPLE 933#undef __FUNC_PROCESS_NON_SAMPLE
838 934
@@ -1043,6 +1139,14 @@ static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
1043 if (type & PERF_SAMPLE_TRANSACTION) 1139 if (type & PERF_SAMPLE_TRANSACTION)
1044 ADD_FIELD(event_class, cw->data.u64, "perf_transaction"); 1140 ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
1045 1141
1142 if (type & PERF_SAMPLE_CALLCHAIN) {
1143 ADD_FIELD(event_class, cw->data.u32, "perf_callchain_size");
1144 ADD_FIELD(event_class,
1145 bt_ctf_field_type_sequence_create(
1146 cw->data.u64_hex, "perf_callchain_size"),
1147 "perf_callchain");
1148 }
1149
1046#undef ADD_FIELD 1150#undef ADD_FIELD
1047 return 0; 1151 return 0;
1048} 1152}
@@ -1164,6 +1268,19 @@ __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(exit,
1164 __NON_SAMPLE_ADD_FIELD(u64, time); 1268 __NON_SAMPLE_ADD_FIELD(u64, time);
1165) 1269)
1166 1270
1271__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(mmap,
1272 __NON_SAMPLE_ADD_FIELD(u32, pid);
1273 __NON_SAMPLE_ADD_FIELD(u32, tid);
1274 __NON_SAMPLE_ADD_FIELD(u64_hex, start);
1275 __NON_SAMPLE_ADD_FIELD(string, filename);
1276)
1277
1278__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(mmap2,
1279 __NON_SAMPLE_ADD_FIELD(u32, pid);
1280 __NON_SAMPLE_ADD_FIELD(u32, tid);
1281 __NON_SAMPLE_ADD_FIELD(u64_hex, start);
1282 __NON_SAMPLE_ADD_FIELD(string, filename);
1283)
1167#undef __NON_SAMPLE_ADD_FIELD 1284#undef __NON_SAMPLE_ADD_FIELD
1168#undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS 1285#undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS
1169 1286
@@ -1181,6 +1298,12 @@ static int setup_non_sample_events(struct ctf_writer *cw,
1181 ret = add_fork_event(cw); 1298 ret = add_fork_event(cw);
1182 if (ret) 1299 if (ret)
1183 return ret; 1300 return ret;
1301 ret = add_mmap_event(cw);
1302 if (ret)
1303 return ret;
1304 ret = add_mmap2_event(cw);
1305 if (ret)
1306 return ret;
1184 return 0; 1307 return 0;
1185} 1308}
1186 1309
@@ -1454,10 +1577,10 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1454 struct perf_data_convert_opts *opts) 1577 struct perf_data_convert_opts *opts)
1455{ 1578{
1456 struct perf_session *session; 1579 struct perf_session *session;
1457 struct perf_data_file file = { 1580 struct perf_data data = {
1458 .path = input, 1581 .file.path = input,
1459 .mode = PERF_DATA_MODE_READ, 1582 .mode = PERF_DATA_MODE_READ,
1460 .force = opts->force, 1583 .force = opts->force,
1461 }; 1584 };
1462 struct convert c = { 1585 struct convert c = {
1463 .tool = { 1586 .tool = {
@@ -1482,6 +1605,8 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1482 c.tool.comm = process_comm_event; 1605 c.tool.comm = process_comm_event;
1483 c.tool.exit = process_exit_event; 1606 c.tool.exit = process_exit_event;
1484 c.tool.fork = process_fork_event; 1607 c.tool.fork = process_fork_event;
1608 c.tool.mmap = process_mmap_event;
1609 c.tool.mmap2 = process_mmap2_event;
1485 } 1610 }
1486 1611
1487 err = perf_config(convert__config, &c); 1612 err = perf_config(convert__config, &c);
@@ -1494,7 +1619,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1494 1619
1495 err = -1; 1620 err = -1;
1496 /* perf.data session */ 1621 /* perf.data session */
1497 session = perf_session__new(&file, 0, &c.tool); 1622 session = perf_session__new(&data, 0, &c.tool);
1498 if (!session) 1623 if (!session)
1499 goto free_writer; 1624 goto free_writer;
1500 1625
@@ -1525,7 +1650,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1525 1650
1526 fprintf(stderr, 1651 fprintf(stderr,
1527 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n", 1652 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
1528 file.path, path); 1653 data.file.path, path);
1529 1654
1530 fprintf(stderr, 1655 fprintf(stderr,
1531 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples", 1656 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
diff --git a/tools/perf/util/data-convert-bt.h b/tools/perf/util/data-convert-bt.h
index 9a3b587f76c1..821674d63c4e 100644
--- a/tools/perf/util/data-convert-bt.h
+++ b/tools/perf/util/data-convert-bt.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __DATA_CONVERT_BT_H 2#ifndef __DATA_CONVERT_BT_H
2#define __DATA_CONVERT_BT_H 3#define __DATA_CONVERT_BT_H
3#include "data-convert.h" 4#include "data-convert.h"
diff --git a/tools/perf/util/data-convert.h b/tools/perf/util/data-convert.h
index 5314962fe95b..af90b6076c06 100644
--- a/tools/perf/util/data-convert.h
+++ b/tools/perf/util/data-convert.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __DATA_CONVERT_H 2#ifndef __DATA_CONVERT_H
2#define __DATA_CONVERT_H 3#define __DATA_CONVERT_H
3 4
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index e84bbc8ec058..48094fde0a68 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -1,8 +1,10 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include <linux/kernel.h> 3#include <linux/kernel.h>
3#include <sys/types.h> 4#include <sys/types.h>
4#include <sys/stat.h> 5#include <sys/stat.h>
5#include <errno.h> 6#include <errno.h>
7#include <fcntl.h>
6#include <unistd.h> 8#include <unistd.h>
7#include <string.h> 9#include <string.h>
8 10
@@ -10,56 +12,66 @@
10#include "util.h" 12#include "util.h"
11#include "debug.h" 13#include "debug.h"
12 14
13static bool check_pipe(struct perf_data_file *file) 15#ifndef O_CLOEXEC
16#ifdef __sparc__
17#define O_CLOEXEC 0x400000
18#elif defined(__alpha__) || defined(__hppa__)
19#define O_CLOEXEC 010000000
20#else
21#define O_CLOEXEC 02000000
22#endif
23#endif
24
25static bool check_pipe(struct perf_data *data)
14{ 26{
15 struct stat st; 27 struct stat st;
16 bool is_pipe = false; 28 bool is_pipe = false;
17 int fd = perf_data_file__is_read(file) ? 29 int fd = perf_data__is_read(data) ?
18 STDIN_FILENO : STDOUT_FILENO; 30 STDIN_FILENO : STDOUT_FILENO;
19 31
20 if (!file->path) { 32 if (!data->file.path) {
21 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode)) 33 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
22 is_pipe = true; 34 is_pipe = true;
23 } else { 35 } else {
24 if (!strcmp(file->path, "-")) 36 if (!strcmp(data->file.path, "-"))
25 is_pipe = true; 37 is_pipe = true;
26 } 38 }
27 39
28 if (is_pipe) 40 if (is_pipe)
29 file->fd = fd; 41 data->file.fd = fd;
30 42
31 return file->is_pipe = is_pipe; 43 return data->is_pipe = is_pipe;
32} 44}
33 45
34static int check_backup(struct perf_data_file *file) 46static int check_backup(struct perf_data *data)
35{ 47{
36 struct stat st; 48 struct stat st;
37 49
38 if (!stat(file->path, &st) && st.st_size) { 50 if (!stat(data->file.path, &st) && st.st_size) {
39 /* TODO check errors properly */ 51 /* TODO check errors properly */
40 char oldname[PATH_MAX]; 52 char oldname[PATH_MAX];
41 snprintf(oldname, sizeof(oldname), "%s.old", 53 snprintf(oldname, sizeof(oldname), "%s.old",
42 file->path); 54 data->file.path);
43 unlink(oldname); 55 unlink(oldname);
44 rename(file->path, oldname); 56 rename(data->file.path, oldname);
45 } 57 }
46 58
47 return 0; 59 return 0;
48} 60}
49 61
50static int open_file_read(struct perf_data_file *file) 62static int open_file_read(struct perf_data *data)
51{ 63{
52 struct stat st; 64 struct stat st;
53 int fd; 65 int fd;
54 char sbuf[STRERR_BUFSIZE]; 66 char sbuf[STRERR_BUFSIZE];
55 67
56 fd = open(file->path, O_RDONLY); 68 fd = open(data->file.path, O_RDONLY);
57 if (fd < 0) { 69 if (fd < 0) {
58 int err = errno; 70 int err = errno;
59 71
60 pr_err("failed to open %s: %s", file->path, 72 pr_err("failed to open %s: %s", data->file.path,
61 str_error_r(err, sbuf, sizeof(sbuf))); 73 str_error_r(err, sbuf, sizeof(sbuf)));
62 if (err == ENOENT && !strcmp(file->path, "perf.data")) 74 if (err == ENOENT && !strcmp(data->file.path, "perf.data"))
63 pr_err(" (try 'perf record' first)"); 75 pr_err(" (try 'perf record' first)");
64 pr_err("\n"); 76 pr_err("\n");
65 return -err; 77 return -err;
@@ -68,19 +80,19 @@ static int open_file_read(struct perf_data_file *file)
68 if (fstat(fd, &st) < 0) 80 if (fstat(fd, &st) < 0)
69 goto out_close; 81 goto out_close;
70 82
71 if (!file->force && st.st_uid && (st.st_uid != geteuid())) { 83 if (!data->force && st.st_uid && (st.st_uid != geteuid())) {
72 pr_err("File %s not owned by current user or root (use -f to override)\n", 84 pr_err("File %s not owned by current user or root (use -f to override)\n",
73 file->path); 85 data->file.path);
74 goto out_close; 86 goto out_close;
75 } 87 }
76 88
77 if (!st.st_size) { 89 if (!st.st_size) {
78 pr_info("zero-sized file (%s), nothing to do!\n", 90 pr_info("zero-sized data (%s), nothing to do!\n",
79 file->path); 91 data->file.path);
80 goto out_close; 92 goto out_close;
81 } 93 }
82 94
83 file->size = st.st_size; 95 data->size = st.st_size;
84 return fd; 96 return fd;
85 97
86 out_close: 98 out_close:
@@ -88,48 +100,49 @@ static int open_file_read(struct perf_data_file *file)
88 return -1; 100 return -1;
89} 101}
90 102
91static int open_file_write(struct perf_data_file *file) 103static int open_file_write(struct perf_data *data)
92{ 104{
93 int fd; 105 int fd;
94 char sbuf[STRERR_BUFSIZE]; 106 char sbuf[STRERR_BUFSIZE];
95 107
96 if (check_backup(file)) 108 if (check_backup(data))
97 return -1; 109 return -1;
98 110
99 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); 111 fd = open(data->file.path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC,
112 S_IRUSR|S_IWUSR);
100 113
101 if (fd < 0) 114 if (fd < 0)
102 pr_err("failed to open %s : %s\n", file->path, 115 pr_err("failed to open %s : %s\n", data->file.path,
103 str_error_r(errno, sbuf, sizeof(sbuf))); 116 str_error_r(errno, sbuf, sizeof(sbuf)));
104 117
105 return fd; 118 return fd;
106} 119}
107 120
108static int open_file(struct perf_data_file *file) 121static int open_file(struct perf_data *data)
109{ 122{
110 int fd; 123 int fd;
111 124
112 fd = perf_data_file__is_read(file) ? 125 fd = perf_data__is_read(data) ?
113 open_file_read(file) : open_file_write(file); 126 open_file_read(data) : open_file_write(data);
114 127
115 file->fd = fd; 128 data->file.fd = fd;
116 return fd < 0 ? -1 : 0; 129 return fd < 0 ? -1 : 0;
117} 130}
118 131
119int perf_data_file__open(struct perf_data_file *file) 132int perf_data__open(struct perf_data *data)
120{ 133{
121 if (check_pipe(file)) 134 if (check_pipe(data))
122 return 0; 135 return 0;
123 136
124 if (!file->path) 137 if (!data->file.path)
125 file->path = "perf.data"; 138 data->file.path = "perf.data";
126 139
127 return open_file(file); 140 return open_file(data);
128} 141}
129 142
130void perf_data_file__close(struct perf_data_file *file) 143void perf_data__close(struct perf_data *data)
131{ 144{
132 close(file->fd); 145 close(data->file.fd);
133} 146}
134 147
135ssize_t perf_data_file__write(struct perf_data_file *file, 148ssize_t perf_data_file__write(struct perf_data_file *file,
@@ -138,42 +151,48 @@ ssize_t perf_data_file__write(struct perf_data_file *file,
138 return writen(file->fd, buf, size); 151 return writen(file->fd, buf, size);
139} 152}
140 153
141int perf_data_file__switch(struct perf_data_file *file, 154ssize_t perf_data__write(struct perf_data *data,
155 void *buf, size_t size)
156{
157 return perf_data_file__write(&data->file, buf, size);
158}
159
160int perf_data__switch(struct perf_data *data,
142 const char *postfix, 161 const char *postfix,
143 size_t pos, bool at_exit) 162 size_t pos, bool at_exit)
144{ 163{
145 char *new_filepath; 164 char *new_filepath;
146 int ret; 165 int ret;
147 166
148 if (check_pipe(file)) 167 if (check_pipe(data))
149 return -EINVAL; 168 return -EINVAL;
150 if (perf_data_file__is_read(file)) 169 if (perf_data__is_read(data))
151 return -EINVAL; 170 return -EINVAL;
152 171
153 if (asprintf(&new_filepath, "%s.%s", file->path, postfix) < 0) 172 if (asprintf(&new_filepath, "%s.%s", data->file.path, postfix) < 0)
154 return -ENOMEM; 173 return -ENOMEM;
155 174
156 /* 175 /*
157 * Only fire a warning, don't return error, continue fill 176 * Only fire a warning, don't return error, continue fill
158 * original file. 177 * original file.
159 */ 178 */
160 if (rename(file->path, new_filepath)) 179 if (rename(data->file.path, new_filepath))
161 pr_warning("Failed to rename %s to %s\n", file->path, new_filepath); 180 pr_warning("Failed to rename %s to %s\n", data->file.path, new_filepath);
162 181
163 if (!at_exit) { 182 if (!at_exit) {
164 close(file->fd); 183 close(data->file.fd);
165 ret = perf_data_file__open(file); 184 ret = perf_data__open(data);
166 if (ret < 0) 185 if (ret < 0)
167 goto out; 186 goto out;
168 187
169 if (lseek(file->fd, pos, SEEK_SET) == (off_t)-1) { 188 if (lseek(data->file.fd, pos, SEEK_SET) == (off_t)-1) {
170 ret = -errno; 189 ret = -errno;
171 pr_debug("Failed to lseek to %zu: %s", 190 pr_debug("Failed to lseek to %zu: %s",
172 pos, strerror(errno)); 191 pos, strerror(errno));
173 goto out; 192 goto out;
174 } 193 }
175 } 194 }
176 ret = file->fd; 195 ret = data->file.fd;
177out: 196out:
178 free(new_filepath); 197 free(new_filepath);
179 return ret; 198 return ret;
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index ae510ce16cb1..4828f7feea89 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_DATA_H 2#ifndef __PERF_DATA_H
2#define __PERF_DATA_H 3#define __PERF_DATA_H
3 4
@@ -9,51 +10,57 @@ enum perf_data_mode {
9}; 10};
10 11
11struct perf_data_file { 12struct perf_data_file {
12 const char *path; 13 const char *path;
13 int fd; 14 int fd;
15};
16
17struct perf_data {
18 struct perf_data_file file;
14 bool is_pipe; 19 bool is_pipe;
15 bool force; 20 bool force;
16 unsigned long size; 21 unsigned long size;
17 enum perf_data_mode mode; 22 enum perf_data_mode mode;
18}; 23};
19 24
20static inline bool perf_data_file__is_read(struct perf_data_file *file) 25static inline bool perf_data__is_read(struct perf_data *data)
21{ 26{
22 return file->mode == PERF_DATA_MODE_READ; 27 return data->mode == PERF_DATA_MODE_READ;
23} 28}
24 29
25static inline bool perf_data_file__is_write(struct perf_data_file *file) 30static inline bool perf_data__is_write(struct perf_data *data)
26{ 31{
27 return file->mode == PERF_DATA_MODE_WRITE; 32 return data->mode == PERF_DATA_MODE_WRITE;
28} 33}
29 34
30static inline int perf_data_file__is_pipe(struct perf_data_file *file) 35static inline int perf_data__is_pipe(struct perf_data *data)
31{ 36{
32 return file->is_pipe; 37 return data->is_pipe;
33} 38}
34 39
35static inline int perf_data_file__fd(struct perf_data_file *file) 40static inline int perf_data__fd(struct perf_data *data)
36{ 41{
37 return file->fd; 42 return data->file.fd;
38} 43}
39 44
40static inline unsigned long perf_data_file__size(struct perf_data_file *file) 45static inline unsigned long perf_data__size(struct perf_data *data)
41{ 46{
42 return file->size; 47 return data->size;
43} 48}
44 49
45int perf_data_file__open(struct perf_data_file *file); 50int perf_data__open(struct perf_data *data);
46void perf_data_file__close(struct perf_data_file *file); 51void perf_data__close(struct perf_data *data);
52ssize_t perf_data__write(struct perf_data *data,
53 void *buf, size_t size);
47ssize_t perf_data_file__write(struct perf_data_file *file, 54ssize_t perf_data_file__write(struct perf_data_file *file,
48 void *buf, size_t size); 55 void *buf, size_t size);
49/* 56/*
50 * If at_exit is set, only rename current perf.data to 57 * If at_exit is set, only rename current perf.data to
51 * perf.data.<postfix>, continue write on original file. 58 * perf.data.<postfix>, continue write on original data.
52 * Set at_exit when flushing the last output. 59 * Set at_exit when flushing the last output.
53 * 60 *
54 * Return value is fd of new output. 61 * Return value is fd of new output.
55 */ 62 */
56int perf_data_file__switch(struct perf_data_file *file, 63int perf_data__switch(struct perf_data *data,
57 const char *postfix, 64 const char *postfix,
58 size_t pos, bool at_exit); 65 size_t pos, bool at_exit);
59#endif /* __PERF_DATA_H */ 66#endif /* __PERF_DATA_H */
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index a5b3777ffee6..f3a71db83947 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* For general debugging purposes */ 2/* For general debugging purposes */
2 3
3#include "../perf.h" 4#include "../perf.h"
@@ -111,50 +112,53 @@ int dump_printf(const char *fmt, ...)
111 return ret; 112 return ret;
112} 113}
113 114
114static void trace_event_printer(enum binary_printer_ops op, 115static int trace_event_printer(enum binary_printer_ops op,
115 unsigned int val, void *extra) 116 unsigned int val, void *extra, FILE *fp)
116{ 117{
117 const char *color = PERF_COLOR_BLUE; 118 const char *color = PERF_COLOR_BLUE;
118 union perf_event *event = (union perf_event *)extra; 119 union perf_event *event = (union perf_event *)extra;
119 unsigned char ch = (unsigned char)val; 120 unsigned char ch = (unsigned char)val;
121 int printed = 0;
120 122
121 switch (op) { 123 switch (op) {
122 case BINARY_PRINT_DATA_BEGIN: 124 case BINARY_PRINT_DATA_BEGIN:
123 printf("."); 125 printed += fprintf(fp, ".");
124 color_fprintf(stdout, color, "\n. ... raw event: size %d bytes\n", 126 printed += color_fprintf(fp, color, "\n. ... raw event: size %d bytes\n",
125 event->header.size); 127 event->header.size);
126 break; 128 break;
127 case BINARY_PRINT_LINE_BEGIN: 129 case BINARY_PRINT_LINE_BEGIN:
128 printf("."); 130 printed += fprintf(fp, ".");
129 break; 131 break;
130 case BINARY_PRINT_ADDR: 132 case BINARY_PRINT_ADDR:
131 color_fprintf(stdout, color, " %04x: ", val); 133 printed += color_fprintf(fp, color, " %04x: ", val);
132 break; 134 break;
133 case BINARY_PRINT_NUM_DATA: 135 case BINARY_PRINT_NUM_DATA:
134 color_fprintf(stdout, color, " %02x", val); 136 printed += color_fprintf(fp, color, " %02x", val);
135 break; 137 break;
136 case BINARY_PRINT_NUM_PAD: 138 case BINARY_PRINT_NUM_PAD:
137 color_fprintf(stdout, color, " "); 139 printed += color_fprintf(fp, color, " ");
138 break; 140 break;
139 case BINARY_PRINT_SEP: 141 case BINARY_PRINT_SEP:
140 color_fprintf(stdout, color, " "); 142 printed += color_fprintf(fp, color, " ");
141 break; 143 break;
142 case BINARY_PRINT_CHAR_DATA: 144 case BINARY_PRINT_CHAR_DATA:
143 color_fprintf(stdout, color, "%c", 145 printed += color_fprintf(fp, color, "%c",
144 isprint(ch) ? ch : '.'); 146 isprint(ch) ? ch : '.');
145 break; 147 break;
146 case BINARY_PRINT_CHAR_PAD: 148 case BINARY_PRINT_CHAR_PAD:
147 color_fprintf(stdout, color, " "); 149 printed += color_fprintf(fp, color, " ");
148 break; 150 break;
149 case BINARY_PRINT_LINE_END: 151 case BINARY_PRINT_LINE_END:
150 color_fprintf(stdout, color, "\n"); 152 printed += color_fprintf(fp, color, "\n");
151 break; 153 break;
152 case BINARY_PRINT_DATA_END: 154 case BINARY_PRINT_DATA_END:
153 printf("\n"); 155 printed += fprintf(fp, "\n");
154 break; 156 break;
155 default: 157 default:
156 break; 158 break;
157 } 159 }
160
161 return printed;
158} 162}
159 163
160void trace_event(union perf_event *event) 164void trace_event(union perf_event *event)
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index c818bdb1c1ab..77445dfc5c7d 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* For debugging general purposes */ 2/* For debugging general purposes */
2#ifndef __PERF_DEBUG_H 3#ifndef __PERF_DEBUG_H
3#define __PERF_DEBUG_H 4#define __PERF_DEBUG_H
diff --git a/tools/perf/util/demangle-java.c b/tools/perf/util/demangle-java.c
index cb66d334f532..e4c486756053 100644
--- a/tools/perf/util/demangle-java.c
+++ b/tools/perf/util/demangle-java.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/types.h> 2#include <sys/types.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <string.h> 4#include <string.h>
diff --git a/tools/perf/util/demangle-java.h b/tools/perf/util/demangle-java.h
index a981c1f968fe..f936c8eabe5d 100644
--- a/tools/perf/util/demangle-java.h
+++ b/tools/perf/util/demangle-java.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_DEMANGLE_JAVA 2#ifndef __PERF_DEMANGLE_JAVA
2#define __PERF_DEMANGLE_JAVA 1 3#define __PERF_DEMANGLE_JAVA 1
3/* 4/*
diff --git a/tools/perf/util/demangle-rust.c b/tools/perf/util/demangle-rust.c
index f9dafa888c06..423afbbd386b 100644
--- a/tools/perf/util/demangle-rust.c
+++ b/tools/perf/util/demangle-rust.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <string.h> 2#include <string.h>
2#include "util.h" 3#include "util.h"
3#include "debug.h" 4#include "debug.h"
diff --git a/tools/perf/util/demangle-rust.h b/tools/perf/util/demangle-rust.h
index 7b41ead7e0dd..2fca618b1aa5 100644
--- a/tools/perf/util/demangle-rust.h
+++ b/tools/perf/util/demangle-rust.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_DEMANGLE_RUST 2#ifndef __PERF_DEMANGLE_RUST
2#define __PERF_DEMANGLE_RUST 1 3#define __PERF_DEMANGLE_RUST 1
3 4
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 4e7ab611377a..d5b6f7f5baff 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <asm/bug.h> 2#include <asm/bug.h>
2#include <linux/kernel.h> 3#include <linux/kernel.h>
3#include <sys/time.h> 4#include <sys/time.h>
@@ -6,9 +7,11 @@
6#include <sys/stat.h> 7#include <sys/stat.h>
7#include <unistd.h> 8#include <unistd.h>
8#include <errno.h> 9#include <errno.h>
10#include <fcntl.h>
9#include "compress.h" 11#include "compress.h"
10#include "path.h" 12#include "path.h"
11#include "symbol.h" 13#include "symbol.h"
14#include "srcline.h"
12#include "dso.h" 15#include "dso.h"
13#include "machine.h" 16#include "machine.h"
14#include "auxtrace.h" 17#include "auxtrace.h"
@@ -32,6 +35,7 @@ char dso__symtab_origin(const struct dso *dso)
32 [DSO_BINARY_TYPE__JAVA_JIT] = 'j', 35 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
33 [DSO_BINARY_TYPE__DEBUGLINK] = 'l', 36 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
34 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B', 37 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
38 [DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO] = 'D',
35 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f', 39 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
36 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u', 40 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
37 [DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o', 41 [DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o',
@@ -97,7 +101,12 @@ int dso__read_binary_type_filename(const struct dso *dso,
97 break; 101 break;
98 } 102 }
99 case DSO_BINARY_TYPE__BUILD_ID_CACHE: 103 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
100 if (dso__build_id_filename(dso, filename, size) == NULL) 104 if (dso__build_id_filename(dso, filename, size, false) == NULL)
105 ret = -1;
106 break;
107
108 case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
109 if (dso__build_id_filename(dso, filename, size, true) == NULL)
101 ret = -1; 110 ret = -1;
102 break; 111 break;
103 112
@@ -504,7 +513,14 @@ static void check_data_close(void);
504 */ 513 */
505static int open_dso(struct dso *dso, struct machine *machine) 514static int open_dso(struct dso *dso, struct machine *machine)
506{ 515{
507 int fd = __open_dso(dso, machine); 516 int fd;
517 struct nscookie nsc;
518
519 if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
520 nsinfo__mountns_enter(dso->nsinfo, &nsc);
521 fd = __open_dso(dso, machine);
522 if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
523 nsinfo__mountns_exit(&nsc);
508 524
509 if (fd >= 0) { 525 if (fd >= 0) {
510 dso__list_add(dso); 526 dso__list_add(dso);
@@ -1187,6 +1203,8 @@ struct dso *dso__new(const char *name)
1187 for (i = 0; i < MAP__NR_TYPES; ++i) 1203 for (i = 0; i < MAP__NR_TYPES; ++i)
1188 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; 1204 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
1189 dso->data.cache = RB_ROOT; 1205 dso->data.cache = RB_ROOT;
1206 dso->inlined_nodes = RB_ROOT;
1207 dso->srclines = RB_ROOT;
1190 dso->data.fd = -1; 1208 dso->data.fd = -1;
1191 dso->data.status = DSO_DATA_STATUS_UNKNOWN; 1209 dso->data.status = DSO_DATA_STATUS_UNKNOWN;
1192 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; 1210 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
@@ -1218,6 +1236,10 @@ void dso__delete(struct dso *dso)
1218 if (!RB_EMPTY_NODE(&dso->rb_node)) 1236 if (!RB_EMPTY_NODE(&dso->rb_node))
1219 pr_err("DSO %s is still in rbtree when being deleted!\n", 1237 pr_err("DSO %s is still in rbtree when being deleted!\n",
1220 dso->long_name); 1238 dso->long_name);
1239
1240 /* free inlines first, as they reference symbols */
1241 inlines__tree_delete(&dso->inlined_nodes);
1242 srcline__tree_delete(&dso->srclines);
1221 for (i = 0; i < MAP__NR_TYPES; ++i) 1243 for (i = 0; i < MAP__NR_TYPES; ++i)
1222 symbols__delete(&dso->symbols[i]); 1244 symbols__delete(&dso->symbols[i]);
1223 1245
@@ -1236,6 +1258,7 @@ void dso__delete(struct dso *dso)
1236 dso_cache__free(dso); 1258 dso_cache__free(dso);
1237 dso__free_a2l(dso); 1259 dso__free_a2l(dso);
1238 zfree(&dso->symsrc_filename); 1260 zfree(&dso->symsrc_filename);
1261 nsinfo__zput(dso->nsinfo);
1239 pthread_mutex_destroy(&dso->lock); 1262 pthread_mutex_destroy(&dso->lock);
1240 free(dso); 1263 free(dso);
1241} 1264}
@@ -1301,6 +1324,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1301{ 1324{
1302 bool have_build_id = false; 1325 bool have_build_id = false;
1303 struct dso *pos; 1326 struct dso *pos;
1327 struct nscookie nsc;
1304 1328
1305 list_for_each_entry(pos, head, node) { 1329 list_for_each_entry(pos, head, node) {
1306 if (with_hits && !pos->hit && !dso__is_vdso(pos)) 1330 if (with_hits && !pos->hit && !dso__is_vdso(pos))
@@ -1309,11 +1333,13 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1309 have_build_id = true; 1333 have_build_id = true;
1310 continue; 1334 continue;
1311 } 1335 }
1336 nsinfo__mountns_enter(pos->nsinfo, &nsc);
1312 if (filename__read_build_id(pos->long_name, pos->build_id, 1337 if (filename__read_build_id(pos->long_name, pos->build_id,
1313 sizeof(pos->build_id)) > 0) { 1338 sizeof(pos->build_id)) > 0) {
1314 have_build_id = true; 1339 have_build_id = true;
1315 pos->has_build_id = true; 1340 pos->has_build_id = true;
1316 } 1341 }
1342 nsinfo__mountns_exit(&nsc);
1317 } 1343 }
1318 1344
1319 return have_build_id; 1345 return have_build_id;
@@ -1348,9 +1374,9 @@ void __dsos__add(struct dsos *dsos, struct dso *dso)
1348 1374
1349void dsos__add(struct dsos *dsos, struct dso *dso) 1375void dsos__add(struct dsos *dsos, struct dso *dso)
1350{ 1376{
1351 pthread_rwlock_wrlock(&dsos->lock); 1377 down_write(&dsos->lock);
1352 __dsos__add(dsos, dso); 1378 __dsos__add(dsos, dso);
1353 pthread_rwlock_unlock(&dsos->lock); 1379 up_write(&dsos->lock);
1354} 1380}
1355 1381
1356struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short) 1382struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
@@ -1369,9 +1395,9 @@ struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
1369struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short) 1395struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
1370{ 1396{
1371 struct dso *dso; 1397 struct dso *dso;
1372 pthread_rwlock_rdlock(&dsos->lock); 1398 down_read(&dsos->lock);
1373 dso = __dsos__find(dsos, name, cmp_short); 1399 dso = __dsos__find(dsos, name, cmp_short);
1374 pthread_rwlock_unlock(&dsos->lock); 1400 up_read(&dsos->lock);
1375 return dso; 1401 return dso;
1376} 1402}
1377 1403
@@ -1398,9 +1424,9 @@ struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
1398struct dso *dsos__findnew(struct dsos *dsos, const char *name) 1424struct dso *dsos__findnew(struct dsos *dsos, const char *name)
1399{ 1425{
1400 struct dso *dso; 1426 struct dso *dso;
1401 pthread_rwlock_wrlock(&dsos->lock); 1427 down_write(&dsos->lock);
1402 dso = dso__get(__dsos__findnew(dsos, name)); 1428 dso = dso__get(__dsos__findnew(dsos, name));
1403 pthread_rwlock_unlock(&dsos->lock); 1429 up_write(&dsos->lock);
1404 return dso; 1430 return dso;
1405} 1431}
1406 1432
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index bd061ba7b47c..c229dbe0277a 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_DSO 2#ifndef __PERF_DSO
2#define __PERF_DSO 3#define __PERF_DSO
3 4
@@ -6,10 +7,11 @@
6#include <linux/rbtree.h> 7#include <linux/rbtree.h>
7#include <sys/types.h> 8#include <sys/types.h>
8#include <stdbool.h> 9#include <stdbool.h>
9#include <pthread.h> 10#include "rwsem.h"
10#include <linux/types.h> 11#include <linux/types.h>
11#include <linux/bitops.h> 12#include <linux/bitops.h>
12#include "map.h" 13#include "map.h"
14#include "namespaces.h"
13#include "build-id.h" 15#include "build-id.h"
14 16
15enum dso_binary_type { 17enum dso_binary_type {
@@ -20,6 +22,7 @@ enum dso_binary_type {
20 DSO_BINARY_TYPE__JAVA_JIT, 22 DSO_BINARY_TYPE__JAVA_JIT,
21 DSO_BINARY_TYPE__DEBUGLINK, 23 DSO_BINARY_TYPE__DEBUGLINK,
22 DSO_BINARY_TYPE__BUILD_ID_CACHE, 24 DSO_BINARY_TYPE__BUILD_ID_CACHE,
25 DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
23 DSO_BINARY_TYPE__FEDORA_DEBUGINFO, 26 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
24 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO, 27 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
25 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 28 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
@@ -127,7 +130,7 @@ struct dso_cache {
127struct dsos { 130struct dsos {
128 struct list_head head; 131 struct list_head head;
129 struct rb_root root; /* rbtree root sorted by long name */ 132 struct rb_root root; /* rbtree root sorted by long name */
130 pthread_rwlock_t lock; 133 struct rw_semaphore lock;
131}; 134};
132 135
133struct auxtrace_cache; 136struct auxtrace_cache;
@@ -139,6 +142,8 @@ struct dso {
139 struct rb_root *root; /* root of rbtree that rb_node is in */ 142 struct rb_root *root; /* root of rbtree that rb_node is in */
140 struct rb_root symbols[MAP__NR_TYPES]; 143 struct rb_root symbols[MAP__NR_TYPES];
141 struct rb_root symbol_names[MAP__NR_TYPES]; 144 struct rb_root symbol_names[MAP__NR_TYPES];
145 struct rb_root inlined_nodes;
146 struct rb_root srclines;
142 struct { 147 struct {
143 u64 addr; 148 u64 addr;
144 struct symbol *symbol; 149 struct symbol *symbol;
@@ -187,6 +192,7 @@ struct dso {
187 void *priv; 192 void *priv;
188 u64 db_id; 193 u64 db_id;
189 }; 194 };
195 struct nsinfo *nsinfo;
190 refcount_t refcnt; 196 refcount_t refcnt;
191 char name[0]; 197 char name[0];
192}; 198};
diff --git a/tools/perf/util/dump-insn.c b/tools/perf/util/dump-insn.c
index ffbdb19f05d0..10988d3de7ce 100644
--- a/tools/perf/util/dump-insn.c
+++ b/tools/perf/util/dump-insn.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include "dump-insn.h" 3#include "dump-insn.h"
3 4
diff --git a/tools/perf/util/dump-insn.h b/tools/perf/util/dump-insn.h
index 90fb115981cf..0e06280a8860 100644
--- a/tools/perf/util/dump-insn.h
+++ b/tools/perf/util/dump-insn.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_DUMP_INSN_H 2#ifndef __PERF_DUMP_INSN_H
2#define __PERF_DUMP_INSN_H 1 3#define __PERF_DUMP_INSN_H 1
3 4
diff --git a/tools/perf/util/dwarf-regs.c b/tools/perf/util/dwarf-regs.c
index c708395b3cb6..db55eddce8cd 100644
--- a/tools/perf/util/dwarf-regs.c
+++ b/tools/perf/util/dwarf-regs.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * dwarf-regs.c : Mapping of DWARF debug register numbers into register names. 3 * dwarf-regs.c : Mapping of DWARF debug register numbers into register names.
3 * 4 *
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index 9e21538c42ae..6276b340f893 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "cpumap.h" 2#include "cpumap.h"
2#include "env.h" 3#include "env.h"
3#include "util.h" 4#include "util.h"
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index b164dfd2dcbf..1eb35b190b34 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_ENV_H 2#ifndef __PERF_ENV_H
2#define __PERF_ENV_H 3#define __PERF_ENV_H
3 4
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index dc5c3bb69d73..97a8ef9980db 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,5 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <dirent.h> 2#include <dirent.h>
2#include <errno.h> 3#include <errno.h>
4#include <fcntl.h>
3#include <inttypes.h> 5#include <inttypes.h>
4#include <linux/kernel.h> 6#include <linux/kernel.h>
5#include <linux/types.h> 7#include <linux/types.h>
@@ -57,6 +59,7 @@ static const char *perf_event__names[] = {
57 [PERF_RECORD_STAT_ROUND] = "STAT_ROUND", 59 [PERF_RECORD_STAT_ROUND] = "STAT_ROUND",
58 [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", 60 [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE",
59 [PERF_RECORD_TIME_CONV] = "TIME_CONV", 61 [PERF_RECORD_TIME_CONV] = "TIME_CONV",
62 [PERF_RECORD_HEADER_FEATURE] = "FEATURE",
60}; 63};
61 64
62static const char *perf_ns__names[] = { 65static const char *perf_ns__names[] = {
@@ -676,21 +679,21 @@ out:
676 return err; 679 return err;
677} 680}
678 681
679int perf_event__synthesize_threads(struct perf_tool *tool, 682static int __perf_event__synthesize_threads(struct perf_tool *tool,
680 perf_event__handler_t process, 683 perf_event__handler_t process,
681 struct machine *machine, 684 struct machine *machine,
682 bool mmap_data, 685 bool mmap_data,
683 unsigned int proc_map_timeout) 686 unsigned int proc_map_timeout,
687 struct dirent **dirent,
688 int start,
689 int num)
684{ 690{
685 DIR *proc;
686 char proc_path[PATH_MAX];
687 struct dirent *dirent;
688 union perf_event *comm_event, *mmap_event, *fork_event; 691 union perf_event *comm_event, *mmap_event, *fork_event;
689 union perf_event *namespaces_event; 692 union perf_event *namespaces_event;
690 int err = -1; 693 int err = -1;
691 694 char *end;
692 if (machine__is_default_guest(machine)) 695 pid_t pid;
693 return 0; 696 int i;
694 697
695 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size); 698 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
696 if (comm_event == NULL) 699 if (comm_event == NULL)
@@ -710,31 +713,25 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
710 if (namespaces_event == NULL) 713 if (namespaces_event == NULL)
711 goto out_free_fork; 714 goto out_free_fork;
712 715
713 snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir); 716 for (i = start; i < start + num; i++) {
714 proc = opendir(proc_path); 717 if (!isdigit(dirent[i]->d_name[0]))
715 718 continue;
716 if (proc == NULL)
717 goto out_free_namespaces;
718
719 while ((dirent = readdir(proc)) != NULL) {
720 char *end;
721 pid_t pid = strtol(dirent->d_name, &end, 10);
722 719
723 if (*end) /* only interested in proper numerical dirents */ 720 pid = (pid_t)strtol(dirent[i]->d_name, &end, 10);
721 /* only interested in proper numerical dirents */
722 if (*end)
724 continue; 723 continue;
725 /* 724 /*
726 * We may race with exiting thread, so don't stop just because 725 * We may race with exiting thread, so don't stop just because
727 * one thread couldn't be synthesized. 726 * one thread couldn't be synthesized.
728 */ 727 */
729 __event__synthesize_thread(comm_event, mmap_event, fork_event, 728 __event__synthesize_thread(comm_event, mmap_event, fork_event,
730 namespaces_event, pid, 1, process, 729 namespaces_event, pid, 1, process,
731 tool, machine, mmap_data, 730 tool, machine, mmap_data,
732 proc_map_timeout); 731 proc_map_timeout);
733 } 732 }
734
735 err = 0; 733 err = 0;
736 closedir(proc); 734
737out_free_namespaces:
738 free(namespaces_event); 735 free(namespaces_event);
739out_free_fork: 736out_free_fork:
740 free(fork_event); 737 free(fork_event);
@@ -746,6 +743,118 @@ out:
746 return err; 743 return err;
747} 744}
748 745
746struct synthesize_threads_arg {
747 struct perf_tool *tool;
748 perf_event__handler_t process;
749 struct machine *machine;
750 bool mmap_data;
751 unsigned int proc_map_timeout;
752 struct dirent **dirent;
753 int num;
754 int start;
755};
756
757static void *synthesize_threads_worker(void *arg)
758{
759 struct synthesize_threads_arg *args = arg;
760
761 __perf_event__synthesize_threads(args->tool, args->process,
762 args->machine, args->mmap_data,
763 args->proc_map_timeout, args->dirent,
764 args->start, args->num);
765 return NULL;
766}
767
768int perf_event__synthesize_threads(struct perf_tool *tool,
769 perf_event__handler_t process,
770 struct machine *machine,
771 bool mmap_data,
772 unsigned int proc_map_timeout,
773 unsigned int nr_threads_synthesize)
774{
775 struct synthesize_threads_arg *args = NULL;
776 pthread_t *synthesize_threads = NULL;
777 char proc_path[PATH_MAX];
778 struct dirent **dirent;
779 int num_per_thread;
780 int m, n, i, j;
781 int thread_nr;
782 int base = 0;
783 int err = -1;
784
785
786 if (machine__is_default_guest(machine))
787 return 0;
788
789 snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
790 n = scandir(proc_path, &dirent, 0, alphasort);
791 if (n < 0)
792 return err;
793
794 if (nr_threads_synthesize == UINT_MAX)
795 thread_nr = sysconf(_SC_NPROCESSORS_ONLN);
796 else
797 thread_nr = nr_threads_synthesize;
798
799 if (thread_nr <= 1) {
800 err = __perf_event__synthesize_threads(tool, process,
801 machine, mmap_data,
802 proc_map_timeout,
803 dirent, base, n);
804 goto free_dirent;
805 }
806 if (thread_nr > n)
807 thread_nr = n;
808
809 synthesize_threads = calloc(sizeof(pthread_t), thread_nr);
810 if (synthesize_threads == NULL)
811 goto free_dirent;
812
813 args = calloc(sizeof(*args), thread_nr);
814 if (args == NULL)
815 goto free_threads;
816
817 num_per_thread = n / thread_nr;
818 m = n % thread_nr;
819 for (i = 0; i < thread_nr; i++) {
820 args[i].tool = tool;
821 args[i].process = process;
822 args[i].machine = machine;
823 args[i].mmap_data = mmap_data;
824 args[i].proc_map_timeout = proc_map_timeout;
825 args[i].dirent = dirent;
826 }
827 for (i = 0; i < m; i++) {
828 args[i].num = num_per_thread + 1;
829 args[i].start = i * args[i].num;
830 }
831 if (i != 0)
832 base = args[i-1].start + args[i-1].num;
833 for (j = i; j < thread_nr; j++) {
834 args[j].num = num_per_thread;
835 args[j].start = base + (j - i) * args[i].num;
836 }
837
838 for (i = 0; i < thread_nr; i++) {
839 if (pthread_create(&synthesize_threads[i], NULL,
840 synthesize_threads_worker, &args[i]))
841 goto out_join;
842 }
843 err = 0;
844out_join:
845 for (i = 0; i < thread_nr; i++)
846 pthread_join(synthesize_threads[i], NULL);
847 free(args);
848free_threads:
849 free(synthesize_threads);
850free_dirent:
851 for (i = 0; i < n; i++)
852 free(dirent[i]);
853 free(dirent);
854
855 return err;
856}
857
749struct process_symbol_args { 858struct process_symbol_args {
750 const char *name; 859 const char *name;
751 u64 start; 860 u64 start;
@@ -1496,6 +1605,7 @@ int machine__resolve(struct machine *machine, struct addr_location *al,
1496 al->sym = NULL; 1605 al->sym = NULL;
1497 al->cpu = sample->cpu; 1606 al->cpu = sample->cpu;
1498 al->socket = -1; 1607 al->socket = -1;
1608 al->srcline = NULL;
1499 1609
1500 if (al->cpu >= 0) { 1610 if (al->cpu >= 0) {
1501 struct perf_env *env = machine->env; 1611 struct perf_env *env = machine->env;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 9967c87af7a6..1ae95efbfb95 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_RECORD_H 2#ifndef __PERF_RECORD_H
2#define __PERF_RECORD_H 3#define __PERF_RECORD_H
3 4
@@ -142,7 +143,8 @@ struct branch_flags {
142 u64 in_tx:1; 143 u64 in_tx:1;
143 u64 abort:1; 144 u64 abort:1;
144 u64 cycles:16; 145 u64 cycles:16;
145 u64 reserved:44; 146 u64 type:4;
147 u64 reserved:40;
146}; 148};
147 149
148struct branch_entry { 150struct branch_entry {
@@ -199,6 +201,7 @@ struct perf_sample {
199 u32 cpu; 201 u32 cpu;
200 u32 raw_size; 202 u32 raw_size;
201 u64 data_src; 203 u64 data_src;
204 u64 phys_addr;
202 u32 flags; 205 u32 flags;
203 u16 insn_len; 206 u16 insn_len;
204 u8 cpumode; 207 u8 cpumode;
@@ -244,6 +247,7 @@ enum perf_user_event_type { /* above any possible kernel type */
244 PERF_RECORD_STAT_ROUND = 77, 247 PERF_RECORD_STAT_ROUND = 77,
245 PERF_RECORD_EVENT_UPDATE = 78, 248 PERF_RECORD_EVENT_UPDATE = 78,
246 PERF_RECORD_TIME_CONV = 79, 249 PERF_RECORD_TIME_CONV = 79,
250 PERF_RECORD_HEADER_FEATURE = 80,
247 PERF_RECORD_HEADER_MAX 251 PERF_RECORD_HEADER_MAX
248}; 252};
249 253
@@ -609,6 +613,12 @@ struct time_conv_event {
609 u64 time_zero; 613 u64 time_zero;
610}; 614};
611 615
616struct feature_event {
617 struct perf_event_header header;
618 u64 feat_id;
619 char data[];
620};
621
612union perf_event { 622union perf_event {
613 struct perf_event_header header; 623 struct perf_event_header header;
614 struct mmap_event mmap; 624 struct mmap_event mmap;
@@ -639,6 +649,7 @@ union perf_event {
639 struct stat_event stat; 649 struct stat_event stat;
640 struct stat_round_event stat_round; 650 struct stat_round_event stat_round;
641 struct time_conv_event time_conv; 651 struct time_conv_event time_conv;
652 struct feature_event feat;
642}; 653};
643 654
644void perf_event__print_totals(void); 655void perf_event__print_totals(void);
@@ -670,7 +681,8 @@ int perf_event__synthesize_cpu_map(struct perf_tool *tool,
670int perf_event__synthesize_threads(struct perf_tool *tool, 681int perf_event__synthesize_threads(struct perf_tool *tool,
671 perf_event__handler_t process, 682 perf_event__handler_t process,
672 struct machine *machine, bool mmap_data, 683 struct machine *machine, bool mmap_data,
673 unsigned int proc_map_timeout); 684 unsigned int proc_map_timeout,
685 unsigned int nr_threads_synthesize);
674int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, 686int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
675 perf_event__handler_t process, 687 perf_event__handler_t process,
676 struct machine *machine); 688 struct machine *machine);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 46c0faf6c502..c6c891e154a6 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -33,9 +33,6 @@
33#include <linux/log2.h> 33#include <linux/log2.h>
34#include <linux/err.h> 34#include <linux/err.h>
35 35
36static void perf_mmap__munmap(struct perf_mmap *map);
37static void perf_mmap__put(struct perf_mmap *map);
38
39#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 36#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
40#define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 37#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
41 38
@@ -242,9 +239,9 @@ void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr)
242 } 239 }
243} 240}
244 241
245int perf_evlist__add_default(struct perf_evlist *evlist) 242int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise)
246{ 243{
247 struct perf_evsel *evsel = perf_evsel__new_cycles(); 244 struct perf_evsel *evsel = perf_evsel__new_cycles(precise);
248 245
249 if (evsel == NULL) 246 if (evsel == NULL)
250 return -ENOMEM; 247 return -ENOMEM;
@@ -704,129 +701,6 @@ static int perf_evlist__resume(struct perf_evlist *evlist)
704 return perf_evlist__set_paused(evlist, false); 701 return perf_evlist__set_paused(evlist, false);
705} 702}
706 703
707/* When check_messup is true, 'end' must points to a good entry */
708static union perf_event *
709perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start,
710 u64 end, u64 *prev)
711{
712 unsigned char *data = md->base + page_size;
713 union perf_event *event = NULL;
714 int diff = end - start;
715
716 if (check_messup) {
717 /*
718 * If we're further behind than half the buffer, there's a chance
719 * the writer will bite our tail and mess up the samples under us.
720 *
721 * If we somehow ended up ahead of the 'end', we got messed up.
722 *
723 * In either case, truncate and restart at 'end'.
724 */
725 if (diff > md->mask / 2 || diff < 0) {
726 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
727
728 /*
729 * 'end' points to a known good entry, start there.
730 */
731 start = end;
732 diff = 0;
733 }
734 }
735
736 if (diff >= (int)sizeof(event->header)) {
737 size_t size;
738
739 event = (union perf_event *)&data[start & md->mask];
740 size = event->header.size;
741
742 if (size < sizeof(event->header) || diff < (int)size) {
743 event = NULL;
744 goto broken_event;
745 }
746
747 /*
748 * Event straddles the mmap boundary -- header should always
749 * be inside due to u64 alignment of output.
750 */
751 if ((start & md->mask) + size != ((start + size) & md->mask)) {
752 unsigned int offset = start;
753 unsigned int len = min(sizeof(*event), size), cpy;
754 void *dst = md->event_copy;
755
756 do {
757 cpy = min(md->mask + 1 - (offset & md->mask), len);
758 memcpy(dst, &data[offset & md->mask], cpy);
759 offset += cpy;
760 dst += cpy;
761 len -= cpy;
762 } while (len);
763
764 event = (union perf_event *) md->event_copy;
765 }
766
767 start += size;
768 }
769
770broken_event:
771 if (prev)
772 *prev = start;
773
774 return event;
775}
776
777union perf_event *perf_mmap__read_forward(struct perf_mmap *md, bool check_messup)
778{
779 u64 head;
780 u64 old = md->prev;
781
782 /*
783 * Check if event was unmapped due to a POLLHUP/POLLERR.
784 */
785 if (!refcount_read(&md->refcnt))
786 return NULL;
787
788 head = perf_mmap__read_head(md);
789
790 return perf_mmap__read(md, check_messup, old, head, &md->prev);
791}
792
793union perf_event *
794perf_mmap__read_backward(struct perf_mmap *md)
795{
796 u64 head, end;
797 u64 start = md->prev;
798
799 /*
800 * Check if event was unmapped due to a POLLHUP/POLLERR.
801 */
802 if (!refcount_read(&md->refcnt))
803 return NULL;
804
805 head = perf_mmap__read_head(md);
806 if (!head)
807 return NULL;
808
809 /*
810 * 'head' pointer starts from 0. Kernel minus sizeof(record) form
811 * it each time when kernel writes to it, so in fact 'head' is
812 * negative. 'end' pointer is made manually by adding the size of
813 * the ring buffer to 'head' pointer, means the validate data can
814 * read is the whole ring buffer. If 'end' is positive, the ring
815 * buffer has not fully filled, so we must adjust 'end' to 0.
816 *
817 * However, since both 'head' and 'end' is unsigned, we can't
818 * simply compare 'end' against 0. Here we compare '-head' and
819 * the size of the ring buffer, where -head is the number of bytes
820 * kernel write to the ring buffer.
821 */
822 if (-head < (u64)(md->mask + 1))
823 end = 0;
824 else
825 end = head + md->mask + 1;
826
827 return perf_mmap__read(md, false, start, end, &md->prev);
828}
829
830union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int idx) 704union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int idx)
831{ 705{
832 struct perf_mmap *md = &evlist->mmap[idx]; 706 struct perf_mmap *md = &evlist->mmap[idx];
@@ -857,96 +731,16 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
857 return perf_evlist__mmap_read_forward(evlist, idx); 731 return perf_evlist__mmap_read_forward(evlist, idx);
858} 732}
859 733
860void perf_mmap__read_catchup(struct perf_mmap *md)
861{
862 u64 head;
863
864 if (!refcount_read(&md->refcnt))
865 return;
866
867 head = perf_mmap__read_head(md);
868 md->prev = head;
869}
870
871void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx) 734void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
872{ 735{
873 perf_mmap__read_catchup(&evlist->mmap[idx]); 736 perf_mmap__read_catchup(&evlist->mmap[idx]);
874} 737}
875 738
876static bool perf_mmap__empty(struct perf_mmap *md)
877{
878 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
879}
880
881static void perf_mmap__get(struct perf_mmap *map)
882{
883 refcount_inc(&map->refcnt);
884}
885
886static void perf_mmap__put(struct perf_mmap *md)
887{
888 BUG_ON(md->base && refcount_read(&md->refcnt) == 0);
889
890 if (refcount_dec_and_test(&md->refcnt))
891 perf_mmap__munmap(md);
892}
893
894void perf_mmap__consume(struct perf_mmap *md, bool overwrite)
895{
896 if (!overwrite) {
897 u64 old = md->prev;
898
899 perf_mmap__write_tail(md, old);
900 }
901
902 if (refcount_read(&md->refcnt) == 1 && perf_mmap__empty(md))
903 perf_mmap__put(md);
904}
905
906void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) 739void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
907{ 740{
908 perf_mmap__consume(&evlist->mmap[idx], evlist->overwrite); 741 perf_mmap__consume(&evlist->mmap[idx], evlist->overwrite);
909} 742}
910 743
911int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused,
912 struct auxtrace_mmap_params *mp __maybe_unused,
913 void *userpg __maybe_unused,
914 int fd __maybe_unused)
915{
916 return 0;
917}
918
919void __weak auxtrace_mmap__munmap(struct auxtrace_mmap *mm __maybe_unused)
920{
921}
922
923void __weak auxtrace_mmap_params__init(
924 struct auxtrace_mmap_params *mp __maybe_unused,
925 off_t auxtrace_offset __maybe_unused,
926 unsigned int auxtrace_pages __maybe_unused,
927 bool auxtrace_overwrite __maybe_unused)
928{
929}
930
931void __weak auxtrace_mmap_params__set_idx(
932 struct auxtrace_mmap_params *mp __maybe_unused,
933 struct perf_evlist *evlist __maybe_unused,
934 int idx __maybe_unused,
935 bool per_cpu __maybe_unused)
936{
937}
938
939static void perf_mmap__munmap(struct perf_mmap *map)
940{
941 if (map->base != NULL) {
942 munmap(map->base, perf_mmap__mmap_len(map));
943 map->base = NULL;
944 map->fd = -1;
945 refcount_set(&map->refcnt, 0);
946 }
947 auxtrace_mmap__munmap(&map->auxtrace_mmap);
948}
949
950static void perf_evlist__munmap_nofree(struct perf_evlist *evlist) 744static void perf_evlist__munmap_nofree(struct perf_evlist *evlist)
951{ 745{
952 int i; 746 int i;
@@ -995,48 +789,6 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist)
995 return map; 789 return map;
996} 790}
997 791
998struct mmap_params {
999 int prot;
1000 int mask;
1001 struct auxtrace_mmap_params auxtrace_mp;
1002};
1003
1004static int perf_mmap__mmap(struct perf_mmap *map,
1005 struct mmap_params *mp, int fd)
1006{
1007 /*
1008 * The last one will be done at perf_evlist__mmap_consume(), so that we
1009 * make sure we don't prevent tools from consuming every last event in
1010 * the ring buffer.
1011 *
1012 * I.e. we can get the POLLHUP meaning that the fd doesn't exist
1013 * anymore, but the last events for it are still in the ring buffer,
1014 * waiting to be consumed.
1015 *
1016 * Tools can chose to ignore this at their own discretion, but the
1017 * evlist layer can't just drop it when filtering events in
1018 * perf_evlist__filter_pollfd().
1019 */
1020 refcount_set(&map->refcnt, 2);
1021 map->prev = 0;
1022 map->mask = mp->mask;
1023 map->base = mmap(NULL, perf_mmap__mmap_len(map), mp->prot,
1024 MAP_SHARED, fd, 0);
1025 if (map->base == MAP_FAILED) {
1026 pr_debug2("failed to mmap perf event ring buffer, error %d\n",
1027 errno);
1028 map->base = NULL;
1029 return -1;
1030 }
1031 map->fd = fd;
1032
1033 if (auxtrace_mmap__mmap(&map->auxtrace_mmap,
1034 &mp->auxtrace_mp, map->base, fd))
1035 return -1;
1036
1037 return 0;
1038}
1039
1040static bool 792static bool
1041perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused, 793perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused,
1042 struct perf_evsel *evsel) 794 struct perf_evsel *evsel)
@@ -1419,8 +1171,6 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e
1419{ 1171{
1420 struct perf_evsel *evsel; 1172 struct perf_evsel *evsel;
1421 int err = 0; 1173 int err = 0;
1422 const int ncpus = cpu_map__nr(evlist->cpus),
1423 nthreads = thread_map__nr(evlist->threads);
1424 1174
1425 evlist__for_each_entry(evlist, evsel) { 1175 evlist__for_each_entry(evlist, evsel) {
1426 if (evsel->filter == NULL) 1176 if (evsel->filter == NULL)
@@ -1430,7 +1180,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e
1430 * filters only work for tracepoint event, which doesn't have cpu limit. 1180 * filters only work for tracepoint event, which doesn't have cpu limit.
1431 * So evlist and evsel should always be same. 1181 * So evlist and evsel should always be same.
1432 */ 1182 */
1433 err = perf_evsel__apply_filter(evsel, ncpus, nthreads, evsel->filter); 1183 err = perf_evsel__apply_filter(evsel, evsel->filter);
1434 if (err) { 1184 if (err) {
1435 *err_evsel = evsel; 1185 *err_evsel = evsel;
1436 break; 1186 break;
@@ -1623,13 +1373,9 @@ void perf_evlist__set_selected(struct perf_evlist *evlist,
1623void perf_evlist__close(struct perf_evlist *evlist) 1373void perf_evlist__close(struct perf_evlist *evlist)
1624{ 1374{
1625 struct perf_evsel *evsel; 1375 struct perf_evsel *evsel;
1626 int ncpus = cpu_map__nr(evlist->cpus);
1627 int nthreads = thread_map__nr(evlist->threads);
1628 1376
1629 evlist__for_each_entry_reverse(evlist, evsel) { 1377 evlist__for_each_entry_reverse(evlist, evsel)
1630 int n = evsel->cpus ? evsel->cpus->nr : ncpus; 1378 perf_evsel__close(evsel);
1631 perf_evsel__close(evsel, n, nthreads);
1632 }
1633} 1379}
1634 1380
1635static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) 1381static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 8d601fbdd8d6..e72ae64c11ac 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_EVLIST_H 2#ifndef __PERF_EVLIST_H
2#define __PERF_EVLIST_H 1 3#define __PERF_EVLIST_H 1
3 4
@@ -6,12 +7,13 @@
6#include <linux/refcount.h> 7#include <linux/refcount.h>
7#include <linux/list.h> 8#include <linux/list.h>
8#include <api/fd/array.h> 9#include <api/fd/array.h>
10#include <fcntl.h>
9#include <stdio.h> 11#include <stdio.h>
10#include "../perf.h" 12#include "../perf.h"
11#include "event.h" 13#include "event.h"
12#include "evsel.h" 14#include "evsel.h"
15#include "mmap.h"
13#include "util.h" 16#include "util.h"
14#include "auxtrace.h"
15#include <signal.h> 17#include <signal.h>
16#include <unistd.h> 18#include <unistd.h>
17 19
@@ -23,55 +25,6 @@ struct record_opts;
23#define PERF_EVLIST__HLIST_BITS 8 25#define PERF_EVLIST__HLIST_BITS 8
24#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) 26#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
25 27
26/**
27 * struct perf_mmap - perf's ring buffer mmap details
28 *
29 * @refcnt - e.g. code using PERF_EVENT_IOC_SET_OUTPUT to share this
30 */
31struct perf_mmap {
32 void *base;
33 int mask;
34 int fd;
35 refcount_t refcnt;
36 u64 prev;
37 struct auxtrace_mmap auxtrace_mmap;
38 char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8);
39};
40
41static inline size_t
42perf_mmap__mmap_len(struct perf_mmap *map)
43{
44 return map->mask + 1 + page_size;
45}
46
47/*
48 * State machine of bkw_mmap_state:
49 *
50 * .________________(forbid)_____________.
51 * | V
52 * NOTREADY --(0)--> RUNNING --(1)--> DATA_PENDING --(2)--> EMPTY
53 * ^ ^ | ^ |
54 * | |__(forbid)____/ |___(forbid)___/|
55 * | |
56 * \_________________(3)_______________/
57 *
58 * NOTREADY : Backward ring buffers are not ready
59 * RUNNING : Backward ring buffers are recording
60 * DATA_PENDING : We are required to collect data from backward ring buffers
61 * EMPTY : We have collected data from backward ring buffers.
62 *
63 * (0): Setup backward ring buffer
64 * (1): Pause ring buffers for reading
65 * (2): Read from ring buffers
66 * (3): Resume ring buffers for recording
67 */
68enum bkw_mmap_state {
69 BKW_MMAP_NOTREADY,
70 BKW_MMAP_RUNNING,
71 BKW_MMAP_DATA_PENDING,
72 BKW_MMAP_EMPTY,
73};
74
75struct perf_evlist { 28struct perf_evlist {
76 struct list_head entries; 29 struct list_head entries;
77 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; 30 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
@@ -115,7 +68,14 @@ void perf_evlist__delete(struct perf_evlist *evlist);
115 68
116void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); 69void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
117void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel); 70void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel);
118int perf_evlist__add_default(struct perf_evlist *evlist); 71
72int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise);
73
74static inline int perf_evlist__add_default(struct perf_evlist *evlist)
75{
76 return __perf_evlist__add_default(evlist, true);
77}
78
119int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 79int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
120 struct perf_event_attr *attrs, size_t nr_attrs); 80 struct perf_event_attr *attrs, size_t nr_attrs);
121 81
@@ -169,12 +129,6 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
169 129
170void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, enum bkw_mmap_state state); 130void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, enum bkw_mmap_state state);
171 131
172union perf_event *perf_mmap__read_forward(struct perf_mmap *map, bool check_messup);
173union perf_event *perf_mmap__read_backward(struct perf_mmap *map);
174
175void perf_mmap__read_catchup(struct perf_mmap *md);
176void perf_mmap__consume(struct perf_mmap *md, bool overwrite);
177
178union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx); 132union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
179 133
180union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, 134union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist,
@@ -258,6 +212,11 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist);
258void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 212void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
259 struct list_head *list); 213 struct list_head *list);
260 214
215static inline bool perf_evlist__empty(struct perf_evlist *evlist)
216{
217 return list_empty(&evlist->entries);
218}
219
261static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist) 220static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist)
262{ 221{
263 return list_entry(evlist->entries.next, struct perf_evsel, node); 222 return list_entry(evlist->entries.next, struct perf_evsel, node);
@@ -273,25 +232,6 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
273int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size); 232int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
274int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size); 233int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size);
275 234
276static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
277{
278 struct perf_event_mmap_page *pc = mm->base;
279 u64 head = ACCESS_ONCE(pc->data_head);
280 rmb();
281 return head;
282}
283
284static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
285{
286 struct perf_event_mmap_page *pc = md->base;
287
288 /*
289 * ensure all reads are done before we write the tail out.
290 */
291 mb();
292 pc->data_tail = tail;
293}
294
295bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str); 235bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str);
296void perf_evlist__to_front(struct perf_evlist *evlist, 236void perf_evlist__to_front(struct perf_evlist *evlist,
297 struct perf_evsel *move_evsel); 237 struct perf_evsel *move_evsel);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 413f74df08de..f894893c203d 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -49,6 +49,7 @@ static struct {
49 bool clockid_wrong; 49 bool clockid_wrong;
50 bool lbr_flags; 50 bool lbr_flags;
51 bool write_backward; 51 bool write_backward;
52 bool group_read;
52} perf_missing_features; 53} perf_missing_features;
53 54
54static clockid_t clockid; 55static clockid_t clockid;
@@ -58,6 +59,8 @@ static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused)
58 return 0; 59 return 0;
59} 60}
60 61
62void __weak test_attr__ready(void) { }
63
61static void perf_evsel__no_extra_fini(struct perf_evsel *evsel __maybe_unused) 64static void perf_evsel__no_extra_fini(struct perf_evsel *evsel __maybe_unused)
62{ 65{
63} 66}
@@ -268,16 +271,24 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
268 return evsel; 271 return evsel;
269} 272}
270 273
271struct perf_evsel *perf_evsel__new_cycles(void) 274static bool perf_event_can_profile_kernel(void)
275{
276 return geteuid() == 0 || perf_event_paranoid() == -1;
277}
278
279struct perf_evsel *perf_evsel__new_cycles(bool precise)
272{ 280{
273 struct perf_event_attr attr = { 281 struct perf_event_attr attr = {
274 .type = PERF_TYPE_HARDWARE, 282 .type = PERF_TYPE_HARDWARE,
275 .config = PERF_COUNT_HW_CPU_CYCLES, 283 .config = PERF_COUNT_HW_CPU_CYCLES,
276 .exclude_kernel = geteuid() != 0, 284 .exclude_kernel = !perf_event_can_profile_kernel(),
277 }; 285 };
278 struct perf_evsel *evsel; 286 struct perf_evsel *evsel;
279 287
280 event_attr_init(&attr); 288 event_attr_init(&attr);
289
290 if (!precise)
291 goto new_event;
281 /* 292 /*
282 * Unnamed union member, not supported as struct member named 293 * Unnamed union member, not supported as struct member named
283 * initializer in older compilers such as gcc 4.4.7 294 * initializer in older compilers such as gcc 4.4.7
@@ -292,7 +303,7 @@ struct perf_evsel *perf_evsel__new_cycles(void)
292 * to kick in when we return and before perf_evsel__open() is called. 303 * to kick in when we return and before perf_evsel__open() is called.
293 */ 304 */
294 attr.sample_period = 0; 305 attr.sample_period = 0;
295 306new_event:
296 evsel = perf_evsel__new(&attr); 307 evsel = perf_evsel__new(&attr);
297 if (evsel == NULL) 308 if (evsel == NULL)
298 goto out; 309 goto out;
@@ -672,7 +683,7 @@ void perf_evsel__config_callchain(struct perf_evsel *evsel,
672 if (!function) { 683 if (!function) {
673 perf_evsel__set_sample_bit(evsel, REGS_USER); 684 perf_evsel__set_sample_bit(evsel, REGS_USER);
674 perf_evsel__set_sample_bit(evsel, STACK_USER); 685 perf_evsel__set_sample_bit(evsel, STACK_USER);
675 attr->sample_regs_user = PERF_REGS_MASK; 686 attr->sample_regs_user |= PERF_REGS_MASK;
676 attr->sample_stack_user = param->dump_size; 687 attr->sample_stack_user = param->dump_size;
677 attr->exclude_callchain_user = 1; 688 attr->exclude_callchain_user = 1;
678 } else { 689 } else {
@@ -896,8 +907,13 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
896 if (opts->no_samples) 907 if (opts->no_samples)
897 attr->sample_freq = 0; 908 attr->sample_freq = 0;
898 909
899 if (opts->inherit_stat) 910 if (opts->inherit_stat) {
911 evsel->attr.read_format |=
912 PERF_FORMAT_TOTAL_TIME_ENABLED |
913 PERF_FORMAT_TOTAL_TIME_RUNNING |
914 PERF_FORMAT_ID;
900 attr->inherit_stat = 1; 915 attr->inherit_stat = 1;
916 }
901 917
902 if (opts->sample_address) { 918 if (opts->sample_address) {
903 perf_evsel__set_sample_bit(evsel, ADDR); 919 perf_evsel__set_sample_bit(evsel, ADDR);
@@ -920,6 +936,11 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
920 perf_evsel__set_sample_bit(evsel, REGS_INTR); 936 perf_evsel__set_sample_bit(evsel, REGS_INTR);
921 } 937 }
922 938
939 if (opts->sample_user_regs) {
940 attr->sample_regs_user |= opts->sample_user_regs;
941 perf_evsel__set_sample_bit(evsel, REGS_USER);
942 }
943
923 if (target__has_cpu(&opts->target) || opts->sample_cpu) 944 if (target__has_cpu(&opts->target) || opts->sample_cpu)
924 perf_evsel__set_sample_bit(evsel, CPU); 945 perf_evsel__set_sample_bit(evsel, CPU);
925 946
@@ -944,6 +965,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
944 if (opts->sample_address) 965 if (opts->sample_address)
945 perf_evsel__set_sample_bit(evsel, DATA_SRC); 966 perf_evsel__set_sample_bit(evsel, DATA_SRC);
946 967
968 if (opts->sample_phys_addr)
969 perf_evsel__set_sample_bit(evsel, PHYS_ADDR);
970
947 if (opts->no_buffering) { 971 if (opts->no_buffering) {
948 attr->watermark = 0; 972 attr->watermark = 0;
949 attr->wakeup_events = 1; 973 attr->wakeup_events = 1;
@@ -1045,16 +1069,13 @@ static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthread
1045 return evsel->fd != NULL ? 0 : -ENOMEM; 1069 return evsel->fd != NULL ? 0 : -ENOMEM;
1046} 1070}
1047 1071
1048static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ncpus, int nthreads, 1072static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
1049 int ioc, void *arg) 1073 int ioc, void *arg)
1050{ 1074{
1051 int cpu, thread; 1075 int cpu, thread;
1052 1076
1053 if (evsel->system_wide) 1077 for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
1054 nthreads = 1; 1078 for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
1055
1056 for (cpu = 0; cpu < ncpus; cpu++) {
1057 for (thread = 0; thread < nthreads; thread++) {
1058 int fd = FD(evsel, cpu, thread), 1079 int fd = FD(evsel, cpu, thread),
1059 err = ioctl(fd, ioc, arg); 1080 err = ioctl(fd, ioc, arg);
1060 1081
@@ -1066,10 +1087,9 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ncpus, int nthrea
1066 return 0; 1087 return 0;
1067} 1088}
1068 1089
1069int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads, 1090int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter)
1070 const char *filter)
1071{ 1091{
1072 return perf_evsel__run_ioctl(evsel, ncpus, nthreads, 1092 return perf_evsel__run_ioctl(evsel,
1073 PERF_EVENT_IOC_SET_FILTER, 1093 PERF_EVENT_IOC_SET_FILTER,
1074 (void *)filter); 1094 (void *)filter);
1075} 1095}
@@ -1116,20 +1136,14 @@ int perf_evsel__append_addr_filter(struct perf_evsel *evsel, const char *filter)
1116 1136
1117int perf_evsel__enable(struct perf_evsel *evsel) 1137int perf_evsel__enable(struct perf_evsel *evsel)
1118{ 1138{
1119 int nthreads = thread_map__nr(evsel->threads); 1139 return perf_evsel__run_ioctl(evsel,
1120 int ncpus = cpu_map__nr(evsel->cpus);
1121
1122 return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
1123 PERF_EVENT_IOC_ENABLE, 1140 PERF_EVENT_IOC_ENABLE,
1124 0); 1141 0);
1125} 1142}
1126 1143
1127int perf_evsel__disable(struct perf_evsel *evsel) 1144int perf_evsel__disable(struct perf_evsel *evsel)
1128{ 1145{
1129 int nthreads = thread_map__nr(evsel->threads); 1146 return perf_evsel__run_ioctl(evsel,
1130 int ncpus = cpu_map__nr(evsel->cpus);
1131
1132 return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
1133 PERF_EVENT_IOC_DISABLE, 1147 PERF_EVENT_IOC_DISABLE,
1134 0); 1148 0);
1135} 1149}
@@ -1179,15 +1193,12 @@ static void perf_evsel__free_config_terms(struct perf_evsel *evsel)
1179 } 1193 }
1180} 1194}
1181 1195
1182void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 1196void perf_evsel__close_fd(struct perf_evsel *evsel)
1183{ 1197{
1184 int cpu, thread; 1198 int cpu, thread;
1185 1199
1186 if (evsel->system_wide) 1200 for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++)
1187 nthreads = 1; 1201 for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
1188
1189 for (cpu = 0; cpu < ncpus; cpu++)
1190 for (thread = 0; thread < nthreads; ++thread) {
1191 close(FD(evsel, cpu, thread)); 1202 close(FD(evsel, cpu, thread));
1192 FD(evsel, cpu, thread) = -1; 1203 FD(evsel, cpu, thread) = -1;
1193 } 1204 }
@@ -1256,20 +1267,148 @@ void perf_counts_values__scale(struct perf_counts_values *count,
1256 *pscaled = scaled; 1267 *pscaled = scaled;
1257} 1268}
1258 1269
1270static int perf_evsel__read_size(struct perf_evsel *evsel)
1271{
1272 u64 read_format = evsel->attr.read_format;
1273 int entry = sizeof(u64); /* value */
1274 int size = 0;
1275 int nr = 1;
1276
1277 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1278 size += sizeof(u64);
1279
1280 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1281 size += sizeof(u64);
1282
1283 if (read_format & PERF_FORMAT_ID)
1284 entry += sizeof(u64);
1285
1286 if (read_format & PERF_FORMAT_GROUP) {
1287 nr = evsel->nr_members;
1288 size += sizeof(u64);
1289 }
1290
1291 size += entry * nr;
1292 return size;
1293}
1294
1259int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, 1295int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
1260 struct perf_counts_values *count) 1296 struct perf_counts_values *count)
1261{ 1297{
1298 size_t size = perf_evsel__read_size(evsel);
1299
1262 memset(count, 0, sizeof(*count)); 1300 memset(count, 0, sizeof(*count));
1263 1301
1264 if (FD(evsel, cpu, thread) < 0) 1302 if (FD(evsel, cpu, thread) < 0)
1265 return -EINVAL; 1303 return -EINVAL;
1266 1304
1267 if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) <= 0) 1305 if (readn(FD(evsel, cpu, thread), count->values, size) <= 0)
1268 return -errno; 1306 return -errno;
1269 1307
1270 return 0; 1308 return 0;
1271} 1309}
1272 1310
1311static int
1312perf_evsel__read_one(struct perf_evsel *evsel, int cpu, int thread)
1313{
1314 struct perf_counts_values *count = perf_counts(evsel->counts, cpu, thread);
1315
1316 return perf_evsel__read(evsel, cpu, thread, count);
1317}
1318
1319static void
1320perf_evsel__set_count(struct perf_evsel *counter, int cpu, int thread,
1321 u64 val, u64 ena, u64 run)
1322{
1323 struct perf_counts_values *count;
1324
1325 count = perf_counts(counter->counts, cpu, thread);
1326
1327 count->val = val;
1328 count->ena = ena;
1329 count->run = run;
1330 count->loaded = true;
1331}
1332
1333static int
1334perf_evsel__process_group_data(struct perf_evsel *leader,
1335 int cpu, int thread, u64 *data)
1336{
1337 u64 read_format = leader->attr.read_format;
1338 struct sample_read_value *v;
1339 u64 nr, ena = 0, run = 0, i;
1340
1341 nr = *data++;
1342
1343 if (nr != (u64) leader->nr_members)
1344 return -EINVAL;
1345
1346 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1347 ena = *data++;
1348
1349 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1350 run = *data++;
1351
1352 v = (struct sample_read_value *) data;
1353
1354 perf_evsel__set_count(leader, cpu, thread,
1355 v[0].value, ena, run);
1356
1357 for (i = 1; i < nr; i++) {
1358 struct perf_evsel *counter;
1359
1360 counter = perf_evlist__id2evsel(leader->evlist, v[i].id);
1361 if (!counter)
1362 return -EINVAL;
1363
1364 perf_evsel__set_count(counter, cpu, thread,
1365 v[i].value, ena, run);
1366 }
1367
1368 return 0;
1369}
1370
1371static int
1372perf_evsel__read_group(struct perf_evsel *leader, int cpu, int thread)
1373{
1374 struct perf_stat_evsel *ps = leader->priv;
1375 u64 read_format = leader->attr.read_format;
1376 int size = perf_evsel__read_size(leader);
1377 u64 *data = ps->group_data;
1378
1379 if (!(read_format & PERF_FORMAT_ID))
1380 return -EINVAL;
1381
1382 if (!perf_evsel__is_group_leader(leader))
1383 return -EINVAL;
1384
1385 if (!data) {
1386 data = zalloc(size);
1387 if (!data)
1388 return -ENOMEM;
1389
1390 ps->group_data = data;
1391 }
1392
1393 if (FD(leader, cpu, thread) < 0)
1394 return -EINVAL;
1395
1396 if (readn(FD(leader, cpu, thread), data, size) <= 0)
1397 return -errno;
1398
1399 return perf_evsel__process_group_data(leader, cpu, thread, data);
1400}
1401
1402int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread)
1403{
1404 u64 read_format = evsel->attr.read_format;
1405
1406 if (read_format & PERF_FORMAT_GROUP)
1407 return perf_evsel__read_group(evsel, cpu, thread);
1408 else
1409 return perf_evsel__read_one(evsel, cpu, thread);
1410}
1411
1273int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 1412int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
1274 int cpu, int thread, bool scale) 1413 int cpu, int thread, bool scale)
1275{ 1414{
@@ -1338,7 +1477,7 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
1338 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), 1477 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1339 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), 1478 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1340 bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC), 1479 bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC),
1341 bit_name(WEIGHT), 1480 bit_name(WEIGHT), bit_name(PHYS_ADDR),
1342 { .name = NULL, } 1481 { .name = NULL, }
1343 }; 1482 };
1344#undef bit_name 1483#undef bit_name
@@ -1545,6 +1684,8 @@ fallback_missing_features:
1545 if (perf_missing_features.lbr_flags) 1684 if (perf_missing_features.lbr_flags)
1546 evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | 1685 evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
1547 PERF_SAMPLE_BRANCH_NO_CYCLES); 1686 PERF_SAMPLE_BRANCH_NO_CYCLES);
1687 if (perf_missing_features.group_read && evsel->attr.inherit)
1688 evsel->attr.read_format &= ~(PERF_FORMAT_GROUP|PERF_FORMAT_ID);
1548retry_sample_id: 1689retry_sample_id:
1549 if (perf_missing_features.sample_id_all) 1690 if (perf_missing_features.sample_id_all)
1550 evsel->attr.sample_id_all = 0; 1691 evsel->attr.sample_id_all = 0;
@@ -1569,6 +1710,8 @@ retry_open:
1569 pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx", 1710 pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx",
1570 pid, cpus->map[cpu], group_fd, flags); 1711 pid, cpus->map[cpu], group_fd, flags);
1571 1712
1713 test_attr__ready();
1714
1572 fd = sys_perf_event_open(&evsel->attr, pid, cpus->map[cpu], 1715 fd = sys_perf_event_open(&evsel->attr, pid, cpus->map[cpu],
1573 group_fd, flags); 1716 group_fd, flags);
1574 1717
@@ -1664,31 +1807,45 @@ try_fallback:
1664 */ 1807 */
1665 if (!perf_missing_features.write_backward && evsel->attr.write_backward) { 1808 if (!perf_missing_features.write_backward && evsel->attr.write_backward) {
1666 perf_missing_features.write_backward = true; 1809 perf_missing_features.write_backward = true;
1810 pr_debug2("switching off write_backward\n");
1667 goto out_close; 1811 goto out_close;
1668 } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { 1812 } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) {
1669 perf_missing_features.clockid_wrong = true; 1813 perf_missing_features.clockid_wrong = true;
1814 pr_debug2("switching off clockid\n");
1670 goto fallback_missing_features; 1815 goto fallback_missing_features;
1671 } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) { 1816 } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) {
1672 perf_missing_features.clockid = true; 1817 perf_missing_features.clockid = true;
1818 pr_debug2("switching off use_clockid\n");
1673 goto fallback_missing_features; 1819 goto fallback_missing_features;
1674 } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) { 1820 } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
1675 perf_missing_features.cloexec = true; 1821 perf_missing_features.cloexec = true;
1822 pr_debug2("switching off cloexec flag\n");
1676 goto fallback_missing_features; 1823 goto fallback_missing_features;
1677 } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { 1824 } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
1678 perf_missing_features.mmap2 = true; 1825 perf_missing_features.mmap2 = true;
1826 pr_debug2("switching off mmap2\n");
1679 goto fallback_missing_features; 1827 goto fallback_missing_features;
1680 } else if (!perf_missing_features.exclude_guest && 1828 } else if (!perf_missing_features.exclude_guest &&
1681 (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { 1829 (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
1682 perf_missing_features.exclude_guest = true; 1830 perf_missing_features.exclude_guest = true;
1831 pr_debug2("switching off exclude_guest, exclude_host\n");
1683 goto fallback_missing_features; 1832 goto fallback_missing_features;
1684 } else if (!perf_missing_features.sample_id_all) { 1833 } else if (!perf_missing_features.sample_id_all) {
1685 perf_missing_features.sample_id_all = true; 1834 perf_missing_features.sample_id_all = true;
1835 pr_debug2("switching off sample_id_all\n");
1686 goto retry_sample_id; 1836 goto retry_sample_id;
1687 } else if (!perf_missing_features.lbr_flags && 1837 } else if (!perf_missing_features.lbr_flags &&
1688 (evsel->attr.branch_sample_type & 1838 (evsel->attr.branch_sample_type &
1689 (PERF_SAMPLE_BRANCH_NO_CYCLES | 1839 (PERF_SAMPLE_BRANCH_NO_CYCLES |
1690 PERF_SAMPLE_BRANCH_NO_FLAGS))) { 1840 PERF_SAMPLE_BRANCH_NO_FLAGS))) {
1691 perf_missing_features.lbr_flags = true; 1841 perf_missing_features.lbr_flags = true;
1842 pr_debug2("switching off branch sample type no (cycles/flags)\n");
1843 goto fallback_missing_features;
1844 } else if (!perf_missing_features.group_read &&
1845 evsel->attr.inherit &&
1846 (evsel->attr.read_format & PERF_FORMAT_GROUP)) {
1847 perf_missing_features.group_read = true;
1848 pr_debug2("switching off group read\n");
1692 goto fallback_missing_features; 1849 goto fallback_missing_features;
1693 } 1850 }
1694out_close: 1851out_close:
@@ -1702,12 +1859,12 @@ out_close:
1702 return err; 1859 return err;
1703} 1860}
1704 1861
1705void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads) 1862void perf_evsel__close(struct perf_evsel *evsel)
1706{ 1863{
1707 if (evsel->fd == NULL) 1864 if (evsel->fd == NULL)
1708 return; 1865 return;
1709 1866
1710 perf_evsel__close_fd(evsel, ncpus, nthreads); 1867 perf_evsel__close_fd(evsel);
1711 perf_evsel__free_fd(evsel); 1868 perf_evsel__free_fd(evsel);
1712} 1869}
1713 1870
@@ -2062,6 +2219,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
2062 } 2219 }
2063 } 2220 }
2064 2221
2222 data->phys_addr = 0;
2223 if (type & PERF_SAMPLE_PHYS_ADDR) {
2224 data->phys_addr = *array;
2225 array++;
2226 }
2227
2065 return 0; 2228 return 0;
2066} 2229}
2067 2230
@@ -2167,6 +2330,9 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
2167 } 2330 }
2168 } 2331 }
2169 2332
2333 if (type & PERF_SAMPLE_PHYS_ADDR)
2334 result += sizeof(u64);
2335
2170 return result; 2336 return result;
2171} 2337}
2172 2338
@@ -2356,6 +2522,11 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
2356 } 2522 }
2357 } 2523 }
2358 2524
2525 if (type & PERF_SAMPLE_PHYS_ADDR) {
2526 *array = sample->phys_addr;
2527 array++;
2528 }
2529
2359 return 0; 2530 return 0;
2360} 2531}
2361 2532
@@ -2535,7 +2706,9 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2535 "unprivileged users (without CAP_SYS_ADMIN).\n\n" 2706 "unprivileged users (without CAP_SYS_ADMIN).\n\n"
2536 "The current value is %d:\n\n" 2707 "The current value is %d:\n\n"
2537 " -1: Allow use of (almost) all events by all users\n" 2708 " -1: Allow use of (almost) all events by all users\n"
2538 ">= 0: Disallow raw tracepoint access by users without CAP_IOC_LOCK\n" 2709 " Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK\n"
2710 ">= 0: Disallow ftrace function tracepoint by users without CAP_SYS_ADMIN\n"
2711 " Disallow raw tracepoint access by users without CAP_SYS_ADMIN\n"
2539 ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n" 2712 ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n"
2540 ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN\n\n" 2713 ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN\n\n"
2541 "To make this setting permanent, edit /etc/sysctl.conf too, e.g.:\n\n" 2714 "To make this setting permanent, edit /etc/sysctl.conf too, e.g.:\n\n"
@@ -2610,3 +2783,10 @@ char *perf_evsel__env_arch(struct perf_evsel *evsel)
2610 return evsel->evlist->env->arch; 2783 return evsel->evlist->env->arch;
2611 return NULL; 2784 return NULL;
2612} 2785}
2786
2787char *perf_evsel__env_cpuid(struct perf_evsel *evsel)
2788{
2789 if (evsel && evsel->evlist && evsel->evlist->env)
2790 return evsel->evlist->env->cpuid;
2791 return NULL;
2792}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index d101695c482c..9277df96ffda 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_EVSEL_H 2#ifndef __PERF_EVSEL_H
2#define __PERF_EVSEL_H 1 3#define __PERF_EVSEL_H 1
3 4
@@ -68,6 +69,8 @@ struct perf_evsel_config_term {
68 } val; 69 } val;
69}; 70};
70 71
72struct perf_stat_evsel;
73
71/** struct perf_evsel - event selector 74/** struct perf_evsel - event selector
72 * 75 *
73 * @evlist - evlist this evsel is in, if it is in one. 76 * @evlist - evlist this evsel is in, if it is in one.
@@ -101,6 +104,7 @@ struct perf_evsel {
101 const char *unit; 104 const char *unit;
102 struct event_format *tp_format; 105 struct event_format *tp_format;
103 off_t id_offset; 106 off_t id_offset;
107 struct perf_stat_evsel *stats;
104 void *priv; 108 void *priv;
105 u64 db_id; 109 u64 db_id;
106 struct cgroup_sel *cgrp; 110 struct cgroup_sel *cgrp;
@@ -131,11 +135,13 @@ struct perf_evsel {
131 bool cmdline_group_boundary; 135 bool cmdline_group_boundary;
132 struct list_head config_terms; 136 struct list_head config_terms;
133 int bpf_fd; 137 int bpf_fd;
138 bool auto_merge_stats;
134 bool merged_stat; 139 bool merged_stat;
135 const char * metric_expr; 140 const char * metric_expr;
136 const char * metric_name; 141 const char * metric_name;
137 struct perf_evsel **metric_events; 142 struct perf_evsel **metric_events;
138 bool collect_stat; 143 bool collect_stat;
144 bool weak_group;
139}; 145};
140 146
141union u64_swap { 147union u64_swap {
@@ -185,7 +191,7 @@ static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *
185 return perf_evsel__newtp_idx(sys, name, 0); 191 return perf_evsel__newtp_idx(sys, name, 0);
186} 192}
187 193
188struct perf_evsel *perf_evsel__new_cycles(void); 194struct perf_evsel *perf_evsel__new_cycles(bool precise);
189 195
190struct event_format *event_format__new(const char *sys, const char *name); 196struct event_format *event_format__new(const char *sys, const char *name);
191 197
@@ -226,7 +232,7 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel);
226int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); 232int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
227 233
228int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 234int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
229void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 235void perf_evsel__close_fd(struct perf_evsel *evsel);
230 236
231void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, 237void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
232 enum perf_event_sample_format bit); 238 enum perf_event_sample_format bit);
@@ -246,8 +252,7 @@ int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter);
246int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter); 252int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter);
247int perf_evsel__append_addr_filter(struct perf_evsel *evsel, 253int perf_evsel__append_addr_filter(struct perf_evsel *evsel,
248 const char *filter); 254 const char *filter);
249int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads, 255int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter);
250 const char *filter);
251int perf_evsel__enable(struct perf_evsel *evsel); 256int perf_evsel__enable(struct perf_evsel *evsel);
252int perf_evsel__disable(struct perf_evsel *evsel); 257int perf_evsel__disable(struct perf_evsel *evsel);
253 258
@@ -257,7 +262,7 @@ int perf_evsel__open_per_thread(struct perf_evsel *evsel,
257 struct thread_map *threads); 262 struct thread_map *threads);
258int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 263int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
259 struct thread_map *threads); 264 struct thread_map *threads);
260void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads); 265void perf_evsel__close(struct perf_evsel *evsel);
261 266
262struct perf_sample; 267struct perf_sample;
263 268
@@ -299,6 +304,8 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1,
299int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, 304int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
300 struct perf_counts_values *count); 305 struct perf_counts_values *count);
301 306
307int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread);
308
302int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 309int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
303 int cpu, int thread, bool scale); 310 int cpu, int thread, bool scale);
304 311
@@ -436,5 +443,6 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
436 attr__fprintf_f attr__fprintf, void *priv); 443 attr__fprintf_f attr__fprintf, void *priv);
437 444
438char *perf_evsel__env_arch(struct perf_evsel *evsel); 445char *perf_evsel__env_arch(struct perf_evsel *evsel);
446char *perf_evsel__env_cpuid(struct perf_evsel *evsel);
439 447
440#endif /* __PERF_EVSEL_H */ 448#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 583f3a602506..06dfb027879d 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <inttypes.h> 2#include <inttypes.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <stdbool.h> 4#include <stdbool.h>
@@ -157,7 +158,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
157 } 158 }
158 } 159 }
159 160
160 if (print_dso) { 161 if (print_dso && (!node->sym || !node->sym->inlined)) {
161 printed += fprintf(fp, " ("); 162 printed += fprintf(fp, " (");
162 printed += map__fprintf_dsoname(node->map, fp); 163 printed += map__fprintf_dsoname(node->map, fp);
163 printed += fprintf(fp, ")"); 164 printed += fprintf(fp, ")");
@@ -166,41 +167,12 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
166 if (print_srcline) 167 if (print_srcline)
167 printed += map__fprintf_srcline(node->map, addr, "\n ", fp); 168 printed += map__fprintf_srcline(node->map, addr, "\n ", fp);
168 169
170 if (node->sym && node->sym->inlined)
171 printed += fprintf(fp, " (inlined)");
172
169 if (!print_oneline) 173 if (!print_oneline)
170 printed += fprintf(fp, "\n"); 174 printed += fprintf(fp, "\n");
171 175
172 if (symbol_conf.inline_name && node->map) {
173 struct inline_node *inode;
174
175 addr = map__rip_2objdump(node->map, node->ip),
176 inode = dso__parse_addr_inlines(node->map->dso, addr);
177
178 if (inode) {
179 struct inline_list *ilist;
180
181 list_for_each_entry(ilist, &inode->val, list) {
182 if (print_arrow)
183 printed += fprintf(fp, " <-");
184
185 /* IP is same, just skip it */
186 if (print_ip)
187 printed += fprintf(fp, "%c%16s",
188 s, "");
189 if (print_sym)
190 printed += fprintf(fp, " %s",
191 ilist->funcname);
192 if (print_srcline)
193 printed += fprintf(fp, "\n %s:%d",
194 ilist->filename,
195 ilist->line_nr);
196 if (!print_oneline)
197 printed += fprintf(fp, "\n");
198 }
199
200 inline_node__delete(inode);
201 }
202 }
203
204 if (symbol_conf.bt_stop_list && 176 if (symbol_conf.bt_stop_list &&
205 node->sym && 177 node->sym &&
206 strlist__has_entry(symbol_conf.bt_stop_list, 178 strlist__has_entry(symbol_conf.bt_stop_list,
diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h
index 9c2760a1a96e..046160831f90 100644
--- a/tools/perf/util/expr.h
+++ b/tools/perf/util/expr.h
@@ -1,7 +1,8 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PARSE_CTX_H 2#ifndef PARSE_CTX_H
2#define PARSE_CTX_H 1 3#define PARSE_CTX_H 1
3 4
4#define EXPR_MAX_OTHER 8 5#define EXPR_MAX_OTHER 15
5#define MAX_PARSE_ID EXPR_MAX_OTHER 6#define MAX_PARSE_ID EXPR_MAX_OTHER
6 7
7struct parse_id { 8struct parse_id {
diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y
index 954556bea36e..432b8560cf51 100644
--- a/tools/perf/util/expr.y
+++ b/tools/perf/util/expr.y
@@ -4,6 +4,7 @@
4#include "util/debug.h" 4#include "util/debug.h"
5#define IN_EXPR_Y 1 5#define IN_EXPR_Y 1
6#include "expr.h" 6#include "expr.h"
7#include "smt.h"
7#include <string.h> 8#include <string.h>
8 9
9#define MAXIDLEN 256 10#define MAXIDLEN 256
@@ -22,13 +23,15 @@
22 23
23%token <num> NUMBER 24%token <num> NUMBER
24%token <id> ID 25%token <id> ID
26%token MIN MAX IF ELSE SMT_ON
27%left MIN MAX IF
25%left '|' 28%left '|'
26%left '^' 29%left '^'
27%left '&' 30%left '&'
28%left '-' '+' 31%left '-' '+'
29%left '*' '/' '%' 32%left '*' '/' '%'
30%left NEG NOT 33%left NEG NOT
31%type <num> expr 34%type <num> expr if_expr
32 35
33%{ 36%{
34static int expr__lex(YYSTYPE *res, const char **pp); 37static int expr__lex(YYSTYPE *res, const char **pp);
@@ -57,22 +60,33 @@ static int lookup_id(struct parse_ctx *ctx, char *id, double *val)
57%} 60%}
58%% 61%%
59 62
60all_expr: expr { *final_val = $1; } 63all_expr: if_expr { *final_val = $1; }
64 ;
65
66if_expr:
67 expr IF expr ELSE expr { $$ = $3 ? $1 : $5; }
68 | expr
61 ; 69 ;
62 70
63expr: NUMBER 71expr: NUMBER
64 | ID { if (lookup_id(ctx, $1, &$$) < 0) { 72 | ID { if (lookup_id(ctx, $1, &$$) < 0) {
65 pr_debug("%s not found", $1); 73 pr_debug("%s not found\n", $1);
66 YYABORT; 74 YYABORT;
67 } 75 }
68 } 76 }
77 | expr '|' expr { $$ = (long)$1 | (long)$3; }
78 | expr '&' expr { $$ = (long)$1 & (long)$3; }
79 | expr '^' expr { $$ = (long)$1 ^ (long)$3; }
69 | expr '+' expr { $$ = $1 + $3; } 80 | expr '+' expr { $$ = $1 + $3; }
70 | expr '-' expr { $$ = $1 - $3; } 81 | expr '-' expr { $$ = $1 - $3; }
71 | expr '*' expr { $$ = $1 * $3; } 82 | expr '*' expr { $$ = $1 * $3; }
72 | expr '/' expr { if ($3 == 0) YYABORT; $$ = $1 / $3; } 83 | expr '/' expr { if ($3 == 0) YYABORT; $$ = $1 / $3; }
73 | expr '%' expr { if ((long)$3 == 0) YYABORT; $$ = (long)$1 % (long)$3; } 84 | expr '%' expr { if ((long)$3 == 0) YYABORT; $$ = (long)$1 % (long)$3; }
74 | '-' expr %prec NEG { $$ = -$2; } 85 | '-' expr %prec NEG { $$ = -$2; }
75 | '(' expr ')' { $$ = $2; } 86 | '(' if_expr ')' { $$ = $2; }
87 | MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; }
88 | MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; }
89 | SMT_ON { $$ = smt_on() > 0; }
76 ; 90 ;
77 91
78%% 92%%
@@ -82,13 +96,47 @@ static int expr__symbol(YYSTYPE *res, const char *p, const char **pp)
82 char *dst = res->id; 96 char *dst = res->id;
83 const char *s = p; 97 const char *s = p;
84 98
85 while (isalnum(*p) || *p == '_' || *p == '.') { 99 if (*p == '#')
100 *dst++ = *p++;
101
102 while (isalnum(*p) || *p == '_' || *p == '.' || *p == ':' || *p == '@' || *p == '\\') {
86 if (p - s >= MAXIDLEN) 103 if (p - s >= MAXIDLEN)
87 return -1; 104 return -1;
88 *dst++ = *p++; 105 /*
106 * Allow @ instead of / to be able to specify pmu/event/ without
107 * conflicts with normal division.
108 */
109 if (*p == '@')
110 *dst++ = '/';
111 else if (*p == '\\')
112 *dst++ = *++p;
113 else
114 *dst++ = *p;
115 p++;
89 } 116 }
90 *dst = 0; 117 *dst = 0;
91 *pp = p; 118 *pp = p;
119 dst = res->id;
120 switch (dst[0]) {
121 case 'm':
122 if (!strcmp(dst, "min"))
123 return MIN;
124 if (!strcmp(dst, "max"))
125 return MAX;
126 break;
127 case 'i':
128 if (!strcmp(dst, "if"))
129 return IF;
130 break;
131 case 'e':
132 if (!strcmp(dst, "else"))
133 return ELSE;
134 break;
135 case '#':
136 if (!strcasecmp(dst, "#smt_on"))
137 return SMT_ON;
138 break;
139 }
92 return ID; 140 return ID;
93} 141}
94 142
@@ -102,6 +150,7 @@ static int expr__lex(YYSTYPE *res, const char **pp)
102 p++; 150 p++;
103 s = p; 151 s = p;
104 switch (*p++) { 152 switch (*p++) {
153 case '#':
105 case 'a' ... 'z': 154 case 'a' ... 'z':
106 case 'A' ... 'Z': 155 case 'A' ... 'Z':
107 return expr__symbol(res, p - 1, pp); 156 return expr__symbol(res, p - 1, pp);
@@ -132,6 +181,19 @@ void expr__ctx_init(struct parse_ctx *ctx)
132 ctx->num_ids = 0; 181 ctx->num_ids = 0;
133} 182}
134 183
184static bool already_seen(const char *val, const char *one, const char **other,
185 int num_other)
186{
187 int i;
188
189 if (one && !strcasecmp(one, val))
190 return true;
191 for (i = 0; i < num_other; i++)
192 if (!strcasecmp(other[i], val))
193 return true;
194 return false;
195}
196
135int expr__find_other(const char *p, const char *one, const char ***other, 197int expr__find_other(const char *p, const char *one, const char ***other,
136 int *num_otherp) 198 int *num_otherp)
137{ 199{
@@ -151,7 +213,7 @@ int expr__find_other(const char *p, const char *one, const char ***other,
151 err = 0; 213 err = 0;
152 break; 214 break;
153 } 215 }
154 if (tok == ID && strcasecmp(one, val.id)) { 216 if (tok == ID && !already_seen(val.id, one, *other, num_other)) {
155 if (num_other >= EXPR_MAX_OTHER - 1) { 217 if (num_other >= EXPR_MAX_OTHER - 1) {
156 pr_debug("Too many extra events in %s\n", orig); 218 pr_debug("Too many extra events in %s\n", orig);
157 break; 219 break;
diff --git a/tools/perf/util/find-vdso-map.c b/tools/perf/util/find-vdso-map.c
index 95ef1cffc056..d7823e3508fc 100644
--- a/tools/perf/util/find-vdso-map.c
+++ b/tools/perf/util/find-vdso-map.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1static int find_vdso_map(void **start, void **end) 2static int find_vdso_map(void **start, void **end)
2{ 3{
3 FILE *maps; 4 FILE *maps;
diff --git a/tools/perf/util/genelf.h b/tools/perf/util/genelf.h
index 2424bd9862a3..de322d51c7fe 100644
--- a/tools/perf/util/genelf.h
+++ b/tools/perf/util/genelf.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __GENELF_H__ 2#ifndef __GENELF_H__
2#define __GENELF_H__ 3#define __GENELF_H__
3 4
diff --git a/tools/perf/util/generate-cmdlist.sh b/tools/perf/util/generate-cmdlist.sh
index 0ac2037c970c..9bbcec4e3365 100755
--- a/tools/perf/util/generate-cmdlist.sh
+++ b/tools/perf/util/generate-cmdlist.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2 3
3echo "/* Automatically generated by $0 */ 4echo "/* Automatically generated by $0 */
4struct cmdname_help 5struct cmdname_help
diff --git a/tools/perf/util/group.h b/tools/perf/util/group.h
index 116debe7a995..f36c7e31780a 100644
--- a/tools/perf/util/group.h
+++ b/tools/perf/util/group.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef GROUP_H 2#ifndef GROUP_H
2#define GROUP_H 1 3#define GROUP_H 1
3 4
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 76ed7d03e500..7c0e9d587bfa 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <inttypes.h> 3#include <inttypes.h>
3#include "util.h" 4#include "util.h"
@@ -12,6 +13,7 @@
12#include <linux/list.h> 13#include <linux/list.h>
13#include <linux/kernel.h> 14#include <linux/kernel.h>
14#include <linux/bitops.h> 15#include <linux/bitops.h>
16#include <linux/stringify.h>
15#include <sys/stat.h> 17#include <sys/stat.h>
16#include <sys/types.h> 18#include <sys/types.h>
17#include <sys/utsname.h> 19#include <sys/utsname.h>
@@ -34,6 +36,7 @@
34#include "data.h" 36#include "data.h"
35#include <api/fs/fs.h> 37#include <api/fs/fs.h>
36#include "asm/bug.h" 38#include "asm/bug.h"
39#include "tool.h"
37 40
38#include "sane_ctype.h" 41#include "sane_ctype.h"
39 42
@@ -59,6 +62,15 @@ struct perf_file_attr {
59 struct perf_file_section ids; 62 struct perf_file_section ids;
60}; 63};
61 64
65struct feat_fd {
66 struct perf_header *ph;
67 int fd;
68 void *buf; /* Either buf != NULL or fd >= 0 */
69 ssize_t offset;
70 size_t size;
71 struct perf_evsel *events;
72};
73
62void perf_header__set_feat(struct perf_header *header, int feat) 74void perf_header__set_feat(struct perf_header *header, int feat)
63{ 75{
64 set_bit(feat, header->adds_features); 76 set_bit(feat, header->adds_features);
@@ -74,28 +86,60 @@ bool perf_header__has_feat(const struct perf_header *header, int feat)
74 return test_bit(feat, header->adds_features); 86 return test_bit(feat, header->adds_features);
75} 87}
76 88
77static int do_write(int fd, const void *buf, size_t size) 89static int __do_write_fd(struct feat_fd *ff, const void *buf, size_t size)
78{ 90{
79 while (size) { 91 ssize_t ret = writen(ff->fd, buf, size);
80 int ret = write(fd, buf, size);
81 92
82 if (ret < 0) 93 if (ret != (ssize_t)size)
83 return -errno; 94 return ret < 0 ? (int)ret : -1;
95 return 0;
96}
97
98static int __do_write_buf(struct feat_fd *ff, const void *buf, size_t size)
99{
100 /* struct perf_event_header::size is u16 */
101 const size_t max_size = 0xffff - sizeof(struct perf_event_header);
102 size_t new_size = ff->size;
103 void *addr;
84 104
85 size -= ret; 105 if (size + ff->offset > max_size)
86 buf += ret; 106 return -E2BIG;
107
108 while (size > (new_size - ff->offset))
109 new_size <<= 1;
110 new_size = min(max_size, new_size);
111
112 if (ff->size < new_size) {
113 addr = realloc(ff->buf, new_size);
114 if (!addr)
115 return -ENOMEM;
116 ff->buf = addr;
117 ff->size = new_size;
87 } 118 }
88 119
120 memcpy(ff->buf + ff->offset, buf, size);
121 ff->offset += size;
122
89 return 0; 123 return 0;
90} 124}
91 125
92int write_padded(int fd, const void *bf, size_t count, size_t count_aligned) 126/* Return: 0 if succeded, -ERR if failed. */
127int do_write(struct feat_fd *ff, const void *buf, size_t size)
128{
129 if (!ff->buf)
130 return __do_write_fd(ff, buf, size);
131 return __do_write_buf(ff, buf, size);
132}
133
134/* Return: 0 if succeded, -ERR if failed. */
135int write_padded(struct feat_fd *ff, const void *bf,
136 size_t count, size_t count_aligned)
93{ 137{
94 static const char zero_buf[NAME_ALIGN]; 138 static const char zero_buf[NAME_ALIGN];
95 int err = do_write(fd, bf, count); 139 int err = do_write(ff, bf, count);
96 140
97 if (!err) 141 if (!err)
98 err = do_write(fd, zero_buf, count_aligned - count); 142 err = do_write(ff, zero_buf, count_aligned - count);
99 143
100 return err; 144 return err;
101} 145}
@@ -103,7 +147,8 @@ int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
103#define string_size(str) \ 147#define string_size(str) \
104 (PERF_ALIGN((strlen(str) + 1), NAME_ALIGN) + sizeof(u32)) 148 (PERF_ALIGN((strlen(str) + 1), NAME_ALIGN) + sizeof(u32))
105 149
106static int do_write_string(int fd, const char *str) 150/* Return: 0 if succeded, -ERR if failed. */
151static int do_write_string(struct feat_fd *ff, const char *str)
107{ 152{
108 u32 len, olen; 153 u32 len, olen;
109 int ret; 154 int ret;
@@ -112,32 +157,80 @@ static int do_write_string(int fd, const char *str)
112 len = PERF_ALIGN(olen, NAME_ALIGN); 157 len = PERF_ALIGN(olen, NAME_ALIGN);
113 158
114 /* write len, incl. \0 */ 159 /* write len, incl. \0 */
115 ret = do_write(fd, &len, sizeof(len)); 160 ret = do_write(ff, &len, sizeof(len));
116 if (ret < 0) 161 if (ret < 0)
117 return ret; 162 return ret;
118 163
119 return write_padded(fd, str, olen, len); 164 return write_padded(ff, str, olen, len);
120} 165}
121 166
122static char *do_read_string(int fd, struct perf_header *ph) 167static int __do_read_fd(struct feat_fd *ff, void *addr, ssize_t size)
168{
169 ssize_t ret = readn(ff->fd, addr, size);
170
171 if (ret != size)
172 return ret < 0 ? (int)ret : -1;
173 return 0;
174}
175
176static int __do_read_buf(struct feat_fd *ff, void *addr, ssize_t size)
177{
178 if (size > (ssize_t)ff->size - ff->offset)
179 return -1;
180
181 memcpy(addr, ff->buf + ff->offset, size);
182 ff->offset += size;
183
184 return 0;
185
186}
187
188static int __do_read(struct feat_fd *ff, void *addr, ssize_t size)
189{
190 if (!ff->buf)
191 return __do_read_fd(ff, addr, size);
192 return __do_read_buf(ff, addr, size);
193}
194
195static int do_read_u32(struct feat_fd *ff, u32 *addr)
196{
197 int ret;
198
199 ret = __do_read(ff, addr, sizeof(*addr));
200 if (ret)
201 return ret;
202
203 if (ff->ph->needs_swap)
204 *addr = bswap_32(*addr);
205 return 0;
206}
207
208static int do_read_u64(struct feat_fd *ff, u64 *addr)
209{
210 int ret;
211
212 ret = __do_read(ff, addr, sizeof(*addr));
213 if (ret)
214 return ret;
215
216 if (ff->ph->needs_swap)
217 *addr = bswap_64(*addr);
218 return 0;
219}
220
221static char *do_read_string(struct feat_fd *ff)
123{ 222{
124 ssize_t sz, ret;
125 u32 len; 223 u32 len;
126 char *buf; 224 char *buf;
127 225
128 sz = readn(fd, &len, sizeof(len)); 226 if (do_read_u32(ff, &len))
129 if (sz < (ssize_t)sizeof(len))
130 return NULL; 227 return NULL;
131 228
132 if (ph->needs_swap)
133 len = bswap_32(len);
134
135 buf = malloc(len); 229 buf = malloc(len);
136 if (!buf) 230 if (!buf)
137 return NULL; 231 return NULL;
138 232
139 ret = readn(fd, buf, len); 233 if (!__do_read(ff, buf, len)) {
140 if (ret == (ssize_t)len) {
141 /* 234 /*
142 * strings are padded by zeroes 235 * strings are padded by zeroes
143 * thus the actual strlen of buf 236 * thus the actual strlen of buf
@@ -150,25 +243,30 @@ static char *do_read_string(int fd, struct perf_header *ph)
150 return NULL; 243 return NULL;
151} 244}
152 245
153static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, 246static int write_tracing_data(struct feat_fd *ff,
154 struct perf_evlist *evlist) 247 struct perf_evlist *evlist)
155{ 248{
156 return read_tracing_data(fd, &evlist->entries); 249 if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
157} 250 return -1;
158 251
252 return read_tracing_data(ff->fd, &evlist->entries);
253}
159 254
160static int write_build_id(int fd, struct perf_header *h, 255static int write_build_id(struct feat_fd *ff,
161 struct perf_evlist *evlist __maybe_unused) 256 struct perf_evlist *evlist __maybe_unused)
162{ 257{
163 struct perf_session *session; 258 struct perf_session *session;
164 int err; 259 int err;
165 260
166 session = container_of(h, struct perf_session, header); 261 session = container_of(ff->ph, struct perf_session, header);
167 262
168 if (!perf_session__read_build_ids(session, true)) 263 if (!perf_session__read_build_ids(session, true))
169 return -1; 264 return -1;
170 265
171 err = perf_session__write_buildid_table(session, fd); 266 if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
267 return -1;
268
269 err = perf_session__write_buildid_table(session, ff);
172 if (err < 0) { 270 if (err < 0) {
173 pr_debug("failed to write buildid table\n"); 271 pr_debug("failed to write buildid table\n");
174 return err; 272 return err;
@@ -178,7 +276,7 @@ static int write_build_id(int fd, struct perf_header *h,
178 return 0; 276 return 0;
179} 277}
180 278
181static int write_hostname(int fd, struct perf_header *h __maybe_unused, 279static int write_hostname(struct feat_fd *ff,
182 struct perf_evlist *evlist __maybe_unused) 280 struct perf_evlist *evlist __maybe_unused)
183{ 281{
184 struct utsname uts; 282 struct utsname uts;
@@ -188,10 +286,10 @@ static int write_hostname(int fd, struct perf_header *h __maybe_unused,
188 if (ret < 0) 286 if (ret < 0)
189 return -1; 287 return -1;
190 288
191 return do_write_string(fd, uts.nodename); 289 return do_write_string(ff, uts.nodename);
192} 290}
193 291
194static int write_osrelease(int fd, struct perf_header *h __maybe_unused, 292static int write_osrelease(struct feat_fd *ff,
195 struct perf_evlist *evlist __maybe_unused) 293 struct perf_evlist *evlist __maybe_unused)
196{ 294{
197 struct utsname uts; 295 struct utsname uts;
@@ -201,10 +299,10 @@ static int write_osrelease(int fd, struct perf_header *h __maybe_unused,
201 if (ret < 0) 299 if (ret < 0)
202 return -1; 300 return -1;
203 301
204 return do_write_string(fd, uts.release); 302 return do_write_string(ff, uts.release);
205} 303}
206 304
207static int write_arch(int fd, struct perf_header *h __maybe_unused, 305static int write_arch(struct feat_fd *ff,
208 struct perf_evlist *evlist __maybe_unused) 306 struct perf_evlist *evlist __maybe_unused)
209{ 307{
210 struct utsname uts; 308 struct utsname uts;
@@ -214,16 +312,16 @@ static int write_arch(int fd, struct perf_header *h __maybe_unused,
214 if (ret < 0) 312 if (ret < 0)
215 return -1; 313 return -1;
216 314
217 return do_write_string(fd, uts.machine); 315 return do_write_string(ff, uts.machine);
218} 316}
219 317
220static int write_version(int fd, struct perf_header *h __maybe_unused, 318static int write_version(struct feat_fd *ff,
221 struct perf_evlist *evlist __maybe_unused) 319 struct perf_evlist *evlist __maybe_unused)
222{ 320{
223 return do_write_string(fd, perf_version_string); 321 return do_write_string(ff, perf_version_string);
224} 322}
225 323
226static int __write_cpudesc(int fd, const char *cpuinfo_proc) 324static int __write_cpudesc(struct feat_fd *ff, const char *cpuinfo_proc)
227{ 325{
228 FILE *file; 326 FILE *file;
229 char *buf = NULL; 327 char *buf = NULL;
@@ -273,25 +371,22 @@ static int __write_cpudesc(int fd, const char *cpuinfo_proc)
273 } 371 }
274 p++; 372 p++;
275 } 373 }
276 ret = do_write_string(fd, s); 374 ret = do_write_string(ff, s);
277done: 375done:
278 free(buf); 376 free(buf);
279 fclose(file); 377 fclose(file);
280 return ret; 378 return ret;
281} 379}
282 380
283static int write_cpudesc(int fd, struct perf_header *h __maybe_unused, 381static int write_cpudesc(struct feat_fd *ff,
284 struct perf_evlist *evlist __maybe_unused) 382 struct perf_evlist *evlist __maybe_unused)
285{ 383{
286#ifndef CPUINFO_PROC
287#define CPUINFO_PROC {"model name", }
288#endif
289 const char *cpuinfo_procs[] = CPUINFO_PROC; 384 const char *cpuinfo_procs[] = CPUINFO_PROC;
290 unsigned int i; 385 unsigned int i;
291 386
292 for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) { 387 for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) {
293 int ret; 388 int ret;
294 ret = __write_cpudesc(fd, cpuinfo_procs[i]); 389 ret = __write_cpudesc(ff, cpuinfo_procs[i]);
295 if (ret >= 0) 390 if (ret >= 0)
296 return ret; 391 return ret;
297 } 392 }
@@ -299,7 +394,7 @@ static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
299} 394}
300 395
301 396
302static int write_nrcpus(int fd, struct perf_header *h __maybe_unused, 397static int write_nrcpus(struct feat_fd *ff,
303 struct perf_evlist *evlist __maybe_unused) 398 struct perf_evlist *evlist __maybe_unused)
304{ 399{
305 long nr; 400 long nr;
@@ -314,14 +409,14 @@ static int write_nrcpus(int fd, struct perf_header *h __maybe_unused,
314 409
315 nra = (u32)(nr & UINT_MAX); 410 nra = (u32)(nr & UINT_MAX);
316 411
317 ret = do_write(fd, &nrc, sizeof(nrc)); 412 ret = do_write(ff, &nrc, sizeof(nrc));
318 if (ret < 0) 413 if (ret < 0)
319 return ret; 414 return ret;
320 415
321 return do_write(fd, &nra, sizeof(nra)); 416 return do_write(ff, &nra, sizeof(nra));
322} 417}
323 418
324static int write_event_desc(int fd, struct perf_header *h __maybe_unused, 419static int write_event_desc(struct feat_fd *ff,
325 struct perf_evlist *evlist) 420 struct perf_evlist *evlist)
326{ 421{
327 struct perf_evsel *evsel; 422 struct perf_evsel *evsel;
@@ -333,7 +428,7 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
333 /* 428 /*
334 * write number of events 429 * write number of events
335 */ 430 */
336 ret = do_write(fd, &nre, sizeof(nre)); 431 ret = do_write(ff, &nre, sizeof(nre));
337 if (ret < 0) 432 if (ret < 0)
338 return ret; 433 return ret;
339 434
@@ -341,12 +436,12 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
341 * size of perf_event_attr struct 436 * size of perf_event_attr struct
342 */ 437 */
343 sz = (u32)sizeof(evsel->attr); 438 sz = (u32)sizeof(evsel->attr);
344 ret = do_write(fd, &sz, sizeof(sz)); 439 ret = do_write(ff, &sz, sizeof(sz));
345 if (ret < 0) 440 if (ret < 0)
346 return ret; 441 return ret;
347 442
348 evlist__for_each_entry(evlist, evsel) { 443 evlist__for_each_entry(evlist, evsel) {
349 ret = do_write(fd, &evsel->attr, sz); 444 ret = do_write(ff, &evsel->attr, sz);
350 if (ret < 0) 445 if (ret < 0)
351 return ret; 446 return ret;
352 /* 447 /*
@@ -357,27 +452,27 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
357 * type of ids, 452 * type of ids,
358 */ 453 */
359 nri = evsel->ids; 454 nri = evsel->ids;
360 ret = do_write(fd, &nri, sizeof(nri)); 455 ret = do_write(ff, &nri, sizeof(nri));
361 if (ret < 0) 456 if (ret < 0)
362 return ret; 457 return ret;
363 458
364 /* 459 /*
365 * write event string as passed on cmdline 460 * write event string as passed on cmdline
366 */ 461 */
367 ret = do_write_string(fd, perf_evsel__name(evsel)); 462 ret = do_write_string(ff, perf_evsel__name(evsel));
368 if (ret < 0) 463 if (ret < 0)
369 return ret; 464 return ret;
370 /* 465 /*
371 * write unique ids for this event 466 * write unique ids for this event
372 */ 467 */
373 ret = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); 468 ret = do_write(ff, evsel->id, evsel->ids * sizeof(u64));
374 if (ret < 0) 469 if (ret < 0)
375 return ret; 470 return ret;
376 } 471 }
377 return 0; 472 return 0;
378} 473}
379 474
380static int write_cmdline(int fd, struct perf_header *h __maybe_unused, 475static int write_cmdline(struct feat_fd *ff,
381 struct perf_evlist *evlist __maybe_unused) 476 struct perf_evlist *evlist __maybe_unused)
382{ 477{
383 char buf[MAXPATHLEN]; 478 char buf[MAXPATHLEN];
@@ -395,16 +490,16 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
395 /* account for binary path */ 490 /* account for binary path */
396 n = perf_env.nr_cmdline + 1; 491 n = perf_env.nr_cmdline + 1;
397 492
398 ret = do_write(fd, &n, sizeof(n)); 493 ret = do_write(ff, &n, sizeof(n));
399 if (ret < 0) 494 if (ret < 0)
400 return ret; 495 return ret;
401 496
402 ret = do_write_string(fd, buf); 497 ret = do_write_string(ff, buf);
403 if (ret < 0) 498 if (ret < 0)
404 return ret; 499 return ret;
405 500
406 for (i = 0 ; i < perf_env.nr_cmdline; i++) { 501 for (i = 0 ; i < perf_env.nr_cmdline; i++) {
407 ret = do_write_string(fd, perf_env.cmdline_argv[i]); 502 ret = do_write_string(ff, perf_env.cmdline_argv[i]);
408 if (ret < 0) 503 if (ret < 0)
409 return ret; 504 return ret;
410 } 505 }
@@ -557,8 +652,8 @@ out_free:
557 return tp; 652 return tp;
558} 653}
559 654
560static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, 655static int write_cpu_topology(struct feat_fd *ff,
561 struct perf_evlist *evlist __maybe_unused) 656 struct perf_evlist *evlist __maybe_unused)
562{ 657{
563 struct cpu_topo *tp; 658 struct cpu_topo *tp;
564 u32 i; 659 u32 i;
@@ -568,21 +663,21 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
568 if (!tp) 663 if (!tp)
569 return -1; 664 return -1;
570 665
571 ret = do_write(fd, &tp->core_sib, sizeof(tp->core_sib)); 666 ret = do_write(ff, &tp->core_sib, sizeof(tp->core_sib));
572 if (ret < 0) 667 if (ret < 0)
573 goto done; 668 goto done;
574 669
575 for (i = 0; i < tp->core_sib; i++) { 670 for (i = 0; i < tp->core_sib; i++) {
576 ret = do_write_string(fd, tp->core_siblings[i]); 671 ret = do_write_string(ff, tp->core_siblings[i]);
577 if (ret < 0) 672 if (ret < 0)
578 goto done; 673 goto done;
579 } 674 }
580 ret = do_write(fd, &tp->thread_sib, sizeof(tp->thread_sib)); 675 ret = do_write(ff, &tp->thread_sib, sizeof(tp->thread_sib));
581 if (ret < 0) 676 if (ret < 0)
582 goto done; 677 goto done;
583 678
584 for (i = 0; i < tp->thread_sib; i++) { 679 for (i = 0; i < tp->thread_sib; i++) {
585 ret = do_write_string(fd, tp->thread_siblings[i]); 680 ret = do_write_string(ff, tp->thread_siblings[i]);
586 if (ret < 0) 681 if (ret < 0)
587 break; 682 break;
588 } 683 }
@@ -592,11 +687,11 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
592 goto done; 687 goto done;
593 688
594 for (j = 0; j < perf_env.nr_cpus_avail; j++) { 689 for (j = 0; j < perf_env.nr_cpus_avail; j++) {
595 ret = do_write(fd, &perf_env.cpu[j].core_id, 690 ret = do_write(ff, &perf_env.cpu[j].core_id,
596 sizeof(perf_env.cpu[j].core_id)); 691 sizeof(perf_env.cpu[j].core_id));
597 if (ret < 0) 692 if (ret < 0)
598 return ret; 693 return ret;
599 ret = do_write(fd, &perf_env.cpu[j].socket_id, 694 ret = do_write(ff, &perf_env.cpu[j].socket_id,
600 sizeof(perf_env.cpu[j].socket_id)); 695 sizeof(perf_env.cpu[j].socket_id));
601 if (ret < 0) 696 if (ret < 0)
602 return ret; 697 return ret;
@@ -608,8 +703,8 @@ done:
608 703
609 704
610 705
611static int write_total_mem(int fd, struct perf_header *h __maybe_unused, 706static int write_total_mem(struct feat_fd *ff,
612 struct perf_evlist *evlist __maybe_unused) 707 struct perf_evlist *evlist __maybe_unused)
613{ 708{
614 char *buf = NULL; 709 char *buf = NULL;
615 FILE *fp; 710 FILE *fp;
@@ -629,7 +724,7 @@ static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
629 if (!ret) { 724 if (!ret) {
630 n = sscanf(buf, "%*s %"PRIu64, &mem); 725 n = sscanf(buf, "%*s %"PRIu64, &mem);
631 if (n == 1) 726 if (n == 1)
632 ret = do_write(fd, &mem, sizeof(mem)); 727 ret = do_write(ff, &mem, sizeof(mem));
633 } else 728 } else
634 ret = -1; 729 ret = -1;
635 free(buf); 730 free(buf);
@@ -637,7 +732,7 @@ static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
637 return ret; 732 return ret;
638} 733}
639 734
640static int write_topo_node(int fd, int node) 735static int write_topo_node(struct feat_fd *ff, int node)
641{ 736{
642 char str[MAXPATHLEN]; 737 char str[MAXPATHLEN];
643 char field[32]; 738 char field[32];
@@ -667,11 +762,11 @@ static int write_topo_node(int fd, int node)
667 fclose(fp); 762 fclose(fp);
668 fp = NULL; 763 fp = NULL;
669 764
670 ret = do_write(fd, &mem_total, sizeof(u64)); 765 ret = do_write(ff, &mem_total, sizeof(u64));
671 if (ret) 766 if (ret)
672 goto done; 767 goto done;
673 768
674 ret = do_write(fd, &mem_free, sizeof(u64)); 769 ret = do_write(ff, &mem_free, sizeof(u64));
675 if (ret) 770 if (ret)
676 goto done; 771 goto done;
677 772
@@ -689,7 +784,7 @@ static int write_topo_node(int fd, int node)
689 if (p) 784 if (p)
690 *p = '\0'; 785 *p = '\0';
691 786
692 ret = do_write_string(fd, buf); 787 ret = do_write_string(ff, buf);
693done: 788done:
694 free(buf); 789 free(buf);
695 if (fp) 790 if (fp)
@@ -697,8 +792,8 @@ done:
697 return ret; 792 return ret;
698} 793}
699 794
700static int write_numa_topology(int fd, struct perf_header *h __maybe_unused, 795static int write_numa_topology(struct feat_fd *ff,
701 struct perf_evlist *evlist __maybe_unused) 796 struct perf_evlist *evlist __maybe_unused)
702{ 797{
703 char *buf = NULL; 798 char *buf = NULL;
704 size_t len = 0; 799 size_t len = 0;
@@ -725,17 +820,17 @@ static int write_numa_topology(int fd, struct perf_header *h __maybe_unused,
725 820
726 nr = (u32)node_map->nr; 821 nr = (u32)node_map->nr;
727 822
728 ret = do_write(fd, &nr, sizeof(nr)); 823 ret = do_write(ff, &nr, sizeof(nr));
729 if (ret < 0) 824 if (ret < 0)
730 goto done; 825 goto done;
731 826
732 for (i = 0; i < nr; i++) { 827 for (i = 0; i < nr; i++) {
733 j = (u32)node_map->map[i]; 828 j = (u32)node_map->map[i];
734 ret = do_write(fd, &j, sizeof(j)); 829 ret = do_write(ff, &j, sizeof(j));
735 if (ret < 0) 830 if (ret < 0)
736 break; 831 break;
737 832
738 ret = write_topo_node(fd, i); 833 ret = write_topo_node(ff, i);
739 if (ret < 0) 834 if (ret < 0)
740 break; 835 break;
741 } 836 }
@@ -758,39 +853,40 @@ done:
758 * }; 853 * };
759 */ 854 */
760 855
761static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused, 856static int write_pmu_mappings(struct feat_fd *ff,
762 struct perf_evlist *evlist __maybe_unused) 857 struct perf_evlist *evlist __maybe_unused)
763{ 858{
764 struct perf_pmu *pmu = NULL; 859 struct perf_pmu *pmu = NULL;
765 off_t offset = lseek(fd, 0, SEEK_CUR); 860 u32 pmu_num = 0;
766 __u32 pmu_num = 0;
767 int ret; 861 int ret;
768 862
769 /* write real pmu_num later */ 863 /*
770 ret = do_write(fd, &pmu_num, sizeof(pmu_num)); 864 * Do a first pass to count number of pmu to avoid lseek so this
865 * works in pipe mode as well.
866 */
867 while ((pmu = perf_pmu__scan(pmu))) {
868 if (!pmu->name)
869 continue;
870 pmu_num++;
871 }
872
873 ret = do_write(ff, &pmu_num, sizeof(pmu_num));
771 if (ret < 0) 874 if (ret < 0)
772 return ret; 875 return ret;
773 876
774 while ((pmu = perf_pmu__scan(pmu))) { 877 while ((pmu = perf_pmu__scan(pmu))) {
775 if (!pmu->name) 878 if (!pmu->name)
776 continue; 879 continue;
777 pmu_num++;
778 880
779 ret = do_write(fd, &pmu->type, sizeof(pmu->type)); 881 ret = do_write(ff, &pmu->type, sizeof(pmu->type));
780 if (ret < 0) 882 if (ret < 0)
781 return ret; 883 return ret;
782 884
783 ret = do_write_string(fd, pmu->name); 885 ret = do_write_string(ff, pmu->name);
784 if (ret < 0) 886 if (ret < 0)
785 return ret; 887 return ret;
786 } 888 }
787 889
788 if (pwrite(fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) {
789 /* discard all */
790 lseek(fd, offset, SEEK_SET);
791 return -1;
792 }
793
794 return 0; 890 return 0;
795} 891}
796 892
@@ -806,14 +902,14 @@ static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused,
806 * }[nr_groups]; 902 * }[nr_groups];
807 * }; 903 * };
808 */ 904 */
809static int write_group_desc(int fd, struct perf_header *h __maybe_unused, 905static int write_group_desc(struct feat_fd *ff,
810 struct perf_evlist *evlist) 906 struct perf_evlist *evlist)
811{ 907{
812 u32 nr_groups = evlist->nr_groups; 908 u32 nr_groups = evlist->nr_groups;
813 struct perf_evsel *evsel; 909 struct perf_evsel *evsel;
814 int ret; 910 int ret;
815 911
816 ret = do_write(fd, &nr_groups, sizeof(nr_groups)); 912 ret = do_write(ff, &nr_groups, sizeof(nr_groups));
817 if (ret < 0) 913 if (ret < 0)
818 return ret; 914 return ret;
819 915
@@ -824,15 +920,15 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
824 u32 leader_idx = evsel->idx; 920 u32 leader_idx = evsel->idx;
825 u32 nr_members = evsel->nr_members; 921 u32 nr_members = evsel->nr_members;
826 922
827 ret = do_write_string(fd, name); 923 ret = do_write_string(ff, name);
828 if (ret < 0) 924 if (ret < 0)
829 return ret; 925 return ret;
830 926
831 ret = do_write(fd, &leader_idx, sizeof(leader_idx)); 927 ret = do_write(ff, &leader_idx, sizeof(leader_idx));
832 if (ret < 0) 928 if (ret < 0)
833 return ret; 929 return ret;
834 930
835 ret = do_write(fd, &nr_members, sizeof(nr_members)); 931 ret = do_write(ff, &nr_members, sizeof(nr_members));
836 if (ret < 0) 932 if (ret < 0)
837 return ret; 933 return ret;
838 } 934 }
@@ -849,7 +945,7 @@ int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
849 return -1; 945 return -1;
850} 946}
851 947
852static int write_cpuid(int fd, struct perf_header *h __maybe_unused, 948static int write_cpuid(struct feat_fd *ff,
853 struct perf_evlist *evlist __maybe_unused) 949 struct perf_evlist *evlist __maybe_unused)
854{ 950{
855 char buffer[64]; 951 char buffer[64];
@@ -861,25 +957,27 @@ static int write_cpuid(int fd, struct perf_header *h __maybe_unused,
861 957
862 return -1; 958 return -1;
863write_it: 959write_it:
864 return do_write_string(fd, buffer); 960 return do_write_string(ff, buffer);
865} 961}
866 962
867static int write_branch_stack(int fd __maybe_unused, 963static int write_branch_stack(struct feat_fd *ff __maybe_unused,
868 struct perf_header *h __maybe_unused, 964 struct perf_evlist *evlist __maybe_unused)
869 struct perf_evlist *evlist __maybe_unused)
870{ 965{
871 return 0; 966 return 0;
872} 967}
873 968
874static int write_auxtrace(int fd, struct perf_header *h, 969static int write_auxtrace(struct feat_fd *ff,
875 struct perf_evlist *evlist __maybe_unused) 970 struct perf_evlist *evlist __maybe_unused)
876{ 971{
877 struct perf_session *session; 972 struct perf_session *session;
878 int err; 973 int err;
879 974
880 session = container_of(h, struct perf_session, header); 975 if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
976 return -1;
977
978 session = container_of(ff->ph, struct perf_session, header);
881 979
882 err = auxtrace_index__write(fd, &session->auxtrace_index); 980 err = auxtrace_index__write(ff->fd, &session->auxtrace_index);
883 if (err < 0) 981 if (err < 0)
884 pr_err("Failed to write auxtrace index\n"); 982 pr_err("Failed to write auxtrace index\n");
885 return err; 983 return err;
@@ -1026,8 +1124,8 @@ static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)
1026 1124
1027#define MAX_CACHES 2000 1125#define MAX_CACHES 2000
1028 1126
1029static int write_cache(int fd, struct perf_header *h __maybe_unused, 1127static int write_cache(struct feat_fd *ff,
1030 struct perf_evlist *evlist __maybe_unused) 1128 struct perf_evlist *evlist __maybe_unused)
1031{ 1129{
1032 struct cpu_cache_level caches[MAX_CACHES]; 1130 struct cpu_cache_level caches[MAX_CACHES];
1033 u32 cnt = 0, i, version = 1; 1131 u32 cnt = 0, i, version = 1;
@@ -1039,11 +1137,11 @@ static int write_cache(int fd, struct perf_header *h __maybe_unused,
1039 1137
1040 qsort(&caches, cnt, sizeof(struct cpu_cache_level), cpu_cache_level__sort); 1138 qsort(&caches, cnt, sizeof(struct cpu_cache_level), cpu_cache_level__sort);
1041 1139
1042 ret = do_write(fd, &version, sizeof(u32)); 1140 ret = do_write(ff, &version, sizeof(u32));
1043 if (ret < 0) 1141 if (ret < 0)
1044 goto out; 1142 goto out;
1045 1143
1046 ret = do_write(fd, &cnt, sizeof(u32)); 1144 ret = do_write(ff, &cnt, sizeof(u32));
1047 if (ret < 0) 1145 if (ret < 0)
1048 goto out; 1146 goto out;
1049 1147
@@ -1051,7 +1149,7 @@ static int write_cache(int fd, struct perf_header *h __maybe_unused,
1051 struct cpu_cache_level *c = &caches[i]; 1149 struct cpu_cache_level *c = &caches[i];
1052 1150
1053 #define _W(v) \ 1151 #define _W(v) \
1054 ret = do_write(fd, &c->v, sizeof(u32)); \ 1152 ret = do_write(ff, &c->v, sizeof(u32)); \
1055 if (ret < 0) \ 1153 if (ret < 0) \
1056 goto out; 1154 goto out;
1057 1155
@@ -1062,7 +1160,7 @@ static int write_cache(int fd, struct perf_header *h __maybe_unused,
1062 #undef _W 1160 #undef _W
1063 1161
1064 #define _W(v) \ 1162 #define _W(v) \
1065 ret = do_write_string(fd, (const char *) c->v); \ 1163 ret = do_write_string(ff, (const char *) c->v); \
1066 if (ret < 0) \ 1164 if (ret < 0) \
1067 goto out; 1165 goto out;
1068 1166
@@ -1078,69 +1176,62 @@ out:
1078 return ret; 1176 return ret;
1079} 1177}
1080 1178
1081static int write_stat(int fd __maybe_unused, 1179static int write_stat(struct feat_fd *ff __maybe_unused,
1082 struct perf_header *h __maybe_unused,
1083 struct perf_evlist *evlist __maybe_unused) 1180 struct perf_evlist *evlist __maybe_unused)
1084{ 1181{
1085 return 0; 1182 return 0;
1086} 1183}
1087 1184
1088static void print_hostname(struct perf_header *ph, int fd __maybe_unused, 1185static void print_hostname(struct feat_fd *ff, FILE *fp)
1089 FILE *fp)
1090{ 1186{
1091 fprintf(fp, "# hostname : %s\n", ph->env.hostname); 1187 fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname);
1092} 1188}
1093 1189
1094static void print_osrelease(struct perf_header *ph, int fd __maybe_unused, 1190static void print_osrelease(struct feat_fd *ff, FILE *fp)
1095 FILE *fp)
1096{ 1191{
1097 fprintf(fp, "# os release : %s\n", ph->env.os_release); 1192 fprintf(fp, "# os release : %s\n", ff->ph->env.os_release);
1098} 1193}
1099 1194
1100static void print_arch(struct perf_header *ph, int fd __maybe_unused, FILE *fp) 1195static void print_arch(struct feat_fd *ff, FILE *fp)
1101{ 1196{
1102 fprintf(fp, "# arch : %s\n", ph->env.arch); 1197 fprintf(fp, "# arch : %s\n", ff->ph->env.arch);
1103} 1198}
1104 1199
1105static void print_cpudesc(struct perf_header *ph, int fd __maybe_unused, 1200static void print_cpudesc(struct feat_fd *ff, FILE *fp)
1106 FILE *fp)
1107{ 1201{
1108 fprintf(fp, "# cpudesc : %s\n", ph->env.cpu_desc); 1202 fprintf(fp, "# cpudesc : %s\n", ff->ph->env.cpu_desc);
1109} 1203}
1110 1204
1111static void print_nrcpus(struct perf_header *ph, int fd __maybe_unused, 1205static void print_nrcpus(struct feat_fd *ff, FILE *fp)
1112 FILE *fp)
1113{ 1206{
1114 fprintf(fp, "# nrcpus online : %u\n", ph->env.nr_cpus_online); 1207 fprintf(fp, "# nrcpus online : %u\n", ff->ph->env.nr_cpus_online);
1115 fprintf(fp, "# nrcpus avail : %u\n", ph->env.nr_cpus_avail); 1208 fprintf(fp, "# nrcpus avail : %u\n", ff->ph->env.nr_cpus_avail);
1116} 1209}
1117 1210
1118static void print_version(struct perf_header *ph, int fd __maybe_unused, 1211static void print_version(struct feat_fd *ff, FILE *fp)
1119 FILE *fp)
1120{ 1212{
1121 fprintf(fp, "# perf version : %s\n", ph->env.version); 1213 fprintf(fp, "# perf version : %s\n", ff->ph->env.version);
1122} 1214}
1123 1215
1124static void print_cmdline(struct perf_header *ph, int fd __maybe_unused, 1216static void print_cmdline(struct feat_fd *ff, FILE *fp)
1125 FILE *fp)
1126{ 1217{
1127 int nr, i; 1218 int nr, i;
1128 1219
1129 nr = ph->env.nr_cmdline; 1220 nr = ff->ph->env.nr_cmdline;
1130 1221
1131 fprintf(fp, "# cmdline : "); 1222 fprintf(fp, "# cmdline : ");
1132 1223
1133 for (i = 0; i < nr; i++) 1224 for (i = 0; i < nr; i++)
1134 fprintf(fp, "%s ", ph->env.cmdline_argv[i]); 1225 fprintf(fp, "%s ", ff->ph->env.cmdline_argv[i]);
1135 fputc('\n', fp); 1226 fputc('\n', fp);
1136} 1227}
1137 1228
1138static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused, 1229static void print_cpu_topology(struct feat_fd *ff, FILE *fp)
1139 FILE *fp)
1140{ 1230{
1231 struct perf_header *ph = ff->ph;
1232 int cpu_nr = ph->env.nr_cpus_avail;
1141 int nr, i; 1233 int nr, i;
1142 char *str; 1234 char *str;
1143 int cpu_nr = ph->env.nr_cpus_avail;
1144 1235
1145 nr = ph->env.nr_sibling_cores; 1236 nr = ph->env.nr_sibling_cores;
1146 str = ph->env.sibling_cores; 1237 str = ph->env.sibling_cores;
@@ -1181,31 +1272,21 @@ static void free_event_desc(struct perf_evsel *events)
1181 free(events); 1272 free(events);
1182} 1273}
1183 1274
1184static struct perf_evsel * 1275static struct perf_evsel *read_event_desc(struct feat_fd *ff)
1185read_event_desc(struct perf_header *ph, int fd)
1186{ 1276{
1187 struct perf_evsel *evsel, *events = NULL; 1277 struct perf_evsel *evsel, *events = NULL;
1188 u64 *id; 1278 u64 *id;
1189 void *buf = NULL; 1279 void *buf = NULL;
1190 u32 nre, sz, nr, i, j; 1280 u32 nre, sz, nr, i, j;
1191 ssize_t ret;
1192 size_t msz; 1281 size_t msz;
1193 1282
1194 /* number of events */ 1283 /* number of events */
1195 ret = readn(fd, &nre, sizeof(nre)); 1284 if (do_read_u32(ff, &nre))
1196 if (ret != (ssize_t)sizeof(nre))
1197 goto error; 1285 goto error;
1198 1286
1199 if (ph->needs_swap) 1287 if (do_read_u32(ff, &sz))
1200 nre = bswap_32(nre);
1201
1202 ret = readn(fd, &sz, sizeof(sz));
1203 if (ret != (ssize_t)sizeof(sz))
1204 goto error; 1288 goto error;
1205 1289
1206 if (ph->needs_swap)
1207 sz = bswap_32(sz);
1208
1209 /* buffer to hold on file attr struct */ 1290 /* buffer to hold on file attr struct */
1210 buf = malloc(sz); 1291 buf = malloc(sz);
1211 if (!buf) 1292 if (!buf)
@@ -1227,25 +1308,23 @@ read_event_desc(struct perf_header *ph, int fd)
1227 * must read entire on-file attr struct to 1308 * must read entire on-file attr struct to
1228 * sync up with layout. 1309 * sync up with layout.
1229 */ 1310 */
1230 ret = readn(fd, buf, sz); 1311 if (__do_read(ff, buf, sz))
1231 if (ret != (ssize_t)sz)
1232 goto error; 1312 goto error;
1233 1313
1234 if (ph->needs_swap) 1314 if (ff->ph->needs_swap)
1235 perf_event__attr_swap(buf); 1315 perf_event__attr_swap(buf);
1236 1316
1237 memcpy(&evsel->attr, buf, msz); 1317 memcpy(&evsel->attr, buf, msz);
1238 1318
1239 ret = readn(fd, &nr, sizeof(nr)); 1319 if (do_read_u32(ff, &nr))
1240 if (ret != (ssize_t)sizeof(nr))
1241 goto error; 1320 goto error;
1242 1321
1243 if (ph->needs_swap) { 1322 if (ff->ph->needs_swap)
1244 nr = bswap_32(nr);
1245 evsel->needs_swap = true; 1323 evsel->needs_swap = true;
1246 }
1247 1324
1248 evsel->name = do_read_string(fd, ph); 1325 evsel->name = do_read_string(ff);
1326 if (!evsel->name)
1327 goto error;
1249 1328
1250 if (!nr) 1329 if (!nr)
1251 continue; 1330 continue;
@@ -1257,11 +1336,8 @@ read_event_desc(struct perf_header *ph, int fd)
1257 evsel->id = id; 1336 evsel->id = id;
1258 1337
1259 for (j = 0 ; j < nr; j++) { 1338 for (j = 0 ; j < nr; j++) {
1260 ret = readn(fd, id, sizeof(*id)); 1339 if (do_read_u64(ff, id))
1261 if (ret != (ssize_t)sizeof(*id))
1262 goto error; 1340 goto error;
1263 if (ph->needs_swap)
1264 *id = bswap_64(*id);
1265 id++; 1341 id++;
1266 } 1342 }
1267 } 1343 }
@@ -1280,12 +1356,17 @@ static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val,
1280 return fprintf(fp, ", %s = %s", name, val); 1356 return fprintf(fp, ", %s = %s", name, val);
1281} 1357}
1282 1358
1283static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) 1359static void print_event_desc(struct feat_fd *ff, FILE *fp)
1284{ 1360{
1285 struct perf_evsel *evsel, *events = read_event_desc(ph, fd); 1361 struct perf_evsel *evsel, *events;
1286 u32 j; 1362 u32 j;
1287 u64 *id; 1363 u64 *id;
1288 1364
1365 if (ff->events)
1366 events = ff->events;
1367 else
1368 events = read_event_desc(ff);
1369
1289 if (!events) { 1370 if (!events) {
1290 fprintf(fp, "# event desc: not available or unable to read\n"); 1371 fprintf(fp, "# event desc: not available or unable to read\n");
1291 return; 1372 return;
@@ -1310,22 +1391,21 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1310 } 1391 }
1311 1392
1312 free_event_desc(events); 1393 free_event_desc(events);
1394 ff->events = NULL;
1313} 1395}
1314 1396
1315static void print_total_mem(struct perf_header *ph, int fd __maybe_unused, 1397static void print_total_mem(struct feat_fd *ff, FILE *fp)
1316 FILE *fp)
1317{ 1398{
1318 fprintf(fp, "# total memory : %Lu kB\n", ph->env.total_mem); 1399 fprintf(fp, "# total memory : %llu kB\n", ff->ph->env.total_mem);
1319} 1400}
1320 1401
1321static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused, 1402static void print_numa_topology(struct feat_fd *ff, FILE *fp)
1322 FILE *fp)
1323{ 1403{
1324 int i; 1404 int i;
1325 struct numa_node *n; 1405 struct numa_node *n;
1326 1406
1327 for (i = 0; i < ph->env.nr_numa_nodes; i++) { 1407 for (i = 0; i < ff->ph->env.nr_numa_nodes; i++) {
1328 n = &ph->env.numa_nodes[i]; 1408 n = &ff->ph->env.numa_nodes[i];
1329 1409
1330 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB," 1410 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB,"
1331 " free = %"PRIu64" kB\n", 1411 " free = %"PRIu64" kB\n",
@@ -1336,56 +1416,51 @@ static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused,
1336 } 1416 }
1337} 1417}
1338 1418
1339static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp) 1419static void print_cpuid(struct feat_fd *ff, FILE *fp)
1340{ 1420{
1341 fprintf(fp, "# cpuid : %s\n", ph->env.cpuid); 1421 fprintf(fp, "# cpuid : %s\n", ff->ph->env.cpuid);
1342} 1422}
1343 1423
1344static void print_branch_stack(struct perf_header *ph __maybe_unused, 1424static void print_branch_stack(struct feat_fd *ff __maybe_unused, FILE *fp)
1345 int fd __maybe_unused, FILE *fp)
1346{ 1425{
1347 fprintf(fp, "# contains samples with branch stack\n"); 1426 fprintf(fp, "# contains samples with branch stack\n");
1348} 1427}
1349 1428
1350static void print_auxtrace(struct perf_header *ph __maybe_unused, 1429static void print_auxtrace(struct feat_fd *ff __maybe_unused, FILE *fp)
1351 int fd __maybe_unused, FILE *fp)
1352{ 1430{
1353 fprintf(fp, "# contains AUX area data (e.g. instruction trace)\n"); 1431 fprintf(fp, "# contains AUX area data (e.g. instruction trace)\n");
1354} 1432}
1355 1433
1356static void print_stat(struct perf_header *ph __maybe_unused, 1434static void print_stat(struct feat_fd *ff __maybe_unused, FILE *fp)
1357 int fd __maybe_unused, FILE *fp)
1358{ 1435{
1359 fprintf(fp, "# contains stat data\n"); 1436 fprintf(fp, "# contains stat data\n");
1360} 1437}
1361 1438
1362static void print_cache(struct perf_header *ph __maybe_unused, 1439static void print_cache(struct feat_fd *ff, FILE *fp __maybe_unused)
1363 int fd __maybe_unused, FILE *fp __maybe_unused)
1364{ 1440{
1365 int i; 1441 int i;
1366 1442
1367 fprintf(fp, "# CPU cache info:\n"); 1443 fprintf(fp, "# CPU cache info:\n");
1368 for (i = 0; i < ph->env.caches_cnt; i++) { 1444 for (i = 0; i < ff->ph->env.caches_cnt; i++) {
1369 fprintf(fp, "# "); 1445 fprintf(fp, "# ");
1370 cpu_cache_level__fprintf(fp, &ph->env.caches[i]); 1446 cpu_cache_level__fprintf(fp, &ff->ph->env.caches[i]);
1371 } 1447 }
1372} 1448}
1373 1449
1374static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused, 1450static void print_pmu_mappings(struct feat_fd *ff, FILE *fp)
1375 FILE *fp)
1376{ 1451{
1377 const char *delimiter = "# pmu mappings: "; 1452 const char *delimiter = "# pmu mappings: ";
1378 char *str, *tmp; 1453 char *str, *tmp;
1379 u32 pmu_num; 1454 u32 pmu_num;
1380 u32 type; 1455 u32 type;
1381 1456
1382 pmu_num = ph->env.nr_pmu_mappings; 1457 pmu_num = ff->ph->env.nr_pmu_mappings;
1383 if (!pmu_num) { 1458 if (!pmu_num) {
1384 fprintf(fp, "# pmu mappings: not available\n"); 1459 fprintf(fp, "# pmu mappings: not available\n");
1385 return; 1460 return;
1386 } 1461 }
1387 1462
1388 str = ph->env.pmu_mappings; 1463 str = ff->ph->env.pmu_mappings;
1389 1464
1390 while (pmu_num) { 1465 while (pmu_num) {
1391 type = strtoul(str, &tmp, 0); 1466 type = strtoul(str, &tmp, 0);
@@ -1408,14 +1483,13 @@ error:
1408 fprintf(fp, "# pmu mappings: unable to read\n"); 1483 fprintf(fp, "# pmu mappings: unable to read\n");
1409} 1484}
1410 1485
1411static void print_group_desc(struct perf_header *ph, int fd __maybe_unused, 1486static void print_group_desc(struct feat_fd *ff, FILE *fp)
1412 FILE *fp)
1413{ 1487{
1414 struct perf_session *session; 1488 struct perf_session *session;
1415 struct perf_evsel *evsel; 1489 struct perf_evsel *evsel;
1416 u32 nr = 0; 1490 u32 nr = 0;
1417 1491
1418 session = container_of(ph, struct perf_session, header); 1492 session = container_of(ff->ph, struct perf_session, header);
1419 1493
1420 evlist__for_each_entry(session->evlist, evsel) { 1494 evlist__for_each_entry(session->evlist, evsel) {
1421 if (perf_evsel__is_group_leader(evsel) && 1495 if (perf_evsel__is_group_leader(evsel) &&
@@ -1588,113 +1662,61 @@ out:
1588 return err; 1662 return err;
1589} 1663}
1590 1664
1591static int process_tracing_data(struct perf_file_section *section __maybe_unused, 1665/* Macro for features that simply need to read and store a string. */
1592 struct perf_header *ph __maybe_unused, 1666#define FEAT_PROCESS_STR_FUN(__feat, __feat_env) \
1593 int fd, void *data) 1667static int process_##__feat(struct feat_fd *ff, void *data __maybe_unused) \
1594{ 1668{\
1595 ssize_t ret = trace_report(fd, data, false); 1669 ff->ph->env.__feat_env = do_read_string(ff); \
1596 return ret < 0 ? -1 : 0; 1670 return ff->ph->env.__feat_env ? 0 : -ENOMEM; \
1597}
1598
1599static int process_build_id(struct perf_file_section *section,
1600 struct perf_header *ph, int fd,
1601 void *data __maybe_unused)
1602{
1603 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1604 pr_debug("Failed to read buildids, continuing...\n");
1605 return 0;
1606} 1671}
1607 1672
1608static int process_hostname(struct perf_file_section *section __maybe_unused, 1673FEAT_PROCESS_STR_FUN(hostname, hostname);
1609 struct perf_header *ph, int fd, 1674FEAT_PROCESS_STR_FUN(osrelease, os_release);
1610 void *data __maybe_unused) 1675FEAT_PROCESS_STR_FUN(version, version);
1611{ 1676FEAT_PROCESS_STR_FUN(arch, arch);
1612 ph->env.hostname = do_read_string(fd, ph); 1677FEAT_PROCESS_STR_FUN(cpudesc, cpu_desc);
1613 return ph->env.hostname ? 0 : -ENOMEM; 1678FEAT_PROCESS_STR_FUN(cpuid, cpuid);
1614}
1615 1679
1616static int process_osrelease(struct perf_file_section *section __maybe_unused, 1680static int process_tracing_data(struct feat_fd *ff, void *data)
1617 struct perf_header *ph, int fd,
1618 void *data __maybe_unused)
1619{ 1681{
1620 ph->env.os_release = do_read_string(fd, ph); 1682 ssize_t ret = trace_report(ff->fd, data, false);
1621 return ph->env.os_release ? 0 : -ENOMEM;
1622}
1623 1683
1624static int process_version(struct perf_file_section *section __maybe_unused, 1684 return ret < 0 ? -1 : 0;
1625 struct perf_header *ph, int fd,
1626 void *data __maybe_unused)
1627{
1628 ph->env.version = do_read_string(fd, ph);
1629 return ph->env.version ? 0 : -ENOMEM;
1630} 1685}
1631 1686
1632static int process_arch(struct perf_file_section *section __maybe_unused, 1687static int process_build_id(struct feat_fd *ff, void *data __maybe_unused)
1633 struct perf_header *ph, int fd,
1634 void *data __maybe_unused)
1635{ 1688{
1636 ph->env.arch = do_read_string(fd, ph); 1689 if (perf_header__read_build_ids(ff->ph, ff->fd, ff->offset, ff->size))
1637 return ph->env.arch ? 0 : -ENOMEM; 1690 pr_debug("Failed to read buildids, continuing...\n");
1691 return 0;
1638} 1692}
1639 1693
1640static int process_nrcpus(struct perf_file_section *section __maybe_unused, 1694static int process_nrcpus(struct feat_fd *ff, void *data __maybe_unused)
1641 struct perf_header *ph, int fd,
1642 void *data __maybe_unused)
1643{ 1695{
1644 ssize_t ret; 1696 int ret;
1645 u32 nr; 1697 u32 nr_cpus_avail, nr_cpus_online;
1646
1647 ret = readn(fd, &nr, sizeof(nr));
1648 if (ret != sizeof(nr))
1649 return -1;
1650
1651 if (ph->needs_swap)
1652 nr = bswap_32(nr);
1653
1654 ph->env.nr_cpus_avail = nr;
1655
1656 ret = readn(fd, &nr, sizeof(nr));
1657 if (ret != sizeof(nr))
1658 return -1;
1659 1698
1660 if (ph->needs_swap) 1699 ret = do_read_u32(ff, &nr_cpus_avail);
1661 nr = bswap_32(nr); 1700 if (ret)
1701 return ret;
1662 1702
1663 ph->env.nr_cpus_online = nr; 1703 ret = do_read_u32(ff, &nr_cpus_online);
1704 if (ret)
1705 return ret;
1706 ff->ph->env.nr_cpus_avail = (int)nr_cpus_avail;
1707 ff->ph->env.nr_cpus_online = (int)nr_cpus_online;
1664 return 0; 1708 return 0;
1665} 1709}
1666 1710
1667static int process_cpudesc(struct perf_file_section *section __maybe_unused, 1711static int process_total_mem(struct feat_fd *ff, void *data __maybe_unused)
1668 struct perf_header *ph, int fd,
1669 void *data __maybe_unused)
1670{
1671 ph->env.cpu_desc = do_read_string(fd, ph);
1672 return ph->env.cpu_desc ? 0 : -ENOMEM;
1673}
1674
1675static int process_cpuid(struct perf_file_section *section __maybe_unused,
1676 struct perf_header *ph, int fd,
1677 void *data __maybe_unused)
1678{
1679 ph->env.cpuid = do_read_string(fd, ph);
1680 return ph->env.cpuid ? 0 : -ENOMEM;
1681}
1682
1683static int process_total_mem(struct perf_file_section *section __maybe_unused,
1684 struct perf_header *ph, int fd,
1685 void *data __maybe_unused)
1686{ 1712{
1687 uint64_t mem; 1713 u64 total_mem;
1688 ssize_t ret; 1714 int ret;
1689 1715
1690 ret = readn(fd, &mem, sizeof(mem)); 1716 ret = do_read_u64(ff, &total_mem);
1691 if (ret != sizeof(mem)) 1717 if (ret)
1692 return -1; 1718 return -1;
1693 1719 ff->ph->env.total_mem = (unsigned long long)total_mem;
1694 if (ph->needs_swap)
1695 mem = bswap_64(mem);
1696
1697 ph->env.total_mem = mem;
1698 return 0; 1720 return 0;
1699} 1721}
1700 1722
@@ -1731,43 +1753,42 @@ perf_evlist__set_event_name(struct perf_evlist *evlist,
1731} 1753}
1732 1754
1733static int 1755static int
1734process_event_desc(struct perf_file_section *section __maybe_unused, 1756process_event_desc(struct feat_fd *ff, void *data __maybe_unused)
1735 struct perf_header *header, int fd,
1736 void *data __maybe_unused)
1737{ 1757{
1738 struct perf_session *session; 1758 struct perf_session *session;
1739 struct perf_evsel *evsel, *events = read_event_desc(header, fd); 1759 struct perf_evsel *evsel, *events = read_event_desc(ff);
1740 1760
1741 if (!events) 1761 if (!events)
1742 return 0; 1762 return 0;
1743 1763
1744 session = container_of(header, struct perf_session, header); 1764 session = container_of(ff->ph, struct perf_session, header);
1765
1766 if (session->data->is_pipe) {
1767 /* Save events for reading later by print_event_desc,
1768 * since they can't be read again in pipe mode. */
1769 ff->events = events;
1770 }
1771
1745 for (evsel = events; evsel->attr.size; evsel++) 1772 for (evsel = events; evsel->attr.size; evsel++)
1746 perf_evlist__set_event_name(session->evlist, evsel); 1773 perf_evlist__set_event_name(session->evlist, evsel);
1747 1774
1748 free_event_desc(events); 1775 if (!session->data->is_pipe)
1776 free_event_desc(events);
1749 1777
1750 return 0; 1778 return 0;
1751} 1779}
1752 1780
1753static int process_cmdline(struct perf_file_section *section, 1781static int process_cmdline(struct feat_fd *ff, void *data __maybe_unused)
1754 struct perf_header *ph, int fd,
1755 void *data __maybe_unused)
1756{ 1782{
1757 ssize_t ret;
1758 char *str, *cmdline = NULL, **argv = NULL; 1783 char *str, *cmdline = NULL, **argv = NULL;
1759 u32 nr, i, len = 0; 1784 u32 nr, i, len = 0;
1760 1785
1761 ret = readn(fd, &nr, sizeof(nr)); 1786 if (do_read_u32(ff, &nr))
1762 if (ret != sizeof(nr))
1763 return -1; 1787 return -1;
1764 1788
1765 if (ph->needs_swap) 1789 ff->ph->env.nr_cmdline = nr;
1766 nr = bswap_32(nr);
1767
1768 ph->env.nr_cmdline = nr;
1769 1790
1770 cmdline = zalloc(section->size + nr + 1); 1791 cmdline = zalloc(ff->size + nr + 1);
1771 if (!cmdline) 1792 if (!cmdline)
1772 return -1; 1793 return -1;
1773 1794
@@ -1776,7 +1797,7 @@ static int process_cmdline(struct perf_file_section *section,
1776 goto error; 1797 goto error;
1777 1798
1778 for (i = 0; i < nr; i++) { 1799 for (i = 0; i < nr; i++) {
1779 str = do_read_string(fd, ph); 1800 str = do_read_string(ff);
1780 if (!str) 1801 if (!str)
1781 goto error; 1802 goto error;
1782 1803
@@ -1785,8 +1806,8 @@ static int process_cmdline(struct perf_file_section *section,
1785 len += strlen(str) + 1; 1806 len += strlen(str) + 1;
1786 free(str); 1807 free(str);
1787 } 1808 }
1788 ph->env.cmdline = cmdline; 1809 ff->ph->env.cmdline = cmdline;
1789 ph->env.cmdline_argv = (const char **) argv; 1810 ff->ph->env.cmdline_argv = (const char **) argv;
1790 return 0; 1811 return 0;
1791 1812
1792error: 1813error:
@@ -1795,35 +1816,29 @@ error:
1795 return -1; 1816 return -1;
1796} 1817}
1797 1818
1798static int process_cpu_topology(struct perf_file_section *section, 1819static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
1799 struct perf_header *ph, int fd,
1800 void *data __maybe_unused)
1801{ 1820{
1802 ssize_t ret;
1803 u32 nr, i; 1821 u32 nr, i;
1804 char *str; 1822 char *str;
1805 struct strbuf sb; 1823 struct strbuf sb;
1806 int cpu_nr = ph->env.nr_cpus_avail; 1824 int cpu_nr = ff->ph->env.nr_cpus_avail;
1807 u64 size = 0; 1825 u64 size = 0;
1826 struct perf_header *ph = ff->ph;
1808 1827
1809 ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu)); 1828 ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu));
1810 if (!ph->env.cpu) 1829 if (!ph->env.cpu)
1811 return -1; 1830 return -1;
1812 1831
1813 ret = readn(fd, &nr, sizeof(nr)); 1832 if (do_read_u32(ff, &nr))
1814 if (ret != sizeof(nr))
1815 goto free_cpu; 1833 goto free_cpu;
1816 1834
1817 if (ph->needs_swap)
1818 nr = bswap_32(nr);
1819
1820 ph->env.nr_sibling_cores = nr; 1835 ph->env.nr_sibling_cores = nr;
1821 size += sizeof(u32); 1836 size += sizeof(u32);
1822 if (strbuf_init(&sb, 128) < 0) 1837 if (strbuf_init(&sb, 128) < 0)
1823 goto free_cpu; 1838 goto free_cpu;
1824 1839
1825 for (i = 0; i < nr; i++) { 1840 for (i = 0; i < nr; i++) {
1826 str = do_read_string(fd, ph); 1841 str = do_read_string(ff);
1827 if (!str) 1842 if (!str)
1828 goto error; 1843 goto error;
1829 1844
@@ -1835,18 +1850,14 @@ static int process_cpu_topology(struct perf_file_section *section,
1835 } 1850 }
1836 ph->env.sibling_cores = strbuf_detach(&sb, NULL); 1851 ph->env.sibling_cores = strbuf_detach(&sb, NULL);
1837 1852
1838 ret = readn(fd, &nr, sizeof(nr)); 1853 if (do_read_u32(ff, &nr))
1839 if (ret != sizeof(nr))
1840 return -1; 1854 return -1;
1841 1855
1842 if (ph->needs_swap)
1843 nr = bswap_32(nr);
1844
1845 ph->env.nr_sibling_threads = nr; 1856 ph->env.nr_sibling_threads = nr;
1846 size += sizeof(u32); 1857 size += sizeof(u32);
1847 1858
1848 for (i = 0; i < nr; i++) { 1859 for (i = 0; i < nr; i++) {
1849 str = do_read_string(fd, ph); 1860 str = do_read_string(ff);
1850 if (!str) 1861 if (!str)
1851 goto error; 1862 goto error;
1852 1863
@@ -1862,28 +1873,20 @@ static int process_cpu_topology(struct perf_file_section *section,
1862 * The header may be from old perf, 1873 * The header may be from old perf,
1863 * which doesn't include core id and socket id information. 1874 * which doesn't include core id and socket id information.
1864 */ 1875 */
1865 if (section->size <= size) { 1876 if (ff->size <= size) {
1866 zfree(&ph->env.cpu); 1877 zfree(&ph->env.cpu);
1867 return 0; 1878 return 0;
1868 } 1879 }
1869 1880
1870 for (i = 0; i < (u32)cpu_nr; i++) { 1881 for (i = 0; i < (u32)cpu_nr; i++) {
1871 ret = readn(fd, &nr, sizeof(nr)); 1882 if (do_read_u32(ff, &nr))
1872 if (ret != sizeof(nr))
1873 goto free_cpu; 1883 goto free_cpu;
1874 1884
1875 if (ph->needs_swap)
1876 nr = bswap_32(nr);
1877
1878 ph->env.cpu[i].core_id = nr; 1885 ph->env.cpu[i].core_id = nr;
1879 1886
1880 ret = readn(fd, &nr, sizeof(nr)); 1887 if (do_read_u32(ff, &nr))
1881 if (ret != sizeof(nr))
1882 goto free_cpu; 1888 goto free_cpu;
1883 1889
1884 if (ph->needs_swap)
1885 nr = bswap_32(nr);
1886
1887 if (nr != (u32)-1 && nr > (u32)cpu_nr) { 1890 if (nr != (u32)-1 && nr > (u32)cpu_nr) {
1888 pr_debug("socket_id number is too big." 1891 pr_debug("socket_id number is too big."
1889 "You may need to upgrade the perf tool.\n"); 1892 "You may need to upgrade the perf tool.\n");
@@ -1902,23 +1905,16 @@ free_cpu:
1902 return -1; 1905 return -1;
1903} 1906}
1904 1907
1905static int process_numa_topology(struct perf_file_section *section __maybe_unused, 1908static int process_numa_topology(struct feat_fd *ff, void *data __maybe_unused)
1906 struct perf_header *ph, int fd,
1907 void *data __maybe_unused)
1908{ 1909{
1909 struct numa_node *nodes, *n; 1910 struct numa_node *nodes, *n;
1910 ssize_t ret;
1911 u32 nr, i; 1911 u32 nr, i;
1912 char *str; 1912 char *str;
1913 1913
1914 /* nr nodes */ 1914 /* nr nodes */
1915 ret = readn(fd, &nr, sizeof(nr)); 1915 if (do_read_u32(ff, &nr))
1916 if (ret != sizeof(nr))
1917 return -1; 1916 return -1;
1918 1917
1919 if (ph->needs_swap)
1920 nr = bswap_32(nr);
1921
1922 nodes = zalloc(sizeof(*nodes) * nr); 1918 nodes = zalloc(sizeof(*nodes) * nr);
1923 if (!nodes) 1919 if (!nodes)
1924 return -ENOMEM; 1920 return -ENOMEM;
@@ -1927,25 +1923,16 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
1927 n = &nodes[i]; 1923 n = &nodes[i];
1928 1924
1929 /* node number */ 1925 /* node number */
1930 ret = readn(fd, &n->node, sizeof(u32)); 1926 if (do_read_u32(ff, &n->node))
1931 if (ret != sizeof(n->node))
1932 goto error; 1927 goto error;
1933 1928
1934 ret = readn(fd, &n->mem_total, sizeof(u64)); 1929 if (do_read_u64(ff, &n->mem_total))
1935 if (ret != sizeof(u64))
1936 goto error; 1930 goto error;
1937 1931
1938 ret = readn(fd, &n->mem_free, sizeof(u64)); 1932 if (do_read_u64(ff, &n->mem_free))
1939 if (ret != sizeof(u64))
1940 goto error; 1933 goto error;
1941 1934
1942 if (ph->needs_swap) { 1935 str = do_read_string(ff);
1943 n->node = bswap_32(n->node);
1944 n->mem_total = bswap_64(n->mem_total);
1945 n->mem_free = bswap_64(n->mem_free);
1946 }
1947
1948 str = do_read_string(fd, ph);
1949 if (!str) 1936 if (!str)
1950 goto error; 1937 goto error;
1951 1938
@@ -1955,8 +1942,8 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
1955 1942
1956 free(str); 1943 free(str);
1957 } 1944 }
1958 ph->env.nr_numa_nodes = nr; 1945 ff->ph->env.nr_numa_nodes = nr;
1959 ph->env.numa_nodes = nodes; 1946 ff->ph->env.numa_nodes = nodes;
1960 return 0; 1947 return 0;
1961 1948
1962error: 1949error:
@@ -1964,39 +1951,30 @@ error:
1964 return -1; 1951 return -1;
1965} 1952}
1966 1953
1967static int process_pmu_mappings(struct perf_file_section *section __maybe_unused, 1954static int process_pmu_mappings(struct feat_fd *ff, void *data __maybe_unused)
1968 struct perf_header *ph, int fd,
1969 void *data __maybe_unused)
1970{ 1955{
1971 ssize_t ret;
1972 char *name; 1956 char *name;
1973 u32 pmu_num; 1957 u32 pmu_num;
1974 u32 type; 1958 u32 type;
1975 struct strbuf sb; 1959 struct strbuf sb;
1976 1960
1977 ret = readn(fd, &pmu_num, sizeof(pmu_num)); 1961 if (do_read_u32(ff, &pmu_num))
1978 if (ret != sizeof(pmu_num))
1979 return -1; 1962 return -1;
1980 1963
1981 if (ph->needs_swap)
1982 pmu_num = bswap_32(pmu_num);
1983
1984 if (!pmu_num) { 1964 if (!pmu_num) {
1985 pr_debug("pmu mappings not available\n"); 1965 pr_debug("pmu mappings not available\n");
1986 return 0; 1966 return 0;
1987 } 1967 }
1988 1968
1989 ph->env.nr_pmu_mappings = pmu_num; 1969 ff->ph->env.nr_pmu_mappings = pmu_num;
1990 if (strbuf_init(&sb, 128) < 0) 1970 if (strbuf_init(&sb, 128) < 0)
1991 return -1; 1971 return -1;
1992 1972
1993 while (pmu_num) { 1973 while (pmu_num) {
1994 if (readn(fd, &type, sizeof(type)) != sizeof(type)) 1974 if (do_read_u32(ff, &type))
1995 goto error; 1975 goto error;
1996 if (ph->needs_swap)
1997 type = bswap_32(type);
1998 1976
1999 name = do_read_string(fd, ph); 1977 name = do_read_string(ff);
2000 if (!name) 1978 if (!name)
2001 goto error; 1979 goto error;
2002 1980
@@ -2007,12 +1985,12 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
2007 goto error; 1985 goto error;
2008 1986
2009 if (!strcmp(name, "msr")) 1987 if (!strcmp(name, "msr"))
2010 ph->env.msr_pmu_type = type; 1988 ff->ph->env.msr_pmu_type = type;
2011 1989
2012 free(name); 1990 free(name);
2013 pmu_num--; 1991 pmu_num--;
2014 } 1992 }
2015 ph->env.pmu_mappings = strbuf_detach(&sb, NULL); 1993 ff->ph->env.pmu_mappings = strbuf_detach(&sb, NULL);
2016 return 0; 1994 return 0;
2017 1995
2018error: 1996error:
@@ -2020,9 +1998,7 @@ error:
2020 return -1; 1998 return -1;
2021} 1999}
2022 2000
2023static int process_group_desc(struct perf_file_section *section __maybe_unused, 2001static int process_group_desc(struct feat_fd *ff, void *data __maybe_unused)
2024 struct perf_header *ph, int fd,
2025 void *data __maybe_unused)
2026{ 2002{
2027 size_t ret = -1; 2003 size_t ret = -1;
2028 u32 i, nr, nr_groups; 2004 u32 i, nr, nr_groups;
@@ -2034,13 +2010,10 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
2034 u32 nr_members; 2010 u32 nr_members;
2035 } *desc; 2011 } *desc;
2036 2012
2037 if (readn(fd, &nr_groups, sizeof(nr_groups)) != sizeof(nr_groups)) 2013 if (do_read_u32(ff, &nr_groups))
2038 return -1; 2014 return -1;
2039 2015
2040 if (ph->needs_swap) 2016 ff->ph->env.nr_groups = nr_groups;
2041 nr_groups = bswap_32(nr_groups);
2042
2043 ph->env.nr_groups = nr_groups;
2044 if (!nr_groups) { 2017 if (!nr_groups) {
2045 pr_debug("group desc not available\n"); 2018 pr_debug("group desc not available\n");
2046 return 0; 2019 return 0;
@@ -2051,26 +2024,21 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
2051 return -1; 2024 return -1;
2052 2025
2053 for (i = 0; i < nr_groups; i++) { 2026 for (i = 0; i < nr_groups; i++) {
2054 desc[i].name = do_read_string(fd, ph); 2027 desc[i].name = do_read_string(ff);
2055 if (!desc[i].name) 2028 if (!desc[i].name)
2056 goto out_free; 2029 goto out_free;
2057 2030
2058 if (readn(fd, &desc[i].leader_idx, sizeof(u32)) != sizeof(u32)) 2031 if (do_read_u32(ff, &desc[i].leader_idx))
2059 goto out_free; 2032 goto out_free;
2060 2033
2061 if (readn(fd, &desc[i].nr_members, sizeof(u32)) != sizeof(u32)) 2034 if (do_read_u32(ff, &desc[i].nr_members))
2062 goto out_free; 2035 goto out_free;
2063
2064 if (ph->needs_swap) {
2065 desc[i].leader_idx = bswap_32(desc[i].leader_idx);
2066 desc[i].nr_members = bswap_32(desc[i].nr_members);
2067 }
2068 } 2036 }
2069 2037
2070 /* 2038 /*
2071 * Rebuild group relationship based on the group_desc 2039 * Rebuild group relationship based on the group_desc
2072 */ 2040 */
2073 session = container_of(ph, struct perf_session, header); 2041 session = container_of(ff->ph, struct perf_session, header);
2074 session->evlist->nr_groups = nr_groups; 2042 session->evlist->nr_groups = nr_groups;
2075 2043
2076 i = nr = 0; 2044 i = nr = 0;
@@ -2114,44 +2082,34 @@ out_free:
2114 return ret; 2082 return ret;
2115} 2083}
2116 2084
2117static int process_auxtrace(struct perf_file_section *section, 2085static int process_auxtrace(struct feat_fd *ff, void *data __maybe_unused)
2118 struct perf_header *ph, int fd,
2119 void *data __maybe_unused)
2120{ 2086{
2121 struct perf_session *session; 2087 struct perf_session *session;
2122 int err; 2088 int err;
2123 2089
2124 session = container_of(ph, struct perf_session, header); 2090 session = container_of(ff->ph, struct perf_session, header);
2125 2091
2126 err = auxtrace_index__process(fd, section->size, session, 2092 err = auxtrace_index__process(ff->fd, ff->size, session,
2127 ph->needs_swap); 2093 ff->ph->needs_swap);
2128 if (err < 0) 2094 if (err < 0)
2129 pr_err("Failed to process auxtrace index\n"); 2095 pr_err("Failed to process auxtrace index\n");
2130 return err; 2096 return err;
2131} 2097}
2132 2098
2133static int process_cache(struct perf_file_section *section __maybe_unused, 2099static int process_cache(struct feat_fd *ff, void *data __maybe_unused)
2134 struct perf_header *ph __maybe_unused, int fd __maybe_unused,
2135 void *data __maybe_unused)
2136{ 2100{
2137 struct cpu_cache_level *caches; 2101 struct cpu_cache_level *caches;
2138 u32 cnt, i, version; 2102 u32 cnt, i, version;
2139 2103
2140 if (readn(fd, &version, sizeof(version)) != sizeof(version)) 2104 if (do_read_u32(ff, &version))
2141 return -1; 2105 return -1;
2142 2106
2143 if (ph->needs_swap)
2144 version = bswap_32(version);
2145
2146 if (version != 1) 2107 if (version != 1)
2147 return -1; 2108 return -1;
2148 2109
2149 if (readn(fd, &cnt, sizeof(cnt)) != sizeof(cnt)) 2110 if (do_read_u32(ff, &cnt))
2150 return -1; 2111 return -1;
2151 2112
2152 if (ph->needs_swap)
2153 cnt = bswap_32(cnt);
2154
2155 caches = zalloc(sizeof(*caches) * cnt); 2113 caches = zalloc(sizeof(*caches) * cnt);
2156 if (!caches) 2114 if (!caches)
2157 return -1; 2115 return -1;
@@ -2160,10 +2118,8 @@ static int process_cache(struct perf_file_section *section __maybe_unused,
2160 struct cpu_cache_level c; 2118 struct cpu_cache_level c;
2161 2119
2162 #define _R(v) \ 2120 #define _R(v) \
2163 if (readn(fd, &c.v, sizeof(u32)) != sizeof(u32))\ 2121 if (do_read_u32(ff, &c.v))\
2164 goto out_free_caches; \ 2122 goto out_free_caches; \
2165 if (ph->needs_swap) \
2166 c.v = bswap_32(c.v); \
2167 2123
2168 _R(level) 2124 _R(level)
2169 _R(line_size) 2125 _R(line_size)
@@ -2171,9 +2127,9 @@ static int process_cache(struct perf_file_section *section __maybe_unused,
2171 _R(ways) 2127 _R(ways)
2172 #undef _R 2128 #undef _R
2173 2129
2174 #define _R(v) \ 2130 #define _R(v) \
2175 c.v = do_read_string(fd, ph); \ 2131 c.v = do_read_string(ff); \
2176 if (!c.v) \ 2132 if (!c.v) \
2177 goto out_free_caches; 2133 goto out_free_caches;
2178 2134
2179 _R(type) 2135 _R(type)
@@ -2184,8 +2140,8 @@ static int process_cache(struct perf_file_section *section __maybe_unused,
2184 caches[i] = c; 2140 caches[i] = c;
2185 } 2141 }
2186 2142
2187 ph->env.caches = caches; 2143 ff->ph->env.caches = caches;
2188 ph->env.caches_cnt = cnt; 2144 ff->ph->env.caches_cnt = cnt;
2189 return 0; 2145 return 0;
2190out_free_caches: 2146out_free_caches:
2191 free(caches); 2147 free(caches);
@@ -2193,48 +2149,62 @@ out_free_caches:
2193} 2149}
2194 2150
2195struct feature_ops { 2151struct feature_ops {
2196 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); 2152 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
2197 void (*print)(struct perf_header *h, int fd, FILE *fp); 2153 void (*print)(struct feat_fd *ff, FILE *fp);
2198 int (*process)(struct perf_file_section *section, 2154 int (*process)(struct feat_fd *ff, void *data);
2199 struct perf_header *h, int fd, void *data);
2200 const char *name; 2155 const char *name;
2201 bool full_only; 2156 bool full_only;
2157 bool synthesize;
2202}; 2158};
2203 2159
2204#define FEAT_OPA(n, func) \ 2160#define FEAT_OPR(n, func, __full_only) \
2205 [n] = { .name = #n, .write = write_##func, .print = print_##func } 2161 [HEADER_##n] = { \
2206#define FEAT_OPP(n, func) \ 2162 .name = __stringify(n), \
2207 [n] = { .name = #n, .write = write_##func, .print = print_##func, \ 2163 .write = write_##func, \
2208 .process = process_##func } 2164 .print = print_##func, \
2209#define FEAT_OPF(n, func) \ 2165 .full_only = __full_only, \
2210 [n] = { .name = #n, .write = write_##func, .print = print_##func, \ 2166 .process = process_##func, \
2211 .process = process_##func, .full_only = true } 2167 .synthesize = true \
2168 }
2169
2170#define FEAT_OPN(n, func, __full_only) \
2171 [HEADER_##n] = { \
2172 .name = __stringify(n), \
2173 .write = write_##func, \
2174 .print = print_##func, \
2175 .full_only = __full_only, \
2176 .process = process_##func \
2177 }
2212 2178
2213/* feature_ops not implemented: */ 2179/* feature_ops not implemented: */
2214#define print_tracing_data NULL 2180#define print_tracing_data NULL
2215#define print_build_id NULL 2181#define print_build_id NULL
2216 2182
2183#define process_branch_stack NULL
2184#define process_stat NULL
2185
2186
2217static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { 2187static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
2218 FEAT_OPP(HEADER_TRACING_DATA, tracing_data), 2188 FEAT_OPN(TRACING_DATA, tracing_data, false),
2219 FEAT_OPP(HEADER_BUILD_ID, build_id), 2189 FEAT_OPN(BUILD_ID, build_id, false),
2220 FEAT_OPP(HEADER_HOSTNAME, hostname), 2190 FEAT_OPR(HOSTNAME, hostname, false),
2221 FEAT_OPP(HEADER_OSRELEASE, osrelease), 2191 FEAT_OPR(OSRELEASE, osrelease, false),
2222 FEAT_OPP(HEADER_VERSION, version), 2192 FEAT_OPR(VERSION, version, false),
2223 FEAT_OPP(HEADER_ARCH, arch), 2193 FEAT_OPR(ARCH, arch, false),
2224 FEAT_OPP(HEADER_NRCPUS, nrcpus), 2194 FEAT_OPR(NRCPUS, nrcpus, false),
2225 FEAT_OPP(HEADER_CPUDESC, cpudesc), 2195 FEAT_OPR(CPUDESC, cpudesc, false),
2226 FEAT_OPP(HEADER_CPUID, cpuid), 2196 FEAT_OPR(CPUID, cpuid, false),
2227 FEAT_OPP(HEADER_TOTAL_MEM, total_mem), 2197 FEAT_OPR(TOTAL_MEM, total_mem, false),
2228 FEAT_OPP(HEADER_EVENT_DESC, event_desc), 2198 FEAT_OPR(EVENT_DESC, event_desc, false),
2229 FEAT_OPP(HEADER_CMDLINE, cmdline), 2199 FEAT_OPR(CMDLINE, cmdline, false),
2230 FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology), 2200 FEAT_OPR(CPU_TOPOLOGY, cpu_topology, true),
2231 FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology), 2201 FEAT_OPR(NUMA_TOPOLOGY, numa_topology, true),
2232 FEAT_OPA(HEADER_BRANCH_STACK, branch_stack), 2202 FEAT_OPN(BRANCH_STACK, branch_stack, false),
2233 FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings), 2203 FEAT_OPR(PMU_MAPPINGS, pmu_mappings, false),
2234 FEAT_OPP(HEADER_GROUP_DESC, group_desc), 2204 FEAT_OPN(GROUP_DESC, group_desc, false),
2235 FEAT_OPP(HEADER_AUXTRACE, auxtrace), 2205 FEAT_OPN(AUXTRACE, auxtrace, false),
2236 FEAT_OPA(HEADER_STAT, stat), 2206 FEAT_OPN(STAT, stat, false),
2237 FEAT_OPF(HEADER_CACHE, cache), 2207 FEAT_OPN(CACHE, cache, true),
2238}; 2208};
2239 2209
2240struct header_print_data { 2210struct header_print_data {
@@ -2247,6 +2217,7 @@ static int perf_file_section__fprintf_info(struct perf_file_section *section,
2247 int feat, int fd, void *data) 2217 int feat, int fd, void *data)
2248{ 2218{
2249 struct header_print_data *hd = data; 2219 struct header_print_data *hd = data;
2220 struct feat_fd ff;
2250 2221
2251 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) { 2222 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
2252 pr_debug("Failed to lseek to %" PRIu64 " offset for feature " 2223 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
@@ -2260,8 +2231,13 @@ static int perf_file_section__fprintf_info(struct perf_file_section *section,
2260 if (!feat_ops[feat].print) 2231 if (!feat_ops[feat].print)
2261 return 0; 2232 return 0;
2262 2233
2234 ff = (struct feat_fd) {
2235 .fd = fd,
2236 .ph = ph,
2237 };
2238
2263 if (!feat_ops[feat].full_only || hd->full) 2239 if (!feat_ops[feat].full_only || hd->full)
2264 feat_ops[feat].print(ph, fd, hd->fp); 2240 feat_ops[feat].print(&ff, hd->fp);
2265 else 2241 else
2266 fprintf(hd->fp, "# %s info available, use -I to display\n", 2242 fprintf(hd->fp, "# %s info available, use -I to display\n",
2267 feat_ops[feat].name); 2243 feat_ops[feat].name);
@@ -2273,7 +2249,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2273{ 2249{
2274 struct header_print_data hd; 2250 struct header_print_data hd;
2275 struct perf_header *header = &session->header; 2251 struct perf_header *header = &session->header;
2276 int fd = perf_data_file__fd(session->file); 2252 int fd = perf_data__fd(session->data);
2277 struct stat st; 2253 struct stat st;
2278 int ret, bit; 2254 int ret, bit;
2279 2255
@@ -2289,7 +2265,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2289 perf_header__process_sections(header, fd, &hd, 2265 perf_header__process_sections(header, fd, &hd,
2290 perf_file_section__fprintf_info); 2266 perf_file_section__fprintf_info);
2291 2267
2292 if (session->file->is_pipe) 2268 if (session->data->is_pipe)
2293 return 0; 2269 return 0;
2294 2270
2295 fprintf(fp, "# missing features: "); 2271 fprintf(fp, "# missing features: ");
@@ -2302,29 +2278,32 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2302 return 0; 2278 return 0;
2303} 2279}
2304 2280
2305static int do_write_feat(int fd, struct perf_header *h, int type, 2281static int do_write_feat(struct feat_fd *ff, int type,
2306 struct perf_file_section **p, 2282 struct perf_file_section **p,
2307 struct perf_evlist *evlist) 2283 struct perf_evlist *evlist)
2308{ 2284{
2309 int err; 2285 int err;
2310 int ret = 0; 2286 int ret = 0;
2311 2287
2312 if (perf_header__has_feat(h, type)) { 2288 if (perf_header__has_feat(ff->ph, type)) {
2313 if (!feat_ops[type].write) 2289 if (!feat_ops[type].write)
2314 return -1; 2290 return -1;
2315 2291
2316 (*p)->offset = lseek(fd, 0, SEEK_CUR); 2292 if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
2293 return -1;
2317 2294
2318 err = feat_ops[type].write(fd, h, evlist); 2295 (*p)->offset = lseek(ff->fd, 0, SEEK_CUR);
2296
2297 err = feat_ops[type].write(ff, evlist);
2319 if (err < 0) { 2298 if (err < 0) {
2320 pr_debug("failed to write feature %s\n", feat_ops[type].name); 2299 pr_debug("failed to write feature %s\n", feat_ops[type].name);
2321 2300
2322 /* undo anything written */ 2301 /* undo anything written */
2323 lseek(fd, (*p)->offset, SEEK_SET); 2302 lseek(ff->fd, (*p)->offset, SEEK_SET);
2324 2303
2325 return -1; 2304 return -1;
2326 } 2305 }
2327 (*p)->size = lseek(fd, 0, SEEK_CUR) - (*p)->offset; 2306 (*p)->size = lseek(ff->fd, 0, SEEK_CUR) - (*p)->offset;
2328 (*p)++; 2307 (*p)++;
2329 } 2308 }
2330 return ret; 2309 return ret;
@@ -2334,12 +2313,18 @@ static int perf_header__adds_write(struct perf_header *header,
2334 struct perf_evlist *evlist, int fd) 2313 struct perf_evlist *evlist, int fd)
2335{ 2314{
2336 int nr_sections; 2315 int nr_sections;
2316 struct feat_fd ff;
2337 struct perf_file_section *feat_sec, *p; 2317 struct perf_file_section *feat_sec, *p;
2338 int sec_size; 2318 int sec_size;
2339 u64 sec_start; 2319 u64 sec_start;
2340 int feat; 2320 int feat;
2341 int err; 2321 int err;
2342 2322
2323 ff = (struct feat_fd){
2324 .fd = fd,
2325 .ph = header,
2326 };
2327
2343 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); 2328 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
2344 if (!nr_sections) 2329 if (!nr_sections)
2345 return 0; 2330 return 0;
@@ -2354,7 +2339,7 @@ static int perf_header__adds_write(struct perf_header *header,
2354 lseek(fd, sec_start + sec_size, SEEK_SET); 2339 lseek(fd, sec_start + sec_size, SEEK_SET);
2355 2340
2356 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) { 2341 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
2357 if (do_write_feat(fd, header, feat, &p, evlist)) 2342 if (do_write_feat(&ff, feat, &p, evlist))
2358 perf_header__clear_feat(header, feat); 2343 perf_header__clear_feat(header, feat);
2359 } 2344 }
2360 2345
@@ -2363,7 +2348,7 @@ static int perf_header__adds_write(struct perf_header *header,
2363 * may write more than needed due to dropped feature, but 2348 * may write more than needed due to dropped feature, but
2364 * this is okay, reader will skip the mising entries 2349 * this is okay, reader will skip the mising entries
2365 */ 2350 */
2366 err = do_write(fd, feat_sec, sec_size); 2351 err = do_write(&ff, feat_sec, sec_size);
2367 if (err < 0) 2352 if (err < 0)
2368 pr_debug("failed to write feature section\n"); 2353 pr_debug("failed to write feature section\n");
2369 free(feat_sec); 2354 free(feat_sec);
@@ -2373,14 +2358,17 @@ static int perf_header__adds_write(struct perf_header *header,
2373int perf_header__write_pipe(int fd) 2358int perf_header__write_pipe(int fd)
2374{ 2359{
2375 struct perf_pipe_file_header f_header; 2360 struct perf_pipe_file_header f_header;
2361 struct feat_fd ff;
2376 int err; 2362 int err;
2377 2363
2364 ff = (struct feat_fd){ .fd = fd };
2365
2378 f_header = (struct perf_pipe_file_header){ 2366 f_header = (struct perf_pipe_file_header){
2379 .magic = PERF_MAGIC, 2367 .magic = PERF_MAGIC,
2380 .size = sizeof(f_header), 2368 .size = sizeof(f_header),
2381 }; 2369 };
2382 2370
2383 err = do_write(fd, &f_header, sizeof(f_header)); 2371 err = do_write(&ff, &f_header, sizeof(f_header));
2384 if (err < 0) { 2372 if (err < 0) {
2385 pr_debug("failed to write perf pipe header\n"); 2373 pr_debug("failed to write perf pipe header\n");
2386 return err; 2374 return err;
@@ -2397,21 +2385,23 @@ int perf_session__write_header(struct perf_session *session,
2397 struct perf_file_attr f_attr; 2385 struct perf_file_attr f_attr;
2398 struct perf_header *header = &session->header; 2386 struct perf_header *header = &session->header;
2399 struct perf_evsel *evsel; 2387 struct perf_evsel *evsel;
2388 struct feat_fd ff;
2400 u64 attr_offset; 2389 u64 attr_offset;
2401 int err; 2390 int err;
2402 2391
2392 ff = (struct feat_fd){ .fd = fd};
2403 lseek(fd, sizeof(f_header), SEEK_SET); 2393 lseek(fd, sizeof(f_header), SEEK_SET);
2404 2394
2405 evlist__for_each_entry(session->evlist, evsel) { 2395 evlist__for_each_entry(session->evlist, evsel) {
2406 evsel->id_offset = lseek(fd, 0, SEEK_CUR); 2396 evsel->id_offset = lseek(fd, 0, SEEK_CUR);
2407 err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); 2397 err = do_write(&ff, evsel->id, evsel->ids * sizeof(u64));
2408 if (err < 0) { 2398 if (err < 0) {
2409 pr_debug("failed to write perf header\n"); 2399 pr_debug("failed to write perf header\n");
2410 return err; 2400 return err;
2411 } 2401 }
2412 } 2402 }
2413 2403
2414 attr_offset = lseek(fd, 0, SEEK_CUR); 2404 attr_offset = lseek(ff.fd, 0, SEEK_CUR);
2415 2405
2416 evlist__for_each_entry(evlist, evsel) { 2406 evlist__for_each_entry(evlist, evsel) {
2417 f_attr = (struct perf_file_attr){ 2407 f_attr = (struct perf_file_attr){
@@ -2421,7 +2411,7 @@ int perf_session__write_header(struct perf_session *session,
2421 .size = evsel->ids * sizeof(u64), 2411 .size = evsel->ids * sizeof(u64),
2422 } 2412 }
2423 }; 2413 };
2424 err = do_write(fd, &f_attr, sizeof(f_attr)); 2414 err = do_write(&ff, &f_attr, sizeof(f_attr));
2425 if (err < 0) { 2415 if (err < 0) {
2426 pr_debug("failed to write perf header attribute\n"); 2416 pr_debug("failed to write perf header attribute\n");
2427 return err; 2417 return err;
@@ -2456,7 +2446,7 @@ int perf_session__write_header(struct perf_session *session,
2456 memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features)); 2446 memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features));
2457 2447
2458 lseek(fd, 0, SEEK_SET); 2448 lseek(fd, 0, SEEK_SET);
2459 err = do_write(fd, &f_header, sizeof(f_header)); 2449 err = do_write(&ff, &f_header, sizeof(f_header));
2460 if (err < 0) { 2450 if (err < 0) {
2461 pr_debug("failed to write perf header\n"); 2451 pr_debug("failed to write perf header\n");
2462 return err; 2452 return err;
@@ -2710,6 +2700,13 @@ static int perf_file_section__process(struct perf_file_section *section,
2710 struct perf_header *ph, 2700 struct perf_header *ph,
2711 int feat, int fd, void *data) 2701 int feat, int fd, void *data)
2712{ 2702{
2703 struct feat_fd fdd = {
2704 .fd = fd,
2705 .ph = ph,
2706 .size = section->size,
2707 .offset = section->offset,
2708 };
2709
2713 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) { 2710 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
2714 pr_debug("Failed to lseek to %" PRIu64 " offset for feature " 2711 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
2715 "%d, continuing...\n", section->offset, feat); 2712 "%d, continuing...\n", section->offset, feat);
@@ -2724,13 +2721,17 @@ static int perf_file_section__process(struct perf_file_section *section,
2724 if (!feat_ops[feat].process) 2721 if (!feat_ops[feat].process)
2725 return 0; 2722 return 0;
2726 2723
2727 return feat_ops[feat].process(section, ph, fd, data); 2724 return feat_ops[feat].process(&fdd, data);
2728} 2725}
2729 2726
2730static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, 2727static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
2731 struct perf_header *ph, int fd, 2728 struct perf_header *ph, int fd,
2732 bool repipe) 2729 bool repipe)
2733{ 2730{
2731 struct feat_fd ff = {
2732 .fd = STDOUT_FILENO,
2733 .ph = ph,
2734 };
2734 ssize_t ret; 2735 ssize_t ret;
2735 2736
2736 ret = readn(fd, header, sizeof(*header)); 2737 ret = readn(fd, header, sizeof(*header));
@@ -2745,7 +2746,7 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
2745 if (ph->needs_swap) 2746 if (ph->needs_swap)
2746 header->size = bswap_64(header->size); 2747 header->size = bswap_64(header->size);
2747 2748
2748 if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0) 2749 if (repipe && do_write(&ff, header, sizeof(*header)) < 0)
2749 return -1; 2750 return -1;
2750 2751
2751 return 0; 2752 return 0;
@@ -2757,7 +2758,7 @@ static int perf_header__read_pipe(struct perf_session *session)
2757 struct perf_pipe_file_header f_header; 2758 struct perf_pipe_file_header f_header;
2758 2759
2759 if (perf_file_header__read_pipe(&f_header, header, 2760 if (perf_file_header__read_pipe(&f_header, header,
2760 perf_data_file__fd(session->file), 2761 perf_data__fd(session->data),
2761 session->repipe) < 0) { 2762 session->repipe) < 0) {
2762 pr_debug("incompatible file format\n"); 2763 pr_debug("incompatible file format\n");
2763 return -EINVAL; 2764 return -EINVAL;
@@ -2860,13 +2861,13 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
2860 2861
2861int perf_session__read_header(struct perf_session *session) 2862int perf_session__read_header(struct perf_session *session)
2862{ 2863{
2863 struct perf_data_file *file = session->file; 2864 struct perf_data *data = session->data;
2864 struct perf_header *header = &session->header; 2865 struct perf_header *header = &session->header;
2865 struct perf_file_header f_header; 2866 struct perf_file_header f_header;
2866 struct perf_file_attr f_attr; 2867 struct perf_file_attr f_attr;
2867 u64 f_id; 2868 u64 f_id;
2868 int nr_attrs, nr_ids, i, j; 2869 int nr_attrs, nr_ids, i, j;
2869 int fd = perf_data_file__fd(file); 2870 int fd = perf_data__fd(data);
2870 2871
2871 session->evlist = perf_evlist__new(); 2872 session->evlist = perf_evlist__new();
2872 if (session->evlist == NULL) 2873 if (session->evlist == NULL)
@@ -2874,7 +2875,7 @@ int perf_session__read_header(struct perf_session *session)
2874 2875
2875 session->evlist->env = &header->env; 2876 session->evlist->env = &header->env;
2876 session->machines.host.env = &header->env; 2877 session->machines.host.env = &header->env;
2877 if (perf_data_file__is_pipe(file)) 2878 if (perf_data__is_pipe(data))
2878 return perf_header__read_pipe(session); 2879 return perf_header__read_pipe(session);
2879 2880
2880 if (perf_file_header__read(&f_header, header, fd) < 0) 2881 if (perf_file_header__read(&f_header, header, fd) < 0)
@@ -2889,7 +2890,7 @@ int perf_session__read_header(struct perf_session *session)
2889 if (f_header.data.size == 0) { 2890 if (f_header.data.size == 0) {
2890 pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n" 2891 pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n"
2891 "Was the 'perf record' command properly terminated?\n", 2892 "Was the 'perf record' command properly terminated?\n",
2892 file->path); 2893 data->file.path);
2893 } 2894 }
2894 2895
2895 nr_attrs = f_header.attrs.size / f_header.attr_size; 2896 nr_attrs = f_header.attrs.size / f_header.attr_size;
@@ -2995,6 +2996,103 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
2995 return err; 2996 return err;
2996} 2997}
2997 2998
2999int perf_event__synthesize_features(struct perf_tool *tool,
3000 struct perf_session *session,
3001 struct perf_evlist *evlist,
3002 perf_event__handler_t process)
3003{
3004 struct perf_header *header = &session->header;
3005 struct feat_fd ff;
3006 struct feature_event *fe;
3007 size_t sz, sz_hdr;
3008 int feat, ret;
3009
3010 sz_hdr = sizeof(fe->header);
3011 sz = sizeof(union perf_event);
3012 /* get a nice alignment */
3013 sz = PERF_ALIGN(sz, page_size);
3014
3015 memset(&ff, 0, sizeof(ff));
3016
3017 ff.buf = malloc(sz);
3018 if (!ff.buf)
3019 return -ENOMEM;
3020
3021 ff.size = sz - sz_hdr;
3022
3023 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
3024 if (!feat_ops[feat].synthesize) {
3025 pr_debug("No record header feature for header :%d\n", feat);
3026 continue;
3027 }
3028
3029 ff.offset = sizeof(*fe);
3030
3031 ret = feat_ops[feat].write(&ff, evlist);
3032 if (ret || ff.offset <= (ssize_t)sizeof(*fe)) {
3033 pr_debug("Error writing feature\n");
3034 continue;
3035 }
3036 /* ff.buf may have changed due to realloc in do_write() */
3037 fe = ff.buf;
3038 memset(fe, 0, sizeof(*fe));
3039
3040 fe->feat_id = feat;
3041 fe->header.type = PERF_RECORD_HEADER_FEATURE;
3042 fe->header.size = ff.offset;
3043
3044 ret = process(tool, ff.buf, NULL, NULL);
3045 if (ret) {
3046 free(ff.buf);
3047 return ret;
3048 }
3049 }
3050 free(ff.buf);
3051 return 0;
3052}
3053
3054int perf_event__process_feature(struct perf_tool *tool,
3055 union perf_event *event,
3056 struct perf_session *session __maybe_unused)
3057{
3058 struct feat_fd ff = { .fd = 0 };
3059 struct feature_event *fe = (struct feature_event *)event;
3060 int type = fe->header.type;
3061 u64 feat = fe->feat_id;
3062
3063 if (type < 0 || type >= PERF_RECORD_HEADER_MAX) {
3064 pr_warning("invalid record type %d in pipe-mode\n", type);
3065 return 0;
3066 }
3067 if (feat == HEADER_RESERVED || feat > HEADER_LAST_FEATURE) {
3068 pr_warning("invalid record type %d in pipe-mode\n", type);
3069 return -1;
3070 }
3071
3072 if (!feat_ops[feat].process)
3073 return 0;
3074
3075 ff.buf = (void *)fe->data;
3076 ff.size = event->header.size - sizeof(event->header);
3077 ff.ph = &session->header;
3078
3079 if (feat_ops[feat].process(&ff, NULL))
3080 return -1;
3081
3082 if (!feat_ops[feat].print || !tool->show_feat_hdr)
3083 return 0;
3084
3085 if (!feat_ops[feat].full_only ||
3086 tool->show_feat_hdr >= SHOW_FEAT_HEADER_FULL_INFO) {
3087 feat_ops[feat].print(&ff, stdout);
3088 } else {
3089 fprintf(stdout, "# %s info available, use -I to display\n",
3090 feat_ops[feat].name);
3091 }
3092
3093 return 0;
3094}
3095
2998static struct event_update_event * 3096static struct event_update_event *
2999event_update_event__new(size_t size, u64 type, u64 id) 3097event_update_event__new(size_t size, u64 type, u64 id)
3000{ 3098{
@@ -3253,6 +3351,7 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
3253 union perf_event ev; 3351 union perf_event ev;
3254 struct tracing_data *tdata; 3352 struct tracing_data *tdata;
3255 ssize_t size = 0, aligned_size = 0, padding; 3353 ssize_t size = 0, aligned_size = 0, padding;
3354 struct feat_fd ff;
3256 int err __maybe_unused = 0; 3355 int err __maybe_unused = 0;
3257 3356
3258 /* 3357 /*
@@ -3287,7 +3386,9 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
3287 */ 3386 */
3288 tracing_data_put(tdata); 3387 tracing_data_put(tdata);
3289 3388
3290 write_padded(fd, NULL, 0, padding); 3389 ff = (struct feat_fd){ .fd = fd };
3390 if (write_padded(&ff, NULL, 0, padding))
3391 return -1;
3291 3392
3292 return aligned_size; 3393 return aligned_size;
3293} 3394}
@@ -3297,7 +3398,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
3297 struct perf_session *session) 3398 struct perf_session *session)
3298{ 3399{
3299 ssize_t size_read, padding, size = event->tracing_data.size; 3400 ssize_t size_read, padding, size = event->tracing_data.size;
3300 int fd = perf_data_file__fd(session->file); 3401 int fd = perf_data__fd(session->data);
3301 off_t offset = lseek(fd, 0, SEEK_CUR); 3402 off_t offset = lseek(fd, 0, SEEK_CUR);
3302 char buf[BUFSIZ]; 3403 char buf[BUFSIZ];
3303 3404
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index d30109b421ee..29ccbfdf8724 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_HEADER_H 2#ifndef __PERF_HEADER_H
2#define __PERF_HEADER_H 3#define __PERF_HEADER_H
3 4
@@ -101,6 +102,15 @@ int perf_header__process_sections(struct perf_header *header, int fd,
101 102
102int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full); 103int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);
103 104
105int perf_event__synthesize_features(struct perf_tool *tool,
106 struct perf_session *session,
107 struct perf_evlist *evlist,
108 perf_event__handler_t process);
109
110int perf_event__process_feature(struct perf_tool *tool,
111 union perf_event *event,
112 struct perf_session *session);
113
104int perf_event__synthesize_attr(struct perf_tool *tool, 114int perf_event__synthesize_attr(struct perf_tool *tool,
105 struct perf_event_attr *attr, u32 ids, u64 *id, 115 struct perf_event_attr *attr, u32 ids, u64 *id,
106 perf_event__handler_t process); 116 perf_event__handler_t process);
@@ -144,7 +154,12 @@ bool is_perf_magic(u64 magic);
144 154
145#define NAME_ALIGN 64 155#define NAME_ALIGN 64
146 156
147int write_padded(int fd, const void *bf, size_t count, size_t count_aligned); 157struct feat_fd;
158
159int do_write(struct feat_fd *fd, const void *buf, size_t size);
160
161int write_padded(struct feat_fd *fd, const void *bf,
162 size_t count, size_t count_aligned);
148 163
149/* 164/*
150 * arch specific callback 165 * arch specific callback
diff --git a/tools/perf/util/help-unknown-cmd.c b/tools/perf/util/help-unknown-cmd.c
index 15b95300d7f3..4f07a5ba5030 100644
--- a/tools/perf/util/help-unknown-cmd.c
+++ b/tools/perf/util/help-unknown-cmd.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "cache.h" 2#include "cache.h"
2#include "config.h" 3#include "config.h"
3#include <poll.h> 4#include <poll.h>
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index cf0186a088c1..b6140950301e 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "util.h" 2#include "util.h"
2#include "build-id.h" 3#include "build-id.h"
3#include "hist.h" 4#include "hist.h"
@@ -167,6 +168,10 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
167 symlen = unresolved_col_width + 4 + 2; 168 symlen = unresolved_col_width + 4 + 2;
168 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO); 169 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
169 } 170 }
171
172 hists__new_col_len(hists, HISTC_MEM_PHYS_DADDR,
173 unresolved_col_width + 4 + 2);
174
170 } else { 175 } else {
171 symlen = unresolved_col_width + 4 + 2; 176 symlen = unresolved_col_width + 4 + 2;
172 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen); 177 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen);
@@ -592,6 +597,7 @@ __hists__add_entry(struct hists *hists,
592 .map = al->map, 597 .map = al->map,
593 .sym = al->sym, 598 .sym = al->sym,
594 }, 599 },
600 .srcline = al->srcline ? strdup(al->srcline) : NULL,
595 .socket = al->socket, 601 .socket = al->socket,
596 .cpu = al->cpu, 602 .cpu = al->cpu,
597 .cpumode = al->cpumode, 603 .cpumode = al->cpumode,
@@ -749,12 +755,9 @@ iter_prepare_branch_entry(struct hist_entry_iter *iter, struct addr_location *al
749} 755}
750 756
751static int 757static int
752iter_add_single_branch_entry(struct hist_entry_iter *iter, 758iter_add_single_branch_entry(struct hist_entry_iter *iter __maybe_unused,
753 struct addr_location *al __maybe_unused) 759 struct addr_location *al __maybe_unused)
754{ 760{
755 /* to avoid calling callback function */
756 iter->he = NULL;
757
758 return 0; 761 return 0;
759} 762}
760 763
@@ -949,6 +952,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
949 .map = al->map, 952 .map = al->map,
950 .sym = al->sym, 953 .sym = al->sym,
951 }, 954 },
955 .srcline = al->srcline ? strdup(al->srcline) : NULL,
952 .parent = iter->parent, 956 .parent = iter->parent,
953 .raw_data = sample->raw_data, 957 .raw_data = sample->raw_data,
954 .raw_size = sample->raw_size, 958 .raw_size = sample->raw_size,
@@ -1140,11 +1144,6 @@ void hist_entry__delete(struct hist_entry *he)
1140 zfree(&he->mem_info); 1144 zfree(&he->mem_info);
1141 } 1145 }
1142 1146
1143 if (he->inline_node) {
1144 inline_node__delete(he->inline_node);
1145 he->inline_node = NULL;
1146 }
1147
1148 zfree(&he->stat_acc); 1147 zfree(&he->stat_acc);
1149 free_srcline(he->srcline); 1148 free_srcline(he->srcline);
1150 if (he->srcfile && he->srcfile[0]) 1149 if (he->srcfile && he->srcfile[0])
@@ -1762,6 +1761,8 @@ void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *pro
1762 else 1761 else
1763 use_callchain = symbol_conf.use_callchain; 1762 use_callchain = symbol_conf.use_callchain;
1764 1763
1764 use_callchain |= symbol_conf.show_branchflag_count;
1765
1765 output_resort(evsel__hists(evsel), prog, use_callchain, NULL); 1766 output_resort(evsel__hists(evsel), prog, use_callchain, NULL);
1766} 1767}
1767 1768
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ee3670a388df..f6630cb95eff 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_HIST_H 2#ifndef __PERF_HIST_H
2#define __PERF_HIST_H 3#define __PERF_HIST_H
3 4
@@ -47,6 +48,7 @@ enum hist_column {
47 HISTC_GLOBAL_WEIGHT, 48 HISTC_GLOBAL_WEIGHT,
48 HISTC_MEM_DADDR_SYMBOL, 49 HISTC_MEM_DADDR_SYMBOL,
49 HISTC_MEM_DADDR_DSO, 50 HISTC_MEM_DADDR_DSO,
51 HISTC_MEM_PHYS_DADDR,
50 HISTC_MEM_LOCKED, 52 HISTC_MEM_LOCKED,
51 HISTC_MEM_TLB, 53 HISTC_MEM_TLB,
52 HISTC_MEM_LVL, 54 HISTC_MEM_LVL,
diff --git a/tools/perf/util/include/asm/asm-offsets.h b/tools/perf/util/include/asm/asm-offsets.h
index ed538942523d..3aff4cf44944 100644
--- a/tools/perf/util/include/asm/asm-offsets.h
+++ b/tools/perf/util/include/asm/asm-offsets.h
@@ -1 +1,2 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* stub */ 2/* stub */
diff --git a/tools/perf/util/include/asm/cpufeature.h b/tools/perf/util/include/asm/cpufeature.h
index acffd5e4d1d4..2270481c7e0a 100644
--- a/tools/perf/util/include/asm/cpufeature.h
+++ b/tools/perf/util/include/asm/cpufeature.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1 2
2#ifndef PERF_CPUFEATURE_H 3#ifndef PERF_CPUFEATURE_H
3#define PERF_CPUFEATURE_H 4#define PERF_CPUFEATURE_H
diff --git a/tools/perf/util/include/asm/dwarf2.h b/tools/perf/util/include/asm/dwarf2.h
index afe38199e922..e9876be63dbf 100644
--- a/tools/perf/util/include/asm/dwarf2.h
+++ b/tools/perf/util/include/asm/dwarf2.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1 2
2#ifndef PERF_DWARF2_H 3#ifndef PERF_DWARF2_H
3#define PERF_DWARF2_H 4#define PERF_DWARF2_H
diff --git a/tools/perf/util/include/asm/uaccess.h b/tools/perf/util/include/asm/uaccess.h
index d0f72b8fcc35..6a6f4b990547 100644
--- a/tools/perf/util/include/asm/uaccess.h
+++ b/tools/perf/util/include/asm/uaccess.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_ASM_UACCESS_H_ 2#ifndef _PERF_ASM_UACCESS_H_
2#define _PERF_ASM_UACCESS_H_ 3#define _PERF_ASM_UACCESS_H_
3 4
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
index 43bfd8da7919..7d99a084e82d 100644
--- a/tools/perf/util/include/dwarf-regs.h
+++ b/tools/perf/util/include/dwarf-regs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_DWARF_REGS_H_ 2#ifndef _PERF_DWARF_REGS_H_
2#define _PERF_DWARF_REGS_H_ 3#define _PERF_DWARF_REGS_H_
3 4
diff --git a/tools/perf/util/include/linux/linkage.h b/tools/perf/util/include/linux/linkage.h
index 06387cffe125..f01d48a8d707 100644
--- a/tools/perf/util/include/linux/linkage.h
+++ b/tools/perf/util/include/linux/linkage.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1 2
2#ifndef PERF_LINUX_LINKAGE_H_ 3#ifndef PERF_LINUX_LINKAGE_H_
3#define PERF_LINUX_LINKAGE_H_ 4#define PERF_LINUX_LINKAGE_H_
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index 218ee2bac9a5..5325e65f9711 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -500,7 +500,7 @@ static int intel_bts_process_queue(struct intel_bts_queue *btsq, u64 *timestamp)
500 } 500 }
501 501
502 if (!buffer->data) { 502 if (!buffer->data) {
503 int fd = perf_data_file__fd(btsq->bts->session->file); 503 int fd = perf_data__fd(btsq->bts->session->data);
504 504
505 buffer->data = auxtrace_buffer__get_data(buffer, fd); 505 buffer->data = auxtrace_buffer__get_data(buffer, fd);
506 if (!buffer->data) { 506 if (!buffer->data) {
@@ -664,10 +664,10 @@ static int intel_bts_process_auxtrace_event(struct perf_session *session,
664 if (!bts->data_queued) { 664 if (!bts->data_queued) {
665 struct auxtrace_buffer *buffer; 665 struct auxtrace_buffer *buffer;
666 off_t data_offset; 666 off_t data_offset;
667 int fd = perf_data_file__fd(session->file); 667 int fd = perf_data__fd(session->data);
668 int err; 668 int err;
669 669
670 if (perf_data_file__is_pipe(session->file)) { 670 if (perf_data__is_pipe(session->data)) {
671 data_offset = 0; 671 data_offset = 0;
672 } else { 672 } else {
673 data_offset = lseek(fd, 0, SEEK_CUR); 673 data_offset = lseek(fd, 0, SEEK_CUR);
diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build
index 7aca5d6d7e1f..10e0814bb8d2 100644
--- a/tools/perf/util/intel-pt-decoder/Build
+++ b/tools/perf/util/intel-pt-decoder/Build
@@ -25,6 +25,6 @@ $(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/in
25 25
26CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder 26CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder
27 27
28ifneq ($(CC), clang) 28ifeq ($(CC_NO_CLANG), 1)
29 CFLAGS_intel-pt-insn-decoder.o += -Wno-override-init 29 CFLAGS_intel-pt-insn-decoder.o += -Wno-override-init
30endif 30endif
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 54e961659514..ddd5c4c21129 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
@@ -1,4 +1,5 @@
1#!/bin/awk -f 1#!/bin/awk -f
2# SPDX-License-Identifier: GPL-2.0
2# gen-insn-attr-x86.awk: Instruction attribute table generator 3# gen-insn-attr-x86.awk: Instruction attribute table generator
3# Written by Masami Hiramatsu <mhiramat@redhat.com> 4# Written by Masami Hiramatsu <mhiramat@redhat.com>
4# 5#
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index b58f9fd1e2ee..23f9ba676df0 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -271,7 +271,7 @@ next:
271 ptq->buffer = buffer; 271 ptq->buffer = buffer;
272 272
273 if (!buffer->data) { 273 if (!buffer->data) {
274 int fd = perf_data_file__fd(ptq->pt->session->file); 274 int fd = perf_data__fd(ptq->pt->session->data);
275 275
276 buffer->data = auxtrace_buffer__get_data(buffer, fd); 276 buffer->data = auxtrace_buffer__get_data(buffer, fd);
277 if (!buffer->data) 277 if (!buffer->data)
@@ -2084,10 +2084,10 @@ static int intel_pt_process_auxtrace_event(struct perf_session *session,
2084 if (!pt->data_queued) { 2084 if (!pt->data_queued) {
2085 struct auxtrace_buffer *buffer; 2085 struct auxtrace_buffer *buffer;
2086 off_t data_offset; 2086 off_t data_offset;
2087 int fd = perf_data_file__fd(session->file); 2087 int fd = perf_data__fd(session->data);
2088 int err; 2088 int err;
2089 2089
2090 if (perf_data_file__is_pipe(session->file)) { 2090 if (perf_data__is_pipe(session->data)) {
2091 data_offset = 0; 2091 data_offset = 0;
2092 } else { 2092 } else {
2093 data_offset = lseek(fd, 0, SEEK_CUR); 2093 data_offset = lseek(fd, 0, SEEK_CUR);
diff --git a/tools/perf/util/intlist.h b/tools/perf/util/intlist.h
index 020b9ca1b47e..85bab8735fa9 100644
--- a/tools/perf/util/intlist.h
+++ b/tools/perf/util/intlist.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_INTLIST_H 2#ifndef __PERF_INTLIST_H
2#define __PERF_INTLIST_H 3#define __PERF_INTLIST_H
3 4
diff --git a/tools/perf/util/jit.h b/tools/perf/util/jit.h
index 3f42ee4d2a0b..6817ffc2a059 100644
--- a/tools/perf/util/jit.h
+++ b/tools/perf/util/jit.h
@@ -1,9 +1,10 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __JIT_H__ 2#ifndef __JIT_H__
2#define __JIT_H__ 3#define __JIT_H__
3 4
4#include <data.h> 5#include <data.h>
5 6
6int jit_process(struct perf_session *session, struct perf_data_file *output, 7int jit_process(struct perf_session *session, struct perf_data *output,
7 struct machine *machine, char *filename, pid_t pid, u64 *nbytes); 8 struct machine *machine, char *filename, pid_t pid, u64 *nbytes);
8 9
9int jit_inject_record(const char *filename); 10int jit_inject_record(const char *filename);
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c
index 9084930e1757..a1863000e972 100644
--- a/tools/perf/util/jitdump.c
+++ b/tools/perf/util/jitdump.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/sysmacros.h> 2#include <sys/sysmacros.h>
2#include <sys/types.h> 3#include <sys/types.h>
3#include <errno.h> 4#include <errno.h>
@@ -29,7 +30,7 @@
29#include "sane_ctype.h" 30#include "sane_ctype.h"
30 31
31struct jit_buf_desc { 32struct jit_buf_desc {
32 struct perf_data_file *output; 33 struct perf_data *output;
33 struct perf_session *session; 34 struct perf_session *session;
34 struct machine *machine; 35 struct machine *machine;
35 union jr_entry *entry; 36 union jr_entry *entry;
@@ -60,8 +61,8 @@ struct debug_line_info {
60 61
61struct jit_tool { 62struct jit_tool {
62 struct perf_tool tool; 63 struct perf_tool tool;
63 struct perf_data_file output; 64 struct perf_data output;
64 struct perf_data_file input; 65 struct perf_data input;
65 u64 bytes_written; 66 u64 bytes_written;
66}; 67};
67 68
@@ -356,7 +357,7 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_event *event)
356{ 357{
357 ssize_t size; 358 ssize_t size;
358 359
359 size = perf_data_file__write(jd->output, event, event->header.size); 360 size = perf_data__write(jd->output, event, event->header.size);
360 if (size < 0) 361 if (size < 0)
361 return -1; 362 return -1;
362 363
@@ -751,7 +752,7 @@ jit_detect(char *mmap_name, pid_t pid)
751 752
752int 753int
753jit_process(struct perf_session *session, 754jit_process(struct perf_session *session,
754 struct perf_data_file *output, 755 struct perf_data *output,
755 struct machine *machine, 756 struct machine *machine,
756 char *filename, 757 char *filename,
757 pid_t pid, 758 pid_t pid,
diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h
index d01e73592f6e..7b1f06567521 100644
--- a/tools/perf/util/kvm-stat.h
+++ b/tools/perf/util/kvm-stat.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_KVM_STAT_H 2#ifndef __PERF_KVM_STAT_H
2#define __PERF_KVM_STAT_H 3#define __PERF_KVM_STAT_H
3 4
diff --git a/tools/perf/util/levenshtein.c b/tools/perf/util/levenshtein.c
index f616e4f65b67..a217ecf0359d 100644
--- a/tools/perf/util/levenshtein.c
+++ b/tools/perf/util/levenshtein.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "levenshtein.h" 2#include "levenshtein.h"
2#include <errno.h> 3#include <errno.h>
3#include <stdlib.h> 4#include <stdlib.h>
diff --git a/tools/perf/util/levenshtein.h b/tools/perf/util/levenshtein.h
index b0fcb6d8a881..34ca173c557d 100644
--- a/tools/perf/util/levenshtein.h
+++ b/tools/perf/util/levenshtein.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_LEVENSHTEIN_H 2#ifndef __PERF_LEVENSHTEIN_H
2#define __PERF_LEVENSHTEIN_H 3#define __PERF_LEVENSHTEIN_H
3 4
diff --git a/tools/perf/util/libunwind/arm64.c b/tools/perf/util/libunwind/arm64.c
index 6559bc586643..66756e6be111 100644
--- a/tools/perf/util/libunwind/arm64.c
+++ b/tools/perf/util/libunwind/arm64.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * This file setups defines to compile arch specific binary from the 3 * This file setups defines to compile arch specific binary from the
3 * generic one. 4 * generic one.
diff --git a/tools/perf/util/libunwind/x86_32.c b/tools/perf/util/libunwind/x86_32.c
index 957ffff72428..c5e568188e19 100644
--- a/tools/perf/util/libunwind/x86_32.c
+++ b/tools/perf/util/libunwind/x86_32.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * This file setups defines to compile arch specific binary from the 3 * This file setups defines to compile arch specific binary from the
3 * generic one. 4 * generic one.
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index c6a15f204c03..4952b429caa7 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright (C) 2015, Wang Nan <wangnan0@huawei.com> 3 * Copyright (C) 2015, Wang Nan <wangnan0@huawei.com>
3 * Copyright (C) 2015, Huawei Inc. 4 * Copyright (C) 2015, Huawei Inc.
@@ -33,7 +34,7 @@ struct llvm_param llvm_param = {
33 34
34int perf_llvm_config(const char *var, const char *value) 35int perf_llvm_config(const char *var, const char *value)
35{ 36{
36 if (prefixcmp(var, "llvm.")) 37 if (!strstarts(var, "llvm."))
37 return 0; 38 return 0;
38 var += sizeof("llvm.") - 1; 39 var += sizeof("llvm.") - 1;
39 40
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h
index c87a2a92a88f..d3ad8deb5db4 100644
--- a/tools/perf/util/llvm-utils.h
+++ b/tools/perf/util/llvm-utils.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Copyright (C) 2015, Wang Nan <wangnan0@huawei.com> 3 * Copyright (C) 2015, Wang Nan <wangnan0@huawei.com>
3 * Copyright (C) 2015, Huawei Inc. 4 * Copyright (C) 2015, Huawei Inc.
diff --git a/tools/perf/util/lzma.c b/tools/perf/util/lzma.c
index 4ca7c5c6cdcd..07498eaddc08 100644
--- a/tools/perf/util/lzma.c
+++ b/tools/perf/util/lzma.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <lzma.h> 3#include <lzma.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 2e9eb6aa3ce2..6a8d03c3d9b7 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <dirent.h> 2#include <dirent.h>
2#include <errno.h> 3#include <errno.h>
3#include <inttypes.h> 4#include <inttypes.h>
@@ -30,7 +31,21 @@ static void dsos__init(struct dsos *dsos)
30{ 31{
31 INIT_LIST_HEAD(&dsos->head); 32 INIT_LIST_HEAD(&dsos->head);
32 dsos->root = RB_ROOT; 33 dsos->root = RB_ROOT;
33 pthread_rwlock_init(&dsos->lock, NULL); 34 init_rwsem(&dsos->lock);
35}
36
37static void machine__threads_init(struct machine *machine)
38{
39 int i;
40
41 for (i = 0; i < THREADS__TABLE_SIZE; i++) {
42 struct threads *threads = &machine->threads[i];
43 threads->entries = RB_ROOT;
44 init_rwsem(&threads->lock);
45 threads->nr = 0;
46 INIT_LIST_HEAD(&threads->dead);
47 threads->last_match = NULL;
48 }
34} 49}
35 50
36int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 51int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
@@ -40,11 +55,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
40 RB_CLEAR_NODE(&machine->rb_node); 55 RB_CLEAR_NODE(&machine->rb_node);
41 dsos__init(&machine->dsos); 56 dsos__init(&machine->dsos);
42 57
43 machine->threads = RB_ROOT; 58 machine__threads_init(machine);
44 pthread_rwlock_init(&machine->threads_lock, NULL);
45 machine->nr_threads = 0;
46 INIT_LIST_HEAD(&machine->dead_threads);
47 machine->last_match = NULL;
48 59
49 machine->vdso_info = NULL; 60 machine->vdso_info = NULL;
50 machine->env = NULL; 61 machine->env = NULL;
@@ -120,7 +131,7 @@ static void dsos__purge(struct dsos *dsos)
120{ 131{
121 struct dso *pos, *n; 132 struct dso *pos, *n;
122 133
123 pthread_rwlock_wrlock(&dsos->lock); 134 down_write(&dsos->lock);
124 135
125 list_for_each_entry_safe(pos, n, &dsos->head, node) { 136 list_for_each_entry_safe(pos, n, &dsos->head, node) {
126 RB_CLEAR_NODE(&pos->rb_node); 137 RB_CLEAR_NODE(&pos->rb_node);
@@ -129,39 +140,49 @@ static void dsos__purge(struct dsos *dsos)
129 dso__put(pos); 140 dso__put(pos);
130 } 141 }
131 142
132 pthread_rwlock_unlock(&dsos->lock); 143 up_write(&dsos->lock);
133} 144}
134 145
135static void dsos__exit(struct dsos *dsos) 146static void dsos__exit(struct dsos *dsos)
136{ 147{
137 dsos__purge(dsos); 148 dsos__purge(dsos);
138 pthread_rwlock_destroy(&dsos->lock); 149 exit_rwsem(&dsos->lock);
139} 150}
140 151
141void machine__delete_threads(struct machine *machine) 152void machine__delete_threads(struct machine *machine)
142{ 153{
143 struct rb_node *nd; 154 struct rb_node *nd;
155 int i;
144 156
145 pthread_rwlock_wrlock(&machine->threads_lock); 157 for (i = 0; i < THREADS__TABLE_SIZE; i++) {
146 nd = rb_first(&machine->threads); 158 struct threads *threads = &machine->threads[i];
147 while (nd) { 159 down_write(&threads->lock);
148 struct thread *t = rb_entry(nd, struct thread, rb_node); 160 nd = rb_first(&threads->entries);
161 while (nd) {
162 struct thread *t = rb_entry(nd, struct thread, rb_node);
149 163
150 nd = rb_next(nd); 164 nd = rb_next(nd);
151 __machine__remove_thread(machine, t, false); 165 __machine__remove_thread(machine, t, false);
166 }
167 up_write(&threads->lock);
152 } 168 }
153 pthread_rwlock_unlock(&machine->threads_lock);
154} 169}
155 170
156void machine__exit(struct machine *machine) 171void machine__exit(struct machine *machine)
157{ 172{
173 int i;
174
158 machine__destroy_kernel_maps(machine); 175 machine__destroy_kernel_maps(machine);
159 map_groups__exit(&machine->kmaps); 176 map_groups__exit(&machine->kmaps);
160 dsos__exit(&machine->dsos); 177 dsos__exit(&machine->dsos);
161 machine__exit_vdso(machine); 178 machine__exit_vdso(machine);
162 zfree(&machine->root_dir); 179 zfree(&machine->root_dir);
163 zfree(&machine->current_tid); 180 zfree(&machine->current_tid);
164 pthread_rwlock_destroy(&machine->threads_lock); 181
182 for (i = 0; i < THREADS__TABLE_SIZE; i++) {
183 struct threads *threads = &machine->threads[i];
184 exit_rwsem(&threads->lock);
185 }
165} 186}
166 187
167void machine__delete(struct machine *machine) 188void machine__delete(struct machine *machine)
@@ -379,10 +400,11 @@ out_err:
379 * lookup/new thread inserted. 400 * lookup/new thread inserted.
380 */ 401 */
381static struct thread *____machine__findnew_thread(struct machine *machine, 402static struct thread *____machine__findnew_thread(struct machine *machine,
403 struct threads *threads,
382 pid_t pid, pid_t tid, 404 pid_t pid, pid_t tid,
383 bool create) 405 bool create)
384{ 406{
385 struct rb_node **p = &machine->threads.rb_node; 407 struct rb_node **p = &threads->entries.rb_node;
386 struct rb_node *parent = NULL; 408 struct rb_node *parent = NULL;
387 struct thread *th; 409 struct thread *th;
388 410
@@ -391,14 +413,14 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
391 * so most of the time we dont have to look up 413 * so most of the time we dont have to look up
392 * the full rbtree: 414 * the full rbtree:
393 */ 415 */
394 th = machine->last_match; 416 th = threads->last_match;
395 if (th != NULL) { 417 if (th != NULL) {
396 if (th->tid == tid) { 418 if (th->tid == tid) {
397 machine__update_thread_pid(machine, th, pid); 419 machine__update_thread_pid(machine, th, pid);
398 return thread__get(th); 420 return thread__get(th);
399 } 421 }
400 422
401 machine->last_match = NULL; 423 threads->last_match = NULL;
402 } 424 }
403 425
404 while (*p != NULL) { 426 while (*p != NULL) {
@@ -406,7 +428,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
406 th = rb_entry(parent, struct thread, rb_node); 428 th = rb_entry(parent, struct thread, rb_node);
407 429
408 if (th->tid == tid) { 430 if (th->tid == tid) {
409 machine->last_match = th; 431 threads->last_match = th;
410 machine__update_thread_pid(machine, th, pid); 432 machine__update_thread_pid(machine, th, pid);
411 return thread__get(th); 433 return thread__get(th);
412 } 434 }
@@ -423,7 +445,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
423 th = thread__new(pid, tid); 445 th = thread__new(pid, tid);
424 if (th != NULL) { 446 if (th != NULL) {
425 rb_link_node(&th->rb_node, parent, p); 447 rb_link_node(&th->rb_node, parent, p);
426 rb_insert_color(&th->rb_node, &machine->threads); 448 rb_insert_color(&th->rb_node, &threads->entries);
427 449
428 /* 450 /*
429 * We have to initialize map_groups separately 451 * We have to initialize map_groups separately
@@ -434,7 +456,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
434 * leader and that would screwed the rb tree. 456 * leader and that would screwed the rb tree.
435 */ 457 */
436 if (thread__init_map_groups(th, machine)) { 458 if (thread__init_map_groups(th, machine)) {
437 rb_erase_init(&th->rb_node, &machine->threads); 459 rb_erase_init(&th->rb_node, &threads->entries);
438 RB_CLEAR_NODE(&th->rb_node); 460 RB_CLEAR_NODE(&th->rb_node);
439 thread__put(th); 461 thread__put(th);
440 return NULL; 462 return NULL;
@@ -443,8 +465,8 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
443 * It is now in the rbtree, get a ref 465 * It is now in the rbtree, get a ref
444 */ 466 */
445 thread__get(th); 467 thread__get(th);
446 machine->last_match = th; 468 threads->last_match = th;
447 ++machine->nr_threads; 469 ++threads->nr;
448 } 470 }
449 471
450 return th; 472 return th;
@@ -452,27 +474,30 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
452 474
453struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid) 475struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid)
454{ 476{
455 return ____machine__findnew_thread(machine, pid, tid, true); 477 return ____machine__findnew_thread(machine, machine__threads(machine, tid), pid, tid, true);
456} 478}
457 479
458struct thread *machine__findnew_thread(struct machine *machine, pid_t pid, 480struct thread *machine__findnew_thread(struct machine *machine, pid_t pid,
459 pid_t tid) 481 pid_t tid)
460{ 482{
483 struct threads *threads = machine__threads(machine, tid);
461 struct thread *th; 484 struct thread *th;
462 485
463 pthread_rwlock_wrlock(&machine->threads_lock); 486 down_write(&threads->lock);
464 th = __machine__findnew_thread(machine, pid, tid); 487 th = __machine__findnew_thread(machine, pid, tid);
465 pthread_rwlock_unlock(&machine->threads_lock); 488 up_write(&threads->lock);
466 return th; 489 return th;
467} 490}
468 491
469struct thread *machine__find_thread(struct machine *machine, pid_t pid, 492struct thread *machine__find_thread(struct machine *machine, pid_t pid,
470 pid_t tid) 493 pid_t tid)
471{ 494{
495 struct threads *threads = machine__threads(machine, tid);
472 struct thread *th; 496 struct thread *th;
473 pthread_rwlock_rdlock(&machine->threads_lock); 497
474 th = ____machine__findnew_thread(machine, pid, tid, false); 498 down_read(&threads->lock);
475 pthread_rwlock_unlock(&machine->threads_lock); 499 th = ____machine__findnew_thread(machine, threads, pid, tid, false);
500 up_read(&threads->lock);
476 return th; 501 return th;
477} 502}
478 503
@@ -564,7 +589,7 @@ static struct dso *machine__findnew_module_dso(struct machine *machine,
564{ 589{
565 struct dso *dso; 590 struct dso *dso;
566 591
567 pthread_rwlock_wrlock(&machine->dsos.lock); 592 down_write(&machine->dsos.lock);
568 593
569 dso = __dsos__find(&machine->dsos, m->name, true); 594 dso = __dsos__find(&machine->dsos, m->name, true);
570 if (!dso) { 595 if (!dso) {
@@ -578,7 +603,7 @@ static struct dso *machine__findnew_module_dso(struct machine *machine,
578 603
579 dso__get(dso); 604 dso__get(dso);
580out_unlock: 605out_unlock:
581 pthread_rwlock_unlock(&machine->dsos.lock); 606 up_write(&machine->dsos.lock);
582 return dso; 607 return dso;
583} 608}
584 609
@@ -705,7 +730,8 @@ size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
705 730
706 if (kdso->has_build_id) { 731 if (kdso->has_build_id) {
707 char filename[PATH_MAX]; 732 char filename[PATH_MAX];
708 if (dso__build_id_filename(kdso, filename, sizeof(filename))) 733 if (dso__build_id_filename(kdso, filename, sizeof(filename),
734 false))
709 printed += fprintf(fp, "[0] %s\n", filename); 735 printed += fprintf(fp, "[0] %s\n", filename);
710 } 736 }
711 737
@@ -718,21 +744,25 @@ size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
718 744
719size_t machine__fprintf(struct machine *machine, FILE *fp) 745size_t machine__fprintf(struct machine *machine, FILE *fp)
720{ 746{
721 size_t ret;
722 struct rb_node *nd; 747 struct rb_node *nd;
748 size_t ret;
749 int i;
723 750
724 pthread_rwlock_rdlock(&machine->threads_lock); 751 for (i = 0; i < THREADS__TABLE_SIZE; i++) {
752 struct threads *threads = &machine->threads[i];
725 753
726 ret = fprintf(fp, "Threads: %u\n", machine->nr_threads); 754 down_read(&threads->lock);
727 755
728 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) { 756 ret = fprintf(fp, "Threads: %u\n", threads->nr);
729 struct thread *pos = rb_entry(nd, struct thread, rb_node);
730 757
731 ret += thread__fprintf(pos, fp); 758 for (nd = rb_first(&threads->entries); nd; nd = rb_next(nd)) {
732 } 759 struct thread *pos = rb_entry(nd, struct thread, rb_node);
733 760
734 pthread_rwlock_unlock(&machine->threads_lock); 761 ret += thread__fprintf(pos, fp);
762 }
735 763
764 up_read(&threads->lock);
765 }
736 return ret; 766 return ret;
737} 767}
738 768
@@ -1137,7 +1167,8 @@ int __weak arch__fix_module_text_start(u64 *start __maybe_unused,
1137 return 0; 1167 return 0;
1138} 1168}
1139 1169
1140static int machine__create_module(void *arg, const char *name, u64 start) 1170static int machine__create_module(void *arg, const char *name, u64 start,
1171 u64 size)
1141{ 1172{
1142 struct machine *machine = arg; 1173 struct machine *machine = arg;
1143 struct map *map; 1174 struct map *map;
@@ -1148,6 +1179,7 @@ static int machine__create_module(void *arg, const char *name, u64 start)
1148 map = machine__findnew_module_map(machine, start, name); 1179 map = machine__findnew_module_map(machine, start, name);
1149 if (map == NULL) 1180 if (map == NULL)
1150 return -1; 1181 return -1;
1182 map->end = start + size;
1151 1183
1152 dso__kernel_module_get_build_id(map->dso, machine->root_dir); 1184 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
1153 1185
@@ -1289,7 +1321,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1289 struct dso *kernel = NULL; 1321 struct dso *kernel = NULL;
1290 struct dso *dso; 1322 struct dso *dso;
1291 1323
1292 pthread_rwlock_rdlock(&machine->dsos.lock); 1324 down_read(&machine->dsos.lock);
1293 1325
1294 list_for_each_entry(dso, &machine->dsos.head, node) { 1326 list_for_each_entry(dso, &machine->dsos.head, node) {
1295 1327
@@ -1319,7 +1351,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1319 break; 1351 break;
1320 } 1352 }
1321 1353
1322 pthread_rwlock_unlock(&machine->dsos.lock); 1354 up_read(&machine->dsos.lock);
1323 1355
1324 if (kernel == NULL) 1356 if (kernel == NULL)
1325 kernel = machine__findnew_dso(machine, kmmap_prefix); 1357 kernel = machine__findnew_dso(machine, kmmap_prefix);
@@ -1392,7 +1424,7 @@ int machine__process_mmap2_event(struct machine *machine,
1392 1424
1393 map = map__new(machine, event->mmap2.start, 1425 map = map__new(machine, event->mmap2.start,
1394 event->mmap2.len, event->mmap2.pgoff, 1426 event->mmap2.len, event->mmap2.pgoff,
1395 event->mmap2.pid, event->mmap2.maj, 1427 event->mmap2.maj,
1396 event->mmap2.min, event->mmap2.ino, 1428 event->mmap2.min, event->mmap2.ino,
1397 event->mmap2.ino_generation, 1429 event->mmap2.ino_generation,
1398 event->mmap2.prot, 1430 event->mmap2.prot,
@@ -1450,7 +1482,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
1450 1482
1451 map = map__new(machine, event->mmap.start, 1483 map = map__new(machine, event->mmap.start,
1452 event->mmap.len, event->mmap.pgoff, 1484 event->mmap.len, event->mmap.pgoff,
1453 event->mmap.pid, 0, 0, 0, 0, 0, 0, 1485 0, 0, 0, 0, 0, 0,
1454 event->mmap.filename, 1486 event->mmap.filename,
1455 type, thread); 1487 type, thread);
1456 1488
@@ -1476,23 +1508,25 @@ out_problem:
1476 1508
1477static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock) 1509static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock)
1478{ 1510{
1479 if (machine->last_match == th) 1511 struct threads *threads = machine__threads(machine, th->tid);
1480 machine->last_match = NULL; 1512
1513 if (threads->last_match == th)
1514 threads->last_match = NULL;
1481 1515
1482 BUG_ON(refcount_read(&th->refcnt) == 0); 1516 BUG_ON(refcount_read(&th->refcnt) == 0);
1483 if (lock) 1517 if (lock)
1484 pthread_rwlock_wrlock(&machine->threads_lock); 1518 down_write(&threads->lock);
1485 rb_erase_init(&th->rb_node, &machine->threads); 1519 rb_erase_init(&th->rb_node, &threads->entries);
1486 RB_CLEAR_NODE(&th->rb_node); 1520 RB_CLEAR_NODE(&th->rb_node);
1487 --machine->nr_threads; 1521 --threads->nr;
1488 /* 1522 /*
1489 * Move it first to the dead_threads list, then drop the reference, 1523 * Move it first to the dead_threads list, then drop the reference,
1490 * if this is the last reference, then the thread__delete destructor 1524 * if this is the last reference, then the thread__delete destructor
1491 * will be called and we will remove it from the dead_threads list. 1525 * will be called and we will remove it from the dead_threads list.
1492 */ 1526 */
1493 list_add_tail(&th->node, &machine->dead_threads); 1527 list_add_tail(&th->node, &threads->dead);
1494 if (lock) 1528 if (lock)
1495 pthread_rwlock_unlock(&machine->threads_lock); 1529 up_write(&threads->lock);
1496 thread__put(th); 1530 thread__put(th);
1497} 1531}
1498 1532
@@ -1632,10 +1666,12 @@ static void ip__resolve_ams(struct thread *thread,
1632 ams->al_addr = al.addr; 1666 ams->al_addr = al.addr;
1633 ams->sym = al.sym; 1667 ams->sym = al.sym;
1634 ams->map = al.map; 1668 ams->map = al.map;
1669 ams->phys_addr = 0;
1635} 1670}
1636 1671
1637static void ip__resolve_data(struct thread *thread, 1672static void ip__resolve_data(struct thread *thread,
1638 u8 m, struct addr_map_symbol *ams, u64 addr) 1673 u8 m, struct addr_map_symbol *ams,
1674 u64 addr, u64 phys_addr)
1639{ 1675{
1640 struct addr_location al; 1676 struct addr_location al;
1641 1677
@@ -1655,6 +1691,7 @@ static void ip__resolve_data(struct thread *thread,
1655 ams->al_addr = al.addr; 1691 ams->al_addr = al.addr;
1656 ams->sym = al.sym; 1692 ams->sym = al.sym;
1657 ams->map = al.map; 1693 ams->map = al.map;
1694 ams->phys_addr = phys_addr;
1658} 1695}
1659 1696
1660struct mem_info *sample__resolve_mem(struct perf_sample *sample, 1697struct mem_info *sample__resolve_mem(struct perf_sample *sample,
@@ -1666,12 +1703,38 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1666 return NULL; 1703 return NULL;
1667 1704
1668 ip__resolve_ams(al->thread, &mi->iaddr, sample->ip); 1705 ip__resolve_ams(al->thread, &mi->iaddr, sample->ip);
1669 ip__resolve_data(al->thread, al->cpumode, &mi->daddr, sample->addr); 1706 ip__resolve_data(al->thread, al->cpumode, &mi->daddr,
1707 sample->addr, sample->phys_addr);
1670 mi->data_src.val = sample->data_src; 1708 mi->data_src.val = sample->data_src;
1671 1709
1672 return mi; 1710 return mi;
1673} 1711}
1674 1712
1713static char *callchain_srcline(struct map *map, struct symbol *sym, u64 ip)
1714{
1715 char *srcline = NULL;
1716
1717 if (!map || callchain_param.key == CCKEY_FUNCTION)
1718 return srcline;
1719
1720 srcline = srcline__tree_find(&map->dso->srclines, ip);
1721 if (!srcline) {
1722 bool show_sym = false;
1723 bool show_addr = callchain_param.key == CCKEY_ADDRESS;
1724
1725 srcline = get_srcline(map->dso, map__rip_2objdump(map, ip),
1726 sym, show_sym, show_addr);
1727 srcline__tree_insert(&map->dso->srclines, ip, srcline);
1728 }
1729
1730 return srcline;
1731}
1732
1733struct iterations {
1734 int nr_loop_iter;
1735 u64 cycles;
1736};
1737
1675static int add_callchain_ip(struct thread *thread, 1738static int add_callchain_ip(struct thread *thread,
1676 struct callchain_cursor *cursor, 1739 struct callchain_cursor *cursor,
1677 struct symbol **parent, 1740 struct symbol **parent,
@@ -1680,10 +1743,13 @@ static int add_callchain_ip(struct thread *thread,
1680 u64 ip, 1743 u64 ip,
1681 bool branch, 1744 bool branch,
1682 struct branch_flags *flags, 1745 struct branch_flags *flags,
1683 int nr_loop_iter, 1746 struct iterations *iter,
1684 int samples) 1747 u64 branch_from)
1685{ 1748{
1686 struct addr_location al; 1749 struct addr_location al;
1750 int nr_loop_iter = 0;
1751 u64 iter_cycles = 0;
1752 const char *srcline = NULL;
1687 1753
1688 al.filtered = 0; 1754 al.filtered = 0;
1689 al.sym = NULL; 1755 al.sym = NULL;
@@ -1733,8 +1799,16 @@ static int add_callchain_ip(struct thread *thread,
1733 1799
1734 if (symbol_conf.hide_unresolved && al.sym == NULL) 1800 if (symbol_conf.hide_unresolved && al.sym == NULL)
1735 return 0; 1801 return 0;
1802
1803 if (iter) {
1804 nr_loop_iter = iter->nr_loop_iter;
1805 iter_cycles = iter->cycles;
1806 }
1807
1808 srcline = callchain_srcline(al.map, al.sym, al.addr);
1736 return callchain_cursor_append(cursor, al.addr, al.map, al.sym, 1809 return callchain_cursor_append(cursor, al.addr, al.map, al.sym,
1737 branch, flags, nr_loop_iter, samples); 1810 branch, flags, nr_loop_iter,
1811 iter_cycles, branch_from, srcline);
1738} 1812}
1739 1813
1740struct branch_info *sample__resolve_bstack(struct perf_sample *sample, 1814struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
@@ -1755,6 +1829,18 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
1755 return bi; 1829 return bi;
1756} 1830}
1757 1831
1832static void save_iterations(struct iterations *iter,
1833 struct branch_entry *be, int nr)
1834{
1835 int i;
1836
1837 iter->nr_loop_iter = nr;
1838 iter->cycles = 0;
1839
1840 for (i = 0; i < nr; i++)
1841 iter->cycles += be[i].flags.cycles;
1842}
1843
1758#define CHASHSZ 127 1844#define CHASHSZ 127
1759#define CHASHBITS 7 1845#define CHASHBITS 7
1760#define NO_ENTRY 0xff 1846#define NO_ENTRY 0xff
@@ -1762,7 +1848,8 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
1762#define PERF_MAX_BRANCH_DEPTH 127 1848#define PERF_MAX_BRANCH_DEPTH 127
1763 1849
1764/* Remove loops. */ 1850/* Remove loops. */
1765static int remove_loops(struct branch_entry *l, int nr) 1851static int remove_loops(struct branch_entry *l, int nr,
1852 struct iterations *iter)
1766{ 1853{
1767 int i, j, off; 1854 int i, j, off;
1768 unsigned char chash[CHASHSZ]; 1855 unsigned char chash[CHASHSZ];
@@ -1787,8 +1874,18 @@ static int remove_loops(struct branch_entry *l, int nr)
1787 break; 1874 break;
1788 } 1875 }
1789 if (is_loop) { 1876 if (is_loop) {
1790 memmove(l + i, l + i + off, 1877 j = nr - (i + off);
1791 (nr - (i + off)) * sizeof(*l)); 1878 if (j > 0) {
1879 save_iterations(iter + i + off,
1880 l + i, off);
1881
1882 memmove(iter + i, iter + i + off,
1883 j * sizeof(*iter));
1884
1885 memmove(l + i, l + i + off,
1886 j * sizeof(*l));
1887 }
1888
1792 nr -= off; 1889 nr -= off;
1793 } 1890 }
1794 } 1891 }
@@ -1813,7 +1910,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1813 struct ip_callchain *chain = sample->callchain; 1910 struct ip_callchain *chain = sample->callchain;
1814 int chain_nr = min(max_stack, (int)chain->nr), i; 1911 int chain_nr = min(max_stack, (int)chain->nr), i;
1815 u8 cpumode = PERF_RECORD_MISC_USER; 1912 u8 cpumode = PERF_RECORD_MISC_USER;
1816 u64 ip; 1913 u64 ip, branch_from = 0;
1817 1914
1818 for (i = 0; i < chain_nr; i++) { 1915 for (i = 0; i < chain_nr; i++) {
1819 if (chain->ips[i] == PERF_CONTEXT_USER) 1916 if (chain->ips[i] == PERF_CONTEXT_USER)
@@ -1855,6 +1952,8 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1855 ip = lbr_stack->entries[0].to; 1952 ip = lbr_stack->entries[0].to;
1856 branch = true; 1953 branch = true;
1857 flags = &lbr_stack->entries[0].flags; 1954 flags = &lbr_stack->entries[0].flags;
1955 branch_from =
1956 lbr_stack->entries[0].from;
1858 } 1957 }
1859 } else { 1958 } else {
1860 if (j < lbr_nr) { 1959 if (j < lbr_nr) {
@@ -1869,12 +1968,15 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1869 ip = lbr_stack->entries[0].to; 1968 ip = lbr_stack->entries[0].to;
1870 branch = true; 1969 branch = true;
1871 flags = &lbr_stack->entries[0].flags; 1970 flags = &lbr_stack->entries[0].flags;
1971 branch_from =
1972 lbr_stack->entries[0].from;
1872 } 1973 }
1873 } 1974 }
1874 1975
1875 err = add_callchain_ip(thread, cursor, parent, 1976 err = add_callchain_ip(thread, cursor, parent,
1876 root_al, &cpumode, ip, 1977 root_al, &cpumode, ip,
1877 branch, flags, 0, 0); 1978 branch, flags, NULL,
1979 branch_from);
1878 if (err) 1980 if (err)
1879 return (err < 0) ? err : 0; 1981 return (err < 0) ? err : 0;
1880 } 1982 }
@@ -1894,12 +1996,14 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1894{ 1996{
1895 struct branch_stack *branch = sample->branch_stack; 1997 struct branch_stack *branch = sample->branch_stack;
1896 struct ip_callchain *chain = sample->callchain; 1998 struct ip_callchain *chain = sample->callchain;
1897 int chain_nr = chain->nr; 1999 int chain_nr = 0;
1898 u8 cpumode = PERF_RECORD_MISC_USER; 2000 u8 cpumode = PERF_RECORD_MISC_USER;
1899 int i, j, err, nr_entries; 2001 int i, j, err, nr_entries;
1900 int skip_idx = -1; 2002 int skip_idx = -1;
1901 int first_call = 0; 2003 int first_call = 0;
1902 int nr_loop_iter; 2004
2005 if (chain)
2006 chain_nr = chain->nr;
1903 2007
1904 if (perf_evsel__has_branch_callstack(evsel)) { 2008 if (perf_evsel__has_branch_callstack(evsel)) {
1905 err = resolve_lbr_callchain_sample(thread, cursor, sample, parent, 2009 err = resolve_lbr_callchain_sample(thread, cursor, sample, parent,
@@ -1929,6 +2033,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1929 if (branch && callchain_param.branch_callstack) { 2033 if (branch && callchain_param.branch_callstack) {
1930 int nr = min(max_stack, (int)branch->nr); 2034 int nr = min(max_stack, (int)branch->nr);
1931 struct branch_entry be[nr]; 2035 struct branch_entry be[nr];
2036 struct iterations iter[nr];
1932 2037
1933 if (branch->nr > PERF_MAX_BRANCH_DEPTH) { 2038 if (branch->nr > PERF_MAX_BRANCH_DEPTH) {
1934 pr_warning("corrupted branch chain. skipping...\n"); 2039 pr_warning("corrupted branch chain. skipping...\n");
@@ -1938,6 +2043,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1938 for (i = 0; i < nr; i++) { 2043 for (i = 0; i < nr; i++) {
1939 if (callchain_param.order == ORDER_CALLEE) { 2044 if (callchain_param.order == ORDER_CALLEE) {
1940 be[i] = branch->entries[i]; 2045 be[i] = branch->entries[i];
2046
2047 if (chain == NULL)
2048 continue;
2049
1941 /* 2050 /*
1942 * Check for overlap into the callchain. 2051 * Check for overlap into the callchain.
1943 * The return address is one off compared to 2052 * The return address is one off compared to
@@ -1955,42 +2064,30 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1955 be[i] = branch->entries[branch->nr - i - 1]; 2064 be[i] = branch->entries[branch->nr - i - 1];
1956 } 2065 }
1957 2066
1958 nr_loop_iter = nr; 2067 memset(iter, 0, sizeof(struct iterations) * nr);
1959 nr = remove_loops(be, nr); 2068 nr = remove_loops(be, nr, iter);
1960
1961 /*
1962 * Get the number of iterations.
1963 * It's only approximation, but good enough in practice.
1964 */
1965 if (nr_loop_iter > nr)
1966 nr_loop_iter = nr_loop_iter - nr + 1;
1967 else
1968 nr_loop_iter = 0;
1969 2069
1970 for (i = 0; i < nr; i++) { 2070 for (i = 0; i < nr; i++) {
1971 if (i == nr - 1) 2071 err = add_callchain_ip(thread, cursor, parent,
1972 err = add_callchain_ip(thread, cursor, parent, 2072 root_al,
1973 root_al, 2073 NULL, be[i].to,
1974 NULL, be[i].to, 2074 true, &be[i].flags,
1975 true, &be[i].flags, 2075 NULL, be[i].from);
1976 nr_loop_iter, 1);
1977 else
1978 err = add_callchain_ip(thread, cursor, parent,
1979 root_al,
1980 NULL, be[i].to,
1981 true, &be[i].flags,
1982 0, 0);
1983 2076
1984 if (!err) 2077 if (!err)
1985 err = add_callchain_ip(thread, cursor, parent, root_al, 2078 err = add_callchain_ip(thread, cursor, parent, root_al,
1986 NULL, be[i].from, 2079 NULL, be[i].from,
1987 true, &be[i].flags, 2080 true, &be[i].flags,
1988 0, 0); 2081 &iter[i], 0);
1989 if (err == -EINVAL) 2082 if (err == -EINVAL)
1990 break; 2083 break;
1991 if (err) 2084 if (err)
1992 return err; 2085 return err;
1993 } 2086 }
2087
2088 if (chain_nr == 0)
2089 return 0;
2090
1994 chain_nr -= nr; 2091 chain_nr -= nr;
1995 } 2092 }
1996 2093
@@ -2015,7 +2112,7 @@ check_calls:
2015 2112
2016 err = add_callchain_ip(thread, cursor, parent, 2113 err = add_callchain_ip(thread, cursor, parent,
2017 root_al, &cpumode, ip, 2114 root_al, &cpumode, ip,
2018 false, NULL, 0, 0); 2115 false, NULL, NULL, 0);
2019 2116
2020 if (err) 2117 if (err)
2021 return (err < 0) ? err : 0; 2118 return (err < 0) ? err : 0;
@@ -2024,15 +2121,54 @@ check_calls:
2024 return 0; 2121 return 0;
2025} 2122}
2026 2123
2124static int append_inlines(struct callchain_cursor *cursor,
2125 struct map *map, struct symbol *sym, u64 ip)
2126{
2127 struct inline_node *inline_node;
2128 struct inline_list *ilist;
2129 u64 addr;
2130 int ret = 1;
2131
2132 if (!symbol_conf.inline_name || !map || !sym)
2133 return ret;
2134
2135 addr = map__rip_2objdump(map, ip);
2136
2137 inline_node = inlines__tree_find(&map->dso->inlined_nodes, addr);
2138 if (!inline_node) {
2139 inline_node = dso__parse_addr_inlines(map->dso, addr, sym);
2140 if (!inline_node)
2141 return ret;
2142 inlines__tree_insert(&map->dso->inlined_nodes, inline_node);
2143 }
2144
2145 list_for_each_entry(ilist, &inline_node->val, list) {
2146 ret = callchain_cursor_append(cursor, ip, map,
2147 ilist->symbol, false,
2148 NULL, 0, 0, 0, ilist->srcline);
2149
2150 if (ret != 0)
2151 return ret;
2152 }
2153
2154 return ret;
2155}
2156
2027static int unwind_entry(struct unwind_entry *entry, void *arg) 2157static int unwind_entry(struct unwind_entry *entry, void *arg)
2028{ 2158{
2029 struct callchain_cursor *cursor = arg; 2159 struct callchain_cursor *cursor = arg;
2160 const char *srcline = NULL;
2030 2161
2031 if (symbol_conf.hide_unresolved && entry->sym == NULL) 2162 if (symbol_conf.hide_unresolved && entry->sym == NULL)
2032 return 0; 2163 return 0;
2164
2165 if (append_inlines(cursor, entry->map, entry->sym, entry->ip) == 0)
2166 return 0;
2167
2168 srcline = callchain_srcline(entry->map, entry->sym, entry->ip);
2033 return callchain_cursor_append(cursor, entry->ip, 2169 return callchain_cursor_append(cursor, entry->ip,
2034 entry->map, entry->sym, 2170 entry->map, entry->sym,
2035 false, NULL, 0, 0); 2171 false, NULL, 0, 0, 0, srcline);
2036} 2172}
2037 2173
2038static int thread__resolve_callchain_unwind(struct thread *thread, 2174static int thread__resolve_callchain_unwind(struct thread *thread,
@@ -2096,21 +2232,26 @@ int machine__for_each_thread(struct machine *machine,
2096 int (*fn)(struct thread *thread, void *p), 2232 int (*fn)(struct thread *thread, void *p),
2097 void *priv) 2233 void *priv)
2098{ 2234{
2235 struct threads *threads;
2099 struct rb_node *nd; 2236 struct rb_node *nd;
2100 struct thread *thread; 2237 struct thread *thread;
2101 int rc = 0; 2238 int rc = 0;
2239 int i;
2102 2240
2103 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) { 2241 for (i = 0; i < THREADS__TABLE_SIZE; i++) {
2104 thread = rb_entry(nd, struct thread, rb_node); 2242 threads = &machine->threads[i];
2105 rc = fn(thread, priv); 2243 for (nd = rb_first(&threads->entries); nd; nd = rb_next(nd)) {
2106 if (rc != 0) 2244 thread = rb_entry(nd, struct thread, rb_node);
2107 return rc; 2245 rc = fn(thread, priv);
2108 } 2246 if (rc != 0)
2247 return rc;
2248 }
2109 2249
2110 list_for_each_entry(thread, &machine->dead_threads, node) { 2250 list_for_each_entry(thread, &threads->dead, node) {
2111 rc = fn(thread, priv); 2251 rc = fn(thread, priv);
2112 if (rc != 0) 2252 if (rc != 0)
2113 return rc; 2253 return rc;
2254 }
2114 } 2255 }
2115 return rc; 2256 return rc;
2116} 2257}
@@ -2139,12 +2280,16 @@ int machines__for_each_thread(struct machines *machines,
2139int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, 2280int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
2140 struct target *target, struct thread_map *threads, 2281 struct target *target, struct thread_map *threads,
2141 perf_event__handler_t process, bool data_mmap, 2282 perf_event__handler_t process, bool data_mmap,
2142 unsigned int proc_map_timeout) 2283 unsigned int proc_map_timeout,
2284 unsigned int nr_threads_synthesize)
2143{ 2285{
2144 if (target__has_task(target)) 2286 if (target__has_task(target))
2145 return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap, proc_map_timeout); 2287 return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap, proc_map_timeout);
2146 else if (target__has_cpu(target)) 2288 else if (target__has_cpu(target))
2147 return perf_event__synthesize_threads(tool, process, machine, data_mmap, proc_map_timeout); 2289 return perf_event__synthesize_threads(tool, process,
2290 machine, data_mmap,
2291 proc_map_timeout,
2292 nr_threads_synthesize);
2148 /* command specified */ 2293 /* command specified */
2149 return 0; 2294 return 0;
2150} 2295}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 3cdb1340f917..5ce860b64c74 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_MACHINE_H 2#ifndef __PERF_MACHINE_H
2#define __PERF_MACHINE_H 3#define __PERF_MACHINE_H
3 4
@@ -6,6 +7,7 @@
6#include "map.h" 7#include "map.h"
7#include "dso.h" 8#include "dso.h"
8#include "event.h" 9#include "event.h"
10#include "rwsem.h"
9 11
10struct addr_location; 12struct addr_location;
11struct branch_stack; 13struct branch_stack;
@@ -23,6 +25,17 @@ extern const char *ref_reloc_sym_names[];
23 25
24struct vdso_info; 26struct vdso_info;
25 27
28#define THREADS__TABLE_BITS 8
29#define THREADS__TABLE_SIZE (1 << THREADS__TABLE_BITS)
30
31struct threads {
32 struct rb_root entries;
33 struct rw_semaphore lock;
34 unsigned int nr;
35 struct list_head dead;
36 struct thread *last_match;
37};
38
26struct machine { 39struct machine {
27 struct rb_node rb_node; 40 struct rb_node rb_node;
28 pid_t pid; 41 pid_t pid;
@@ -30,11 +43,7 @@ struct machine {
30 bool comm_exec; 43 bool comm_exec;
31 bool kptr_restrict_warned; 44 bool kptr_restrict_warned;
32 char *root_dir; 45 char *root_dir;
33 struct rb_root threads; 46 struct threads threads[THREADS__TABLE_SIZE];
34 pthread_rwlock_t threads_lock;
35 unsigned int nr_threads;
36 struct list_head dead_threads;
37 struct thread *last_match;
38 struct vdso_info *vdso_info; 47 struct vdso_info *vdso_info;
39 struct perf_env *env; 48 struct perf_env *env;
40 struct dsos dsos; 49 struct dsos dsos;
@@ -48,6 +57,12 @@ struct machine {
48 }; 57 };
49}; 58};
50 59
60static inline struct threads *machine__threads(struct machine *machine, pid_t tid)
61{
62 /* Cast it to handle tid == -1 */
63 return &machine->threads[(unsigned int)tid % THREADS__TABLE_SIZE];
64}
65
51static inline 66static inline
52struct map *__machine__kernel_map(struct machine *machine, enum map_type type) 67struct map *__machine__kernel_map(struct machine *machine, enum map_type type)
53{ 68{
@@ -243,15 +258,18 @@ int machines__for_each_thread(struct machines *machines,
243int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, 258int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
244 struct target *target, struct thread_map *threads, 259 struct target *target, struct thread_map *threads,
245 perf_event__handler_t process, bool data_mmap, 260 perf_event__handler_t process, bool data_mmap,
246 unsigned int proc_map_timeout); 261 unsigned int proc_map_timeout,
262 unsigned int nr_threads_synthesize);
247static inline 263static inline
248int machine__synthesize_threads(struct machine *machine, struct target *target, 264int machine__synthesize_threads(struct machine *machine, struct target *target,
249 struct thread_map *threads, bool data_mmap, 265 struct thread_map *threads, bool data_mmap,
250 unsigned int proc_map_timeout) 266 unsigned int proc_map_timeout,
267 unsigned int nr_threads_synthesize)
251{ 268{
252 return __machine__synthesize_threads(machine, NULL, target, threads, 269 return __machine__synthesize_threads(machine, NULL, target, threads,
253 perf_event__process, data_mmap, 270 perf_event__process, data_mmap,
254 proc_map_timeout); 271 proc_map_timeout,
272 nr_threads_synthesize);
255} 273}
256 274
257pid_t machine__get_current_tid(struct machine *machine, int cpu); 275pid_t machine__get_current_tid(struct machine *machine, int cpu);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 2179b2deb730..6d40efd74402 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "symbol.h" 2#include "symbol.h"
2#include <errno.h> 3#include <errno.h>
3#include <inttypes.h> 4#include <inttypes.h>
@@ -16,6 +17,7 @@
16#include "machine.h" 17#include "machine.h"
17#include <linux/string.h> 18#include <linux/string.h>
18#include "srcline.h" 19#include "srcline.h"
20#include "namespaces.h"
19#include "unwind.h" 21#include "unwind.h"
20 22
21static void __maps__insert(struct maps *maps, struct map *map); 23static void __maps__insert(struct maps *maps, struct map *map);
@@ -145,11 +147,13 @@ void map__init(struct map *map, enum map_type type,
145} 147}
146 148
147struct map *map__new(struct machine *machine, u64 start, u64 len, 149struct map *map__new(struct machine *machine, u64 start, u64 len,
148 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, 150 u64 pgoff, u32 d_maj, u32 d_min, u64 ino,
149 u64 ino_gen, u32 prot, u32 flags, char *filename, 151 u64 ino_gen, u32 prot, u32 flags, char *filename,
150 enum map_type type, struct thread *thread) 152 enum map_type type, struct thread *thread)
151{ 153{
152 struct map *map = malloc(sizeof(*map)); 154 struct map *map = malloc(sizeof(*map));
155 struct nsinfo *nsi = NULL;
156 struct nsinfo *nnsi;
153 157
154 if (map != NULL) { 158 if (map != NULL) {
155 char newfilename[PATH_MAX]; 159 char newfilename[PATH_MAX];
@@ -167,9 +171,11 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
167 map->ino_generation = ino_gen; 171 map->ino_generation = ino_gen;
168 map->prot = prot; 172 map->prot = prot;
169 map->flags = flags; 173 map->flags = flags;
174 nsi = nsinfo__get(thread->nsinfo);
170 175
171 if ((anon || no_dso) && type == MAP__FUNCTION) { 176 if ((anon || no_dso) && nsi && type == MAP__FUNCTION) {
172 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); 177 snprintf(newfilename, sizeof(newfilename),
178 "/tmp/perf-%d.map", nsi->pid);
173 filename = newfilename; 179 filename = newfilename;
174 } 180 }
175 181
@@ -179,6 +185,16 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
179 } 185 }
180 186
181 if (vdso) { 187 if (vdso) {
188 /* The vdso maps are always on the host and not the
189 * container. Ensure that we don't use setns to look
190 * them up.
191 */
192 nnsi = nsinfo__copy(nsi);
193 if (nnsi) {
194 nsinfo__put(nsi);
195 nnsi->need_setns = false;
196 nsi = nnsi;
197 }
182 pgoff = 0; 198 pgoff = 0;
183 dso = machine__findnew_vdso(machine, thread); 199 dso = machine__findnew_vdso(machine, thread);
184 } else 200 } else
@@ -200,10 +216,12 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
200 if (type != MAP__FUNCTION) 216 if (type != MAP__FUNCTION)
201 dso__set_loaded(dso, map->type); 217 dso__set_loaded(dso, map->type);
202 } 218 }
219 dso->nsinfo = nsi;
203 dso__put(dso); 220 dso__put(dso);
204 } 221 }
205 return map; 222 return map;
206out_delete: 223out_delete:
224 nsinfo__put(nsi);
207 free(map); 225 free(map);
208 return NULL; 226 return NULL;
209} 227}
@@ -471,7 +489,7 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
471static void maps__init(struct maps *maps) 489static void maps__init(struct maps *maps)
472{ 490{
473 maps->entries = RB_ROOT; 491 maps->entries = RB_ROOT;
474 pthread_rwlock_init(&maps->lock, NULL); 492 init_rwsem(&maps->lock);
475} 493}
476 494
477void map_groups__init(struct map_groups *mg, struct machine *machine) 495void map_groups__init(struct map_groups *mg, struct machine *machine)
@@ -500,9 +518,9 @@ static void __maps__purge(struct maps *maps)
500 518
501static void maps__exit(struct maps *maps) 519static void maps__exit(struct maps *maps)
502{ 520{
503 pthread_rwlock_wrlock(&maps->lock); 521 down_write(&maps->lock);
504 __maps__purge(maps); 522 __maps__purge(maps);
505 pthread_rwlock_unlock(&maps->lock); 523 up_write(&maps->lock);
506} 524}
507 525
508void map_groups__exit(struct map_groups *mg) 526void map_groups__exit(struct map_groups *mg)
@@ -569,7 +587,7 @@ struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
569 struct symbol *sym; 587 struct symbol *sym;
570 struct rb_node *nd; 588 struct rb_node *nd;
571 589
572 pthread_rwlock_rdlock(&maps->lock); 590 down_read(&maps->lock);
573 591
574 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) { 592 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) {
575 struct map *pos = rb_entry(nd, struct map, rb_node); 593 struct map *pos = rb_entry(nd, struct map, rb_node);
@@ -585,7 +603,7 @@ struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
585 603
586 sym = NULL; 604 sym = NULL;
587out: 605out:
588 pthread_rwlock_unlock(&maps->lock); 606 up_read(&maps->lock);
589 return sym; 607 return sym;
590} 608}
591 609
@@ -621,7 +639,7 @@ static size_t maps__fprintf(struct maps *maps, FILE *fp)
621 size_t printed = 0; 639 size_t printed = 0;
622 struct rb_node *nd; 640 struct rb_node *nd;
623 641
624 pthread_rwlock_rdlock(&maps->lock); 642 down_read(&maps->lock);
625 643
626 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) { 644 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) {
627 struct map *pos = rb_entry(nd, struct map, rb_node); 645 struct map *pos = rb_entry(nd, struct map, rb_node);
@@ -633,7 +651,7 @@ static size_t maps__fprintf(struct maps *maps, FILE *fp)
633 } 651 }
634 } 652 }
635 653
636 pthread_rwlock_unlock(&maps->lock); 654 up_read(&maps->lock);
637 655
638 return printed; 656 return printed;
639} 657}
@@ -665,7 +683,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
665 struct rb_node *next; 683 struct rb_node *next;
666 int err = 0; 684 int err = 0;
667 685
668 pthread_rwlock_wrlock(&maps->lock); 686 down_write(&maps->lock);
669 687
670 root = &maps->entries; 688 root = &maps->entries;
671 next = rb_first(root); 689 next = rb_first(root);
@@ -733,7 +751,7 @@ put_map:
733 751
734 err = 0; 752 err = 0;
735out: 753out:
736 pthread_rwlock_unlock(&maps->lock); 754 up_write(&maps->lock);
737 return err; 755 return err;
738} 756}
739 757
@@ -754,7 +772,7 @@ int map_groups__clone(struct thread *thread,
754 struct map *map; 772 struct map *map;
755 struct maps *maps = &parent->maps[type]; 773 struct maps *maps = &parent->maps[type];
756 774
757 pthread_rwlock_rdlock(&maps->lock); 775 down_read(&maps->lock);
758 776
759 for (map = maps__first(maps); map; map = map__next(map)) { 777 for (map = maps__first(maps); map; map = map__next(map)) {
760 struct map *new = map__clone(map); 778 struct map *new = map__clone(map);
@@ -771,7 +789,7 @@ int map_groups__clone(struct thread *thread,
771 789
772 err = 0; 790 err = 0;
773out_unlock: 791out_unlock:
774 pthread_rwlock_unlock(&maps->lock); 792 up_read(&maps->lock);
775 return err; 793 return err;
776} 794}
777 795
@@ -798,9 +816,9 @@ static void __maps__insert(struct maps *maps, struct map *map)
798 816
799void maps__insert(struct maps *maps, struct map *map) 817void maps__insert(struct maps *maps, struct map *map)
800{ 818{
801 pthread_rwlock_wrlock(&maps->lock); 819 down_write(&maps->lock);
802 __maps__insert(maps, map); 820 __maps__insert(maps, map);
803 pthread_rwlock_unlock(&maps->lock); 821 up_write(&maps->lock);
804} 822}
805 823
806static void __maps__remove(struct maps *maps, struct map *map) 824static void __maps__remove(struct maps *maps, struct map *map)
@@ -811,9 +829,9 @@ static void __maps__remove(struct maps *maps, struct map *map)
811 829
812void maps__remove(struct maps *maps, struct map *map) 830void maps__remove(struct maps *maps, struct map *map)
813{ 831{
814 pthread_rwlock_wrlock(&maps->lock); 832 down_write(&maps->lock);
815 __maps__remove(maps, map); 833 __maps__remove(maps, map);
816 pthread_rwlock_unlock(&maps->lock); 834 up_write(&maps->lock);
817} 835}
818 836
819struct map *maps__find(struct maps *maps, u64 ip) 837struct map *maps__find(struct maps *maps, u64 ip)
@@ -821,7 +839,7 @@ struct map *maps__find(struct maps *maps, u64 ip)
821 struct rb_node **p, *parent = NULL; 839 struct rb_node **p, *parent = NULL;
822 struct map *m; 840 struct map *m;
823 841
824 pthread_rwlock_rdlock(&maps->lock); 842 down_read(&maps->lock);
825 843
826 p = &maps->entries.rb_node; 844 p = &maps->entries.rb_node;
827 while (*p != NULL) { 845 while (*p != NULL) {
@@ -837,7 +855,7 @@ struct map *maps__find(struct maps *maps, u64 ip)
837 855
838 m = NULL; 856 m = NULL;
839out: 857out:
840 pthread_rwlock_unlock(&maps->lock); 858 up_read(&maps->lock);
841 return m; 859 return m;
842} 860}
843 861
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index f9e8ac8a52cd..edeb7291c8e1 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_MAP_H 2#ifndef __PERF_MAP_H
2#define __PERF_MAP_H 3#define __PERF_MAP_H
3 4
@@ -9,6 +10,7 @@
9#include <stdio.h> 10#include <stdio.h>
10#include <stdbool.h> 11#include <stdbool.h>
11#include <linux/types.h> 12#include <linux/types.h>
13#include "rwsem.h"
12 14
13enum map_type { 15enum map_type {
14 MAP__FUNCTION = 0, 16 MAP__FUNCTION = 0,
@@ -61,7 +63,7 @@ struct kmap {
61 63
62struct maps { 64struct maps {
63 struct rb_root entries; 65 struct rb_root entries;
64 pthread_rwlock_t lock; 66 struct rw_semaphore lock;
65}; 67};
66 68
67struct map_groups { 69struct map_groups {
@@ -141,7 +143,7 @@ struct thread;
141void map__init(struct map *map, enum map_type type, 143void map__init(struct map *map, enum map_type type,
142 u64 start, u64 end, u64 pgoff, struct dso *dso); 144 u64 start, u64 end, u64 pgoff, struct dso *dso);
143struct map *map__new(struct machine *machine, u64 start, u64 len, 145struct map *map__new(struct machine *machine, u64 start, u64 len,
144 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, 146 u64 pgoff, u32 d_maj, u32 d_min, u64 ino,
145 u64 ino_gen, u32 prot, u32 flags, 147 u64 ino_gen, u32 prot, u32 flags,
146 char *filename, enum map_type type, struct thread *thread); 148 char *filename, enum map_type type, struct thread *thread);
147struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 149struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c
index 06f5a3a4295c..93f74d8d3cdd 100644
--- a/tools/perf/util/mem-events.c
+++ b/tools/perf/util/mem-events.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stddef.h> 2#include <stddef.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <string.h> 4#include <string.h>
@@ -166,11 +167,20 @@ static const char * const mem_lvl[] = {
166 "Uncached", 167 "Uncached",
167}; 168};
168 169
170static const char * const mem_lvlnum[] = {
171 [PERF_MEM_LVLNUM_ANY_CACHE] = "Any cache",
172 [PERF_MEM_LVLNUM_LFB] = "LFB",
173 [PERF_MEM_LVLNUM_RAM] = "RAM",
174 [PERF_MEM_LVLNUM_PMEM] = "PMEM",
175 [PERF_MEM_LVLNUM_NA] = "N/A",
176};
177
169int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info) 178int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
170{ 179{
171 size_t i, l = 0; 180 size_t i, l = 0;
172 u64 m = PERF_MEM_LVL_NA; 181 u64 m = PERF_MEM_LVL_NA;
173 u64 hit, miss; 182 u64 hit, miss;
183 int printed;
174 184
175 if (mem_info) 185 if (mem_info)
176 m = mem_info->data_src.mem_lvl; 186 m = mem_info->data_src.mem_lvl;
@@ -184,17 +194,37 @@ int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
184 /* already taken care of */ 194 /* already taken care of */
185 m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS); 195 m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
186 196
197
198 if (mem_info && mem_info->data_src.mem_remote) {
199 strcat(out, "Remote ");
200 l += 7;
201 }
202
203 printed = 0;
187 for (i = 0; m && i < ARRAY_SIZE(mem_lvl); i++, m >>= 1) { 204 for (i = 0; m && i < ARRAY_SIZE(mem_lvl); i++, m >>= 1) {
188 if (!(m & 0x1)) 205 if (!(m & 0x1))
189 continue; 206 continue;
190 if (l) { 207 if (printed++) {
191 strcat(out, " or "); 208 strcat(out, " or ");
192 l += 4; 209 l += 4;
193 } 210 }
194 l += scnprintf(out + l, sz - l, mem_lvl[i]); 211 l += scnprintf(out + l, sz - l, mem_lvl[i]);
195 } 212 }
196 if (*out == '\0') 213
197 l += scnprintf(out, sz - l, "N/A"); 214 if (mem_info && mem_info->data_src.mem_lvl_num) {
215 int lvl = mem_info->data_src.mem_lvl_num;
216 if (printed++) {
217 strcat(out, " or ");
218 l += 4;
219 }
220 if (mem_lvlnum[lvl])
221 l += scnprintf(out + l, sz - l, mem_lvlnum[lvl]);
222 else
223 l += scnprintf(out + l, sz - l, "L%d", lvl);
224 }
225
226 if (l == 0)
227 l += scnprintf(out + l, sz - l, "N/A");
198 if (hit) 228 if (hit)
199 l += scnprintf(out + l, sz - l, " hit"); 229 l += scnprintf(out + l, sz - l, " hit");
200 if (miss) 230 if (miss)
@@ -231,6 +261,14 @@ int perf_mem__snp_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
231 } 261 }
232 l += scnprintf(out + l, sz - l, snoop_access[i]); 262 l += scnprintf(out + l, sz - l, snoop_access[i]);
233 } 263 }
264 if (mem_info &&
265 (mem_info->data_src.mem_snoopx & PERF_MEM_SNOOPX_FWD)) {
266 if (l) {
267 strcat(out, " or ");
268 l += 4;
269 }
270 l += scnprintf(out + l, sz - l, "Fwd");
271 }
234 272
235 if (*out == '\0') 273 if (*out == '\0')
236 l += scnprintf(out, sz - l, "N/A"); 274 l += scnprintf(out, sz - l, "N/A");
@@ -279,6 +317,11 @@ int c2c_decode_stats(struct c2c_stats *stats, struct mem_info *mi)
279 u64 lvl = data_src->mem_lvl; 317 u64 lvl = data_src->mem_lvl;
280 u64 snoop = data_src->mem_snoop; 318 u64 snoop = data_src->mem_snoop;
281 u64 lock = data_src->mem_lock; 319 u64 lock = data_src->mem_lock;
320 /*
321 * Skylake might report unknown remote level via this
322 * bit, consider it when evaluating remote HITMs.
323 */
324 bool mrem = data_src->mem_remote;
282 int err = 0; 325 int err = 0;
283 326
284#define HITM_INC(__f) \ 327#define HITM_INC(__f) \
@@ -324,7 +367,8 @@ do { \
324 } 367 }
325 368
326 if ((lvl & P(LVL, REM_RAM1)) || 369 if ((lvl & P(LVL, REM_RAM1)) ||
327 (lvl & P(LVL, REM_RAM2))) { 370 (lvl & P(LVL, REM_RAM2)) ||
371 mrem) {
328 stats->rmt_dram++; 372 stats->rmt_dram++;
329 if (snoop & P(SNOOP, HIT)) 373 if (snoop & P(SNOOP, HIT))
330 stats->ld_shared++; 374 stats->ld_shared++;
@@ -334,7 +378,8 @@ do { \
334 } 378 }
335 379
336 if ((lvl & P(LVL, REM_CCE1)) || 380 if ((lvl & P(LVL, REM_CCE1)) ||
337 (lvl & P(LVL, REM_CCE2))) { 381 (lvl & P(LVL, REM_CCE2)) ||
382 mrem) {
338 if (snoop & P(SNOOP, HIT)) 383 if (snoop & P(SNOOP, HIT))
339 stats->rmt_hit++; 384 stats->rmt_hit++;
340 else if (snoop & P(SNOOP, HITM)) 385 else if (snoop & P(SNOOP, HITM))
diff --git a/tools/perf/util/mem-events.h b/tools/perf/util/mem-events.h
index 40f72ee4f42a..a889ec2fa9f5 100644
--- a/tools/perf/util/mem-events.h
+++ b/tools/perf/util/mem-events.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_MEM_EVENTS_H 2#ifndef __PERF_MEM_EVENTS_H
2#define __PERF_MEM_EVENTS_H 3#define __PERF_MEM_EVENTS_H
3 4
diff --git a/tools/perf/util/memswap.c b/tools/perf/util/memswap.c
index 55f7faa8d9ec..c1317e4983bc 100644
--- a/tools/perf/util/memswap.c
+++ b/tools/perf/util/memswap.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <byteswap.h> 2#include <byteswap.h>
2#include "memswap.h" 3#include "memswap.h"
3#include <linux/types.h> 4#include <linux/types.h>
diff --git a/tools/perf/util/memswap.h b/tools/perf/util/memswap.h
index 7d1b1c34bb57..1e29ff903ca9 100644
--- a/tools/perf/util/memswap.h
+++ b/tools/perf/util/memswap.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PERF_MEMSWAP_H_ 2#ifndef PERF_MEMSWAP_H_
2#define PERF_MEMSWAP_H_ 3#define PERF_MEMSWAP_H_
3 4
diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c
new file mode 100644
index 000000000000..0ddd9c199227
--- /dev/null
+++ b/tools/perf/util/metricgroup.c
@@ -0,0 +1,490 @@
1/*
2 * Copyright (c) 2017, 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 */
14
15/* Manage metrics and groups of metrics from JSON files */
16
17#include "metricgroup.h"
18#include "evlist.h"
19#include "strbuf.h"
20#include "pmu.h"
21#include "expr.h"
22#include "rblist.h"
23#include "pmu.h"
24#include <string.h>
25#include <stdbool.h>
26#include <errno.h>
27#include "pmu-events/pmu-events.h"
28#include "strbuf.h"
29#include "strlist.h"
30#include <assert.h>
31#include <ctype.h>
32
33struct metric_event *metricgroup__lookup(struct rblist *metric_events,
34 struct perf_evsel *evsel,
35 bool create)
36{
37 struct rb_node *nd;
38 struct metric_event me = {
39 .evsel = evsel
40 };
41 nd = rblist__find(metric_events, &me);
42 if (nd)
43 return container_of(nd, struct metric_event, nd);
44 if (create) {
45 rblist__add_node(metric_events, &me);
46 nd = rblist__find(metric_events, &me);
47 if (nd)
48 return container_of(nd, struct metric_event, nd);
49 }
50 return NULL;
51}
52
53static int metric_event_cmp(struct rb_node *rb_node, const void *entry)
54{
55 struct metric_event *a = container_of(rb_node,
56 struct metric_event,
57 nd);
58 const struct metric_event *b = entry;
59
60 if (a->evsel == b->evsel)
61 return 0;
62 if ((char *)a->evsel < (char *)b->evsel)
63 return -1;
64 return +1;
65}
66
67static struct rb_node *metric_event_new(struct rblist *rblist __maybe_unused,
68 const void *entry)
69{
70 struct metric_event *me = malloc(sizeof(struct metric_event));
71
72 if (!me)
73 return NULL;
74 memcpy(me, entry, sizeof(struct metric_event));
75 me->evsel = ((struct metric_event *)entry)->evsel;
76 INIT_LIST_HEAD(&me->head);
77 return &me->nd;
78}
79
80static void metricgroup__rblist_init(struct rblist *metric_events)
81{
82 rblist__init(metric_events);
83 metric_events->node_cmp = metric_event_cmp;
84 metric_events->node_new = metric_event_new;
85}
86
87struct egroup {
88 struct list_head nd;
89 int idnum;
90 const char **ids;
91 const char *metric_name;
92 const char *metric_expr;
93};
94
95static struct perf_evsel *find_evsel(struct perf_evlist *perf_evlist,
96 const char **ids,
97 int idnum,
98 struct perf_evsel **metric_events)
99{
100 struct perf_evsel *ev, *start = NULL;
101 int ind = 0;
102
103 evlist__for_each_entry (perf_evlist, ev) {
104 if (!strcmp(ev->name, ids[ind])) {
105 metric_events[ind] = ev;
106 if (ind == 0)
107 start = ev;
108 if (++ind == idnum) {
109 metric_events[ind] = NULL;
110 return start;
111 }
112 } else {
113 ind = 0;
114 start = NULL;
115 }
116 }
117 /*
118 * This can happen when an alias expands to multiple
119 * events, like for uncore events.
120 * We don't support this case for now.
121 */
122 return NULL;
123}
124
125static int metricgroup__setup_events(struct list_head *groups,
126 struct perf_evlist *perf_evlist,
127 struct rblist *metric_events_list)
128{
129 struct metric_event *me;
130 struct metric_expr *expr;
131 int i = 0;
132 int ret = 0;
133 struct egroup *eg;
134 struct perf_evsel *evsel;
135
136 list_for_each_entry (eg, groups, nd) {
137 struct perf_evsel **metric_events;
138
139 metric_events = calloc(sizeof(void *), eg->idnum + 1);
140 if (!metric_events) {
141 ret = -ENOMEM;
142 break;
143 }
144 evsel = find_evsel(perf_evlist, eg->ids, eg->idnum,
145 metric_events);
146 if (!evsel) {
147 pr_debug("Cannot resolve %s: %s\n",
148 eg->metric_name, eg->metric_expr);
149 continue;
150 }
151 for (i = 0; i < eg->idnum; i++)
152 metric_events[i]->collect_stat = true;
153 me = metricgroup__lookup(metric_events_list, evsel, true);
154 if (!me) {
155 ret = -ENOMEM;
156 break;
157 }
158 expr = malloc(sizeof(struct metric_expr));
159 if (!expr) {
160 ret = -ENOMEM;
161 break;
162 }
163 expr->metric_expr = eg->metric_expr;
164 expr->metric_name = eg->metric_name;
165 expr->metric_events = metric_events;
166 list_add(&expr->nd, &me->head);
167 }
168 return ret;
169}
170
171static bool match_metric(const char *n, const char *list)
172{
173 int len;
174 char *m;
175
176 if (!list)
177 return false;
178 if (!strcmp(list, "all"))
179 return true;
180 if (!n)
181 return !strcasecmp(list, "No_group");
182 len = strlen(list);
183 m = strcasestr(n, list);
184 if (!m)
185 return false;
186 if ((m == n || m[-1] == ';' || m[-1] == ' ') &&
187 (m[len] == 0 || m[len] == ';'))
188 return true;
189 return false;
190}
191
192struct mep {
193 struct rb_node nd;
194 const char *name;
195 struct strlist *metrics;
196};
197
198static int mep_cmp(struct rb_node *rb_node, const void *entry)
199{
200 struct mep *a = container_of(rb_node, struct mep, nd);
201 struct mep *b = (struct mep *)entry;
202
203 return strcmp(a->name, b->name);
204}
205
206static struct rb_node *mep_new(struct rblist *rl __maybe_unused,
207 const void *entry)
208{
209 struct mep *me = malloc(sizeof(struct mep));
210
211 if (!me)
212 return NULL;
213 memcpy(me, entry, sizeof(struct mep));
214 me->name = strdup(me->name);
215 if (!me->name)
216 goto out_me;
217 me->metrics = strlist__new(NULL, NULL);
218 if (!me->metrics)
219 goto out_name;
220 return &me->nd;
221out_name:
222 free((char *)me->name);
223out_me:
224 free(me);
225 return NULL;
226}
227
228static struct mep *mep_lookup(struct rblist *groups, const char *name)
229{
230 struct rb_node *nd;
231 struct mep me = {
232 .name = name
233 };
234 nd = rblist__find(groups, &me);
235 if (nd)
236 return container_of(nd, struct mep, nd);
237 rblist__add_node(groups, &me);
238 nd = rblist__find(groups, &me);
239 if (nd)
240 return container_of(nd, struct mep, nd);
241 return NULL;
242}
243
244static void mep_delete(struct rblist *rl __maybe_unused,
245 struct rb_node *nd)
246{
247 struct mep *me = container_of(nd, struct mep, nd);
248
249 strlist__delete(me->metrics);
250 free((void *)me->name);
251 free(me);
252}
253
254static void metricgroup__print_strlist(struct strlist *metrics, bool raw)
255{
256 struct str_node *sn;
257 int n = 0;
258
259 strlist__for_each_entry (sn, metrics) {
260 if (raw)
261 printf("%s%s", n > 0 ? " " : "", sn->s);
262 else
263 printf(" %s\n", sn->s);
264 n++;
265 }
266 if (raw)
267 putchar('\n');
268}
269
270void metricgroup__print(bool metrics, bool metricgroups, char *filter,
271 bool raw)
272{
273 struct pmu_events_map *map = perf_pmu__find_map();
274 struct pmu_event *pe;
275 int i;
276 struct rblist groups;
277 struct rb_node *node, *next;
278 struct strlist *metriclist = NULL;
279
280 if (!map)
281 return;
282
283 if (!metricgroups) {
284 metriclist = strlist__new(NULL, NULL);
285 if (!metriclist)
286 return;
287 }
288
289 rblist__init(&groups);
290 groups.node_new = mep_new;
291 groups.node_cmp = mep_cmp;
292 groups.node_delete = mep_delete;
293 for (i = 0; ; i++) {
294 const char *g;
295 pe = &map->table[i];
296
297 if (!pe->name && !pe->metric_group && !pe->metric_name)
298 break;
299 if (!pe->metric_expr)
300 continue;
301 g = pe->metric_group;
302 if (!g && pe->metric_name) {
303 if (pe->name)
304 continue;
305 g = "No_group";
306 }
307 if (g) {
308 char *omg;
309 char *mg = strdup(g);
310
311 if (!mg)
312 return;
313 omg = mg;
314 while ((g = strsep(&mg, ";")) != NULL) {
315 struct mep *me;
316 char *s;
317
318 if (*g == 0)
319 g = "No_group";
320 while (isspace(*g))
321 g++;
322 if (filter && !strstr(g, filter))
323 continue;
324 if (raw)
325 s = (char *)pe->metric_name;
326 else {
327 if (asprintf(&s, "%s\n\t[%s]",
328 pe->metric_name, pe->desc) < 0)
329 return;
330 }
331
332 if (!s)
333 continue;
334
335 if (!metricgroups) {
336 strlist__add(metriclist, s);
337 } else {
338 me = mep_lookup(&groups, g);
339 if (!me)
340 continue;
341 strlist__add(me->metrics, s);
342 }
343 }
344 free(omg);
345 }
346 }
347
348 if (metricgroups && !raw)
349 printf("\nMetric Groups:\n\n");
350 else if (metrics && !raw)
351 printf("\nMetrics:\n\n");
352
353 for (node = rb_first(&groups.entries); node; node = next) {
354 struct mep *me = container_of(node, struct mep, nd);
355
356 if (metricgroups)
357 printf("%s%s%s", me->name, metrics ? ":" : "", raw ? " " : "\n");
358 if (metrics)
359 metricgroup__print_strlist(me->metrics, raw);
360 next = rb_next(node);
361 rblist__remove_node(&groups, node);
362 }
363 if (!metricgroups)
364 metricgroup__print_strlist(metriclist, raw);
365 strlist__delete(metriclist);
366}
367
368static int metricgroup__add_metric(const char *metric, struct strbuf *events,
369 struct list_head *group_list)
370{
371 struct pmu_events_map *map = perf_pmu__find_map();
372 struct pmu_event *pe;
373 int ret = -EINVAL;
374 int i, j;
375
376 if (!map)
377 return 0;
378
379 for (i = 0; ; i++) {
380 pe = &map->table[i];
381
382 if (!pe->name && !pe->metric_group && !pe->metric_name)
383 break;
384 if (!pe->metric_expr)
385 continue;
386 if (match_metric(pe->metric_group, metric) ||
387 match_metric(pe->metric_name, metric)) {
388 const char **ids;
389 int idnum;
390 struct egroup *eg;
391
392 pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name);
393
394 if (expr__find_other(pe->metric_expr,
395 NULL, &ids, &idnum) < 0)
396 continue;
397 if (events->len > 0)
398 strbuf_addf(events, ",");
399 for (j = 0; j < idnum; j++) {
400 pr_debug("found event %s\n", ids[j]);
401 strbuf_addf(events, "%s%s",
402 j == 0 ? "{" : ",",
403 ids[j]);
404 }
405 strbuf_addf(events, "}:W");
406
407 eg = malloc(sizeof(struct egroup));
408 if (!eg) {
409 ret = -ENOMEM;
410 break;
411 }
412 eg->ids = ids;
413 eg->idnum = idnum;
414 eg->metric_name = pe->metric_name;
415 eg->metric_expr = pe->metric_expr;
416 list_add_tail(&eg->nd, group_list);
417 ret = 0;
418 }
419 }
420 return ret;
421}
422
423static int metricgroup__add_metric_list(const char *list, struct strbuf *events,
424 struct list_head *group_list)
425{
426 char *llist, *nlist, *p;
427 int ret = -EINVAL;
428
429 nlist = strdup(list);
430 if (!nlist)
431 return -ENOMEM;
432 llist = nlist;
433
434 strbuf_init(events, 100);
435 strbuf_addf(events, "%s", "");
436
437 while ((p = strsep(&llist, ",")) != NULL) {
438 ret = metricgroup__add_metric(p, events, group_list);
439 if (ret == -EINVAL) {
440 fprintf(stderr, "Cannot find metric or group `%s'\n",
441 p);
442 break;
443 }
444 }
445 free(nlist);
446 return ret;
447}
448
449static void metricgroup__free_egroups(struct list_head *group_list)
450{
451 struct egroup *eg, *egtmp;
452 int i;
453
454 list_for_each_entry_safe (eg, egtmp, group_list, nd) {
455 for (i = 0; i < eg->idnum; i++)
456 free((char *)eg->ids[i]);
457 free(eg->ids);
458 free(eg);
459 }
460}
461
462int metricgroup__parse_groups(const struct option *opt,
463 const char *str,
464 struct rblist *metric_events)
465{
466 struct parse_events_error parse_error;
467 struct perf_evlist *perf_evlist = *(struct perf_evlist **)opt->value;
468 struct strbuf extra_events;
469 LIST_HEAD(group_list);
470 int ret;
471
472 if (metric_events->nr_entries == 0)
473 metricgroup__rblist_init(metric_events);
474 ret = metricgroup__add_metric_list(str, &extra_events, &group_list);
475 if (ret)
476 return ret;
477 pr_debug("adding %s\n", extra_events.buf);
478 memset(&parse_error, 0, sizeof(struct parse_events_error));
479 ret = parse_events(perf_evlist, extra_events.buf, &parse_error);
480 if (ret) {
481 parse_events_print_error(&parse_error, extra_events.buf);
482 goto out;
483 }
484 strbuf_release(&extra_events);
485 ret = metricgroup__setup_events(&group_list, perf_evlist,
486 metric_events);
487out:
488 metricgroup__free_egroups(&group_list);
489 return ret;
490}
diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h
new file mode 100644
index 000000000000..06854e125ee7
--- /dev/null
+++ b/tools/perf/util/metricgroup.h
@@ -0,0 +1,31 @@
1#ifndef METRICGROUP_H
2#define METRICGROUP_H 1
3
4#include "linux/list.h"
5#include "rblist.h"
6#include <subcmd/parse-options.h>
7#include "evlist.h"
8#include "strbuf.h"
9
10struct metric_event {
11 struct rb_node nd;
12 struct perf_evsel *evsel;
13 struct list_head head; /* list of metric_expr */
14};
15
16struct metric_expr {
17 struct list_head nd;
18 const char *metric_expr;
19 const char *metric_name;
20 struct perf_evsel **metric_events;
21};
22
23struct metric_event *metricgroup__lookup(struct rblist *metric_events,
24 struct perf_evsel *evsel,
25 bool create);
26int metricgroup__parse_groups(const struct option *opt,
27 const char *str,
28 struct rblist *metric_events);
29
30void metricgroup__print(bool metrics, bool groups, char *filter, bool raw);
31#endif
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
new file mode 100644
index 000000000000..9fe5f9c7d577
--- /dev/null
+++ b/tools/perf/util/mmap.c
@@ -0,0 +1,352 @@
1/*
2 * Copyright (C) 2011-2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 *
4 * Parts came from evlist.c builtin-{top,stat,record}.c, see those files for further
5 * copyright notes.
6 *
7 * Released under the GPL v2. (and only v2, not any later version)
8 */
9
10#include <sys/mman.h>
11#include <inttypes.h>
12#include <asm/bug.h>
13#include "debug.h"
14#include "event.h"
15#include "mmap.h"
16#include "util.h" /* page_size */
17
18size_t perf_mmap__mmap_len(struct perf_mmap *map)
19{
20 return map->mask + 1 + page_size;
21}
22
23/* When check_messup is true, 'end' must points to a good entry */
24static union perf_event *perf_mmap__read(struct perf_mmap *map, bool check_messup,
25 u64 start, u64 end, u64 *prev)
26{
27 unsigned char *data = map->base + page_size;
28 union perf_event *event = NULL;
29 int diff = end - start;
30
31 if (check_messup) {
32 /*
33 * If we're further behind than half the buffer, there's a chance
34 * the writer will bite our tail and mess up the samples under us.
35 *
36 * If we somehow ended up ahead of the 'end', we got messed up.
37 *
38 * In either case, truncate and restart at 'end'.
39 */
40 if (diff > map->mask / 2 || diff < 0) {
41 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
42
43 /*
44 * 'end' points to a known good entry, start there.
45 */
46 start = end;
47 diff = 0;
48 }
49 }
50
51 if (diff >= (int)sizeof(event->header)) {
52 size_t size;
53
54 event = (union perf_event *)&data[start & map->mask];
55 size = event->header.size;
56
57 if (size < sizeof(event->header) || diff < (int)size) {
58 event = NULL;
59 goto broken_event;
60 }
61
62 /*
63 * Event straddles the mmap boundary -- header should always
64 * be inside due to u64 alignment of output.
65 */
66 if ((start & map->mask) + size != ((start + size) & map->mask)) {
67 unsigned int offset = start;
68 unsigned int len = min(sizeof(*event), size), cpy;
69 void *dst = map->event_copy;
70
71 do {
72 cpy = min(map->mask + 1 - (offset & map->mask), len);
73 memcpy(dst, &data[offset & map->mask], cpy);
74 offset += cpy;
75 dst += cpy;
76 len -= cpy;
77 } while (len);
78
79 event = (union perf_event *)map->event_copy;
80 }
81
82 start += size;
83 }
84
85broken_event:
86 if (prev)
87 *prev = start;
88
89 return event;
90}
91
92union perf_event *perf_mmap__read_forward(struct perf_mmap *map, bool check_messup)
93{
94 u64 head;
95 u64 old = map->prev;
96
97 /*
98 * Check if event was unmapped due to a POLLHUP/POLLERR.
99 */
100 if (!refcount_read(&map->refcnt))
101 return NULL;
102
103 head = perf_mmap__read_head(map);
104
105 return perf_mmap__read(map, check_messup, old, head, &map->prev);
106}
107
108union perf_event *perf_mmap__read_backward(struct perf_mmap *map)
109{
110 u64 head, end;
111 u64 start = map->prev;
112
113 /*
114 * Check if event was unmapped due to a POLLHUP/POLLERR.
115 */
116 if (!refcount_read(&map->refcnt))
117 return NULL;
118
119 head = perf_mmap__read_head(map);
120 if (!head)
121 return NULL;
122
123 /*
124 * 'head' pointer starts from 0. Kernel minus sizeof(record) form
125 * it each time when kernel writes to it, so in fact 'head' is
126 * negative. 'end' pointer is made manually by adding the size of
127 * the ring buffer to 'head' pointer, means the validate data can
128 * read is the whole ring buffer. If 'end' is positive, the ring
129 * buffer has not fully filled, so we must adjust 'end' to 0.
130 *
131 * However, since both 'head' and 'end' is unsigned, we can't
132 * simply compare 'end' against 0. Here we compare '-head' and
133 * the size of the ring buffer, where -head is the number of bytes
134 * kernel write to the ring buffer.
135 */
136 if (-head < (u64)(map->mask + 1))
137 end = 0;
138 else
139 end = head + map->mask + 1;
140
141 return perf_mmap__read(map, false, start, end, &map->prev);
142}
143
144void perf_mmap__read_catchup(struct perf_mmap *map)
145{
146 u64 head;
147
148 if (!refcount_read(&map->refcnt))
149 return;
150
151 head = perf_mmap__read_head(map);
152 map->prev = head;
153}
154
155static bool perf_mmap__empty(struct perf_mmap *map)
156{
157 return perf_mmap__read_head(map) == map->prev && !map->auxtrace_mmap.base;
158}
159
160void perf_mmap__get(struct perf_mmap *map)
161{
162 refcount_inc(&map->refcnt);
163}
164
165void perf_mmap__put(struct perf_mmap *map)
166{
167 BUG_ON(map->base && refcount_read(&map->refcnt) == 0);
168
169 if (refcount_dec_and_test(&map->refcnt))
170 perf_mmap__munmap(map);
171}
172
173void perf_mmap__consume(struct perf_mmap *map, bool overwrite)
174{
175 if (!overwrite) {
176 u64 old = map->prev;
177
178 perf_mmap__write_tail(map, old);
179 }
180
181 if (refcount_read(&map->refcnt) == 1 && perf_mmap__empty(map))
182 perf_mmap__put(map);
183}
184
185int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused,
186 struct auxtrace_mmap_params *mp __maybe_unused,
187 void *userpg __maybe_unused,
188 int fd __maybe_unused)
189{
190 return 0;
191}
192
193void __weak auxtrace_mmap__munmap(struct auxtrace_mmap *mm __maybe_unused)
194{
195}
196
197void __weak auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp __maybe_unused,
198 off_t auxtrace_offset __maybe_unused,
199 unsigned int auxtrace_pages __maybe_unused,
200 bool auxtrace_overwrite __maybe_unused)
201{
202}
203
204void __weak auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp __maybe_unused,
205 struct perf_evlist *evlist __maybe_unused,
206 int idx __maybe_unused,
207 bool per_cpu __maybe_unused)
208{
209}
210
211void perf_mmap__munmap(struct perf_mmap *map)
212{
213 if (map->base != NULL) {
214 munmap(map->base, perf_mmap__mmap_len(map));
215 map->base = NULL;
216 map->fd = -1;
217 refcount_set(&map->refcnt, 0);
218 }
219 auxtrace_mmap__munmap(&map->auxtrace_mmap);
220}
221
222int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd)
223{
224 /*
225 * The last one will be done at perf_evlist__mmap_consume(), so that we
226 * make sure we don't prevent tools from consuming every last event in
227 * the ring buffer.
228 *
229 * I.e. we can get the POLLHUP meaning that the fd doesn't exist
230 * anymore, but the last events for it are still in the ring buffer,
231 * waiting to be consumed.
232 *
233 * Tools can chose to ignore this at their own discretion, but the
234 * evlist layer can't just drop it when filtering events in
235 * perf_evlist__filter_pollfd().
236 */
237 refcount_set(&map->refcnt, 2);
238 map->prev = 0;
239 map->mask = mp->mask;
240 map->base = mmap(NULL, perf_mmap__mmap_len(map), mp->prot,
241 MAP_SHARED, fd, 0);
242 if (map->base == MAP_FAILED) {
243 pr_debug2("failed to mmap perf event ring buffer, error %d\n",
244 errno);
245 map->base = NULL;
246 return -1;
247 }
248 map->fd = fd;
249
250 if (auxtrace_mmap__mmap(&map->auxtrace_mmap,
251 &mp->auxtrace_mp, map->base, fd))
252 return -1;
253
254 return 0;
255}
256
257static int backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end)
258{
259 struct perf_event_header *pheader;
260 u64 evt_head = head;
261 int size = mask + 1;
262
263 pr_debug2("backward_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head);
264 pheader = (struct perf_event_header *)(buf + (head & mask));
265 *start = head;
266 while (true) {
267 if (evt_head - head >= (unsigned int)size) {
268 pr_debug("Finished reading backward ring buffer: rewind\n");
269 if (evt_head - head > (unsigned int)size)
270 evt_head -= pheader->size;
271 *end = evt_head;
272 return 0;
273 }
274
275 pheader = (struct perf_event_header *)(buf + (evt_head & mask));
276
277 if (pheader->size == 0) {
278 pr_debug("Finished reading backward ring buffer: get start\n");
279 *end = evt_head;
280 return 0;
281 }
282
283 evt_head += pheader->size;
284 pr_debug3("move evt_head: %"PRIx64"\n", evt_head);
285 }
286 WARN_ONCE(1, "Shouldn't get here\n");
287 return -1;
288}
289
290static int rb_find_range(void *data, int mask, u64 head, u64 old,
291 u64 *start, u64 *end, bool backward)
292{
293 if (!backward) {
294 *start = old;
295 *end = head;
296 return 0;
297 }
298
299 return backward_rb_find_range(data, mask, head, start, end);
300}
301
302int perf_mmap__push(struct perf_mmap *md, bool overwrite, bool backward,
303 void *to, int push(void *to, void *buf, size_t size))
304{
305 u64 head = perf_mmap__read_head(md);
306 u64 old = md->prev;
307 u64 end = head, start = old;
308 unsigned char *data = md->base + page_size;
309 unsigned long size;
310 void *buf;
311 int rc = 0;
312
313 if (rb_find_range(data, md->mask, head, old, &start, &end, backward))
314 return -1;
315
316 if (start == end)
317 return 0;
318
319 size = end - start;
320 if (size > (unsigned long)(md->mask) + 1) {
321 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
322
323 md->prev = head;
324 perf_mmap__consume(md, overwrite || backward);
325 return 0;
326 }
327
328 if ((start & md->mask) + size != (end & md->mask)) {
329 buf = &data[start & md->mask];
330 size = md->mask + 1 - (start & md->mask);
331 start += size;
332
333 if (push(to, buf, size) < 0) {
334 rc = -1;
335 goto out;
336 }
337 }
338
339 buf = &data[start & md->mask];
340 size = end - start;
341 start += size;
342
343 if (push(to, buf, size) < 0) {
344 rc = -1;
345 goto out;
346 }
347
348 md->prev = head;
349 perf_mmap__consume(md, overwrite || backward);
350out:
351 return rc;
352}
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
new file mode 100644
index 000000000000..efd78b827b05
--- /dev/null
+++ b/tools/perf/util/mmap.h
@@ -0,0 +1,97 @@
1#ifndef __PERF_MMAP_H
2#define __PERF_MMAP_H 1
3
4#include <linux/compiler.h>
5#include <linux/refcount.h>
6#include <linux/types.h>
7#include <asm/barrier.h>
8#include <stdbool.h>
9#include "auxtrace.h"
10#include "event.h"
11
12/**
13 * struct perf_mmap - perf's ring buffer mmap details
14 *
15 * @refcnt - e.g. code using PERF_EVENT_IOC_SET_OUTPUT to share this
16 */
17struct perf_mmap {
18 void *base;
19 int mask;
20 int fd;
21 refcount_t refcnt;
22 u64 prev;
23 struct auxtrace_mmap auxtrace_mmap;
24 char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8);
25};
26
27/*
28 * State machine of bkw_mmap_state:
29 *
30 * .________________(forbid)_____________.
31 * | V
32 * NOTREADY --(0)--> RUNNING --(1)--> DATA_PENDING --(2)--> EMPTY
33 * ^ ^ | ^ |
34 * | |__(forbid)____/ |___(forbid)___/|
35 * | |
36 * \_________________(3)_______________/
37 *
38 * NOTREADY : Backward ring buffers are not ready
39 * RUNNING : Backward ring buffers are recording
40 * DATA_PENDING : We are required to collect data from backward ring buffers
41 * EMPTY : We have collected data from backward ring buffers.
42 *
43 * (0): Setup backward ring buffer
44 * (1): Pause ring buffers for reading
45 * (2): Read from ring buffers
46 * (3): Resume ring buffers for recording
47 */
48enum bkw_mmap_state {
49 BKW_MMAP_NOTREADY,
50 BKW_MMAP_RUNNING,
51 BKW_MMAP_DATA_PENDING,
52 BKW_MMAP_EMPTY,
53};
54
55struct mmap_params {
56 int prot, mask;
57 struct auxtrace_mmap_params auxtrace_mp;
58};
59
60int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd);
61void perf_mmap__munmap(struct perf_mmap *map);
62
63void perf_mmap__get(struct perf_mmap *map);
64void perf_mmap__put(struct perf_mmap *map);
65
66void perf_mmap__consume(struct perf_mmap *map, bool overwrite);
67
68void perf_mmap__read_catchup(struct perf_mmap *md);
69
70static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
71{
72 struct perf_event_mmap_page *pc = mm->base;
73 u64 head = ACCESS_ONCE(pc->data_head);
74 rmb();
75 return head;
76}
77
78static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
79{
80 struct perf_event_mmap_page *pc = md->base;
81
82 /*
83 * ensure all reads are done before we write the tail out.
84 */
85 mb();
86 pc->data_tail = tail;
87}
88
89union perf_event *perf_mmap__read_forward(struct perf_mmap *map, bool check_messup);
90union perf_event *perf_mmap__read_backward(struct perf_mmap *map);
91
92int perf_mmap__push(struct perf_mmap *md, bool overwrite, bool backward,
93 void *to, int push(void *to, void *buf, size_t size));
94
95size_t perf_mmap__mmap_len(struct perf_mmap *map);
96
97#endif /*__PERF_MMAP_H */
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
index 67dcbcc73c7d..5be021701f34 100644
--- a/tools/perf/util/namespaces.c
+++ b/tools/perf/util/namespaces.c
@@ -9,9 +9,15 @@
9#include "namespaces.h" 9#include "namespaces.h"
10#include "util.h" 10#include "util.h"
11#include "event.h" 11#include "event.h"
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <limits.h>
16#include <sched.h>
12#include <stdlib.h> 17#include <stdlib.h>
13#include <stdio.h> 18#include <stdio.h>
14#include <string.h> 19#include <string.h>
20#include <unistd.h>
15 21
16struct namespaces *namespaces__new(struct namespaces_event *event) 22struct namespaces *namespaces__new(struct namespaces_event *event)
17{ 23{
@@ -35,3 +41,209 @@ void namespaces__free(struct namespaces *namespaces)
35{ 41{
36 free(namespaces); 42 free(namespaces);
37} 43}
44
45int nsinfo__init(struct nsinfo *nsi)
46{
47 char oldns[PATH_MAX];
48 char spath[PATH_MAX];
49 char *newns = NULL;
50 char *statln = NULL;
51 struct stat old_stat;
52 struct stat new_stat;
53 FILE *f = NULL;
54 size_t linesz = 0;
55 int rv = -1;
56
57 if (snprintf(oldns, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
58 return rv;
59
60 if (asprintf(&newns, "/proc/%d/ns/mnt", nsi->pid) == -1)
61 return rv;
62
63 if (stat(oldns, &old_stat) < 0)
64 goto out;
65
66 if (stat(newns, &new_stat) < 0)
67 goto out;
68
69 /* Check if the mount namespaces differ, if so then indicate that we
70 * want to switch as part of looking up dso/map data.
71 */
72 if (old_stat.st_ino != new_stat.st_ino) {
73 nsi->need_setns = true;
74 nsi->mntns_path = newns;
75 newns = NULL;
76 }
77
78 /* If we're dealing with a process that is in a different PID namespace,
79 * attempt to work out the innermost tgid for the process.
80 */
81 if (snprintf(spath, PATH_MAX, "/proc/%d/status", nsi->pid) >= PATH_MAX)
82 goto out;
83
84 f = fopen(spath, "r");
85 if (f == NULL)
86 goto out;
87
88 while (getline(&statln, &linesz, f) != -1) {
89 /* Use tgid if CONFIG_PID_NS is not defined. */
90 if (strstr(statln, "Tgid:") != NULL) {
91 nsi->tgid = (pid_t)strtol(strrchr(statln, '\t'),
92 NULL, 10);
93 nsi->nstgid = nsi->tgid;
94 }
95
96 if (strstr(statln, "NStgid:") != NULL) {
97 nsi->nstgid = (pid_t)strtol(strrchr(statln, '\t'),
98 NULL, 10);
99 break;
100 }
101 }
102 rv = 0;
103
104out:
105 if (f != NULL)
106 (void) fclose(f);
107 free(statln);
108 free(newns);
109 return rv;
110}
111
112struct nsinfo *nsinfo__new(pid_t pid)
113{
114 struct nsinfo *nsi;
115
116 if (pid == 0)
117 return NULL;
118
119 nsi = calloc(1, sizeof(*nsi));
120 if (nsi != NULL) {
121 nsi->pid = pid;
122 nsi->tgid = pid;
123 nsi->nstgid = pid;
124 nsi->need_setns = false;
125 /* Init may fail if the process exits while we're trying to look
126 * at its proc information. In that case, save the pid but
127 * don't try to enter the namespace.
128 */
129 if (nsinfo__init(nsi) == -1)
130 nsi->need_setns = false;
131
132 refcount_set(&nsi->refcnt, 1);
133 }
134
135 return nsi;
136}
137
138struct nsinfo *nsinfo__copy(struct nsinfo *nsi)
139{
140 struct nsinfo *nnsi;
141
142 nnsi = calloc(1, sizeof(*nnsi));
143 if (nnsi != NULL) {
144 nnsi->pid = nsi->pid;
145 nnsi->tgid = nsi->tgid;
146 nnsi->nstgid = nsi->nstgid;
147 nnsi->need_setns = nsi->need_setns;
148 if (nsi->mntns_path) {
149 nnsi->mntns_path = strdup(nsi->mntns_path);
150 if (!nnsi->mntns_path) {
151 free(nnsi);
152 return NULL;
153 }
154 }
155 refcount_set(&nnsi->refcnt, 1);
156 }
157
158 return nnsi;
159}
160
161void nsinfo__delete(struct nsinfo *nsi)
162{
163 zfree(&nsi->mntns_path);
164 free(nsi);
165}
166
167struct nsinfo *nsinfo__get(struct nsinfo *nsi)
168{
169 if (nsi)
170 refcount_inc(&nsi->refcnt);
171 return nsi;
172}
173
174void nsinfo__put(struct nsinfo *nsi)
175{
176 if (nsi && refcount_dec_and_test(&nsi->refcnt))
177 nsinfo__delete(nsi);
178}
179
180void nsinfo__mountns_enter(struct nsinfo *nsi,
181 struct nscookie *nc)
182{
183 char curpath[PATH_MAX];
184 int oldns = -1;
185 int newns = -1;
186
187 if (nc == NULL)
188 return;
189
190 nc->oldns = -1;
191 nc->newns = -1;
192
193 if (!nsi || !nsi->need_setns)
194 return;
195
196 if (snprintf(curpath, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
197 return;
198
199 oldns = open(curpath, O_RDONLY);
200 if (oldns < 0)
201 return;
202
203 newns = open(nsi->mntns_path, O_RDONLY);
204 if (newns < 0)
205 goto errout;
206
207 if (setns(newns, CLONE_NEWNS) < 0)
208 goto errout;
209
210 nc->oldns = oldns;
211 nc->newns = newns;
212 return;
213
214errout:
215 if (oldns > -1)
216 close(oldns);
217 if (newns > -1)
218 close(newns);
219}
220
221void nsinfo__mountns_exit(struct nscookie *nc)
222{
223 if (nc == NULL || nc->oldns == -1 || nc->newns == -1)
224 return;
225
226 setns(nc->oldns, CLONE_NEWNS);
227
228 if (nc->oldns > -1) {
229 close(nc->oldns);
230 nc->oldns = -1;
231 }
232
233 if (nc->newns > -1) {
234 close(nc->newns);
235 nc->newns = -1;
236 }
237}
238
239char *nsinfo__realpath(const char *path, struct nsinfo *nsi)
240{
241 char *rpath;
242 struct nscookie nsc;
243
244 nsinfo__mountns_enter(nsi, &nsc);
245 rpath = realpath(path, NULL);
246 nsinfo__mountns_exit(&nsc);
247
248 return rpath;
249}
diff --git a/tools/perf/util/namespaces.h b/tools/perf/util/namespaces.h
index 468f1e9a1484..760558dcfd18 100644
--- a/tools/perf/util/namespaces.h
+++ b/tools/perf/util/namespaces.h
@@ -9,8 +9,10 @@
9#ifndef __PERF_NAMESPACES_H 9#ifndef __PERF_NAMESPACES_H
10#define __PERF_NAMESPACES_H 10#define __PERF_NAMESPACES_H
11 11
12#include "../perf.h" 12#include <sys/types.h>
13#include <linux/list.h> 13#include <linux/perf_event.h>
14#include <linux/refcount.h>
15#include <linux/types.h>
14 16
15struct namespaces_event; 17struct namespaces_event;
16 18
@@ -23,4 +25,41 @@ struct namespaces {
23struct namespaces *namespaces__new(struct namespaces_event *event); 25struct namespaces *namespaces__new(struct namespaces_event *event);
24void namespaces__free(struct namespaces *namespaces); 26void namespaces__free(struct namespaces *namespaces);
25 27
28struct nsinfo {
29 pid_t pid;
30 pid_t tgid;
31 pid_t nstgid;
32 bool need_setns;
33 char *mntns_path;
34 refcount_t refcnt;
35};
36
37struct nscookie {
38 int oldns;
39 int newns;
40};
41
42int nsinfo__init(struct nsinfo *nsi);
43struct nsinfo *nsinfo__new(pid_t pid);
44struct nsinfo *nsinfo__copy(struct nsinfo *nsi);
45void nsinfo__delete(struct nsinfo *nsi);
46
47struct nsinfo *nsinfo__get(struct nsinfo *nsi);
48void nsinfo__put(struct nsinfo *nsi);
49
50void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc);
51void nsinfo__mountns_exit(struct nscookie *nc);
52
53char *nsinfo__realpath(const char *path, struct nsinfo *nsi);
54
55static inline void __nsinfo__zput(struct nsinfo **nsip)
56{
57 if (nsip) {
58 nsinfo__put(*nsip);
59 *nsip = NULL;
60 }
61}
62
63#define nsinfo__zput(nsi) __nsinfo__zput(&nsi)
64
26#endif /* __PERF_NAMESPACES_H */ 65#endif /* __PERF_NAMESPACES_H */
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index 4de398cfb577..8e09fd2d842f 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <inttypes.h> 3#include <inttypes.h>
3#include <linux/list.h> 4#include <linux/list.h>
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
index e11468a9a6e4..96e5292d88e2 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __ORDERED_EVENTS_H 2#ifndef __ORDERED_EVENTS_H
2#define __ORDERED_EVENTS_H 3#define __ORDERED_EVENTS_H
3 4
diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c
index 38fd11504015..bd779d9f4d1e 100644
--- a/tools/perf/util/parse-branch-options.c
+++ b/tools/perf/util/parse-branch-options.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "perf.h" 2#include "perf.h"
2#include "util/util.h" 3#include "util/util.h"
3#include "util/debug.h" 4#include "util/debug.h"
@@ -28,6 +29,7 @@ static const struct branch_mode branch_modes[] = {
28 BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND), 29 BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND),
29 BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP), 30 BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP),
30 BRANCH_OPT("call", PERF_SAMPLE_BRANCH_CALL), 31 BRANCH_OPT("call", PERF_SAMPLE_BRANCH_CALL),
32 BRANCH_OPT("save_type", PERF_SAMPLE_BRANCH_TYPE_SAVE),
31 BRANCH_END 33 BRANCH_END
32}; 34};
33 35
diff --git a/tools/perf/util/parse-branch-options.h b/tools/perf/util/parse-branch-options.h
index 6086fd90eb23..11d1722733f2 100644
--- a/tools/perf/util/parse-branch-options.h
+++ b/tools/perf/util/parse-branch-options.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_PARSE_BRANCH_OPTIONS_H 2#ifndef _PERF_PARSE_BRANCH_OPTIONS_H
2#define _PERF_PARSE_BRANCH_OPTIONS_H 1 3#define _PERF_PARSE_BRANCH_OPTIONS_H 1
3#include <stdint.h> 4#include <stdint.h>
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 01e779b91c8e..a7fcd95961ef 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/hw_breakpoint.h> 2#include <linux/hw_breakpoint.h>
2#include <linux/err.h> 3#include <linux/err.h>
3#include <dirent.h> 4#include <dirent.h>
@@ -28,13 +29,14 @@
28#include "probe-file.h" 29#include "probe-file.h"
29#include "asm/bug.h" 30#include "asm/bug.h"
30#include "util/parse-branch-options.h" 31#include "util/parse-branch-options.h"
32#include "metricgroup.h"
31 33
32#define MAX_NAME_LEN 100 34#define MAX_NAME_LEN 100
33 35
34#ifdef PARSER_DEBUG 36#ifdef PARSER_DEBUG
35extern int parse_events_debug; 37extern int parse_events_debug;
36#endif 38#endif
37int parse_events_parse(void *data, void *scanner); 39int parse_events_parse(void *parse_state, void *scanner);
38static int get_config_terms(struct list_head *head_config, 40static int get_config_terms(struct list_head *head_config,
39 struct list_head *head_terms __maybe_unused); 41 struct list_head *head_terms __maybe_unused);
40 42
@@ -309,10 +311,11 @@ static char *get_config_name(struct list_head *head_terms)
309static struct perf_evsel * 311static struct perf_evsel *
310__add_event(struct list_head *list, int *idx, 312__add_event(struct list_head *list, int *idx,
311 struct perf_event_attr *attr, 313 struct perf_event_attr *attr,
312 char *name, struct cpu_map *cpus, 314 char *name, struct perf_pmu *pmu,
313 struct list_head *config_terms) 315 struct list_head *config_terms, bool auto_merge_stats)
314{ 316{
315 struct perf_evsel *evsel; 317 struct perf_evsel *evsel;
318 struct cpu_map *cpus = pmu ? pmu->cpus : NULL;
316 319
317 event_attr_init(attr); 320 event_attr_init(attr);
318 321
@@ -323,7 +326,8 @@ __add_event(struct list_head *list, int *idx,
323 (*idx)++; 326 (*idx)++;
324 evsel->cpus = cpu_map__get(cpus); 327 evsel->cpus = cpu_map__get(cpus);
325 evsel->own_cpus = cpu_map__get(cpus); 328 evsel->own_cpus = cpu_map__get(cpus);
326 evsel->system_wide = !!cpus; 329 evsel->system_wide = pmu ? pmu->is_uncore : false;
330 evsel->auto_merge_stats = auto_merge_stats;
327 331
328 if (name) 332 if (name)
329 evsel->name = strdup(name); 333 evsel->name = strdup(name);
@@ -339,7 +343,7 @@ static int add_event(struct list_head *list, int *idx,
339 struct perf_event_attr *attr, char *name, 343 struct perf_event_attr *attr, char *name,
340 struct list_head *config_terms) 344 struct list_head *config_terms)
341{ 345{
342 return __add_event(list, idx, attr, name, NULL, config_terms) ? 0 : -ENOMEM; 346 return __add_event(list, idx, attr, name, NULL, config_terms, false) ? 0 : -ENOMEM;
343} 347}
344 348
345static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) 349static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
@@ -589,7 +593,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
589} 593}
590 594
591struct __add_bpf_event_param { 595struct __add_bpf_event_param {
592 struct parse_events_evlist *data; 596 struct parse_events_state *parse_state;
593 struct list_head *list; 597 struct list_head *list;
594 struct list_head *head_config; 598 struct list_head *head_config;
595}; 599};
@@ -599,7 +603,7 @@ static int add_bpf_event(const char *group, const char *event, int fd,
599{ 603{
600 LIST_HEAD(new_evsels); 604 LIST_HEAD(new_evsels);
601 struct __add_bpf_event_param *param = _param; 605 struct __add_bpf_event_param *param = _param;
602 struct parse_events_evlist *evlist = param->data; 606 struct parse_events_state *parse_state = param->parse_state;
603 struct list_head *list = param->list; 607 struct list_head *list = param->list;
604 struct perf_evsel *pos; 608 struct perf_evsel *pos;
605 int err; 609 int err;
@@ -607,8 +611,8 @@ static int add_bpf_event(const char *group, const char *event, int fd,
607 pr_debug("add bpf event %s:%s and attach bpf program %d\n", 611 pr_debug("add bpf event %s:%s and attach bpf program %d\n",
608 group, event, fd); 612 group, event, fd);
609 613
610 err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, group, 614 err = parse_events_add_tracepoint(&new_evsels, &parse_state->idx, group,
611 event, evlist->error, 615 event, parse_state->error,
612 param->head_config); 616 param->head_config);
613 if (err) { 617 if (err) {
614 struct perf_evsel *evsel, *tmp; 618 struct perf_evsel *evsel, *tmp;
@@ -632,14 +636,14 @@ static int add_bpf_event(const char *group, const char *event, int fd,
632 return 0; 636 return 0;
633} 637}
634 638
635int parse_events_load_bpf_obj(struct parse_events_evlist *data, 639int parse_events_load_bpf_obj(struct parse_events_state *parse_state,
636 struct list_head *list, 640 struct list_head *list,
637 struct bpf_object *obj, 641 struct bpf_object *obj,
638 struct list_head *head_config) 642 struct list_head *head_config)
639{ 643{
640 int err; 644 int err;
641 char errbuf[BUFSIZ]; 645 char errbuf[BUFSIZ];
642 struct __add_bpf_event_param param = {data, list, head_config}; 646 struct __add_bpf_event_param param = {parse_state, list, head_config};
643 static bool registered_unprobe_atexit = false; 647 static bool registered_unprobe_atexit = false;
644 648
645 if (IS_ERR(obj) || !obj) { 649 if (IS_ERR(obj) || !obj) {
@@ -680,13 +684,13 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data,
680 684
681 return 0; 685 return 0;
682errout: 686errout:
683 data->error->help = strdup("(add -v to see detail)"); 687 parse_state->error->help = strdup("(add -v to see detail)");
684 data->error->str = strdup(errbuf); 688 parse_state->error->str = strdup(errbuf);
685 return err; 689 return err;
686} 690}
687 691
688static int 692static int
689parse_events_config_bpf(struct parse_events_evlist *data, 693parse_events_config_bpf(struct parse_events_state *parse_state,
690 struct bpf_object *obj, 694 struct bpf_object *obj,
691 struct list_head *head_config) 695 struct list_head *head_config)
692{ 696{
@@ -705,28 +709,28 @@ parse_events_config_bpf(struct parse_events_evlist *data,
705 "Invalid config term for BPF object"); 709 "Invalid config term for BPF object");
706 errbuf[BUFSIZ - 1] = '\0'; 710 errbuf[BUFSIZ - 1] = '\0';
707 711
708 data->error->idx = term->err_term; 712 parse_state->error->idx = term->err_term;
709 data->error->str = strdup(errbuf); 713 parse_state->error->str = strdup(errbuf);
710 return -EINVAL; 714 return -EINVAL;
711 } 715 }
712 716
713 err = bpf__config_obj(obj, term, data->evlist, &error_pos); 717 err = bpf__config_obj(obj, term, parse_state->evlist, &error_pos);
714 if (err) { 718 if (err) {
715 bpf__strerror_config_obj(obj, term, data->evlist, 719 bpf__strerror_config_obj(obj, term, parse_state->evlist,
716 &error_pos, err, errbuf, 720 &error_pos, err, errbuf,
717 sizeof(errbuf)); 721 sizeof(errbuf));
718 data->error->help = strdup( 722 parse_state->error->help = strdup(
719"Hint:\tValid config terms:\n" 723"Hint:\tValid config terms:\n"
720" \tmap:[<arraymap>].value<indices>=[value]\n" 724" \tmap:[<arraymap>].value<indices>=[value]\n"
721" \tmap:[<eventmap>].event<indices>=[event]\n" 725" \tmap:[<eventmap>].event<indices>=[event]\n"
722"\n" 726"\n"
723" \twhere <indices> is something like [0,3...5] or [all]\n" 727" \twhere <indices> is something like [0,3...5] or [all]\n"
724" \t(add -v to see detail)"); 728" \t(add -v to see detail)");
725 data->error->str = strdup(errbuf); 729 parse_state->error->str = strdup(errbuf);
726 if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE) 730 if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
727 data->error->idx = term->err_val; 731 parse_state->error->idx = term->err_val;
728 else 732 else
729 data->error->idx = term->err_term + error_pos; 733 parse_state->error->idx = term->err_term + error_pos;
730 return err; 734 return err;
731 } 735 }
732 } 736 }
@@ -762,7 +766,7 @@ split_bpf_config_terms(struct list_head *evt_head_config,
762 list_move_tail(&term->list, obj_head_config); 766 list_move_tail(&term->list, obj_head_config);
763} 767}
764 768
765int parse_events_load_bpf(struct parse_events_evlist *data, 769int parse_events_load_bpf(struct parse_events_state *parse_state,
766 struct list_head *list, 770 struct list_head *list,
767 char *bpf_file_name, 771 char *bpf_file_name,
768 bool source, 772 bool source,
@@ -790,15 +794,15 @@ int parse_events_load_bpf(struct parse_events_evlist *data,
790 -err, errbuf, 794 -err, errbuf,
791 sizeof(errbuf)); 795 sizeof(errbuf));
792 796
793 data->error->help = strdup("(add -v to see detail)"); 797 parse_state->error->help = strdup("(add -v to see detail)");
794 data->error->str = strdup(errbuf); 798 parse_state->error->str = strdup(errbuf);
795 return err; 799 return err;
796 } 800 }
797 801
798 err = parse_events_load_bpf_obj(data, list, obj, head_config); 802 err = parse_events_load_bpf_obj(parse_state, list, obj, head_config);
799 if (err) 803 if (err)
800 return err; 804 return err;
801 err = parse_events_config_bpf(data, obj, &obj_head_config); 805 err = parse_events_config_bpf(parse_state, obj, &obj_head_config);
802 806
803 /* 807 /*
804 * Caller doesn't know anything about obj_head_config, 808 * Caller doesn't know anything about obj_head_config,
@@ -1184,7 +1188,7 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
1184 err, head_config); 1188 err, head_config);
1185} 1189}
1186 1190
1187int parse_events_add_numeric(struct parse_events_evlist *data, 1191int parse_events_add_numeric(struct parse_events_state *parse_state,
1188 struct list_head *list, 1192 struct list_head *list,
1189 u32 type, u64 config, 1193 u32 type, u64 config,
1190 struct list_head *head_config) 1194 struct list_head *head_config)
@@ -1197,7 +1201,7 @@ int parse_events_add_numeric(struct parse_events_evlist *data,
1197 attr.config = config; 1201 attr.config = config;
1198 1202
1199 if (head_config) { 1203 if (head_config) {
1200 if (config_attr(&attr, head_config, data->error, 1204 if (config_attr(&attr, head_config, parse_state->error,
1201 config_term_common)) 1205 config_term_common))
1202 return -EINVAL; 1206 return -EINVAL;
1203 1207
@@ -1205,23 +1209,29 @@ int parse_events_add_numeric(struct parse_events_evlist *data,
1205 return -ENOMEM; 1209 return -ENOMEM;
1206 } 1210 }
1207 1211
1208 return add_event(list, &data->idx, &attr, 1212 return add_event(list, &parse_state->idx, &attr,
1209 get_config_name(head_config), &config_terms); 1213 get_config_name(head_config), &config_terms);
1210} 1214}
1211 1215
1212int parse_events_add_pmu(struct parse_events_evlist *data, 1216static int __parse_events_add_pmu(struct parse_events_state *parse_state,
1213 struct list_head *list, char *name, 1217 struct list_head *list, char *name,
1214 struct list_head *head_config) 1218 struct list_head *head_config, bool auto_merge_stats)
1215{ 1219{
1216 struct perf_event_attr attr; 1220 struct perf_event_attr attr;
1217 struct perf_pmu_info info; 1221 struct perf_pmu_info info;
1218 struct perf_pmu *pmu; 1222 struct perf_pmu *pmu;
1219 struct perf_evsel *evsel; 1223 struct perf_evsel *evsel;
1224 struct parse_events_error *err = parse_state->error;
1220 LIST_HEAD(config_terms); 1225 LIST_HEAD(config_terms);
1221 1226
1222 pmu = perf_pmu__find(name); 1227 pmu = perf_pmu__find(name);
1223 if (!pmu) 1228 if (!pmu) {
1229 if (asprintf(&err->str,
1230 "Cannot find PMU `%s'. Missing kernel support?",
1231 name) < 0)
1232 err->str = NULL;
1224 return -EINVAL; 1233 return -EINVAL;
1234 }
1225 1235
1226 if (pmu->default_config) { 1236 if (pmu->default_config) {
1227 memcpy(&attr, pmu->default_config, 1237 memcpy(&attr, pmu->default_config,
@@ -1232,7 +1242,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
1232 1242
1233 if (!head_config) { 1243 if (!head_config) {
1234 attr.type = pmu->type; 1244 attr.type = pmu->type;
1235 evsel = __add_event(list, &data->idx, &attr, NULL, pmu->cpus, NULL); 1245 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats);
1236 return evsel ? 0 : -ENOMEM; 1246 return evsel ? 0 : -ENOMEM;
1237 } 1247 }
1238 1248
@@ -1243,18 +1253,18 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
1243 * Configure hardcoded terms first, no need to check 1253 * Configure hardcoded terms first, no need to check
1244 * return value when called with fail == 0 ;) 1254 * return value when called with fail == 0 ;)
1245 */ 1255 */
1246 if (config_attr(&attr, head_config, data->error, config_term_pmu)) 1256 if (config_attr(&attr, head_config, parse_state->error, config_term_pmu))
1247 return -EINVAL; 1257 return -EINVAL;
1248 1258
1249 if (get_config_terms(head_config, &config_terms)) 1259 if (get_config_terms(head_config, &config_terms))
1250 return -ENOMEM; 1260 return -ENOMEM;
1251 1261
1252 if (perf_pmu__config(pmu, &attr, head_config, data->error)) 1262 if (perf_pmu__config(pmu, &attr, head_config, parse_state->error))
1253 return -EINVAL; 1263 return -EINVAL;
1254 1264
1255 evsel = __add_event(list, &data->idx, &attr, 1265 evsel = __add_event(list, &parse_state->idx, &attr,
1256 get_config_name(head_config), pmu->cpus, 1266 get_config_name(head_config), pmu,
1257 &config_terms); 1267 &config_terms, auto_merge_stats);
1258 if (evsel) { 1268 if (evsel) {
1259 evsel->unit = info.unit; 1269 evsel->unit = info.unit;
1260 evsel->scale = info.scale; 1270 evsel->scale = info.scale;
@@ -1267,7 +1277,14 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
1267 return evsel ? 0 : -ENOMEM; 1277 return evsel ? 0 : -ENOMEM;
1268} 1278}
1269 1279
1270int parse_events_multi_pmu_add(struct parse_events_evlist *data, 1280int parse_events_add_pmu(struct parse_events_state *parse_state,
1281 struct list_head *list, char *name,
1282 struct list_head *head_config)
1283{
1284 return __parse_events_add_pmu(parse_state, list, name, head_config, false);
1285}
1286
1287int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1271 char *str, struct list_head **listp) 1288 char *str, struct list_head **listp)
1272{ 1289{
1273 struct list_head *head; 1290 struct list_head *head;
@@ -1296,8 +1313,8 @@ int parse_events_multi_pmu_add(struct parse_events_evlist *data,
1296 return -1; 1313 return -1;
1297 list_add_tail(&term->list, head); 1314 list_add_tail(&term->list, head);
1298 1315
1299 if (!parse_events_add_pmu(data, list, 1316 if (!__parse_events_add_pmu(parse_state, list,
1300 pmu->name, head)) { 1317 pmu->name, head, true)) {
1301 pr_debug("%s -> %s/%s/\n", str, 1318 pr_debug("%s -> %s/%s/\n", str,
1302 pmu->name, alias->str); 1319 pmu->name, alias->str);
1303 ok++; 1320 ok++;
@@ -1358,6 +1375,7 @@ struct event_modifier {
1358 int exclude_GH; 1375 int exclude_GH;
1359 int sample_read; 1376 int sample_read;
1360 int pinned; 1377 int pinned;
1378 int weak;
1361}; 1379};
1362 1380
1363static int get_event_modifier(struct event_modifier *mod, char *str, 1381static int get_event_modifier(struct event_modifier *mod, char *str,
@@ -1376,6 +1394,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
1376 1394
1377 int exclude = eu | ek | eh; 1395 int exclude = eu | ek | eh;
1378 int exclude_GH = evsel ? evsel->exclude_GH : 0; 1396 int exclude_GH = evsel ? evsel->exclude_GH : 0;
1397 int weak = 0;
1379 1398
1380 memset(mod, 0, sizeof(*mod)); 1399 memset(mod, 0, sizeof(*mod));
1381 1400
@@ -1413,6 +1432,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
1413 sample_read = 1; 1432 sample_read = 1;
1414 } else if (*str == 'D') { 1433 } else if (*str == 'D') {
1415 pinned = 1; 1434 pinned = 1;
1435 } else if (*str == 'W') {
1436 weak = 1;
1416 } else 1437 } else
1417 break; 1438 break;
1418 1439
@@ -1443,6 +1464,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
1443 mod->exclude_GH = exclude_GH; 1464 mod->exclude_GH = exclude_GH;
1444 mod->sample_read = sample_read; 1465 mod->sample_read = sample_read;
1445 mod->pinned = pinned; 1466 mod->pinned = pinned;
1467 mod->weak = weak;
1446 1468
1447 return 0; 1469 return 0;
1448} 1470}
@@ -1456,7 +1478,7 @@ static int check_modifier(char *str)
1456 char *p = str; 1478 char *p = str;
1457 1479
1458 /* The sizeof includes 0 byte as well. */ 1480 /* The sizeof includes 0 byte as well. */
1459 if (strlen(str) > (sizeof("ukhGHpppPSDI") - 1)) 1481 if (strlen(str) > (sizeof("ukhGHpppPSDIW") - 1))
1460 return -1; 1482 return -1;
1461 1483
1462 while (*p) { 1484 while (*p) {
@@ -1496,6 +1518,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
1496 evsel->exclude_GH = mod.exclude_GH; 1518 evsel->exclude_GH = mod.exclude_GH;
1497 evsel->sample_read = mod.sample_read; 1519 evsel->sample_read = mod.sample_read;
1498 evsel->precise_max = mod.precise_max; 1520 evsel->precise_max = mod.precise_max;
1521 evsel->weak_group = mod.weak;
1499 1522
1500 if (perf_evsel__is_group_leader(evsel)) 1523 if (perf_evsel__is_group_leader(evsel))
1501 evsel->attr.pinned = mod.pinned; 1524 evsel->attr.pinned = mod.pinned;
@@ -1628,7 +1651,7 @@ perf_pmu__parse_check(const char *name)
1628 return r ? r->type : PMU_EVENT_SYMBOL_ERR; 1651 return r ? r->type : PMU_EVENT_SYMBOL_ERR;
1629} 1652}
1630 1653
1631static int parse_events__scanner(const char *str, void *data, int start_token) 1654static int parse_events__scanner(const char *str, void *parse_state, int start_token)
1632{ 1655{
1633 YY_BUFFER_STATE buffer; 1656 YY_BUFFER_STATE buffer;
1634 void *scanner; 1657 void *scanner;
@@ -1643,7 +1666,7 @@ static int parse_events__scanner(const char *str, void *data, int start_token)
1643#ifdef PARSER_DEBUG 1666#ifdef PARSER_DEBUG
1644 parse_events_debug = 1; 1667 parse_events_debug = 1;
1645#endif 1668#endif
1646 ret = parse_events_parse(data, scanner); 1669 ret = parse_events_parse(parse_state, scanner);
1647 1670
1648 parse_events__flush_buffer(buffer, scanner); 1671 parse_events__flush_buffer(buffer, scanner);
1649 parse_events__delete_buffer(buffer, scanner); 1672 parse_events__delete_buffer(buffer, scanner);
@@ -1656,45 +1679,45 @@ static int parse_events__scanner(const char *str, void *data, int start_token)
1656 */ 1679 */
1657int parse_events_terms(struct list_head *terms, const char *str) 1680int parse_events_terms(struct list_head *terms, const char *str)
1658{ 1681{
1659 struct parse_events_terms data = { 1682 struct parse_events_state parse_state = {
1660 .terms = NULL, 1683 .terms = NULL,
1661 }; 1684 };
1662 int ret; 1685 int ret;
1663 1686
1664 ret = parse_events__scanner(str, &data, PE_START_TERMS); 1687 ret = parse_events__scanner(str, &parse_state, PE_START_TERMS);
1665 if (!ret) { 1688 if (!ret) {
1666 list_splice(data.terms, terms); 1689 list_splice(parse_state.terms, terms);
1667 zfree(&data.terms); 1690 zfree(&parse_state.terms);
1668 return 0; 1691 return 0;
1669 } 1692 }
1670 1693
1671 parse_events_terms__delete(data.terms); 1694 parse_events_terms__delete(parse_state.terms);
1672 return ret; 1695 return ret;
1673} 1696}
1674 1697
1675int parse_events(struct perf_evlist *evlist, const char *str, 1698int parse_events(struct perf_evlist *evlist, const char *str,
1676 struct parse_events_error *err) 1699 struct parse_events_error *err)
1677{ 1700{
1678 struct parse_events_evlist data = { 1701 struct parse_events_state parse_state = {
1679 .list = LIST_HEAD_INIT(data.list), 1702 .list = LIST_HEAD_INIT(parse_state.list),
1680 .idx = evlist->nr_entries, 1703 .idx = evlist->nr_entries,
1681 .error = err, 1704 .error = err,
1682 .evlist = evlist, 1705 .evlist = evlist,
1683 }; 1706 };
1684 int ret; 1707 int ret;
1685 1708
1686 ret = parse_events__scanner(str, &data, PE_START_EVENTS); 1709 ret = parse_events__scanner(str, &parse_state, PE_START_EVENTS);
1687 perf_pmu__parse_cleanup(); 1710 perf_pmu__parse_cleanup();
1688 if (!ret) { 1711 if (!ret) {
1689 struct perf_evsel *last; 1712 struct perf_evsel *last;
1690 1713
1691 if (list_empty(&data.list)) { 1714 if (list_empty(&parse_state.list)) {
1692 WARN_ONCE(true, "WARNING: event parser found nothing"); 1715 WARN_ONCE(true, "WARNING: event parser found nothing");
1693 return -1; 1716 return -1;
1694 } 1717 }
1695 1718
1696 perf_evlist__splice_list_tail(evlist, &data.list); 1719 perf_evlist__splice_list_tail(evlist, &parse_state.list);
1697 evlist->nr_groups += data.nr_groups; 1720 evlist->nr_groups += parse_state.nr_groups;
1698 last = perf_evlist__last(evlist); 1721 last = perf_evlist__last(evlist);
1699 last->cmdline_group_boundary = true; 1722 last->cmdline_group_boundary = true;
1700 1723
@@ -1718,8 +1741,8 @@ static int get_term_width(void)
1718 return ws.ws_col > MAX_WIDTH ? MAX_WIDTH : ws.ws_col; 1741 return ws.ws_col > MAX_WIDTH ? MAX_WIDTH : ws.ws_col;
1719} 1742}
1720 1743
1721static void parse_events_print_error(struct parse_events_error *err, 1744void parse_events_print_error(struct parse_events_error *err,
1722 const char *event) 1745 const char *event)
1723{ 1746{
1724 const char *str = "invalid or unsupported event: "; 1747 const char *str = "invalid or unsupported event: ";
1725 char _buf[MAX_WIDTH]; 1748 char _buf[MAX_WIDTH];
@@ -1774,8 +1797,6 @@ static void parse_events_print_error(struct parse_events_error *err,
1774 zfree(&err->str); 1797 zfree(&err->str);
1775 zfree(&err->help); 1798 zfree(&err->help);
1776 } 1799 }
1777
1778 fprintf(stderr, "Run 'perf list' for a list of valid events\n");
1779} 1800}
1780 1801
1781#undef MAX_WIDTH 1802#undef MAX_WIDTH
@@ -1787,8 +1808,10 @@ int parse_events_option(const struct option *opt, const char *str,
1787 struct parse_events_error err = { .idx = 0, }; 1808 struct parse_events_error err = { .idx = 0, };
1788 int ret = parse_events(evlist, str, &err); 1809 int ret = parse_events(evlist, str, &err);
1789 1810
1790 if (ret) 1811 if (ret) {
1791 parse_events_print_error(&err, str); 1812 parse_events_print_error(&err, str);
1813 fprintf(stderr, "Run 'perf list' for a list of valid events\n");
1814 }
1792 1815
1793 return ret; 1816 return ret;
1794} 1817}
@@ -2124,7 +2147,7 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob,
2124 return; 2147 return;
2125 } 2148 }
2126 strlist__for_each_entry(nd, bidlist) { 2149 strlist__for_each_entry(nd, bidlist) {
2127 pcache = probe_cache__new(nd->s); 2150 pcache = probe_cache__new(nd->s, NULL);
2128 if (!pcache) 2151 if (!pcache)
2129 continue; 2152 continue;
2130 list_for_each_entry(ent, &pcache->entries, node) { 2153 list_for_each_entry(ent, &pcache->entries, node) {
@@ -2366,6 +2389,8 @@ void print_events(const char *event_glob, bool name_only, bool quiet_flag,
2366 print_tracepoint_events(NULL, NULL, name_only); 2389 print_tracepoint_events(NULL, NULL, name_only);
2367 2390
2368 print_sdt_events(NULL, NULL, name_only); 2391 print_sdt_events(NULL, NULL, name_only);
2392
2393 metricgroup__print(true, true, NULL, name_only);
2369} 2394}
2370 2395
2371int parse_events__is_hardcoded_term(struct parse_events_term *term) 2396int parse_events__is_hardcoded_term(struct parse_events_term *term)
@@ -2520,10 +2545,10 @@ void parse_events__clear_array(struct parse_events_array *a)
2520 zfree(&a->ranges); 2545 zfree(&a->ranges);
2521} 2546}
2522 2547
2523void parse_events_evlist_error(struct parse_events_evlist *data, 2548void parse_events_evlist_error(struct parse_events_state *parse_state,
2524 int idx, const char *str) 2549 int idx, const char *str)
2525{ 2550{
2526 struct parse_events_error *err = data->error; 2551 struct parse_events_error *err = parse_state->error;
2527 2552
2528 if (!err) 2553 if (!err)
2529 return; 2554 return;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index a235f4d6d5e5..be337c266697 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_PARSE_EVENTS_H 2#ifndef __PERF_PARSE_EVENTS_H
2#define __PERF_PARSE_EVENTS_H 3#define __PERF_PARSE_EVENTS_H
3/* 4/*
@@ -108,16 +109,13 @@ struct parse_events_error {
108 char *help; /* optional help string */ 109 char *help; /* optional help string */
109}; 110};
110 111
111struct parse_events_evlist { 112struct parse_events_state {
112 struct list_head list; 113 struct list_head list;
113 int idx; 114 int idx;
114 int nr_groups; 115 int nr_groups;
115 struct parse_events_error *error; 116 struct parse_events_error *error;
116 struct perf_evlist *evlist; 117 struct perf_evlist *evlist;
117}; 118 struct list_head *terms;
118
119struct parse_events_terms {
120 struct list_head *terms;
121}; 119};
122 120
123void parse_events__shrink_config_terms(void); 121void parse_events__shrink_config_terms(void);
@@ -143,18 +141,18 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
143 const char *sys, const char *event, 141 const char *sys, const char *event,
144 struct parse_events_error *error, 142 struct parse_events_error *error,
145 struct list_head *head_config); 143 struct list_head *head_config);
146int parse_events_load_bpf(struct parse_events_evlist *data, 144int parse_events_load_bpf(struct parse_events_state *parse_state,
147 struct list_head *list, 145 struct list_head *list,
148 char *bpf_file_name, 146 char *bpf_file_name,
149 bool source, 147 bool source,
150 struct list_head *head_config); 148 struct list_head *head_config);
151/* Provide this function for perf test */ 149/* Provide this function for perf test */
152struct bpf_object; 150struct bpf_object;
153int parse_events_load_bpf_obj(struct parse_events_evlist *data, 151int parse_events_load_bpf_obj(struct parse_events_state *parse_state,
154 struct list_head *list, 152 struct list_head *list,
155 struct bpf_object *obj, 153 struct bpf_object *obj,
156 struct list_head *head_config); 154 struct list_head *head_config);
157int parse_events_add_numeric(struct parse_events_evlist *data, 155int parse_events_add_numeric(struct parse_events_state *parse_state,
158 struct list_head *list, 156 struct list_head *list,
159 u32 type, u64 config, 157 u32 type, u64 config,
160 struct list_head *head_config); 158 struct list_head *head_config);
@@ -164,11 +162,11 @@ int parse_events_add_cache(struct list_head *list, int *idx,
164 struct list_head *head_config); 162 struct list_head *head_config);
165int parse_events_add_breakpoint(struct list_head *list, int *idx, 163int parse_events_add_breakpoint(struct list_head *list, int *idx,
166 void *ptr, char *type, u64 len); 164 void *ptr, char *type, u64 len);
167int parse_events_add_pmu(struct parse_events_evlist *data, 165int parse_events_add_pmu(struct parse_events_state *parse_state,
168 struct list_head *list, char *name, 166 struct list_head *list, char *name,
169 struct list_head *head_config); 167 struct list_head *head_config);
170 168
171int parse_events_multi_pmu_add(struct parse_events_evlist *data, 169int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
172 char *str, 170 char *str,
173 struct list_head **listp); 171 struct list_head **listp);
174 172
@@ -180,7 +178,7 @@ perf_pmu__parse_check(const char *name);
180void parse_events__set_leader(char *name, struct list_head *list); 178void parse_events__set_leader(char *name, struct list_head *list);
181void parse_events_update_lists(struct list_head *list_event, 179void parse_events_update_lists(struct list_head *list_event,
182 struct list_head *list_all); 180 struct list_head *list_all);
183void parse_events_evlist_error(struct parse_events_evlist *data, 181void parse_events_evlist_error(struct parse_events_state *parse_state,
184 int idx, const char *str); 182 int idx, const char *str);
185 183
186void print_events(const char *event_glob, bool name_only, bool quiet, 184void print_events(const char *event_glob, bool name_only, bool quiet,
@@ -205,6 +203,9 @@ int is_valid_tracepoint(const char *event_string);
205int valid_event_mount(const char *eventfs); 203int valid_event_mount(const char *eventfs);
206char *parse_events_formats_error_string(char *additional_terms); 204char *parse_events_formats_error_string(char *additional_terms);
207 205
206void parse_events_print_error(struct parse_events_error *err,
207 const char *event);
208
208#ifdef HAVE_LIBELF_SUPPORT 209#ifdef HAVE_LIBELF_SUPPORT
209/* 210/*
210 * If the probe point starts with '%', 211 * If the probe point starts with '%',
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 660fca05bc93..655ecff636a8 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -5,9 +5,13 @@
5%option stack 5%option stack
6%option bison-locations 6%option bison-locations
7%option yylineno 7%option yylineno
8%option reject
8 9
9%{ 10%{
10#include <errno.h> 11#include <errno.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <unistd.h>
11#include "../perf.h" 15#include "../perf.h"
12#include "parse-events.h" 16#include "parse-events.h"
13#include "parse-events-bison.h" 17#include "parse-events-bison.h"
@@ -53,6 +57,31 @@ static int str(yyscan_t scanner, int token)
53 return token; 57 return token;
54} 58}
55 59
60static bool isbpf_suffix(char *text)
61{
62 int len = strlen(text);
63
64 if (len < 2)
65 return false;
66 if ((text[len - 1] == 'c' || text[len - 1] == 'o') &&
67 text[len - 2] == '.')
68 return true;
69 if (len > 4 && !strcmp(text + len - 4, ".obj"))
70 return true;
71 return false;
72}
73
74static bool isbpf(yyscan_t scanner)
75{
76 char *text = parse_events_get_text(scanner);
77 struct stat st;
78
79 if (!isbpf_suffix(text))
80 return false;
81
82 return stat(text, &st) == 0;
83}
84
56/* 85/*
57 * This function is called when the parser gets two kind of input: 86 * This function is called when the parser gets two kind of input:
58 * 87 *
@@ -126,6 +155,10 @@ do { \
126 yycolumn += yyleng; \ 155 yycolumn += yyleng; \
127} while (0); 156} while (0);
128 157
158#define USER_REJECT \
159 yycolumn -= yyleng; \
160 REJECT
161
129%} 162%}
130 163
131%x mem 164%x mem
@@ -136,8 +169,8 @@ do { \
136group [^,{}/]*[{][^}]*[}][^,{}/]* 169group [^,{}/]*[{][^}]*[}][^,{}/]*
137event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* 170event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
138event [^,{}/]+ 171event [^,{}/]+
139bpf_object [^,{}]+\.(o|bpf) 172bpf_object [^,{}]+\.(o|bpf)[a-zA-Z0-9._]*
140bpf_source [^,{}]+\.c 173bpf_source [^,{}]+\.c[a-zA-Z0-9._]*
141 174
142num_dec [0-9]+ 175num_dec [0-9]+
143num_hex 0x[a-fA-F0-9]+ 176num_hex 0x[a-fA-F0-9]+
@@ -146,7 +179,7 @@ name [a-zA-Z_*?][a-zA-Z0-9_*?.]*
146name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]* 179name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
147drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)? 180drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
148/* If you add a modifier you need to update check_modifier() */ 181/* If you add a modifier you need to update check_modifier() */
149modifier_event [ukhpPGHSDI]+ 182modifier_event [ukhpPGHSDIW]+
150modifier_bp [rwx]{1,3} 183modifier_bp [rwx]{1,3}
151 184
152%% 185%%
@@ -273,6 +306,7 @@ cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COU
273alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); } 306alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
274emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } 307emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
275dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); } 308dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
309duration_time { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
276bpf-output { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); } 310bpf-output { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); }
277 311
278 /* 312 /*
@@ -307,8 +341,8 @@ r{num_raw_hex} { return raw(yyscanner); }
307{num_hex} { return value(yyscanner, 16); } 341{num_hex} { return value(yyscanner, 16); }
308 342
309{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } 343{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
310{bpf_object} { return str(yyscanner, PE_BPF_OBJECT); } 344{bpf_object} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_OBJECT); }
311{bpf_source} { return str(yyscanner, PE_BPF_SOURCE); } 345{bpf_source} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_SOURCE); }
312{name} { return pmu_str_check(yyscanner); } 346{name} { return pmu_str_check(yyscanner); }
313"/" { BEGIN(config); return '/'; } 347"/" { BEGIN(config); return '/'; }
314- { return '-'; } 348- { return '-'; }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 04fd8c9af9f9..e81a20ea8d7d 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -1,5 +1,5 @@
1%pure-parser 1%pure-parser
2%parse-param {void *_data} 2%parse-param {void *_parse_state}
3%parse-param {void *scanner} 3%parse-param {void *scanner}
4%lex-param {void* scanner} 4%lex-param {void* scanner}
5%locations 5%locations
@@ -17,7 +17,7 @@
17#include "parse-events.h" 17#include "parse-events.h"
18#include "parse-events-bison.h" 18#include "parse-events-bison.h"
19 19
20void parse_events_error(YYLTYPE *loc, void *data, void *scanner, char const *msg); 20void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg);
21 21
22#define ABORT_ON(val) \ 22#define ABORT_ON(val) \
23do { \ 23do { \
@@ -33,11 +33,11 @@ do { \
33} while (0) 33} while (0)
34 34
35static void inc_group_count(struct list_head *list, 35static void inc_group_count(struct list_head *list,
36 struct parse_events_evlist *data) 36 struct parse_events_state *parse_state)
37{ 37{
38 /* Count groups only have more than 1 members */ 38 /* Count groups only have more than 1 members */
39 if (!list_is_last(list->next, list)) 39 if (!list_is_last(list->next, list))
40 data->nr_groups++; 40 parse_state->nr_groups++;
41} 41}
42 42
43%} 43%}
@@ -115,9 +115,9 @@ PE_START_TERMS start_terms
115 115
116start_events: groups 116start_events: groups
117{ 117{
118 struct parse_events_evlist *data = _data; 118 struct parse_events_state *parse_state = _parse_state;
119 119
120 parse_events_update_lists($1, &data->list); 120 parse_events_update_lists($1, &parse_state->list);
121} 121}
122 122
123groups: 123groups:
@@ -159,7 +159,7 @@ PE_NAME '{' events '}'
159{ 159{
160 struct list_head *list = $3; 160 struct list_head *list = $3;
161 161
162 inc_group_count(list, _data); 162 inc_group_count(list, _parse_state);
163 parse_events__set_leader($1, list); 163 parse_events__set_leader($1, list);
164 $$ = list; 164 $$ = list;
165} 165}
@@ -168,7 +168,7 @@ PE_NAME '{' events '}'
168{ 168{
169 struct list_head *list = $2; 169 struct list_head *list = $2;
170 170
171 inc_group_count(list, _data); 171 inc_group_count(list, _parse_state);
172 parse_events__set_leader(NULL, list); 172 parse_events__set_leader(NULL, list);
173 $$ = list; 173 $$ = list;
174} 174}
@@ -225,14 +225,13 @@ event_def: event_pmu |
225event_pmu: 225event_pmu:
226PE_NAME opt_event_config 226PE_NAME opt_event_config
227{ 227{
228 struct parse_events_evlist *data = _data;
229 struct list_head *list, *orig_terms, *terms; 228 struct list_head *list, *orig_terms, *terms;
230 229
231 if (parse_events_copy_term_list($2, &orig_terms)) 230 if (parse_events_copy_term_list($2, &orig_terms))
232 YYABORT; 231 YYABORT;
233 232
234 ALLOC_LIST(list); 233 ALLOC_LIST(list);
235 if (parse_events_add_pmu(data, list, $1, $2)) { 234 if (parse_events_add_pmu(_parse_state, list, $1, $2)) {
236 struct perf_pmu *pmu = NULL; 235 struct perf_pmu *pmu = NULL;
237 int ok = 0; 236 int ok = 0;
238 237
@@ -245,7 +244,7 @@ PE_NAME opt_event_config
245 if (!strncmp($1, name, strlen($1))) { 244 if (!strncmp($1, name, strlen($1))) {
246 if (parse_events_copy_term_list(orig_terms, &terms)) 245 if (parse_events_copy_term_list(orig_terms, &terms))
247 YYABORT; 246 YYABORT;
248 if (!parse_events_add_pmu(data, list, pmu->name, terms)) 247 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms))
249 ok++; 248 ok++;
250 parse_events_terms__delete(terms); 249 parse_events_terms__delete(terms);
251 } 250 }
@@ -262,7 +261,7 @@ PE_KERNEL_PMU_EVENT sep_dc
262{ 261{
263 struct list_head *list; 262 struct list_head *list;
264 263
265 if (parse_events_multi_pmu_add(_data, $1, &list) < 0) 264 if (parse_events_multi_pmu_add(_parse_state, $1, &list) < 0)
266 YYABORT; 265 YYABORT;
267 $$ = list; 266 $$ = list;
268} 267}
@@ -273,7 +272,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
273 char pmu_name[128]; 272 char pmu_name[128];
274 273
275 snprintf(&pmu_name, 128, "%s-%s", $1, $3); 274 snprintf(&pmu_name, 128, "%s-%s", $1, $3);
276 if (parse_events_multi_pmu_add(_data, pmu_name, &list) < 0) 275 if (parse_events_multi_pmu_add(_parse_state, pmu_name, &list) < 0)
277 YYABORT; 276 YYABORT;
278 $$ = list; 277 $$ = list;
279} 278}
@@ -286,62 +285,60 @@ PE_VALUE_SYM_SW
286event_legacy_symbol: 285event_legacy_symbol:
287value_sym '/' event_config '/' 286value_sym '/' event_config '/'
288{ 287{
289 struct parse_events_evlist *data = _data;
290 struct list_head *list; 288 struct list_head *list;
291 int type = $1 >> 16; 289 int type = $1 >> 16;
292 int config = $1 & 255; 290 int config = $1 & 255;
293 291
294 ALLOC_LIST(list); 292 ALLOC_LIST(list);
295 ABORT_ON(parse_events_add_numeric(data, list, type, config, $3)); 293 ABORT_ON(parse_events_add_numeric(_parse_state, list, type, config, $3));
296 parse_events_terms__delete($3); 294 parse_events_terms__delete($3);
297 $$ = list; 295 $$ = list;
298} 296}
299| 297|
300value_sym sep_slash_dc 298value_sym sep_slash_dc
301{ 299{
302 struct parse_events_evlist *data = _data;
303 struct list_head *list; 300 struct list_head *list;
304 int type = $1 >> 16; 301 int type = $1 >> 16;
305 int config = $1 & 255; 302 int config = $1 & 255;
306 303
307 ALLOC_LIST(list); 304 ALLOC_LIST(list);
308 ABORT_ON(parse_events_add_numeric(data, list, type, config, NULL)); 305 ABORT_ON(parse_events_add_numeric(_parse_state, list, type, config, NULL));
309 $$ = list; 306 $$ = list;
310} 307}
311 308
312event_legacy_cache: 309event_legacy_cache:
313PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_event_config 310PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_event_config
314{ 311{
315 struct parse_events_evlist *data = _data; 312 struct parse_events_state *parse_state = _parse_state;
316 struct parse_events_error *error = data->error; 313 struct parse_events_error *error = parse_state->error;
317 struct list_head *list; 314 struct list_head *list;
318 315
319 ALLOC_LIST(list); 316 ALLOC_LIST(list);
320 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5, error, $6)); 317 ABORT_ON(parse_events_add_cache(list, &parse_state->idx, $1, $3, $5, error, $6));
321 parse_events_terms__delete($6); 318 parse_events_terms__delete($6);
322 $$ = list; 319 $$ = list;
323} 320}
324| 321|
325PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config 322PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config
326{ 323{
327 struct parse_events_evlist *data = _data; 324 struct parse_events_state *parse_state = _parse_state;
328 struct parse_events_error *error = data->error; 325 struct parse_events_error *error = parse_state->error;
329 struct list_head *list; 326 struct list_head *list;
330 327
331 ALLOC_LIST(list); 328 ALLOC_LIST(list);
332 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL, error, $4)); 329 ABORT_ON(parse_events_add_cache(list, &parse_state->idx, $1, $3, NULL, error, $4));
333 parse_events_terms__delete($4); 330 parse_events_terms__delete($4);
334 $$ = list; 331 $$ = list;
335} 332}
336| 333|
337PE_NAME_CACHE_TYPE opt_event_config 334PE_NAME_CACHE_TYPE opt_event_config
338{ 335{
339 struct parse_events_evlist *data = _data; 336 struct parse_events_state *parse_state = _parse_state;
340 struct parse_events_error *error = data->error; 337 struct parse_events_error *error = parse_state->error;
341 struct list_head *list; 338 struct list_head *list;
342 339
343 ALLOC_LIST(list); 340 ALLOC_LIST(list);
344 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL, error, $2)); 341 ABORT_ON(parse_events_add_cache(list, &parse_state->idx, $1, NULL, NULL, error, $2));
345 parse_events_terms__delete($2); 342 parse_events_terms__delete($2);
346 $$ = list; 343 $$ = list;
347} 344}
@@ -349,44 +346,44 @@ PE_NAME_CACHE_TYPE opt_event_config
349event_legacy_mem: 346event_legacy_mem:
350PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc 347PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc
351{ 348{
352 struct parse_events_evlist *data = _data; 349 struct parse_events_state *parse_state = _parse_state;
353 struct list_head *list; 350 struct list_head *list;
354 351
355 ALLOC_LIST(list); 352 ALLOC_LIST(list);
356 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 353 ABORT_ON(parse_events_add_breakpoint(list, &parse_state->idx,
357 (void *) $2, $6, $4)); 354 (void *) $2, $6, $4));
358 $$ = list; 355 $$ = list;
359} 356}
360| 357|
361PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc 358PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc
362{ 359{
363 struct parse_events_evlist *data = _data; 360 struct parse_events_state *parse_state = _parse_state;
364 struct list_head *list; 361 struct list_head *list;
365 362
366 ALLOC_LIST(list); 363 ALLOC_LIST(list);
367 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 364 ABORT_ON(parse_events_add_breakpoint(list, &parse_state->idx,
368 (void *) $2, NULL, $4)); 365 (void *) $2, NULL, $4));
369 $$ = list; 366 $$ = list;
370} 367}
371| 368|
372PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 369PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
373{ 370{
374 struct parse_events_evlist *data = _data; 371 struct parse_events_state *parse_state = _parse_state;
375 struct list_head *list; 372 struct list_head *list;
376 373
377 ALLOC_LIST(list); 374 ALLOC_LIST(list);
378 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 375 ABORT_ON(parse_events_add_breakpoint(list, &parse_state->idx,
379 (void *) $2, $4, 0)); 376 (void *) $2, $4, 0));
380 $$ = list; 377 $$ = list;
381} 378}
382| 379|
383PE_PREFIX_MEM PE_VALUE sep_dc 380PE_PREFIX_MEM PE_VALUE sep_dc
384{ 381{
385 struct parse_events_evlist *data = _data; 382 struct parse_events_state *parse_state = _parse_state;
386 struct list_head *list; 383 struct list_head *list;
387 384
388 ALLOC_LIST(list); 385 ALLOC_LIST(list);
389 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 386 ABORT_ON(parse_events_add_breakpoint(list, &parse_state->idx,
390 (void *) $2, NULL, 0)); 387 (void *) $2, NULL, 0));
391 $$ = list; 388 $$ = list;
392} 389}
@@ -394,15 +391,15 @@ PE_PREFIX_MEM PE_VALUE sep_dc
394event_legacy_tracepoint: 391event_legacy_tracepoint:
395tracepoint_name opt_event_config 392tracepoint_name opt_event_config
396{ 393{
397 struct parse_events_evlist *data = _data; 394 struct parse_events_state *parse_state = _parse_state;
398 struct parse_events_error *error = data->error; 395 struct parse_events_error *error = parse_state->error;
399 struct list_head *list; 396 struct list_head *list;
400 397
401 ALLOC_LIST(list); 398 ALLOC_LIST(list);
402 if (error) 399 if (error)
403 error->idx = @1.first_column; 400 error->idx = @1.first_column;
404 401
405 if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event, 402 if (parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event,
406 error, $2)) 403 error, $2))
407 return -1; 404 return -1;
408 405
@@ -432,11 +429,10 @@ PE_NAME ':' PE_NAME
432event_legacy_numeric: 429event_legacy_numeric:
433PE_VALUE ':' PE_VALUE opt_event_config 430PE_VALUE ':' PE_VALUE opt_event_config
434{ 431{
435 struct parse_events_evlist *data = _data;
436 struct list_head *list; 432 struct list_head *list;
437 433
438 ALLOC_LIST(list); 434 ALLOC_LIST(list);
439 ABORT_ON(parse_events_add_numeric(data, list, (u32)$1, $3, $4)); 435 ABORT_ON(parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4));
440 parse_events_terms__delete($4); 436 parse_events_terms__delete($4);
441 $$ = list; 437 $$ = list;
442} 438}
@@ -444,11 +440,10 @@ PE_VALUE ':' PE_VALUE opt_event_config
444event_legacy_raw: 440event_legacy_raw:
445PE_RAW opt_event_config 441PE_RAW opt_event_config
446{ 442{
447 struct parse_events_evlist *data = _data;
448 struct list_head *list; 443 struct list_head *list;
449 444
450 ALLOC_LIST(list); 445 ALLOC_LIST(list);
451 ABORT_ON(parse_events_add_numeric(data, list, PERF_TYPE_RAW, $1, $2)); 446 ABORT_ON(parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, $1, $2));
452 parse_events_terms__delete($2); 447 parse_events_terms__delete($2);
453 $$ = list; 448 $$ = list;
454} 449}
@@ -456,23 +451,22 @@ PE_RAW opt_event_config
456event_bpf_file: 451event_bpf_file:
457PE_BPF_OBJECT opt_event_config 452PE_BPF_OBJECT opt_event_config
458{ 453{
459 struct parse_events_evlist *data = _data; 454 struct parse_events_state *parse_state = _parse_state;
460 struct parse_events_error *error = data->error; 455 struct parse_events_error *error = parse_state->error;
461 struct list_head *list; 456 struct list_head *list;
462 457
463 ALLOC_LIST(list); 458 ALLOC_LIST(list);
464 ABORT_ON(parse_events_load_bpf(data, list, $1, false, $2)); 459 ABORT_ON(parse_events_load_bpf(parse_state, list, $1, false, $2));
465 parse_events_terms__delete($2); 460 parse_events_terms__delete($2);
466 $$ = list; 461 $$ = list;
467} 462}
468| 463|
469PE_BPF_SOURCE opt_event_config 464PE_BPF_SOURCE opt_event_config
470{ 465{
471 struct parse_events_evlist *data = _data;
472 struct list_head *list; 466 struct list_head *list;
473 467
474 ALLOC_LIST(list); 468 ALLOC_LIST(list);
475 ABORT_ON(parse_events_load_bpf(data, list, $1, true, $2)); 469 ABORT_ON(parse_events_load_bpf(_parse_state, list, $1, true, $2));
476 parse_events_terms__delete($2); 470 parse_events_terms__delete($2);
477 $$ = list; 471 $$ = list;
478} 472}
@@ -494,8 +488,8 @@ opt_event_config:
494 488
495start_terms: event_config 489start_terms: event_config
496{ 490{
497 struct parse_events_terms *data = _data; 491 struct parse_events_state *parse_state = _parse_state;
498 data->terms = $1; 492 parse_state->terms = $1;
499} 493}
500 494
501event_config: 495event_config:
@@ -685,9 +679,9 @@ sep_slash_dc: '/' | ':' |
685 679
686%% 680%%
687 681
688void parse_events_error(YYLTYPE *loc, void *data, 682void parse_events_error(YYLTYPE *loc, void *parse_state,
689 void *scanner __maybe_unused, 683 void *scanner __maybe_unused,
690 char const *msg __maybe_unused) 684 char const *msg __maybe_unused)
691{ 685{
692 parse_events_evlist_error(data, loc->last_column, "parser error"); 686 parse_events_evlist_error(parse_state, loc->last_column, "parser error");
693} 687}
diff --git a/tools/perf/util/parse-regs-options.c b/tools/perf/util/parse-regs-options.c
index 646ecf736aad..e6599e290f46 100644
--- a/tools/perf/util/parse-regs-options.c
+++ b/tools/perf/util/parse-regs-options.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "perf.h" 2#include "perf.h"
2#include "util/util.h" 3#include "util/util.h"
3#include "util/debug.h" 4#include "util/debug.h"
diff --git a/tools/perf/util/parse-regs-options.h b/tools/perf/util/parse-regs-options.h
index 7d762b188007..cdefb1acf6be 100644
--- a/tools/perf/util/parse-regs-options.h
+++ b/tools/perf/util/parse-regs-options.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_PARSE_REGS_OPTIONS_H 2#ifndef _PERF_PARSE_REGS_OPTIONS_H
2#define _PERF_PARSE_REGS_OPTIONS_H 1 3#define _PERF_PARSE_REGS_OPTIONS_H 1
3struct option; 4struct option;
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index 50ec3bc87a60..933f5c6bffb4 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * I'm tired of doing "vsnprintf()" etc just to open a 3 * I'm tired of doing "vsnprintf()" etc just to open a
3 * file, so here's a "return static buffer with printf" 4 * file, so here's a "return static buffer with printf"
diff --git a/tools/perf/util/path.h b/tools/perf/util/path.h
index 9a276a58e3c2..14a254ada7eb 100644
--- a/tools/perf/util/path.h
+++ b/tools/perf/util/path.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_PATH_H 2#ifndef _PERF_PATH_H
2#define _PERF_PATH_H 3#define _PERF_PATH_H
3 4
diff --git a/tools/perf/util/perf-hooks.c b/tools/perf/util/perf-hooks.c
index d55092964da2..4f3aa8d99ef4 100644
--- a/tools/perf/util/perf-hooks.c
+++ b/tools/perf/util/perf-hooks.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * perf_hooks.c 3 * perf_hooks.c
3 * 4 *
diff --git a/tools/perf/util/perf-hooks.h b/tools/perf/util/perf-hooks.h
index 838d5797bc1e..27fbec62d4fe 100644
--- a/tools/perf/util/perf-hooks.h
+++ b/tools/perf/util/perf-hooks.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PERF_UTIL_PERF_HOOKS_H 2#ifndef PERF_UTIL_PERF_HOOKS_H
2#define PERF_UTIL_PERF_HOOKS_H 3#define PERF_UTIL_PERF_HOOKS_H
3 4
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index b2ae039eff85..2acfcc527cac 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include "perf_regs.h" 3#include "perf_regs.h"
3#include "event.h" 4#include "event.h"
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 32b37d19dcc3..c9319f8d17a6 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_REGS_H 2#ifndef __PERF_REGS_H
2#define __PERF_REGS_H 3#define __PERF_REGS_H
3 4
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index ac16a9db1fb5..07cb2ac041d7 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -1,7 +1,9 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/list.h> 2#include <linux/list.h>
2#include <linux/compiler.h> 3#include <linux/compiler.h>
3#include <sys/types.h> 4#include <sys/types.h>
4#include <errno.h> 5#include <errno.h>
6#include <fcntl.h>
5#include <sys/stat.h> 7#include <sys/stat.h>
6#include <unistd.h> 8#include <unistd.h>
7#include <stdio.h> 9#include <stdio.h>
@@ -470,17 +472,36 @@ static void pmu_read_sysfs(void)
470 closedir(dir); 472 closedir(dir);
471} 473}
472 474
475static struct cpu_map *__pmu_cpumask(const char *path)
476{
477 FILE *file;
478 struct cpu_map *cpus;
479
480 file = fopen(path, "r");
481 if (!file)
482 return NULL;
483
484 cpus = cpu_map__read(file);
485 fclose(file);
486 return cpus;
487}
488
489/*
490 * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64)
491 * may have a "cpus" file.
492 */
493#define CPUS_TEMPLATE_UNCORE "%s/bus/event_source/devices/%s/cpumask"
494#define CPUS_TEMPLATE_CPU "%s/bus/event_source/devices/%s/cpus"
495
473static struct cpu_map *pmu_cpumask(const char *name) 496static struct cpu_map *pmu_cpumask(const char *name)
474{ 497{
475 struct stat st;
476 char path[PATH_MAX]; 498 char path[PATH_MAX];
477 FILE *file;
478 struct cpu_map *cpus; 499 struct cpu_map *cpus;
479 const char *sysfs = sysfs__mountpoint(); 500 const char *sysfs = sysfs__mountpoint();
480 const char *templates[] = { 501 const char *templates[] = {
481 "%s/bus/event_source/devices/%s/cpumask", 502 CPUS_TEMPLATE_UNCORE,
482 "%s/bus/event_source/devices/%s/cpus", 503 CPUS_TEMPLATE_CPU,
483 NULL 504 NULL
484 }; 505 };
485 const char **template; 506 const char **template;
486 507
@@ -489,20 +510,25 @@ static struct cpu_map *pmu_cpumask(const char *name)
489 510
490 for (template = templates; *template; template++) { 511 for (template = templates; *template; template++) {
491 snprintf(path, PATH_MAX, *template, sysfs, name); 512 snprintf(path, PATH_MAX, *template, sysfs, name);
492 if (stat(path, &st) == 0) 513 cpus = __pmu_cpumask(path);
493 break; 514 if (cpus)
515 return cpus;
494 } 516 }
495 517
496 if (!*template) 518 return NULL;
497 return NULL; 519}
498 520
499 file = fopen(path, "r"); 521static bool pmu_is_uncore(const char *name)
500 if (!file) 522{
501 return NULL; 523 char path[PATH_MAX];
524 struct cpu_map *cpus;
525 const char *sysfs = sysfs__mountpoint();
502 526
503 cpus = cpu_map__read(file); 527 snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name);
504 fclose(file); 528 cpus = __pmu_cpumask(path);
505 return cpus; 529 cpu_map__put(cpus);
530
531 return !!cpus;
506} 532}
507 533
508/* 534/*
@@ -516,16 +542,8 @@ char * __weak get_cpuid_str(void)
516 return NULL; 542 return NULL;
517} 543}
518 544
519/* 545static char *perf_pmu__getcpuid(void)
520 * From the pmu_events_map, find the table of PMU events that corresponds
521 * to the current running CPU. Then, add all PMU events from that table
522 * as aliases.
523 */
524static void pmu_add_cpu_aliases(struct list_head *head, const char *name)
525{ 546{
526 int i;
527 struct pmu_events_map *map;
528 struct pmu_event *pe;
529 char *cpuid; 547 char *cpuid;
530 static bool printed; 548 static bool printed;
531 549
@@ -535,22 +553,50 @@ static void pmu_add_cpu_aliases(struct list_head *head, const char *name)
535 if (!cpuid) 553 if (!cpuid)
536 cpuid = get_cpuid_str(); 554 cpuid = get_cpuid_str();
537 if (!cpuid) 555 if (!cpuid)
538 return; 556 return NULL;
539 557
540 if (!printed) { 558 if (!printed) {
541 pr_debug("Using CPUID %s\n", cpuid); 559 pr_debug("Using CPUID %s\n", cpuid);
542 printed = true; 560 printed = true;
543 } 561 }
562 return cpuid;
563}
564
565struct pmu_events_map *perf_pmu__find_map(void)
566{
567 struct pmu_events_map *map;
568 char *cpuid = perf_pmu__getcpuid();
569 int i;
544 570
545 i = 0; 571 i = 0;
546 while (1) { 572 for (;;) {
547 map = &pmu_events_map[i++]; 573 map = &pmu_events_map[i++];
548 if (!map->table) 574 if (!map->table) {
549 goto out; 575 map = NULL;
576 break;
577 }
550 578
551 if (!strcmp(map->cpuid, cpuid)) 579 if (!strcmp(map->cpuid, cpuid))
552 break; 580 break;
553 } 581 }
582 free(cpuid);
583 return map;
584}
585
586/*
587 * From the pmu_events_map, find the table of PMU events that corresponds
588 * to the current running CPU. Then, add all PMU events from that table
589 * as aliases.
590 */
591static void pmu_add_cpu_aliases(struct list_head *head, const char *name)
592{
593 int i;
594 struct pmu_events_map *map;
595 struct pmu_event *pe;
596
597 map = perf_pmu__find_map();
598 if (!map)
599 return;
554 600
555 /* 601 /*
556 * Found a matching PMU events table. Create aliases 602 * Found a matching PMU events table. Create aliases
@@ -560,8 +606,11 @@ static void pmu_add_cpu_aliases(struct list_head *head, const char *name)
560 const char *pname; 606 const char *pname;
561 607
562 pe = &map->table[i++]; 608 pe = &map->table[i++];
563 if (!pe->name) 609 if (!pe->name) {
610 if (pe->metric_group || pe->metric_name)
611 continue;
564 break; 612 break;
613 }
565 614
566 pname = pe->pmu ? pe->pmu : "cpu"; 615 pname = pe->pmu ? pe->pmu : "cpu";
567 if (strncmp(pname, name, strlen(pname))) 616 if (strncmp(pname, name, strlen(pname)))
@@ -575,9 +624,6 @@ static void pmu_add_cpu_aliases(struct list_head *head, const char *name)
575 (char *)pe->metric_expr, 624 (char *)pe->metric_expr,
576 (char *)pe->metric_name); 625 (char *)pe->metric_name);
577 } 626 }
578
579out:
580 free(cpuid);
581} 627}
582 628
583struct perf_event_attr * __weak 629struct perf_event_attr * __weak
@@ -617,6 +663,8 @@ static struct perf_pmu *pmu_lookup(const char *name)
617 663
618 pmu->cpus = pmu_cpumask(name); 664 pmu->cpus = pmu_cpumask(name);
619 665
666 pmu->is_uncore = pmu_is_uncore(name);
667
620 INIT_LIST_HEAD(&pmu->format); 668 INIT_LIST_HEAD(&pmu->format);
621 INIT_LIST_HEAD(&pmu->aliases); 669 INIT_LIST_HEAD(&pmu->aliases);
622 list_splice(&format, &pmu->format); 670 list_splice(&format, &pmu->format);
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 389e9729331f..27c75e635866 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PMU_H 2#ifndef __PMU_H
2#define __PMU_H 3#define __PMU_H
3 4
@@ -22,6 +23,7 @@ struct perf_pmu {
22 char *name; 23 char *name;
23 __u32 type; 24 __u32 type;
24 bool selectable; 25 bool selectable;
26 bool is_uncore;
25 struct perf_event_attr *default_config; 27 struct perf_event_attr *default_config;
26 struct cpu_map *cpus; 28 struct cpu_map *cpus;
27 struct list_head format; /* HEAD struct perf_pmu_format -> list */ 29 struct list_head format; /* HEAD struct perf_pmu_format -> list */
@@ -90,4 +92,6 @@ int perf_pmu__test(void);
90 92
91struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu); 93struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
92 94
95struct pmu_events_map *perf_pmu__find_map(void);
96
93#endif /* __PMU_H */ 97#endif /* __PMU_H */
diff --git a/tools/perf/util/print_binary.c b/tools/perf/util/print_binary.c
index e908177b9976..23e367063446 100644
--- a/tools/perf/util/print_binary.c
+++ b/tools/perf/util/print_binary.c
@@ -1,41 +1,44 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "print_binary.h" 2#include "print_binary.h"
2#include <linux/log2.h> 3#include <linux/log2.h>
3#include "sane_ctype.h" 4#include "sane_ctype.h"
4 5
5void print_binary(unsigned char *data, size_t len, 6int binary__fprintf(unsigned char *data, size_t len,
6 size_t bytes_per_line, print_binary_t printer, 7 size_t bytes_per_line, binary__fprintf_t printer,
7 void *extra) 8 void *extra, FILE *fp)
8{ 9{
9 size_t i, j, mask; 10 size_t i, j, mask;
11 int printed = 0;
10 12
11 if (!printer) 13 if (!printer)
12 return; 14 return 0;
13 15
14 bytes_per_line = roundup_pow_of_two(bytes_per_line); 16 bytes_per_line = roundup_pow_of_two(bytes_per_line);
15 mask = bytes_per_line - 1; 17 mask = bytes_per_line - 1;
16 18
17 printer(BINARY_PRINT_DATA_BEGIN, 0, extra); 19 printed += printer(BINARY_PRINT_DATA_BEGIN, 0, extra, fp);
18 for (i = 0; i < len; i++) { 20 for (i = 0; i < len; i++) {
19 if ((i & mask) == 0) { 21 if ((i & mask) == 0) {
20 printer(BINARY_PRINT_LINE_BEGIN, -1, extra); 22 printed += printer(BINARY_PRINT_LINE_BEGIN, -1, extra, fp);
21 printer(BINARY_PRINT_ADDR, i, extra); 23 printed += printer(BINARY_PRINT_ADDR, i, extra, fp);
22 } 24 }
23 25
24 printer(BINARY_PRINT_NUM_DATA, data[i], extra); 26 printed += printer(BINARY_PRINT_NUM_DATA, data[i], extra, fp);
25 27
26 if (((i & mask) == mask) || i == len - 1) { 28 if (((i & mask) == mask) || i == len - 1) {
27 for (j = 0; j < mask-(i & mask); j++) 29 for (j = 0; j < mask-(i & mask); j++)
28 printer(BINARY_PRINT_NUM_PAD, -1, extra); 30 printed += printer(BINARY_PRINT_NUM_PAD, -1, extra, fp);
29 31
30 printer(BINARY_PRINT_SEP, i, extra); 32 printer(BINARY_PRINT_SEP, i, extra, fp);
31 for (j = i & ~mask; j <= i; j++) 33 for (j = i & ~mask; j <= i; j++)
32 printer(BINARY_PRINT_CHAR_DATA, data[j], extra); 34 printed += printer(BINARY_PRINT_CHAR_DATA, data[j], extra, fp);
33 for (j = 0; j < mask-(i & mask); j++) 35 for (j = 0; j < mask-(i & mask); j++)
34 printer(BINARY_PRINT_CHAR_PAD, i, extra); 36 printed += printer(BINARY_PRINT_CHAR_PAD, i, extra, fp);
35 printer(BINARY_PRINT_LINE_END, -1, extra); 37 printed += printer(BINARY_PRINT_LINE_END, -1, extra, fp);
36 } 38 }
37 } 39 }
38 printer(BINARY_PRINT_DATA_END, -1, extra); 40 printed += printer(BINARY_PRINT_DATA_END, -1, extra, fp);
41 return printed;
39} 42}
40 43
41int is_printable_array(char *p, unsigned int len) 44int is_printable_array(char *p, unsigned int len)
diff --git a/tools/perf/util/print_binary.h b/tools/perf/util/print_binary.h
index da0427263d2d..2a1554afc957 100644
--- a/tools/perf/util/print_binary.h
+++ b/tools/perf/util/print_binary.h
@@ -1,7 +1,9 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PERF_PRINT_BINARY_H 2#ifndef PERF_PRINT_BINARY_H
2#define PERF_PRINT_BINARY_H 3#define PERF_PRINT_BINARY_H
3 4
4#include <stddef.h> 5#include <stddef.h>
6#include <stdio.h>
5 7
6enum binary_printer_ops { 8enum binary_printer_ops {
7 BINARY_PRINT_DATA_BEGIN, 9 BINARY_PRINT_DATA_BEGIN,
@@ -16,12 +18,19 @@ enum binary_printer_ops {
16 BINARY_PRINT_DATA_END, 18 BINARY_PRINT_DATA_END,
17}; 19};
18 20
19typedef void (*print_binary_t)(enum binary_printer_ops op, 21typedef int (*binary__fprintf_t)(enum binary_printer_ops op,
20 unsigned int val, void *extra); 22 unsigned int val, void *extra, FILE *fp);
21 23
22void print_binary(unsigned char *data, size_t len, 24int binary__fprintf(unsigned char *data, size_t len,
23 size_t bytes_per_line, print_binary_t printer, 25 size_t bytes_per_line, binary__fprintf_t printer,
24 void *extra); 26 void *extra, FILE *fp);
27
28static inline void print_binary(unsigned char *data, size_t len,
29 size_t bytes_per_line, binary__fprintf_t printer,
30 void *extra)
31{
32 binary__fprintf(data, len, bytes_per_line, printer, extra, stdout);
33}
25 34
26int is_printable_array(char *p, unsigned int len); 35int is_printable_array(char *p, unsigned int len);
27 36
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index a2670e9d652d..b7aaf9b2294d 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -184,13 +184,19 @@ static struct map *kernel_get_module_map(const char *module)
184 return NULL; 184 return NULL;
185} 185}
186 186
187struct map *get_target_map(const char *target, bool user) 187struct map *get_target_map(const char *target, struct nsinfo *nsi, bool user)
188{ 188{
189 /* Init maps of given executable or kernel */ 189 /* Init maps of given executable or kernel */
190 if (user) 190 if (user) {
191 return dso__new_map(target); 191 struct map *map;
192 else 192
193 map = dso__new_map(target);
194 if (map && map->dso)
195 map->dso->nsinfo = nsinfo__get(nsi);
196 return map;
197 } else {
193 return kernel_get_module_map(target); 198 return kernel_get_module_map(target);
199 }
194} 200}
195 201
196static int convert_exec_to_group(const char *exec, char **result) 202static int convert_exec_to_group(const char *exec, char **result)
@@ -366,7 +372,8 @@ found:
366static int find_alternative_probe_point(struct debuginfo *dinfo, 372static int find_alternative_probe_point(struct debuginfo *dinfo,
367 struct perf_probe_point *pp, 373 struct perf_probe_point *pp,
368 struct perf_probe_point *result, 374 struct perf_probe_point *result,
369 const char *target, bool uprobes) 375 const char *target, struct nsinfo *nsi,
376 bool uprobes)
370{ 377{
371 struct map *map = NULL; 378 struct map *map = NULL;
372 struct symbol *sym; 379 struct symbol *sym;
@@ -377,7 +384,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
377 if (!pp->function || pp->file) 384 if (!pp->function || pp->file)
378 return -ENOTSUP; 385 return -ENOTSUP;
379 386
380 map = get_target_map(target, uprobes); 387 map = get_target_map(target, nsi, uprobes);
381 if (!map) 388 if (!map)
382 return -EINVAL; 389 return -EINVAL;
383 390
@@ -421,8 +428,8 @@ static int get_alternative_probe_event(struct debuginfo *dinfo,
421 428
422 memcpy(tmp, &pev->point, sizeof(*tmp)); 429 memcpy(tmp, &pev->point, sizeof(*tmp));
423 memset(&pev->point, 0, sizeof(pev->point)); 430 memset(&pev->point, 0, sizeof(pev->point));
424 ret = find_alternative_probe_point(dinfo, tmp, &pev->point, 431 ret = find_alternative_probe_point(dinfo, tmp, &pev->point, pev->target,
425 pev->target, pev->uprobes); 432 pev->nsi, pev->uprobes);
426 if (ret < 0) 433 if (ret < 0)
427 memcpy(&pev->point, tmp, sizeof(*tmp)); 434 memcpy(&pev->point, tmp, sizeof(*tmp));
428 435
@@ -444,7 +451,7 @@ static int get_alternative_line_range(struct debuginfo *dinfo,
444 if (lr->end != INT_MAX) 451 if (lr->end != INT_MAX)
445 len = lr->end - lr->start; 452 len = lr->end - lr->start;
446 ret = find_alternative_probe_point(dinfo, &pp, &result, 453 ret = find_alternative_probe_point(dinfo, &pp, &result,
447 target, user); 454 target, NULL, user);
448 if (!ret) { 455 if (!ret) {
449 lr->function = result.function; 456 lr->function = result.function;
450 lr->file = result.file; 457 lr->file = result.file;
@@ -457,12 +464,14 @@ static int get_alternative_line_range(struct debuginfo *dinfo,
457} 464}
458 465
459/* Open new debuginfo of given module */ 466/* Open new debuginfo of given module */
460static struct debuginfo *open_debuginfo(const char *module, bool silent) 467static struct debuginfo *open_debuginfo(const char *module, struct nsinfo *nsi,
468 bool silent)
461{ 469{
462 const char *path = module; 470 const char *path = module;
463 char reason[STRERR_BUFSIZE]; 471 char reason[STRERR_BUFSIZE];
464 struct debuginfo *ret = NULL; 472 struct debuginfo *ret = NULL;
465 struct dso *dso = NULL; 473 struct dso *dso = NULL;
474 struct nscookie nsc;
466 int err; 475 int err;
467 476
468 if (!module || !strchr(module, '/')) { 477 if (!module || !strchr(module, '/')) {
@@ -480,6 +489,7 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent)
480 } 489 }
481 path = dso->long_name; 490 path = dso->long_name;
482 } 491 }
492 nsinfo__mountns_enter(nsi, &nsc);
483 ret = debuginfo__new(path); 493 ret = debuginfo__new(path);
484 if (!ret && !silent) { 494 if (!ret && !silent) {
485 pr_warning("The %s file has no debug information.\n", path); 495 pr_warning("The %s file has no debug information.\n", path);
@@ -489,6 +499,7 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent)
489 pr_warning("Rebuild with -g, "); 499 pr_warning("Rebuild with -g, ");
490 pr_warning("or install an appropriate debuginfo package.\n"); 500 pr_warning("or install an appropriate debuginfo package.\n");
491 } 501 }
502 nsinfo__mountns_exit(&nsc);
492 return ret; 503 return ret;
493} 504}
494 505
@@ -516,7 +527,7 @@ static struct debuginfo *debuginfo_cache__open(const char *module, bool silent)
516 goto out; 527 goto out;
517 } 528 }
518 529
519 debuginfo_cache = open_debuginfo(module, silent); 530 debuginfo_cache = open_debuginfo(module, NULL, silent);
520 if (!debuginfo_cache) 531 if (!debuginfo_cache)
521 zfree(&debuginfo_cache_path); 532 zfree(&debuginfo_cache_path);
522out: 533out:
@@ -531,14 +542,18 @@ static void debuginfo_cache__exit(void)
531} 542}
532 543
533 544
534static int get_text_start_address(const char *exec, unsigned long *address) 545static int get_text_start_address(const char *exec, unsigned long *address,
546 struct nsinfo *nsi)
535{ 547{
536 Elf *elf; 548 Elf *elf;
537 GElf_Ehdr ehdr; 549 GElf_Ehdr ehdr;
538 GElf_Shdr shdr; 550 GElf_Shdr shdr;
539 int fd, ret = -ENOENT; 551 int fd, ret = -ENOENT;
552 struct nscookie nsc;
540 553
554 nsinfo__mountns_enter(nsi, &nsc);
541 fd = open(exec, O_RDONLY); 555 fd = open(exec, O_RDONLY);
556 nsinfo__mountns_exit(&nsc);
542 if (fd < 0) 557 if (fd < 0)
543 return -errno; 558 return -errno;
544 559
@@ -582,7 +597,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
582 ret = -EINVAL; 597 ret = -EINVAL;
583 goto error; 598 goto error;
584 } 599 }
585 ret = get_text_start_address(tp->module, &stext); 600 ret = get_text_start_address(tp->module, &stext, NULL);
586 if (ret < 0) 601 if (ret < 0)
587 goto error; 602 goto error;
588 addr += stext; 603 addr += stext;
@@ -659,7 +674,7 @@ post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
659 674
660 /* Prepare a map for offline binary */ 675 /* Prepare a map for offline binary */
661 map = dso__new_map(pathname); 676 map = dso__new_map(pathname);
662 if (!map || get_text_start_address(pathname, &stext) < 0) { 677 if (!map || get_text_start_address(pathname, &stext, NULL) < 0) {
663 pr_warning("Failed to get ELF symbols for %s\n", pathname); 678 pr_warning("Failed to get ELF symbols for %s\n", pathname);
664 return -EINVAL; 679 return -EINVAL;
665 } 680 }
@@ -676,7 +691,8 @@ post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
676} 691}
677 692
678static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, 693static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
679 int ntevs, const char *exec) 694 int ntevs, const char *exec,
695 struct nsinfo *nsi)
680{ 696{
681 int i, ret = 0; 697 int i, ret = 0;
682 unsigned long stext = 0; 698 unsigned long stext = 0;
@@ -684,7 +700,7 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
684 if (!exec) 700 if (!exec)
685 return 0; 701 return 0;
686 702
687 ret = get_text_start_address(exec, &stext); 703 ret = get_text_start_address(exec, &stext, nsi);
688 if (ret < 0) 704 if (ret < 0)
689 return ret; 705 return ret;
690 706
@@ -715,7 +731,7 @@ post_process_module_probe_trace_events(struct probe_trace_event *tevs,
715 if (!module) 731 if (!module)
716 return 0; 732 return 0;
717 733
718 map = get_target_map(module, false); 734 map = get_target_map(module, NULL, false);
719 if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) { 735 if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) {
720 pr_warning("Failed to get ELF symbols for %s\n", module); 736 pr_warning("Failed to get ELF symbols for %s\n", module);
721 return -EINVAL; 737 return -EINVAL;
@@ -802,7 +818,8 @@ static int post_process_probe_trace_events(struct perf_probe_event *pev,
802 int ret; 818 int ret;
803 819
804 if (uprobe) 820 if (uprobe)
805 ret = add_exec_to_probe_trace_events(tevs, ntevs, module); 821 ret = add_exec_to_probe_trace_events(tevs, ntevs, module,
822 pev->nsi);
806 else if (module) 823 else if (module)
807 /* Currently ref_reloc_sym based probe is not for drivers */ 824 /* Currently ref_reloc_sym based probe is not for drivers */
808 ret = post_process_module_probe_trace_events(tevs, ntevs, 825 ret = post_process_module_probe_trace_events(tevs, ntevs,
@@ -825,7 +842,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
825 struct debuginfo *dinfo; 842 struct debuginfo *dinfo;
826 int ntevs, ret = 0; 843 int ntevs, ret = 0;
827 844
828 dinfo = open_debuginfo(pev->target, !need_dwarf); 845 dinfo = open_debuginfo(pev->target, pev->nsi, !need_dwarf);
829 if (!dinfo) { 846 if (!dinfo) {
830 if (need_dwarf) 847 if (need_dwarf)
831 return -ENOENT; 848 return -ENOENT;
@@ -945,7 +962,7 @@ static int __show_line_range(struct line_range *lr, const char *module,
945 char sbuf[STRERR_BUFSIZE]; 962 char sbuf[STRERR_BUFSIZE];
946 963
947 /* Search a line range */ 964 /* Search a line range */
948 dinfo = open_debuginfo(module, false); 965 dinfo = open_debuginfo(module, NULL, false);
949 if (!dinfo) 966 if (!dinfo)
950 return -ENOENT; 967 return -ENOENT;
951 968
@@ -1021,14 +1038,18 @@ end:
1021 return ret; 1038 return ret;
1022} 1039}
1023 1040
1024int show_line_range(struct line_range *lr, const char *module, bool user) 1041int show_line_range(struct line_range *lr, const char *module,
1042 struct nsinfo *nsi, bool user)
1025{ 1043{
1026 int ret; 1044 int ret;
1045 struct nscookie nsc;
1027 1046
1028 ret = init_probe_symbol_maps(user); 1047 ret = init_probe_symbol_maps(user);
1029 if (ret < 0) 1048 if (ret < 0)
1030 return ret; 1049 return ret;
1050 nsinfo__mountns_enter(nsi, &nsc);
1031 ret = __show_line_range(lr, module, user); 1051 ret = __show_line_range(lr, module, user);
1052 nsinfo__mountns_exit(&nsc);
1032 exit_probe_symbol_maps(); 1053 exit_probe_symbol_maps();
1033 1054
1034 return ret; 1055 return ret;
@@ -1111,7 +1132,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
1111 if (ret < 0) 1132 if (ret < 0)
1112 return ret; 1133 return ret;
1113 1134
1114 dinfo = open_debuginfo(pevs->target, false); 1135 dinfo = open_debuginfo(pevs->target, pevs->nsi, false);
1115 if (!dinfo) { 1136 if (!dinfo) {
1116 ret = -ENOENT; 1137 ret = -ENOENT;
1117 goto out; 1138 goto out;
@@ -1155,6 +1176,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
1155 1176
1156int show_line_range(struct line_range *lr __maybe_unused, 1177int show_line_range(struct line_range *lr __maybe_unused,
1157 const char *module __maybe_unused, 1178 const char *module __maybe_unused,
1179 struct nsinfo *nsi __maybe_unused,
1158 bool user __maybe_unused) 1180 bool user __maybe_unused)
1159{ 1181{
1160 pr_warning("Debuginfo-analysis is not supported.\n"); 1182 pr_warning("Debuginfo-analysis is not supported.\n");
@@ -2373,7 +2395,7 @@ kprobe_blacklist__find_by_address(struct list_head *blacklist,
2373 struct kprobe_blacklist_node *node; 2395 struct kprobe_blacklist_node *node;
2374 2396
2375 list_for_each_entry(node, blacklist, list) { 2397 list_for_each_entry(node, blacklist, list) {
2376 if (node->start <= address && address <= node->end) 2398 if (node->start <= address && address < node->end)
2377 return node; 2399 return node;
2378 } 2400 }
2379 2401
@@ -2703,6 +2725,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2703 struct probe_trace_event *tev = NULL; 2725 struct probe_trace_event *tev = NULL;
2704 struct probe_cache *cache = NULL; 2726 struct probe_cache *cache = NULL;
2705 struct strlist *namelist[2] = {NULL, NULL}; 2727 struct strlist *namelist[2] = {NULL, NULL};
2728 struct nscookie nsc;
2706 2729
2707 up = pev->uprobes ? 1 : 0; 2730 up = pev->uprobes ? 1 : 0;
2708 fd[up] = __open_probe_file_and_namelist(up, &namelist[up]); 2731 fd[up] = __open_probe_file_and_namelist(up, &namelist[up]);
@@ -2729,7 +2752,9 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2729 if (ret < 0) 2752 if (ret < 0)
2730 break; 2753 break;
2731 2754
2755 nsinfo__mountns_enter(pev->nsi, &nsc);
2732 ret = probe_file__add_event(fd[up], tev); 2756 ret = probe_file__add_event(fd[up], tev);
2757 nsinfo__mountns_exit(&nsc);
2733 if (ret < 0) 2758 if (ret < 0)
2734 break; 2759 break;
2735 2760
@@ -2744,7 +2769,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2744 if (ret == -EINVAL && pev->uprobes) 2769 if (ret == -EINVAL && pev->uprobes)
2745 warn_uprobe_event_compat(tev); 2770 warn_uprobe_event_compat(tev);
2746 if (ret == 0 && probe_conf.cache) { 2771 if (ret == 0 && probe_conf.cache) {
2747 cache = probe_cache__new(pev->target); 2772 cache = probe_cache__new(pev->target, pev->nsi);
2748 if (!cache || 2773 if (!cache ||
2749 probe_cache__add_entry(cache, pev, tevs, ntevs) < 0 || 2774 probe_cache__add_entry(cache, pev, tevs, ntevs) < 0 ||
2750 probe_cache__commit(cache) < 0) 2775 probe_cache__commit(cache) < 0)
@@ -2805,7 +2830,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2805 int ret, i, j, skipped = 0; 2830 int ret, i, j, skipped = 0;
2806 char *mod_name; 2831 char *mod_name;
2807 2832
2808 map = get_target_map(pev->target, pev->uprobes); 2833 map = get_target_map(pev->target, pev->nsi, pev->uprobes);
2809 if (!map) { 2834 if (!map) {
2810 ret = -EINVAL; 2835 ret = -EINVAL;
2811 goto out; 2836 goto out;
@@ -3094,7 +3119,7 @@ static int find_cached_events(struct perf_probe_event *pev,
3094 int ntevs = 0; 3119 int ntevs = 0;
3095 int ret = 0; 3120 int ret = 0;
3096 3121
3097 cache = probe_cache__new(target); 3122 cache = probe_cache__new(target, pev->nsi);
3098 /* Return 0 ("not found") if the target has no probe cache. */ 3123 /* Return 0 ("not found") if the target has no probe cache. */
3099 if (!cache) 3124 if (!cache)
3100 return 0; 3125 return 0;
@@ -3184,7 +3209,7 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
3184 else 3209 else
3185 return find_cached_events(pev, tevs, pev->target); 3210 return find_cached_events(pev, tevs, pev->target);
3186 } 3211 }
3187 cache = probe_cache__new(pev->target); 3212 cache = probe_cache__new(pev->target, pev->nsi);
3188 if (!cache) 3213 if (!cache)
3189 return 0; 3214 return 0;
3190 3215
@@ -3345,13 +3370,16 @@ int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs)
3345void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs) 3370void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs)
3346{ 3371{
3347 int i, j; 3372 int i, j;
3373 struct perf_probe_event *pev;
3348 3374
3349 /* Loop 3: cleanup and free trace events */ 3375 /* Loop 3: cleanup and free trace events */
3350 for (i = 0; i < npevs; i++) { 3376 for (i = 0; i < npevs; i++) {
3377 pev = &pevs[i];
3351 for (j = 0; j < pevs[i].ntevs; j++) 3378 for (j = 0; j < pevs[i].ntevs; j++)
3352 clear_probe_trace_event(&pevs[i].tevs[j]); 3379 clear_probe_trace_event(&pevs[i].tevs[j]);
3353 zfree(&pevs[i].tevs); 3380 zfree(&pevs[i].tevs);
3354 pevs[i].ntevs = 0; 3381 pevs[i].ntevs = 0;
3382 nsinfo__zput(pev->nsi);
3355 clear_perf_probe_event(&pevs[i]); 3383 clear_perf_probe_event(&pevs[i]);
3356 } 3384 }
3357} 3385}
@@ -3409,8 +3437,8 @@ out:
3409 return ret; 3437 return ret;
3410} 3438}
3411 3439
3412int show_available_funcs(const char *target, struct strfilter *_filter, 3440int show_available_funcs(const char *target, struct nsinfo *nsi,
3413 bool user) 3441 struct strfilter *_filter, bool user)
3414{ 3442{
3415 struct rb_node *nd; 3443 struct rb_node *nd;
3416 struct map *map; 3444 struct map *map;
@@ -3421,7 +3449,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
3421 return ret; 3449 return ret;
3422 3450
3423 /* Get a symbol map */ 3451 /* Get a symbol map */
3424 map = get_target_map(target, user); 3452 map = get_target_map(target, nsi, user);
3425 if (!map) { 3453 if (!map) {
3426 pr_err("Failed to get a map for %s\n", (target) ? : "kernel"); 3454 pr_err("Failed to get a map for %s\n", (target) ? : "kernel");
3427 return -EINVAL; 3455 return -EINVAL;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 5812947418dd..45b14f020558 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -1,9 +1,11 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PROBE_EVENT_H 2#ifndef _PROBE_EVENT_H
2#define _PROBE_EVENT_H 3#define _PROBE_EVENT_H
3 4
4#include <linux/compiler.h> 5#include <linux/compiler.h>
5#include <stdbool.h> 6#include <stdbool.h>
6#include "intlist.h" 7#include "intlist.h"
8#include "namespaces.h"
7 9
8/* Probe related configurations */ 10/* Probe related configurations */
9struct probe_conf { 11struct probe_conf {
@@ -92,6 +94,7 @@ struct perf_probe_event {
92 struct perf_probe_arg *args; /* Arguments */ 94 struct perf_probe_arg *args; /* Arguments */
93 struct probe_trace_event *tevs; 95 struct probe_trace_event *tevs;
94 int ntevs; 96 int ntevs;
97 struct nsinfo *nsi; /* Target namespace */
95}; 98};
96 99
97/* Line range */ 100/* Line range */
@@ -163,10 +166,12 @@ int show_perf_probe_event(const char *group, const char *event,
163 struct perf_probe_event *pev, 166 struct perf_probe_event *pev,
164 const char *module, bool use_stdout); 167 const char *module, bool use_stdout);
165int show_perf_probe_events(struct strfilter *filter); 168int show_perf_probe_events(struct strfilter *filter);
166int show_line_range(struct line_range *lr, const char *module, bool user); 169int show_line_range(struct line_range *lr, const char *module,
170 struct nsinfo *nsi, bool user);
167int show_available_vars(struct perf_probe_event *pevs, int npevs, 171int show_available_vars(struct perf_probe_event *pevs, int npevs,
168 struct strfilter *filter); 172 struct strfilter *filter);
169int show_available_funcs(const char *module, struct strfilter *filter, bool user); 173int show_available_funcs(const char *module, struct nsinfo *nsi,
174 struct strfilter *filter, bool user);
170void arch__fix_tev_from_maps(struct perf_probe_event *pev, 175void arch__fix_tev_from_maps(struct perf_probe_event *pev,
171 struct probe_trace_event *tev, struct map *map, 176 struct probe_trace_event *tev, struct map *map,
172 struct symbol *sym); 177 struct symbol *sym);
@@ -180,7 +185,7 @@ int e_snprintf(char *str, size_t size, const char *format, ...) __printf(3, 4);
180int copy_to_probe_trace_arg(struct probe_trace_arg *tvar, 185int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
181 struct perf_probe_arg *pvar); 186 struct perf_probe_arg *pvar);
182 187
183struct map *get_target_map(const char *target, bool user); 188struct map *get_target_map(const char *target, struct nsinfo *nsi, bool user);
184 189
185void arch__post_process_probe_trace_events(struct perf_probe_event *pev, 190void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
186 int ntevs); 191 int ntevs);
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index d679389e627c..4ae1123c6794 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -15,6 +15,7 @@
15 * 15 *
16 */ 16 */
17#include <errno.h> 17#include <errno.h>
18#include <fcntl.h>
18#include <sys/stat.h> 19#include <sys/stat.h>
19#include <sys/types.h> 20#include <sys/types.h>
20#include <sys/uio.h> 21#include <sys/uio.h>
@@ -412,13 +413,15 @@ int probe_cache_entry__get_event(struct probe_cache_entry *entry,
412} 413}
413 414
414/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */ 415/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
415static int probe_cache__open(struct probe_cache *pcache, const char *target) 416static int probe_cache__open(struct probe_cache *pcache, const char *target,
417 struct nsinfo *nsi)
416{ 418{
417 char cpath[PATH_MAX]; 419 char cpath[PATH_MAX];
418 char sbuildid[SBUILD_ID_SIZE]; 420 char sbuildid[SBUILD_ID_SIZE];
419 char *dir_name = NULL; 421 char *dir_name = NULL;
420 bool is_kallsyms = false; 422 bool is_kallsyms = false;
421 int ret, fd; 423 int ret, fd;
424 struct nscookie nsc;
422 425
423 if (target && build_id_cache__cached(target)) { 426 if (target && build_id_cache__cached(target)) {
424 /* This is a cached buildid */ 427 /* This is a cached buildid */
@@ -431,8 +434,11 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
431 target = DSO__NAME_KALLSYMS; 434 target = DSO__NAME_KALLSYMS;
432 is_kallsyms = true; 435 is_kallsyms = true;
433 ret = sysfs__sprintf_build_id("/", sbuildid); 436 ret = sysfs__sprintf_build_id("/", sbuildid);
434 } else 437 } else {
438 nsinfo__mountns_enter(nsi, &nsc);
435 ret = filename__sprintf_build_id(target, sbuildid); 439 ret = filename__sprintf_build_id(target, sbuildid);
440 nsinfo__mountns_exit(&nsc);
441 }
436 442
437 if (ret < 0) { 443 if (ret < 0) {
438 pr_debug("Failed to get build-id from %s.\n", target); 444 pr_debug("Failed to get build-id from %s.\n", target);
@@ -441,7 +447,7 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
441 447
442 /* If we have no buildid cache, make it */ 448 /* If we have no buildid cache, make it */
443 if (!build_id_cache__cached(sbuildid)) { 449 if (!build_id_cache__cached(sbuildid)) {
444 ret = build_id_cache__add_s(sbuildid, target, 450 ret = build_id_cache__add_s(sbuildid, target, nsi,
445 is_kallsyms, NULL); 451 is_kallsyms, NULL);
446 if (ret < 0) { 452 if (ret < 0) {
447 pr_debug("Failed to add build-id cache: %s\n", target); 453 pr_debug("Failed to add build-id cache: %s\n", target);
@@ -449,7 +455,7 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
449 } 455 }
450 } 456 }
451 457
452 dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms, 458 dir_name = build_id_cache__cachedir(sbuildid, target, nsi, is_kallsyms,
453 false); 459 false);
454found: 460found:
455 if (!dir_name) { 461 if (!dir_name) {
@@ -554,7 +560,7 @@ void probe_cache__delete(struct probe_cache *pcache)
554 free(pcache); 560 free(pcache);
555} 561}
556 562
557struct probe_cache *probe_cache__new(const char *target) 563struct probe_cache *probe_cache__new(const char *target, struct nsinfo *nsi)
558{ 564{
559 struct probe_cache *pcache = probe_cache__alloc(); 565 struct probe_cache *pcache = probe_cache__alloc();
560 int ret; 566 int ret;
@@ -562,7 +568,7 @@ struct probe_cache *probe_cache__new(const char *target)
562 if (!pcache) 568 if (!pcache)
563 return NULL; 569 return NULL;
564 570
565 ret = probe_cache__open(pcache, target); 571 ret = probe_cache__open(pcache, target, nsi);
566 if (ret < 0) { 572 if (ret < 0) {
567 pr_debug("Cache open error: %d\n", ret); 573 pr_debug("Cache open error: %d\n", ret);
568 goto out_err; 574 goto out_err;
@@ -974,7 +980,7 @@ int probe_cache__show_all_caches(struct strfilter *filter)
974 return -EINVAL; 980 return -EINVAL;
975 } 981 }
976 strlist__for_each_entry(nd, bidlist) { 982 strlist__for_each_entry(nd, bidlist) {
977 pcache = probe_cache__new(nd->s); 983 pcache = probe_cache__new(nd->s, NULL);
978 if (!pcache) 984 if (!pcache)
979 continue; 985 continue;
980 if (!list_empty(&pcache->entries)) { 986 if (!list_empty(&pcache->entries)) {
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 5ecc9d3925db..63f29b1d22c1 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PROBE_FILE_H 2#ifndef __PROBE_FILE_H
2#define __PROBE_FILE_H 3#define __PROBE_FILE_H
3 4
@@ -51,7 +52,7 @@ int probe_file__del_strlist(int fd, struct strlist *namelist);
51int probe_cache_entry__get_event(struct probe_cache_entry *entry, 52int probe_cache_entry__get_event(struct probe_cache_entry *entry,
52 struct probe_trace_event **tevs); 53 struct probe_trace_event **tevs);
53 54
54struct probe_cache *probe_cache__new(const char *target); 55struct probe_cache *probe_cache__new(const char *target, struct nsinfo *nsi);
55int probe_cache__add_entry(struct probe_cache *pcache, 56int probe_cache__add_entry(struct probe_cache *pcache,
56 struct perf_probe_event *pev, 57 struct perf_probe_event *pev,
57 struct probe_trace_event *tevs, int ntevs); 58 struct probe_trace_event *tevs, int ntevs);
@@ -69,7 +70,7 @@ int probe_cache__show_all_caches(struct strfilter *filter);
69bool probe_type_is_available(enum probe_type type); 70bool probe_type_is_available(enum probe_type type);
70bool kretprobe_offset_is_supported(void); 71bool kretprobe_offset_is_supported(void);
71#else /* ! HAVE_LIBELF_SUPPORT */ 72#else /* ! HAVE_LIBELF_SUPPORT */
72static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused) 73static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused, struct nsinfo *nsi __maybe_unused)
73{ 74{
74 return NULL; 75 return NULL;
75} 76}
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 27f061551012..16252980ff00 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PROBE_FINDER_H 2#ifndef _PROBE_FINDER_H
2#define _PROBE_FINDER_H 3#define _PROBE_FINDER_H
3 4
diff --git a/tools/perf/util/pstack.c b/tools/perf/util/pstack.c
index b234a6e3d0d4..797fe1ae2d2e 100644
--- a/tools/perf/util/pstack.c
+++ b/tools/perf/util/pstack.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Simple pointer stack 3 * Simple pointer stack
3 * 4 *
diff --git a/tools/perf/util/pstack.h b/tools/perf/util/pstack.h
index ded7f2e36624..8729b8be061d 100644
--- a/tools/perf/util/pstack.h
+++ b/tools/perf/util/pstack.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_PSTACK_ 2#ifndef _PERF_PSTACK_
2#define _PERF_PSTACK_ 3#define _PERF_PSTACK_
3 4
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 9f3b0d9754a8..b4f2f06722a7 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -10,6 +10,8 @@ util/ctype.c
10util/evlist.c 10util/evlist.c
11util/evsel.c 11util/evsel.c
12util/cpumap.c 12util/cpumap.c
13util/mmap.c
14util/namespaces.c
13../lib/bitmap.c 15../lib/bitmap.c
14../lib/find_bit.c 16../lib/find_bit.c
15../lib/hweight.c 17../lib/hweight.c
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index c129e99114ae..8e49d9cafcfc 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <Python.h> 2#include <Python.h>
2#include <structmember.h> 3#include <structmember.h>
3#include <inttypes.h> 4#include <inttypes.h>
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c
index 1ba8920151d8..22eaa201aa27 100644
--- a/tools/perf/util/quote.c
+++ b/tools/perf/util/quote.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include "strbuf.h" 4#include "strbuf.h"
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h
index 055ca45bed99..274bf26d3511 100644
--- a/tools/perf/util/quote.h
+++ b/tools/perf/util/quote.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_QUOTE_H 2#ifndef __PERF_QUOTE_H
2#define __PERF_QUOTE_H 3#define __PERF_QUOTE_H
3 4
diff --git a/tools/perf/util/rb_resort.h b/tools/perf/util/rb_resort.h
index 808cc45611fe..a920f702a74d 100644
--- a/tools/perf/util/rb_resort.h
+++ b/tools/perf/util/rb_resort.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_RESORT_RB_H_ 2#ifndef _PERF_RESORT_RB_H_
2#define _PERF_RESORT_RB_H_ 3#define _PERF_RESORT_RB_H_
3/* 4/*
@@ -143,7 +144,8 @@ struct __name##_sorted *__name = __name##_sorted__new
143 __ilist->rblist.nr_entries) 144 __ilist->rblist.nr_entries)
144 145
145/* For 'struct machine->threads' */ 146/* For 'struct machine->threads' */
146#define DECLARE_RESORT_RB_MACHINE_THREADS(__name, __machine) \ 147#define DECLARE_RESORT_RB_MACHINE_THREADS(__name, __machine, hash_bucket) \
147 DECLARE_RESORT_RB(__name)(&__machine->threads, __machine->nr_threads) 148 DECLARE_RESORT_RB(__name)(&__machine->threads[hash_bucket].entries, \
149 __machine->threads[hash_bucket].nr)
148 150
149#endif /* _PERF_RESORT_RB_H_ */ 151#endif /* _PERF_RESORT_RB_H_ */
diff --git a/tools/perf/util/rblist.h b/tools/perf/util/rblist.h
index ff9913b994c2..4c8638a22571 100644
--- a/tools/perf/util/rblist.h
+++ b/tools/perf/util/rblist.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_RBLIST_H 2#ifndef __PERF_RBLIST_H
2#define __PERF_RBLIST_H 3#define __PERF_RBLIST_H
3 4
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index d91bdf5a1aa4..1e97937b03a9 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "evlist.h" 2#include "evlist.h"
2#include "evsel.h" 3#include "evsel.h"
3#include "cpumap.h" 4#include "cpumap.h"
diff --git a/tools/perf/util/rwsem.c b/tools/perf/util/rwsem.c
new file mode 100644
index 000000000000..5e52e7baa7b6
--- /dev/null
+++ b/tools/perf/util/rwsem.c
@@ -0,0 +1,32 @@
1#include "util.h"
2#include "rwsem.h"
3
4int init_rwsem(struct rw_semaphore *sem)
5{
6 return pthread_rwlock_init(&sem->lock, NULL);
7}
8
9int exit_rwsem(struct rw_semaphore *sem)
10{
11 return pthread_rwlock_destroy(&sem->lock);
12}
13
14int down_read(struct rw_semaphore *sem)
15{
16 return perf_singlethreaded ? 0 : pthread_rwlock_rdlock(&sem->lock);
17}
18
19int up_read(struct rw_semaphore *sem)
20{
21 return perf_singlethreaded ? 0 : pthread_rwlock_unlock(&sem->lock);
22}
23
24int down_write(struct rw_semaphore *sem)
25{
26 return perf_singlethreaded ? 0 : pthread_rwlock_wrlock(&sem->lock);
27}
28
29int up_write(struct rw_semaphore *sem)
30{
31 return perf_singlethreaded ? 0 : pthread_rwlock_unlock(&sem->lock);
32}
diff --git a/tools/perf/util/rwsem.h b/tools/perf/util/rwsem.h
new file mode 100644
index 000000000000..94565ad4d494
--- /dev/null
+++ b/tools/perf/util/rwsem.h
@@ -0,0 +1,19 @@
1#ifndef _PERF_RWSEM_H
2#define _PERF_RWSEM_H
3
4#include <pthread.h>
5
6struct rw_semaphore {
7 pthread_rwlock_t lock;
8};
9
10int init_rwsem(struct rw_semaphore *sem);
11int exit_rwsem(struct rw_semaphore *sem);
12
13int down_read(struct rw_semaphore *sem);
14int up_read(struct rw_semaphore *sem);
15
16int down_write(struct rw_semaphore *sem);
17int up_write(struct rw_semaphore *sem);
18
19#endif /* _PERF_RWSEM_H */
diff --git a/tools/perf/util/sane_ctype.h b/tools/perf/util/sane_ctype.h
index 4308c22c22ad..c2b42ff9ff32 100644
--- a/tools/perf/util/sane_ctype.h
+++ b/tools/perf/util/sane_ctype.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_SANE_CTYPE_H 2#ifndef _PERF_SANE_CTYPE_H
2#define _PERF_SANE_CTYPE_H 3#define _PERF_SANE_CTYPE_H
3 4
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 57b7a00e6f16..c7187f067d31 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -116,6 +116,34 @@ static PyObject *get_handler(const char *handler_name)
116 return handler; 116 return handler;
117} 117}
118 118
119static int get_argument_count(PyObject *handler)
120{
121 int arg_count = 0;
122
123 /*
124 * The attribute for the code object is func_code in Python 2,
125 * whereas it is __code__ in Python 3.0+.
126 */
127 PyObject *code_obj = PyObject_GetAttrString(handler,
128 "func_code");
129 if (PyErr_Occurred()) {
130 PyErr_Clear();
131 code_obj = PyObject_GetAttrString(handler,
132 "__code__");
133 }
134 PyErr_Clear();
135 if (code_obj) {
136 PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
137 "co_argcount");
138 if (arg_count_obj) {
139 arg_count = (int) PyInt_AsLong(arg_count_obj);
140 Py_DECREF(arg_count_obj);
141 }
142 Py_DECREF(code_obj);
143 }
144 return arg_count;
145}
146
119static void call_object(PyObject *handler, PyObject *args, const char *die_msg) 147static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
120{ 148{
121 PyObject *retval; 149 PyObject *retval;
@@ -391,13 +419,115 @@ exit:
391 return pylist; 419 return pylist;
392} 420}
393 421
422static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
423{
424 PyObject *t;
425
426 t = PyTuple_New(2);
427 if (!t)
428 Py_FatalError("couldn't create Python tuple");
429 PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
430 PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
431 return t;
432}
433
434static void set_sample_read_in_dict(PyObject *dict_sample,
435 struct perf_sample *sample,
436 struct perf_evsel *evsel)
437{
438 u64 read_format = evsel->attr.read_format;
439 PyObject *values;
440 unsigned int i;
441
442 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
443 pydict_set_item_string_decref(dict_sample, "time_enabled",
444 PyLong_FromUnsignedLongLong(sample->read.time_enabled));
445 }
446
447 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
448 pydict_set_item_string_decref(dict_sample, "time_running",
449 PyLong_FromUnsignedLongLong(sample->read.time_running));
450 }
451
452 if (read_format & PERF_FORMAT_GROUP)
453 values = PyList_New(sample->read.group.nr);
454 else
455 values = PyList_New(1);
456
457 if (!values)
458 Py_FatalError("couldn't create Python list");
459
460 if (read_format & PERF_FORMAT_GROUP) {
461 for (i = 0; i < sample->read.group.nr; i++) {
462 PyObject *t = get_sample_value_as_tuple(&sample->read.group.values[i]);
463 PyList_SET_ITEM(values, i, t);
464 }
465 } else {
466 PyObject *t = get_sample_value_as_tuple(&sample->read.one);
467 PyList_SET_ITEM(values, 0, t);
468 }
469 pydict_set_item_string_decref(dict_sample, "values", values);
470}
471
472static PyObject *get_perf_sample_dict(struct perf_sample *sample,
473 struct perf_evsel *evsel,
474 struct addr_location *al,
475 PyObject *callchain)
476{
477 PyObject *dict, *dict_sample;
478
479 dict = PyDict_New();
480 if (!dict)
481 Py_FatalError("couldn't create Python dictionary");
482
483 dict_sample = PyDict_New();
484 if (!dict_sample)
485 Py_FatalError("couldn't create Python dictionary");
486
487 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
488 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
489 (const char *)&evsel->attr, sizeof(evsel->attr)));
490
491 pydict_set_item_string_decref(dict_sample, "pid",
492 PyInt_FromLong(sample->pid));
493 pydict_set_item_string_decref(dict_sample, "tid",
494 PyInt_FromLong(sample->tid));
495 pydict_set_item_string_decref(dict_sample, "cpu",
496 PyInt_FromLong(sample->cpu));
497 pydict_set_item_string_decref(dict_sample, "ip",
498 PyLong_FromUnsignedLongLong(sample->ip));
499 pydict_set_item_string_decref(dict_sample, "time",
500 PyLong_FromUnsignedLongLong(sample->time));
501 pydict_set_item_string_decref(dict_sample, "period",
502 PyLong_FromUnsignedLongLong(sample->period));
503 set_sample_read_in_dict(dict_sample, sample, evsel);
504 pydict_set_item_string_decref(dict, "sample", dict_sample);
505
506 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
507 (const char *)sample->raw_data, sample->raw_size));
508 pydict_set_item_string_decref(dict, "comm",
509 PyString_FromString(thread__comm_str(al->thread)));
510 if (al->map) {
511 pydict_set_item_string_decref(dict, "dso",
512 PyString_FromString(al->map->dso->name));
513 }
514 if (al->sym) {
515 pydict_set_item_string_decref(dict, "symbol",
516 PyString_FromString(al->sym->name));
517 }
518
519 pydict_set_item_string_decref(dict, "callchain", callchain);
520
521 return dict;
522}
523
394static void python_process_tracepoint(struct perf_sample *sample, 524static void python_process_tracepoint(struct perf_sample *sample,
395 struct perf_evsel *evsel, 525 struct perf_evsel *evsel,
396 struct addr_location *al) 526 struct addr_location *al)
397{ 527{
398 struct event_format *event = evsel->tp_format; 528 struct event_format *event = evsel->tp_format;
399 PyObject *handler, *context, *t, *obj = NULL, *callchain; 529 PyObject *handler, *context, *t, *obj = NULL, *callchain;
400 PyObject *dict = NULL; 530 PyObject *dict = NULL, *all_entries_dict = NULL;
401 static char handler_name[256]; 531 static char handler_name[256];
402 struct format_field *field; 532 struct format_field *field;
403 unsigned long s, ns; 533 unsigned long s, ns;
@@ -407,10 +537,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
407 void *data = sample->raw_data; 537 void *data = sample->raw_data;
408 unsigned long long nsecs = sample->time; 538 unsigned long long nsecs = sample->time;
409 const char *comm = thread__comm_str(al->thread); 539 const char *comm = thread__comm_str(al->thread);
410 540 const char *default_handler_name = "trace_unhandled";
411 t = PyTuple_New(MAX_FIELDS);
412 if (!t)
413 Py_FatalError("couldn't create Python tuple");
414 541
415 if (!event) { 542 if (!event) {
416 snprintf(handler_name, sizeof(handler_name), 543 snprintf(handler_name, sizeof(handler_name),
@@ -427,10 +554,19 @@ static void python_process_tracepoint(struct perf_sample *sample,
427 554
428 handler = get_handler(handler_name); 555 handler = get_handler(handler_name);
429 if (!handler) { 556 if (!handler) {
557 handler = get_handler(default_handler_name);
558 if (!handler)
559 return;
430 dict = PyDict_New(); 560 dict = PyDict_New();
431 if (!dict) 561 if (!dict)
432 Py_FatalError("couldn't create Python dict"); 562 Py_FatalError("couldn't create Python dict");
433 } 563 }
564
565 t = PyTuple_New(MAX_FIELDS);
566 if (!t)
567 Py_FatalError("couldn't create Python tuple");
568
569
434 s = nsecs / NSEC_PER_SEC; 570 s = nsecs / NSEC_PER_SEC;
435 ns = nsecs - s * NSEC_PER_SEC; 571 ns = nsecs - s * NSEC_PER_SEC;
436 572
@@ -444,8 +580,10 @@ static void python_process_tracepoint(struct perf_sample *sample,
444 580
445 /* ip unwinding */ 581 /* ip unwinding */
446 callchain = python_process_callchain(sample, evsel, al); 582 callchain = python_process_callchain(sample, evsel, al);
583 /* Need an additional reference for the perf_sample dict */
584 Py_INCREF(callchain);
447 585
448 if (handler) { 586 if (!dict) {
449 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 587 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
450 PyTuple_SetItem(t, n++, PyInt_FromLong(s)); 588 PyTuple_SetItem(t, n++, PyInt_FromLong(s));
451 PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); 589 PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
@@ -484,26 +622,35 @@ static void python_process_tracepoint(struct perf_sample *sample,
484 } else { /* FIELD_IS_NUMERIC */ 622 } else { /* FIELD_IS_NUMERIC */
485 obj = get_field_numeric_entry(event, field, data); 623 obj = get_field_numeric_entry(event, field, data);
486 } 624 }
487 if (handler) 625 if (!dict)
488 PyTuple_SetItem(t, n++, obj); 626 PyTuple_SetItem(t, n++, obj);
489 else 627 else
490 pydict_set_item_string_decref(dict, field->name, obj); 628 pydict_set_item_string_decref(dict, field->name, obj);
491 629
492 } 630 }
493 631
494 if (!handler) 632 if (dict)
495 PyTuple_SetItem(t, n++, dict); 633 PyTuple_SetItem(t, n++, dict);
496 634
635 if (get_argument_count(handler) == (int) n + 1) {
636 all_entries_dict = get_perf_sample_dict(sample, evsel, al,
637 callchain);
638 PyTuple_SetItem(t, n++, all_entries_dict);
639 } else {
640 Py_DECREF(callchain);
641 }
642
497 if (_PyTuple_Resize(&t, n) == -1) 643 if (_PyTuple_Resize(&t, n) == -1)
498 Py_FatalError("error resizing Python tuple"); 644 Py_FatalError("error resizing Python tuple");
499 645
500 if (handler) { 646 if (!dict) {
501 call_object(handler, t, handler_name); 647 call_object(handler, t, handler_name);
502 } else { 648 } else {
503 try_call_object("trace_unhandled", t); 649 call_object(handler, t, default_handler_name);
504 Py_DECREF(dict); 650 Py_DECREF(dict);
505 } 651 }
506 652
653 Py_XDECREF(all_entries_dict);
507 Py_DECREF(t); 654 Py_DECREF(t);
508} 655}
509 656
@@ -795,10 +942,16 @@ static void python_process_general_event(struct perf_sample *sample,
795 struct perf_evsel *evsel, 942 struct perf_evsel *evsel,
796 struct addr_location *al) 943 struct addr_location *al)
797{ 944{
798 PyObject *handler, *t, *dict, *callchain, *dict_sample; 945 PyObject *handler, *t, *dict, *callchain;
799 static char handler_name[64]; 946 static char handler_name[64];
800 unsigned n = 0; 947 unsigned n = 0;
801 948
949 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
950
951 handler = get_handler(handler_name);
952 if (!handler)
953 return;
954
802 /* 955 /*
803 * Use the MAX_FIELDS to make the function expandable, though 956 * Use the MAX_FIELDS to make the function expandable, though
804 * currently there is only one item for the tuple. 957 * currently there is only one item for the tuple.
@@ -807,61 +960,16 @@ static void python_process_general_event(struct perf_sample *sample,
807 if (!t) 960 if (!t)
808 Py_FatalError("couldn't create Python tuple"); 961 Py_FatalError("couldn't create Python tuple");
809 962
810 dict = PyDict_New();
811 if (!dict)
812 Py_FatalError("couldn't create Python dictionary");
813
814 dict_sample = PyDict_New();
815 if (!dict_sample)
816 Py_FatalError("couldn't create Python dictionary");
817
818 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
819
820 handler = get_handler(handler_name);
821 if (!handler)
822 goto exit;
823
824 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
825 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
826 (const char *)&evsel->attr, sizeof(evsel->attr)));
827
828 pydict_set_item_string_decref(dict_sample, "pid",
829 PyInt_FromLong(sample->pid));
830 pydict_set_item_string_decref(dict_sample, "tid",
831 PyInt_FromLong(sample->tid));
832 pydict_set_item_string_decref(dict_sample, "cpu",
833 PyInt_FromLong(sample->cpu));
834 pydict_set_item_string_decref(dict_sample, "ip",
835 PyLong_FromUnsignedLongLong(sample->ip));
836 pydict_set_item_string_decref(dict_sample, "time",
837 PyLong_FromUnsignedLongLong(sample->time));
838 pydict_set_item_string_decref(dict_sample, "period",
839 PyLong_FromUnsignedLongLong(sample->period));
840 pydict_set_item_string_decref(dict, "sample", dict_sample);
841
842 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
843 (const char *)sample->raw_data, sample->raw_size));
844 pydict_set_item_string_decref(dict, "comm",
845 PyString_FromString(thread__comm_str(al->thread)));
846 if (al->map) {
847 pydict_set_item_string_decref(dict, "dso",
848 PyString_FromString(al->map->dso->name));
849 }
850 if (al->sym) {
851 pydict_set_item_string_decref(dict, "symbol",
852 PyString_FromString(al->sym->name));
853 }
854
855 /* ip unwinding */ 963 /* ip unwinding */
856 callchain = python_process_callchain(sample, evsel, al); 964 callchain = python_process_callchain(sample, evsel, al);
857 pydict_set_item_string_decref(dict, "callchain", callchain); 965 dict = get_perf_sample_dict(sample, evsel, al, callchain);
858 966
859 PyTuple_SetItem(t, n++, dict); 967 PyTuple_SetItem(t, n++, dict);
860 if (_PyTuple_Resize(&t, n) == -1) 968 if (_PyTuple_Resize(&t, n) == -1)
861 Py_FatalError("error resizing Python tuple"); 969 Py_FatalError("error resizing Python tuple");
862 970
863 call_object(handler, t, handler_name); 971 call_object(handler, t, handler_name);
864exit: 972
865 Py_DECREF(dict); 973 Py_DECREF(dict);
866 Py_DECREF(t); 974 Py_DECREF(t);
867} 975}
@@ -1259,6 +1367,12 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
1259 1367
1260 fprintf(ofp, "%s", f->name); 1368 fprintf(ofp, "%s", f->name);
1261 } 1369 }
1370 if (not_first++)
1371 fprintf(ofp, ", ");
1372 if (++count % 5 == 0)
1373 fprintf(ofp, "\n\t\t");
1374 fprintf(ofp, "perf_sample_dict");
1375
1262 fprintf(ofp, "):\n"); 1376 fprintf(ofp, "):\n");
1263 1377
1264 fprintf(ofp, "\t\tprint_header(event_name, common_cpu, " 1378 fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
@@ -1328,6 +1442,9 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
1328 1442
1329 fprintf(ofp, ")\n\n"); 1443 fprintf(ofp, ")\n\n");
1330 1444
1445 fprintf(ofp, "\t\tprint 'Sample: {'+"
1446 "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
1447
1331 fprintf(ofp, "\t\tfor node in common_callchain:"); 1448 fprintf(ofp, "\t\tfor node in common_callchain:");
1332 fprintf(ofp, "\n\t\t\tif 'sym' in node:"); 1449 fprintf(ofp, "\n\t\t\tif 'sym' in node:");
1333 fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])"); 1450 fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])");
@@ -1338,15 +1455,20 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
1338 } 1455 }
1339 1456
1340 fprintf(ofp, "def trace_unhandled(event_name, context, " 1457 fprintf(ofp, "def trace_unhandled(event_name, context, "
1341 "event_fields_dict):\n"); 1458 "event_fields_dict, perf_sample_dict):\n");
1342 1459
1343 fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))" 1460 fprintf(ofp, "\t\tprint get_dict_as_string(event_fields_dict)\n");
1344 "for k,v in sorted(event_fields_dict.items())])\n\n"); 1461 fprintf(ofp, "\t\tprint 'Sample: {'+"
1462 "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
1345 1463
1346 fprintf(ofp, "def print_header(" 1464 fprintf(ofp, "def print_header("
1347 "event_name, cpu, secs, nsecs, pid, comm):\n" 1465 "event_name, cpu, secs, nsecs, pid, comm):\n"
1348 "\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t" 1466 "\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
1349 "(event_name, cpu, secs, nsecs, pid, comm),\n"); 1467 "(event_name, cpu, secs, nsecs, pid, comm),\n\n");
1468
1469 fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n"
1470 "\treturn delimiter.join"
1471 "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])\n");
1350 1472
1351 fclose(ofp); 1473 fclose(ofp);
1352 1474
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index d19c40a81040..5c412310f266 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <inttypes.h> 3#include <inttypes.h>
3#include <linux/kernel.h> 4#include <linux/kernel.h>
@@ -32,14 +33,14 @@ static int perf_session__deliver_event(struct perf_session *session,
32 33
33static int perf_session__open(struct perf_session *session) 34static int perf_session__open(struct perf_session *session)
34{ 35{
35 struct perf_data_file *file = session->file; 36 struct perf_data *data = session->data;
36 37
37 if (perf_session__read_header(session) < 0) { 38 if (perf_session__read_header(session) < 0) {
38 pr_err("incompatible file format (rerun with -v to learn more)\n"); 39 pr_err("incompatible file format (rerun with -v to learn more)\n");
39 return -1; 40 return -1;
40 } 41 }
41 42
42 if (perf_data_file__is_pipe(file)) 43 if (perf_data__is_pipe(data))
43 return 0; 44 return 0;
44 45
45 if (perf_header__has_feat(&session->header, HEADER_STAT)) 46 if (perf_header__has_feat(&session->header, HEADER_STAT))
@@ -120,7 +121,7 @@ static int ordered_events__deliver_event(struct ordered_events *oe,
120 session->tool, event->file_offset); 121 session->tool, event->file_offset);
121} 122}
122 123
123struct perf_session *perf_session__new(struct perf_data_file *file, 124struct perf_session *perf_session__new(struct perf_data *data,
124 bool repipe, struct perf_tool *tool) 125 bool repipe, struct perf_tool *tool)
125{ 126{
126 struct perf_session *session = zalloc(sizeof(*session)); 127 struct perf_session *session = zalloc(sizeof(*session));
@@ -134,13 +135,13 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
134 machines__init(&session->machines); 135 machines__init(&session->machines);
135 ordered_events__init(&session->ordered_events, ordered_events__deliver_event); 136 ordered_events__init(&session->ordered_events, ordered_events__deliver_event);
136 137
137 if (file) { 138 if (data) {
138 if (perf_data_file__open(file)) 139 if (perf_data__open(data))
139 goto out_delete; 140 goto out_delete;
140 141
141 session->file = file; 142 session->data = data;
142 143
143 if (perf_data_file__is_read(file)) { 144 if (perf_data__is_read(data)) {
144 if (perf_session__open(session) < 0) 145 if (perf_session__open(session) < 0)
145 goto out_close; 146 goto out_close;
146 147
@@ -148,7 +149,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
148 * set session attributes that are present in perf.data 149 * set session attributes that are present in perf.data
149 * but not in pipe-mode. 150 * but not in pipe-mode.
150 */ 151 */
151 if (!file->is_pipe) { 152 if (!data->is_pipe) {
152 perf_session__set_id_hdr_size(session); 153 perf_session__set_id_hdr_size(session);
153 perf_session__set_comm_exec(session); 154 perf_session__set_comm_exec(session);
154 } 155 }
@@ -157,7 +158,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
157 session->machines.host.env = &perf_env; 158 session->machines.host.env = &perf_env;
158 } 159 }
159 160
160 if (!file || perf_data_file__is_write(file)) { 161 if (!data || perf_data__is_write(data)) {
161 /* 162 /*
162 * In O_RDONLY mode this will be performed when reading the 163 * In O_RDONLY mode this will be performed when reading the
163 * kernel MMAP event, in perf_event__process_mmap(). 164 * kernel MMAP event, in perf_event__process_mmap().
@@ -170,7 +171,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
170 * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is 171 * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is
171 * processed, so perf_evlist__sample_id_all is not meaningful here. 172 * processed, so perf_evlist__sample_id_all is not meaningful here.
172 */ 173 */
173 if ((!file || !file->is_pipe) && tool && tool->ordering_requires_timestamps && 174 if ((!data || !data->is_pipe) && tool && tool->ordering_requires_timestamps &&
174 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) { 175 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
175 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 176 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
176 tool->ordered_events = false; 177 tool->ordered_events = false;
@@ -179,7 +180,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
179 return session; 180 return session;
180 181
181 out_close: 182 out_close:
182 perf_data_file__close(file); 183 perf_data__close(data);
183 out_delete: 184 out_delete:
184 perf_session__delete(session); 185 perf_session__delete(session);
185 out: 186 out:
@@ -201,8 +202,8 @@ void perf_session__delete(struct perf_session *session)
201 perf_session__delete_threads(session); 202 perf_session__delete_threads(session);
202 perf_env__exit(&session->header.env); 203 perf_env__exit(&session->header.env);
203 machines__exit(&session->machines); 204 machines__exit(&session->machines);
204 if (session->file) 205 if (session->data)
205 perf_data_file__close(session->file); 206 perf_data__close(session->data);
206 free(session); 207 free(session);
207} 208}
208 209
@@ -290,8 +291,8 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,
290 __maybe_unused) 291 __maybe_unused)
291{ 292{
292 dump_printf(": unhandled!\n"); 293 dump_printf(": unhandled!\n");
293 if (perf_data_file__is_pipe(session->file)) 294 if (perf_data__is_pipe(session->data))
294 skipn(perf_data_file__fd(session->file), event->auxtrace.size); 295 skipn(perf_data__fd(session->data), event->auxtrace.size);
295 return event->auxtrace.size; 296 return event->auxtrace.size;
296} 297}
297 298
@@ -374,6 +375,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
374 tool->mmap2 = process_event_stub; 375 tool->mmap2 = process_event_stub;
375 if (tool->comm == NULL) 376 if (tool->comm == NULL)
376 tool->comm = process_event_stub; 377 tool->comm = process_event_stub;
378 if (tool->namespaces == NULL)
379 tool->namespaces = process_event_stub;
377 if (tool->fork == NULL) 380 if (tool->fork == NULL)
378 tool->fork = process_event_stub; 381 tool->fork = process_event_stub;
379 if (tool->exit == NULL) 382 if (tool->exit == NULL)
@@ -428,6 +431,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
428 tool->stat_round = process_stat_round_stub; 431 tool->stat_round = process_stat_round_stub;
429 if (tool->time_conv == NULL) 432 if (tool->time_conv == NULL)
430 tool->time_conv = process_event_op2_stub; 433 tool->time_conv = process_event_op2_stub;
434 if (tool->feature == NULL)
435 tool->feature = process_event_op2_stub;
431} 436}
432 437
433static void swap_sample_id_all(union perf_event *event, void *data) 438static void swap_sample_id_all(union perf_event *event, void *data)
@@ -1118,6 +1123,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
1118 if (sample_type & PERF_SAMPLE_DATA_SRC) 1123 if (sample_type & PERF_SAMPLE_DATA_SRC)
1119 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src); 1124 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src);
1120 1125
1126 if (sample_type & PERF_SAMPLE_PHYS_ADDR)
1127 printf(" .. phys_addr: 0x%"PRIx64"\n", sample->phys_addr);
1128
1121 if (sample_type & PERF_SAMPLE_TRANSACTION) 1129 if (sample_type & PERF_SAMPLE_TRANSACTION)
1122 printf("... transaction: %" PRIx64 "\n", sample->transaction); 1130 printf("... transaction: %" PRIx64 "\n", sample->transaction);
1123 1131
@@ -1125,6 +1133,30 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
1125 sample_read__printf(sample, evsel->attr.read_format); 1133 sample_read__printf(sample, evsel->attr.read_format);
1126} 1134}
1127 1135
1136static void dump_read(struct perf_evsel *evsel, union perf_event *event)
1137{
1138 struct read_event *read_event = &event->read;
1139 u64 read_format;
1140
1141 if (!dump_trace)
1142 return;
1143
1144 printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
1145 evsel ? perf_evsel__name(evsel) : "FAIL",
1146 event->read.value);
1147
1148 read_format = evsel->attr.read_format;
1149
1150 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1151 printf("... time enabled : %" PRIu64 "\n", read_event->time_enabled);
1152
1153 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1154 printf("... time running : %" PRIu64 "\n", read_event->time_running);
1155
1156 if (read_format & PERF_FORMAT_ID)
1157 printf("... id : %" PRIu64 "\n", read_event->id);
1158}
1159
1128static struct machine *machines__find_for_cpumode(struct machines *machines, 1160static struct machine *machines__find_for_cpumode(struct machines *machines,
1129 union perf_event *event, 1161 union perf_event *event,
1130 struct perf_sample *sample) 1162 struct perf_sample *sample)
@@ -1269,6 +1301,7 @@ static int machines__deliver_event(struct machines *machines,
1269 evlist->stats.total_lost_samples += event->lost_samples.lost; 1301 evlist->stats.total_lost_samples += event->lost_samples.lost;
1270 return tool->lost_samples(tool, event, sample, machine); 1302 return tool->lost_samples(tool, event, sample, machine);
1271 case PERF_RECORD_READ: 1303 case PERF_RECORD_READ:
1304 dump_read(evsel, event);
1272 return tool->read(tool, event, sample, evsel, machine); 1305 return tool->read(tool, event, sample, evsel, machine);
1273 case PERF_RECORD_THROTTLE: 1306 case PERF_RECORD_THROTTLE:
1274 return tool->throttle(tool, event, sample, machine); 1307 return tool->throttle(tool, event, sample, machine);
@@ -1317,7 +1350,7 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1317{ 1350{
1318 struct ordered_events *oe = &session->ordered_events; 1351 struct ordered_events *oe = &session->ordered_events;
1319 struct perf_tool *tool = session->tool; 1352 struct perf_tool *tool = session->tool;
1320 int fd = perf_data_file__fd(session->file); 1353 int fd = perf_data__fd(session->data);
1321 int err; 1354 int err;
1322 1355
1323 dump_event(session->evlist, event, file_offset, NULL); 1356 dump_event(session->evlist, event, file_offset, NULL);
@@ -1371,6 +1404,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1371 case PERF_RECORD_TIME_CONV: 1404 case PERF_RECORD_TIME_CONV:
1372 session->time_conv = event->time_conv; 1405 session->time_conv = event->time_conv;
1373 return tool->time_conv(tool, event, session); 1406 return tool->time_conv(tool, event, session);
1407 case PERF_RECORD_HEADER_FEATURE:
1408 return tool->feature(tool, event, session);
1374 default: 1409 default:
1375 return -EINVAL; 1410 return -EINVAL;
1376 } 1411 }
@@ -1415,10 +1450,10 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
1415 goto out_parse_sample; 1450 goto out_parse_sample;
1416 } 1451 }
1417 1452
1418 if (perf_data_file__is_pipe(session->file)) 1453 if (perf_data__is_pipe(session->data))
1419 return -1; 1454 return -1;
1420 1455
1421 fd = perf_data_file__fd(session->file); 1456 fd = perf_data__fd(session->data);
1422 hdr_sz = sizeof(struct perf_event_header); 1457 hdr_sz = sizeof(struct perf_event_header);
1423 1458
1424 if (buf_sz < hdr_sz) 1459 if (buf_sz < hdr_sz)
@@ -1653,7 +1688,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session)
1653{ 1688{
1654 struct ordered_events *oe = &session->ordered_events; 1689 struct ordered_events *oe = &session->ordered_events;
1655 struct perf_tool *tool = session->tool; 1690 struct perf_tool *tool = session->tool;
1656 int fd = perf_data_file__fd(session->file); 1691 int fd = perf_data__fd(session->data);
1657 union perf_event *event; 1692 union perf_event *event;
1658 uint32_t size, cur_size = 0; 1693 uint32_t size, cur_size = 0;
1659 void *buf = NULL; 1694 void *buf = NULL;
@@ -1794,7 +1829,7 @@ static int __perf_session__process_events(struct perf_session *session,
1794{ 1829{
1795 struct ordered_events *oe = &session->ordered_events; 1830 struct ordered_events *oe = &session->ordered_events;
1796 struct perf_tool *tool = session->tool; 1831 struct perf_tool *tool = session->tool;
1797 int fd = perf_data_file__fd(session->file); 1832 int fd = perf_data__fd(session->data);
1798 u64 head, page_offset, file_offset, file_pos, size; 1833 u64 head, page_offset, file_offset, file_pos, size;
1799 int err, mmap_prot, mmap_flags, map_idx = 0; 1834 int err, mmap_prot, mmap_flags, map_idx = 0;
1800 size_t mmap_size; 1835 size_t mmap_size;
@@ -1815,7 +1850,7 @@ static int __perf_session__process_events(struct perf_session *session,
1815 if (data_offset + data_size < file_size) 1850 if (data_offset + data_size < file_size)
1816 file_size = data_offset + data_size; 1851 file_size = data_offset + data_size;
1817 1852
1818 ui_progress__init(&prog, file_size, "Processing events..."); 1853 ui_progress__init_size(&prog, file_size, "Processing events...");
1819 1854
1820 mmap_size = MMAP_SIZE; 1855 mmap_size = MMAP_SIZE;
1821 if (mmap_size > file_size) { 1856 if (mmap_size > file_size) {
@@ -1911,13 +1946,13 @@ out_err:
1911 1946
1912int perf_session__process_events(struct perf_session *session) 1947int perf_session__process_events(struct perf_session *session)
1913{ 1948{
1914 u64 size = perf_data_file__size(session->file); 1949 u64 size = perf_data__size(session->data);
1915 int err; 1950 int err;
1916 1951
1917 if (perf_session__register_idle_thread(session) < 0) 1952 if (perf_session__register_idle_thread(session) < 0)
1918 return -ENOMEM; 1953 return -ENOMEM;
1919 1954
1920 if (!perf_data_file__is_pipe(session->file)) 1955 if (!perf_data__is_pipe(session->data))
1921 err = __perf_session__process_events(session, 1956 err = __perf_session__process_events(session,
1922 session->header.data_offset, 1957 session->header.data_offset,
1923 session->header.data_size, size); 1958 session->header.data_size, size);
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 47b5e7dbcb18..da1434a7c120 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_SESSION_H 2#ifndef __PERF_SESSION_H
2#define __PERF_SESSION_H 3#define __PERF_SESSION_H
3 4
@@ -32,13 +33,13 @@ struct perf_session {
32 void *one_mmap_addr; 33 void *one_mmap_addr;
33 u64 one_mmap_offset; 34 u64 one_mmap_offset;
34 struct ordered_events ordered_events; 35 struct ordered_events ordered_events;
35 struct perf_data_file *file; 36 struct perf_data *data;
36 struct perf_tool *tool; 37 struct perf_tool *tool;
37}; 38};
38 39
39struct perf_tool; 40struct perf_tool;
40 41
41struct perf_session *perf_session__new(struct perf_data_file *file, 42struct perf_session *perf_session__new(struct perf_data *data,
42 bool repipe, struct perf_tool *tool); 43 bool repipe, struct perf_tool *tool);
43void perf_session__delete(struct perf_session *session); 44void perf_session__delete(struct perf_session *session);
44 45
@@ -113,7 +114,7 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
113 114
114extern volatile int session_done; 115extern volatile int session_done;
115 116
116#define session_done() ACCESS_ONCE(session_done) 117#define session_done() READ_ONCE(session_done)
117 118
118int perf_session__deliver_synth_event(struct perf_session *session, 119int perf_session__deliver_synth_event(struct perf_session *session,
119 union perf_event *event, 120 union perf_event *event,
diff --git a/tools/perf/util/setns.c b/tools/perf/util/setns.c
new file mode 100644
index 000000000000..ce8fc290fce8
--- /dev/null
+++ b/tools/perf/util/setns.c
@@ -0,0 +1,8 @@
1#include "util.h"
2#include <unistd.h>
3#include <sys/syscall.h>
4
5int setns(int fd, int nstype)
6{
7 return syscall(__NR_setns, fd, nstype);
8}
diff --git a/tools/perf/util/smt.c b/tools/perf/util/smt.c
new file mode 100644
index 000000000000..453f6f6f29f3
--- /dev/null
+++ b/tools/perf/util/smt.c
@@ -0,0 +1,44 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <linux/bitops.h>
5#include "api/fs/fs.h"
6#include "smt.h"
7
8int smt_on(void)
9{
10 static bool cached;
11 static int cached_result;
12 int cpu;
13 int ncpu;
14
15 if (cached)
16 return cached_result;
17
18 ncpu = sysconf(_SC_NPROCESSORS_CONF);
19 for (cpu = 0; cpu < ncpu; cpu++) {
20 unsigned long long siblings;
21 char *str;
22 size_t strlen;
23 char fn[256];
24
25 snprintf(fn, sizeof fn,
26 "devices/system/cpu/cpu%d/topology/thread_siblings",
27 cpu);
28 if (sysfs__read_str(fn, &str, &strlen) < 0)
29 continue;
30 /* Entry is hex, but does not have 0x, so need custom parser */
31 siblings = strtoull(str, NULL, 16);
32 free(str);
33 if (hweight64(siblings) > 1) {
34 cached_result = 1;
35 cached = true;
36 break;
37 }
38 }
39 if (!cached) {
40 cached_result = 0;
41 cached = true;
42 }
43 return cached_result;
44}
diff --git a/tools/perf/util/smt.h b/tools/perf/util/smt.h
new file mode 100644
index 000000000000..b8414b7bcbc8
--- /dev/null
+++ b/tools/perf/util/smt.h
@@ -0,0 +1,6 @@
1#ifndef SMT_H
2#define SMT_H 1
3
4int smt_on(void);
5
6#endif
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 8b327c955a4f..a00eacdf02ed 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <inttypes.h> 3#include <inttypes.h>
3#include <regex.h> 4#include <regex.h>
@@ -225,6 +226,9 @@ static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
225 if (sym_l == sym_r) 226 if (sym_l == sym_r)
226 return 0; 227 return 0;
227 228
229 if (sym_l->inlined || sym_r->inlined)
230 return strcmp(sym_l->name, sym_r->name);
231
228 if (sym_l->start != sym_r->start) 232 if (sym_l->start != sym_r->start)
229 return (int64_t)(sym_r->start - sym_l->start); 233 return (int64_t)(sym_r->start - sym_l->start);
230 234
@@ -283,6 +287,9 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
283 ret += repsep_snprintf(bf + ret, size - ret, "%.*s", 287 ret += repsep_snprintf(bf + ret, size - ret, "%.*s",
284 width - ret, 288 width - ret,
285 sym->name); 289 sym->name);
290 if (sym->inlined)
291 ret += repsep_snprintf(bf + ret, size - ret,
292 " (inlined)");
286 } 293 }
287 } else { 294 } else {
288 size_t len = BITS_PER_LONG / 4; 295 size_t len = BITS_PER_LONG / 4;
@@ -1316,6 +1323,47 @@ struct sort_entry sort_mem_dcacheline = {
1316}; 1323};
1317 1324
1318static int64_t 1325static int64_t
1326sort__phys_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
1327{
1328 uint64_t l = 0, r = 0;
1329
1330 if (left->mem_info)
1331 l = left->mem_info->daddr.phys_addr;
1332 if (right->mem_info)
1333 r = right->mem_info->daddr.phys_addr;
1334
1335 return (int64_t)(r - l);
1336}
1337
1338static int hist_entry__phys_daddr_snprintf(struct hist_entry *he, char *bf,
1339 size_t size, unsigned int width)
1340{
1341 uint64_t addr = 0;
1342 size_t ret = 0;
1343 size_t len = BITS_PER_LONG / 4;
1344
1345 addr = he->mem_info->daddr.phys_addr;
1346
1347 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", he->level);
1348
1349 ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx", len, addr);
1350
1351 ret += repsep_snprintf(bf + ret, size - ret, "%-*s", width - ret, "");
1352
1353 if (ret > width)
1354 bf[width] = '\0';
1355
1356 return width;
1357}
1358
1359struct sort_entry sort_mem_phys_daddr = {
1360 .se_header = "Data Physical Address",
1361 .se_cmp = sort__phys_daddr_cmp,
1362 .se_snprintf = hist_entry__phys_daddr_snprintf,
1363 .se_width_idx = HISTC_MEM_PHYS_DADDR,
1364};
1365
1366static int64_t
1319sort__abort_cmp(struct hist_entry *left, struct hist_entry *right) 1367sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
1320{ 1368{
1321 if (!left->branch_info || !right->branch_info) 1369 if (!left->branch_info || !right->branch_info)
@@ -1547,6 +1595,7 @@ static struct sort_dimension memory_sort_dimensions[] = {
1547 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl), 1595 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
1548 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop), 1596 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
1549 DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline), 1597 DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline),
1598 DIM(SORT_MEM_PHYS_DADDR, "phys_daddr", sort_mem_phys_daddr),
1550}; 1599};
1551 1600
1552#undef DIM 1601#undef DIM
@@ -2563,7 +2612,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist)
2563 2612
2564 BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders)); 2613 BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
2565 2614
2566 if (evlist == NULL) 2615 if (evlist == NULL || perf_evlist__empty(evlist))
2567 goto out_no_evlist; 2616 goto out_no_evlist;
2568 2617
2569 evlist__for_each_entry(evlist, evsel) { 2618 evlist__for_each_entry(evlist, evsel) {
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index b7c75597e18f..f5901c10a563 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_SORT_H 2#ifndef __PERF_SORT_H
2#define __PERF_SORT_H 3#define __PERF_SORT_H
3#include "../builtin.h" 4#include "../builtin.h"
@@ -129,7 +130,6 @@ struct hist_entry {
129 }; 130 };
130 char *srcline; 131 char *srcline;
131 char *srcfile; 132 char *srcfile;
132 struct inline_node *inline_node;
133 struct symbol *parent; 133 struct symbol *parent;
134 struct branch_info *branch_info; 134 struct branch_info *branch_info;
135 struct hists *hists; 135 struct hists *hists;
@@ -245,6 +245,7 @@ enum sort_type {
245 SORT_MEM_SNOOP, 245 SORT_MEM_SNOOP,
246 SORT_MEM_DCACHELINE, 246 SORT_MEM_DCACHELINE,
247 SORT_MEM_IADDR_SYMBOL, 247 SORT_MEM_IADDR_SYMBOL,
248 SORT_MEM_PHYS_DADDR,
248}; 249};
249 250
250/* 251/*
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index ebc88a74e67b..d19f05c56de6 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <inttypes.h> 2#include <inttypes.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <stdlib.h> 4#include <stdlib.h>
@@ -10,7 +11,7 @@
10#include "util/debug.h" 11#include "util/debug.h"
11#include "util/callchain.h" 12#include "util/callchain.h"
12#include "srcline.h" 13#include "srcline.h"
13 14#include "string2.h"
14#include "symbol.h" 15#include "symbol.h"
15 16
16bool srcline_full_filename; 17bool srcline_full_filename;
@@ -33,28 +34,17 @@ static const char *dso__name(struct dso *dso)
33 return dso_name; 34 return dso_name;
34} 35}
35 36
36static int inline_list__append(char *filename, char *funcname, int line_nr, 37static int inline_list__append(struct symbol *symbol, char *srcline,
37 struct inline_node *node, struct dso *dso) 38 struct inline_node *node)
38{ 39{
39 struct inline_list *ilist; 40 struct inline_list *ilist;
40 char *demangled;
41 41
42 ilist = zalloc(sizeof(*ilist)); 42 ilist = zalloc(sizeof(*ilist));
43 if (ilist == NULL) 43 if (ilist == NULL)
44 return -1; 44 return -1;
45 45
46 ilist->filename = filename; 46 ilist->symbol = symbol;
47 ilist->line_nr = line_nr; 47 ilist->srcline = srcline;
48
49 if (dso != NULL) {
50 demangled = dso__demangle_sym(dso, 0, funcname);
51 if (demangled == NULL) {
52 ilist->funcname = funcname;
53 } else {
54 ilist->funcname = demangled;
55 free(funcname);
56 }
57 }
58 48
59 if (callchain_param.order == ORDER_CALLEE) 49 if (callchain_param.order == ORDER_CALLEE)
60 list_add_tail(&ilist->list, &node->val); 50 list_add_tail(&ilist->list, &node->val);
@@ -64,6 +54,65 @@ static int inline_list__append(char *filename, char *funcname, int line_nr,
64 return 0; 54 return 0;
65} 55}
66 56
57/* basename version that takes a const input string */
58static const char *gnu_basename(const char *path)
59{
60 const char *base = strrchr(path, '/');
61
62 return base ? base + 1 : path;
63}
64
65static char *srcline_from_fileline(const char *file, unsigned int line)
66{
67 char *srcline;
68
69 if (!file)
70 return NULL;
71
72 if (!srcline_full_filename)
73 file = gnu_basename(file);
74
75 if (asprintf(&srcline, "%s:%u", file, line) < 0)
76 return NULL;
77
78 return srcline;
79}
80
81static struct symbol *new_inline_sym(struct dso *dso,
82 struct symbol *base_sym,
83 const char *funcname)
84{
85 struct symbol *inline_sym;
86 char *demangled = NULL;
87
88 if (dso) {
89 demangled = dso__demangle_sym(dso, 0, funcname);
90 if (demangled)
91 funcname = demangled;
92 }
93
94 if (base_sym && strcmp(funcname, base_sym->name) == 0) {
95 /* reuse the real, existing symbol */
96 inline_sym = base_sym;
97 /* ensure that we don't alias an inlined symbol, which could
98 * lead to double frees in inline_node__delete
99 */
100 assert(!base_sym->inlined);
101 } else {
102 /* create a fake symbol for the inline frame */
103 inline_sym = symbol__new(base_sym ? base_sym->start : 0,
104 base_sym ? base_sym->end : 0,
105 base_sym ? base_sym->binding : 0,
106 funcname);
107 if (inline_sym)
108 inline_sym->inlined = 1;
109 }
110
111 free(demangled);
112
113 return inline_sym;
114}
115
67#ifdef HAVE_LIBBFD_SUPPORT 116#ifdef HAVE_LIBBFD_SUPPORT
68 117
69/* 118/*
@@ -155,6 +204,9 @@ static void find_address_in_section(bfd *abfd, asection *section, void *data)
155 a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma, 204 a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma,
156 &a2l->filename, &a2l->funcname, 205 &a2l->filename, &a2l->funcname,
157 &a2l->line); 206 &a2l->line);
207
208 if (a2l->filename && !strlen(a2l->filename))
209 a2l->filename = NULL;
158} 210}
159 211
160static struct a2l_data *addr2line_init(const char *path) 212static struct a2l_data *addr2line_init(const char *path)
@@ -204,18 +256,23 @@ static void addr2line_cleanup(struct a2l_data *a2l)
204#define MAX_INLINE_NEST 1024 256#define MAX_INLINE_NEST 1024
205 257
206static int inline_list__append_dso_a2l(struct dso *dso, 258static int inline_list__append_dso_a2l(struct dso *dso,
207 struct inline_node *node) 259 struct inline_node *node,
260 struct symbol *sym)
208{ 261{
209 struct a2l_data *a2l = dso->a2l; 262 struct a2l_data *a2l = dso->a2l;
210 char *funcname = a2l->funcname ? strdup(a2l->funcname) : NULL; 263 struct symbol *inline_sym = new_inline_sym(dso, sym, a2l->funcname);
211 char *filename = a2l->filename ? strdup(a2l->filename) : NULL; 264 char *srcline = NULL;
212 265
213 return inline_list__append(filename, funcname, a2l->line, node, dso); 266 if (a2l->filename)
267 srcline = srcline_from_fileline(a2l->filename, a2l->line);
268
269 return inline_list__append(inline_sym, srcline, node);
214} 270}
215 271
216static int addr2line(const char *dso_name, u64 addr, 272static int addr2line(const char *dso_name, u64 addr,
217 char **file, unsigned int *line, struct dso *dso, 273 char **file, unsigned int *line, struct dso *dso,
218 bool unwind_inlines, struct inline_node *node) 274 bool unwind_inlines, struct inline_node *node,
275 struct symbol *sym)
219{ 276{
220 int ret = 0; 277 int ret = 0;
221 struct a2l_data *a2l = dso->a2l; 278 struct a2l_data *a2l = dso->a2l;
@@ -241,15 +298,18 @@ static int addr2line(const char *dso_name, u64 addr,
241 if (unwind_inlines) { 298 if (unwind_inlines) {
242 int cnt = 0; 299 int cnt = 0;
243 300
244 if (node && inline_list__append_dso_a2l(dso, node)) 301 if (node && inline_list__append_dso_a2l(dso, node, sym))
245 return 0; 302 return 0;
246 303
247 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename, 304 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename,
248 &a2l->funcname, &a2l->line) && 305 &a2l->funcname, &a2l->line) &&
249 cnt++ < MAX_INLINE_NEST) { 306 cnt++ < MAX_INLINE_NEST) {
250 307
308 if (a2l->filename && !strlen(a2l->filename))
309 a2l->filename = NULL;
310
251 if (node != NULL) { 311 if (node != NULL) {
252 if (inline_list__append_dso_a2l(dso, node)) 312 if (inline_list__append_dso_a2l(dso, node, sym))
253 return 0; 313 return 0;
254 // found at least one inline frame 314 // found at least one inline frame
255 ret = 1; 315 ret = 1;
@@ -281,7 +341,7 @@ void dso__free_a2l(struct dso *dso)
281} 341}
282 342
283static struct inline_node *addr2inlines(const char *dso_name, u64 addr, 343static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
284 struct dso *dso) 344 struct dso *dso, struct symbol *sym)
285{ 345{
286 struct inline_node *node; 346 struct inline_node *node;
287 347
@@ -294,17 +354,8 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
294 INIT_LIST_HEAD(&node->val); 354 INIT_LIST_HEAD(&node->val);
295 node->addr = addr; 355 node->addr = addr;
296 356
297 if (!addr2line(dso_name, addr, NULL, NULL, dso, TRUE, node)) 357 addr2line(dso_name, addr, NULL, NULL, dso, true, node, sym);
298 goto out_free_inline_node;
299
300 if (list_empty(&node->val))
301 goto out_free_inline_node;
302
303 return node; 358 return node;
304
305out_free_inline_node:
306 inline_node__delete(node);
307 return NULL;
308} 359}
309 360
310#else /* HAVE_LIBBFD_SUPPORT */ 361#else /* HAVE_LIBBFD_SUPPORT */
@@ -334,7 +385,8 @@ static int addr2line(const char *dso_name, u64 addr,
334 char **file, unsigned int *line_nr, 385 char **file, unsigned int *line_nr,
335 struct dso *dso __maybe_unused, 386 struct dso *dso __maybe_unused,
336 bool unwind_inlines __maybe_unused, 387 bool unwind_inlines __maybe_unused,
337 struct inline_node *node __maybe_unused) 388 struct inline_node *node __maybe_unused,
389 struct symbol *sym __maybe_unused)
338{ 390{
339 FILE *fp; 391 FILE *fp;
340 char cmd[PATH_MAX]; 392 char cmd[PATH_MAX];
@@ -374,16 +426,18 @@ void dso__free_a2l(struct dso *dso __maybe_unused)
374} 426}
375 427
376static struct inline_node *addr2inlines(const char *dso_name, u64 addr, 428static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
377 struct dso *dso __maybe_unused) 429 struct dso *dso __maybe_unused,
430 struct symbol *sym)
378{ 431{
379 FILE *fp; 432 FILE *fp;
380 char cmd[PATH_MAX]; 433 char cmd[PATH_MAX];
381 struct inline_node *node; 434 struct inline_node *node;
382 char *filename = NULL; 435 char *filename = NULL;
383 size_t len; 436 char *funcname = NULL;
437 size_t filelen, funclen;
384 unsigned int line_nr = 0; 438 unsigned int line_nr = 0;
385 439
386 scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i %016"PRIx64, 440 scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i -f %016"PRIx64,
387 dso_name, addr); 441 dso_name, addr);
388 442
389 fp = popen(cmd, "r"); 443 fp = popen(cmd, "r");
@@ -401,26 +455,34 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
401 INIT_LIST_HEAD(&node->val); 455 INIT_LIST_HEAD(&node->val);
402 node->addr = addr; 456 node->addr = addr;
403 457
404 while (getline(&filename, &len, fp) != -1) { 458 /* addr2line -f generates two lines for each inlined functions */
405 if (filename_split(filename, &line_nr) != 1) { 459 while (getline(&funcname, &funclen, fp) != -1) {
406 free(filename); 460 char *srcline;
461 struct symbol *inline_sym;
462
463 rtrim(funcname);
464
465 if (getline(&filename, &filelen, fp) == -1)
407 goto out; 466 goto out;
408 }
409 467
410 if (inline_list__append(filename, NULL, line_nr, node, 468 if (filename_split(filename, &line_nr) != 1)
411 NULL) != 0)
412 goto out; 469 goto out;
413 470
414 filename = NULL; 471 srcline = srcline_from_fileline(filename, line_nr);
472 inline_sym = new_inline_sym(dso, sym, funcname);
473
474 if (inline_list__append(inline_sym, srcline, node) != 0) {
475 free(srcline);
476 if (inline_sym && inline_sym->inlined)
477 symbol__delete(inline_sym);
478 goto out;
479 }
415 } 480 }
416 481
417out: 482out:
418 pclose(fp); 483 pclose(fp);
419 484 free(filename);
420 if (list_empty(&node->val)) { 485 free(funcname);
421 inline_node__delete(node);
422 return NULL;
423 }
424 486
425 return node; 487 return node;
426} 488}
@@ -448,19 +510,18 @@ char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
448 if (dso_name == NULL) 510 if (dso_name == NULL)
449 goto out; 511 goto out;
450 512
451 if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines, NULL)) 513 if (!addr2line(dso_name, addr, &file, &line, dso,
514 unwind_inlines, NULL, sym))
452 goto out; 515 goto out;
453 516
454 if (asprintf(&srcline, "%s:%u", 517 srcline = srcline_from_fileline(file, line);
455 srcline_full_filename ? file : basename(file), 518 free(file);
456 line) < 0) { 519
457 free(file); 520 if (!srcline)
458 goto out; 521 goto out;
459 }
460 522
461 dso->a2l_fails = 0; 523 dso->a2l_fails = 0;
462 524
463 free(file);
464 return srcline; 525 return srcline;
465 526
466out: 527out:
@@ -494,7 +555,74 @@ char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
494 return __get_srcline(dso, addr, sym, show_sym, show_addr, false); 555 return __get_srcline(dso, addr, sym, show_sym, show_addr, false);
495} 556}
496 557
497struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr) 558struct srcline_node {
559 u64 addr;
560 char *srcline;
561 struct rb_node rb_node;
562};
563
564void srcline__tree_insert(struct rb_root *tree, u64 addr, char *srcline)
565{
566 struct rb_node **p = &tree->rb_node;
567 struct rb_node *parent = NULL;
568 struct srcline_node *i, *node;
569
570 node = zalloc(sizeof(struct srcline_node));
571 if (!node) {
572 perror("not enough memory for the srcline node");
573 return;
574 }
575
576 node->addr = addr;
577 node->srcline = srcline;
578
579 while (*p != NULL) {
580 parent = *p;
581 i = rb_entry(parent, struct srcline_node, rb_node);
582 if (addr < i->addr)
583 p = &(*p)->rb_left;
584 else
585 p = &(*p)->rb_right;
586 }
587 rb_link_node(&node->rb_node, parent, p);
588 rb_insert_color(&node->rb_node, tree);
589}
590
591char *srcline__tree_find(struct rb_root *tree, u64 addr)
592{
593 struct rb_node *n = tree->rb_node;
594
595 while (n) {
596 struct srcline_node *i = rb_entry(n, struct srcline_node,
597 rb_node);
598
599 if (addr < i->addr)
600 n = n->rb_left;
601 else if (addr > i->addr)
602 n = n->rb_right;
603 else
604 return i->srcline;
605 }
606
607 return NULL;
608}
609
610void srcline__tree_delete(struct rb_root *tree)
611{
612 struct srcline_node *pos;
613 struct rb_node *next = rb_first(tree);
614
615 while (next) {
616 pos = rb_entry(next, struct srcline_node, rb_node);
617 next = rb_next(&pos->rb_node);
618 rb_erase(&pos->rb_node, tree);
619 free_srcline(pos->srcline);
620 zfree(&pos);
621 }
622}
623
624struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr,
625 struct symbol *sym)
498{ 626{
499 const char *dso_name; 627 const char *dso_name;
500 628
@@ -502,7 +630,7 @@ struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr)
502 if (dso_name == NULL) 630 if (dso_name == NULL)
503 return NULL; 631 return NULL;
504 632
505 return addr2inlines(dso_name, addr, dso); 633 return addr2inlines(dso_name, addr, dso, sym);
506} 634}
507 635
508void inline_node__delete(struct inline_node *node) 636void inline_node__delete(struct inline_node *node)
@@ -511,10 +639,63 @@ void inline_node__delete(struct inline_node *node)
511 639
512 list_for_each_entry_safe(ilist, tmp, &node->val, list) { 640 list_for_each_entry_safe(ilist, tmp, &node->val, list) {
513 list_del_init(&ilist->list); 641 list_del_init(&ilist->list);
514 zfree(&ilist->filename); 642 free_srcline(ilist->srcline);
515 zfree(&ilist->funcname); 643 /* only the inlined symbols are owned by the list */
644 if (ilist->symbol && ilist->symbol->inlined)
645 symbol__delete(ilist->symbol);
516 free(ilist); 646 free(ilist);
517 } 647 }
518 648
519 free(node); 649 free(node);
520} 650}
651
652void inlines__tree_insert(struct rb_root *tree, struct inline_node *inlines)
653{
654 struct rb_node **p = &tree->rb_node;
655 struct rb_node *parent = NULL;
656 const u64 addr = inlines->addr;
657 struct inline_node *i;
658
659 while (*p != NULL) {
660 parent = *p;
661 i = rb_entry(parent, struct inline_node, rb_node);
662 if (addr < i->addr)
663 p = &(*p)->rb_left;
664 else
665 p = &(*p)->rb_right;
666 }
667 rb_link_node(&inlines->rb_node, parent, p);
668 rb_insert_color(&inlines->rb_node, tree);
669}
670
671struct inline_node *inlines__tree_find(struct rb_root *tree, u64 addr)
672{
673 struct rb_node *n = tree->rb_node;
674
675 while (n) {
676 struct inline_node *i = rb_entry(n, struct inline_node,
677 rb_node);
678
679 if (addr < i->addr)
680 n = n->rb_left;
681 else if (addr > i->addr)
682 n = n->rb_right;
683 else
684 return i;
685 }
686
687 return NULL;
688}
689
690void inlines__tree_delete(struct rb_root *tree)
691{
692 struct inline_node *pos;
693 struct rb_node *next = rb_first(tree);
694
695 while (next) {
696 pos = rb_entry(next, struct inline_node, rb_node);
697 next = rb_next(&pos->rb_node);
698 rb_erase(&pos->rb_node, tree);
699 inline_node__delete(pos);
700 }
701}
diff --git a/tools/perf/util/srcline.h b/tools/perf/util/srcline.h
index 7b52ba88676e..847b7086182c 100644
--- a/tools/perf/util/srcline.h
+++ b/tools/perf/util/srcline.h
@@ -1,7 +1,9 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PERF_SRCLINE_H 2#ifndef PERF_SRCLINE_H
2#define PERF_SRCLINE_H 3#define PERF_SRCLINE_H
3 4
4#include <linux/list.h> 5#include <linux/list.h>
6#include <linux/rbtree.h>
5#include <linux/types.h> 7#include <linux/types.h>
6 8
7struct dso; 9struct dso;
@@ -14,21 +16,38 @@ char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
14 bool show_sym, bool show_addr, bool unwind_inlines); 16 bool show_sym, bool show_addr, bool unwind_inlines);
15void free_srcline(char *srcline); 17void free_srcline(char *srcline);
16 18
19/* insert the srcline into the DSO, which will take ownership */
20void srcline__tree_insert(struct rb_root *tree, u64 addr, char *srcline);
21/* find previously inserted srcline */
22char *srcline__tree_find(struct rb_root *tree, u64 addr);
23/* delete all srclines within the tree */
24void srcline__tree_delete(struct rb_root *tree);
25
17#define SRCLINE_UNKNOWN ((char *) "??:0") 26#define SRCLINE_UNKNOWN ((char *) "??:0")
18 27
19struct inline_list { 28struct inline_list {
20 char *filename; 29 struct symbol *symbol;
21 char *funcname; 30 char *srcline;
22 unsigned int line_nr;
23 struct list_head list; 31 struct list_head list;
24}; 32};
25 33
26struct inline_node { 34struct inline_node {
27 u64 addr; 35 u64 addr;
28 struct list_head val; 36 struct list_head val;
37 struct rb_node rb_node;
29}; 38};
30 39
31struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr); 40/* parse inlined frames for the given address */
41struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr,
42 struct symbol *sym);
43/* free resources associated to the inline node list */
32void inline_node__delete(struct inline_node *node); 44void inline_node__delete(struct inline_node *node);
33 45
46/* insert the inline node list into the DSO, which will take ownership */
47void inlines__tree_insert(struct rb_root *tree, struct inline_node *inlines);
48/* find previously inserted inline node list */
49struct inline_node *inlines__tree_find(struct rb_root *tree, u64 addr);
50/* delete all nodes within the tree of inline_node s */
51void inlines__tree_delete(struct rb_root *tree);
52
34#endif /* PERF_SRCLINE_H */ 53#endif /* PERF_SRCLINE_H */
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 719d6cb86952..855e35cbb1dc 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include "evsel.h" 3#include "evsel.h"
3#include "stat.h" 4#include "stat.h"
@@ -6,6 +7,7 @@
6#include "rblist.h" 7#include "rblist.h"
7#include "evlist.h" 8#include "evlist.h"
8#include "expr.h" 9#include "expr.h"
10#include "metricgroup.h"
9 11
10enum { 12enum {
11 CTX_BIT_USER = 1 << 0, 13 CTX_BIT_USER = 1 << 0,
@@ -55,7 +57,6 @@ struct saved_value {
55 struct rb_node rb_node; 57 struct rb_node rb_node;
56 struct perf_evsel *evsel; 58 struct perf_evsel *evsel;
57 int cpu; 59 int cpu;
58 int ctx;
59 struct stats stats; 60 struct stats stats;
60}; 61};
61 62
@@ -66,11 +67,13 @@ static int saved_value_cmp(struct rb_node *rb_node, const void *entry)
66 rb_node); 67 rb_node);
67 const struct saved_value *b = entry; 68 const struct saved_value *b = entry;
68 69
69 if (a->ctx != b->ctx)
70 return a->ctx - b->ctx;
71 if (a->cpu != b->cpu) 70 if (a->cpu != b->cpu)
72 return a->cpu - b->cpu; 71 return a->cpu - b->cpu;
73 return a->evsel - b->evsel; 72 if (a->evsel == b->evsel)
73 return 0;
74 if ((char *)a->evsel < (char *)b->evsel)
75 return -1;
76 return +1;
74} 77}
75 78
76static struct rb_node *saved_value_new(struct rblist *rblist __maybe_unused, 79static struct rb_node *saved_value_new(struct rblist *rblist __maybe_unused,
@@ -85,13 +88,12 @@ static struct rb_node *saved_value_new(struct rblist *rblist __maybe_unused,
85} 88}
86 89
87static struct saved_value *saved_value_lookup(struct perf_evsel *evsel, 90static struct saved_value *saved_value_lookup(struct perf_evsel *evsel,
88 int cpu, int ctx, 91 int cpu,
89 bool create) 92 bool create)
90{ 93{
91 struct rb_node *nd; 94 struct rb_node *nd;
92 struct saved_value dm = { 95 struct saved_value dm = {
93 .cpu = cpu, 96 .cpu = cpu,
94 .ctx = ctx,
95 .evsel = evsel, 97 .evsel = evsel,
96 }; 98 };
97 nd = rblist__find(&runtime_saved_values, &dm); 99 nd = rblist__find(&runtime_saved_values, &dm);
@@ -177,59 +179,60 @@ void perf_stat__reset_shadow_stats(void)
177 * more semantic information such as miss/hit ratios, 179 * more semantic information such as miss/hit ratios,
178 * instruction rates, etc: 180 * instruction rates, etc:
179 */ 181 */
180void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count, 182void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count,
181 int cpu) 183 int cpu)
182{ 184{
183 int ctx = evsel_context(counter); 185 int ctx = evsel_context(counter);
184 186
187 count *= counter->scale;
188
185 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK) || 189 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK) ||
186 perf_evsel__match(counter, SOFTWARE, SW_CPU_CLOCK)) 190 perf_evsel__match(counter, SOFTWARE, SW_CPU_CLOCK))
187 update_stats(&runtime_nsecs_stats[cpu], count[0]); 191 update_stats(&runtime_nsecs_stats[cpu], count);
188 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 192 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
189 update_stats(&runtime_cycles_stats[ctx][cpu], count[0]); 193 update_stats(&runtime_cycles_stats[ctx][cpu], count);
190 else if (perf_stat_evsel__is(counter, CYCLES_IN_TX)) 194 else if (perf_stat_evsel__is(counter, CYCLES_IN_TX))
191 update_stats(&runtime_cycles_in_tx_stats[ctx][cpu], count[0]); 195 update_stats(&runtime_cycles_in_tx_stats[ctx][cpu], count);
192 else if (perf_stat_evsel__is(counter, TRANSACTION_START)) 196 else if (perf_stat_evsel__is(counter, TRANSACTION_START))
193 update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); 197 update_stats(&runtime_transaction_stats[ctx][cpu], count);
194 else if (perf_stat_evsel__is(counter, ELISION_START)) 198 else if (perf_stat_evsel__is(counter, ELISION_START))
195 update_stats(&runtime_elision_stats[ctx][cpu], count[0]); 199 update_stats(&runtime_elision_stats[ctx][cpu], count);
196 else if (perf_stat_evsel__is(counter, TOPDOWN_TOTAL_SLOTS)) 200 else if (perf_stat_evsel__is(counter, TOPDOWN_TOTAL_SLOTS))
197 update_stats(&runtime_topdown_total_slots[ctx][cpu], count[0]); 201 update_stats(&runtime_topdown_total_slots[ctx][cpu], count);
198 else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_ISSUED)) 202 else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_ISSUED))
199 update_stats(&runtime_topdown_slots_issued[ctx][cpu], count[0]); 203 update_stats(&runtime_topdown_slots_issued[ctx][cpu], count);
200 else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_RETIRED)) 204 else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_RETIRED))
201 update_stats(&runtime_topdown_slots_retired[ctx][cpu], count[0]); 205 update_stats(&runtime_topdown_slots_retired[ctx][cpu], count);
202 else if (perf_stat_evsel__is(counter, TOPDOWN_FETCH_BUBBLES)) 206 else if (perf_stat_evsel__is(counter, TOPDOWN_FETCH_BUBBLES))
203 update_stats(&runtime_topdown_fetch_bubbles[ctx][cpu],count[0]); 207 update_stats(&runtime_topdown_fetch_bubbles[ctx][cpu], count);
204 else if (perf_stat_evsel__is(counter, TOPDOWN_RECOVERY_BUBBLES)) 208 else if (perf_stat_evsel__is(counter, TOPDOWN_RECOVERY_BUBBLES))
205 update_stats(&runtime_topdown_recovery_bubbles[ctx][cpu], count[0]); 209 update_stats(&runtime_topdown_recovery_bubbles[ctx][cpu], count);
206 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) 210 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
207 update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]); 211 update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count);
208 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) 212 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
209 update_stats(&runtime_stalled_cycles_back_stats[ctx][cpu], count[0]); 213 update_stats(&runtime_stalled_cycles_back_stats[ctx][cpu], count);
210 else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) 214 else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
211 update_stats(&runtime_branches_stats[ctx][cpu], count[0]); 215 update_stats(&runtime_branches_stats[ctx][cpu], count);
212 else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES)) 216 else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES))
213 update_stats(&runtime_cacherefs_stats[ctx][cpu], count[0]); 217 update_stats(&runtime_cacherefs_stats[ctx][cpu], count);
214 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D)) 218 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D))
215 update_stats(&runtime_l1_dcache_stats[ctx][cpu], count[0]); 219 update_stats(&runtime_l1_dcache_stats[ctx][cpu], count);
216 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I)) 220 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I))
217 update_stats(&runtime_ll_cache_stats[ctx][cpu], count[0]); 221 update_stats(&runtime_ll_cache_stats[ctx][cpu], count);
218 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL)) 222 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL))
219 update_stats(&runtime_ll_cache_stats[ctx][cpu], count[0]); 223 update_stats(&runtime_ll_cache_stats[ctx][cpu], count);
220 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB)) 224 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB))
221 update_stats(&runtime_dtlb_cache_stats[ctx][cpu], count[0]); 225 update_stats(&runtime_dtlb_cache_stats[ctx][cpu], count);
222 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB)) 226 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
223 update_stats(&runtime_itlb_cache_stats[ctx][cpu], count[0]); 227 update_stats(&runtime_itlb_cache_stats[ctx][cpu], count);
224 else if (perf_stat_evsel__is(counter, SMI_NUM)) 228 else if (perf_stat_evsel__is(counter, SMI_NUM))
225 update_stats(&runtime_smi_num_stats[ctx][cpu], count[0]); 229 update_stats(&runtime_smi_num_stats[ctx][cpu], count);
226 else if (perf_stat_evsel__is(counter, APERF)) 230 else if (perf_stat_evsel__is(counter, APERF))
227 update_stats(&runtime_aperf_stats[ctx][cpu], count[0]); 231 update_stats(&runtime_aperf_stats[ctx][cpu], count);
228 232
229 if (counter->collect_stat) { 233 if (counter->collect_stat) {
230 struct saved_value *v = saved_value_lookup(counter, cpu, ctx, 234 struct saved_value *v = saved_value_lookup(counter, cpu, true);
231 true); 235 update_stats(&v->stats, count);
232 update_stats(&v->stats, count[0]);
233 } 236 }
234} 237}
235 238
@@ -623,15 +626,68 @@ static void print_smi_cost(int cpu, struct perf_evsel *evsel,
623 out->print_metric(out->ctx, NULL, "%4.0f", "SMI#", smi_num); 626 out->print_metric(out->ctx, NULL, "%4.0f", "SMI#", smi_num);
624} 627}
625 628
629static void generic_metric(const char *metric_expr,
630 struct perf_evsel **metric_events,
631 char *name,
632 const char *metric_name,
633 double avg,
634 int cpu,
635 struct perf_stat_output_ctx *out)
636{
637 print_metric_t print_metric = out->print_metric;
638 struct parse_ctx pctx;
639 double ratio;
640 int i;
641 void *ctxp = out->ctx;
642
643 expr__ctx_init(&pctx);
644 expr__add_id(&pctx, name, avg);
645 for (i = 0; metric_events[i]; i++) {
646 struct saved_value *v;
647 struct stats *stats;
648 double scale;
649
650 if (!strcmp(metric_events[i]->name, "duration_time")) {
651 stats = &walltime_nsecs_stats;
652 scale = 1e-9;
653 } else {
654 v = saved_value_lookup(metric_events[i], cpu, false);
655 if (!v)
656 break;
657 stats = &v->stats;
658 scale = 1.0;
659 }
660 expr__add_id(&pctx, metric_events[i]->name, avg_stats(stats)*scale);
661 }
662 if (!metric_events[i]) {
663 const char *p = metric_expr;
664
665 if (expr__parse(&ratio, &pctx, &p) == 0)
666 print_metric(ctxp, NULL, "%8.1f",
667 metric_name ?
668 metric_name :
669 out->force_header ? name : "",
670 ratio);
671 else
672 print_metric(ctxp, NULL, NULL,
673 out->force_header ?
674 (metric_name ? metric_name : name) : "", 0);
675 } else
676 print_metric(ctxp, NULL, NULL, "", 0);
677}
678
626void perf_stat__print_shadow_stats(struct perf_evsel *evsel, 679void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
627 double avg, int cpu, 680 double avg, int cpu,
628 struct perf_stat_output_ctx *out) 681 struct perf_stat_output_ctx *out,
682 struct rblist *metric_events)
629{ 683{
630 void *ctxp = out->ctx; 684 void *ctxp = out->ctx;
631 print_metric_t print_metric = out->print_metric; 685 print_metric_t print_metric = out->print_metric;
632 double total, ratio = 0.0, total2; 686 double total, ratio = 0.0, total2;
633 const char *color = NULL; 687 const char *color = NULL;
634 int ctx = evsel_context(evsel); 688 int ctx = evsel_context(evsel);
689 struct metric_event *me;
690 int num = 1;
635 691
636 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { 692 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
637 total = avg_stats(&runtime_cycles_stats[ctx][cpu]); 693 total = avg_stats(&runtime_cycles_stats[ctx][cpu]);
@@ -815,33 +871,8 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
815 else 871 else
816 print_metric(ctxp, NULL, NULL, name, 0); 872 print_metric(ctxp, NULL, NULL, name, 0);
817 } else if (evsel->metric_expr) { 873 } else if (evsel->metric_expr) {
818 struct parse_ctx pctx; 874 generic_metric(evsel->metric_expr, evsel->metric_events, evsel->name,
819 int i; 875 evsel->metric_name, avg, cpu, out);
820
821 expr__ctx_init(&pctx);
822 expr__add_id(&pctx, evsel->name, avg);
823 for (i = 0; evsel->metric_events[i]; i++) {
824 struct saved_value *v;
825
826 v = saved_value_lookup(evsel->metric_events[i], cpu, ctx, false);
827 if (!v)
828 break;
829 expr__add_id(&pctx, evsel->metric_events[i]->name,
830 avg_stats(&v->stats));
831 }
832 if (!evsel->metric_events[i]) {
833 const char *p = evsel->metric_expr;
834
835 if (expr__parse(&ratio, &pctx, &p) == 0)
836 print_metric(ctxp, NULL, "%8.1f",
837 evsel->metric_name ?
838 evsel->metric_name :
839 out->force_header ? evsel->name : "",
840 ratio);
841 else
842 print_metric(ctxp, NULL, NULL, "", 0);
843 } else
844 print_metric(ctxp, NULL, NULL, "", 0);
845 } else if (runtime_nsecs_stats[cpu].n != 0) { 876 } else if (runtime_nsecs_stats[cpu].n != 0) {
846 char unit = 'M'; 877 char unit = 'M';
847 char unit_buf[10]; 878 char unit_buf[10];
@@ -859,6 +890,20 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
859 } else if (perf_stat_evsel__is(evsel, SMI_NUM)) { 890 } else if (perf_stat_evsel__is(evsel, SMI_NUM)) {
860 print_smi_cost(cpu, evsel, out); 891 print_smi_cost(cpu, evsel, out);
861 } else { 892 } else {
862 print_metric(ctxp, NULL, NULL, NULL, 0); 893 num = 0;
863 } 894 }
895
896 if ((me = metricgroup__lookup(metric_events, evsel, false)) != NULL) {
897 struct metric_expr *mexp;
898
899 list_for_each_entry (mexp, &me->head, nd) {
900 if (num++ > 0)
901 out->new_line(ctxp);
902 generic_metric(mexp->metric_expr, mexp->metric_events,
903 evsel->name, mexp->metric_name,
904 avg, cpu, out);
905 }
906 }
907 if (num == 0)
908 print_metric(ctxp, NULL, NULL, NULL, 0);
864} 909}
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 53b9a994a3dc..151e9efd7286 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <inttypes.h> 3#include <inttypes.h>
3#include <math.h> 4#include <math.h>
@@ -69,7 +70,7 @@ double rel_stddev_stats(double stddev, double avg)
69bool __perf_evsel_stat__is(struct perf_evsel *evsel, 70bool __perf_evsel_stat__is(struct perf_evsel *evsel,
70 enum perf_stat_evsel_id id) 71 enum perf_stat_evsel_id id)
71{ 72{
72 struct perf_stat_evsel *ps = evsel->priv; 73 struct perf_stat_evsel *ps = evsel->stats;
73 74
74 return ps->id == id; 75 return ps->id == id;
75} 76}
@@ -93,7 +94,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
93 94
94void perf_stat_evsel_id_init(struct perf_evsel *evsel) 95void perf_stat_evsel_id_init(struct perf_evsel *evsel)
95{ 96{
96 struct perf_stat_evsel *ps = evsel->priv; 97 struct perf_stat_evsel *ps = evsel->stats;
97 int i; 98 int i;
98 99
99 /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */ 100 /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
@@ -109,7 +110,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
109static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) 110static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
110{ 111{
111 int i; 112 int i;
112 struct perf_stat_evsel *ps = evsel->priv; 113 struct perf_stat_evsel *ps = evsel->stats;
113 114
114 for (i = 0; i < 3; i++) 115 for (i = 0; i < 3; i++)
115 init_stats(&ps->res_stats[i]); 116 init_stats(&ps->res_stats[i]);
@@ -119,8 +120,8 @@ static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
119 120
120static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) 121static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
121{ 122{
122 evsel->priv = zalloc(sizeof(struct perf_stat_evsel)); 123 evsel->stats = zalloc(sizeof(struct perf_stat_evsel));
123 if (evsel->priv == NULL) 124 if (evsel->stats == NULL)
124 return -ENOMEM; 125 return -ENOMEM;
125 perf_evsel__reset_stat_priv(evsel); 126 perf_evsel__reset_stat_priv(evsel);
126 return 0; 127 return 0;
@@ -128,7 +129,11 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
128 129
129static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) 130static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
130{ 131{
131 zfree(&evsel->priv); 132 struct perf_stat_evsel *ps = evsel->stats;
133
134 if (ps)
135 free(ps->group_data);
136 zfree(&evsel->stats);
132} 137}
133 138
134static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, 139static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
@@ -273,7 +278,9 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel
273 perf_evsel__compute_deltas(evsel, cpu, thread, count); 278 perf_evsel__compute_deltas(evsel, cpu, thread, count);
274 perf_counts_values__scale(count, config->scale, NULL); 279 perf_counts_values__scale(count, config->scale, NULL);
275 if (config->aggr_mode == AGGR_NONE) 280 if (config->aggr_mode == AGGR_NONE)
276 perf_stat__update_shadow_stats(evsel, count->values, cpu); 281 perf_stat__update_shadow_stats(evsel, count->val, cpu);
282 if (config->aggr_mode == AGGR_THREAD)
283 perf_stat__update_shadow_stats(evsel, count->val, 0);
277 break; 284 break;
278 case AGGR_GLOBAL: 285 case AGGR_GLOBAL:
279 aggr->val += count->val; 286 aggr->val += count->val;
@@ -314,9 +321,8 @@ int perf_stat_process_counter(struct perf_stat_config *config,
314 struct perf_evsel *counter) 321 struct perf_evsel *counter)
315{ 322{
316 struct perf_counts_values *aggr = &counter->counts->aggr; 323 struct perf_counts_values *aggr = &counter->counts->aggr;
317 struct perf_stat_evsel *ps = counter->priv; 324 struct perf_stat_evsel *ps = counter->stats;
318 u64 *count = counter->counts->aggr.values; 325 u64 *count = counter->counts->aggr.values;
319 u64 val;
320 int i, ret; 326 int i, ret;
321 327
322 aggr->val = aggr->ena = aggr->run = 0; 328 aggr->val = aggr->ena = aggr->run = 0;
@@ -356,8 +362,7 @@ int perf_stat_process_counter(struct perf_stat_config *config,
356 /* 362 /*
357 * Save the full runtime - to allow normalization during printout: 363 * Save the full runtime - to allow normalization during printout:
358 */ 364 */
359 val = counter->scale * *count; 365 perf_stat__update_shadow_stats(counter, *count, 0);
360 perf_stat__update_shadow_stats(counter, &val, 0);
361 366
362 return 0; 367 return 0;
363} 368}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 7522bf10b03e..eefca5c981fd 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_STATS_H 2#ifndef __PERF_STATS_H
2#define __PERF_STATS_H 3#define __PERF_STATS_H
3 4
@@ -28,8 +29,9 @@ enum perf_stat_evsel_id {
28}; 29};
29 30
30struct perf_stat_evsel { 31struct perf_stat_evsel {
31 struct stats res_stats[3]; 32 struct stats res_stats[3];
32 enum perf_stat_evsel_id id; 33 enum perf_stat_evsel_id id;
34 u64 *group_data;
33}; 35};
34 36
35enum aggr_mode { 37enum aggr_mode {
@@ -81,7 +83,7 @@ typedef void (*new_line_t )(void *ctx);
81 83
82void perf_stat__init_shadow_stats(void); 84void perf_stat__init_shadow_stats(void);
83void perf_stat__reset_shadow_stats(void); 85void perf_stat__reset_shadow_stats(void);
84void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count, 86void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count,
85 int cpu); 87 int cpu);
86struct perf_stat_output_ctx { 88struct perf_stat_output_ctx {
87 void *ctx; 89 void *ctx;
@@ -90,9 +92,11 @@ struct perf_stat_output_ctx {
90 bool force_header; 92 bool force_header;
91}; 93};
92 94
95struct rblist;
93void perf_stat__print_shadow_stats(struct perf_evsel *evsel, 96void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
94 double avg, int cpu, 97 double avg, int cpu,
95 struct perf_stat_output_ctx *out); 98 struct perf_stat_output_ctx *out,
99 struct rblist *metric_events);
96void perf_stat__collect_metric_expr(struct perf_evlist *); 100void perf_stat__collect_metric_expr(struct perf_evlist *);
97 101
98int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw); 102int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw);
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index aafe908b82b5..3d1cf5bf7f18 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "debug.h" 2#include "debug.h"
2#include "util.h" 3#include "util.h"
3#include <linux/kernel.h> 4#include <linux/kernel.h>
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index 802d743378af..ea94d8628980 100644
--- a/tools/perf/util/strbuf.h
+++ b/tools/perf/util/strbuf.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_STRBUF_H 2#ifndef __PERF_STRBUF_H
2#define __PERF_STRBUF_H 3#define __PERF_STRBUF_H
3 4
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c
index 4dc0af669a30..7f3253d44afd 100644
--- a/tools/perf/util/strfilter.c
+++ b/tools/perf/util/strfilter.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "util.h" 2#include "util.h"
2#include "string2.h" 3#include "string2.h"
3#include "strfilter.h" 4#include "strfilter.h"
diff --git a/tools/perf/util/strfilter.h b/tools/perf/util/strfilter.h
index cff5eda88728..e0c25a40f796 100644
--- a/tools/perf/util/strfilter.h
+++ b/tools/perf/util/strfilter.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_STRFILTER_H 2#ifndef __PERF_STRFILTER_H
2#define __PERF_STRFILTER_H 3#define __PERF_STRFILTER_H
3/* General purpose glob matching filter */ 4/* General purpose glob matching filter */
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index cca53b693a48..aaa08ee8c717 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "string2.h" 2#include "string2.h"
2#include <linux/kernel.h> 3#include <linux/kernel.h>
3#include <linux/string.h> 4#include <linux/string.h>
diff --git a/tools/perf/util/string2.h b/tools/perf/util/string2.h
index 2f619681bd6a..ee14ca5451ab 100644
--- a/tools/perf/util/string2.h
+++ b/tools/perf/util/string2.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PERF_STRING_H 2#ifndef PERF_STRING_H
2#define PERF_STRING_H 3#define PERF_STRING_H
3 4
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h
index 19207e50fce5..d58f1e08b170 100644
--- a/tools/perf/util/strlist.h
+++ b/tools/perf/util/strlist.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_STRLIST_H 2#ifndef __PERF_STRLIST_H
2#define __PERF_STRLIST_H 3#define __PERF_STRLIST_H
3 4
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index 946fdf2db97c..e55338d5c3bd 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_SVGHELPER_H 2#ifndef __PERF_SVGHELPER_H
2#define __PERF_SVGHELPER_H 3#define __PERF_SVGHELPER_H
3 4
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 502505cf236a..2de770511e70 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <fcntl.h> 2#include <fcntl.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <errno.h> 4#include <errno.h>
@@ -259,7 +260,7 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
259{ 260{
260 uint32_t nr_rel_entries, idx; 261 uint32_t nr_rel_entries, idx;
261 GElf_Sym sym; 262 GElf_Sym sym;
262 u64 plt_offset; 263 u64 plt_offset, plt_header_size, plt_entry_size;
263 GElf_Shdr shdr_plt; 264 GElf_Shdr shdr_plt;
264 struct symbol *f; 265 struct symbol *f;
265 GElf_Shdr shdr_rel_plt, shdr_dynsym; 266 GElf_Shdr shdr_rel_plt, shdr_dynsym;
@@ -326,6 +327,23 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
326 327
327 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; 328 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
328 plt_offset = shdr_plt.sh_offset; 329 plt_offset = shdr_plt.sh_offset;
330 switch (ehdr.e_machine) {
331 case EM_ARM:
332 plt_header_size = 20;
333 plt_entry_size = 12;
334 break;
335
336 case EM_AARCH64:
337 plt_header_size = 32;
338 plt_entry_size = 16;
339 break;
340
341 default: /* FIXME: s390/alpha/mips/parisc/poperpc/sh/sparc/xtensa need to be checked */
342 plt_header_size = shdr_plt.sh_entsize;
343 plt_entry_size = shdr_plt.sh_entsize;
344 break;
345 }
346 plt_offset += plt_header_size;
329 347
330 if (shdr_rel_plt.sh_type == SHT_RELA) { 348 if (shdr_rel_plt.sh_type == SHT_RELA) {
331 GElf_Rela pos_mem, *pos; 349 GElf_Rela pos_mem, *pos;
@@ -335,7 +353,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
335 const char *elf_name = NULL; 353 const char *elf_name = NULL;
336 char *demangled = NULL; 354 char *demangled = NULL;
337 symidx = GELF_R_SYM(pos->r_info); 355 symidx = GELF_R_SYM(pos->r_info);
338 plt_offset += shdr_plt.sh_entsize;
339 gelf_getsym(syms, symidx, &sym); 356 gelf_getsym(syms, symidx, &sym);
340 357
341 elf_name = elf_sym__name(&sym, symstrs); 358 elf_name = elf_sym__name(&sym, symstrs);
@@ -346,11 +363,12 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
346 "%s@plt", elf_name); 363 "%s@plt", elf_name);
347 free(demangled); 364 free(demangled);
348 365
349 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 366 f = symbol__new(plt_offset, plt_entry_size,
350 STB_GLOBAL, sympltname); 367 STB_GLOBAL, sympltname);
351 if (!f) 368 if (!f)
352 goto out_elf_end; 369 goto out_elf_end;
353 370
371 plt_offset += plt_entry_size;
354 symbols__insert(&dso->symbols[map->type], f); 372 symbols__insert(&dso->symbols[map->type], f);
355 ++nr; 373 ++nr;
356 } 374 }
@@ -361,7 +379,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
361 const char *elf_name = NULL; 379 const char *elf_name = NULL;
362 char *demangled = NULL; 380 char *demangled = NULL;
363 symidx = GELF_R_SYM(pos->r_info); 381 symidx = GELF_R_SYM(pos->r_info);
364 plt_offset += shdr_plt.sh_entsize;
365 gelf_getsym(syms, symidx, &sym); 382 gelf_getsym(syms, symidx, &sym);
366 383
367 elf_name = elf_sym__name(&sym, symstrs); 384 elf_name = elf_sym__name(&sym, symstrs);
@@ -372,11 +389,12 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
372 "%s@plt", elf_name); 389 "%s@plt", elf_name);
373 free(demangled); 390 free(demangled);
374 391
375 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 392 f = symbol__new(plt_offset, plt_entry_size,
376 STB_GLOBAL, sympltname); 393 STB_GLOBAL, sympltname);
377 if (!f) 394 if (!f)
378 goto out_elf_end; 395 goto out_elf_end;
379 396
397 plt_offset += plt_entry_size;
380 symbols__insert(&dso->symbols[map->type], f); 398 symbols__insert(&dso->symbols[map->type], f);
381 ++nr; 399 ++nr;
382 } 400 }
@@ -391,7 +409,7 @@ out_elf_end:
391 return 0; 409 return 0;
392} 410}
393 411
394char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name) 412char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
395{ 413{
396 return demangle_sym(dso, kmodule, elf_name); 414 return demangle_sym(dso, kmodule, elf_name);
397} 415}
@@ -1442,7 +1460,7 @@ static int kcore_copy__parse_kallsyms(struct kcore_copy_info *kci,
1442 1460
1443static int kcore_copy__process_modules(void *arg, 1461static int kcore_copy__process_modules(void *arg,
1444 const char *name __maybe_unused, 1462 const char *name __maybe_unused,
1445 u64 start) 1463 u64 start, u64 size __maybe_unused)
1446{ 1464{
1447 struct kcore_copy_info *kci = arg; 1465 struct kcore_copy_info *kci = arg;
1448 1466
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 40bf5d4c0bfd..ff48d0d49584 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "symbol.h" 2#include "symbol.h"
2#include "util.h" 3#include "util.h"
3 4
@@ -377,7 +378,7 @@ void symbol__elf_init(void)
377 378
378char *dso__demangle_sym(struct dso *dso __maybe_unused, 379char *dso__demangle_sym(struct dso *dso __maybe_unused,
379 int kmodule __maybe_unused, 380 int kmodule __maybe_unused,
380 char *elf_name __maybe_unused) 381 const char *elf_name __maybe_unused)
381{ 382{
382 return NULL; 383 return NULL;
383} 384}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e7a98dbd2aed..1b67a8639dfe 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <dirent.h> 2#include <dirent.h>
2#include <errno.h> 3#include <errno.h>
3#include <stdlib.h> 4#include <stdlib.h>
@@ -18,6 +19,7 @@
18#include "symbol.h" 19#include "symbol.h"
19#include "strlist.h" 20#include "strlist.h"
20#include "intlist.h" 21#include "intlist.h"
22#include "namespaces.h"
21#include "header.h" 23#include "header.h"
22#include "path.h" 24#include "path.h"
23#include "sane_ctype.h" 25#include "sane_ctype.h"
@@ -44,6 +46,7 @@ struct symbol_conf symbol_conf = {
44 .show_hist_headers = true, 46 .show_hist_headers = true,
45 .symfs = "", 47 .symfs = "",
46 .event_group = true, 48 .event_group = true,
49 .inline_name = true,
47}; 50};
48 51
49static enum dso_binary_type binary_type_symtab[] = { 52static enum dso_binary_type binary_type_symtab[] = {
@@ -52,6 +55,7 @@ static enum dso_binary_type binary_type_symtab[] = {
52 DSO_BINARY_TYPE__JAVA_JIT, 55 DSO_BINARY_TYPE__JAVA_JIT,
53 DSO_BINARY_TYPE__DEBUGLINK, 56 DSO_BINARY_TYPE__DEBUGLINK,
54 DSO_BINARY_TYPE__BUILD_ID_CACHE, 57 DSO_BINARY_TYPE__BUILD_ID_CACHE,
58 DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
55 DSO_BINARY_TYPE__FEDORA_DEBUGINFO, 59 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
56 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO, 60 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
57 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 61 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
@@ -224,14 +228,15 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
224 struct maps *maps = &mg->maps[type]; 228 struct maps *maps = &mg->maps[type];
225 struct map *next, *curr; 229 struct map *next, *curr;
226 230
227 pthread_rwlock_wrlock(&maps->lock); 231 down_write(&maps->lock);
228 232
229 curr = maps__first(maps); 233 curr = maps__first(maps);
230 if (curr == NULL) 234 if (curr == NULL)
231 goto out_unlock; 235 goto out_unlock;
232 236
233 for (next = map__next(curr); next; next = map__next(curr)) { 237 for (next = map__next(curr); next; next = map__next(curr)) {
234 curr->end = next->start; 238 if (!curr->end)
239 curr->end = next->start;
235 curr = next; 240 curr = next;
236 } 241 }
237 242
@@ -239,10 +244,11 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
239 * We still haven't the actual symbols, so guess the 244 * We still haven't the actual symbols, so guess the
240 * last map final address. 245 * last map final address.
241 */ 246 */
242 curr->end = ~0ULL; 247 if (!curr->end)
248 curr->end = ~0ULL;
243 249
244out_unlock: 250out_unlock:
245 pthread_rwlock_unlock(&maps->lock); 251 up_write(&maps->lock);
246} 252}
247 253
248struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name) 254struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
@@ -550,7 +556,7 @@ void dso__sort_by_name(struct dso *dso, enum map_type type)
550 556
551int modules__parse(const char *filename, void *arg, 557int modules__parse(const char *filename, void *arg,
552 int (*process_module)(void *arg, const char *name, 558 int (*process_module)(void *arg, const char *name,
553 u64 start)) 559 u64 start, u64 size))
554{ 560{
555 char *line = NULL; 561 char *line = NULL;
556 size_t n; 562 size_t n;
@@ -563,8 +569,8 @@ int modules__parse(const char *filename, void *arg,
563 569
564 while (1) { 570 while (1) {
565 char name[PATH_MAX]; 571 char name[PATH_MAX];
566 u64 start; 572 u64 start, size;
567 char *sep; 573 char *sep, *endptr;
568 ssize_t line_len; 574 ssize_t line_len;
569 575
570 line_len = getline(&line, &n, file); 576 line_len = getline(&line, &n, file);
@@ -596,7 +602,11 @@ int modules__parse(const char *filename, void *arg,
596 602
597 scnprintf(name, sizeof(name), "[%s]", line); 603 scnprintf(name, sizeof(name), "[%s]", line);
598 604
599 err = process_module(arg, name, start); 605 size = strtoul(sep + 1, &endptr, 0);
606 if (*endptr != ' ' && *endptr != '\t')
607 continue;
608
609 err = process_module(arg, name, start, size);
600 if (err) 610 if (err)
601 break; 611 break;
602 } 612 }
@@ -943,7 +953,8 @@ static struct module_info *find_module(const char *name,
943 return NULL; 953 return NULL;
944} 954}
945 955
946static int __read_proc_modules(void *arg, const char *name, u64 start) 956static int __read_proc_modules(void *arg, const char *name, u64 start,
957 u64 size __maybe_unused)
947{ 958{
948 struct rb_root *modules = arg; 959 struct rb_root *modules = arg;
949 struct module_info *mi; 960 struct module_info *mi;
@@ -1325,14 +1336,15 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
1325 return __dso__load_kallsyms(dso, filename, map, false); 1336 return __dso__load_kallsyms(dso, filename, map, false);
1326} 1337}
1327 1338
1328static int dso__load_perf_map(struct dso *dso, struct map *map) 1339static int dso__load_perf_map(const char *map_path, struct dso *dso,
1340 struct map *map)
1329{ 1341{
1330 char *line = NULL; 1342 char *line = NULL;
1331 size_t n; 1343 size_t n;
1332 FILE *file; 1344 FILE *file;
1333 int nr_syms = 0; 1345 int nr_syms = 0;
1334 1346
1335 file = fopen(dso->long_name, "r"); 1347 file = fopen(map_path, "r");
1336 if (file == NULL) 1348 if (file == NULL)
1337 goto out_failure; 1349 goto out_failure;
1338 1350
@@ -1416,6 +1428,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1416 return kmod && dso->symtab_type == type; 1428 return kmod && dso->symtab_type == type;
1417 1429
1418 case DSO_BINARY_TYPE__BUILD_ID_CACHE: 1430 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
1431 case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
1419 return true; 1432 return true;
1420 1433
1421 case DSO_BINARY_TYPE__NOT_FOUND: 1434 case DSO_BINARY_TYPE__NOT_FOUND:
@@ -1424,6 +1437,44 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1424 } 1437 }
1425} 1438}
1426 1439
1440/* Checks for the existence of the perf-<pid>.map file in two different
1441 * locations. First, if the process is a separate mount namespace, check in
1442 * that namespace using the pid of the innermost pid namespace. If's not in a
1443 * namespace, or the file can't be found there, try in the mount namespace of
1444 * the tracing process using our view of its pid.
1445 */
1446static int dso__find_perf_map(char *filebuf, size_t bufsz,
1447 struct nsinfo **nsip)
1448{
1449 struct nscookie nsc;
1450 struct nsinfo *nsi;
1451 struct nsinfo *nnsi;
1452 int rc = -1;
1453
1454 nsi = *nsip;
1455
1456 if (nsi->need_setns) {
1457 snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nsi->nstgid);
1458 nsinfo__mountns_enter(nsi, &nsc);
1459 rc = access(filebuf, R_OK);
1460 nsinfo__mountns_exit(&nsc);
1461 if (rc == 0)
1462 return rc;
1463 }
1464
1465 nnsi = nsinfo__copy(nsi);
1466 if (nnsi) {
1467 nsinfo__put(nsi);
1468
1469 nnsi->need_setns = false;
1470 snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nnsi->tgid);
1471 *nsip = nnsi;
1472 rc = 0;
1473 }
1474
1475 return rc;
1476}
1477
1427int dso__load(struct dso *dso, struct map *map) 1478int dso__load(struct dso *dso, struct map *map)
1428{ 1479{
1429 char *name; 1480 char *name;
@@ -1435,8 +1486,21 @@ int dso__load(struct dso *dso, struct map *map)
1435 struct symsrc ss_[2]; 1486 struct symsrc ss_[2];
1436 struct symsrc *syms_ss = NULL, *runtime_ss = NULL; 1487 struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
1437 bool kmod; 1488 bool kmod;
1489 bool perfmap;
1438 unsigned char build_id[BUILD_ID_SIZE]; 1490 unsigned char build_id[BUILD_ID_SIZE];
1491 struct nscookie nsc;
1492 char newmapname[PATH_MAX];
1493 const char *map_path = dso->long_name;
1494
1495 perfmap = strncmp(dso->name, "/tmp/perf-", 10) == 0;
1496 if (perfmap) {
1497 if (dso->nsinfo && (dso__find_perf_map(newmapname,
1498 sizeof(newmapname), &dso->nsinfo) == 0)) {
1499 map_path = newmapname;
1500 }
1501 }
1439 1502
1503 nsinfo__mountns_enter(dso->nsinfo, &nsc);
1440 pthread_mutex_lock(&dso->lock); 1504 pthread_mutex_lock(&dso->lock);
1441 1505
1442 /* check again under the dso->lock */ 1506 /* check again under the dso->lock */
@@ -1461,19 +1525,19 @@ int dso__load(struct dso *dso, struct map *map)
1461 1525
1462 dso->adjust_symbols = 0; 1526 dso->adjust_symbols = 0;
1463 1527
1464 if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { 1528 if (perfmap) {
1465 struct stat st; 1529 struct stat st;
1466 1530
1467 if (lstat(dso->name, &st) < 0) 1531 if (lstat(map_path, &st) < 0)
1468 goto out; 1532 goto out;
1469 1533
1470 if (!symbol_conf.force && st.st_uid && (st.st_uid != geteuid())) { 1534 if (!symbol_conf.force && st.st_uid && (st.st_uid != geteuid())) {
1471 pr_warning("File %s not owned by current user or root, " 1535 pr_warning("File %s not owned by current user or root, "
1472 "ignoring it (use -f to override).\n", dso->name); 1536 "ignoring it (use -f to override).\n", map_path);
1473 goto out; 1537 goto out;
1474 } 1538 }
1475 1539
1476 ret = dso__load_perf_map(dso, map); 1540 ret = dso__load_perf_map(map_path, dso, map);
1477 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : 1541 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
1478 DSO_BINARY_TYPE__NOT_FOUND; 1542 DSO_BINARY_TYPE__NOT_FOUND;
1479 goto out; 1543 goto out;
@@ -1511,9 +1575,15 @@ int dso__load(struct dso *dso, struct map *map)
1511 for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) { 1575 for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) {
1512 struct symsrc *ss = &ss_[ss_pos]; 1576 struct symsrc *ss = &ss_[ss_pos];
1513 bool next_slot = false; 1577 bool next_slot = false;
1578 bool is_reg;
1579 bool nsexit;
1580 int sirc;
1514 1581
1515 enum dso_binary_type symtab_type = binary_type_symtab[i]; 1582 enum dso_binary_type symtab_type = binary_type_symtab[i];
1516 1583
1584 nsexit = (symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE ||
1585 symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO);
1586
1517 if (!dso__is_compatible_symtab_type(dso, kmod, symtab_type)) 1587 if (!dso__is_compatible_symtab_type(dso, kmod, symtab_type))
1518 continue; 1588 continue;
1519 1589
@@ -1521,12 +1591,20 @@ int dso__load(struct dso *dso, struct map *map)
1521 root_dir, name, PATH_MAX)) 1591 root_dir, name, PATH_MAX))
1522 continue; 1592 continue;
1523 1593
1524 if (!is_regular_file(name)) 1594 if (nsexit)
1525 continue; 1595 nsinfo__mountns_exit(&nsc);
1596
1597 is_reg = is_regular_file(name);
1598 sirc = symsrc__init(ss, dso, name, symtab_type);
1526 1599
1527 /* Name is now the name of the next image to try */ 1600 if (nsexit)
1528 if (symsrc__init(ss, dso, name, symtab_type) < 0) 1601 nsinfo__mountns_enter(dso->nsinfo, &nsc);
1602
1603 if (!is_reg || sirc < 0) {
1604 if (sirc >= 0)
1605 symsrc__destroy(ss);
1529 continue; 1606 continue;
1607 }
1530 1608
1531 if (!syms_ss && symsrc__has_symtab(ss)) { 1609 if (!syms_ss && symsrc__has_symtab(ss)) {
1532 syms_ss = ss; 1610 syms_ss = ss;
@@ -1584,6 +1662,7 @@ out_free:
1584out: 1662out:
1585 dso__set_loaded(dso, map->type); 1663 dso__set_loaded(dso, map->type);
1586 pthread_mutex_unlock(&dso->lock); 1664 pthread_mutex_unlock(&dso->lock);
1665 nsinfo__mountns_exit(&nsc);
1587 1666
1588 return ret; 1667 return ret;
1589} 1668}
@@ -1594,7 +1673,7 @@ struct map *map_groups__find_by_name(struct map_groups *mg,
1594 struct maps *maps = &mg->maps[type]; 1673 struct maps *maps = &mg->maps[type];
1595 struct map *map; 1674 struct map *map;
1596 1675
1597 pthread_rwlock_rdlock(&maps->lock); 1676 down_read(&maps->lock);
1598 1677
1599 for (map = maps__first(maps); map; map = map__next(map)) { 1678 for (map = maps__first(maps); map; map = map__next(map)) {
1600 if (map->dso && strcmp(map->dso->short_name, name) == 0) 1679 if (map->dso && strcmp(map->dso->short_name, name) == 0)
@@ -1604,7 +1683,7 @@ struct map *map_groups__find_by_name(struct map_groups *mg,
1604 map = NULL; 1683 map = NULL;
1605 1684
1606out_unlock: 1685out_unlock:
1607 pthread_rwlock_unlock(&maps->lock); 1686 up_read(&maps->lock);
1608 return map; 1687 return map;
1609} 1688}
1610 1689
@@ -1660,7 +1739,7 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map)
1660 } 1739 }
1661 1740
1662 if (!symbol_conf.ignore_vmlinux_buildid) 1741 if (!symbol_conf.ignore_vmlinux_buildid)
1663 filename = dso__build_id_filename(dso, NULL, 0); 1742 filename = dso__build_id_filename(dso, NULL, 0, false);
1664 if (filename != NULL) { 1743 if (filename != NULL) {
1665 err = dso__load_vmlinux(dso, map, filename, true); 1744 err = dso__load_vmlinux(dso, map, filename, true);
1666 if (err > 0) 1745 if (err > 0)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 41ebba9a2eb2..a4f0075b4e5c 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_SYMBOL 2#ifndef __PERF_SYMBOL
2#define __PERF_SYMBOL 1 3#define __PERF_SYMBOL 1
3 4
@@ -59,6 +60,7 @@ struct symbol {
59 u8 binding; 60 u8 binding;
60 u8 idle:1; 61 u8 idle:1;
61 u8 ignore:1; 62 u8 ignore:1;
63 u8 inlined:1;
62 u8 arch_sym; 64 u8 arch_sym;
63 char name[0]; 65 char name[0];
64}; 66};
@@ -186,6 +188,7 @@ struct addr_map_symbol {
186 struct symbol *sym; 188 struct symbol *sym;
187 u64 addr; 189 u64 addr;
188 u64 al_addr; 190 u64 al_addr;
191 u64 phys_addr;
189}; 192};
190 193
191struct branch_info { 194struct branch_info {
@@ -207,6 +210,7 @@ struct addr_location {
207 struct thread *thread; 210 struct thread *thread;
208 struct map *map; 211 struct map *map;
209 struct symbol *sym; 212 struct symbol *sym;
213 const char *srcline;
210 u64 addr; 214 u64 addr;
211 char level; 215 char level;
212 u8 filtered; 216 u8 filtered;
@@ -273,7 +277,7 @@ int filename__read_build_id(const char *filename, void *bf, size_t size);
273int sysfs__read_build_id(const char *filename, void *bf, size_t size); 277int sysfs__read_build_id(const char *filename, void *bf, size_t size);
274int modules__parse(const char *filename, void *arg, 278int modules__parse(const char *filename, void *arg,
275 int (*process_module)(void *arg, const char *name, 279 int (*process_module)(void *arg, const char *name,
276 u64 start)); 280 u64 start, u64 size));
277int filename__read_debuglink(const char *filename, char *debuglink, 281int filename__read_debuglink(const char *filename, char *debuglink,
278 size_t size); 282 size_t size);
279 283
@@ -306,7 +310,7 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
306int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, 310int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss,
307 struct map *map); 311 struct map *map);
308 312
309char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name); 313char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name);
310 314
311void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel); 315void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
312void symbols__insert(struct rb_root *symbols, struct symbol *sym); 316void symbols__insert(struct rb_root *symbols, struct symbol *sym);
diff --git a/tools/perf/util/symbol_fprintf.c b/tools/perf/util/symbol_fprintf.c
index 63694e174e5c..6dd2cb88ccbe 100644
--- a/tools/perf/util/symbol_fprintf.c
+++ b/tools/perf/util/symbol_fprintf.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <elf.h> 2#include <elf.h>
2#include <inttypes.h> 3#include <inttypes.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index bbb4c1957578..6eea7cff3d4e 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -15,10 +15,11 @@
15 15
16#include "syscalltbl.h" 16#include "syscalltbl.h"
17#include <stdlib.h> 17#include <stdlib.h>
18#include <linux/compiler.h>
18 19
19#ifdef HAVE_SYSCALL_TABLE 20#ifdef HAVE_SYSCALL_TABLE
20#include <linux/compiler.h>
21#include <string.h> 21#include <string.h>
22#include "string2.h"
22#include "util.h" 23#include "util.h"
23 24
24#if defined(__x86_64__) 25#if defined(__x86_64__)
@@ -105,6 +106,27 @@ int syscalltbl__id(struct syscalltbl *tbl, const char *name)
105 return sc ? sc->id : -1; 106 return sc ? sc->id : -1;
106} 107}
107 108
109int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
110{
111 int i;
112 struct syscall *syscalls = tbl->syscalls.entries;
113
114 for (i = *idx + 1; i < tbl->syscalls.nr_entries; ++i) {
115 if (strglobmatch(syscalls[i].name, syscall_glob)) {
116 *idx = i;
117 return syscalls[i].id;
118 }
119 }
120
121 return -1;
122}
123
124int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
125{
126 *idx = -1;
127 return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
128}
129
108#else /* HAVE_SYSCALL_TABLE */ 130#else /* HAVE_SYSCALL_TABLE */
109 131
110#include <libaudit.h> 132#include <libaudit.h>
@@ -131,4 +153,15 @@ int syscalltbl__id(struct syscalltbl *tbl, const char *name)
131{ 153{
132 return audit_name_to_syscall(name, tbl->audit_machine); 154 return audit_name_to_syscall(name, tbl->audit_machine);
133} 155}
156
157int syscalltbl__strglobmatch_next(struct syscalltbl *tbl __maybe_unused,
158 const char *syscall_glob __maybe_unused, int *idx __maybe_unused)
159{
160 return -1;
161}
162
163int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
164{
165 return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
166}
134#endif /* HAVE_SYSCALL_TABLE */ 167#endif /* HAVE_SYSCALL_TABLE */
diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/util/syscalltbl.h
index e2951510484f..c8e7e9ce0f01 100644
--- a/tools/perf/util/syscalltbl.h
+++ b/tools/perf/util/syscalltbl.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_SYSCALLTBL_H 2#ifndef __PERF_SYSCALLTBL_H
2#define __PERF_SYSCALLTBL_H 3#define __PERF_SYSCALLTBL_H
3 4
@@ -17,4 +18,7 @@ void syscalltbl__delete(struct syscalltbl *tbl);
17const char *syscalltbl__name(const struct syscalltbl *tbl, int id); 18const char *syscalltbl__name(const struct syscalltbl *tbl, int id);
18int syscalltbl__id(struct syscalltbl *tbl, const char *name); 19int syscalltbl__id(struct syscalltbl *tbl, const char *name);
19 20
21int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
22int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
23
20#endif /* __PERF_SYSCALLTBL_H */ 24#endif /* __PERF_SYSCALLTBL_H */
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h
index 7381b1ca4041..446aa7a56f25 100644
--- a/tools/perf/util/target.h
+++ b/tools/perf/util/target.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_TARGET_H 2#ifndef _PERF_TARGET_H
2#define _PERF_TARGET_H 3#define _PERF_TARGET_H
3 4
diff --git a/tools/perf/util/term.c b/tools/perf/util/term.c
index 8f254a74d97d..e7aa82c06c76 100644
--- a/tools/perf/util/term.c
+++ b/tools/perf/util/term.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "term.h" 2#include "term.h"
2#include <stdlib.h> 3#include <stdlib.h>
3#include <termios.h> 4#include <termios.h>
diff --git a/tools/perf/util/term.h b/tools/perf/util/term.h
index 2c06a61846a1..607b170a9017 100644
--- a/tools/perf/util/term.h
+++ b/tools/perf/util/term.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_TERM_H 2#ifndef __PERF_TERM_H
2#define __PERF_TERM_H 3#define __PERF_TERM_H
3 4
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 378c418ca0c1..68b65b10579b 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "../perf.h" 2#include "../perf.h"
2#include <errno.h> 3#include <errno.h>
3#include <stdlib.h> 4#include <stdlib.h>
@@ -45,6 +46,8 @@ struct thread *thread__new(pid_t pid, pid_t tid)
45 thread->cpu = -1; 46 thread->cpu = -1;
46 INIT_LIST_HEAD(&thread->namespaces_list); 47 INIT_LIST_HEAD(&thread->namespaces_list);
47 INIT_LIST_HEAD(&thread->comm_list); 48 INIT_LIST_HEAD(&thread->comm_list);
49 init_rwsem(&thread->namespaces_lock);
50 init_rwsem(&thread->comm_lock);
48 51
49 comm_str = malloc(32); 52 comm_str = malloc(32);
50 if (!comm_str) 53 if (!comm_str)
@@ -59,6 +62,8 @@ struct thread *thread__new(pid_t pid, pid_t tid)
59 list_add(&comm->list, &thread->comm_list); 62 list_add(&comm->list, &thread->comm_list);
60 refcount_set(&thread->refcnt, 1); 63 refcount_set(&thread->refcnt, 1);
61 RB_CLEAR_NODE(&thread->rb_node); 64 RB_CLEAR_NODE(&thread->rb_node);
65 /* Thread holds first ref to nsdata. */
66 thread->nsinfo = nsinfo__new(pid);
62 } 67 }
63 68
64 return thread; 69 return thread;
@@ -81,17 +86,26 @@ void thread__delete(struct thread *thread)
81 map_groups__put(thread->mg); 86 map_groups__put(thread->mg);
82 thread->mg = NULL; 87 thread->mg = NULL;
83 } 88 }
89 down_write(&thread->namespaces_lock);
84 list_for_each_entry_safe(namespaces, tmp_namespaces, 90 list_for_each_entry_safe(namespaces, tmp_namespaces,
85 &thread->namespaces_list, list) { 91 &thread->namespaces_list, list) {
86 list_del(&namespaces->list); 92 list_del(&namespaces->list);
87 namespaces__free(namespaces); 93 namespaces__free(namespaces);
88 } 94 }
95 up_write(&thread->namespaces_lock);
96
97 down_write(&thread->comm_lock);
89 list_for_each_entry_safe(comm, tmp_comm, &thread->comm_list, list) { 98 list_for_each_entry_safe(comm, tmp_comm, &thread->comm_list, list) {
90 list_del(&comm->list); 99 list_del(&comm->list);
91 comm__free(comm); 100 comm__free(comm);
92 } 101 }
102 up_write(&thread->comm_lock);
103
93 unwind__finish_access(thread); 104 unwind__finish_access(thread);
105 nsinfo__zput(thread->nsinfo);
94 106
107 exit_rwsem(&thread->namespaces_lock);
108 exit_rwsem(&thread->comm_lock);
95 free(thread); 109 free(thread);
96} 110}
97 111
@@ -122,8 +136,8 @@ struct namespaces *thread__namespaces(const struct thread *thread)
122 return list_first_entry(&thread->namespaces_list, struct namespaces, list); 136 return list_first_entry(&thread->namespaces_list, struct namespaces, list);
123} 137}
124 138
125int thread__set_namespaces(struct thread *thread, u64 timestamp, 139static int __thread__set_namespaces(struct thread *thread, u64 timestamp,
126 struct namespaces_event *event) 140 struct namespaces_event *event)
127{ 141{
128 struct namespaces *new, *curr = thread__namespaces(thread); 142 struct namespaces *new, *curr = thread__namespaces(thread);
129 143
@@ -146,6 +160,17 @@ int thread__set_namespaces(struct thread *thread, u64 timestamp,
146 return 0; 160 return 0;
147} 161}
148 162
163int thread__set_namespaces(struct thread *thread, u64 timestamp,
164 struct namespaces_event *event)
165{
166 int ret;
167
168 down_write(&thread->namespaces_lock);
169 ret = __thread__set_namespaces(thread, timestamp, event);
170 up_write(&thread->namespaces_lock);
171 return ret;
172}
173
149struct comm *thread__comm(const struct thread *thread) 174struct comm *thread__comm(const struct thread *thread)
150{ 175{
151 if (list_empty(&thread->comm_list)) 176 if (list_empty(&thread->comm_list))
@@ -167,8 +192,8 @@ struct comm *thread__exec_comm(const struct thread *thread)
167 return last; 192 return last;
168} 193}
169 194
170int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, 195static int ____thread__set_comm(struct thread *thread, const char *str,
171 bool exec) 196 u64 timestamp, bool exec)
172{ 197{
173 struct comm *new, *curr = thread__comm(thread); 198 struct comm *new, *curr = thread__comm(thread);
174 199
@@ -192,6 +217,17 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
192 return 0; 217 return 0;
193} 218}
194 219
220int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
221 bool exec)
222{
223 int ret;
224
225 down_write(&thread->comm_lock);
226 ret = ____thread__set_comm(thread, str, timestamp, exec);
227 up_write(&thread->comm_lock);
228 return ret;
229}
230
195int thread__set_comm_from_proc(struct thread *thread) 231int thread__set_comm_from_proc(struct thread *thread)
196{ 232{
197 char path[64]; 233 char path[64];
@@ -209,7 +245,7 @@ int thread__set_comm_from_proc(struct thread *thread)
209 return err; 245 return err;
210} 246}
211 247
212const char *thread__comm_str(const struct thread *thread) 248static const char *__thread__comm_str(const struct thread *thread)
213{ 249{
214 const struct comm *comm = thread__comm(thread); 250 const struct comm *comm = thread__comm(thread);
215 251
@@ -219,6 +255,17 @@ const char *thread__comm_str(const struct thread *thread)
219 return comm__str(comm); 255 return comm__str(comm);
220} 256}
221 257
258const char *thread__comm_str(const struct thread *thread)
259{
260 const char *str;
261
262 down_read((struct rw_semaphore *)&thread->comm_lock);
263 str = __thread__comm_str(thread);
264 up_read((struct rw_semaphore *)&thread->comm_lock);
265
266 return str;
267}
268
222/* CHECKME: it should probably better return the max comm len from its comm list */ 269/* CHECKME: it should probably better return the max comm len from its comm list */
223int thread__comm_len(struct thread *thread) 270int thread__comm_len(struct thread *thread)
224{ 271{
@@ -261,7 +308,7 @@ static int __thread__prepare_access(struct thread *thread)
261 struct maps *maps = &thread->mg->maps[i]; 308 struct maps *maps = &thread->mg->maps[i];
262 struct map *map; 309 struct map *map;
263 310
264 pthread_rwlock_rdlock(&maps->lock); 311 down_read(&maps->lock);
265 312
266 for (map = maps__first(maps); map; map = map__next(map)) { 313 for (map = maps__first(maps); map; map = map__next(map)) {
267 err = unwind__prepare_access(thread, map, &initialized); 314 err = unwind__prepare_access(thread, map, &initialized);
@@ -269,7 +316,7 @@ static int __thread__prepare_access(struct thread *thread)
269 break; 316 break;
270 } 317 }
271 318
272 pthread_rwlock_unlock(&maps->lock); 319 up_read(&maps->lock);
273 } 320 }
274 321
275 return err; 322 return err;
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 4eb849e9098f..40cfa36c022a 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_THREAD_H 2#ifndef __PERF_THREAD_H
2#define __PERF_THREAD_H 3#define __PERF_THREAD_H
3 4
@@ -9,6 +10,7 @@
9#include "symbol.h" 10#include "symbol.h"
10#include <strlist.h> 11#include <strlist.h>
11#include <intlist.h> 12#include <intlist.h>
13#include "rwsem.h"
12 14
13struct thread_stack; 15struct thread_stack;
14struct unwind_libunwind_ops; 16struct unwind_libunwind_ops;
@@ -29,11 +31,14 @@ struct thread {
29 int comm_len; 31 int comm_len;
30 bool dead; /* if set thread has exited */ 32 bool dead; /* if set thread has exited */
31 struct list_head namespaces_list; 33 struct list_head namespaces_list;
34 struct rw_semaphore namespaces_lock;
32 struct list_head comm_list; 35 struct list_head comm_list;
36 struct rw_semaphore comm_lock;
33 u64 db_id; 37 u64 db_id;
34 38
35 void *priv; 39 void *priv;
36 struct thread_stack *ts; 40 struct thread_stack *ts;
41 struct nsinfo *nsinfo;
37#ifdef HAVE_LIBUNWIND_SUPPORT 42#ifdef HAVE_LIBUNWIND_SUPPORT
38 void *addr_space; 43 void *addr_space;
39 struct unwind_libunwind_ops *unwind_libunwind_ops; 44 struct unwind_libunwind_ops *unwind_libunwind_ops;
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 63ead7b06324..be0d5a736dea 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <dirent.h> 2#include <dirent.h>
2#include <errno.h> 3#include <errno.h>
3#include <limits.h> 4#include <limits.h>
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index bd34d7a0b9fa..f15803985435 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_THREAD_MAP_H 2#ifndef __PERF_THREAD_MAP_H
2#define __PERF_THREAD_MAP_H 3#define __PERF_THREAD_MAP_H
3 4
diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c
index 5b5d0214debd..81927d027417 100644
--- a/tools/perf/util/time-utils.c
+++ b/tools/perf/util/time-utils.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdlib.h> 2#include <stdlib.h>
2#include <string.h> 3#include <string.h>
3#include <sys/time.h> 4#include <sys/time.h>
diff --git a/tools/perf/util/time-utils.h b/tools/perf/util/time-utils.h
index 8656be08513b..15b475c50ccf 100644
--- a/tools/perf/util/time-utils.h
+++ b/tools/perf/util/time-utils.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TIME_UTILS_H_ 2#ifndef _TIME_UTILS_H_
2#define _TIME_UTILS_H_ 3#define _TIME_UTILS_H_
3 4
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 829471a1c6d7..2532b558099b 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_TOOL_H 2#ifndef __PERF_TOOL_H
2#define __PERF_TOOL_H 3#define __PERF_TOOL_H
3 4
@@ -34,6 +35,12 @@ typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event,
34typedef s64 (*event_op3)(struct perf_tool *tool, union perf_event *event, 35typedef s64 (*event_op3)(struct perf_tool *tool, union perf_event *event,
35 struct perf_session *session); 36 struct perf_session *session);
36 37
38enum show_feature_header {
39 SHOW_FEAT_NO_HEADER = 0,
40 SHOW_FEAT_HEADER,
41 SHOW_FEAT_HEADER_FULL_INFO,
42};
43
37struct perf_tool { 44struct perf_tool {
38 event_sample sample, 45 event_sample sample,
39 read; 46 read;
@@ -63,11 +70,13 @@ struct perf_tool {
63 cpu_map, 70 cpu_map,
64 stat_config, 71 stat_config,
65 stat, 72 stat,
66 stat_round; 73 stat_round,
74 feature;
67 event_op3 auxtrace; 75 event_op3 auxtrace;
68 bool ordered_events; 76 bool ordered_events;
69 bool ordering_requires_timestamps; 77 bool ordering_requires_timestamps;
70 bool namespace_events; 78 bool namespace_events;
79 enum show_feature_header show_feat_hdr;
71}; 80};
72 81
73#endif /* __PERF_TOOL_H */ 82#endif /* __PERF_TOOL_H */
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 9bdfb78a9a35..9892323cdd7c 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_TOP_H 2#ifndef __PERF_TOP_H
2#define __PERF_TOP_H 1 3#define __PERF_TOP_H 1
3 4
@@ -37,6 +38,7 @@ struct perf_top {
37 int sym_pcnt_filter; 38 int sym_pcnt_filter;
38 const char *sym_filter; 39 const char *sym_filter;
39 float min_percent; 40 float min_percent;
41 unsigned int nr_threads_synthesize;
40}; 42};
41 43
42#define CONSOLE_CLEAR "" 44#define CONSOLE_CLEAR ""
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index e7d60d05596d..d7f2113462fb 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -28,7 +28,6 @@
28#include <sys/types.h> 28#include <sys/types.h>
29#include <sys/stat.h> 29#include <sys/stat.h>
30#include <sys/wait.h> 30#include <sys/wait.h>
31#include <pthread.h>
32#include <fcntl.h> 31#include <fcntl.h>
33#include <unistd.h> 32#include <unistd.h>
34#include <errno.h> 33#include <errno.h>
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 8a9a677f7576..40b425949aa3 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -27,7 +27,6 @@
27#include <sys/stat.h> 27#include <sys/stat.h>
28#include <sys/wait.h> 28#include <sys/wait.h>
29#include <sys/mman.h> 29#include <sys/mman.h>
30#include <pthread.h>
31#include <fcntl.h> 30#include <fcntl.h>
32#include <unistd.h> 31#include <unistd.h>
33#include <errno.h> 32#include <errno.h>
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
index c330780674fc..16a776371d03 100644
--- a/tools/perf/util/trace-event.c
+++ b/tools/perf/util/trace-event.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1 2
2#include <stdio.h> 3#include <stdio.h>
3#include <unistd.h> 4#include <unistd.h>
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 1fbc044f9eb0..dcbdb53dc702 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_UTIL_TRACE_EVENT_H 2#ifndef _PERF_UTIL_TRACE_EVENT_H
2#define _PERF_UTIL_TRACE_EVENT_H 3#define _PERF_UTIL_TRACE_EVENT_H
3 4
diff --git a/tools/perf/util/trigger.h b/tools/perf/util/trigger.h
index e97d7016d771..370138e7e35c 100644
--- a/tools/perf/util/trigger.h
+++ b/tools/perf/util/trigger.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __TRIGGER_H_ 2#ifndef __TRIGGER_H_
2#define __TRIGGER_H_ 1 3#define __TRIGGER_H_ 1
3 4
diff --git a/tools/perf/util/tsc.c b/tools/perf/util/tsc.c
index 1b741646eed0..bfa782421cbd 100644
--- a/tools/perf/util/tsc.c
+++ b/tools/perf/util/tsc.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include <linux/types.h> 3#include <linux/types.h>
3 4
diff --git a/tools/perf/util/tsc.h b/tools/perf/util/tsc.h
index d5b11e2b85e0..e0c3af34ac8d 100644
--- a/tools/perf/util/tsc.h
+++ b/tools/perf/util/tsc.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_TSC_H 2#ifndef __PERF_TSC_H
2#define __PERF_TSC_H 3#define __PERF_TSC_H
3 4
diff --git a/tools/perf/util/units.c b/tools/perf/util/units.c
index 4767ec2c5ef6..a46762aec4c9 100644
--- a/tools/perf/util/units.c
+++ b/tools/perf/util/units.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "units.h" 2#include "units.h"
2#include <inttypes.h> 3#include <inttypes.h>
3#include <limits.h> 4#include <limits.h>
diff --git a/tools/perf/util/units.h b/tools/perf/util/units.h
index f02c87317150..99263b6a23f7 100644
--- a/tools/perf/util/units.h
+++ b/tools/perf/util/units.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PERF_UNIT_H 2#ifndef PERF_UNIT_H
2#define PERF_UNIT_H 3#define PERF_UNIT_H
3 4
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 7755a5e0fe5e..1e9c974faf67 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include <elfutils/libdw.h> 3#include <elfutils/libdw.h>
3#include <elfutils/libdwfl.h> 4#include <elfutils/libdwfl.h>
diff --git a/tools/perf/util/unwind-libdw.h b/tools/perf/util/unwind-libdw.h
index 4a2b269a7b3b..0cbd2650e280 100644
--- a/tools/perf/util/unwind-libdw.h
+++ b/tools/perf/util/unwind-libdw.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_UNWIND_LIBDW_H 2#ifndef __PERF_UNWIND_LIBDW_H
2#define __PERF_UNWIND_LIBDW_H 3#define __PERF_UNWIND_LIBDW_H
3 4
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index 672c2ada9357..7a42f703e858 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps. 3 * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps.
3 * 4 *
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 8aef572d0889..647a1e6b4c7b 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "unwind.h" 2#include "unwind.h"
2#include "thread.h" 3#include "thread.h"
3#include "session.h" 4#include "session.h"
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index bfbdcc6198c9..8a44a1569a21 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __UNWIND_H 2#ifndef __UNWIND_H
2#define __UNWIND_H 3#define __UNWIND_H
3 4
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c
index 6cc9d9888ce0..070d25ceea6a 100644
--- a/tools/perf/util/usage.c
+++ b/tools/perf/util/usage.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * usage.c 3 * usage.c
3 * 4 *
diff --git a/tools/perf/util/util-cxx.h b/tools/perf/util/util-cxx.h
index 0e0e019c9f34..80a99e458d4e 100644
--- a/tools/perf/util/util-cxx.h
+++ b/tools/perf/util/util-cxx.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Support C++ source use utilities defined in util.h 3 * Support C++ source use utilities defined in util.h
3 */ 4 */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 988111e0bab5..a789f952b3e9 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "../perf.h" 2#include "../perf.h"
2#include "util.h" 3#include "util.h"
3#include "debug.h" 4#include "debug.h"
@@ -6,6 +7,7 @@
6#include <sys/stat.h> 7#include <sys/stat.h>
7#include <sys/utsname.h> 8#include <sys/utsname.h>
8#include <dirent.h> 9#include <dirent.h>
10#include <fcntl.h>
9#include <inttypes.h> 11#include <inttypes.h>
10#include <signal.h> 12#include <signal.h>
11#include <stdio.h> 13#include <stdio.h>
@@ -22,6 +24,19 @@
22/* 24/*
23 * XXX We need to find a better place for these things... 25 * XXX We need to find a better place for these things...
24 */ 26 */
27
28bool perf_singlethreaded = true;
29
30void perf_set_singlethreaded(void)
31{
32 perf_singlethreaded = true;
33}
34
35void perf_set_multithreaded(void)
36{
37 perf_singlethreaded = false;
38}
39
25unsigned int page_size; 40unsigned int page_size;
26int cacheline_size; 41int cacheline_size;
27 42
@@ -143,13 +158,17 @@ out:
143 return list; 158 return list;
144} 159}
145 160
146static int slow_copyfile(const char *from, const char *to) 161static int slow_copyfile(const char *from, const char *to, struct nsinfo *nsi)
147{ 162{
148 int err = -1; 163 int err = -1;
149 char *line = NULL; 164 char *line = NULL;
150 size_t n; 165 size_t n;
151 FILE *from_fp = fopen(from, "r"), *to_fp; 166 FILE *from_fp, *to_fp;
167 struct nscookie nsc;
152 168
169 nsinfo__mountns_enter(nsi, &nsc);
170 from_fp = fopen(from, "r");
171 nsinfo__mountns_exit(&nsc);
153 if (from_fp == NULL) 172 if (from_fp == NULL)
154 goto out; 173 goto out;
155 174
@@ -170,7 +189,7 @@ out:
170 return err; 189 return err;
171} 190}
172 191
173int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size) 192static int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
174{ 193{
175 void *ptr; 194 void *ptr;
176 loff_t pgoff; 195 loff_t pgoff;
@@ -198,15 +217,21 @@ int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
198 return size ? -1 : 0; 217 return size ? -1 : 0;
199} 218}
200 219
201int copyfile_mode(const char *from, const char *to, mode_t mode) 220static int copyfile_mode_ns(const char *from, const char *to, mode_t mode,
221 struct nsinfo *nsi)
202{ 222{
203 int fromfd, tofd; 223 int fromfd, tofd;
204 struct stat st; 224 struct stat st;
205 int err = -1; 225 int err;
206 char *tmp = NULL, *ptr = NULL; 226 char *tmp = NULL, *ptr = NULL;
227 struct nscookie nsc;
207 228
208 if (stat(from, &st)) 229 nsinfo__mountns_enter(nsi, &nsc);
230 err = stat(from, &st);
231 nsinfo__mountns_exit(&nsc);
232 if (err)
209 goto out; 233 goto out;
234 err = -1;
210 235
211 /* extra 'x' at the end is to reserve space for '.' */ 236 /* extra 'x' at the end is to reserve space for '.' */
212 if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) { 237 if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) {
@@ -227,11 +252,13 @@ int copyfile_mode(const char *from, const char *to, mode_t mode)
227 goto out_close_to; 252 goto out_close_to;
228 253
229 if (st.st_size == 0) { /* /proc? do it slowly... */ 254 if (st.st_size == 0) { /* /proc? do it slowly... */
230 err = slow_copyfile(from, tmp); 255 err = slow_copyfile(from, tmp, nsi);
231 goto out_close_to; 256 goto out_close_to;
232 } 257 }
233 258
259 nsinfo__mountns_enter(nsi, &nsc);
234 fromfd = open(from, O_RDONLY); 260 fromfd = open(from, O_RDONLY);
261 nsinfo__mountns_exit(&nsc);
235 if (fromfd < 0) 262 if (fromfd < 0)
236 goto out_close_to; 263 goto out_close_to;
237 264
@@ -248,6 +275,16 @@ out:
248 return err; 275 return err;
249} 276}
250 277
278int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi)
279{
280 return copyfile_mode_ns(from, to, 0755, nsi);
281}
282
283int copyfile_mode(const char *from, const char *to, mode_t mode)
284{
285 return copyfile_mode_ns(from, to, mode, NULL);
286}
287
251int copyfile(const char *from, const char *to) 288int copyfile(const char *from, const char *to)
252{ 289{
253 return copyfile_mode(from, to, 0755); 290 return copyfile_mode(from, to, 0755);
@@ -259,6 +296,7 @@ static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
259 size_t left = n; 296 size_t left = n;
260 297
261 while (left) { 298 while (left) {
299 /* buf must be treated as const if !is_read. */
262 ssize_t ret = is_read ? read(fd, buf, left) : 300 ssize_t ret = is_read ? read(fd, buf, left) :
263 write(fd, buf, left); 301 write(fd, buf, left);
264 302
@@ -286,9 +324,10 @@ ssize_t readn(int fd, void *buf, size_t n)
286/* 324/*
287 * Write exactly 'n' bytes or return an error. 325 * Write exactly 'n' bytes or return an error.
288 */ 326 */
289ssize_t writen(int fd, void *buf, size_t n) 327ssize_t writen(int fd, const void *buf, size_t n)
290{ 328{
291 return ion(false, fd, buf, n); 329 /* ion does not modify buf. */
330 return ion(false, fd, (void *)buf, n);
292} 331}
293 332
294size_t hex_width(u64 v) 333size_t hex_width(u64 v)
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 2c9e58a45310..01434509c2e9 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef GIT_COMPAT_UTIL_H 2#ifndef GIT_COMPAT_UTIL_H
2#define GIT_COMPAT_UTIL_H 3#define GIT_COMPAT_UTIL_H
3 4
@@ -5,13 +6,13 @@
5/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */ 6/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
6#define _DEFAULT_SOURCE 1 7#define _DEFAULT_SOURCE 1
7 8
8#include <fcntl.h>
9#include <stdbool.h> 9#include <stdbool.h>
10#include <stddef.h> 10#include <stddef.h>
11#include <stdlib.h> 11#include <stdlib.h>
12#include <stdarg.h> 12#include <stdarg.h>
13#include <linux/compiler.h> 13#include <linux/compiler.h>
14#include <linux/types.h> 14#include <linux/types.h>
15#include "namespaces.h"
15 16
16/* General helper functions */ 17/* General helper functions */
17void usage(const char *err) __noreturn; 18void usage(const char *err) __noreturn;
@@ -33,10 +34,10 @@ struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dire
33bool lsdir_no_dot_filter(const char *name, struct dirent *d); 34bool lsdir_no_dot_filter(const char *name, struct dirent *d);
34int copyfile(const char *from, const char *to); 35int copyfile(const char *from, const char *to);
35int copyfile_mode(const char *from, const char *to, mode_t mode); 36int copyfile_mode(const char *from, const char *to, mode_t mode);
36int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size); 37int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi);
37 38
38ssize_t readn(int fd, void *buf, size_t n); 39ssize_t readn(int fd, void *buf, size_t n);
39ssize_t writen(int fd, void *buf, size_t n); 40ssize_t writen(int fd, const void *buf, size_t n);
40 41
41size_t hex_width(u64 v); 42size_t hex_width(u64 v);
42int hex2u64(const char *ptr, u64 *val); 43int hex2u64(const char *ptr, u64 *val);
@@ -58,4 +59,13 @@ const char *perf_tip(const char *dirpath);
58int sched_getcpu(void); 59int sched_getcpu(void);
59#endif 60#endif
60 61
62#ifndef HAVE_SETNS_SUPPORT
63int setns(int fd, int nstype);
64#endif
65
66extern bool perf_singlethreaded;
67
68void perf_set_singlethreaded(void);
69void perf_set_multithreaded(void);
70
61#endif /* GIT_COMPAT_UTIL_H */ 71#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
index 5de2e15e2eda..4b7a303e4ba8 100644
--- a/tools/perf/util/values.c
+++ b/tools/perf/util/values.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <inttypes.h> 2#include <inttypes.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <stdlib.h> 4#include <stdlib.h>
@@ -12,7 +13,7 @@ int perf_read_values_init(struct perf_read_values *values)
12 values->threads_max = 16; 13 values->threads_max = 16;
13 values->pid = malloc(values->threads_max * sizeof(*values->pid)); 14 values->pid = malloc(values->threads_max * sizeof(*values->pid));
14 values->tid = malloc(values->threads_max * sizeof(*values->tid)); 15 values->tid = malloc(values->threads_max * sizeof(*values->tid));
15 values->value = malloc(values->threads_max * sizeof(*values->value)); 16 values->value = zalloc(values->threads_max * sizeof(*values->value));
16 if (!values->pid || !values->tid || !values->value) { 17 if (!values->pid || !values->tid || !values->value) {
17 pr_debug("failed to allocate read_values threads arrays"); 18 pr_debug("failed to allocate read_values threads arrays");
18 goto out_free_pid; 19 goto out_free_pid;
@@ -98,15 +99,16 @@ static int perf_read_values__findnew_thread(struct perf_read_values *values,
98 return i; 99 return i;
99 } 100 }
100 101
101 i = values->threads + 1; 102 i = values->threads;
102 values->value[i] = malloc(values->counters_max * sizeof(**values->value)); 103
104 values->value[i] = zalloc(values->counters_max * sizeof(**values->value));
103 if (!values->value[i]) { 105 if (!values->value[i]) {
104 pr_debug("failed to allocate read_values counters array"); 106 pr_debug("failed to allocate read_values counters array");
105 return -ENOMEM; 107 return -ENOMEM;
106 } 108 }
107 values->pid[i] = pid; 109 values->pid[i] = pid;
108 values->tid[i] = tid; 110 values->tid[i] = tid;
109 values->threads = i; 111 values->threads = i + 1;
110 112
111 return i; 113 return i;
112} 114}
@@ -130,12 +132,16 @@ static int perf_read_values__enlarge_counters(struct perf_read_values *values)
130 132
131 for (i = 0; i < values->threads; i++) { 133 for (i = 0; i < values->threads; i++) {
132 u64 *value = realloc(values->value[i], counters_max * sizeof(**values->value)); 134 u64 *value = realloc(values->value[i], counters_max * sizeof(**values->value));
135 int j;
133 136
134 if (value) { 137 if (!value) {
135 pr_debug("failed to enlarge read_values ->values array"); 138 pr_debug("failed to enlarge read_values ->values array");
136 goto out_free_name; 139 goto out_free_name;
137 } 140 }
138 141
142 for (j = values->counters_max; j < counters_max; j++)
143 value[j] = 0;
144
139 values->value[i] = value; 145 values->value[i] = value;
140 } 146 }
141 147
@@ -187,7 +193,7 @@ int perf_read_values_add_value(struct perf_read_values *values,
187 if (cindex < 0) 193 if (cindex < 0)
188 return cindex; 194 return cindex;
189 195
190 values->value[tindex][cindex] = value; 196 values->value[tindex][cindex] += value;
191 return 0; 197 return 0;
192} 198}
193 199
diff --git a/tools/perf/util/values.h b/tools/perf/util/values.h
index 808ff9c73bf5..8c41f22f42cf 100644
--- a/tools/perf/util/values.h
+++ b/tools/perf/util/values.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_VALUES_H 2#ifndef __PERF_VALUES_H
2#define __PERF_VALUES_H 3#define __PERF_VALUES_H
3 4
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index d3c39eec89a8..0acb1ec0e2f0 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <unistd.h> 3#include <unistd.h>
3#include <stdio.h> 4#include <stdio.h>
@@ -319,7 +320,7 @@ struct dso *machine__findnew_vdso(struct machine *machine,
319 struct vdso_info *vdso_info; 320 struct vdso_info *vdso_info;
320 struct dso *dso = NULL; 321 struct dso *dso = NULL;
321 322
322 pthread_rwlock_wrlock(&machine->dsos.lock); 323 down_write(&machine->dsos.lock);
323 if (!machine->vdso_info) 324 if (!machine->vdso_info)
324 machine->vdso_info = vdso_info__new(); 325 machine->vdso_info = vdso_info__new();
325 326
@@ -347,7 +348,7 @@ struct dso *machine__findnew_vdso(struct machine *machine,
347 348
348out_unlock: 349out_unlock:
349 dso__get(dso); 350 dso__get(dso);
350 pthread_rwlock_unlock(&machine->dsos.lock); 351 up_write(&machine->dsos.lock);
351 return dso; 352 return dso;
352} 353}
353 354
diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h
index cdc4fabfc212..bc74ace603ae 100644
--- a/tools/perf/util/vdso.h
+++ b/tools/perf/util/vdso.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __PERF_VDSO__ 2#ifndef __PERF_VDSO__
2#define __PERF_VDSO__ 3#define __PERF_VDSO__
3 4
diff --git a/tools/perf/util/xyarray.c b/tools/perf/util/xyarray.c
index 7251fdbabced..dc95154f5646 100644
--- a/tools/perf/util/xyarray.c
+++ b/tools/perf/util/xyarray.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include "xyarray.h" 2#include "xyarray.h"
2#include "util.h" 3#include "util.h"
3#include <stdlib.h> 4#include <stdlib.h>
@@ -12,6 +13,8 @@ struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)
12 xy->entry_size = entry_size; 13 xy->entry_size = entry_size;
13 xy->row_size = row_size; 14 xy->row_size = row_size;
14 xy->entries = xlen * ylen; 15 xy->entries = xlen * ylen;
16 xy->max_x = xlen;
17 xy->max_y = ylen;
15 } 18 }
16 19
17 return xy; 20 return xy;
diff --git a/tools/perf/util/xyarray.h b/tools/perf/util/xyarray.h
index 7f30af371b7e..7ffe562e7ae7 100644
--- a/tools/perf/util/xyarray.h
+++ b/tools/perf/util/xyarray.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PERF_XYARRAY_H_ 2#ifndef _PERF_XYARRAY_H_
2#define _PERF_XYARRAY_H_ 1 3#define _PERF_XYARRAY_H_ 1
3 4
@@ -7,6 +8,8 @@ struct xyarray {
7 size_t row_size; 8 size_t row_size;
8 size_t entry_size; 9 size_t entry_size;
9 size_t entries; 10 size_t entries;
11 size_t max_x;
12 size_t max_y;
10 char contents[]; 13 char contents[];
11}; 14};
12 15
@@ -19,4 +22,14 @@ static inline void *xyarray__entry(struct xyarray *xy, int x, int y)
19 return &xy->contents[x * xy->row_size + y * xy->entry_size]; 22 return &xy->contents[x * xy->row_size + y * xy->entry_size];
20} 23}
21 24
25static inline int xyarray__max_y(struct xyarray *xy)
26{
27 return xy->max_y;
28}
29
30static inline int xyarray__max_x(struct xyarray *xy)
31{
32 return xy->max_x;
33}
34
22#endif /* _PERF_XYARRAY_H_ */ 35#endif /* _PERF_XYARRAY_H_ */
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
index 1329d843eb7b..a725b958cf31 100644
--- a/tools/perf/util/zlib.c
+++ b/tools/perf/util/zlib.c
@@ -1,3 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <fcntl.h>
1#include <stdio.h> 3#include <stdio.h>
2#include <unistd.h> 4#include <unistd.h>
3#include <sys/stat.h> 5#include <sys/stat.h>
diff --git a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
index 82a2ff896a95..52a39ecf5ca1 100644
--- a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
+++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
@@ -759,7 +759,7 @@ static acpi_status osl_list_bios_tables(void)
759 759
760 /* Skip NULL entries in RSDT/XSDT */ 760 /* Skip NULL entries in RSDT/XSDT */
761 761
762 if (!table_address) { 762 if (table_address == 0) {
763 continue; 763 continue;
764 } 764 }
765 765
@@ -808,7 +808,8 @@ osl_get_bios_table(char *signature,
808 u8 number_of_tables; 808 u8 number_of_tables;
809 u8 item_size; 809 u8 item_size;
810 u32 current_instance = 0; 810 u32 current_instance = 0;
811 acpi_physical_address table_address = 0; 811 acpi_physical_address table_address;
812 acpi_physical_address first_table_address = 0;
812 u32 table_length = 0; 813 u32 table_length = 0;
813 acpi_status status = AE_OK; 814 acpi_status status = AE_OK;
814 u32 i; 815 u32 i;
@@ -820,9 +821,10 @@ osl_get_bios_table(char *signature,
820 ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) || 821 ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) ||
821 ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) || 822 ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) ||
822 ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { 823 ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
823 if (instance > 0) { 824
824 return (AE_LIMIT); 825find_next_instance:
825 } 826
827 table_address = 0;
826 828
827 /* 829 /*
828 * Get the appropriate address, either 32-bit or 64-bit. Be very 830 * Get the appropriate address, either 32-bit or 64-bit. Be very
@@ -830,41 +832,66 @@ osl_get_bios_table(char *signature,
830 * Note: The 64-bit addresses have priority. 832 * Note: The 64-bit addresses have priority.
831 */ 833 */
832 if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) { 834 if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) {
833 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) && 835 if (current_instance < 2) {
834 gbl_fadt->Xdsdt) { 836 if ((gbl_fadt->header.length >=
835 table_address = 837 MIN_FADT_FOR_XDSDT) && gbl_fadt->Xdsdt
836 (acpi_physical_address)gbl_fadt->Xdsdt; 838 && current_instance == 0) {
837 } else 839 table_address =
838 if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT) 840 (acpi_physical_address)gbl_fadt->
839 && gbl_fadt->dsdt) { 841 Xdsdt;
840 table_address = 842 } else
841 (acpi_physical_address)gbl_fadt->dsdt; 843 if ((gbl_fadt->header.length >=
844 MIN_FADT_FOR_DSDT)
845 && gbl_fadt->dsdt !=
846 first_table_address) {
847 table_address =
848 (acpi_physical_address)gbl_fadt->
849 dsdt;
850 }
842 } 851 }
843 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { 852 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
844 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) && 853 if (current_instance < 2) {
845 gbl_fadt->Xfacs) { 854 if ((gbl_fadt->header.length >=
846 table_address = 855 MIN_FADT_FOR_XFACS) && gbl_fadt->Xfacs
847 (acpi_physical_address)gbl_fadt->Xfacs; 856 && current_instance == 0) {
848 } else 857 table_address =
849 if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS) 858 (acpi_physical_address)gbl_fadt->
850 && gbl_fadt->facs) { 859 Xfacs;
851 table_address = 860 } else
852 (acpi_physical_address)gbl_fadt->facs; 861 if ((gbl_fadt->header.length >=
862 MIN_FADT_FOR_FACS)
863 && gbl_fadt->facs !=
864 first_table_address) {
865 table_address =
866 (acpi_physical_address)gbl_fadt->
867 facs;
868 }
853 } 869 }
854 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) { 870 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) {
855 if (!gbl_revision) { 871 if (!gbl_revision) {
856 return (AE_BAD_SIGNATURE); 872 return (AE_BAD_SIGNATURE);
857 } 873 }
858 table_address = 874 if (current_instance == 0) {
859 (acpi_physical_address)gbl_rsdp. 875 table_address =
860 xsdt_physical_address; 876 (acpi_physical_address)gbl_rsdp.
877 xsdt_physical_address;
878 }
861 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) { 879 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) {
862 table_address = 880 if (current_instance == 0) {
863 (acpi_physical_address)gbl_rsdp. 881 table_address =
864 rsdt_physical_address; 882 (acpi_physical_address)gbl_rsdp.
883 rsdt_physical_address;
884 }
865 } else { 885 } else {
866 table_address = (acpi_physical_address)gbl_rsdp_address; 886 if (current_instance == 0) {
867 signature = ACPI_SIG_RSDP; 887 table_address =
888 (acpi_physical_address)gbl_rsdp_address;
889 signature = ACPI_SIG_RSDP;
890 }
891 }
892
893 if (table_address == 0) {
894 goto exit_find_table;
868 } 895 }
869 896
870 /* Now we can get the requested special table */ 897 /* Now we can get the requested special table */
@@ -875,6 +902,18 @@ osl_get_bios_table(char *signature,
875 } 902 }
876 903
877 table_length = ap_get_table_length(mapped_table); 904 table_length = ap_get_table_length(mapped_table);
905 if (first_table_address == 0) {
906 first_table_address = table_address;
907 }
908
909 /* Match table instance */
910
911 if (current_instance != instance) {
912 osl_unmap_table(mapped_table);
913 mapped_table = NULL;
914 current_instance++;
915 goto find_next_instance;
916 }
878 } else { /* Case for a normal ACPI table */ 917 } else { /* Case for a normal ACPI table */
879 918
880 if (osl_can_use_xsdt()) { 919 if (osl_can_use_xsdt()) {
@@ -913,7 +952,7 @@ osl_get_bios_table(char *signature,
913 952
914 /* Skip NULL entries in RSDT/XSDT */ 953 /* Skip NULL entries in RSDT/XSDT */
915 954
916 if (!table_address) { 955 if (table_address == 0) {
917 continue; 956 continue;
918 } 957 }
919 958
@@ -946,6 +985,8 @@ osl_get_bios_table(char *signature,
946 } 985 }
947 } 986 }
948 987
988exit_find_table:
989
949 if (!mapped_table) { 990 if (!mapped_table) {
950 return (AE_LIMIT); 991 return (AE_LIMIT);
951 } 992 }
diff --git a/tools/power/acpi/tools/acpidump/Makefile b/tools/power/acpi/tools/acpidump/Makefile
index f7c7af1f9258..b436f8675f6a 100644
--- a/tools/power/acpi/tools/acpidump/Makefile
+++ b/tools/power/acpi/tools/acpidump/Makefile
@@ -39,6 +39,7 @@ TOOL_OBJS = \
39 utnonansi.o\ 39 utnonansi.o\
40 utprint.o\ 40 utprint.o\
41 utstring.o\ 41 utstring.o\
42 utstrsuppt.o\
42 utstrtoul64.o\ 43 utstrtoul64.o\
43 utxferror.o\ 44 utxferror.o\
44 oslinuxtbl.o\ 45 oslinuxtbl.o\
diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c
index 60df1fbd4a77..0634449156d8 100644
--- a/tools/power/acpi/tools/acpidump/apdump.c
+++ b/tools/power/acpi/tools/acpidump/apdump.c
@@ -287,8 +287,7 @@ int ap_dump_table_by_address(char *ascii_address)
287 287
288 /* Convert argument to an integer physical address */ 288 /* Convert argument to an integer physical address */
289 289
290 status = acpi_ut_strtoul64(ascii_address, ACPI_STRTOUL_64BIT, 290 status = acpi_ut_strtoul64(ascii_address, &long_address);
291 &long_address);
292 if (ACPI_FAILURE(status)) { 291 if (ACPI_FAILURE(status)) {
293 fprintf(stderr, "%s: Could not convert to a physical address\n", 292 fprintf(stderr, "%s: Could not convert to a physical address\n",
294 ascii_address); 293 ascii_address);
diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c
index 31b5a7f74015..d686e11936c4 100644
--- a/tools/power/acpi/tools/acpidump/apfiles.c
+++ b/tools/power/acpi/tools/acpidump/apfiles.c
@@ -61,7 +61,7 @@ static int ap_is_existing_file(char *pathname);
61 61
62static int ap_is_existing_file(char *pathname) 62static int ap_is_existing_file(char *pathname)
63{ 63{
64#ifndef _GNU_EFI 64#if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
65 struct stat stat_info; 65 struct stat stat_info;
66 66
67 if (!stat(pathname, &stat_info)) { 67 if (!stat(pathname, &stat_info)) {
diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c
index dd82afa897bd..22c3b4ee1617 100644
--- a/tools/power/acpi/tools/acpidump/apmain.c
+++ b/tools/power/acpi/tools/acpidump/apmain.c
@@ -208,9 +208,7 @@ static int ap_do_options(int argc, char **argv)
208 case 'r': /* Dump tables from specified RSDP */ 208 case 'r': /* Dump tables from specified RSDP */
209 209
210 status = 210 status =
211 acpi_ut_strtoul64(acpi_gbl_optarg, 211 acpi_ut_strtoul64(acpi_gbl_optarg, &gbl_rsdp_base);
212 ACPI_STRTOUL_64BIT,
213 &gbl_rsdp_base);
214 if (ACPI_FAILURE(status)) { 212 if (ACPI_FAILURE(status)) {
215 fprintf(stderr, 213 fprintf(stderr,
216 "%s: Could not convert to a physical address\n", 214 "%s: Could not convert to a physical address\n",
@@ -300,7 +298,7 @@ static int ap_do_options(int argc, char **argv)
300 * 298 *
301 ******************************************************************************/ 299 ******************************************************************************/
302 300
303#ifndef _GNU_EFI 301#if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
304int ACPI_SYSTEM_XFACE main(int argc, char *argv[]) 302int ACPI_SYSTEM_XFACE main(int argc, char *argv[])
305#else 303#else
306int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[]) 304int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[])
diff --git a/tools/power/cpupower/.gitignore b/tools/power/cpupower/.gitignore
index d42073f12609..1f9977cc609c 100644
--- a/tools/power/cpupower/.gitignore
+++ b/tools/power/cpupower/.gitignore
@@ -1,7 +1,6 @@
1.libs 1.libs
2libcpupower.so 2libcpupower.so
3libcpupower.so.0 3libcpupower.so.*
4libcpupower.so.0.0.0
5build/ccdv 4build/ccdv
6cpufreq-info 5cpufreq-info
7cpufreq-set 6cpufreq-set
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index d6e1c02ddcfe..1dd5f4fcffd5 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -26,10 +26,12 @@ endif
26 26
27ifneq ($(OUTPUT),) 27ifneq ($(OUTPUT),)
28# check that the output directory actually exists 28# check that the output directory actually exists
29OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd) 29OUTDIR := $(shell cd $(OUTPUT) && pwd)
30$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist)) 30$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
31endif 31endif
32 32
33include ../../scripts/Makefile.arch
34
33# --- CONFIGURATION BEGIN --- 35# --- CONFIGURATION BEGIN ---
34 36
35# Set the following to `true' to make a unstripped, unoptimized 37# Set the following to `true' to make a unstripped, unoptimized
@@ -79,7 +81,11 @@ bindir ?= /usr/bin
79sbindir ?= /usr/sbin 81sbindir ?= /usr/sbin
80mandir ?= /usr/man 82mandir ?= /usr/man
81includedir ?= /usr/include 83includedir ?= /usr/include
84ifeq ($(IS_64_BIT), 1)
85libdir ?= /usr/lib64
86else
82libdir ?= /usr/lib 87libdir ?= /usr/lib
88endif
83localedir ?= /usr/share/locale 89localedir ?= /usr/share/locale
84docdir ?= /usr/share/doc/packages/cpupower 90docdir ?= /usr/share/doc/packages/cpupower
85confdir ?= /etc/ 91confdir ?= /etc/
diff --git a/tools/power/cpupower/bench/Makefile b/tools/power/cpupower/bench/Makefile
index 3e59f1aa3947..d79ab161cc75 100644
--- a/tools/power/cpupower/bench/Makefile
+++ b/tools/power/cpupower/bench/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1OUTPUT := ./ 2OUTPUT := ./
2ifeq ("$(origin O)", "command line") 3ifeq ("$(origin O)", "command line")
3ifneq ($(O),) 4ifneq ($(O),)
diff --git a/tools/power/cpupower/debug/i386/Makefile b/tools/power/cpupower/debug/i386/Makefile
index c05cc0ac80c7..b3f771039b17 100644
--- a/tools/power/cpupower/debug/i386/Makefile
+++ b/tools/power/cpupower/debug/i386/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1OUTPUT=./ 2OUTPUT=./
2ifeq ("$(origin O)", "command line") 3ifeq ("$(origin O)", "command line")
3 OUTPUT := $(O)/ 4 OUTPUT := $(O)/
diff --git a/tools/power/cpupower/debug/kernel/Makefile b/tools/power/cpupower/debug/kernel/Makefile
index a8a6f8eec5c2..c23e5a6ceb7e 100644
--- a/tools/power/cpupower/debug/kernel/Makefile
+++ b/tools/power/cpupower/debug/kernel/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1obj-m := 2obj-m :=
2 3
3KDIR := /lib/modules/$(shell uname -r)/build 4KDIR := /lib/modules/$(shell uname -r)/build
diff --git a/tools/power/cpupower/debug/x86_64/Makefile b/tools/power/cpupower/debug/x86_64/Makefile
index 1c5214526716..59af84b8ef45 100644
--- a/tools/power/cpupower/debug/x86_64/Makefile
+++ b/tools/power/cpupower/debug/x86_64/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1OUTPUT=./ 2OUTPUT=./
2ifeq ("$(origin O)", "command line") 3ifeq ("$(origin O)", "command line")
3 OUTPUT := $(O)/ 4 OUTPUT := $(O)/
diff --git a/tools/power/cpupower/lib/cpuidle.h b/tools/power/cpupower/lib/cpuidle.h
index 04eb3cfa6e42..2e10fead2e1e 100644
--- a/tools/power/cpupower/lib/cpuidle.h
+++ b/tools/power/cpupower/lib/cpuidle.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __CPUPOWER_CPUIDLE_H__ 2#ifndef __CPUPOWER_CPUIDLE_H__
2#define __CPUPOWER_CPUIDLE_H__ 3#define __CPUPOWER_CPUIDLE_H__
3 4
diff --git a/tools/power/cpupower/lib/cpupower.h b/tools/power/cpupower/lib/cpupower.h
index fa031fcc7710..e4e4292eacec 100644
--- a/tools/power/cpupower/lib/cpupower.h
+++ b/tools/power/cpupower/lib/cpupower.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __CPUPOWER_CPUPOWER_H__ 2#ifndef __CPUPOWER_CPUPOWER_H__
2#define __CPUPOWER_CPUPOWER_H__ 3#define __CPUPOWER_CPUPOWER_H__
3 4
diff --git a/tools/power/cpupower/lib/cpupower_intern.h b/tools/power/cpupower/lib/cpupower_intern.h
index f8ec4009621c..92affdfbe417 100644
--- a/tools/power/cpupower/lib/cpupower_intern.h
+++ b/tools/power/cpupower/lib/cpupower_intern.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#define PATH_TO_CPU "/sys/devices/system/cpu/" 2#define PATH_TO_CPU "/sys/devices/system/cpu/"
2#define MAX_LINE_LEN 4096 3#define MAX_LINE_LEN 4096
3#define SYSFS_PATH_MAX 255 4#define SYSFS_PATH_MAX 255
diff --git a/tools/power/cpupower/utils/builtin.h b/tools/power/cpupower/utils/builtin.h
index 2284c8ea4e2a..f7065ae60a14 100644
--- a/tools/power/cpupower/utils/builtin.h
+++ b/tools/power/cpupower/utils/builtin.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef BUILTIN_H 2#ifndef BUILTIN_H
2#define BUILTIN_H 3#define BUILTIN_H
3 4
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
index 3e701f0e9c14..df43cd45d810 100644
--- a/tools/power/cpupower/utils/cpufreq-info.c
+++ b/tools/power/cpupower/utils/cpufreq-info.c
@@ -93,8 +93,6 @@ static void print_speed(unsigned long speed)
93 if (speed > 1000000) 93 if (speed > 1000000)
94 printf("%u.%06u GHz", ((unsigned int) speed/1000000), 94 printf("%u.%06u GHz", ((unsigned int) speed/1000000),
95 ((unsigned int) speed%1000000)); 95 ((unsigned int) speed%1000000));
96 else if (speed > 100000)
97 printf("%u MHz", (unsigned int) speed);
98 else if (speed > 1000) 96 else if (speed > 1000)
99 printf("%u.%03u MHz", ((unsigned int) speed/1000), 97 printf("%u.%03u MHz", ((unsigned int) speed/1000),
100 (unsigned int) (speed%1000)); 98 (unsigned int) (speed%1000));
diff --git a/tools/power/cpupower/utils/cpuidle-set.c b/tools/power/cpupower/utils/cpuidle-set.c
index 691c24d50ef4..569f268f4c7f 100644
--- a/tools/power/cpupower/utils/cpuidle-set.c
+++ b/tools/power/cpupower/utils/cpuidle-set.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <unistd.h> 2#include <unistd.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <errno.h> 4#include <errno.h>
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c
index 9ea914378985..2dccf4998599 100644
--- a/tools/power/cpupower/utils/cpupower.c
+++ b/tools/power/cpupower/utils/cpupower.c
@@ -12,6 +12,7 @@
12#include <string.h> 12#include <string.h>
13#include <unistd.h> 13#include <unistd.h>
14#include <errno.h> 14#include <errno.h>
15#include <sched.h>
15#include <sys/types.h> 16#include <sys/types.h>
16#include <sys/stat.h> 17#include <sys/stat.h>
17#include <sys/utsname.h> 18#include <sys/utsname.h>
@@ -31,6 +32,7 @@ static int cmd_help(int argc, const char **argv);
31 */ 32 */
32struct cpupower_cpu_info cpupower_cpu_info; 33struct cpupower_cpu_info cpupower_cpu_info;
33int run_as_root; 34int run_as_root;
35int base_cpu;
34/* Affected cpus chosen by -c/--cpu param */ 36/* Affected cpus chosen by -c/--cpu param */
35struct bitmask *cpus_chosen; 37struct bitmask *cpus_chosen;
36 38
@@ -174,6 +176,7 @@ int main(int argc, const char *argv[])
174 unsigned int i, ret; 176 unsigned int i, ret;
175 struct stat statbuf; 177 struct stat statbuf;
176 struct utsname uts; 178 struct utsname uts;
179 char pathname[32];
177 180
178 cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF)); 181 cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
179 182
@@ -198,17 +201,23 @@ int main(int argc, const char *argv[])
198 argv[0] = cmd = "help"; 201 argv[0] = cmd = "help";
199 } 202 }
200 203
201 get_cpu_info(0, &cpupower_cpu_info); 204 base_cpu = sched_getcpu();
205 if (base_cpu < 0) {
206 fprintf(stderr, _("No valid cpus found.\n"));
207 return EXIT_FAILURE;
208 }
209
210 get_cpu_info(&cpupower_cpu_info);
202 run_as_root = !geteuid(); 211 run_as_root = !geteuid();
203 if (run_as_root) { 212 if (run_as_root) {
204 ret = uname(&uts); 213 ret = uname(&uts);
214 sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
205 if (!ret && !strcmp(uts.machine, "x86_64") && 215 if (!ret && !strcmp(uts.machine, "x86_64") &&
206 stat("/dev/cpu/0/msr", &statbuf) != 0) { 216 stat(pathname, &statbuf) != 0) {
207 if (system("modprobe msr") == -1) 217 if (system("modprobe msr") == -1)
208 fprintf(stderr, _("MSR access not available.\n")); 218 fprintf(stderr, _("MSR access not available.\n"));
209 } 219 }
210 } 220 }
211
212 221
213 for (i = 0; i < ARRAY_SIZE(commands); i++) { 222 for (i = 0; i < ARRAY_SIZE(commands); i++) {
214 struct cmd_struct *p = commands + i; 223 struct cmd_struct *p = commands + i;
diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c
index 5fd5c5b8c7b8..bb41cdd0df6b 100644
--- a/tools/power/cpupower/utils/helpers/amd.c
+++ b/tools/power/cpupower/utils/helpers/amd.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#if defined(__i386__) || defined(__x86_64__) 2#if defined(__i386__) || defined(__x86_64__)
2#include <unistd.h> 3#include <unistd.h>
3#include <errno.h> 4#include <errno.h>
diff --git a/tools/power/cpupower/utils/helpers/bitmask.c b/tools/power/cpupower/utils/helpers/bitmask.c
index 5c074c60f904..6c7932f5bd66 100644
--- a/tools/power/cpupower/utils/helpers/bitmask.c
+++ b/tools/power/cpupower/utils/helpers/bitmask.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <string.h> 4#include <string.h>
diff --git a/tools/power/cpupower/utils/helpers/bitmask.h b/tools/power/cpupower/utils/helpers/bitmask.h
index eb289df41053..b98d93a44e1b 100644
--- a/tools/power/cpupower/utils/helpers/bitmask.h
+++ b/tools/power/cpupower/utils/helpers/bitmask.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __CPUPOWER_BITMASK__ 2#ifndef __CPUPOWER_BITMASK__
2#define __CPUPOWER_BITMASK__ 3#define __CPUPOWER_BITMASK__
3 4
diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
index 39c2c7d067bb..732b0b41ba26 100644
--- a/tools/power/cpupower/utils/helpers/cpuid.c
+++ b/tools/power/cpupower/utils/helpers/cpuid.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <errno.h> 3#include <errno.h>
3#include <string.h> 4#include <string.h>
@@ -42,7 +43,7 @@ cpuid_func(edx);
42 * 43 *
43 * TBD: Should there be a cpuid alternative for this if /proc is not mounted? 44 * TBD: Should there be a cpuid alternative for this if /proc is not mounted?
44 */ 45 */
45int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info) 46int get_cpu_info(struct cpupower_cpu_info *cpu_info)
46{ 47{
47 FILE *fp; 48 FILE *fp;
48 char value[64]; 49 char value[64];
@@ -70,7 +71,7 @@ int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info)
70 if (!strncmp(value, "processor\t: ", 12)) 71 if (!strncmp(value, "processor\t: ", 12))
71 sscanf(value, "processor\t: %u", &proc); 72 sscanf(value, "processor\t: %u", &proc);
72 73
73 if (proc != cpu) 74 if (proc != (unsigned int)base_cpu)
74 continue; 75 continue;
75 76
76 /* Get CPU vendor */ 77 /* Get CPU vendor */
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index 799a18be60aa..41da392be448 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -34,6 +34,7 @@
34/* Internationalization ****************************/ 34/* Internationalization ****************************/
35 35
36extern int run_as_root; 36extern int run_as_root;
37extern int base_cpu;
37extern struct bitmask *cpus_chosen; 38extern struct bitmask *cpus_chosen;
38 39
39/* Global verbose (-d) stuff *********************************/ 40/* Global verbose (-d) stuff *********************************/
@@ -87,11 +88,11 @@ struct cpupower_cpu_info {
87 * 88 *
88 * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo 89 * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo
89 * 90 *
90 * Returns 0 on success or a negativ error code 91 * Returns 0 on success or a negative error code
91 * Only used on x86, below global's struct values are zero/unknown on 92 * Only used on x86, below global's struct values are zero/unknown on
92 * other archs 93 * other archs
93 */ 94 */
94extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info); 95extern int get_cpu_info(struct cpupower_cpu_info *cpu_info);
95extern struct cpupower_cpu_info cpupower_cpu_info; 96extern struct cpupower_cpu_info cpupower_cpu_info;
96/* cpuid and cpuinfo helpers **************************/ 97/* cpuid and cpuinfo helpers **************************/
97 98
diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
index 601d719d4e60..80fdf55f414d 100644
--- a/tools/power/cpupower/utils/helpers/misc.c
+++ b/tools/power/cpupower/utils/helpers/misc.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#if defined(__i386__) || defined(__x86_64__) 2#if defined(__i386__) || defined(__x86_64__)
2 3
3#include "helpers/helpers.h" 4#include "helpers/helpers.h"
@@ -13,7 +14,7 @@ int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
13 14
14 *support = *active = *states = 0; 15 *support = *active = *states = 0;
15 16
16 ret = get_cpu_info(0, &cpu_info); 17 ret = get_cpu_info(&cpu_info);
17 if (ret) 18 if (ret)
18 return ret; 19 return ret;
19 20
diff --git a/tools/power/cpupower/utils/helpers/msr.c b/tools/power/cpupower/utils/helpers/msr.c
index 31a4b24a8bc6..ab9950748838 100644
--- a/tools/power/cpupower/utils/helpers/msr.c
+++ b/tools/power/cpupower/utils/helpers/msr.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#if defined(__i386__) || defined(__x86_64__) 2#if defined(__i386__) || defined(__x86_64__)
2 3
3#include <fcntl.h> 4#include <fcntl.h>
diff --git a/tools/power/cpupower/utils/helpers/pci.c b/tools/power/cpupower/utils/helpers/pci.c
index 8b278983cfc5..113f3da2a203 100644
--- a/tools/power/cpupower/utils/helpers/pci.c
+++ b/tools/power/cpupower/utils/helpers/pci.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#if defined(__i386__) || defined(__x86_64__) 2#if defined(__i386__) || defined(__x86_64__)
2 3
3#include <helpers/helpers.h> 4#include <helpers/helpers.h>
diff --git a/tools/power/cpupower/utils/helpers/sysfs.h b/tools/power/cpupower/utils/helpers/sysfs.h
index d28f11fedbda..0f0b9ad97e4a 100644
--- a/tools/power/cpupower/utils/helpers/sysfs.h
+++ b/tools/power/cpupower/utils/helpers/sysfs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __CPUPOWER_HELPERS_SYSFS_H__ 2#ifndef __CPUPOWER_HELPERS_SYSFS_H__
2#define __CPUPOWER_HELPERS_SYSFS_H__ 3#define __CPUPOWER_HELPERS_SYSFS_H__
3 4
diff --git a/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c b/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c
index ebeaba6571a3..f794d6bbb7e9 100644
--- a/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c
+++ b/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c
@@ -123,7 +123,7 @@ static int hsw_ext_start(void)
123 previous_count[num][cpu] = val; 123 previous_count[num][cpu] = val;
124 } 124 }
125 } 125 }
126 hsw_ext_get_count(TSC, &tsc_at_measure_start, 0); 126 hsw_ext_get_count(TSC, &tsc_at_measure_start, base_cpu);
127 return 0; 127 return 0;
128} 128}
129 129
@@ -132,7 +132,7 @@ static int hsw_ext_stop(void)
132 unsigned long long val; 132 unsigned long long val;
133 int num, cpu; 133 int num, cpu;
134 134
135 hsw_ext_get_count(TSC, &tsc_at_measure_end, 0); 135 hsw_ext_get_count(TSC, &tsc_at_measure_end, base_cpu);
136 136
137 for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) { 137 for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) {
138 for (cpu = 0; cpu < cpu_count; cpu++) { 138 for (cpu = 0; cpu < cpu_count; cpu++) {
diff --git a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
index c83f1606970b..d7c2a6d13dea 100644
--- a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
+++ b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
@@ -80,7 +80,8 @@ static int *is_valid;
80static int mperf_get_tsc(unsigned long long *tsc) 80static int mperf_get_tsc(unsigned long long *tsc)
81{ 81{
82 int ret; 82 int ret;
83 ret = read_msr(0, MSR_TSC, tsc); 83
84 ret = read_msr(base_cpu, MSR_TSC, tsc);
84 if (ret) 85 if (ret)
85 dprint("Reading TSC MSR failed, returning %llu\n", *tsc); 86 dprint("Reading TSC MSR failed, returning %llu\n", *tsc);
86 return ret; 87 return ret;
diff --git a/tools/power/cpupower/utils/idle_monitor/nhm_idle.c b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
index d2a91dd0d563..abf8cb5f7349 100644
--- a/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
+++ b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
@@ -129,7 +129,7 @@ static int nhm_start(void)
129 int num, cpu; 129 int num, cpu;
130 unsigned long long dbg, val; 130 unsigned long long dbg, val;
131 131
132 nhm_get_count(TSC, &tsc_at_measure_start, 0); 132 nhm_get_count(TSC, &tsc_at_measure_start, base_cpu);
133 133
134 for (num = 0; num < NHM_CSTATE_COUNT; num++) { 134 for (num = 0; num < NHM_CSTATE_COUNT; num++) {
135 for (cpu = 0; cpu < cpu_count; cpu++) { 135 for (cpu = 0; cpu < cpu_count; cpu++) {
@@ -137,7 +137,7 @@ static int nhm_start(void)
137 previous_count[num][cpu] = val; 137 previous_count[num][cpu] = val;
138 } 138 }
139 } 139 }
140 nhm_get_count(TSC, &dbg, 0); 140 nhm_get_count(TSC, &dbg, base_cpu);
141 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start); 141 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start);
142 return 0; 142 return 0;
143} 143}
@@ -148,7 +148,7 @@ static int nhm_stop(void)
148 unsigned long long dbg; 148 unsigned long long dbg;
149 int num, cpu; 149 int num, cpu;
150 150
151 nhm_get_count(TSC, &tsc_at_measure_end, 0); 151 nhm_get_count(TSC, &tsc_at_measure_end, base_cpu);
152 152
153 for (num = 0; num < NHM_CSTATE_COUNT; num++) { 153 for (num = 0; num < NHM_CSTATE_COUNT; num++) {
154 for (cpu = 0; cpu < cpu_count; cpu++) { 154 for (cpu = 0; cpu < cpu_count; cpu++) {
@@ -156,7 +156,7 @@ static int nhm_stop(void)
156 current_count[num][cpu] = val; 156 current_count[num][cpu] = val;
157 } 157 }
158 } 158 }
159 nhm_get_count(TSC, &dbg, 0); 159 nhm_get_count(TSC, &dbg, base_cpu);
160 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end); 160 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end);
161 161
162 return 0; 162 return 0;
diff --git a/tools/power/cpupower/utils/idle_monitor/snb_idle.c b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
index efc8a69c9aba..a2b45219648d 100644
--- a/tools/power/cpupower/utils/idle_monitor/snb_idle.c
+++ b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
@@ -120,7 +120,7 @@ static int snb_start(void)
120 previous_count[num][cpu] = val; 120 previous_count[num][cpu] = val;
121 } 121 }
122 } 122 }
123 snb_get_count(TSC, &tsc_at_measure_start, 0); 123 snb_get_count(TSC, &tsc_at_measure_start, base_cpu);
124 return 0; 124 return 0;
125} 125}
126 126
@@ -129,7 +129,7 @@ static int snb_stop(void)
129 unsigned long long val; 129 unsigned long long val;
130 int num, cpu; 130 int num, cpu;
131 131
132 snb_get_count(TSC, &tsc_at_measure_end, 0); 132 snb_get_count(TSC, &tsc_at_measure_end, base_cpu);
133 133
134 for (num = 0; num < SNB_CSTATE_COUNT; num++) { 134 for (num = 0; num < SNB_CSTATE_COUNT; num++) {
135 for (cpu = 0; cpu < cpu_count; cpu++) { 135 for (cpu = 0; cpu < cpu_count; cpu++) {
diff --git a/tools/power/cpupower/utils/version-gen.sh b/tools/power/cpupower/utils/version-gen.sh
index 5ec41c556992..c70de2eabffb 100755
--- a/tools/power/cpupower/utils/version-gen.sh
+++ b/tools/power/cpupower/utils/version-gen.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# 3#
3# Script which prints out the version to use for building cpupowerutils. 4# Script which prints out the version to use for building cpupowerutils.
4# Must be called from tools/power/cpupower/ 5# Must be called from tools/power/cpupower/
diff --git a/tools/power/pm-graph/Makefile b/tools/power/pm-graph/Makefile
index 4d0ccc89e6c6..4e1e999e7b05 100644
--- a/tools/power/pm-graph/Makefile
+++ b/tools/power/pm-graph/Makefile
@@ -1,10 +1,11 @@
1# SPDX-License-Identifier: GPL-2.0
1PREFIX ?= /usr 2PREFIX ?= /usr
2DESTDIR ?= 3DESTDIR ?=
3 4
4all: 5all:
5 @echo "Nothing to build" 6 @echo "Nothing to build"
6 7
7install : 8install : uninstall
8 install -d $(DESTDIR)$(PREFIX)/lib/pm-graph 9 install -d $(DESTDIR)$(PREFIX)/lib/pm-graph
9 install analyze_suspend.py $(DESTDIR)$(PREFIX)/lib/pm-graph 10 install analyze_suspend.py $(DESTDIR)$(PREFIX)/lib/pm-graph
10 install analyze_boot.py $(DESTDIR)$(PREFIX)/lib/pm-graph 11 install analyze_boot.py $(DESTDIR)$(PREFIX)/lib/pm-graph
@@ -17,12 +18,15 @@ install :
17 install sleepgraph.8 $(DESTDIR)$(PREFIX)/share/man/man8 18 install sleepgraph.8 $(DESTDIR)$(PREFIX)/share/man/man8
18 19
19uninstall : 20uninstall :
20 rm $(DESTDIR)$(PREFIX)/share/man/man8/bootgraph.8 21 rm -f $(DESTDIR)$(PREFIX)/share/man/man8/bootgraph.8
21 rm $(DESTDIR)$(PREFIX)/share/man/man8/sleepgraph.8 22 rm -f $(DESTDIR)$(PREFIX)/share/man/man8/sleepgraph.8
22 23
23 rm $(DESTDIR)$(PREFIX)/bin/bootgraph 24 rm -f $(DESTDIR)$(PREFIX)/bin/bootgraph
24 rm $(DESTDIR)$(PREFIX)/bin/sleepgraph 25 rm -f $(DESTDIR)$(PREFIX)/bin/sleepgraph
25 26
26 rm $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_boot.py 27 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_boot.py
27 rm $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_suspend.py 28 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_suspend.py
28 rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph 29 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/*.pyc
30 if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph ] ; then \
31 rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph; \
32 fi;
diff --git a/tools/power/pm-graph/analyze_boot.py b/tools/power/pm-graph/analyze_boot.py
index 3e1dcbbf1adc..e83df141a597 100755
--- a/tools/power/pm-graph/analyze_boot.py
+++ b/tools/power/pm-graph/analyze_boot.py
@@ -42,7 +42,7 @@ import analyze_suspend as aslib
42# store system values and test parameters 42# store system values and test parameters
43class SystemValues(aslib.SystemValues): 43class SystemValues(aslib.SystemValues):
44 title = 'BootGraph' 44 title = 'BootGraph'
45 version = 2.0 45 version = '2.1'
46 hostname = 'localhost' 46 hostname = 'localhost'
47 testtime = '' 47 testtime = ''
48 kernel = '' 48 kernel = ''
@@ -50,9 +50,14 @@ class SystemValues(aslib.SystemValues):
50 ftracefile = '' 50 ftracefile = ''
51 htmlfile = 'bootgraph.html' 51 htmlfile = 'bootgraph.html'
52 outfile = '' 52 outfile = ''
53 phoronix = False 53 testdir = ''
54 addlogs = False 54 testdirprefix = 'boot'
55 embedded = False
56 testlog = False
57 dmesglog = False
58 ftracelog = False
55 useftrace = False 59 useftrace = False
60 usecallgraph = False
56 usedevsrc = True 61 usedevsrc = True
57 suspendmode = 'boot' 62 suspendmode = 'boot'
58 max_graph_depth = 2 63 max_graph_depth = 2
@@ -61,10 +66,12 @@ class SystemValues(aslib.SystemValues):
61 manual = False 66 manual = False
62 iscronjob = False 67 iscronjob = False
63 timeformat = '%.6f' 68 timeformat = '%.6f'
69 bootloader = 'grub'
70 blexec = []
64 def __init__(self): 71 def __init__(self):
65 if('LOG_FILE' in os.environ and 'TEST_RESULTS_IDENTIFIER' in os.environ): 72 if('LOG_FILE' in os.environ and 'TEST_RESULTS_IDENTIFIER' in os.environ):
66 self.phoronix = True 73 self.embedded = True
67 self.addlogs = True 74 self.dmesglog = True
68 self.outfile = os.environ['LOG_FILE'] 75 self.outfile = os.environ['LOG_FILE']
69 self.htmlfile = os.environ['LOG_FILE'] 76 self.htmlfile = os.environ['LOG_FILE']
70 self.hostname = platform.node() 77 self.hostname = platform.node()
@@ -76,42 +83,80 @@ class SystemValues(aslib.SystemValues):
76 self.kernel = self.kernelVersion(val) 83 self.kernel = self.kernelVersion(val)
77 else: 84 else:
78 self.kernel = 'unknown' 85 self.kernel = 'unknown'
86 self.testdir = datetime.now().strftime('boot-%y%m%d-%H%M%S')
79 def kernelVersion(self, msg): 87 def kernelVersion(self, msg):
80 return msg.split()[2] 88 return msg.split()[2]
89 def checkFtraceKernelVersion(self):
90 val = tuple(map(int, self.kernel.split('-')[0].split('.')))
91 if val >= (4, 10, 0):
92 return True
93 return False
81 def kernelParams(self): 94 def kernelParams(self):
82 cmdline = 'initcall_debug log_buf_len=32M' 95 cmdline = 'initcall_debug log_buf_len=32M'
83 if self.useftrace: 96 if self.useftrace:
84 cmdline += ' trace_buf_size=128M trace_clock=global '\ 97 if self.cpucount > 0:
98 bs = min(self.memtotal / 2, 2*1024*1024) / self.cpucount
99 else:
100 bs = 131072
101 cmdline += ' trace_buf_size=%dK trace_clock=global '\
85 'trace_options=nooverwrite,funcgraph-abstime,funcgraph-cpu,'\ 102 'trace_options=nooverwrite,funcgraph-abstime,funcgraph-cpu,'\
86 'funcgraph-duration,funcgraph-proc,funcgraph-tail,'\ 103 'funcgraph-duration,funcgraph-proc,funcgraph-tail,'\
87 'nofuncgraph-overhead,context-info,graph-time '\ 104 'nofuncgraph-overhead,context-info,graph-time '\
88 'ftrace=function_graph '\ 105 'ftrace=function_graph '\
89 'ftrace_graph_max_depth=%d '\ 106 'ftrace_graph_max_depth=%d '\
90 'ftrace_graph_filter=%s' % \ 107 'ftrace_graph_filter=%s' % \
91 (self.max_graph_depth, self.graph_filter) 108 (bs, self.max_graph_depth, self.graph_filter)
92 return cmdline 109 return cmdline
93 def setGraphFilter(self, val): 110 def setGraphFilter(self, val):
94 fp = open(self.tpath+'available_filter_functions') 111 master = self.getBootFtraceFilterFunctions()
95 master = fp.read().split('\n') 112 fs = ''
96 fp.close()
97 for i in val.split(','): 113 for i in val.split(','):
98 func = i.strip() 114 func = i.strip()
115 if func == '':
116 doError('badly formatted filter function string')
117 if '[' in func or ']' in func:
118 doError('loadable module functions not allowed - "%s"' % func)
119 if ' ' in func:
120 doError('spaces found in filter functions - "%s"' % func)
99 if func not in master: 121 if func not in master:
100 doError('function "%s" not available for ftrace' % func) 122 doError('function "%s" not available for ftrace' % func)
101 self.graph_filter = val 123 if not fs:
124 fs = func
125 else:
126 fs += ','+func
127 if not fs:
128 doError('badly formatted filter function string')
129 self.graph_filter = fs
130 def getBootFtraceFilterFunctions(self):
131 self.rootCheck(True)
132 fp = open(self.tpath+'available_filter_functions')
133 fulllist = fp.read().split('\n')
134 fp.close()
135 list = []
136 for i in fulllist:
137 if not i or ' ' in i or '[' in i or ']' in i:
138 continue
139 list.append(i)
140 return list
141 def myCronJob(self, line):
142 if '@reboot' not in line:
143 return False
144 if 'bootgraph' in line or 'analyze_boot.py' in line or '-cronjob' in line:
145 return True
146 return False
102 def cronjobCmdString(self): 147 def cronjobCmdString(self):
103 cmdline = '%s -cronjob' % os.path.abspath(sys.argv[0]) 148 cmdline = '%s -cronjob' % os.path.abspath(sys.argv[0])
104 args = iter(sys.argv[1:]) 149 args = iter(sys.argv[1:])
105 for arg in args: 150 for arg in args:
106 if arg in ['-h', '-v', '-cronjob', '-reboot']: 151 if arg in ['-h', '-v', '-cronjob', '-reboot']:
107 continue 152 continue
108 elif arg in ['-o', '-dmesg', '-ftrace', '-filter']: 153 elif arg in ['-o', '-dmesg', '-ftrace', '-func']:
109 args.next() 154 args.next()
110 continue 155 continue
111 cmdline += ' '+arg 156 cmdline += ' '+arg
112 if self.graph_filter != 'do_one_initcall': 157 if self.graph_filter != 'do_one_initcall':
113 cmdline += ' -filter "%s"' % self.graph_filter 158 cmdline += ' -func "%s"' % self.graph_filter
114 cmdline += ' -o "%s"' % os.path.abspath(self.htmlfile) 159 cmdline += ' -o "%s"' % os.path.abspath(self.testdir)
115 return cmdline 160 return cmdline
116 def manualRebootRequired(self): 161 def manualRebootRequired(self):
117 cmdline = self.kernelParams() 162 cmdline = self.kernelParams()
@@ -121,6 +166,39 @@ class SystemValues(aslib.SystemValues):
121 print '3. After reboot, re-run this tool with the same arguments but no command (w/o -reboot or -manual).\n' 166 print '3. After reboot, re-run this tool with the same arguments but no command (w/o -reboot or -manual).\n'
122 print 'CMDLINE="%s"' % cmdline 167 print 'CMDLINE="%s"' % cmdline
123 sys.exit() 168 sys.exit()
169 def getExec(self, cmd):
170 dirlist = ['/sbin', '/bin', '/usr/sbin', '/usr/bin',
171 '/usr/local/sbin', '/usr/local/bin']
172 for path in dirlist:
173 cmdfull = os.path.join(path, cmd)
174 if os.path.exists(cmdfull):
175 return cmdfull
176 return ''
177 def blGrub(self):
178 blcmd = ''
179 for cmd in ['update-grub', 'grub-mkconfig', 'grub2-mkconfig']:
180 if blcmd:
181 break
182 blcmd = self.getExec(cmd)
183 if not blcmd:
184 doError('[GRUB] missing update command')
185 if not os.path.exists('/etc/default/grub'):
186 doError('[GRUB] missing /etc/default/grub')
187 if 'grub2' in blcmd:
188 cfg = '/boot/grub2/grub.cfg'
189 else:
190 cfg = '/boot/grub/grub.cfg'
191 if not os.path.exists(cfg):
192 doError('[GRUB] missing %s' % cfg)
193 if 'update-grub' in blcmd:
194 self.blexec = [blcmd]
195 else:
196 self.blexec = [blcmd, '-o', cfg]
197 def getBootLoader(self):
198 if self.bootloader == 'grub':
199 self.blGrub()
200 else:
201 doError('unknown boot loader: %s' % self.bootloader)
124 202
125sysvals = SystemValues() 203sysvals = SystemValues()
126 204
@@ -136,20 +214,23 @@ class Data(aslib.Data):
136 idstr = '' 214 idstr = ''
137 html_device_id = 0 215 html_device_id = 0
138 valid = False 216 valid = False
139 initstart = 0.0 217 tUserMode = 0.0
140 boottime = '' 218 boottime = ''
141 phases = ['boot'] 219 phases = ['kernel', 'user']
142 do_one_initcall = False 220 do_one_initcall = False
143 def __init__(self, num): 221 def __init__(self, num):
144 self.testnumber = num 222 self.testnumber = num
145 self.idstr = 'a' 223 self.idstr = 'a'
146 self.dmesgtext = [] 224 self.dmesgtext = []
147 self.dmesg = { 225 self.dmesg = {
148 'boot': {'list': dict(), 'start': -1.0, 'end': -1.0, 'row': 0, 'color': '#dddddd'} 226 'kernel': {'list': dict(), 'start': -1.0, 'end': -1.0, 'row': 0,
227 'order': 0, 'color': 'linear-gradient(to bottom, #fff, #bcf)'},
228 'user': {'list': dict(), 'start': -1.0, 'end': -1.0, 'row': 0,
229 'order': 1, 'color': '#fff'}
149 } 230 }
150 def deviceTopology(self): 231 def deviceTopology(self):
151 return '' 232 return ''
152 def newAction(self, phase, name, start, end, ret, ulen): 233 def newAction(self, phase, name, pid, start, end, ret, ulen):
153 # new device callback for a specific phase 234 # new device callback for a specific phase
154 self.html_device_id += 1 235 self.html_device_id += 1
155 devid = '%s%d' % (self.idstr, self.html_device_id) 236 devid = '%s%d' % (self.idstr, self.html_device_id)
@@ -163,41 +244,46 @@ class Data(aslib.Data):
163 name = '%s[%d]' % (origname, i) 244 name = '%s[%d]' % (origname, i)
164 i += 1 245 i += 1
165 list[name] = {'name': name, 'start': start, 'end': end, 246 list[name] = {'name': name, 'start': start, 'end': end,
166 'pid': 0, 'length': length, 'row': 0, 'id': devid, 247 'pid': pid, 'length': length, 'row': 0, 'id': devid,
167 'ret': ret, 'ulen': ulen } 248 'ret': ret, 'ulen': ulen }
168 return name 249 return name
169 def deviceMatch(self, cg): 250 def deviceMatch(self, pid, cg):
170 if cg.end - cg.start == 0: 251 if cg.end - cg.start == 0:
171 return True 252 return True
172 list = self.dmesg['boot']['list'] 253 for p in data.phases:
173 for devname in list: 254 list = self.dmesg[p]['list']
174 dev = list[devname] 255 for devname in list:
175 if cg.name == 'do_one_initcall': 256 dev = list[devname]
176 if(cg.start <= dev['start'] and cg.end >= dev['end'] and dev['length'] > 0): 257 if pid != dev['pid']:
177 dev['ftrace'] = cg 258 continue
178 self.do_one_initcall = True 259 if cg.name == 'do_one_initcall':
179 return True 260 if(cg.start <= dev['start'] and cg.end >= dev['end'] and dev['length'] > 0):
180 else: 261 dev['ftrace'] = cg
181 if(cg.start > dev['start'] and cg.end < dev['end']): 262 self.do_one_initcall = True
182 if 'ftraces' not in dev: 263 return True
183 dev['ftraces'] = [] 264 else:
184 dev['ftraces'].append(cg) 265 if(cg.start > dev['start'] and cg.end < dev['end']):
185 return True 266 if 'ftraces' not in dev:
267 dev['ftraces'] = []
268 dev['ftraces'].append(cg)
269 return True
186 return False 270 return False
187 271
188# ----------------- FUNCTIONS -------------------- 272# ----------------- FUNCTIONS --------------------
189 273
190# Function: loadKernelLog 274# Function: parseKernelLog
191# Description: 275# Description:
192# Load a raw kernel log from dmesg 276# parse a kernel log for boot data
193def loadKernelLog(): 277def parseKernelLog():
278 phase = 'kernel'
194 data = Data(0) 279 data = Data(0)
195 data.dmesg['boot']['start'] = data.start = ktime = 0.0 280 data.dmesg['kernel']['start'] = data.start = ktime = 0.0
196 sysvals.stamp = { 281 sysvals.stamp = {
197 'time': datetime.now().strftime('%B %d %Y, %I:%M:%S %p'), 282 'time': datetime.now().strftime('%B %d %Y, %I:%M:%S %p'),
198 'host': sysvals.hostname, 283 'host': sysvals.hostname,
199 'mode': 'boot', 'kernel': ''} 284 'mode': 'boot', 'kernel': ''}
200 285
286 tp = aslib.TestProps()
201 devtemp = dict() 287 devtemp = dict()
202 if(sysvals.dmesgfile): 288 if(sysvals.dmesgfile):
203 lf = open(sysvals.dmesgfile, 'r') 289 lf = open(sysvals.dmesgfile, 'r')
@@ -205,6 +291,13 @@ def loadKernelLog():
205 lf = Popen('dmesg', stdout=PIPE).stdout 291 lf = Popen('dmesg', stdout=PIPE).stdout
206 for line in lf: 292 for line in lf:
207 line = line.replace('\r\n', '') 293 line = line.replace('\r\n', '')
294 # grab the stamp and sysinfo
295 if re.match(tp.stampfmt, line):
296 tp.stamp = line
297 continue
298 elif re.match(tp.sysinfofmt, line):
299 tp.sysinfo = line
300 continue
208 idx = line.find('[') 301 idx = line.find('[')
209 if idx > 1: 302 if idx > 1:
210 line = line[idx:] 303 line = line[idx:]
@@ -215,7 +308,6 @@ def loadKernelLog():
215 if(ktime > 120): 308 if(ktime > 120):
216 break 309 break
217 msg = m.group('msg') 310 msg = m.group('msg')
218 data.end = data.initstart = ktime
219 data.dmesgtext.append(line) 311 data.dmesgtext.append(line)
220 if(ktime == 0.0 and re.match('^Linux version .*', msg)): 312 if(ktime == 0.0 and re.match('^Linux version .*', msg)):
221 if(not sysvals.stamp['kernel']): 313 if(not sysvals.stamp['kernel']):
@@ -228,43 +320,39 @@ def loadKernelLog():
228 data.boottime = bt.strftime('%Y-%m-%d_%H:%M:%S') 320 data.boottime = bt.strftime('%Y-%m-%d_%H:%M:%S')
229 sysvals.stamp['time'] = bt.strftime('%B %d %Y, %I:%M:%S %p') 321 sysvals.stamp['time'] = bt.strftime('%B %d %Y, %I:%M:%S %p')
230 continue 322 continue
231 m = re.match('^calling *(?P<f>.*)\+.*', msg) 323 m = re.match('^calling *(?P<f>.*)\+.* @ (?P<p>[0-9]*)', msg)
232 if(m): 324 if(m):
233 devtemp[m.group('f')] = ktime 325 func = m.group('f')
326 pid = int(m.group('p'))
327 devtemp[func] = (ktime, pid)
234 continue 328 continue
235 m = re.match('^initcall *(?P<f>.*)\+.* returned (?P<r>.*) after (?P<t>.*) usecs', msg) 329 m = re.match('^initcall *(?P<f>.*)\+.* returned (?P<r>.*) after (?P<t>.*) usecs', msg)
236 if(m): 330 if(m):
237 data.valid = True 331 data.valid = True
332 data.end = ktime
238 f, r, t = m.group('f', 'r', 't') 333 f, r, t = m.group('f', 'r', 't')
239 if(f in devtemp): 334 if(f in devtemp):
240 data.newAction('boot', f, devtemp[f], ktime, int(r), int(t)) 335 start, pid = devtemp[f]
241 data.end = ktime 336 data.newAction(phase, f, pid, start, ktime, int(r), int(t))
242 del devtemp[f] 337 del devtemp[f]
243 continue 338 continue
244 if(re.match('^Freeing unused kernel memory.*', msg)): 339 if(re.match('^Freeing unused kernel memory.*', msg)):
245 break 340 data.tUserMode = ktime
246 341 data.dmesg['kernel']['end'] = ktime
247 data.dmesg['boot']['end'] = data.end 342 data.dmesg['user']['start'] = ktime
343 phase = 'user'
344
345 if tp.stamp:
346 sysvals.stamp = 0
347 tp.parseStamp(data, sysvals)
348 data.dmesg['user']['end'] = data.end
248 lf.close() 349 lf.close()
249 return data 350 return data
250 351
251# Function: loadTraceLog 352# Function: parseTraceLog
252# Description: 353# Description:
253# Check if trace is available and copy to a temp file 354# Check if trace is available and copy to a temp file
254def loadTraceLog(data): 355def parseTraceLog(data):
255 # load the data to a temp file if none given
256 if not sysvals.ftracefile:
257 lib = aslib.sysvals
258 aslib.rootCheck(True)
259 if not lib.verifyFtrace():
260 doError('ftrace not available')
261 if lib.fgetVal('current_tracer').strip() != 'function_graph':
262 doError('ftrace not configured for a boot callgraph')
263 sysvals.ftracefile = '/tmp/boot_ftrace.%s.txt' % os.getpid()
264 call('cat '+lib.tpath+'trace > '+sysvals.ftracefile, shell=True)
265 if not sysvals.ftracefile:
266 doError('No trace data available')
267
268 # parse the trace log 356 # parse the trace log
269 ftemp = dict() 357 ftemp = dict()
270 tp = aslib.TestProps() 358 tp = aslib.TestProps()
@@ -306,9 +394,29 @@ def loadTraceLog(data):
306 print('Sanity check failed for %s-%d' % (proc, pid)) 394 print('Sanity check failed for %s-%d' % (proc, pid))
307 continue 395 continue
308 # match cg data to devices 396 # match cg data to devices
309 if not data.deviceMatch(cg): 397 if not data.deviceMatch(pid, cg):
310 print ' BAD: %s %s-%d [%f - %f]' % (cg.name, proc, pid, cg.start, cg.end) 398 print ' BAD: %s %s-%d [%f - %f]' % (cg.name, proc, pid, cg.start, cg.end)
311 399
400# Function: retrieveLogs
401# Description:
402# Create copies of dmesg and/or ftrace for later processing
403def retrieveLogs():
404 # check ftrace is configured first
405 if sysvals.useftrace:
406 tracer = sysvals.fgetVal('current_tracer').strip()
407 if tracer != 'function_graph':
408 doError('ftrace not configured for a boot callgraph')
409 # create the folder and get dmesg
410 sysvals.systemInfo(aslib.dmidecode(sysvals.mempath))
411 sysvals.initTestOutput('boot')
412 sysvals.writeDatafileHeader(sysvals.dmesgfile)
413 call('dmesg >> '+sysvals.dmesgfile, shell=True)
414 if not sysvals.useftrace:
415 return
416 # get ftrace
417 sysvals.writeDatafileHeader(sysvals.ftracefile)
418 call('cat '+sysvals.tpath+'trace >> '+sysvals.ftracefile, shell=True)
419
312# Function: colorForName 420# Function: colorForName
313# Description: 421# Description:
314# Generate a repeatable color from a list for a given name 422# Generate a repeatable color from a list for a given name
@@ -353,18 +461,19 @@ def cgOverview(cg, minlen):
353# testruns: array of Data objects from parseKernelLog or parseTraceLog 461# testruns: array of Data objects from parseKernelLog or parseTraceLog
354# Output: 462# Output:
355# True if the html file was created, false if it failed 463# True if the html file was created, false if it failed
356def createBootGraph(data, embedded): 464def createBootGraph(data):
357 # html function templates 465 # html function templates
358 html_srccall = '<div id={6} title="{5}" class="srccall" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;">{0}</div>\n' 466 html_srccall = '<div id={6} title="{5}" class="srccall" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;">{0}</div>\n'
359 html_timetotal = '<table class="time1">\n<tr>'\ 467 html_timetotal = '<table class="time1">\n<tr>'\
360 '<td class="blue">Time from Kernel Boot to start of User Mode: <b>{0} ms</b></td>'\ 468 '<td class="blue">Init process starts @ <b>{0} ms</b></td>'\
469 '<td class="blue">Last initcall ends @ <b>{1} ms</b></td>'\
361 '</tr>\n</table>\n' 470 '</tr>\n</table>\n'
362 471
363 # device timeline 472 # device timeline
364 devtl = aslib.Timeline(100, 20) 473 devtl = aslib.Timeline(100, 20)
365 474
366 # write the test title and general info header 475 # write the test title and general info header
367 devtl.createHeader(sysvals, 'noftrace') 476 devtl.createHeader(sysvals)
368 477
369 # Generate the header for this timeline 478 # Generate the header for this timeline
370 t0 = data.start 479 t0 = data.start
@@ -373,84 +482,98 @@ def createBootGraph(data, embedded):
373 if(tTotal == 0): 482 if(tTotal == 0):
374 print('ERROR: No timeline data') 483 print('ERROR: No timeline data')
375 return False 484 return False
376 boot_time = '%.0f'%(tTotal*1000) 485 user_mode = '%.0f'%(data.tUserMode*1000)
377 devtl.html += html_timetotal.format(boot_time) 486 last_init = '%.0f'%(tTotal*1000)
487 devtl.html += html_timetotal.format(user_mode, last_init)
378 488
379 # determine the maximum number of rows we need to draw 489 # determine the maximum number of rows we need to draw
380 phase = 'boot'
381 list = data.dmesg[phase]['list']
382 devlist = [] 490 devlist = []
383 for devname in list: 491 for p in data.phases:
384 d = aslib.DevItem(0, phase, list[devname]) 492 list = data.dmesg[p]['list']
385 devlist.append(d) 493 for devname in list:
386 devtl.getPhaseRows(devlist) 494 d = aslib.DevItem(0, p, list[devname])
495 devlist.append(d)
496 devtl.getPhaseRows(devlist, 0, 'start')
387 devtl.calcTotalRows() 497 devtl.calcTotalRows()
388 498
389 # draw the timeline background 499 # draw the timeline background
390 devtl.createZoomBox() 500 devtl.createZoomBox()
391 boot = data.dmesg[phase] 501 devtl.html += devtl.html_tblock.format('boot', '0', '100', devtl.scaleH)
392 length = boot['end']-boot['start'] 502 for p in data.phases:
393 left = '%.3f' % (((boot['start']-t0)*100.0)/tTotal) 503 phase = data.dmesg[p]
394 width = '%.3f' % ((length*100.0)/tTotal) 504 length = phase['end']-phase['start']
395 devtl.html += devtl.html_tblock.format(phase, left, width, devtl.scaleH) 505 left = '%.3f' % (((phase['start']-t0)*100.0)/tTotal)
396 devtl.html += devtl.html_phase.format('0', '100', \ 506 width = '%.3f' % ((length*100.0)/tTotal)
397 '%.3f'%devtl.scaleH, '%.3f'%devtl.bodyH, \ 507 devtl.html += devtl.html_phase.format(left, width, \
398 'white', '') 508 '%.3f'%devtl.scaleH, '%.3f'%devtl.bodyH, \
509 phase['color'], '')
399 510
400 # draw the device timeline 511 # draw the device timeline
401 num = 0 512 num = 0
402 devstats = dict() 513 devstats = dict()
403 for devname in sorted(list): 514 for phase in data.phases:
404 cls, color = colorForName(devname) 515 list = data.dmesg[phase]['list']
405 dev = list[devname] 516 for devname in sorted(list):
406 info = '@|%.3f|%.3f|%.3f|%d' % (dev['start']*1000.0, dev['end']*1000.0, 517 cls, color = colorForName(devname)
407 dev['ulen']/1000.0, dev['ret']) 518 dev = list[devname]
408 devstats[dev['id']] = {'info':info} 519 info = '@|%.3f|%.3f|%.3f|%d' % (dev['start']*1000.0, dev['end']*1000.0,
409 dev['color'] = color 520 dev['ulen']/1000.0, dev['ret'])
410 height = devtl.phaseRowHeight(0, phase, dev['row']) 521 devstats[dev['id']] = {'info':info}
411 top = '%.6f' % ((dev['row']*height) + devtl.scaleH) 522 dev['color'] = color
412 left = '%.6f' % (((dev['start']-t0)*100)/tTotal) 523 height = devtl.phaseRowHeight(0, phase, dev['row'])
413 width = '%.6f' % (((dev['end']-dev['start'])*100)/tTotal) 524 top = '%.6f' % ((dev['row']*height) + devtl.scaleH)
414 length = ' (%0.3f ms) ' % ((dev['end']-dev['start'])*1000) 525 left = '%.6f' % (((dev['start']-t0)*100)/tTotal)
415 devtl.html += devtl.html_device.format(dev['id'], 526 width = '%.6f' % (((dev['end']-dev['start'])*100)/tTotal)
416 devname+length+'kernel_mode', left, top, '%.3f'%height, 527 length = ' (%0.3f ms) ' % ((dev['end']-dev['start'])*1000)
417 width, devname, ' '+cls, '') 528 devtl.html += devtl.html_device.format(dev['id'],
418 rowtop = devtl.phaseRowTop(0, phase, dev['row']) 529 devname+length+phase+'_mode', left, top, '%.3f'%height,
419 height = '%.6f' % (devtl.rowH / 2) 530 width, devname, ' '+cls, '')
420 top = '%.6f' % (rowtop + devtl.scaleH + (devtl.rowH / 2)) 531 rowtop = devtl.phaseRowTop(0, phase, dev['row'])
421 if data.do_one_initcall: 532 height = '%.6f' % (devtl.rowH / 2)
422 if('ftrace' not in dev): 533 top = '%.6f' % (rowtop + devtl.scaleH + (devtl.rowH / 2))
534 if data.do_one_initcall:
535 if('ftrace' not in dev):
536 continue
537 cg = dev['ftrace']
538 large, stats = cgOverview(cg, 0.001)
539 devstats[dev['id']]['fstat'] = stats
540 for l in large:
541 left = '%f' % (((l.time-t0)*100)/tTotal)
542 width = '%f' % (l.length*100/tTotal)
543 title = '%s (%0.3fms)' % (l.name, l.length * 1000.0)
544 devtl.html += html_srccall.format(l.name, left,
545 top, height, width, title, 'x%d'%num)
546 num += 1
547 continue
548 if('ftraces' not in dev):
423 continue 549 continue
424 cg = dev['ftrace'] 550 for cg in dev['ftraces']:
425 large, stats = cgOverview(cg, 0.001) 551 left = '%f' % (((cg.start-t0)*100)/tTotal)
426 devstats[dev['id']]['fstat'] = stats 552 width = '%f' % ((cg.end-cg.start)*100/tTotal)
427 for l in large: 553 cglen = (cg.end - cg.start) * 1000.0
428 left = '%f' % (((l.time-t0)*100)/tTotal) 554 title = '%s (%0.3fms)' % (cg.name, cglen)
429 width = '%f' % (l.length*100/tTotal) 555 cg.id = 'x%d' % num
430 title = '%s (%0.3fms)' % (l.name, l.length * 1000.0) 556 devtl.html += html_srccall.format(cg.name, left,
431 devtl.html += html_srccall.format(l.name, left, 557 top, height, width, title, dev['id']+cg.id)
432 top, height, width, title, 'x%d'%num)
433 num += 1 558 num += 1
434 continue
435 if('ftraces' not in dev):
436 continue
437 for cg in dev['ftraces']:
438 left = '%f' % (((cg.start-t0)*100)/tTotal)
439 width = '%f' % ((cg.end-cg.start)*100/tTotal)
440 cglen = (cg.end - cg.start) * 1000.0
441 title = '%s (%0.3fms)' % (cg.name, cglen)
442 cg.id = 'x%d' % num
443 devtl.html += html_srccall.format(cg.name, left,
444 top, height, width, title, dev['id']+cg.id)
445 num += 1
446 559
447 # draw the time scale, try to make the number of labels readable 560 # draw the time scale, try to make the number of labels readable
448 devtl.createTimeScale(t0, tMax, tTotal, phase) 561 devtl.createTimeScale(t0, tMax, tTotal, 'boot')
449 devtl.html += '</div>\n' 562 devtl.html += '</div>\n'
450 563
451 # timeline is finished 564 # timeline is finished
452 devtl.html += '</div>\n</div>\n' 565 devtl.html += '</div>\n</div>\n'
453 566
567 # draw a legend which describes the phases by color
568 devtl.html += '<div class="legend">\n'
569 pdelta = 20.0
570 pmargin = 36.0
571 for phase in data.phases:
572 order = '%.2f' % ((data.dmesg[phase]['order'] * pdelta) + pmargin)
573 devtl.html += devtl.html_legend.format(order, \
574 data.dmesg[phase]['color'], phase+'_mode', phase[0])
575 devtl.html += '</div>\n'
576
454 if(sysvals.outfile == sysvals.htmlfile): 577 if(sysvals.outfile == sysvals.htmlfile):
455 hf = open(sysvals.htmlfile, 'a') 578 hf = open(sysvals.htmlfile, 'a')
456 else: 579 else:
@@ -474,7 +597,7 @@ def createBootGraph(data, embedded):
474 .fstat td {text-align:left;width:35px;}\n\ 597 .fstat td {text-align:left;width:35px;}\n\
475 .srccall {position:absolute;font-size:10px;z-index:7;overflow:hidden;color:black;text-align:center;white-space:nowrap;border-radius:5px;border:1px solid black;background:linear-gradient(to bottom right,#CCC,#969696);}\n\ 598 .srccall {position:absolute;font-size:10px;z-index:7;overflow:hidden;color:black;text-align:center;white-space:nowrap;border-radius:5px;border:1px solid black;background:linear-gradient(to bottom right,#CCC,#969696);}\n\
476 .srccall:hover {color:white;font-weight:bold;border:1px solid white;}\n' 599 .srccall:hover {color:white;font-weight:bold;border:1px solid white;}\n'
477 if(not embedded): 600 if(not sysvals.embedded):
478 aslib.addCSS(hf, sysvals, 1, False, extra) 601 aslib.addCSS(hf, sysvals, 1, False, extra)
479 602
480 # write the device timeline 603 # write the device timeline
@@ -495,9 +618,11 @@ def createBootGraph(data, embedded):
495 html = \ 618 html = \
496 '<div id="devicedetailtitle"></div>\n'\ 619 '<div id="devicedetailtitle"></div>\n'\
497 '<div id="devicedetail" style="display:none;">\n'\ 620 '<div id="devicedetail" style="display:none;">\n'\
498 '<div id="devicedetail0">\n'\ 621 '<div id="devicedetail0">\n'
499 '<div id="kernel_mode" class="phaselet" style="left:0%;width:100%;background:#DDDDDD"></div>\n'\ 622 for p in data.phases:
500 '</div>\n</div>\n'\ 623 phase = data.dmesg[p]
624 html += devtl.html_phaselet.format(p+'_mode', '0', '100', phase['color'])
625 html += '</div>\n</div>\n'\
501 '<script type="text/javascript">\n'+statinfo+\ 626 '<script type="text/javascript">\n'+statinfo+\
502 '</script>\n' 627 '</script>\n'
503 hf.write(html) 628 hf.write(html)
@@ -507,21 +632,21 @@ def createBootGraph(data, embedded):
507 aslib.addCallgraphs(sysvals, hf, data) 632 aslib.addCallgraphs(sysvals, hf, data)
508 633
509 # add the dmesg log as a hidden div 634 # add the dmesg log as a hidden div
510 if sysvals.addlogs: 635 if sysvals.dmesglog:
511 hf.write('<div id="dmesglog" style="display:none;">\n') 636 hf.write('<div id="dmesglog" style="display:none;">\n')
512 for line in data.dmesgtext: 637 for line in data.dmesgtext:
513 line = line.replace('<', '&lt').replace('>', '&gt') 638 line = line.replace('<', '&lt').replace('>', '&gt')
514 hf.write(line) 639 hf.write(line)
515 hf.write('</div>\n') 640 hf.write('</div>\n')
516 641
517 if(not embedded): 642 if(not sysvals.embedded):
518 # write the footer and close 643 # write the footer and close
519 aslib.addScriptCode(hf, [data]) 644 aslib.addScriptCode(hf, [data])
520 hf.write('</body>\n</html>\n') 645 hf.write('</body>\n</html>\n')
521 else: 646 else:
522 # embedded out will be loaded in a page, skip the js 647 # embedded out will be loaded in a page, skip the js
523 hf.write('<div id=bounds style=display:none>%f,%f</div>' % \ 648 hf.write('<div id=bounds style=display:none>%f,%f</div>' % \
524 (data.start*1000, data.initstart*1000)) 649 (data.start*1000, data.end*1000))
525 hf.close() 650 hf.close()
526 return True 651 return True
527 652
@@ -533,17 +658,20 @@ def updateCron(restore=False):
533 if not restore: 658 if not restore:
534 sysvals.rootUser(True) 659 sysvals.rootUser(True)
535 crondir = '/var/spool/cron/crontabs/' 660 crondir = '/var/spool/cron/crontabs/'
536 cronfile = crondir+'root' 661 if not os.path.exists(crondir):
537 backfile = crondir+'root-analyze_boot-backup' 662 crondir = '/var/spool/cron/'
538 if not os.path.exists(crondir): 663 if not os.path.exists(crondir):
539 doError('%s not found' % crondir) 664 doError('%s not found' % crondir)
540 out = Popen(['which', 'crontab'], stdout=PIPE).stdout.read() 665 cronfile = crondir+'root'
541 if not out: 666 backfile = crondir+'root-analyze_boot-backup'
667 cmd = sysvals.getExec('crontab')
668 if not cmd:
542 doError('crontab not found') 669 doError('crontab not found')
543 # on restore: move the backup cron back into place 670 # on restore: move the backup cron back into place
544 if restore: 671 if restore:
545 if os.path.exists(backfile): 672 if os.path.exists(backfile):
546 shutil.move(backfile, cronfile) 673 shutil.move(backfile, cronfile)
674 call([cmd, cronfile])
547 return 675 return
548 # backup current cron and install new one with reboot 676 # backup current cron and install new one with reboot
549 if os.path.exists(cronfile): 677 if os.path.exists(cronfile):
@@ -556,13 +684,13 @@ def updateCron(restore=False):
556 fp = open(backfile, 'r') 684 fp = open(backfile, 'r')
557 op = open(cronfile, 'w') 685 op = open(cronfile, 'w')
558 for line in fp: 686 for line in fp:
559 if '@reboot' not in line: 687 if not sysvals.myCronJob(line):
560 op.write(line) 688 op.write(line)
561 continue 689 continue
562 fp.close() 690 fp.close()
563 op.write('@reboot python %s\n' % sysvals.cronjobCmdString()) 691 op.write('@reboot python %s\n' % sysvals.cronjobCmdString())
564 op.close() 692 op.close()
565 res = call('crontab %s' % cronfile, shell=True) 693 res = call([cmd, cronfile])
566 except Exception, e: 694 except Exception, e:
567 print 'Exception: %s' % str(e) 695 print 'Exception: %s' % str(e)
568 shutil.move(backfile, cronfile) 696 shutil.move(backfile, cronfile)
@@ -577,25 +705,16 @@ def updateGrub(restore=False):
577 # call update-grub on restore 705 # call update-grub on restore
578 if restore: 706 if restore:
579 try: 707 try:
580 call(['update-grub'], stderr=PIPE, stdout=PIPE, 708 call(sysvals.blexec, stderr=PIPE, stdout=PIPE,
581 env={'PATH': '.:/sbin:/usr/sbin:/usr/bin:/sbin:/bin'}) 709 env={'PATH': '.:/sbin:/usr/sbin:/usr/bin:/sbin:/bin'})
582 except Exception, e: 710 except Exception, e:
583 print 'Exception: %s\n' % str(e) 711 print 'Exception: %s\n' % str(e)
584 return 712 return
585 # verify we can do this
586 sysvals.rootUser(True)
587 grubfile = '/etc/default/grub'
588 if not os.path.exists(grubfile):
589 print 'ERROR: Unable to set the kernel parameters via grub.\n'
590 sysvals.manualRebootRequired()
591 out = Popen(['which', 'update-grub'], stdout=PIPE).stdout.read()
592 if not out:
593 print 'ERROR: Unable to set the kernel parameters via grub.\n'
594 sysvals.manualRebootRequired()
595
596 # extract the option and create a grub config without it 713 # extract the option and create a grub config without it
714 sysvals.rootUser(True)
597 tgtopt = 'GRUB_CMDLINE_LINUX_DEFAULT' 715 tgtopt = 'GRUB_CMDLINE_LINUX_DEFAULT'
598 cmdline = '' 716 cmdline = ''
717 grubfile = '/etc/default/grub'
599 tempfile = '/etc/default/grub.analyze_boot' 718 tempfile = '/etc/default/grub.analyze_boot'
600 shutil.move(grubfile, tempfile) 719 shutil.move(grubfile, tempfile)
601 res = -1 720 res = -1
@@ -622,7 +741,7 @@ def updateGrub(restore=False):
622 # if the target option value is in quotes, strip them 741 # if the target option value is in quotes, strip them
623 sp = '"' 742 sp = '"'
624 val = cmdline.strip() 743 val = cmdline.strip()
625 if val[0] == '\'' or val[0] == '"': 744 if val and (val[0] == '\'' or val[0] == '"'):
626 sp = val[0] 745 sp = val[0]
627 val = val.strip(sp) 746 val = val.strip(sp)
628 cmdline = val 747 cmdline = val
@@ -633,7 +752,7 @@ def updateGrub(restore=False):
633 # write out the updated target option 752 # write out the updated target option
634 op.write('\n%s=%s%s%s\n' % (tgtopt, sp, cmdline, sp)) 753 op.write('\n%s=%s%s%s\n' % (tgtopt, sp, cmdline, sp))
635 op.close() 754 op.close()
636 res = call('update-grub') 755 res = call(sysvals.blexec)
637 os.remove(grubfile) 756 os.remove(grubfile)
638 except Exception, e: 757 except Exception, e:
639 print 'Exception: %s' % str(e) 758 print 'Exception: %s' % str(e)
@@ -641,10 +760,18 @@ def updateGrub(restore=False):
641 # cleanup 760 # cleanup
642 shutil.move(tempfile, grubfile) 761 shutil.move(tempfile, grubfile)
643 if res != 0: 762 if res != 0:
644 doError('update-grub failed') 763 doError('update grub failed')
645 764
646# Function: doError 765# Function: updateKernelParams
647# Description: 766# Description:
767# update boot conf for all kernels with our parameters
768def updateKernelParams(restore=False):
769 # find the boot loader
770 sysvals.getBootLoader()
771 if sysvals.bootloader == 'grub':
772 updateGrub(restore)
773
774# Function: doError Description:
648# generic error function for catastrphic failures 775# generic error function for catastrphic failures
649# Arguments: 776# Arguments:
650# msg: the error message to print 777# msg: the error message to print
@@ -660,7 +787,7 @@ def doError(msg, help=False):
660# print out the help text 787# print out the help text
661def printHelp(): 788def printHelp():
662 print('') 789 print('')
663 print('%s v%.1f' % (sysvals.title, sysvals.version)) 790 print('%s v%s' % (sysvals.title, sysvals.version))
664 print('Usage: bootgraph <options> <command>') 791 print('Usage: bootgraph <options> <command>')
665 print('') 792 print('')
666 print('Description:') 793 print('Description:')
@@ -669,13 +796,19 @@ def printHelp():
669 print(' the start of the init process.') 796 print(' the start of the init process.')
670 print('') 797 print('')
671 print(' If no specific command is given the tool reads the current dmesg') 798 print(' If no specific command is given the tool reads the current dmesg')
672 print(' and/or ftrace log and outputs bootgraph.html') 799 print(' and/or ftrace log and creates a timeline')
800 print('')
801 print(' Generates output files in subdirectory: boot-yymmdd-HHMMSS')
802 print(' HTML output: <hostname>_boot.html')
803 print(' raw dmesg output: <hostname>_boot_dmesg.txt')
804 print(' raw ftrace output: <hostname>_boot_ftrace.txt')
673 print('') 805 print('')
674 print('Options:') 806 print('Options:')
675 print(' -h Print this help text') 807 print(' -h Print this help text')
676 print(' -v Print the current tool version') 808 print(' -v Print the current tool version')
677 print(' -addlogs Add the dmesg log to the html output') 809 print(' -addlogs Add the dmesg log to the html output')
678 print(' -o file Html timeline name (default: bootgraph.html)') 810 print(' -o name Overrides the output subdirectory name when running a new test')
811 print(' default: boot-{date}-{time}')
679 print(' [advanced]') 812 print(' [advanced]')
680 print(' -f Use ftrace to add function detail (default: disabled)') 813 print(' -f Use ftrace to add function detail (default: disabled)')
681 print(' -callgraph Add callgraph detail, can be very large (default: disabled)') 814 print(' -callgraph Add callgraph detail, can be very large (default: disabled)')
@@ -683,13 +816,18 @@ def printHelp():
683 print(' -mincg ms Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)') 816 print(' -mincg ms Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)')
684 print(' -timeprec N Number of significant digits in timestamps (0:S, 3:ms, [6:us])') 817 print(' -timeprec N Number of significant digits in timestamps (0:S, 3:ms, [6:us])')
685 print(' -expandcg pre-expand the callgraph data in the html output (default: disabled)') 818 print(' -expandcg pre-expand the callgraph data in the html output (default: disabled)')
686 print(' -filter list Limit ftrace to comma-delimited list of functions (default: do_one_initcall)') 819 print(' -func list Limit ftrace to comma-delimited list of functions (default: do_one_initcall)')
687 print(' [commands]') 820 print(' -cgfilter S Filter the callgraph output in the timeline')
821 print(' -bl name Use the following boot loader for kernel params (default: grub)')
688 print(' -reboot Reboot the machine automatically and generate a new timeline') 822 print(' -reboot Reboot the machine automatically and generate a new timeline')
689 print(' -manual Show the requirements to generate a new timeline manually') 823 print(' -manual Show the steps to generate a new timeline manually (used with -reboot)')
690 print(' -dmesg file Load a stored dmesg file (used with -ftrace)') 824 print('')
691 print(' -ftrace file Load a stored ftrace file (used with -dmesg)') 825 print('Other commands:')
692 print(' -flistall Print all functions capable of being captured in ftrace') 826 print(' -flistall Print all functions capable of being captured in ftrace')
827 print(' -sysinfo Print out system info extracted from BIOS')
828 print(' [redo]')
829 print(' -dmesg file Create HTML output using dmesg input (used with -ftrace)')
830 print(' -ftrace file Create HTML output using ftrace input (used with -dmesg)')
693 print('') 831 print('')
694 return True 832 return True
695 833
@@ -698,14 +836,15 @@ def printHelp():
698if __name__ == '__main__': 836if __name__ == '__main__':
699 # loop through the command line arguments 837 # loop through the command line arguments
700 cmd = '' 838 cmd = ''
701 simplecmds = ['-updategrub', '-flistall'] 839 testrun = True
840 simplecmds = ['-sysinfo', '-kpupdate', '-flistall', '-checkbl']
702 args = iter(sys.argv[1:]) 841 args = iter(sys.argv[1:])
703 for arg in args: 842 for arg in args:
704 if(arg == '-h'): 843 if(arg == '-h'):
705 printHelp() 844 printHelp()
706 sys.exit() 845 sys.exit()
707 elif(arg == '-v'): 846 elif(arg == '-v'):
708 print("Version %.1f" % sysvals.version) 847 print("Version %s" % sysvals.version)
709 sys.exit() 848 sys.exit()
710 elif(arg in simplecmds): 849 elif(arg in simplecmds):
711 cmd = arg[1:] 850 cmd = arg[1:]
@@ -716,16 +855,32 @@ if __name__ == '__main__':
716 sysvals.usecallgraph = True 855 sysvals.usecallgraph = True
717 elif(arg == '-mincg'): 856 elif(arg == '-mincg'):
718 sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0) 857 sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0)
858 elif(arg == '-cgfilter'):
859 try:
860 val = args.next()
861 except:
862 doError('No callgraph functions supplied', True)
863 sysvals.setDeviceFilter(val)
864 elif(arg == '-bl'):
865 try:
866 val = args.next()
867 except:
868 doError('No boot loader name supplied', True)
869 if val.lower() not in ['grub']:
870 doError('Unknown boot loader: %s' % val, True)
871 sysvals.bootloader = val.lower()
719 elif(arg == '-timeprec'): 872 elif(arg == '-timeprec'):
720 sysvals.setPrecision(aslib.getArgInt('-timeprec', args, 0, 6)) 873 sysvals.setPrecision(aslib.getArgInt('-timeprec', args, 0, 6))
721 elif(arg == '-maxdepth'): 874 elif(arg == '-maxdepth'):
722 sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000) 875 sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000)
723 elif(arg == '-filter'): 876 elif(arg == '-func'):
724 try: 877 try:
725 val = args.next() 878 val = args.next()
726 except: 879 except:
727 doError('No filter functions supplied', True) 880 doError('No filter functions supplied', True)
728 aslib.rootCheck(True) 881 sysvals.useftrace = True
882 sysvals.usecallgraph = True
883 sysvals.rootCheck(True)
729 sysvals.setGraphFilter(val) 884 sysvals.setGraphFilter(val)
730 elif(arg == '-ftrace'): 885 elif(arg == '-ftrace'):
731 try: 886 try:
@@ -734,9 +889,10 @@ if __name__ == '__main__':
734 doError('No ftrace file supplied', True) 889 doError('No ftrace file supplied', True)
735 if(os.path.exists(val) == False): 890 if(os.path.exists(val) == False):
736 doError('%s does not exist' % val) 891 doError('%s does not exist' % val)
892 testrun = False
737 sysvals.ftracefile = val 893 sysvals.ftracefile = val
738 elif(arg == '-addlogs'): 894 elif(arg == '-addlogs'):
739 sysvals.addlogs = True 895 sysvals.dmesglog = True
740 elif(arg == '-expandcg'): 896 elif(arg == '-expandcg'):
741 sysvals.cgexp = True 897 sysvals.cgexp = True
742 elif(arg == '-dmesg'): 898 elif(arg == '-dmesg'):
@@ -748,18 +904,15 @@ if __name__ == '__main__':
748 doError('%s does not exist' % val) 904 doError('%s does not exist' % val)
749 if(sysvals.htmlfile == val or sysvals.outfile == val): 905 if(sysvals.htmlfile == val or sysvals.outfile == val):
750 doError('Output filename collision') 906 doError('Output filename collision')
907 testrun = False
751 sysvals.dmesgfile = val 908 sysvals.dmesgfile = val
752 elif(arg == '-o'): 909 elif(arg == '-o'):
753 try: 910 try:
754 val = args.next() 911 val = args.next()
755 except: 912 except:
756 doError('No HTML filename supplied', True) 913 doError('No subdirectory name supplied', True)
757 if(sysvals.dmesgfile == val or sysvals.ftracefile == val): 914 sysvals.testdir = sysvals.setOutputFolder(val)
758 doError('Output filename collision')
759 sysvals.htmlfile = val
760 elif(arg == '-reboot'): 915 elif(arg == '-reboot'):
761 if sysvals.iscronjob:
762 doError('-reboot and -cronjob are incompatible')
763 sysvals.reboot = True 916 sysvals.reboot = True
764 elif(arg == '-manual'): 917 elif(arg == '-manual'):
765 sysvals.reboot = True 918 sysvals.reboot = True
@@ -767,58 +920,93 @@ if __name__ == '__main__':
767 # remaining options are only for cron job use 920 # remaining options are only for cron job use
768 elif(arg == '-cronjob'): 921 elif(arg == '-cronjob'):
769 sysvals.iscronjob = True 922 sysvals.iscronjob = True
770 if sysvals.reboot:
771 doError('-reboot and -cronjob are incompatible')
772 else: 923 else:
773 doError('Invalid argument: '+arg, True) 924 doError('Invalid argument: '+arg, True)
774 925
926 # compatibility errors and access checks
927 if(sysvals.iscronjob and (sysvals.reboot or \
928 sysvals.dmesgfile or sysvals.ftracefile or cmd)):
929 doError('-cronjob is meant for batch purposes only')
930 if(sysvals.reboot and (sysvals.dmesgfile or sysvals.ftracefile)):
931 doError('-reboot and -dmesg/-ftrace are incompatible')
932 if cmd or sysvals.reboot or sysvals.iscronjob or testrun:
933 sysvals.rootCheck(True)
934 if (testrun and sysvals.useftrace) or cmd == 'flistall':
935 if not sysvals.verifyFtrace():
936 doError('Ftrace is not properly enabled')
937
938 # run utility commands
939 sysvals.cpuInfo()
775 if cmd != '': 940 if cmd != '':
776 if cmd == 'updategrub': 941 if cmd == 'kpupdate':
777 updateGrub() 942 updateKernelParams()
778 elif cmd == 'flistall': 943 elif cmd == 'flistall':
779 sysvals.getFtraceFilterFunctions(False) 944 for f in sysvals.getBootFtraceFilterFunctions():
945 print f
946 elif cmd == 'checkbl':
947 sysvals.getBootLoader()
948 print 'Boot Loader: %s\n%s' % (sysvals.bootloader, sysvals.blexec)
949 elif(cmd == 'sysinfo'):
950 sysvals.printSystemInfo()
780 sys.exit() 951 sys.exit()
781 952
782 # update grub, setup a cronjob, and reboot 953 # reboot: update grub, setup a cronjob, and reboot
783 if sysvals.reboot: 954 if sysvals.reboot:
955 if (sysvals.useftrace or sysvals.usecallgraph) and \
956 not sysvals.checkFtraceKernelVersion():
957 doError('Ftrace functionality requires kernel v4.10 or newer')
784 if not sysvals.manual: 958 if not sysvals.manual:
785 updateGrub() 959 updateKernelParams()
786 updateCron() 960 updateCron()
787 call('reboot') 961 call('reboot')
788 else: 962 else:
789 sysvals.manualRebootRequired() 963 sysvals.manualRebootRequired()
790 sys.exit() 964 sys.exit()
791 965
792 # disable the cronjob 966 # cronjob: remove the cronjob, grub changes, and disable ftrace
793 if sysvals.iscronjob: 967 if sysvals.iscronjob:
794 updateCron(True) 968 updateCron(True)
795 updateGrub(True) 969 updateKernelParams(True)
970 try:
971 sysvals.fsetVal('0', 'tracing_on')
972 except:
973 pass
796 974
797 data = loadKernelLog() 975 # testrun: generate copies of the logs
798 if sysvals.useftrace: 976 if testrun:
799 loadTraceLog(data) 977 retrieveLogs()
800 if sysvals.iscronjob: 978 else:
801 try: 979 sysvals.setOutputFile()
802 sysvals.fsetVal('0', 'tracing_on')
803 except:
804 pass
805 980
806 if(sysvals.outfile and sysvals.phoronix): 981 # process the log data
807 fp = open(sysvals.outfile, 'w') 982 if sysvals.dmesgfile:
808 fp.write('pass %s initstart %.3f end %.3f boot %s\n' % 983 data = parseKernelLog()
809 (data.valid, data.initstart*1000, data.end*1000, data.boottime)) 984 if(not data.valid):
810 fp.close()
811 if(not data.valid):
812 if sysvals.dmesgfile:
813 doError('No initcall data found in %s' % sysvals.dmesgfile) 985 doError('No initcall data found in %s' % sysvals.dmesgfile)
814 else: 986 if sysvals.useftrace and sysvals.ftracefile:
815 doError('No initcall data found, is initcall_debug enabled?') 987 parseTraceLog(data)
988 else:
989 doError('dmesg file required')
816 990
817 print(' Host: %s' % sysvals.hostname) 991 print(' Host: %s' % sysvals.hostname)
818 print(' Test time: %s' % sysvals.testtime) 992 print(' Test time: %s' % sysvals.testtime)
819 print(' Boot time: %s' % data.boottime) 993 print(' Boot time: %s' % data.boottime)
820 print('Kernel Version: %s' % sysvals.kernel) 994 print('Kernel Version: %s' % sysvals.kernel)
821 print(' Kernel start: %.3f' % (data.start * 1000)) 995 print(' Kernel start: %.3f' % (data.start * 1000))
822 print(' init start: %.3f' % (data.initstart * 1000)) 996 print('Usermode start: %.3f' % (data.tUserMode * 1000))
997 print('Last Init Call: %.3f' % (data.end * 1000))
998
999 # handle embedded output logs
1000 if(sysvals.outfile and sysvals.embedded):
1001 fp = open(sysvals.outfile, 'w')
1002 fp.write('pass %s initstart %.3f end %.3f boot %s\n' %
1003 (data.valid, data.tUserMode*1000, data.end*1000, data.boottime))
1004 fp.close()
1005
1006 createBootGraph(data)
823 1007
824 createBootGraph(data, sysvals.phoronix) 1008 # if running as root, change output dir owner to sudo_user
1009 if testrun and os.path.isdir(sysvals.testdir) and \
1010 os.getuid() == 0 and 'SUDO_USER' in os.environ:
1011 cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1'
1012 call(cmd.format(os.environ['SUDO_USER'], sysvals.testdir), shell=True)
diff --git a/tools/power/pm-graph/analyze_suspend.py b/tools/power/pm-graph/analyze_suspend.py
index a9206e67fc1f..1b60fe203741 100755
--- a/tools/power/pm-graph/analyze_suspend.py
+++ b/tools/power/pm-graph/analyze_suspend.py
@@ -68,10 +68,12 @@ from subprocess import call, Popen, PIPE
68# store system values and test parameters 68# store system values and test parameters
69class SystemValues: 69class SystemValues:
70 title = 'SleepGraph' 70 title = 'SleepGraph'
71 version = '4.6' 71 version = '4.7'
72 ansi = False 72 ansi = False
73 verbose = False 73 verbose = False
74 addlogs = False 74 testlog = True
75 dmesglog = False
76 ftracelog = False
75 mindevlen = 0.0 77 mindevlen = 0.0
76 mincglen = 0.0 78 mincglen = 0.0
77 cgphase = '' 79 cgphase = ''
@@ -79,10 +81,11 @@ class SystemValues:
79 max_graph_depth = 0 81 max_graph_depth = 0
80 callloopmaxgap = 0.0001 82 callloopmaxgap = 0.0001
81 callloopmaxlen = 0.005 83 callloopmaxlen = 0.005
84 cpucount = 0
85 memtotal = 204800
82 srgap = 0 86 srgap = 0
83 cgexp = False 87 cgexp = False
84 outdir = '' 88 testdir = ''
85 testdir = '.'
86 tpath = '/sys/kernel/debug/tracing/' 89 tpath = '/sys/kernel/debug/tracing/'
87 fpdtpath = '/sys/firmware/acpi/tables/FPDT' 90 fpdtpath = '/sys/firmware/acpi/tables/FPDT'
88 epath = '/sys/kernel/debug/tracing/events/power/' 91 epath = '/sys/kernel/debug/tracing/events/power/'
@@ -95,14 +98,17 @@ class SystemValues:
95 testcommand = '' 98 testcommand = ''
96 mempath = '/dev/mem' 99 mempath = '/dev/mem'
97 powerfile = '/sys/power/state' 100 powerfile = '/sys/power/state'
101 mempowerfile = '/sys/power/mem_sleep'
98 suspendmode = 'mem' 102 suspendmode = 'mem'
103 memmode = ''
99 hostname = 'localhost' 104 hostname = 'localhost'
100 prefix = 'test' 105 prefix = 'test'
101 teststamp = '' 106 teststamp = ''
107 sysstamp = ''
102 dmesgstart = 0.0 108 dmesgstart = 0.0
103 dmesgfile = '' 109 dmesgfile = ''
104 ftracefile = '' 110 ftracefile = ''
105 htmlfile = '' 111 htmlfile = 'output.html'
106 embedded = False 112 embedded = False
107 rtcwake = True 113 rtcwake = True
108 rtcwaketime = 15 114 rtcwaketime = 15
@@ -127,9 +133,6 @@ class SystemValues:
127 devpropfmt = '# Device Properties: .*' 133 devpropfmt = '# Device Properties: .*'
128 tracertypefmt = '# tracer: (?P<t>.*)' 134 tracertypefmt = '# tracer: (?P<t>.*)'
129 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$' 135 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$'
130 stampfmt = '# suspend-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\
131 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\
132 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$'
133 tracefuncs = { 136 tracefuncs = {
134 'sys_sync': dict(), 137 'sys_sync': dict(),
135 'pm_prepare_console': dict(), 138 'pm_prepare_console': dict(),
@@ -218,7 +221,7 @@ class SystemValues:
218 # if this is a phoronix test run, set some default options 221 # if this is a phoronix test run, set some default options
219 if('LOG_FILE' in os.environ and 'TEST_RESULTS_IDENTIFIER' in os.environ): 222 if('LOG_FILE' in os.environ and 'TEST_RESULTS_IDENTIFIER' in os.environ):
220 self.embedded = True 223 self.embedded = True
221 self.addlogs = True 224 self.dmesglog = self.ftracelog = True
222 self.htmlfile = os.environ['LOG_FILE'] 225 self.htmlfile = os.environ['LOG_FILE']
223 self.archargs = 'args_'+platform.machine() 226 self.archargs = 'args_'+platform.machine()
224 self.hostname = platform.node() 227 self.hostname = platform.node()
@@ -233,6 +236,13 @@ class SystemValues:
233 self.rtcpath = rtc 236 self.rtcpath = rtc
234 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()): 237 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()):
235 self.ansi = True 238 self.ansi = True
239 self.testdir = datetime.now().strftime('suspend-%y%m%d-%H%M%S')
240 def rootCheck(self, fatal=True):
241 if(os.access(self.powerfile, os.W_OK)):
242 return True
243 if fatal:
244 doError('This command requires sysfs mount and root access')
245 return False
236 def rootUser(self, fatal=False): 246 def rootUser(self, fatal=False):
237 if 'USER' in os.environ and os.environ['USER'] == 'root': 247 if 'USER' in os.environ and os.environ['USER'] == 'root':
238 return True 248 return True
@@ -249,30 +259,60 @@ class SystemValues:
249 args['date'] = n.strftime('%y%m%d') 259 args['date'] = n.strftime('%y%m%d')
250 args['time'] = n.strftime('%H%M%S') 260 args['time'] = n.strftime('%H%M%S')
251 args['hostname'] = self.hostname 261 args['hostname'] = self.hostname
252 self.outdir = value.format(**args) 262 return value.format(**args)
253 def setOutputFile(self): 263 def setOutputFile(self):
254 if((self.htmlfile == '') and (self.dmesgfile != '')): 264 if self.dmesgfile != '':
255 m = re.match('(?P<name>.*)_dmesg\.txt$', self.dmesgfile) 265 m = re.match('(?P<name>.*)_dmesg\.txt$', self.dmesgfile)
256 if(m): 266 if(m):
257 self.htmlfile = m.group('name')+'.html' 267 self.htmlfile = m.group('name')+'.html'
258 if((self.htmlfile == '') and (self.ftracefile != '')): 268 if self.ftracefile != '':
259 m = re.match('(?P<name>.*)_ftrace\.txt$', self.ftracefile) 269 m = re.match('(?P<name>.*)_ftrace\.txt$', self.ftracefile)
260 if(m): 270 if(m):
261 self.htmlfile = m.group('name')+'.html' 271 self.htmlfile = m.group('name')+'.html'
262 if(self.htmlfile == ''): 272 def systemInfo(self, info):
263 self.htmlfile = 'output.html' 273 p = c = m = b = ''
264 def initTestOutput(self, subdir, testpath=''): 274 if 'baseboard-manufacturer' in info:
275 m = info['baseboard-manufacturer']
276 elif 'system-manufacturer' in info:
277 m = info['system-manufacturer']
278 if 'baseboard-product-name' in info:
279 p = info['baseboard-product-name']
280 elif 'system-product-name' in info:
281 p = info['system-product-name']
282 if 'processor-version' in info:
283 c = info['processor-version']
284 if 'bios-version' in info:
285 b = info['bios-version']
286 self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | numcpu:%d | memsz:%d' % \
287 (m, p, c, b, self.cpucount, self.memtotal)
288 def printSystemInfo(self):
289 self.rootCheck(True)
290 out = dmidecode(self.mempath, True)
291 fmt = '%-24s: %s'
292 for name in sorted(out):
293 print fmt % (name, out[name])
294 print fmt % ('cpucount', ('%d' % self.cpucount))
295 print fmt % ('memtotal', ('%d kB' % self.memtotal))
296 def cpuInfo(self):
297 self.cpucount = 0
298 fp = open('/proc/cpuinfo', 'r')
299 for line in fp:
300 if re.match('^processor[ \t]*:[ \t]*[0-9]*', line):
301 self.cpucount += 1
302 fp.close()
303 fp = open('/proc/meminfo', 'r')
304 for line in fp:
305 m = re.match('^MemTotal:[ \t]*(?P<sz>[0-9]*) *kB', line)
306 if m:
307 self.memtotal = int(m.group('sz'))
308 break
309 fp.close()
310 def initTestOutput(self, name):
265 self.prefix = self.hostname 311 self.prefix = self.hostname
266 v = open('/proc/version', 'r').read().strip() 312 v = open('/proc/version', 'r').read().strip()
267 kver = string.split(v)[2] 313 kver = string.split(v)[2]
268 n = datetime.now() 314 fmt = name+'-%m%d%y-%H%M%S'
269 testtime = n.strftime('suspend-%m%d%y-%H%M%S') 315 testtime = datetime.now().strftime(fmt)
270 if not testpath:
271 testpath = n.strftime('suspend-%y%m%d-%H%M%S')
272 if(subdir != "."):
273 self.testdir = subdir+"/"+testpath
274 else:
275 self.testdir = testpath
276 self.teststamp = \ 316 self.teststamp = \
277 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver 317 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver
278 if(self.embedded): 318 if(self.embedded):
@@ -355,7 +395,7 @@ class SystemValues:
355 continue 395 continue
356 self.tracefuncs[i] = dict() 396 self.tracefuncs[i] = dict()
357 def getFtraceFilterFunctions(self, current): 397 def getFtraceFilterFunctions(self, current):
358 rootCheck(True) 398 self.rootCheck(True)
359 if not current: 399 if not current:
360 call('cat '+self.tpath+'available_filter_functions', shell=True) 400 call('cat '+self.tpath+'available_filter_functions', shell=True)
361 return 401 return
@@ -453,7 +493,7 @@ class SystemValues:
453 val += '\nr:%s_ret %s $retval\n' % (name, func) 493 val += '\nr:%s_ret %s $retval\n' % (name, func)
454 return val 494 return val
455 def addKprobes(self, output=False): 495 def addKprobes(self, output=False):
456 if len(sysvals.kprobes) < 1: 496 if len(self.kprobes) < 1:
457 return 497 return
458 if output: 498 if output:
459 print(' kprobe functions in this kernel:') 499 print(' kprobe functions in this kernel:')
@@ -525,7 +565,7 @@ class SystemValues:
525 fp.flush() 565 fp.flush()
526 fp.close() 566 fp.close()
527 except: 567 except:
528 pass 568 return False
529 return True 569 return True
530 def fgetVal(self, path): 570 def fgetVal(self, path):
531 file = self.tpath+path 571 file = self.tpath+path
@@ -566,9 +606,15 @@ class SystemValues:
566 self.cleanupFtrace() 606 self.cleanupFtrace()
567 # set the trace clock to global 607 # set the trace clock to global
568 self.fsetVal('global', 'trace_clock') 608 self.fsetVal('global', 'trace_clock')
569 # set trace buffer to a huge value
570 self.fsetVal('nop', 'current_tracer') 609 self.fsetVal('nop', 'current_tracer')
571 self.fsetVal('131073', 'buffer_size_kb') 610 # set trace buffer to a huge value
611 if self.usecallgraph or self.usedevsrc:
612 tgtsize = min(self.memtotal / 2, 2*1024*1024)
613 maxbuf = '%d' % (tgtsize / max(1, self.cpucount))
614 if self.cpucount < 1 or not self.fsetVal(maxbuf, 'buffer_size_kb'):
615 self.fsetVal('131072', 'buffer_size_kb')
616 else:
617 self.fsetVal('16384', 'buffer_size_kb')
572 # go no further if this is just a status check 618 # go no further if this is just a status check
573 if testing: 619 if testing:
574 return 620 return
@@ -641,6 +687,15 @@ class SystemValues:
641 if not self.ansi: 687 if not self.ansi:
642 return str 688 return str
643 return '\x1B[%d;40m%s\x1B[m' % (color, str) 689 return '\x1B[%d;40m%s\x1B[m' % (color, str)
690 def writeDatafileHeader(self, filename, fwdata=[]):
691 fp = open(filename, 'w')
692 fp.write(self.teststamp+'\n')
693 fp.write(self.sysstamp+'\n')
694 if(self.suspendmode == 'mem' or self.suspendmode == 'command'):
695 for fw in fwdata:
696 if(fw):
697 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1]))
698 fp.close()
644 699
645sysvals = SystemValues() 700sysvals = SystemValues()
646suspendmodename = { 701suspendmodename = {
@@ -1008,6 +1063,12 @@ class Data:
1008 else: 1063 else:
1009 self.trimTime(self.tSuspended, \ 1064 self.trimTime(self.tSuspended, \
1010 self.tResumed-self.tSuspended, False) 1065 self.tResumed-self.tSuspended, False)
1066 def getTimeValues(self):
1067 sktime = (self.dmesg['suspend_machine']['end'] - \
1068 self.tKernSus) * 1000
1069 rktime = (self.dmesg['resume_complete']['end'] - \
1070 self.dmesg['resume_machine']['start']) * 1000
1071 return (sktime, rktime)
1011 def setPhase(self, phase, ktime, isbegin): 1072 def setPhase(self, phase, ktime, isbegin):
1012 if(isbegin): 1073 if(isbegin):
1013 self.dmesg[phase]['start'] = ktime 1074 self.dmesg[phase]['start'] = ktime
@@ -1517,7 +1578,7 @@ class FTraceCallGraph:
1517 prelinedep += 1 1578 prelinedep += 1
1518 last = 0 1579 last = 0
1519 lasttime = line.time 1580 lasttime = line.time
1520 virtualfname = 'execution_misalignment' 1581 virtualfname = 'missing_function_name'
1521 if len(self.list) > 0: 1582 if len(self.list) > 0:
1522 last = self.list[-1] 1583 last = self.list[-1]
1523 lasttime = last.time 1584 lasttime = last.time
@@ -1773,24 +1834,30 @@ class Timeline:
1773 html_device = '<div id="{0}" title="{1}" class="thread{7}" style="left:{2}%;top:{3}px;height:{4}px;width:{5}%;{8}">{6}</div>\n' 1834 html_device = '<div id="{0}" title="{1}" class="thread{7}" style="left:{2}%;top:{3}px;height:{4}px;width:{5}%;{8}">{6}</div>\n'
1774 html_phase = '<div class="phase" style="left:{0}%;width:{1}%;top:{2}px;height:{3}px;background:{4}">{5}</div>\n' 1835 html_phase = '<div class="phase" style="left:{0}%;width:{1}%;top:{2}px;height:{3}px;background:{4}">{5}</div>\n'
1775 html_phaselet = '<div id="{0}" class="phaselet" style="left:{1}%;width:{2}%;background:{3}"></div>\n' 1836 html_phaselet = '<div id="{0}" class="phaselet" style="left:{1}%;width:{2}%;background:{3}"></div>\n'
1837 html_legend = '<div id="p{3}" class="square" style="left:{0}%;background:{1}">&nbsp;{2}</div>\n'
1776 def __init__(self, rowheight, scaleheight): 1838 def __init__(self, rowheight, scaleheight):
1777 self.rowH = rowheight 1839 self.rowH = rowheight
1778 self.scaleH = scaleheight 1840 self.scaleH = scaleheight
1779 self.html = '' 1841 self.html = ''
1780 def createHeader(self, sv, suppress=''): 1842 def createHeader(self, sv):
1781 if(not sv.stamp['time']): 1843 if(not sv.stamp['time']):
1782 return 1844 return
1783 self.html += '<div class="version"><a href="https://01.org/suspendresume">%s v%s</a></div>' \ 1845 self.html += '<div class="version"><a href="https://01.org/suspendresume">%s v%s</a></div>' \
1784 % (sv.title, sv.version) 1846 % (sv.title, sv.version)
1785 if sv.logmsg and 'log' not in suppress: 1847 if sv.logmsg and sv.testlog:
1786 self.html += '<button id="showtest" class="logbtn">log</button>' 1848 self.html += '<button id="showtest" class="logbtn btnfmt">log</button>'
1787 if sv.addlogs and 'dmesg' not in suppress: 1849 if sv.dmesglog:
1788 self.html += '<button id="showdmesg" class="logbtn">dmesg</button>' 1850 self.html += '<button id="showdmesg" class="logbtn btnfmt">dmesg</button>'
1789 if sv.addlogs and sv.ftracefile and 'ftrace' not in suppress: 1851 if sv.ftracelog:
1790 self.html += '<button id="showftrace" class="logbtn">ftrace</button>' 1852 self.html += '<button id="showftrace" class="logbtn btnfmt">ftrace</button>'
1791 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n' 1853 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n'
1792 self.html += headline_stamp.format(sv.stamp['host'], sv.stamp['kernel'], 1854 self.html += headline_stamp.format(sv.stamp['host'], sv.stamp['kernel'],
1793 sv.stamp['mode'], sv.stamp['time']) 1855 sv.stamp['mode'], sv.stamp['time'])
1856 if 'man' in sv.stamp and 'plat' in sv.stamp and 'cpu' in sv.stamp:
1857 headline_sysinfo = '<div class="stamp sysinfo">{0} {1} <i>with</i> {2}</div>\n'
1858 self.html += headline_sysinfo.format(sv.stamp['man'],
1859 sv.stamp['plat'], sv.stamp['cpu'])
1860
1794 # Function: getDeviceRows 1861 # Function: getDeviceRows
1795 # Description: 1862 # Description:
1796 # determine how may rows the device funcs will take 1863 # determine how may rows the device funcs will take
@@ -1839,7 +1906,7 @@ class Timeline:
1839 # devlist: the list of devices/actions in a group of contiguous phases 1906 # devlist: the list of devices/actions in a group of contiguous phases
1840 # Output: 1907 # Output:
1841 # The total number of rows needed to display this phase of the timeline 1908 # The total number of rows needed to display this phase of the timeline
1842 def getPhaseRows(self, devlist, row=0): 1909 def getPhaseRows(self, devlist, row=0, sortby='length'):
1843 # clear all rows and set them to undefined 1910 # clear all rows and set them to undefined
1844 remaining = len(devlist) 1911 remaining = len(devlist)
1845 rowdata = dict() 1912 rowdata = dict()
@@ -1852,8 +1919,12 @@ class Timeline:
1852 if tp not in myphases: 1919 if tp not in myphases:
1853 myphases.append(tp) 1920 myphases.append(tp)
1854 dev['row'] = -1 1921 dev['row'] = -1
1855 # sort by length 1st, then name 2nd 1922 if sortby == 'start':
1856 sortdict[item] = (float(dev['end']) - float(dev['start']), item.dev['name']) 1923 # sort by start 1st, then length 2nd
1924 sortdict[item] = (-1*float(dev['start']), float(dev['end']) - float(dev['start']))
1925 else:
1926 # sort by length 1st, then name 2nd
1927 sortdict[item] = (float(dev['end']) - float(dev['start']), item.dev['name'])
1857 if 'src' in dev: 1928 if 'src' in dev:
1858 dev['devrows'] = self.getDeviceRows(dev['src']) 1929 dev['devrows'] = self.getDeviceRows(dev['src'])
1859 # sort the devlist by length so that large items graph on top 1930 # sort the devlist by length so that large items graph on top
@@ -1995,8 +2066,13 @@ class Timeline:
1995# A list of values describing the properties of these test runs 2066# A list of values describing the properties of these test runs
1996class TestProps: 2067class TestProps:
1997 stamp = '' 2068 stamp = ''
2069 sysinfo = ''
1998 S0i3 = False 2070 S0i3 = False
1999 fwdata = [] 2071 fwdata = []
2072 stampfmt = '# [a-z]*-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\
2073 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\
2074 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$'
2075 sysinfofmt = '^# sysinfo .*'
2000 ftrace_line_fmt_fg = \ 2076 ftrace_line_fmt_fg = \
2001 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\ 2077 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\
2002 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\ 2078 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\
@@ -2019,6 +2095,36 @@ class TestProps:
2019 self.ftrace_line_fmt = self.ftrace_line_fmt_nop 2095 self.ftrace_line_fmt = self.ftrace_line_fmt_nop
2020 else: 2096 else:
2021 doError('Invalid tracer format: [%s]' % tracer) 2097 doError('Invalid tracer format: [%s]' % tracer)
2098 def parseStamp(self, data, sv):
2099 m = re.match(self.stampfmt, self.stamp)
2100 data.stamp = {'time': '', 'host': '', 'mode': ''}
2101 dt = datetime(int(m.group('y'))+2000, int(m.group('m')),
2102 int(m.group('d')), int(m.group('H')), int(m.group('M')),
2103 int(m.group('S')))
2104 data.stamp['time'] = dt.strftime('%B %d %Y, %I:%M:%S %p')
2105 data.stamp['host'] = m.group('host')
2106 data.stamp['mode'] = m.group('mode')
2107 data.stamp['kernel'] = m.group('kernel')
2108 if re.match(self.sysinfofmt, self.sysinfo):
2109 for f in self.sysinfo.split('|'):
2110 if '#' in f:
2111 continue
2112 tmp = f.strip().split(':', 1)
2113 key = tmp[0]
2114 val = tmp[1]
2115 data.stamp[key] = val
2116 sv.hostname = data.stamp['host']
2117 sv.suspendmode = data.stamp['mode']
2118 if sv.suspendmode == 'command' and sv.ftracefile != '':
2119 modes = ['on', 'freeze', 'standby', 'mem']
2120 out = Popen(['grep', 'suspend_enter', sv.ftracefile],
2121 stderr=PIPE, stdout=PIPE).stdout.read()
2122 m = re.match('.* suspend_enter\[(?P<mode>.*)\]', out)
2123 if m and m.group('mode') in ['1', '2', '3']:
2124 sv.suspendmode = modes[int(m.group('mode'))]
2125 data.stamp['mode'] = sv.suspendmode
2126 if not sv.stamp:
2127 sv.stamp = data.stamp
2022 2128
2023# Class: TestRun 2129# Class: TestRun
2024# Description: 2130# Description:
@@ -2090,35 +2196,6 @@ def vprint(msg):
2090 if(sysvals.verbose): 2196 if(sysvals.verbose):
2091 print(msg) 2197 print(msg)
2092 2198
2093# Function: parseStamp
2094# Description:
2095# Pull in the stamp comment line from the data file(s),
2096# create the stamp, and add it to the global sysvals object
2097# Arguments:
2098# m: the valid re.match output for the stamp line
2099def parseStamp(line, data):
2100 m = re.match(sysvals.stampfmt, line)
2101 data.stamp = {'time': '', 'host': '', 'mode': ''}
2102 dt = datetime(int(m.group('y'))+2000, int(m.group('m')),
2103 int(m.group('d')), int(m.group('H')), int(m.group('M')),
2104 int(m.group('S')))
2105 data.stamp['time'] = dt.strftime('%B %d %Y, %I:%M:%S %p')
2106 data.stamp['host'] = m.group('host')
2107 data.stamp['mode'] = m.group('mode')
2108 data.stamp['kernel'] = m.group('kernel')
2109 sysvals.hostname = data.stamp['host']
2110 sysvals.suspendmode = data.stamp['mode']
2111 if sysvals.suspendmode == 'command' and sysvals.ftracefile != '':
2112 modes = ['on', 'freeze', 'standby', 'mem']
2113 out = Popen(['grep', 'suspend_enter', sysvals.ftracefile],
2114 stderr=PIPE, stdout=PIPE).stdout.read()
2115 m = re.match('.* suspend_enter\[(?P<mode>.*)\]', out)
2116 if m and m.group('mode') in ['1', '2', '3']:
2117 sysvals.suspendmode = modes[int(m.group('mode'))]
2118 data.stamp['mode'] = sysvals.suspendmode
2119 if not sysvals.stamp:
2120 sysvals.stamp = data.stamp
2121
2122# Function: doesTraceLogHaveTraceEvents 2199# Function: doesTraceLogHaveTraceEvents
2123# Description: 2200# Description:
2124# Quickly determine if the ftrace log has some or all of the trace events 2201# Quickly determine if the ftrace log has some or all of the trace events
@@ -2136,11 +2213,6 @@ def doesTraceLogHaveTraceEvents():
2136 sysvals.usekprobes = True 2213 sysvals.usekprobes = True
2137 out = Popen(['head', '-1', sysvals.ftracefile], 2214 out = Popen(['head', '-1', sysvals.ftracefile],
2138 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '') 2215 stderr=PIPE, stdout=PIPE).stdout.read().replace('\n', '')
2139 m = re.match(sysvals.stampfmt, out)
2140 if m and m.group('mode') == 'command':
2141 sysvals.usetraceeventsonly = True
2142 sysvals.usetraceevents = True
2143 return
2144 # figure out what level of trace events are supported 2216 # figure out what level of trace events are supported
2145 sysvals.usetraceeventsonly = True 2217 sysvals.usetraceeventsonly = True
2146 sysvals.usetraceevents = False 2218 sysvals.usetraceevents = False
@@ -2182,11 +2254,13 @@ def appendIncompleteTraceLog(testruns):
2182 for line in tf: 2254 for line in tf:
2183 # remove any latent carriage returns 2255 # remove any latent carriage returns
2184 line = line.replace('\r\n', '') 2256 line = line.replace('\r\n', '')
2185 # grab the time stamp 2257 # grab the stamp and sysinfo
2186 m = re.match(sysvals.stampfmt, line) 2258 if re.match(tp.stampfmt, line):
2187 if(m):
2188 tp.stamp = line 2259 tp.stamp = line
2189 continue 2260 continue
2261 elif re.match(tp.sysinfofmt, line):
2262 tp.sysinfo = line
2263 continue
2190 # determine the trace data type (required for further parsing) 2264 # determine the trace data type (required for further parsing)
2191 m = re.match(sysvals.tracertypefmt, line) 2265 m = re.match(sysvals.tracertypefmt, line)
2192 if(m): 2266 if(m):
@@ -2219,7 +2293,7 @@ def appendIncompleteTraceLog(testruns):
2219 # look for the suspend start marker 2293 # look for the suspend start marker
2220 if(t.startMarker()): 2294 if(t.startMarker()):
2221 data = testrun[testidx].data 2295 data = testrun[testidx].data
2222 parseStamp(tp.stamp, data) 2296 tp.parseStamp(data, sysvals)
2223 data.setStart(t.time) 2297 data.setStart(t.time)
2224 continue 2298 continue
2225 if(not data): 2299 if(not data):
@@ -2389,11 +2463,13 @@ def parseTraceLog():
2389 for line in tf: 2463 for line in tf:
2390 # remove any latent carriage returns 2464 # remove any latent carriage returns
2391 line = line.replace('\r\n', '') 2465 line = line.replace('\r\n', '')
2392 # stamp line: each stamp means a new test run 2466 # stamp and sysinfo lines
2393 m = re.match(sysvals.stampfmt, line) 2467 if re.match(tp.stampfmt, line):
2394 if(m):
2395 tp.stamp = line 2468 tp.stamp = line
2396 continue 2469 continue
2470 elif re.match(tp.sysinfofmt, line):
2471 tp.sysinfo = line
2472 continue
2397 # firmware line: pull out any firmware data 2473 # firmware line: pull out any firmware data
2398 m = re.match(sysvals.firmwarefmt, line) 2474 m = re.match(sysvals.firmwarefmt, line)
2399 if(m): 2475 if(m):
@@ -2439,7 +2515,7 @@ def parseTraceLog():
2439 testdata.append(data) 2515 testdata.append(data)
2440 testrun = TestRun(data) 2516 testrun = TestRun(data)
2441 testruns.append(testrun) 2517 testruns.append(testrun)
2442 parseStamp(tp.stamp, data) 2518 tp.parseStamp(data, sysvals)
2443 data.setStart(t.time) 2519 data.setStart(t.time)
2444 data.tKernSus = t.time 2520 data.tKernSus = t.time
2445 continue 2521 continue
@@ -2820,10 +2896,13 @@ def loadKernelLog(justtext=False):
2820 idx = line.find('[') 2896 idx = line.find('[')
2821 if idx > 1: 2897 if idx > 1:
2822 line = line[idx:] 2898 line = line[idx:]
2823 m = re.match(sysvals.stampfmt, line) 2899 # grab the stamp and sysinfo
2824 if(m): 2900 if re.match(tp.stampfmt, line):
2825 tp.stamp = line 2901 tp.stamp = line
2826 continue 2902 continue
2903 elif re.match(tp.sysinfofmt, line):
2904 tp.sysinfo = line
2905 continue
2827 m = re.match(sysvals.firmwarefmt, line) 2906 m = re.match(sysvals.firmwarefmt, line)
2828 if(m): 2907 if(m):
2829 tp.fwdata.append((int(m.group('s')), int(m.group('r')))) 2908 tp.fwdata.append((int(m.group('s')), int(m.group('r'))))
@@ -2839,7 +2918,7 @@ def loadKernelLog(justtext=False):
2839 if(data): 2918 if(data):
2840 testruns.append(data) 2919 testruns.append(data)
2841 data = Data(len(testruns)) 2920 data = Data(len(testruns))
2842 parseStamp(tp.stamp, data) 2921 tp.parseStamp(data, sysvals)
2843 if len(tp.fwdata) > data.testnumber: 2922 if len(tp.fwdata) > data.testnumber:
2844 data.fwSuspend, data.fwResume = tp.fwdata[data.testnumber] 2923 data.fwSuspend, data.fwResume = tp.fwdata[data.testnumber]
2845 if(data.fwSuspend > 0 or data.fwResume > 0): 2924 if(data.fwSuspend > 0 or data.fwResume > 0):
@@ -3170,6 +3249,8 @@ def addCallgraphs(sv, hf, data):
3170 continue 3249 continue
3171 list = data.dmesg[p]['list'] 3250 list = data.dmesg[p]['list']
3172 for devname in data.sortedDevices(p): 3251 for devname in data.sortedDevices(p):
3252 if len(sv.devicefilter) > 0 and devname not in sv.devicefilter:
3253 continue
3173 dev = list[devname] 3254 dev = list[devname]
3174 color = 'white' 3255 color = 'white'
3175 if 'color' in data.dmesg[p]: 3256 if 'color' in data.dmesg[p]:
@@ -3309,7 +3390,6 @@ def createHTML(testruns):
3309 html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">ERROR&rarr;</div>\n' 3390 html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">ERROR&rarr;</div>\n'
3310 html_traceevent = '<div title="{0}" class="traceevent{6}" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;{7}">{5}</div>\n' 3391 html_traceevent = '<div title="{0}" class="traceevent{6}" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;{7}">{5}</div>\n'
3311 html_cpuexec = '<div class="jiffie" style="left:{0}%;top:{1}px;height:{2}px;width:{3}%;background:{4};"></div>\n' 3392 html_cpuexec = '<div class="jiffie" style="left:{0}%;top:{1}px;height:{2}px;width:{3}%;background:{4};"></div>\n'
3312 html_legend = '<div id="p{3}" class="square" style="left:{0}%;background:{1}">&nbsp;{2}</div>\n'
3313 html_timetotal = '<table class="time1">\n<tr>'\ 3393 html_timetotal = '<table class="time1">\n<tr>'\
3314 '<td class="green" title="{3}">{2} Suspend Time: <b>{0} ms</b></td>'\ 3394 '<td class="green" title="{3}">{2} Suspend Time: <b>{0} ms</b></td>'\
3315 '<td class="yellow" title="{4}">{2} Resume Time: <b>{1} ms</b></td>'\ 3395 '<td class="yellow" title="{4}">{2} Resume Time: <b>{1} ms</b></td>'\
@@ -3346,10 +3426,7 @@ def createHTML(testruns):
3346 # Generate the header for this timeline 3426 # Generate the header for this timeline
3347 for data in testruns: 3427 for data in testruns:
3348 tTotal = data.end - data.start 3428 tTotal = data.end - data.start
3349 sktime = (data.dmesg['suspend_machine']['end'] - \ 3429 sktime, rktime = data.getTimeValues()
3350 data.tKernSus) * 1000
3351 rktime = (data.dmesg['resume_complete']['end'] - \
3352 data.dmesg['resume_machine']['start']) * 1000
3353 if(tTotal == 0): 3430 if(tTotal == 0):
3354 print('ERROR: No timeline data') 3431 print('ERROR: No timeline data')
3355 sys.exit() 3432 sys.exit()
@@ -3581,7 +3658,7 @@ def createHTML(testruns):
3581 id += tmp[1][0] 3658 id += tmp[1][0]
3582 order = '%.2f' % ((data.dmesg[phase]['order'] * pdelta) + pmargin) 3659 order = '%.2f' % ((data.dmesg[phase]['order'] * pdelta) + pmargin)
3583 name = string.replace(phase, '_', ' &nbsp;') 3660 name = string.replace(phase, '_', ' &nbsp;')
3584 devtl.html += html_legend.format(order, \ 3661 devtl.html += devtl.html_legend.format(order, \
3585 data.dmesg[phase]['color'], name, id) 3662 data.dmesg[phase]['color'], name, id)
3586 devtl.html += '</div>\n' 3663 devtl.html += '</div>\n'
3587 3664
@@ -3628,10 +3705,10 @@ def createHTML(testruns):
3628 addCallgraphs(sysvals, hf, data) 3705 addCallgraphs(sysvals, hf, data)
3629 3706
3630 # add the test log as a hidden div 3707 # add the test log as a hidden div
3631 if sysvals.logmsg: 3708 if sysvals.testlog and sysvals.logmsg:
3632 hf.write('<div id="testlog" style="display:none;">\n'+sysvals.logmsg+'</div>\n') 3709 hf.write('<div id="testlog" style="display:none;">\n'+sysvals.logmsg+'</div>\n')
3633 # add the dmesg log as a hidden div 3710 # add the dmesg log as a hidden div
3634 if sysvals.addlogs and sysvals.dmesgfile: 3711 if sysvals.dmesglog and sysvals.dmesgfile:
3635 hf.write('<div id="dmesglog" style="display:none;">\n') 3712 hf.write('<div id="dmesglog" style="display:none;">\n')
3636 lf = open(sysvals.dmesgfile, 'r') 3713 lf = open(sysvals.dmesgfile, 'r')
3637 for line in lf: 3714 for line in lf:
@@ -3640,7 +3717,7 @@ def createHTML(testruns):
3640 lf.close() 3717 lf.close()
3641 hf.write('</div>\n') 3718 hf.write('</div>\n')
3642 # add the ftrace log as a hidden div 3719 # add the ftrace log as a hidden div
3643 if sysvals.addlogs and sysvals.ftracefile: 3720 if sysvals.ftracelog and sysvals.ftracefile:
3644 hf.write('<div id="ftracelog" style="display:none;">\n') 3721 hf.write('<div id="ftracelog" style="display:none;">\n')
3645 lf = open(sysvals.ftracefile, 'r') 3722 lf = open(sysvals.ftracefile, 'r')
3646 for line in lf: 3723 for line in lf:
@@ -3701,6 +3778,7 @@ def addCSS(hf, sv, testcount=1, kerror=False, extra=''):
3701 <style type=\'text/css\'>\n\ 3778 <style type=\'text/css\'>\n\
3702 body {overflow-y:scroll;}\n\ 3779 body {overflow-y:scroll;}\n\
3703 .stamp {width:100%;text-align:center;background:gray;line-height:30px;color:white;font:25px Arial;}\n\ 3780 .stamp {width:100%;text-align:center;background:gray;line-height:30px;color:white;font:25px Arial;}\n\
3781 .stamp.sysinfo {font:10px Arial;}\n\
3704 .callgraph {margin-top:30px;box-shadow:5px 5px 20px black;}\n\ 3782 .callgraph {margin-top:30px;box-shadow:5px 5px 20px black;}\n\
3705 .callgraph article * {padding-left:28px;}\n\ 3783 .callgraph article * {padding-left:28px;}\n\
3706 h1 {color:black;font:bold 30px Times;}\n\ 3784 h1 {color:black;font:bold 30px Times;}\n\
@@ -3746,7 +3824,7 @@ def addCSS(hf, sv, testcount=1, kerror=False, extra=''):
3746 .legend {position:relative; width:100%; height:40px; text-align:center;margin-bottom:20px}\n\ 3824 .legend {position:relative; width:100%; height:40px; text-align:center;margin-bottom:20px}\n\
3747 .legend .square {position:absolute;cursor:pointer;top:10px; width:0px;height:20px;border:1px solid;padding-left:20px;}\n\ 3825 .legend .square {position:absolute;cursor:pointer;top:10px; width:0px;height:20px;border:1px solid;padding-left:20px;}\n\
3748 button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\ 3826 button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\
3749 .logbtn {position:relative;float:right;height:25px;width:50px;margin-top:3px;margin-bottom:0;font-size:10px;text-align:center;}\n\ 3827 .btnfmt {position:relative;float:right;height:25px;width:auto;margin-top:3px;margin-bottom:0;font-size:10px;text-align:center;}\n\
3750 .devlist {position:'+devlistpos+';width:190px;}\n\ 3828 .devlist {position:'+devlistpos+';width:190px;}\n\
3751 a:link {color:white;text-decoration:none;}\n\ 3829 a:link {color:white;text-decoration:none;}\n\
3752 a:visited {color:white;}\n\ 3830 a:visited {color:white;}\n\
@@ -4084,8 +4162,6 @@ def addScriptCode(hf, testruns):
4084 ' win.document.write(title+"<pre>"+log.innerHTML+"</pre>");\n'\ 4162 ' win.document.write(title+"<pre>"+log.innerHTML+"</pre>");\n'\
4085 ' win.document.close();\n'\ 4163 ' win.document.close();\n'\
4086 ' }\n'\ 4164 ' }\n'\
4087 ' function onClickPhase(e) {\n'\
4088 ' }\n'\
4089 ' function onMouseDown(e) {\n'\ 4165 ' function onMouseDown(e) {\n'\
4090 ' dragval[0] = e.clientX;\n'\ 4166 ' dragval[0] = e.clientX;\n'\
4091 ' dragval[1] = document.getElementById("dmesgzoombox").scrollLeft;\n'\ 4167 ' dragval[1] = document.getElementById("dmesgzoombox").scrollLeft;\n'\
@@ -4120,9 +4196,6 @@ def addScriptCode(hf, testruns):
4120 ' document.getElementById("zoomin").onclick = zoomTimeline;\n'\ 4196 ' document.getElementById("zoomin").onclick = zoomTimeline;\n'\
4121 ' document.getElementById("zoomout").onclick = zoomTimeline;\n'\ 4197 ' document.getElementById("zoomout").onclick = zoomTimeline;\n'\
4122 ' document.getElementById("zoomdef").onclick = zoomTimeline;\n'\ 4198 ' document.getElementById("zoomdef").onclick = zoomTimeline;\n'\
4123 ' var list = document.getElementsByClassName("square");\n'\
4124 ' for (var i = 0; i < list.length; i++)\n'\
4125 ' list[i].onclick = onClickPhase;\n'\
4126 ' var list = document.getElementsByClassName("err");\n'\ 4199 ' var list = document.getElementsByClassName("err");\n'\
4127 ' for (var i = 0; i < list.length; i++)\n'\ 4200 ' for (var i = 0; i < list.length; i++)\n'\
4128 ' list[i].onclick = errWindow;\n'\ 4201 ' list[i].onclick = errWindow;\n'\
@@ -4193,8 +4266,14 @@ def executeSuspend():
4193 if sysvals.testcommand != '': 4266 if sysvals.testcommand != '':
4194 call(sysvals.testcommand+' 2>&1', shell=True); 4267 call(sysvals.testcommand+' 2>&1', shell=True);
4195 else: 4268 else:
4269 mode = sysvals.suspendmode
4270 if sysvals.memmode and os.path.exists(sysvals.mempowerfile):
4271 mode = 'mem'
4272 pf = open(sysvals.mempowerfile, 'w')
4273 pf.write(sysvals.memmode)
4274 pf.close()
4196 pf = open(sysvals.powerfile, 'w') 4275 pf = open(sysvals.powerfile, 'w')
4197 pf.write(sysvals.suspendmode) 4276 pf.write(mode)
4198 # execution will pause here 4277 # execution will pause here
4199 try: 4278 try:
4200 pf.close() 4279 pf.close()
@@ -4219,24 +4298,15 @@ def executeSuspend():
4219 pm.stop() 4298 pm.stop()
4220 sysvals.fsetVal('0', 'tracing_on') 4299 sysvals.fsetVal('0', 'tracing_on')
4221 print('CAPTURING TRACE') 4300 print('CAPTURING TRACE')
4222 writeDatafileHeader(sysvals.ftracefile, fwdata) 4301 sysvals.writeDatafileHeader(sysvals.ftracefile, fwdata)
4223 call('cat '+tp+'trace >> '+sysvals.ftracefile, shell=True) 4302 call('cat '+tp+'trace >> '+sysvals.ftracefile, shell=True)
4224 sysvals.fsetVal('', 'trace') 4303 sysvals.fsetVal('', 'trace')
4225 devProps() 4304 devProps()
4226 # grab a copy of the dmesg output 4305 # grab a copy of the dmesg output
4227 print('CAPTURING DMESG') 4306 print('CAPTURING DMESG')
4228 writeDatafileHeader(sysvals.dmesgfile, fwdata) 4307 sysvals.writeDatafileHeader(sysvals.dmesgfile, fwdata)
4229 sysvals.getdmesg() 4308 sysvals.getdmesg()
4230 4309
4231def writeDatafileHeader(filename, fwdata):
4232 fp = open(filename, 'a')
4233 fp.write(sysvals.teststamp+'\n')
4234 if(sysvals.suspendmode == 'mem' or sysvals.suspendmode == 'command'):
4235 for fw in fwdata:
4236 if(fw):
4237 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1]))
4238 fp.close()
4239
4240# Function: setUSBDevicesAuto 4310# Function: setUSBDevicesAuto
4241# Description: 4311# Description:
4242# Set the autosuspend control parameter of all USB devices to auto 4312# Set the autosuspend control parameter of all USB devices to auto
@@ -4244,7 +4314,7 @@ def writeDatafileHeader(filename, fwdata):
4244# to always-on since the kernel cant determine if the device can 4314# to always-on since the kernel cant determine if the device can
4245# properly autosuspend 4315# properly autosuspend
4246def setUSBDevicesAuto(): 4316def setUSBDevicesAuto():
4247 rootCheck(True) 4317 sysvals.rootCheck(True)
4248 for dirname, dirnames, filenames in os.walk('/sys/devices'): 4318 for dirname, dirnames, filenames in os.walk('/sys/devices'):
4249 if(re.match('.*/usb[0-9]*.*', dirname) and 4319 if(re.match('.*/usb[0-9]*.*', dirname) and
4250 'idVendor' in filenames and 'idProduct' in filenames): 4320 'idVendor' in filenames and 'idProduct' in filenames):
@@ -4467,13 +4537,146 @@ def devProps(data=0):
4467# Output: 4537# Output:
4468# A string list of the available modes 4538# A string list of the available modes
4469def getModes(): 4539def getModes():
4470 modes = '' 4540 modes = []
4471 if(os.path.exists(sysvals.powerfile)): 4541 if(os.path.exists(sysvals.powerfile)):
4472 fp = open(sysvals.powerfile, 'r') 4542 fp = open(sysvals.powerfile, 'r')
4473 modes = string.split(fp.read()) 4543 modes = string.split(fp.read())
4474 fp.close() 4544 fp.close()
4545 if(os.path.exists(sysvals.mempowerfile)):
4546 deep = False
4547 fp = open(sysvals.mempowerfile, 'r')
4548 for m in string.split(fp.read()):
4549 memmode = m.strip('[]')
4550 if memmode == 'deep':
4551 deep = True
4552 else:
4553 modes.append('mem-%s' % memmode)
4554 fp.close()
4555 if 'mem' in modes and not deep:
4556 modes.remove('mem')
4475 return modes 4557 return modes
4476 4558
4559# Function: dmidecode
4560# Description:
4561# Read the bios tables and pull out system info
4562# Arguments:
4563# mempath: /dev/mem or custom mem path
4564# fatal: True to exit on error, False to return empty dict
4565# Output:
4566# A dict object with all available key/values
4567def dmidecode(mempath, fatal=False):
4568 out = dict()
4569
4570 # the list of values to retrieve, with hardcoded (type, idx)
4571 info = {
4572 'bios-vendor': (0, 4),
4573 'bios-version': (0, 5),
4574 'bios-release-date': (0, 8),
4575 'system-manufacturer': (1, 4),
4576 'system-product-name': (1, 5),
4577 'system-version': (1, 6),
4578 'system-serial-number': (1, 7),
4579 'baseboard-manufacturer': (2, 4),
4580 'baseboard-product-name': (2, 5),
4581 'baseboard-version': (2, 6),
4582 'baseboard-serial-number': (2, 7),
4583 'chassis-manufacturer': (3, 4),
4584 'chassis-type': (3, 5),
4585 'chassis-version': (3, 6),
4586 'chassis-serial-number': (3, 7),
4587 'processor-manufacturer': (4, 7),
4588 'processor-version': (4, 16),
4589 }
4590 if(not os.path.exists(mempath)):
4591 if(fatal):
4592 doError('file does not exist: %s' % mempath)
4593 return out
4594 if(not os.access(mempath, os.R_OK)):
4595 if(fatal):
4596 doError('file is not readable: %s' % mempath)
4597 return out
4598
4599 # by default use legacy scan, but try to use EFI first
4600 memaddr = 0xf0000
4601 memsize = 0x10000
4602 for ep in ['/sys/firmware/efi/systab', '/proc/efi/systab']:
4603 if not os.path.exists(ep) or not os.access(ep, os.R_OK):
4604 continue
4605 fp = open(ep, 'r')
4606 buf = fp.read()
4607 fp.close()
4608 i = buf.find('SMBIOS=')
4609 if i >= 0:
4610 try:
4611 memaddr = int(buf[i+7:], 16)
4612 memsize = 0x20
4613 except:
4614 continue
4615
4616 # read in the memory for scanning
4617 fp = open(mempath, 'rb')
4618 try:
4619 fp.seek(memaddr)
4620 buf = fp.read(memsize)
4621 except:
4622 if(fatal):
4623 doError('DMI table is unreachable, sorry')
4624 else:
4625 return out
4626 fp.close()
4627
4628 # search for either an SM table or DMI table
4629 i = base = length = num = 0
4630 while(i < memsize):
4631 if buf[i:i+4] == '_SM_' and i < memsize - 16:
4632 length = struct.unpack('H', buf[i+22:i+24])[0]
4633 base, num = struct.unpack('IH', buf[i+24:i+30])
4634 break
4635 elif buf[i:i+5] == '_DMI_':
4636 length = struct.unpack('H', buf[i+6:i+8])[0]
4637 base, num = struct.unpack('IH', buf[i+8:i+14])
4638 break
4639 i += 16
4640 if base == 0 and length == 0 and num == 0:
4641 if(fatal):
4642 doError('Neither SMBIOS nor DMI were found')
4643 else:
4644 return out
4645
4646 # read in the SM or DMI table
4647 fp = open(mempath, 'rb')
4648 try:
4649 fp.seek(base)
4650 buf = fp.read(length)
4651 except:
4652 if(fatal):
4653 doError('DMI table is unreachable, sorry')
4654 else:
4655 return out
4656 fp.close()
4657
4658 # scan the table for the values we want
4659 count = i = 0
4660 while(count < num and i <= len(buf) - 4):
4661 type, size, handle = struct.unpack('BBH', buf[i:i+4])
4662 n = i + size
4663 while n < len(buf) - 1:
4664 if 0 == struct.unpack('H', buf[n:n+2])[0]:
4665 break
4666 n += 1
4667 data = buf[i+size:n+2].split('\0')
4668 for name in info:
4669 itype, idxadr = info[name]
4670 if itype == type:
4671 idx = struct.unpack('B', buf[i+idxadr])[0]
4672 if idx > 0 and idx < len(data) - 1:
4673 s = data[idx-1].strip()
4674 if s and s.lower() != 'to be filled by o.e.m.':
4675 out[name] = data[idx-1]
4676 i = n + 2
4677 count += 1
4678 return out
4679
4477# Function: getFPDT 4680# Function: getFPDT
4478# Description: 4681# Description:
4479# Read the acpi bios tables and pull out FPDT, the firmware data 4682# Read the acpi bios tables and pull out FPDT, the firmware data
@@ -4487,7 +4690,7 @@ def getFPDT(output):
4487 prectype[0] = 'Basic S3 Resume Performance Record' 4690 prectype[0] = 'Basic S3 Resume Performance Record'
4488 prectype[1] = 'Basic S3 Suspend Performance Record' 4691 prectype[1] = 'Basic S3 Suspend Performance Record'
4489 4692
4490 rootCheck(True) 4693 sysvals.rootCheck(True)
4491 if(not os.path.exists(sysvals.fpdtpath)): 4694 if(not os.path.exists(sysvals.fpdtpath)):
4492 if(output): 4695 if(output):
4493 doError('file does not exist: %s' % sysvals.fpdtpath) 4696 doError('file does not exist: %s' % sysvals.fpdtpath)
@@ -4617,7 +4820,7 @@ def statusCheck(probecheck=False):
4617 4820
4618 # check we have root access 4821 # check we have root access
4619 res = sysvals.colorText('NO (No features of this tool will work!)') 4822 res = sysvals.colorText('NO (No features of this tool will work!)')
4620 if(rootCheck(False)): 4823 if(sysvals.rootCheck(False)):
4621 res = 'YES' 4824 res = 'YES'
4622 print(' have root access: %s' % res) 4825 print(' have root access: %s' % res)
4623 if(res != 'YES'): 4826 if(res != 'YES'):
@@ -4716,16 +4919,6 @@ def doError(msg, help=False):
4716 print('ERROR: %s\n') % msg 4919 print('ERROR: %s\n') % msg
4717 sys.exit() 4920 sys.exit()
4718 4921
4719# Function: rootCheck
4720# Description:
4721# quick check to see if we have root access
4722def rootCheck(fatal):
4723 if(os.access(sysvals.powerfile, os.W_OK)):
4724 return True
4725 if fatal:
4726 doError('This command requires sysfs mount and root access')
4727 return False
4728
4729# Function: getArgInt 4922# Function: getArgInt
4730# Description: 4923# Description:
4731# pull out an integer argument from the command line with checks 4924# pull out an integer argument from the command line with checks
@@ -4779,6 +4972,7 @@ def processData():
4779 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)): 4972 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)):
4780 appendIncompleteTraceLog(testruns) 4973 appendIncompleteTraceLog(testruns)
4781 createHTML(testruns) 4974 createHTML(testruns)
4975 return testruns
4782 4976
4783# Function: rerunTest 4977# Function: rerunTest
4784# Description: 4978# Description:
@@ -4790,17 +4984,20 @@ def rerunTest():
4790 doError('recreating this html output requires a dmesg file') 4984 doError('recreating this html output requires a dmesg file')
4791 sysvals.setOutputFile() 4985 sysvals.setOutputFile()
4792 vprint('Output file: %s' % sysvals.htmlfile) 4986 vprint('Output file: %s' % sysvals.htmlfile)
4793 if(os.path.exists(sysvals.htmlfile) and not os.access(sysvals.htmlfile, os.W_OK)): 4987 if os.path.exists(sysvals.htmlfile):
4794 doError('missing permission to write to %s' % sysvals.htmlfile) 4988 if not os.path.isfile(sysvals.htmlfile):
4795 processData() 4989 doError('a directory already exists with this name: %s' % sysvals.htmlfile)
4990 elif not os.access(sysvals.htmlfile, os.W_OK):
4991 doError('missing permission to write to %s' % sysvals.htmlfile)
4992 return processData()
4796 4993
4797# Function: runTest 4994# Function: runTest
4798# Description: 4995# Description:
4799# execute a suspend/resume, gather the logs, and generate the output 4996# execute a suspend/resume, gather the logs, and generate the output
4800def runTest(subdir, testpath=''): 4997def runTest():
4801 # prepare for the test 4998 # prepare for the test
4802 sysvals.initFtrace() 4999 sysvals.initFtrace()
4803 sysvals.initTestOutput(subdir, testpath) 5000 sysvals.initTestOutput('suspend')
4804 vprint('Output files:\n\t%s\n\t%s\n\t%s' % \ 5001 vprint('Output files:\n\t%s\n\t%s\n\t%s' % \
4805 (sysvals.dmesgfile, sysvals.ftracefile, sysvals.htmlfile)) 5002 (sysvals.dmesgfile, sysvals.ftracefile, sysvals.htmlfile))
4806 5003
@@ -4897,7 +5094,7 @@ def configFromFile(file):
4897 if(opt.lower() == 'verbose'): 5094 if(opt.lower() == 'verbose'):
4898 sysvals.verbose = checkArgBool(value) 5095 sysvals.verbose = checkArgBool(value)
4899 elif(opt.lower() == 'addlogs'): 5096 elif(opt.lower() == 'addlogs'):
4900 sysvals.addlogs = checkArgBool(value) 5097 sysvals.dmesglog = sysvals.ftracelog = checkArgBool(value)
4901 elif(opt.lower() == 'dev'): 5098 elif(opt.lower() == 'dev'):
4902 sysvals.usedevsrc = checkArgBool(value) 5099 sysvals.usedevsrc = checkArgBool(value)
4903 elif(opt.lower() == 'proc'): 5100 elif(opt.lower() == 'proc'):
@@ -4947,7 +5144,7 @@ def configFromFile(file):
4947 elif(opt.lower() == 'mincg'): 5144 elif(opt.lower() == 'mincg'):
4948 sysvals.mincglen = getArgFloat('-mincg', value, 0.0, 10000.0, False) 5145 sysvals.mincglen = getArgFloat('-mincg', value, 0.0, 10000.0, False)
4949 elif(opt.lower() == 'output-dir'): 5146 elif(opt.lower() == 'output-dir'):
4950 sysvals.setOutputFolder(value) 5147 sysvals.testdir = sysvals.setOutputFolder(value)
4951 5148
4952 if sysvals.suspendmode == 'command' and not sysvals.testcommand: 5149 if sysvals.suspendmode == 'command' and not sysvals.testcommand:
4953 doError('No command supplied for mode "command"') 5150 doError('No command supplied for mode "command"')
@@ -5030,8 +5227,6 @@ def configFromFile(file):
5030# Description: 5227# Description:
5031# print out the help text 5228# print out the help text
5032def printHelp(): 5229def printHelp():
5033 modes = getModes()
5034
5035 print('') 5230 print('')
5036 print('%s v%s' % (sysvals.title, sysvals.version)) 5231 print('%s v%s' % (sysvals.title, sysvals.version))
5037 print('Usage: sudo sleepgraph <options> <commands>') 5232 print('Usage: sudo sleepgraph <options> <commands>')
@@ -5048,7 +5243,7 @@ def printHelp():
5048 print(' If no specific command is given, the default behavior is to initiate') 5243 print(' If no specific command is given, the default behavior is to initiate')
5049 print(' a suspend/resume and capture the dmesg/ftrace output as an html timeline.') 5244 print(' a suspend/resume and capture the dmesg/ftrace output as an html timeline.')
5050 print('') 5245 print('')
5051 print(' Generates output files in subdirectory: suspend-mmddyy-HHMMSS') 5246 print(' Generates output files in subdirectory: suspend-yymmdd-HHMMSS')
5052 print(' HTML output: <hostname>_<mode>.html') 5247 print(' HTML output: <hostname>_<mode>.html')
5053 print(' raw dmesg output: <hostname>_<mode>_dmesg.txt') 5248 print(' raw dmesg output: <hostname>_<mode>_dmesg.txt')
5054 print(' raw ftrace output: <hostname>_<mode>_ftrace.txt') 5249 print(' raw ftrace output: <hostname>_<mode>_ftrace.txt')
@@ -5058,8 +5253,9 @@ def printHelp():
5058 print(' -v Print the current tool version') 5253 print(' -v Print the current tool version')
5059 print(' -config fn Pull arguments and config options from file fn') 5254 print(' -config fn Pull arguments and config options from file fn')
5060 print(' -verbose Print extra information during execution and analysis') 5255 print(' -verbose Print extra information during execution and analysis')
5061 print(' -m mode Mode to initiate for suspend %s (default: %s)') % (modes, sysvals.suspendmode) 5256 print(' -m mode Mode to initiate for suspend (default: %s)') % (sysvals.suspendmode)
5062 print(' -o subdir Override the output subdirectory') 5257 print(' -o name Overrides the output subdirectory name when running a new test')
5258 print(' default: suspend-{date}-{time}')
5063 print(' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)') 5259 print(' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)')
5064 print(' -addlogs Add the dmesg and ftrace logs to the html output') 5260 print(' -addlogs Add the dmesg and ftrace logs to the html output')
5065 print(' -srgap Add a visible gap in the timeline between sus/res (default: disabled)') 5261 print(' -srgap Add a visible gap in the timeline between sus/res (default: disabled)')
@@ -5084,17 +5280,20 @@ def printHelp():
5084 print(' -cgphase P Only show callgraph data for phase P (e.g. suspend_late)') 5280 print(' -cgphase P Only show callgraph data for phase P (e.g. suspend_late)')
5085 print(' -cgtest N Only show callgraph data for test N (e.g. 0 or 1 in an x2 run)') 5281 print(' -cgtest N Only show callgraph data for test N (e.g. 0 or 1 in an x2 run)')
5086 print(' -timeprec N Number of significant digits in timestamps (0:S, [3:ms], 6:us)') 5282 print(' -timeprec N Number of significant digits in timestamps (0:S, [3:ms], 6:us)')
5087 print(' [commands]') 5283 print('')
5088 print(' -ftrace ftracefile Create HTML output using ftrace input (used with -dmesg)') 5284 print('Other commands:')
5089 print(' -dmesg dmesgfile Create HTML output using dmesg (used with -ftrace)')
5090 print(' -summary directory Create a summary of all test in this dir')
5091 print(' -modes List available suspend modes') 5285 print(' -modes List available suspend modes')
5092 print(' -status Test to see if the system is enabled to run this tool') 5286 print(' -status Test to see if the system is enabled to run this tool')
5093 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table') 5287 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table')
5288 print(' -sysinfo Print out system info extracted from BIOS')
5094 print(' -usbtopo Print out the current USB topology with power info') 5289 print(' -usbtopo Print out the current USB topology with power info')
5095 print(' -usbauto Enable autosuspend for all connected USB devices') 5290 print(' -usbauto Enable autosuspend for all connected USB devices')
5096 print(' -flist Print the list of functions currently being captured in ftrace') 5291 print(' -flist Print the list of functions currently being captured in ftrace')
5097 print(' -flistall Print all functions capable of being captured in ftrace') 5292 print(' -flistall Print all functions capable of being captured in ftrace')
5293 print(' -summary directory Create a summary of all test in this dir')
5294 print(' [redo]')
5295 print(' -ftrace ftracefile Create HTML output using ftrace input (used with -dmesg)')
5296 print(' -dmesg dmesgfile Create HTML output using dmesg (used with -ftrace)')
5098 print('') 5297 print('')
5099 return True 5298 return True
5100 5299
@@ -5102,9 +5301,9 @@ def printHelp():
5102# exec start (skipped if script is loaded as library) 5301# exec start (skipped if script is loaded as library)
5103if __name__ == '__main__': 5302if __name__ == '__main__':
5104 cmd = '' 5303 cmd = ''
5105 cmdarg = '' 5304 outdir = ''
5106 multitest = {'run': False, 'count': 0, 'delay': 0} 5305 multitest = {'run': False, 'count': 0, 'delay': 0}
5107 simplecmds = ['-modes', '-fpdt', '-flist', '-flistall', '-usbtopo', '-usbauto', '-status'] 5306 simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall', '-usbtopo', '-usbauto', '-status']
5108 # loop through the command line arguments 5307 # loop through the command line arguments
5109 args = iter(sys.argv[1:]) 5308 args = iter(sys.argv[1:])
5110 for arg in args: 5309 for arg in args:
@@ -5135,7 +5334,7 @@ if __name__ == '__main__':
5135 elif(arg == '-f'): 5334 elif(arg == '-f'):
5136 sysvals.usecallgraph = True 5335 sysvals.usecallgraph = True
5137 elif(arg == '-addlogs'): 5336 elif(arg == '-addlogs'):
5138 sysvals.addlogs = True 5337 sysvals.dmesglog = sysvals.ftracelog = True
5139 elif(arg == '-verbose'): 5338 elif(arg == '-verbose'):
5140 sysvals.verbose = True 5339 sysvals.verbose = True
5141 elif(arg == '-proc'): 5340 elif(arg == '-proc'):
@@ -5195,7 +5394,7 @@ if __name__ == '__main__':
5195 val = args.next() 5394 val = args.next()
5196 except: 5395 except:
5197 doError('No subdirectory name supplied', True) 5396 doError('No subdirectory name supplied', True)
5198 sysvals.setOutputFolder(val) 5397 outdir = sysvals.setOutputFolder(val)
5199 elif(arg == '-config'): 5398 elif(arg == '-config'):
5200 try: 5399 try:
5201 val = args.next() 5400 val = args.next()
@@ -5236,7 +5435,7 @@ if __name__ == '__main__':
5236 except: 5435 except:
5237 doError('No directory supplied', True) 5436 doError('No directory supplied', True)
5238 cmd = 'summary' 5437 cmd = 'summary'
5239 cmdarg = val 5438 outdir = val
5240 sysvals.notestrun = True 5439 sysvals.notestrun = True
5241 if(os.path.isdir(val) == False): 5440 if(os.path.isdir(val) == False):
5242 doError('%s is not accesible' % val) 5441 doError('%s is not accesible' % val)
@@ -5260,11 +5459,14 @@ if __name__ == '__main__':
5260 sysvals.mincglen = sysvals.mindevlen 5459 sysvals.mincglen = sysvals.mindevlen
5261 5460
5262 # just run a utility command and exit 5461 # just run a utility command and exit
5462 sysvals.cpuInfo()
5263 if(cmd != ''): 5463 if(cmd != ''):
5264 if(cmd == 'status'): 5464 if(cmd == 'status'):
5265 statusCheck(True) 5465 statusCheck(True)
5266 elif(cmd == 'fpdt'): 5466 elif(cmd == 'fpdt'):
5267 getFPDT(True) 5467 getFPDT(True)
5468 elif(cmd == 'sysinfo'):
5469 sysvals.printSystemInfo()
5268 elif(cmd == 'usbtopo'): 5470 elif(cmd == 'usbtopo'):
5269 detectUSB() 5471 detectUSB()
5270 elif(cmd == 'modes'): 5472 elif(cmd == 'modes'):
@@ -5276,7 +5478,7 @@ if __name__ == '__main__':
5276 elif(cmd == 'usbauto'): 5478 elif(cmd == 'usbauto'):
5277 setUSBDevicesAuto() 5479 setUSBDevicesAuto()
5278 elif(cmd == 'summary'): 5480 elif(cmd == 'summary'):
5279 runSummary(cmdarg, True) 5481 runSummary(outdir, True)
5280 sys.exit() 5482 sys.exit()
5281 5483
5282 # if instructed, re-analyze existing data files 5484 # if instructed, re-analyze existing data files
@@ -5289,21 +5491,43 @@ if __name__ == '__main__':
5289 print('Check FAILED, aborting the test run!') 5491 print('Check FAILED, aborting the test run!')
5290 sys.exit() 5492 sys.exit()
5291 5493
5494 # extract mem modes and convert
5495 mode = sysvals.suspendmode
5496 if 'mem' == mode[:3]:
5497 if '-' in mode:
5498 memmode = mode.split('-')[-1]
5499 else:
5500 memmode = 'deep'
5501 if memmode == 'shallow':
5502 mode = 'standby'
5503 elif memmode == 's2idle':
5504 mode = 'freeze'
5505 else:
5506 mode = 'mem'
5507 sysvals.memmode = memmode
5508 sysvals.suspendmode = mode
5509
5510 sysvals.systemInfo(dmidecode(sysvals.mempath))
5511
5292 if multitest['run']: 5512 if multitest['run']:
5293 # run multiple tests in a separate subdirectory 5513 # run multiple tests in a separate subdirectory
5294 s = 'x%d' % multitest['count'] 5514 if not outdir:
5295 if not sysvals.outdir: 5515 s = 'suspend-x%d' % multitest['count']
5296 sysvals.outdir = datetime.now().strftime('suspend-'+s+'-%m%d%y-%H%M%S') 5516 outdir = datetime.now().strftime(s+'-%y%m%d-%H%M%S')
5297 if not os.path.isdir(sysvals.outdir): 5517 if not os.path.isdir(outdir):
5298 os.mkdir(sysvals.outdir) 5518 os.mkdir(outdir)
5299 for i in range(multitest['count']): 5519 for i in range(multitest['count']):
5300 if(i != 0): 5520 if(i != 0):
5301 print('Waiting %d seconds...' % (multitest['delay'])) 5521 print('Waiting %d seconds...' % (multitest['delay']))
5302 time.sleep(multitest['delay']) 5522 time.sleep(multitest['delay'])
5303 print('TEST (%d/%d) START' % (i+1, multitest['count'])) 5523 print('TEST (%d/%d) START' % (i+1, multitest['count']))
5304 runTest(sysvals.outdir) 5524 fmt = 'suspend-%y%m%d-%H%M%S'
5525 sysvals.testdir = os.path.join(outdir, datetime.now().strftime(fmt))
5526 runTest()
5305 print('TEST (%d/%d) COMPLETE' % (i+1, multitest['count'])) 5527 print('TEST (%d/%d) COMPLETE' % (i+1, multitest['count']))
5306 runSummary(sysvals.outdir, False) 5528 runSummary(outdir, False)
5307 else: 5529 else:
5530 if outdir:
5531 sysvals.testdir = outdir
5308 # run the test in the current directory 5532 # run the test in the current directory
5309 runTest('.', sysvals.outdir) 5533 runTest()
diff --git a/tools/power/pm-graph/bootgraph.8 b/tools/power/pm-graph/bootgraph.8
index 55272a67b0e7..dbdafcf546df 100644
--- a/tools/power/pm-graph/bootgraph.8
+++ b/tools/power/pm-graph/bootgraph.8
@@ -8,14 +8,23 @@ bootgraph \- Kernel boot timing analysis
8.RB [ COMMAND ] 8.RB [ COMMAND ]
9.SH DESCRIPTION 9.SH DESCRIPTION
10\fBbootgraph \fP reads the dmesg log from kernel boot and 10\fBbootgraph \fP reads the dmesg log from kernel boot and
11creates an html representation of the initcall timeline up to the start 11creates an html representation of the initcall timeline. It graphs
12of the init process. 12every module init call found, through both kernel and user modes. The
13timeline is split into two phases: kernel mode & user mode. kernel mode
14represents a single process run on a single cpu with serial init calls.
15Once user mode begins, the init process is called, and the init calls
16start working in parallel.
13.PP 17.PP
14If no specific command is given, the tool reads the current dmesg log and 18If no specific command is given, the tool reads the current dmesg log and
15outputs bootgraph.html. 19outputs a new timeline.
16.PP 20.PP
17The tool can also augment the timeline with ftrace data on custom target 21The tool can also augment the timeline with ftrace data on custom target
18functions as well as full trace callgraphs. 22functions as well as full trace callgraphs.
23.PP
24Generates output files in subdirectory: boot-yymmdd-HHMMSS
25 html timeline : <hostname>_boot.html
26 raw dmesg file : <hostname>_boot_dmesg.txt
27 raw ftrace file : <hostname>_boot_ftrace.txt
19.SH OPTIONS 28.SH OPTIONS
20.TP 29.TP
21\fB-h\fR 30\fB-h\fR
@@ -28,15 +37,18 @@ Print the current tool version
28Add the dmesg log to the html output. It will be viewable by 37Add the dmesg log to the html output. It will be viewable by
29clicking a button in the timeline. 38clicking a button in the timeline.
30.TP 39.TP
31\fB-o \fIfile\fR 40\fB-o \fIname\fR
32Override the HTML output filename (default: bootgraph.html) 41Overrides the output subdirectory name when running a new test.
33.SS "Ftrace Debug" 42Use {date}, {time}, {hostname} for current values.
43.sp
44e.g. boot-{hostname}-{date}-{time}
45.SS "advanced"
34.TP 46.TP
35\fB-f\fR 47\fB-f\fR
36Use ftrace to add function detail (default: disabled) 48Use ftrace to add function detail (default: disabled)
37.TP 49.TP
38\fB-callgraph\fR 50\fB-callgraph\fR
39Use ftrace to create initcall callgraphs (default: disabled). If -filter 51Use ftrace to create initcall callgraphs (default: disabled). If -func
40is not used there will be one callgraph per initcall. This can produce 52is not used there will be one callgraph per initcall. This can produce
41very large outputs, i.e. 10MB - 100MB. 53very large outputs, i.e. 10MB - 100MB.
42.TP 54.TP
@@ -50,16 +62,19 @@ This reduces the html file size as there can be many tiny callgraphs
50which are barely visible in the timeline. 62which are barely visible in the timeline.
51The value is a float: e.g. 0.001 represents 1 us. 63The value is a float: e.g. 0.001 represents 1 us.
52.TP 64.TP
65\fB-cgfilter \fI"func1,func2,..."\fR
66Reduce callgraph output in the timeline by limiting it to a list of calls. The
67argument can be a single function name or a comma delimited list.
68(default: none)
69.TP
53\fB-timeprec \fIn\fR 70\fB-timeprec \fIn\fR
54Number of significant digits in timestamps (0:S, 3:ms, [6:us]) 71Number of significant digits in timestamps (0:S, 3:ms, [6:us])
55.TP 72.TP
56\fB-expandcg\fR 73\fB-expandcg\fR
57pre-expand the callgraph data in the html output (default: disabled) 74pre-expand the callgraph data in the html output (default: disabled)
58.TP 75.TP
59\fB-filter \fI"func1,func2,..."\fR 76\fB-func \fI"func1,func2,..."\fR
60Instead of tracing each initcall, trace a custom list of functions (default: do_one_initcall) 77Instead of tracing each initcall, trace a custom list of functions (default: do_one_initcall)
61
62.SH COMMANDS
63.TP 78.TP
64\fB-reboot\fR 79\fB-reboot\fR
65Reboot the machine and generate a new timeline automatically. Works in 4 steps. 80Reboot the machine and generate a new timeline automatically. Works in 4 steps.
@@ -73,16 +88,23 @@ Show the requirements to generate a new timeline manually. Requires 3 steps.
73 1. append the string to the kernel command line via your native boot manager. 88 1. append the string to the kernel command line via your native boot manager.
74 2. reboot the system 89 2. reboot the system
75 3. after startup, re-run the tool with the same arguments and no command 90 3. after startup, re-run the tool with the same arguments and no command
91
92.SH COMMANDS
93.SS "rebuild"
76.TP 94.TP
77\fB-dmesg \fIfile\fR 95\fB-dmesg \fIfile\fR
78Create HTML output from an existing dmesg file. 96Create HTML output from an existing dmesg file.
79.TP 97.TP
80\fB-ftrace \fIfile\fR 98\fB-ftrace \fIfile\fR
81Create HTML output from an existing ftrace file (used with -dmesg). 99Create HTML output from an existing ftrace file (used with -dmesg).
100.SS "other"
82.TP 101.TP
83\fB-flistall\fR 102\fB-flistall\fR
84Print all ftrace functions capable of being captured. These are all the 103Print all ftrace functions capable of being captured. These are all the
85possible values you can add to trace via the -filter argument. 104possible values you can add to trace via the -func argument.
105.TP
106\fB-sysinfo\fR
107Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode.
86 108
87.SH EXAMPLES 109.SH EXAMPLES
88Create a timeline using the current dmesg log. 110Create a timeline using the current dmesg log.
@@ -93,13 +115,13 @@ Create a timeline using the current dmesg and ftrace log.
93.IP 115.IP
94\f(CW$ bootgraph -callgraph\fR 116\f(CW$ bootgraph -callgraph\fR
95.PP 117.PP
96Create a timeline using the current dmesg, add the log to the html and change the name. 118Create a timeline using the current dmesg, add the log to the html and change the folder.
97.IP 119.IP
98\f(CW$ bootgraph -addlogs -o myboot.html\fR 120\f(CW$ bootgraph -addlogs -o "myboot-{date}-{time}"\fR
99.PP 121.PP
100Capture a new boot timeline by automatically rebooting the machine. 122Capture a new boot timeline by automatically rebooting the machine.
101.IP 123.IP
102\f(CW$ sudo bootgraph -reboot -addlogs -o latestboot.html\fR 124\f(CW$ sudo bootgraph -reboot -addlogs -o "latest-{hostname)"\fR
103.PP 125.PP
104Capture a new boot timeline with function trace data. 126Capture a new boot timeline with function trace data.
105.IP 127.IP
@@ -111,7 +133,7 @@ Capture a new boot timeline with trace & callgraph data. Skip callgraphs smaller
111.PP 133.PP
112Capture a new boot timeline with callgraph data over custom functions. 134Capture a new boot timeline with callgraph data over custom functions.
113.IP 135.IP
114\f(CW$ sudo bootgraph -reboot -callgraph -filter "acpi_ps_parse_aml,msleep"\fR 136\f(CW$ sudo bootgraph -reboot -callgraph -func "acpi_ps_parse_aml,msleep"\fR
115.PP 137.PP
116Capture a brand new boot timeline with manual reboot. 138Capture a brand new boot timeline with manual reboot.
117.IP 139.IP
@@ -123,6 +145,15 @@ Capture a brand new boot timeline with manual reboot.
123.IP 145.IP
124\f(CW$ sudo bootgraph -callgraph # re-run the tool after restart\fR 146\f(CW$ sudo bootgraph -callgraph # re-run the tool after restart\fR
125.PP 147.PP
148.SS "rebuild timeline from logs"
149.PP
150Rebuild the html from a previous run's logs, using the same options.
151.IP
152\f(CW$ bootgraph -dmesg dmesg.txt -ftrace ftrace.txt -callgraph\fR
153.PP
154Rebuild the html with different options.
155.IP
156\f(CW$ bootgraph -dmesg dmesg.txt -ftrace ftrace.txt -addlogs\fR
126 157
127.SH "SEE ALSO" 158.SH "SEE ALSO"
128dmesg(1), update-grub(8), crontab(1), reboot(8) 159dmesg(1), update-grub(8), crontab(1), reboot(8)
diff --git a/tools/power/pm-graph/sleepgraph.8 b/tools/power/pm-graph/sleepgraph.8
index 610e72ebbc06..fbe7bd3eae8e 100644
--- a/tools/power/pm-graph/sleepgraph.8
+++ b/tools/power/pm-graph/sleepgraph.8
@@ -39,8 +39,9 @@ Pull arguments and config options from a file.
39\fB-m \fImode\fR 39\fB-m \fImode\fR
40Mode to initiate for suspend e.g. standby, freeze, mem (default: mem). 40Mode to initiate for suspend e.g. standby, freeze, mem (default: mem).
41.TP 41.TP
42\fB-o \fIsubdir\fR 42\fB-o \fIname\fR
43Override the output subdirectory. Use {date}, {time}, {hostname} for current values. 43Overrides the output subdirectory name when running a new test.
44Use {date}, {time}, {hostname} for current values.
44.sp 45.sp
45e.g. suspend-{hostname}-{date}-{time} 46e.g. suspend-{hostname}-{date}-{time}
46.TP 47.TP
@@ -52,7 +53,7 @@ disable rtcwake and require a user keypress to resume.
52Add the dmesg and ftrace logs to the html output. They will be viewable by 53Add the dmesg and ftrace logs to the html output. They will be viewable by
53clicking buttons in the timeline. 54clicking buttons in the timeline.
54 55
55.SS "Advanced" 56.SS "advanced"
56.TP 57.TP
57\fB-cmd \fIstr\fR 58\fB-cmd \fIstr\fR
58Run the timeline over a custom suspend command, e.g. pm-suspend. By default 59Run the timeline over a custom suspend command, e.g. pm-suspend. By default
@@ -91,7 +92,7 @@ Include \fIt\fR ms delay after last resume (default: 0 ms).
91Execute \fIn\fR consecutive tests at \fId\fR seconds intervals. The outputs will 92Execute \fIn\fR consecutive tests at \fId\fR seconds intervals. The outputs will
92be created in a new subdirectory with a summary page: suspend-xN-{date}-{time}. 93be created in a new subdirectory with a summary page: suspend-xN-{date}-{time}.
93 94
94.SS "Ftrace Debug" 95.SS "ftrace debug"
95.TP 96.TP
96\fB-f\fR 97\fB-f\fR
97Use ftrace to create device callgraphs (default: disabled). This can produce 98Use ftrace to create device callgraphs (default: disabled). This can produce
@@ -124,12 +125,6 @@ Number of significant digits in timestamps (0:S, [3:ms], 6:us).
124 125
125.SH COMMANDS 126.SH COMMANDS
126.TP 127.TP
127\fB-ftrace \fIfile\fR
128Create HTML output from an existing ftrace file.
129.TP
130\fB-dmesg \fIfile\fR
131Create HTML output from an existing dmesg file.
132.TP
133\fB-summary \fIindir\fR 128\fB-summary \fIindir\fR
134Create a summary page of all tests in \fIindir\fR. Creates summary.html 129Create a summary page of all tests in \fIindir\fR. Creates summary.html
135in the current folder. The output page is a table of tests with 130in the current folder. The output page is a table of tests with
@@ -146,6 +141,9 @@ with any options you intend to use to see if they will work.
146\fB-fpdt\fR 141\fB-fpdt\fR
147Print out the contents of the ACPI Firmware Performance Data Table. 142Print out the contents of the ACPI Firmware Performance Data Table.
148.TP 143.TP
144\fB-sysinfo\fR
145Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode.
146.TP
149\fB-usbtopo\fR 147\fB-usbtopo\fR
150Print out the current USB topology with power info. 148Print out the current USB topology with power info.
151.TP 149.TP
@@ -162,9 +160,16 @@ with -fadd they will also be checked.
162\fB-flistall\fR 160\fB-flistall\fR
163Print all ftrace functions capable of being captured. These are all the 161Print all ftrace functions capable of being captured. These are all the
164possible values you can add to trace via the -fadd argument. 162possible values you can add to trace via the -fadd argument.
163.SS "rebuild"
164.TP
165\fB-ftrace \fIfile\fR
166Create HTML output from an existing ftrace file.
167.TP
168\fB-dmesg \fIfile\fR
169Create HTML output from an existing dmesg file.
165 170
166.SH EXAMPLES 171.SH EXAMPLES
167.SS "Simple Commands" 172.SS "simple commands"
168Check which suspend modes are currently supported. 173Check which suspend modes are currently supported.
169.IP 174.IP
170\f(CW$ sleepgraph -modes\fR 175\f(CW$ sleepgraph -modes\fR
@@ -185,12 +190,8 @@ Generate a summary of all timelines in a particular folder.
185.IP 190.IP
186\f(CW$ sleepgraph -summary ~/workspace/myresults/\fR 191\f(CW$ sleepgraph -summary ~/workspace/myresults/\fR
187.PP 192.PP
188Re-generate the html output from a previous run's dmesg and ftrace log.
189.IP
190\f(CW$ sleepgraph -dmesg myhost_mem_dmesg.txt -ftrace myhost_mem_ftrace.txt\fR
191.PP
192 193
193.SS "Capturing Simple Timelines" 194.SS "capturing basic timelines"
194Execute a mem suspend with a 15 second wakeup. Include the logs in the html. 195Execute a mem suspend with a 15 second wakeup. Include the logs in the html.
195.IP 196.IP
196\f(CW$ sudo sleepgraph -rtcwake 15 -addlogs\fR 197\f(CW$ sudo sleepgraph -rtcwake 15 -addlogs\fR
@@ -204,7 +205,7 @@ Execute a freeze with no wakeup (require keypress). Change output folder name.
204\f(CW$ sudo sleepgraph -m freeze -rtcwake off -o "freeze-{hostname}-{date}-{time}"\fR 205\f(CW$ sudo sleepgraph -m freeze -rtcwake off -o "freeze-{hostname}-{date}-{time}"\fR
205.PP 206.PP
206 207
207.SS "Capturing Advanced Timelines" 208.SS "capturing advanced timelines"
208Execute a suspend & include dev mode source calls, limit callbacks to 5ms or larger. 209Execute a suspend & include dev mode source calls, limit callbacks to 5ms or larger.
209.IP 210.IP
210\f(CW$ sudo sleepgraph -m mem -rtcwake 15 -dev -mindev 5\fR 211\f(CW$ sudo sleepgraph -m mem -rtcwake 15 -dev -mindev 5\fR
@@ -222,8 +223,7 @@ Execute a suspend using a custom command.
222\f(CW$ sudo sleepgraph -cmd "echo mem > /sys/power/state" -rtcwake 15\fR 223\f(CW$ sudo sleepgraph -cmd "echo mem > /sys/power/state" -rtcwake 15\fR
223.PP 224.PP
224 225
225 226.SS "adding callgraph data"
226.SS "Capturing Timelines with Callgraph Data"
227Add device callgraphs. Limit the trace depth and only show callgraphs 10ms or larger. 227Add device callgraphs. Limit the trace depth and only show callgraphs 10ms or larger.
228.IP 228.IP
229\f(CW$ sudo sleepgraph -m mem -rtcwake 15 -f -maxdepth 5 -mincg 10\fR 229\f(CW$ sudo sleepgraph -m mem -rtcwake 15 -f -maxdepth 5 -mincg 10\fR
@@ -235,6 +235,16 @@ Capture a full callgraph across all suspend, then filter the html by a single ph
235\f(CW$ sleepgraph -dmesg host_mem_dmesg.txt -ftrace host_mem_ftrace.txt -f -cgphase resume 235\f(CW$ sleepgraph -dmesg host_mem_dmesg.txt -ftrace host_mem_ftrace.txt -f -cgphase resume
236.PP 236.PP
237 237
238.SS "rebuild timeline from logs"
239.PP
240Rebuild the html from a previous run's logs, using the same options.
241.IP
242\f(CW$ sleepgraph -dmesg dmesg.txt -ftrace ftrace.txt -callgraph\fR
243.PP
244Rebuild the html with different options.
245.IP
246\f(CW$ sleepgraph -dmesg dmesg.txt -ftrace ftrace.txt -addlogs -srgap\fR
247
238.SH "SEE ALSO" 248.SH "SEE ALSO"
239dmesg(1) 249dmesg(1)
240.PP 250.PP
diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile
index 8792ad8dbf83..a9bc914a8fe8 100644
--- a/tools/power/x86/turbostat/Makefile
+++ b/tools/power/x86/turbostat/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1CC = $(CROSS_COMPILE)gcc 2CC = $(CROSS_COMPILE)gcc
2BUILD_OUTPUT := $(CURDIR) 3BUILD_OUTPUT := $(CURDIR)
3PREFIX ?= /usr 4PREFIX ?= /usr
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 0dafba2c1e7d..bd9c6b31a504 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -92,7 +92,6 @@ unsigned int do_ring_perf_limit_reasons;
92unsigned int crystal_hz; 92unsigned int crystal_hz;
93unsigned long long tsc_hz; 93unsigned long long tsc_hz;
94int base_cpu; 94int base_cpu;
95int do_migrate;
96double discover_bclk(unsigned int family, unsigned int model); 95double discover_bclk(unsigned int family, unsigned int model);
97unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */ 96unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
98 /* IA32_HWP_REQUEST, IA32_HWP_STATUS */ 97 /* IA32_HWP_REQUEST, IA32_HWP_STATUS */
@@ -303,9 +302,6 @@ int for_all_cpus(int (func)(struct thread_data *, struct core_data *, struct pkg
303 302
304int cpu_migrate(int cpu) 303int cpu_migrate(int cpu)
305{ 304{
306 if (!do_migrate)
307 return 0;
308
309 CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); 305 CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);
310 CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set); 306 CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set);
311 if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1) 307 if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1)
@@ -5007,7 +5003,6 @@ void cmdline(int argc, char **argv)
5007 {"hide", required_argument, 0, 'H'}, // meh, -h taken by --help 5003 {"hide", required_argument, 0, 'H'}, // meh, -h taken by --help
5008 {"Joules", no_argument, 0, 'J'}, 5004 {"Joules", no_argument, 0, 'J'},
5009 {"list", no_argument, 0, 'l'}, 5005 {"list", no_argument, 0, 'l'},
5010 {"migrate", no_argument, 0, 'm'},
5011 {"out", required_argument, 0, 'o'}, 5006 {"out", required_argument, 0, 'o'},
5012 {"quiet", no_argument, 0, 'q'}, 5007 {"quiet", no_argument, 0, 'q'},
5013 {"show", required_argument, 0, 's'}, 5008 {"show", required_argument, 0, 's'},
@@ -5019,7 +5014,7 @@ void cmdline(int argc, char **argv)
5019 5014
5020 progname = argv[0]; 5015 progname = argv[0];
5021 5016
5022 while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:Jmo:qST:v", 5017 while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:o:qST:v",
5023 long_options, &option_index)) != -1) { 5018 long_options, &option_index)) != -1) {
5024 switch (opt) { 5019 switch (opt) {
5025 case 'a': 5020 case 'a':
@@ -5062,9 +5057,6 @@ void cmdline(int argc, char **argv)
5062 list_header_only++; 5057 list_header_only++;
5063 quiet++; 5058 quiet++;
5064 break; 5059 break;
5065 case 'm':
5066 do_migrate = 1;
5067 break;
5068 case 'o': 5060 case 'o':
5069 outf = fopen_or_die(optarg, "w"); 5061 outf = fopen_or_die(optarg, "w");
5070 break; 5062 break;
diff --git a/tools/power/x86/x86_energy_perf_policy/Makefile b/tools/power/x86/x86_energy_perf_policy/Makefile
index a711eec0c895..2447b1bbaacf 100644
--- a/tools/power/x86/x86_energy_perf_policy/Makefile
+++ b/tools/power/x86/x86_energy_perf_policy/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1CC = $(CROSS_COMPILE)gcc 2CC = $(CROSS_COMPILE)gcc
2BUILD_OUTPUT := $(CURDIR) 3BUILD_OUTPUT := $(CURDIR)
3PREFIX := /usr 4PREFIX := /usr
diff --git a/tools/scripts/Makefile.arch b/tools/scripts/Makefile.arch
index ad85b921a607..78d90a249e88 100644
--- a/tools/scripts/Makefile.arch
+++ b/tools/scripts/Makefile.arch
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1HOSTARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \ 2HOSTARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
2 -e s/sun4u/sparc/ -e s/sparc64/sparc/ \ 3 -e s/sun4u/sparc/ -e s/sparc64/sparc/ \
3 -e /arm64/!s/arm.*/arm/ -e s/sa110/arm/ \ 4 -e /arm64/!s/arm.*/arm/ -e s/sa110/arm/ \
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index ccad8ce925e4..3fab179b1aba 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1ifneq ($(O),) 2ifneq ($(O),)
2ifeq ($(origin O), command line) 3ifeq ($(origin O), command line)
3 dummy := $(if $(shell test -d $(O) || echo $(O)),$(error O=$(O) does not exist),) 4 dummy := $(if $(shell test -d $(O) || echo $(O)),$(error O=$(O) does not exist),)
@@ -12,7 +13,7 @@ endif
12 13
13# check that the output directory actually exists 14# check that the output directory actually exists
14ifneq ($(OUTPUT),) 15ifneq ($(OUTPUT),)
15OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd) 16OUTDIR := $(shell cd $(OUTPUT) && pwd)
16$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist)) 17$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
17endif 18endif
18 19
@@ -39,7 +40,9 @@ EXTRA_WARNINGS += -Wundef
39EXTRA_WARNINGS += -Wwrite-strings 40EXTRA_WARNINGS += -Wwrite-strings
40EXTRA_WARNINGS += -Wformat 41EXTRA_WARNINGS += -Wformat
41 42
42ifneq ($(CC), clang) 43CC_NO_CLANG := $(shell $(CC) -dM -E -x c /dev/null | grep -Fq "__clang__"; echo $$?)
44
45ifeq ($(CC_NO_CLANG), 1)
43EXTRA_WARNINGS += -Wstrict-aliasing=3 46EXTRA_WARNINGS += -Wstrict-aliasing=3
44endif 47endif
45 48
diff --git a/tools/spi/Build b/tools/spi/Build
new file mode 100644
index 000000000000..8e8466033d99
--- /dev/null
+++ b/tools/spi/Build
@@ -0,0 +1,2 @@
1spidev_test-y += spidev_test.o
2spidev_fdx-y += spidev_fdx.o
diff --git a/tools/spi/Makefile b/tools/spi/Makefile
index 3815b18ba070..90615e10c79a 100644
--- a/tools/spi/Makefile
+++ b/tools/spi/Makefile
@@ -1,6 +1,66 @@
1include ../scripts/Makefile.include
2
3bindir ?= /usr/bin
4
5ifeq ($(srctree),)
6srctree := $(patsubst %/,%,$(dir $(CURDIR)))
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
15LD = $(CROSS_COMPILE)ld
16CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
17
18ALL_TARGETS := spidev_test spidev_fdx
19ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
20
21all: $(ALL_PROGRAMS)
22
23export srctree OUTPUT CC LD CFLAGS
24include $(srctree)/tools/build/Makefile.include
2 25
3all: spidev_test spidev_fdx 26#
27# We need the following to be outside of kernel tree
28#
29$(OUTPUT)include/linux/spi/spidev.h: ../../include/uapi/linux/spi/spidev.h
30 mkdir -p $(OUTPUT)include/linux/spi 2>&1 || true
31 ln -sf $(CURDIR)/../../include/uapi/linux/spi/spidev.h $@
32
33prepare: $(OUTPUT)include/linux/spi/spidev.h
34
35#
36# spidev_test
37#
38SPIDEV_TEST_IN := $(OUTPUT)spidev_test-in.o
39$(SPIDEV_TEST_IN): prepare FORCE
40 $(Q)$(MAKE) $(build)=spidev_test
41$(OUTPUT)spidev_test: $(SPIDEV_TEST_IN)
42 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
43
44#
45# spidev_fdx
46#
47SPIDEV_FDX_IN := $(OUTPUT)spidev_fdx-in.o
48$(SPIDEV_FDX_IN): prepare FORCE
49 $(Q)$(MAKE) $(build)=spidev_fdx
50$(OUTPUT)spidev_fdx: $(SPIDEV_FDX_IN)
51 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
4 52
5clean: 53clean:
6 $(RM) spidev_test spidev_fdx 54 rm -f $(ALL_PROGRAMS)
55 rm -f $(OUTPUT)include/linux/spi/spidev.h
56 find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete
57
58install: $(ALL_PROGRAMS)
59 install -d -m 755 $(DESTDIR)$(bindir); \
60 for program in $(ALL_PROGRAMS); do \
61 install $$program $(DESTDIR)$(bindir); \
62 done
63
64FORCE:
65
66.PHONY: all install clean FORCE prepare
diff --git a/tools/spi/spidev_fdx.c b/tools/spi/spidev_fdx.c
index 0ea3e51292fc..7d2a867cd4ae 100644
--- a/tools/spi/spidev_fdx.c
+++ b/tools/spi/spidev_fdx.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <unistd.h> 3#include <unistd.h>
3#include <stdlib.h> 4#include <stdlib.h>
diff --git a/tools/testing/fault-injection/failcmd.sh b/tools/testing/fault-injection/failcmd.sh
index 78a9ed7fecdb..29a6c63c5a15 100644
--- a/tools/testing/fault-injection/failcmd.sh
+++ b/tools/testing/fault-injection/failcmd.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2# 3#
3# NAME 4# NAME
4# failcmd.sh - run a command with injecting slab/page allocation failures 5# failcmd.sh - run a command with injecting slab/page allocation failures
diff --git a/tools/testing/ktest/compare-ktest-sample.pl b/tools/testing/ktest/compare-ktest-sample.pl
index a373a5bfff68..4118eb4a842d 100755
--- a/tools/testing/ktest/compare-ktest-sample.pl
+++ b/tools/testing/ktest/compare-ktest-sample.pl
@@ -1,4 +1,5 @@
1#!/usr/bin/perl 1#!/usr/bin/perl
2# SPDX-License-Identifier: GPL-2.0
2 3
3open (IN,"ktest.pl"); 4open (IN,"ktest.pl");
4while (<IN>) { 5while (<IN>) {
diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild
index d870520da68b..db33b28c5ef3 100644
--- a/tools/testing/nvdimm/Kbuild
+++ b/tools/testing/nvdimm/Kbuild
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1ldflags-y += --wrap=ioremap_wc 2ldflags-y += --wrap=ioremap_wc
2ldflags-y += --wrap=memremap 3ldflags-y += --wrap=memremap
3ldflags-y += --wrap=devm_ioremap_nocache 4ldflags-y += --wrap=devm_ioremap_nocache
@@ -69,6 +70,7 @@ libnvdimm-y += $(NVDIMM_SRC)/region_devs.o
69libnvdimm-y += $(NVDIMM_SRC)/region.o 70libnvdimm-y += $(NVDIMM_SRC)/region.o
70libnvdimm-y += $(NVDIMM_SRC)/namespace_devs.o 71libnvdimm-y += $(NVDIMM_SRC)/namespace_devs.o
71libnvdimm-y += $(NVDIMM_SRC)/label.o 72libnvdimm-y += $(NVDIMM_SRC)/label.o
73libnvdimm-y += $(NVDIMM_SRC)/badrange.o
72libnvdimm-$(CONFIG_ND_CLAIM) += $(NVDIMM_SRC)/claim.o 74libnvdimm-$(CONFIG_ND_CLAIM) += $(NVDIMM_SRC)/claim.o
73libnvdimm-$(CONFIG_BTT) += $(NVDIMM_SRC)/btt_devs.o 75libnvdimm-$(CONFIG_BTT) += $(NVDIMM_SRC)/btt_devs.o
74libnvdimm-$(CONFIG_NVDIMM_PFN) += $(NVDIMM_SRC)/pfn_devs.o 76libnvdimm-$(CONFIG_NVDIMM_PFN) += $(NVDIMM_SRC)/pfn_devs.o
diff --git a/tools/testing/nvdimm/Makefile b/tools/testing/nvdimm/Makefile
index 3dfe024b4e7e..c37a6a0bde28 100644
--- a/tools/testing/nvdimm/Makefile
+++ b/tools/testing/nvdimm/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1KDIR ?= ../../../ 2KDIR ?= ../../../
2 3
3default: 4default:
diff --git a/tools/testing/nvdimm/config_check.c b/tools/testing/nvdimm/config_check.c
index 7dc5a0af9b54..cac891028cd1 100644
--- a/tools/testing/nvdimm/config_check.c
+++ b/tools/testing/nvdimm/config_check.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <linux/bug.h> 2#include <linux/bug.h>
2 3
3void check(void) 4void check(void)
diff --git a/tools/testing/nvdimm/test/Kbuild b/tools/testing/nvdimm/test/Kbuild
index d32f25bba42a..fb3c3d7cdb9b 100644
--- a/tools/testing/nvdimm/test/Kbuild
+++ b/tools/testing/nvdimm/test/Kbuild
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1ccflags-y := -I$(src)/../../../../drivers/nvdimm/ 2ccflags-y := -I$(src)/../../../../drivers/nvdimm/
2ccflags-y += -I$(src)/../../../../drivers/acpi/nfit/ 3ccflags-y += -I$(src)/../../../../drivers/acpi/nfit/
3 4
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 4c2fa98ef39d..7217b2b953b5 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -168,8 +168,12 @@ struct nfit_test {
168 spinlock_t lock; 168 spinlock_t lock;
169 } ars_state; 169 } ars_state;
170 struct device *dimm_dev[NUM_DCR]; 170 struct device *dimm_dev[NUM_DCR];
171 struct badrange badrange;
172 struct work_struct work;
171}; 173};
172 174
175static struct workqueue_struct *nfit_wq;
176
173static struct nfit_test *to_nfit_test(struct device *dev) 177static struct nfit_test *to_nfit_test(struct device *dev)
174{ 178{
175 struct platform_device *pdev = to_platform_device(dev); 179 struct platform_device *pdev = to_platform_device(dev);
@@ -234,48 +238,68 @@ static int nfit_test_cmd_set_config_data(struct nd_cmd_set_config_hdr *nd_cmd,
234 return rc; 238 return rc;
235} 239}
236 240
237#define NFIT_TEST_ARS_RECORDS 4
238#define NFIT_TEST_CLEAR_ERR_UNIT 256 241#define NFIT_TEST_CLEAR_ERR_UNIT 256
239 242
240static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd, 243static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd,
241 unsigned int buf_len) 244 unsigned int buf_len)
242{ 245{
246 int ars_recs;
247
243 if (buf_len < sizeof(*nd_cmd)) 248 if (buf_len < sizeof(*nd_cmd))
244 return -EINVAL; 249 return -EINVAL;
245 250
251 /* for testing, only store up to n records that fit within 4k */
252 ars_recs = SZ_4K / sizeof(struct nd_ars_record);
253
246 nd_cmd->max_ars_out = sizeof(struct nd_cmd_ars_status) 254 nd_cmd->max_ars_out = sizeof(struct nd_cmd_ars_status)
247 + NFIT_TEST_ARS_RECORDS * sizeof(struct nd_ars_record); 255 + ars_recs * sizeof(struct nd_ars_record);
248 nd_cmd->status = (ND_ARS_PERSISTENT | ND_ARS_VOLATILE) << 16; 256 nd_cmd->status = (ND_ARS_PERSISTENT | ND_ARS_VOLATILE) << 16;
249 nd_cmd->clear_err_unit = NFIT_TEST_CLEAR_ERR_UNIT; 257 nd_cmd->clear_err_unit = NFIT_TEST_CLEAR_ERR_UNIT;
250 258
251 return 0; 259 return 0;
252} 260}
253 261
254/* 262static void post_ars_status(struct ars_state *ars_state,
255 * Initialize the ars_state to return an ars_result 1 second in the future with 263 struct badrange *badrange, u64 addr, u64 len)
256 * a 4K error range in the middle of the requested address range.
257 */
258static void post_ars_status(struct ars_state *ars_state, u64 addr, u64 len)
259{ 264{
260 struct nd_cmd_ars_status *ars_status; 265 struct nd_cmd_ars_status *ars_status;
261 struct nd_ars_record *ars_record; 266 struct nd_ars_record *ars_record;
267 struct badrange_entry *be;
268 u64 end = addr + len - 1;
269 int i = 0;
262 270
263 ars_state->deadline = jiffies + 1*HZ; 271 ars_state->deadline = jiffies + 1*HZ;
264 ars_status = ars_state->ars_status; 272 ars_status = ars_state->ars_status;
265 ars_status->status = 0; 273 ars_status->status = 0;
266 ars_status->out_length = sizeof(struct nd_cmd_ars_status)
267 + sizeof(struct nd_ars_record);
268 ars_status->address = addr; 274 ars_status->address = addr;
269 ars_status->length = len; 275 ars_status->length = len;
270 ars_status->type = ND_ARS_PERSISTENT; 276 ars_status->type = ND_ARS_PERSISTENT;
271 ars_status->num_records = 1; 277
272 ars_record = &ars_status->records[0]; 278 spin_lock(&badrange->lock);
273 ars_record->handle = 0; 279 list_for_each_entry(be, &badrange->list, list) {
274 ars_record->err_address = addr + len / 2; 280 u64 be_end = be->start + be->length - 1;
275 ars_record->length = SZ_4K; 281 u64 rstart, rend;
282
283 /* skip entries outside the range */
284 if (be_end < addr || be->start > end)
285 continue;
286
287 rstart = (be->start < addr) ? addr : be->start;
288 rend = (be_end < end) ? be_end : end;
289 ars_record = &ars_status->records[i];
290 ars_record->handle = 0;
291 ars_record->err_address = rstart;
292 ars_record->length = rend - rstart + 1;
293 i++;
294 }
295 spin_unlock(&badrange->lock);
296 ars_status->num_records = i;
297 ars_status->out_length = sizeof(struct nd_cmd_ars_status)
298 + i * sizeof(struct nd_ars_record);
276} 299}
277 300
278static int nfit_test_cmd_ars_start(struct ars_state *ars_state, 301static int nfit_test_cmd_ars_start(struct nfit_test *t,
302 struct ars_state *ars_state,
279 struct nd_cmd_ars_start *ars_start, unsigned int buf_len, 303 struct nd_cmd_ars_start *ars_start, unsigned int buf_len,
280 int *cmd_rc) 304 int *cmd_rc)
281{ 305{
@@ -289,7 +313,7 @@ static int nfit_test_cmd_ars_start(struct ars_state *ars_state,
289 } else { 313 } else {
290 ars_start->status = 0; 314 ars_start->status = 0;
291 ars_start->scrub_time = 1; 315 ars_start->scrub_time = 1;
292 post_ars_status(ars_state, ars_start->address, 316 post_ars_status(ars_state, &t->badrange, ars_start->address,
293 ars_start->length); 317 ars_start->length);
294 *cmd_rc = 0; 318 *cmd_rc = 0;
295 } 319 }
@@ -320,7 +344,8 @@ static int nfit_test_cmd_ars_status(struct ars_state *ars_state,
320 return 0; 344 return 0;
321} 345}
322 346
323static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error *clear_err, 347static int nfit_test_cmd_clear_error(struct nfit_test *t,
348 struct nd_cmd_clear_error *clear_err,
324 unsigned int buf_len, int *cmd_rc) 349 unsigned int buf_len, int *cmd_rc)
325{ 350{
326 const u64 mask = NFIT_TEST_CLEAR_ERR_UNIT - 1; 351 const u64 mask = NFIT_TEST_CLEAR_ERR_UNIT - 1;
@@ -330,18 +355,91 @@ static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error *clear_err,
330 if ((clear_err->address & mask) || (clear_err->length & mask)) 355 if ((clear_err->address & mask) || (clear_err->length & mask))
331 return -EINVAL; 356 return -EINVAL;
332 357
333 /* 358 badrange_forget(&t->badrange, clear_err->address, clear_err->length);
334 * Report 'all clear' success for all commands even though a new
335 * scrub will find errors again. This is enough to have the
336 * error removed from the 'badblocks' tracking in the pmem
337 * driver.
338 */
339 clear_err->status = 0; 359 clear_err->status = 0;
340 clear_err->cleared = clear_err->length; 360 clear_err->cleared = clear_err->length;
341 *cmd_rc = 0; 361 *cmd_rc = 0;
342 return 0; 362 return 0;
343} 363}
344 364
365struct region_search_spa {
366 u64 addr;
367 struct nd_region *region;
368};
369
370static int is_region_device(struct device *dev)
371{
372 return !strncmp(dev->kobj.name, "region", 6);
373}
374
375static int nfit_test_search_region_spa(struct device *dev, void *data)
376{
377 struct region_search_spa *ctx = data;
378 struct nd_region *nd_region;
379 resource_size_t ndr_end;
380
381 if (!is_region_device(dev))
382 return 0;
383
384 nd_region = to_nd_region(dev);
385 ndr_end = nd_region->ndr_start + nd_region->ndr_size;
386
387 if (ctx->addr >= nd_region->ndr_start && ctx->addr < ndr_end) {
388 ctx->region = nd_region;
389 return 1;
390 }
391
392 return 0;
393}
394
395static int nfit_test_search_spa(struct nvdimm_bus *bus,
396 struct nd_cmd_translate_spa *spa)
397{
398 int ret;
399 struct nd_region *nd_region = NULL;
400 struct nvdimm *nvdimm = NULL;
401 struct nd_mapping *nd_mapping = NULL;
402 struct region_search_spa ctx = {
403 .addr = spa->spa,
404 .region = NULL,
405 };
406 u64 dpa;
407
408 ret = device_for_each_child(&bus->dev, &ctx,
409 nfit_test_search_region_spa);
410
411 if (!ret)
412 return -ENODEV;
413
414 nd_region = ctx.region;
415
416 dpa = ctx.addr - nd_region->ndr_start;
417
418 /*
419 * last dimm is selected for test
420 */
421 nd_mapping = &nd_region->mapping[nd_region->ndr_mappings - 1];
422 nvdimm = nd_mapping->nvdimm;
423
424 spa->devices[0].nfit_device_handle = handle[nvdimm->id];
425 spa->num_nvdimms = 1;
426 spa->devices[0].dpa = dpa;
427
428 return 0;
429}
430
431static int nfit_test_cmd_translate_spa(struct nvdimm_bus *bus,
432 struct nd_cmd_translate_spa *spa, unsigned int buf_len)
433{
434 if (buf_len < spa->translate_length)
435 return -EINVAL;
436
437 if (nfit_test_search_spa(bus, spa) < 0 || !spa->num_nvdimms)
438 spa->status = 2;
439
440 return 0;
441}
442
345static int nfit_test_cmd_smart(struct nd_cmd_smart *smart, unsigned int buf_len) 443static int nfit_test_cmd_smart(struct nd_cmd_smart *smart, unsigned int buf_len)
346{ 444{
347 static const struct nd_smart_payload smart_data = { 445 static const struct nd_smart_payload smart_data = {
@@ -378,6 +476,93 @@ static int nfit_test_cmd_smart_threshold(struct nd_cmd_smart_threshold *smart_t,
378 return 0; 476 return 0;
379} 477}
380 478
479static void uc_error_notify(struct work_struct *work)
480{
481 struct nfit_test *t = container_of(work, typeof(*t), work);
482
483 __acpi_nfit_notify(&t->pdev.dev, t, NFIT_NOTIFY_UC_MEMORY_ERROR);
484}
485
486static int nfit_test_cmd_ars_error_inject(struct nfit_test *t,
487 struct nd_cmd_ars_err_inj *err_inj, unsigned int buf_len)
488{
489 int rc;
490
491 if (buf_len != sizeof(*err_inj)) {
492 rc = -EINVAL;
493 goto err;
494 }
495
496 if (err_inj->err_inj_spa_range_length <= 0) {
497 rc = -EINVAL;
498 goto err;
499 }
500
501 rc = badrange_add(&t->badrange, err_inj->err_inj_spa_range_base,
502 err_inj->err_inj_spa_range_length);
503 if (rc < 0)
504 goto err;
505
506 if (err_inj->err_inj_options & (1 << ND_ARS_ERR_INJ_OPT_NOTIFY))
507 queue_work(nfit_wq, &t->work);
508
509 err_inj->status = 0;
510 return 0;
511
512err:
513 err_inj->status = NFIT_ARS_INJECT_INVALID;
514 return rc;
515}
516
517static int nfit_test_cmd_ars_inject_clear(struct nfit_test *t,
518 struct nd_cmd_ars_err_inj_clr *err_clr, unsigned int buf_len)
519{
520 int rc;
521
522 if (buf_len != sizeof(*err_clr)) {
523 rc = -EINVAL;
524 goto err;
525 }
526
527 if (err_clr->err_inj_clr_spa_range_length <= 0) {
528 rc = -EINVAL;
529 goto err;
530 }
531
532 badrange_forget(&t->badrange, err_clr->err_inj_clr_spa_range_base,
533 err_clr->err_inj_clr_spa_range_length);
534
535 err_clr->status = 0;
536 return 0;
537
538err:
539 err_clr->status = NFIT_ARS_INJECT_INVALID;
540 return rc;
541}
542
543static int nfit_test_cmd_ars_inject_status(struct nfit_test *t,
544 struct nd_cmd_ars_err_inj_stat *err_stat,
545 unsigned int buf_len)
546{
547 struct badrange_entry *be;
548 int max = SZ_4K / sizeof(struct nd_error_stat_query_record);
549 int i = 0;
550
551 err_stat->status = 0;
552 spin_lock(&t->badrange.lock);
553 list_for_each_entry(be, &t->badrange.list, list) {
554 err_stat->record[i].err_inj_stat_spa_range_base = be->start;
555 err_stat->record[i].err_inj_stat_spa_range_length = be->length;
556 i++;
557 if (i > max)
558 break;
559 }
560 spin_unlock(&t->badrange.lock);
561 err_stat->inj_err_rec_count = i;
562
563 return 0;
564}
565
381static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, 566static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
382 struct nvdimm *nvdimm, unsigned int cmd, void *buf, 567 struct nvdimm *nvdimm, unsigned int cmd, void *buf,
383 unsigned int buf_len, int *cmd_rc) 568 unsigned int buf_len, int *cmd_rc)
@@ -449,6 +634,38 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
449 } 634 }
450 } else { 635 } else {
451 struct ars_state *ars_state = &t->ars_state; 636 struct ars_state *ars_state = &t->ars_state;
637 struct nd_cmd_pkg *call_pkg = buf;
638
639 if (!nd_desc)
640 return -ENOTTY;
641
642 if (cmd == ND_CMD_CALL) {
643 func = call_pkg->nd_command;
644
645 buf_len = call_pkg->nd_size_in + call_pkg->nd_size_out;
646 buf = (void *) call_pkg->nd_payload;
647
648 switch (func) {
649 case NFIT_CMD_TRANSLATE_SPA:
650 rc = nfit_test_cmd_translate_spa(
651 acpi_desc->nvdimm_bus, buf, buf_len);
652 return rc;
653 case NFIT_CMD_ARS_INJECT_SET:
654 rc = nfit_test_cmd_ars_error_inject(t, buf,
655 buf_len);
656 return rc;
657 case NFIT_CMD_ARS_INJECT_CLEAR:
658 rc = nfit_test_cmd_ars_inject_clear(t, buf,
659 buf_len);
660 return rc;
661 case NFIT_CMD_ARS_INJECT_GET:
662 rc = nfit_test_cmd_ars_inject_status(t, buf,
663 buf_len);
664 return rc;
665 default:
666 return -ENOTTY;
667 }
668 }
452 669
453 if (!nd_desc || !test_bit(cmd, &nd_desc->cmd_mask)) 670 if (!nd_desc || !test_bit(cmd, &nd_desc->cmd_mask))
454 return -ENOTTY; 671 return -ENOTTY;
@@ -458,15 +675,15 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
458 rc = nfit_test_cmd_ars_cap(buf, buf_len); 675 rc = nfit_test_cmd_ars_cap(buf, buf_len);
459 break; 676 break;
460 case ND_CMD_ARS_START: 677 case ND_CMD_ARS_START:
461 rc = nfit_test_cmd_ars_start(ars_state, buf, buf_len, 678 rc = nfit_test_cmd_ars_start(t, ars_state, buf,
462 cmd_rc); 679 buf_len, cmd_rc);
463 break; 680 break;
464 case ND_CMD_ARS_STATUS: 681 case ND_CMD_ARS_STATUS:
465 rc = nfit_test_cmd_ars_status(ars_state, buf, buf_len, 682 rc = nfit_test_cmd_ars_status(ars_state, buf, buf_len,
466 cmd_rc); 683 cmd_rc);
467 break; 684 break;
468 case ND_CMD_CLEAR_ERROR: 685 case ND_CMD_CLEAR_ERROR:
469 rc = nfit_test_cmd_clear_error(buf, buf_len, cmd_rc); 686 rc = nfit_test_cmd_clear_error(t, buf, buf_len, cmd_rc);
470 break; 687 break;
471 default: 688 default:
472 return -ENOTTY; 689 return -ENOTTY;
@@ -566,10 +783,9 @@ static struct nfit_test_resource *nfit_test_lookup(resource_size_t addr)
566 783
567static int ars_state_init(struct device *dev, struct ars_state *ars_state) 784static int ars_state_init(struct device *dev, struct ars_state *ars_state)
568{ 785{
786 /* for testing, only store up to n records that fit within 4k */
569 ars_state->ars_status = devm_kzalloc(dev, 787 ars_state->ars_status = devm_kzalloc(dev,
570 sizeof(struct nd_cmd_ars_status) 788 sizeof(struct nd_cmd_ars_status) + SZ_4K, GFP_KERNEL);
571 + sizeof(struct nd_ars_record) * NFIT_TEST_ARS_RECORDS,
572 GFP_KERNEL);
573 if (!ars_state->ars_status) 789 if (!ars_state->ars_status)
574 return -ENOMEM; 790 return -ENOMEM;
575 spin_lock_init(&ars_state->lock); 791 spin_lock_init(&ars_state->lock);
@@ -1419,7 +1635,8 @@ static void nfit_test0_setup(struct nfit_test *t)
1419 + i * sizeof(u64); 1635 + i * sizeof(u64);
1420 } 1636 }
1421 1637
1422 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE); 1638 post_ars_status(&t->ars_state, &t->badrange, t->spa_set_dma[0],
1639 SPA0_SIZE);
1423 1640
1424 acpi_desc = &t->acpi_desc; 1641 acpi_desc = &t->acpi_desc;
1425 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en); 1642 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en);
@@ -1430,7 +1647,12 @@ static void nfit_test0_setup(struct nfit_test *t)
1430 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en); 1647 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
1431 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en); 1648 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
1432 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en); 1649 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
1650 set_bit(ND_CMD_CALL, &acpi_desc->bus_cmd_force_en);
1433 set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en); 1651 set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
1652 set_bit(NFIT_CMD_TRANSLATE_SPA, &acpi_desc->bus_nfit_cmd_force_en);
1653 set_bit(NFIT_CMD_ARS_INJECT_SET, &acpi_desc->bus_nfit_cmd_force_en);
1654 set_bit(NFIT_CMD_ARS_INJECT_CLEAR, &acpi_desc->bus_nfit_cmd_force_en);
1655 set_bit(NFIT_CMD_ARS_INJECT_GET, &acpi_desc->bus_nfit_cmd_force_en);
1434} 1656}
1435 1657
1436static void nfit_test1_setup(struct nfit_test *t) 1658static void nfit_test1_setup(struct nfit_test *t)
@@ -1520,16 +1742,14 @@ static void nfit_test1_setup(struct nfit_test *t)
1520 dcr->code = NFIT_FIC_BYTE; 1742 dcr->code = NFIT_FIC_BYTE;
1521 dcr->windows = 0; 1743 dcr->windows = 0;
1522 1744
1523 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA2_SIZE); 1745 post_ars_status(&t->ars_state, &t->badrange, t->spa_set_dma[0],
1746 SPA2_SIZE);
1524 1747
1525 acpi_desc = &t->acpi_desc; 1748 acpi_desc = &t->acpi_desc;
1526 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en); 1749 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
1527 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en); 1750 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
1528 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en); 1751 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
1529 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en); 1752 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
1530 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en);
1531 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1532 set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1533} 1753}
1534 1754
1535static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa, 1755static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
@@ -1546,8 +1766,8 @@ static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
1546 else { 1766 else {
1547 memcpy(iobuf, mmio->addr.base + dpa, len); 1767 memcpy(iobuf, mmio->addr.base + dpa, len);
1548 1768
1549 /* give us some some coverage of the mmio_flush_range() API */ 1769 /* give us some some coverage of the arch_invalidate_pmem() API */
1550 mmio_flush_range(mmio->addr.base + dpa, len); 1770 arch_invalidate_pmem(mmio->addr.base + dpa, len);
1551 } 1771 }
1552 nd_region_release_lane(nd_region, lane); 1772 nd_region_release_lane(nd_region, lane);
1553 1773
@@ -1592,6 +1812,7 @@ static int nfit_ctl_test(struct device *dev)
1592 unsigned long mask, cmd_size, offset; 1812 unsigned long mask, cmd_size, offset;
1593 union { 1813 union {
1594 struct nd_cmd_get_config_size cfg_size; 1814 struct nd_cmd_get_config_size cfg_size;
1815 struct nd_cmd_clear_error clear_err;
1595 struct nd_cmd_ars_status ars_stat; 1816 struct nd_cmd_ars_status ars_stat;
1596 struct nd_cmd_ars_cap ars_cap; 1817 struct nd_cmd_ars_cap ars_cap;
1597 char buf[sizeof(struct nd_cmd_ars_status) 1818 char buf[sizeof(struct nd_cmd_ars_status)
@@ -1616,10 +1837,15 @@ static int nfit_ctl_test(struct device *dev)
1616 .cmd_mask = 1UL << ND_CMD_ARS_CAP 1837 .cmd_mask = 1UL << ND_CMD_ARS_CAP
1617 | 1UL << ND_CMD_ARS_START 1838 | 1UL << ND_CMD_ARS_START
1618 | 1UL << ND_CMD_ARS_STATUS 1839 | 1UL << ND_CMD_ARS_STATUS
1619 | 1UL << ND_CMD_CLEAR_ERROR, 1840 | 1UL << ND_CMD_CLEAR_ERROR
1841 | 1UL << ND_CMD_CALL,
1620 .module = THIS_MODULE, 1842 .module = THIS_MODULE,
1621 .provider_name = "ACPI.NFIT", 1843 .provider_name = "ACPI.NFIT",
1622 .ndctl = acpi_nfit_ctl, 1844 .ndctl = acpi_nfit_ctl,
1845 .bus_dsm_mask = 1UL << NFIT_CMD_TRANSLATE_SPA
1846 | 1UL << NFIT_CMD_ARS_INJECT_SET
1847 | 1UL << NFIT_CMD_ARS_INJECT_CLEAR
1848 | 1UL << NFIT_CMD_ARS_INJECT_GET,
1623 }, 1849 },
1624 .dev = &adev->dev, 1850 .dev = &adev->dev,
1625 }; 1851 };
@@ -1770,6 +1996,23 @@ static int nfit_ctl_test(struct device *dev)
1770 return -EIO; 1996 return -EIO;
1771 } 1997 }
1772 1998
1999 /* test clear error */
2000 cmd_size = sizeof(cmds.clear_err);
2001 cmds.clear_err = (struct nd_cmd_clear_error) {
2002 .length = 512,
2003 .cleared = 512,
2004 };
2005 rc = setup_result(cmds.buf, cmd_size);
2006 if (rc)
2007 return rc;
2008 rc = acpi_nfit_ctl(&acpi_desc->nd_desc, NULL, ND_CMD_CLEAR_ERROR,
2009 cmds.buf, cmd_size, &cmd_rc);
2010 if (rc < 0 || cmd_rc) {
2011 dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n",
2012 __func__, __LINE__, rc, cmd_rc);
2013 return -EIO;
2014 }
2015
1773 return 0; 2016 return 0;
1774} 2017}
1775 2018
@@ -1918,6 +2161,10 @@ static __init int nfit_test_init(void)
1918 2161
1919 nfit_test_setup(nfit_test_lookup, nfit_test_evaluate_dsm); 2162 nfit_test_setup(nfit_test_lookup, nfit_test_evaluate_dsm);
1920 2163
2164 nfit_wq = create_singlethread_workqueue("nfit");
2165 if (!nfit_wq)
2166 return -ENOMEM;
2167
1921 nfit_test_dimm = class_create(THIS_MODULE, "nfit_test_dimm"); 2168 nfit_test_dimm = class_create(THIS_MODULE, "nfit_test_dimm");
1922 if (IS_ERR(nfit_test_dimm)) { 2169 if (IS_ERR(nfit_test_dimm)) {
1923 rc = PTR_ERR(nfit_test_dimm); 2170 rc = PTR_ERR(nfit_test_dimm);
@@ -1934,6 +2181,7 @@ static __init int nfit_test_init(void)
1934 goto err_register; 2181 goto err_register;
1935 } 2182 }
1936 INIT_LIST_HEAD(&nfit_test->resources); 2183 INIT_LIST_HEAD(&nfit_test->resources);
2184 badrange_init(&nfit_test->badrange);
1937 switch (i) { 2185 switch (i) {
1938 case 0: 2186 case 0:
1939 nfit_test->num_pm = NUM_PM; 2187 nfit_test->num_pm = NUM_PM;
@@ -1969,6 +2217,7 @@ static __init int nfit_test_init(void)
1969 goto err_register; 2217 goto err_register;
1970 2218
1971 instances[i] = nfit_test; 2219 instances[i] = nfit_test;
2220 INIT_WORK(&nfit_test->work, uc_error_notify);
1972 } 2221 }
1973 2222
1974 rc = platform_driver_register(&nfit_test_driver); 2223 rc = platform_driver_register(&nfit_test_driver);
@@ -1977,6 +2226,7 @@ static __init int nfit_test_init(void)
1977 return 0; 2226 return 0;
1978 2227
1979 err_register: 2228 err_register:
2229 destroy_workqueue(nfit_wq);
1980 for (i = 0; i < NUM_NFITS; i++) 2230 for (i = 0; i < NUM_NFITS; i++)
1981 if (instances[i]) 2231 if (instances[i])
1982 platform_device_unregister(&instances[i]->pdev); 2232 platform_device_unregister(&instances[i]->pdev);
@@ -1992,6 +2242,8 @@ static __exit void nfit_test_exit(void)
1992{ 2242{
1993 int i; 2243 int i;
1994 2244
2245 flush_workqueue(nfit_wq);
2246 destroy_workqueue(nfit_wq);
1995 for (i = 0; i < NUM_NFITS; i++) 2247 for (i = 0; i < NUM_NFITS; i++)
1996 platform_device_unregister(&instances[i]->pdev); 2248 platform_device_unregister(&instances[i]->pdev);
1997 platform_driver_unregister(&nfit_test_driver); 2249 platform_driver_unregister(&nfit_test_driver);
diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h
index d3d63dd5ed38..113b44675a71 100644
--- a/tools/testing/nvdimm/test/nfit_test.h
+++ b/tools/testing/nvdimm/test/nfit_test.h
@@ -32,6 +32,58 @@ struct nfit_test_resource {
32 void *buf; 32 void *buf;
33}; 33};
34 34
35#define ND_TRANSLATE_SPA_STATUS_INVALID_SPA 2
36#define NFIT_ARS_INJECT_INVALID 2
37
38enum err_inj_options {
39 ND_ARS_ERR_INJ_OPT_NOTIFY = 0,
40};
41
42/* nfit commands */
43enum nfit_cmd_num {
44 NFIT_CMD_TRANSLATE_SPA = 5,
45 NFIT_CMD_ARS_INJECT_SET = 7,
46 NFIT_CMD_ARS_INJECT_CLEAR = 8,
47 NFIT_CMD_ARS_INJECT_GET = 9,
48};
49
50struct nd_cmd_translate_spa {
51 __u64 spa;
52 __u32 status;
53 __u8 flags;
54 __u8 _reserved[3];
55 __u64 translate_length;
56 __u32 num_nvdimms;
57 struct nd_nvdimm_device {
58 __u32 nfit_device_handle;
59 __u32 _reserved;
60 __u64 dpa;
61 } __packed devices[0];
62
63} __packed;
64
65struct nd_cmd_ars_err_inj {
66 __u64 err_inj_spa_range_base;
67 __u64 err_inj_spa_range_length;
68 __u8 err_inj_options;
69 __u32 status;
70} __packed;
71
72struct nd_cmd_ars_err_inj_clr {
73 __u64 err_inj_clr_spa_range_base;
74 __u64 err_inj_clr_spa_range_length;
75 __u32 status;
76} __packed;
77
78struct nd_cmd_ars_err_inj_stat {
79 __u32 status;
80 __u32 inj_err_rec_count;
81 struct nd_error_stat_query_record {
82 __u64 err_inj_stat_spa_range_base;
83 __u64 err_inj_stat_spa_range_length;
84 } __packed record[0];
85} __packed;
86
35union acpi_object; 87union acpi_object;
36typedef void *acpi_handle; 88typedef void *acpi_handle;
37 89
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index 6a9480c03cbd..fa7ee369b3c9 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1 2
2CFLAGS += -I. -I../../include -g -O2 -Wall -D_LGPL_SOURCE -fsanitize=address 3CFLAGS += -I. -I../../include -g -O2 -Wall -D_LGPL_SOURCE -fsanitize=address
3LDFLAGS += -fsanitize=address 4LDFLAGS += -fsanitize=address
diff --git a/tools/testing/radix-tree/linux.c b/tools/testing/radix-tree/linux.c
index cf48c8473f48..6903ccf35595 100644
--- a/tools/testing/radix-tree/linux.c
+++ b/tools/testing/radix-tree/linux.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdlib.h> 2#include <stdlib.h>
2#include <string.h> 3#include <string.h>
3#include <malloc.h> 4#include <malloc.h>
diff --git a/tools/testing/radix-tree/linux/gfp.h b/tools/testing/radix-tree/linux/gfp.h
index 39a0dcb9475a..e9fff59dfd8a 100644
--- a/tools/testing/radix-tree/linux/gfp.h
+++ b/tools/testing/radix-tree/linux/gfp.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _GFP_H 2#ifndef _GFP_H
2#define _GFP_H 3#define _GFP_H
3 4
diff --git a/tools/testing/radix-tree/linux/kernel.h b/tools/testing/radix-tree/linux/kernel.h
index b21a77fddcf7..c3bc3f364f68 100644
--- a/tools/testing/radix-tree/linux/kernel.h
+++ b/tools/testing/radix-tree/linux/kernel.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _KERNEL_H 2#ifndef _KERNEL_H
2#define _KERNEL_H 3#define _KERNEL_H
3 4
diff --git a/tools/testing/radix-tree/linux/percpu.h b/tools/testing/radix-tree/linux/percpu.h
index 3ea01a1a88c2..b2403aa743b2 100644
--- a/tools/testing/radix-tree/linux/percpu.h
+++ b/tools/testing/radix-tree/linux/percpu.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#define DECLARE_PER_CPU(type, val) extern type val 2#define DECLARE_PER_CPU(type, val) extern type val
2#define DEFINE_PER_CPU(type, val) type val 3#define DEFINE_PER_CPU(type, val) type val
3 4
diff --git a/tools/testing/radix-tree/linux/preempt.h b/tools/testing/radix-tree/linux/preempt.h
index 35c5ac81529f..edb10302b903 100644
--- a/tools/testing/radix-tree/linux/preempt.h
+++ b/tools/testing/radix-tree/linux/preempt.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __LINUX_PREEMPT_H 2#ifndef __LINUX_PREEMPT_H
2#define __LINUX_PREEMPT_H 3#define __LINUX_PREEMPT_H
3 4
diff --git a/tools/testing/radix-tree/linux/radix-tree.h b/tools/testing/radix-tree/linux/radix-tree.h
index bf1bb231f9b5..24f13d27a8da 100644
--- a/tools/testing/radix-tree/linux/radix-tree.h
+++ b/tools/testing/radix-tree/linux/radix-tree.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _TEST_RADIX_TREE_H 2#ifndef _TEST_RADIX_TREE_H
2#define _TEST_RADIX_TREE_H 3#define _TEST_RADIX_TREE_H
3 4
diff --git a/tools/testing/radix-tree/linux/rcupdate.h b/tools/testing/radix-tree/linux/rcupdate.h
index f7129ea2a899..73ed33658203 100644
--- a/tools/testing/radix-tree/linux/rcupdate.h
+++ b/tools/testing/radix-tree/linux/rcupdate.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _RCUPDATE_H 2#ifndef _RCUPDATE_H
2#define _RCUPDATE_H 3#define _RCUPDATE_H
3 4
diff --git a/tools/testing/radix-tree/linux/slab.h b/tools/testing/radix-tree/linux/slab.h
index e40337f41a38..979baeec7e70 100644
--- a/tools/testing/radix-tree/linux/slab.h
+++ b/tools/testing/radix-tree/linux/slab.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef SLAB_H 2#ifndef SLAB_H
2#define SLAB_H 3#define SLAB_H
3 4
diff --git a/tools/testing/radix-tree/main.c b/tools/testing/radix-tree/main.c
index bc9a78449572..257f3f8aacaa 100644
--- a/tools/testing/radix-tree/main.c
+++ b/tools/testing/radix-tree/main.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <unistd.h> 4#include <unistd.h>
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c
index 06c71178d07d..59245b3d587c 100644
--- a/tools/testing/radix-tree/multiorder.c
+++ b/tools/testing/radix-tree/multiorder.c
@@ -618,7 +618,7 @@ static void multiorder_account(void)
618 __radix_tree_insert(&tree, 1 << 5, 5, (void *)0x12); 618 __radix_tree_insert(&tree, 1 << 5, 5, (void *)0x12);
619 __radix_tree_lookup(&tree, 1 << 5, &node, &slot); 619 __radix_tree_lookup(&tree, 1 << 5, &node, &slot);
620 assert(node->count == node->exceptional * 2); 620 assert(node->count == node->exceptional * 2);
621 __radix_tree_replace(&tree, node, slot, NULL, NULL, NULL); 621 __radix_tree_replace(&tree, node, slot, NULL, NULL);
622 assert(node->exceptional == 0); 622 assert(node->exceptional == 0);
623 623
624 item_kill_tree(&tree); 624 item_kill_tree(&tree);
diff --git a/tools/testing/radix-tree/regression.h b/tools/testing/radix-tree/regression.h
index e018c4816688..3c8a1584e9ee 100644
--- a/tools/testing/radix-tree/regression.h
+++ b/tools/testing/radix-tree/regression.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __REGRESSION_H__ 2#ifndef __REGRESSION_H__
2#define __REGRESSION_H__ 3#define __REGRESSION_H__
3 4
diff --git a/tools/testing/radix-tree/regression1.c b/tools/testing/radix-tree/regression1.c
index bf97742fc18c..0aece092f40e 100644
--- a/tools/testing/radix-tree/regression1.c
+++ b/tools/testing/radix-tree/regression1.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Regression1 3 * Regression1
3 * Description: 4 * Description:
diff --git a/tools/testing/radix-tree/regression2.c b/tools/testing/radix-tree/regression2.c
index 42dd2a33ed24..424b91c77831 100644
--- a/tools/testing/radix-tree/regression2.c
+++ b/tools/testing/radix-tree/regression2.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Regression2 3 * Regression2
3 * Description: 4 * Description:
diff --git a/tools/testing/radix-tree/regression3.c b/tools/testing/radix-tree/regression3.c
index 670c3d2ae7b1..ace2543c3eda 100644
--- a/tools/testing/radix-tree/regression3.c
+++ b/tools/testing/radix-tree/regression3.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Regression3 3 * Regression3
3 * Description: 4 * Description:
diff --git a/tools/testing/radix-tree/tag_check.c b/tools/testing/radix-tree/tag_check.c
index 36dcf7d6945d..543181e4847b 100644
--- a/tools/testing/radix-tree/tag_check.c
+++ b/tools/testing/radix-tree/tag_check.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdlib.h> 2#include <stdlib.h>
2#include <assert.h> 3#include <assert.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/testing/radix-tree/test.c b/tools/testing/radix-tree/test.c
index 1a257d738a1e..5978ab1f403d 100644
--- a/tools/testing/radix-tree/test.c
+++ b/tools/testing/radix-tree/test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdlib.h> 2#include <stdlib.h>
2#include <assert.h> 3#include <assert.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h
index 0f8220cc6166..d9c031dbeb1a 100644
--- a/tools/testing/radix-tree/test.h
+++ b/tools/testing/radix-tree/test.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include <linux/gfp.h> 2#include <linux/gfp.h>
2#include <linux/types.h> 3#include <linux/types.h>
3#include <linux/radix-tree.h> 4#include <linux/radix-tree.h>
diff --git a/tools/testing/scatterlist/Makefile b/tools/testing/scatterlist/Makefile
new file mode 100644
index 000000000000..933c3a6e4d77
--- /dev/null
+++ b/tools/testing/scatterlist/Makefile
@@ -0,0 +1,30 @@
1CFLAGS += -I. -I../../include -g -O2 -Wall -fsanitize=address
2LDFLAGS += -fsanitize=address -fsanitize=undefined
3TARGETS = main
4OFILES = main.o scatterlist.o
5
6ifeq ($(BUILD), 32)
7 CFLAGS += -m32
8 LDFLAGS += -m32
9endif
10
11targets: include $(TARGETS)
12
13main: $(OFILES)
14
15clean:
16 $(RM) $(TARGETS) $(OFILES) scatterlist.c linux/scatterlist.h linux/highmem.h linux/kmemleak.h asm/io.h
17 @rmdir asm
18
19scatterlist.c: ../../../lib/scatterlist.c
20 @sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@
21
22.PHONY: include
23
24include: ../../../include/linux/scatterlist.h
25 @mkdir -p linux
26 @mkdir -p asm
27 @touch asm/io.h
28 @touch linux/highmem.h
29 @touch linux/kmemleak.h
30 @cp $< linux/scatterlist.h
diff --git a/tools/testing/scatterlist/linux/mm.h b/tools/testing/scatterlist/linux/mm.h
new file mode 100644
index 000000000000..6f9ac14aa800
--- /dev/null
+++ b/tools/testing/scatterlist/linux/mm.h
@@ -0,0 +1,125 @@
1#ifndef _LINUX_MM_H
2#define _LINUX_MM_H
3
4#include <assert.h>
5#include <string.h>
6#include <stdlib.h>
7#include <errno.h>
8#include <limits.h>
9#include <stdio.h>
10
11typedef unsigned long dma_addr_t;
12
13#define unlikely
14
15#define BUG_ON(x) assert(!(x))
16
17#define WARN_ON(condition) ({ \
18 int __ret_warn_on = !!(condition); \
19 unlikely(__ret_warn_on); \
20})
21
22#define WARN_ON_ONCE(condition) ({ \
23 int __ret_warn_on = !!(condition); \
24 if (unlikely(__ret_warn_on)) \
25 assert(0); \
26 unlikely(__ret_warn_on); \
27})
28
29#define PAGE_SIZE (4096)
30#define PAGE_SHIFT (12)
31#define PAGE_MASK (~(PAGE_SIZE-1))
32
33#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
34#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
35#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
36
37#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)
38
39#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
40
41#define virt_to_page(x) ((void *)x)
42#define page_address(x) ((void *)x)
43
44static inline unsigned long page_to_phys(struct page *page)
45{
46 assert(0);
47
48 return 0;
49}
50
51#define page_to_pfn(page) ((unsigned long)(page) / PAGE_SIZE)
52#define pfn_to_page(pfn) (void *)((pfn) * PAGE_SIZE)
53#define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
54
55#define __min(t1, t2, min1, min2, x, y) ({ \
56 t1 min1 = (x); \
57 t2 min2 = (y); \
58 (void) (&min1 == &min2); \
59 min1 < min2 ? min1 : min2; })
60
61#define ___PASTE(a,b) a##b
62#define __PASTE(a,b) ___PASTE(a,b)
63
64#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
65
66#define min(x, y) \
67 __min(typeof(x), typeof(y), \
68 __UNIQUE_ID(min1_), __UNIQUE_ID(min2_), \
69 x, y)
70
71#define min_t(type, x, y) \
72 __min(type, type, \
73 __UNIQUE_ID(min1_), __UNIQUE_ID(min2_), \
74 x, y)
75
76#define preemptible() (1)
77
78static inline void *kmap(struct page *page)
79{
80 assert(0);
81
82 return NULL;
83}
84
85static inline void *kmap_atomic(struct page *page)
86{
87 assert(0);
88
89 return NULL;
90}
91
92static inline void kunmap(void *addr)
93{
94 assert(0);
95}
96
97static inline void kunmap_atomic(void *addr)
98{
99 assert(0);
100}
101
102static inline unsigned long __get_free_page(unsigned int flags)
103{
104 return (unsigned long)malloc(PAGE_SIZE);
105}
106
107static inline void free_page(unsigned long page)
108{
109 free((void *)page);
110}
111
112static inline void *kmalloc(unsigned int size, unsigned int flags)
113{
114 return malloc(size);
115}
116
117#define kfree(x) free(x)
118
119#define kmemleak_alloc(a, b, c, d)
120#define kmemleak_free(a)
121
122#define PageSlab(p) (0)
123#define flush_kernel_dcache_page(p)
124
125#endif
diff --git a/tools/testing/scatterlist/main.c b/tools/testing/scatterlist/main.c
new file mode 100644
index 000000000000..0a1464181226
--- /dev/null
+++ b/tools/testing/scatterlist/main.c
@@ -0,0 +1,79 @@
1#include <stdio.h>
2#include <assert.h>
3
4#include <linux/scatterlist.h>
5
6#define MAX_PAGES (64)
7
8static void set_pages(struct page **pages, const unsigned *array, unsigned num)
9{
10 unsigned int i;
11
12 assert(num < MAX_PAGES);
13 for (i = 0; i < num; i++)
14 pages[i] = (struct page *)(unsigned long)
15 ((1 + array[i]) * PAGE_SIZE);
16}
17
18#define pfn(...) (unsigned []){ __VA_ARGS__ }
19
20int main(void)
21{
22 const unsigned int sgmax = SCATTERLIST_MAX_SEGMENT;
23 struct test {
24 int alloc_ret;
25 unsigned num_pages;
26 unsigned *pfn;
27 unsigned size;
28 unsigned int max_seg;
29 unsigned int expected_segments;
30 } *test, tests[] = {
31 { -EINVAL, 1, pfn(0), PAGE_SIZE, PAGE_SIZE + 1, 1 },
32 { -EINVAL, 1, pfn(0), PAGE_SIZE, 0, 1 },
33 { -EINVAL, 1, pfn(0), PAGE_SIZE, sgmax + 1, 1 },
34 { 0, 1, pfn(0), PAGE_SIZE, sgmax, 1 },
35 { 0, 1, pfn(0), 1, sgmax, 1 },
36 { 0, 2, pfn(0, 1), 2 * PAGE_SIZE, sgmax, 1 },
37 { 0, 2, pfn(1, 0), 2 * PAGE_SIZE, sgmax, 2 },
38 { 0, 3, pfn(0, 1, 2), 3 * PAGE_SIZE, sgmax, 1 },
39 { 0, 3, pfn(0, 2, 1), 3 * PAGE_SIZE, sgmax, 3 },
40 { 0, 3, pfn(0, 1, 3), 3 * PAGE_SIZE, sgmax, 2 },
41 { 0, 3, pfn(1, 2, 4), 3 * PAGE_SIZE, sgmax, 2 },
42 { 0, 3, pfn(1, 3, 4), 3 * PAGE_SIZE, sgmax, 2 },
43 { 0, 4, pfn(0, 1, 3, 4), 4 * PAGE_SIZE, sgmax, 2 },
44 { 0, 5, pfn(0, 1, 3, 4, 5), 5 * PAGE_SIZE, sgmax, 2 },
45 { 0, 5, pfn(0, 1, 3, 4, 6), 5 * PAGE_SIZE, sgmax, 3 },
46 { 0, 5, pfn(0, 1, 2, 3, 4), 5 * PAGE_SIZE, sgmax, 1 },
47 { 0, 5, pfn(0, 1, 2, 3, 4), 5 * PAGE_SIZE, 2 * PAGE_SIZE, 3 },
48 { 0, 6, pfn(0, 1, 2, 3, 4, 5), 6 * PAGE_SIZE, 2 * PAGE_SIZE, 3 },
49 { 0, 6, pfn(0, 2, 3, 4, 5, 6), 6 * PAGE_SIZE, 2 * PAGE_SIZE, 4 },
50 { 0, 6, pfn(0, 1, 3, 4, 5, 6), 6 * PAGE_SIZE, 2 * PAGE_SIZE, 3 },
51 { 0, 0, NULL, 0, 0, 0 },
52 };
53 unsigned int i;
54
55 for (i = 0, test = tests; test->expected_segments; test++, i++) {
56 struct page *pages[MAX_PAGES];
57 struct sg_table st;
58 int ret;
59
60 set_pages(pages, test->pfn, test->num_pages);
61
62 ret = __sg_alloc_table_from_pages(&st, pages, test->num_pages,
63 0, test->size, test->max_seg,
64 GFP_KERNEL);
65 assert(ret == test->alloc_ret);
66
67 if (test->alloc_ret)
68 continue;
69
70 assert(st.nents == test->expected_segments);
71 assert(st.orig_nents == test->expected_segments);
72
73 sg_free_table(&st);
74 }
75
76 assert(i == (sizeof(tests) / sizeof(tests[0])) - 1);
77
78 return 0;
79}
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 26ce4f7168be..eaf599dc2137 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -1,4 +1,6 @@
1TARGETS = bpf 1# SPDX-License-Identifier: GPL-2.0
2TARGETS = android
3TARGETS += bpf
2TARGETS += breakpoints 4TARGETS += breakpoints
3TARGETS += capabilities 5TARGETS += capabilities
4TARGETS += cpufreq 6TARGETS += cpufreq
@@ -52,6 +54,10 @@ override LDFLAGS =
52override MAKEFLAGS = 54override MAKEFLAGS =
53endif 55endif
54 56
57ifneq ($(KBUILD_SRC),)
58override LDFLAGS =
59endif
60
55BUILD := $(O) 61BUILD := $(O)
56ifndef BUILD 62ifndef BUILD
57 BUILD := $(KBUILD_OUTPUT) 63 BUILD := $(KBUILD_OUTPUT)
@@ -62,32 +68,32 @@ endif
62 68
63export BUILD 69export BUILD
64all: 70all:
65 for TARGET in $(TARGETS); do \ 71 @for TARGET in $(TARGETS); do \
66 BUILD_TARGET=$$BUILD/$$TARGET; \ 72 BUILD_TARGET=$$BUILD/$$TARGET; \
67 mkdir $$BUILD_TARGET -p; \ 73 mkdir $$BUILD_TARGET -p; \
68 make OUTPUT=$$BUILD_TARGET -C $$TARGET;\ 74 make OUTPUT=$$BUILD_TARGET -C $$TARGET;\
69 done; 75 done;
70 76
71run_tests: all 77run_tests: all
72 for TARGET in $(TARGETS); do \ 78 @for TARGET in $(TARGETS); do \
73 BUILD_TARGET=$$BUILD/$$TARGET; \ 79 BUILD_TARGET=$$BUILD/$$TARGET; \
74 make OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests;\ 80 make OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests;\
75 done; 81 done;
76 82
77hotplug: 83hotplug:
78 for TARGET in $(TARGETS_HOTPLUG); do \ 84 @for TARGET in $(TARGETS_HOTPLUG); do \
79 BUILD_TARGET=$$BUILD/$$TARGET; \ 85 BUILD_TARGET=$$BUILD/$$TARGET; \
80 make OUTPUT=$$BUILD_TARGET -C $$TARGET;\ 86 make OUTPUT=$$BUILD_TARGET -C $$TARGET;\
81 done; 87 done;
82 88
83run_hotplug: hotplug 89run_hotplug: hotplug
84 for TARGET in $(TARGETS_HOTPLUG); do \ 90 @for TARGET in $(TARGETS_HOTPLUG); do \
85 BUILD_TARGET=$$BUILD/$$TARGET; \ 91 BUILD_TARGET=$$BUILD/$$TARGET; \
86 make OUTPUT=$$BUILD_TARGET -C $$TARGET run_full_test;\ 92 make OUTPUT=$$BUILD_TARGET -C $$TARGET run_full_test;\
87 done; 93 done;
88 94
89clean_hotplug: 95clean_hotplug:
90 for TARGET in $(TARGETS_HOTPLUG); do \ 96 @for TARGET in $(TARGETS_HOTPLUG); do \
91 BUILD_TARGET=$$BUILD/$$TARGET; \ 97 BUILD_TARGET=$$BUILD/$$TARGET; \
92 make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\ 98 make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\
93 done; 99 done;
@@ -103,7 +109,7 @@ install:
103ifdef INSTALL_PATH 109ifdef INSTALL_PATH
104 @# Ask all targets to install their files 110 @# Ask all targets to install their files
105 mkdir -p $(INSTALL_PATH) 111 mkdir -p $(INSTALL_PATH)
106 for TARGET in $(TARGETS); do \ 112 @for TARGET in $(TARGETS); do \
107 BUILD_TARGET=$$BUILD/$$TARGET; \ 113 BUILD_TARGET=$$BUILD/$$TARGET; \
108 make OUTPUT=$$BUILD_TARGET -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \ 114 make OUTPUT=$$BUILD_TARGET -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \
109 done; 115 done;
@@ -128,7 +134,7 @@ else
128endif 134endif
129 135
130clean: 136clean:
131 for TARGET in $(TARGETS); do \ 137 @for TARGET in $(TARGETS); do \
132 BUILD_TARGET=$$BUILD/$$TARGET; \ 138 BUILD_TARGET=$$BUILD/$$TARGET; \
133 make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\ 139 make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\
134 done; 140 done;
diff --git a/tools/testing/selftests/android/Makefile b/tools/testing/selftests/android/Makefile
new file mode 100644
index 000000000000..1a7492268993
--- /dev/null
+++ b/tools/testing/selftests/android/Makefile
@@ -0,0 +1,46 @@
1SUBDIRS := ion
2
3TEST_PROGS := run.sh
4
5.PHONY: all clean
6
7include ../lib.mk
8
9all:
10 @for DIR in $(SUBDIRS); do \
11 BUILD_TARGET=$(OUTPUT)/$$DIR; \
12 mkdir $$BUILD_TARGET -p; \
13 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
14 #SUBDIR test prog name should be in the form: SUBDIR_test.sh
15 TEST=$$DIR"_test.sh"; \
16 if [ -e $$DIR/$$TEST ]; then
17 rsync -a $$DIR/$$TEST $$BUILD_TARGET/;
18 fi
19 done
20
21override define RUN_TESTS
22 @cd $(OUTPUT); ./run.sh
23endef
24
25override define INSTALL_RULE
26 mkdir -p $(INSTALL_PATH)
27 install -t $(INSTALL_PATH) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES)
28
29 @for SUBDIR in $(SUBDIRS); do \
30 BUILD_TARGET=$(OUTPUT)/$$SUBDIR; \
31 mkdir $$BUILD_TARGET -p; \
32 $(MAKE) OUTPUT=$$BUILD_TARGET -C $$SUBDIR INSTALL_PATH=$(INSTALL_PATH)/$$SUBDIR install; \
33 done;
34endef
35
36override define EMIT_TESTS
37 echo "./run.sh"
38endef
39
40override define CLEAN
41 @for DIR in $(SUBDIRS); do \
42 BUILD_TARGET=$(OUTPUT)/$$DIR; \
43 mkdir $$BUILD_TARGET -p; \
44 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
45 done
46endef
diff --git a/tools/testing/selftests/android/ion/.gitignore b/tools/testing/selftests/android/ion/.gitignore
new file mode 100644
index 000000000000..67e6f391b2a9
--- /dev/null
+++ b/tools/testing/selftests/android/ion/.gitignore
@@ -0,0 +1,2 @@
1ionapp_export
2ionapp_import
diff --git a/tools/testing/selftests/android/ion/Makefile b/tools/testing/selftests/android/ion/Makefile
new file mode 100644
index 000000000000..96e0c448b39d
--- /dev/null
+++ b/tools/testing/selftests/android/ion/Makefile
@@ -0,0 +1,16 @@
1
2INCLUDEDIR := -I. -I../../../../../drivers/staging/android/uapi/
3CFLAGS := $(CFLAGS) $(INCLUDEDIR) -Wall -O2 -g
4
5TEST_GEN_FILES := ionapp_export ionapp_import
6
7all: $(TEST_GEN_FILES)
8
9$(TEST_GEN_FILES): ipcsocket.c ionutils.c
10
11TEST_PROGS := ion_test.sh
12
13include ../../lib.mk
14
15$(OUTPUT)/ionapp_export: ionapp_export.c ipcsocket.c ionutils.c
16$(OUTPUT)/ionapp_import: ionapp_import.c ipcsocket.c ionutils.c
diff --git a/tools/testing/selftests/android/ion/README b/tools/testing/selftests/android/ion/README
new file mode 100644
index 000000000000..21783e9c451e
--- /dev/null
+++ b/tools/testing/selftests/android/ion/README
@@ -0,0 +1,101 @@
1ION BUFFER SHARING UTILITY
2==========================
3File: ion_test.sh : Utility to test ION driver buffer sharing mechanism.
4Author: Pintu Kumar <pintu.ping@gmail.com>
5
6Introduction:
7-------------
8This is a test utility to verify ION buffer sharing in user space
9between 2 independent processes.
10It uses unix domain socket (with SCM_RIGHTS) as IPC to transfer an FD to
11another process to share the same buffer.
12This utility demonstrates how ION buffer sharing can be implemented between
13two user space processes, using various heap types.
14The following heap types are supported by ION driver.
15ION_HEAP_TYPE_SYSTEM (0)
16ION_HEAP_TYPE_SYSTEM_CONTIG (1)
17ION_HEAP_TYPE_CARVEOUT (2)
18ION_HEAP_TYPE_CHUNK (3)
19ION_HEAP_TYPE_DMA (4)
20
21By default only the SYSTEM and SYSTEM_CONTIG heaps are supported.
22Each heap is associated with the respective heap id.
23This utility is designed in the form of client/server program.
24The server part (ionapp_export) is the exporter of the buffer.
25It is responsible for creating an ION client, allocating the buffer based on
26the heap id, writing some data to this buffer and then exporting the FD
27(associated with this buffer) to another process using socket IPC.
28This FD is called as buffer FD (which is different than the ION client FD).
29
30The client part (ionapp_import) is the importer of the buffer.
31It retrives the FD from the socket data and installs into its address space.
32This new FD internally points to the same kernel buffer.
33So first it reads the data that is stored in this buffer and prints it.
34Then it writes the different size of data (it could be different data) to the
35same buffer.
36Finally the buffer FD must be closed by both the exporter and importer.
37Thus the same kernel buffer is shared among two user space processes using
38ION driver and only one time allocation.
39
40Prerequisite:
41-------------
42This utility works only if /dev/ion interface is present.
43The following configs needs to be enabled in kernel to include ion driver.
44CONFIG_ANDROID=y
45CONFIG_STAGING=y
46CONFIG_ION=y
47CONFIG_ION_SYSTEM_HEAP=y
48
49This utility requires to be run as root user.
50
51
52Compile and test:
53-----------------
54This utility is made to be run as part of kselftest framework in kernel.
55To compile and run using kselftest you can simply do the following from the
56kernel top directory.
57linux$ make TARGETS=android kselftest
58Or you can also use:
59linux$ make -C tools/testing/selftests TARGETS=android run_tests
60Using the selftest it can directly execute the ion_test.sh script to test the
61buffer sharing using ion system heap.
62Currently the heap size is hard coded as just 10 bytes inside this script.
63You need to be a root user to run under selftest.
64
65You can also compile and test manually using the following steps:
66ion$ make
67These will generate 2 executable: ionapp_export, ionapp_import
68Now you can run the export and import manually by specifying the heap type
69and the heap size.
70You can also directly execute the shell script to run the test automatically.
71Simply use the following command to run the test.
72ion$ sudo ./ion_test.sh
73
74Test Results:
75-------------
76The utility is verified on Ubuntu-32 bit system with Linux Kernel 4.14.
77Here is the snapshot of the test result using kselftest.
78
79linux# make TARGETS=android kselftest
80heap_type: 0, heap_size: 10
81--------------------------------------
82heap type: 0
83 heap id: 1
84heap name: ion_system_heap
85--------------------------------------
86Fill buffer content:
870xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd
88Sharing fd: 6, Client fd: 5
89<ion_close_buffer_fd>: buffer release successfully....
90Received buffer fd: 4
91Read buffer content:
920xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0x0 0x0 0x0 0x0 0x0 0x0
930x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
94Fill buffer content:
950xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd
960xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd
970xfd 0xfd
98<ion_close_buffer_fd>: buffer release successfully....
99ion_test.sh: heap_type: 0 - [PASS]
100
101ion_test.sh: done
diff --git a/tools/testing/selftests/android/ion/config b/tools/testing/selftests/android/ion/config
new file mode 100644
index 000000000000..19db6ca9aa2b
--- /dev/null
+++ b/tools/testing/selftests/android/ion/config
@@ -0,0 +1,4 @@
1CONFIG_ANDROID=y
2CONFIG_STAGING=y
3CONFIG_ION=y
4CONFIG_ION_SYSTEM_HEAP=y
diff --git a/tools/testing/selftests/android/ion/ion.h b/tools/testing/selftests/android/ion/ion.h
new file mode 100644
index 000000000000..f7021ac51335
--- /dev/null
+++ b/tools/testing/selftests/android/ion/ion.h
@@ -0,0 +1,143 @@
1/*
2 * ion.h
3 *
4 * Copyright (C) 2011 Google, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
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 */
16
17/* This file is copied from drivers/staging/android/uapi/ion.h
18 * This local copy is required for the selftest to pass, when build
19 * outside the kernel source tree.
20 * Please keep this file in sync with its original file until the
21 * ion driver is moved outside the staging tree.
22 */
23
24#ifndef _UAPI_LINUX_ION_H
25#define _UAPI_LINUX_ION_H
26
27#include <linux/ioctl.h>
28#include <linux/types.h>
29
30/**
31 * enum ion_heap_types - list of all possible types of heaps
32 * @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc
33 * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc
34 * @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved
35 * carveout heap, allocations are physically
36 * contiguous
37 * @ION_HEAP_TYPE_DMA: memory allocated via DMA API
38 * @ION_NUM_HEAPS: helper for iterating over heaps, a bit mask
39 * is used to identify the heaps, so only 32
40 * total heap types are supported
41 */
42enum ion_heap_type {
43 ION_HEAP_TYPE_SYSTEM,
44 ION_HEAP_TYPE_SYSTEM_CONTIG,
45 ION_HEAP_TYPE_CARVEOUT,
46 ION_HEAP_TYPE_CHUNK,
47 ION_HEAP_TYPE_DMA,
48 ION_HEAP_TYPE_CUSTOM, /*
49 * must be last so device specific heaps always
50 * are at the end of this enum
51 */
52};
53
54#define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8)
55
56/**
57 * allocation flags - the lower 16 bits are used by core ion, the upper 16
58 * bits are reserved for use by the heaps themselves.
59 */
60
61/*
62 * mappings of this buffer should be cached, ion will do cache maintenance
63 * when the buffer is mapped for dma
64 */
65#define ION_FLAG_CACHED 1
66
67/**
68 * DOC: Ion Userspace API
69 *
70 * create a client by opening /dev/ion
71 * most operations handled via following ioctls
72 *
73 */
74
75/**
76 * struct ion_allocation_data - metadata passed from userspace for allocations
77 * @len: size of the allocation
78 * @heap_id_mask: mask of heap ids to allocate from
79 * @flags: flags passed to heap
80 * @handle: pointer that will be populated with a cookie to use to
81 * refer to this allocation
82 *
83 * Provided by userspace as an argument to the ioctl
84 */
85struct ion_allocation_data {
86 __u64 len;
87 __u32 heap_id_mask;
88 __u32 flags;
89 __u32 fd;
90 __u32 unused;
91};
92
93#define MAX_HEAP_NAME 32
94
95/**
96 * struct ion_heap_data - data about a heap
97 * @name - first 32 characters of the heap name
98 * @type - heap type
99 * @heap_id - heap id for the heap
100 */
101struct ion_heap_data {
102 char name[MAX_HEAP_NAME];
103 __u32 type;
104 __u32 heap_id;
105 __u32 reserved0;
106 __u32 reserved1;
107 __u32 reserved2;
108};
109
110/**
111 * struct ion_heap_query - collection of data about all heaps
112 * @cnt - total number of heaps to be copied
113 * @heaps - buffer to copy heap data
114 */
115struct ion_heap_query {
116 __u32 cnt; /* Total number of heaps to be copied */
117 __u32 reserved0; /* align to 64bits */
118 __u64 heaps; /* buffer to be populated */
119 __u32 reserved1;
120 __u32 reserved2;
121};
122
123#define ION_IOC_MAGIC 'I'
124
125/**
126 * DOC: ION_IOC_ALLOC - allocate memory
127 *
128 * Takes an ion_allocation_data struct and returns it with the handle field
129 * populated with the opaque handle for the allocation.
130 */
131#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \
132 struct ion_allocation_data)
133
134/**
135 * DOC: ION_IOC_HEAP_QUERY - information about available heaps
136 *
137 * Takes an ion_heap_query structure and populates information about
138 * available Ion heaps.
139 */
140#define ION_IOC_HEAP_QUERY _IOWR(ION_IOC_MAGIC, 8, \
141 struct ion_heap_query)
142
143#endif /* _UAPI_LINUX_ION_H */
diff --git a/tools/testing/selftests/android/ion/ion_test.sh b/tools/testing/selftests/android/ion/ion_test.sh
new file mode 100755
index 000000000000..a1aff506f5e6
--- /dev/null
+++ b/tools/testing/selftests/android/ion/ion_test.sh
@@ -0,0 +1,55 @@
1#!/bin/bash
2
3heapsize=4096
4TCID="ion_test.sh"
5errcode=0
6
7run_test()
8{
9 heaptype=$1
10 ./ionapp_export -i $heaptype -s $heapsize &
11 sleep 1
12 ./ionapp_import
13 if [ $? -ne 0 ]; then
14 echo "$TCID: heap_type: $heaptype - [FAIL]"
15 errcode=1
16 else
17 echo "$TCID: heap_type: $heaptype - [PASS]"
18 fi
19 sleep 1
20 echo ""
21}
22
23check_root()
24{
25 uid=$(id -u)
26 if [ $uid -ne 0 ]; then
27 echo $TCID: must be run as root >&2
28 exit 0
29 fi
30}
31
32check_device()
33{
34 DEVICE=/dev/ion
35 if [ ! -e $DEVICE ]; then
36 echo $TCID: No $DEVICE device found >&2
37 echo $TCID: May be CONFIG_ION is not set >&2
38 exit 0
39 fi
40}
41
42main_function()
43{
44 check_device
45 check_root
46
47 # ION_SYSTEM_HEAP TEST
48 run_test 0
49 # ION_SYSTEM_CONTIG_HEAP TEST
50 run_test 1
51}
52
53main_function
54echo "$TCID: done"
55exit $errcode
diff --git a/tools/testing/selftests/android/ion/ionapp_export.c b/tools/testing/selftests/android/ion/ionapp_export.c
new file mode 100644
index 000000000000..a944e72621a9
--- /dev/null
+++ b/tools/testing/selftests/android/ion/ionapp_export.c
@@ -0,0 +1,135 @@
1/*
2 * ionapp_export.c
3 *
4 * It is a user space utility to create and export android
5 * ion memory buffer fd to another process using unix domain socket as IPC.
6 * This acts like a server for ionapp_import(client).
7 * So, this server has to be started first before the client.
8 *
9 * Copyright (C) 2017 Pintu Kumar <pintu.ping@gmail.com>
10 *
11 * This software is licensed under the terms of the GNU General Public
12 * License version 2, as published by the Free Software Foundation, and
13 * may be copied, distributed, and modified under those terms.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26#include <errno.h>
27#include <sys/time.h>
28#include "ionutils.h"
29#include "ipcsocket.h"
30
31
32void print_usage(int argc, char *argv[])
33{
34 printf("Usage: %s [-h <help>] [-i <heap id>] [-s <size in bytes>]\n",
35 argv[0]);
36}
37
38int main(int argc, char *argv[])
39{
40 int opt, ret, status, heapid;
41 int sockfd, client_fd, shared_fd;
42 unsigned char *map_buf;
43 unsigned long map_len, heap_type, heap_size, flags;
44 struct ion_buffer_info info;
45 struct socket_info skinfo;
46
47 if (argc < 2) {
48 print_usage(argc, argv);
49 return -1;
50 }
51
52 heap_size = 0;
53 flags = 0;
54
55 while ((opt = getopt(argc, argv, "hi:s:")) != -1) {
56 switch (opt) {
57 case 'h':
58 print_usage(argc, argv);
59 exit(0);
60 break;
61 case 'i':
62 heapid = atoi(optarg);
63 switch (heapid) {
64 case 0:
65 heap_type = ION_HEAP_TYPE_SYSTEM;
66 break;
67 case 1:
68 heap_type = ION_HEAP_TYPE_SYSTEM_CONTIG;
69 break;
70 default:
71 printf("ERROR: heap type not supported\n");
72 exit(1);
73 }
74 break;
75 case 's':
76 heap_size = atoi(optarg);
77 break;
78 default:
79 print_usage(argc, argv);
80 exit(1);
81 break;
82 }
83 }
84
85 if (heap_size <= 0) {
86 printf("heap_size cannot be 0\n");
87 print_usage(argc, argv);
88 exit(1);
89 }
90
91 printf("heap_type: %ld, heap_size: %ld\n", heap_type, heap_size);
92 info.heap_type = heap_type;
93 info.heap_size = heap_size;
94 info.flag_type = flags;
95
96 /* This is server: open the socket connection first */
97 /* Here; 1 indicates server or exporter */
98 status = opensocket(&sockfd, SOCKET_NAME, 1);
99 if (status < 0) {
100 fprintf(stderr, "<%s>: Failed opensocket.\n", __func__);
101 goto err_socket;
102 }
103 skinfo.sockfd = sockfd;
104
105 ret = ion_export_buffer_fd(&info);
106 if (ret < 0) {
107 fprintf(stderr, "FAILED: ion_get_buffer_fd\n");
108 goto err_export;
109 }
110 client_fd = info.ionfd;
111 shared_fd = info.buffd;
112 map_buf = info.buffer;
113 map_len = info.buflen;
114 write_buffer(map_buf, map_len);
115
116 /* share ion buf fd with other user process */
117 printf("Sharing fd: %d, Client fd: %d\n", shared_fd, client_fd);
118 skinfo.datafd = shared_fd;
119 skinfo.buflen = map_len;
120
121 ret = socket_send_fd(&skinfo);
122 if (ret < 0) {
123 fprintf(stderr, "FAILED: socket_send_fd\n");
124 goto err_send;
125 }
126
127err_send:
128err_export:
129 ion_close_buffer_fd(&info);
130
131err_socket:
132 closesocket(sockfd, SOCKET_NAME);
133
134 return 0;
135}
diff --git a/tools/testing/selftests/android/ion/ionapp_import.c b/tools/testing/selftests/android/ion/ionapp_import.c
new file mode 100644
index 000000000000..ae2d704cfa46
--- /dev/null
+++ b/tools/testing/selftests/android/ion/ionapp_import.c
@@ -0,0 +1,88 @@
1/*
2 * ionapp_import.c
3 *
4 * It is a user space utility to receive android ion memory buffer fd
5 * over unix domain socket IPC that can be exported by ionapp_export.
6 * This acts like a client for ionapp_export.
7 *
8 * Copyright (C) 2017 Pintu Kumar <pintu.ping@gmail.com>
9 *
10 * This software is licensed under the terms of the GNU General Public
11 * License version 2, as published by the Free Software Foundation, and
12 * may be copied, distributed, and modified under those terms.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 */
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <unistd.h>
24#include <string.h>
25#include "ionutils.h"
26#include "ipcsocket.h"
27
28
29int main(void)
30{
31 int ret, status;
32 int sockfd, shared_fd;
33 unsigned char *map_buf;
34 unsigned long map_len;
35 struct ion_buffer_info info;
36 struct socket_info skinfo;
37
38 /* This is the client part. Here 0 means client or importer */
39 status = opensocket(&sockfd, SOCKET_NAME, 0);
40 if (status < 0) {
41 fprintf(stderr, "No exporter exists...\n");
42 ret = status;
43 goto err_socket;
44 }
45
46 skinfo.sockfd = sockfd;
47
48 ret = socket_receive_fd(&skinfo);
49 if (ret < 0) {
50 fprintf(stderr, "Failed: socket_receive_fd\n");
51 goto err_recv;
52 }
53
54 shared_fd = skinfo.datafd;
55 printf("Received buffer fd: %d\n", shared_fd);
56 if (shared_fd <= 0) {
57 fprintf(stderr, "ERROR: improper buf fd\n");
58 ret = -1;
59 goto err_fd;
60 }
61
62 memset(&info, 0, sizeof(info));
63 info.buffd = shared_fd;
64 info.buflen = ION_BUFFER_LEN;
65
66 ret = ion_import_buffer_fd(&info);
67 if (ret < 0) {
68 fprintf(stderr, "Failed: ion_use_buffer_fd\n");
69 goto err_import;
70 }
71
72 map_buf = info.buffer;
73 map_len = info.buflen;
74 read_buffer(map_buf, map_len);
75
76 /* Write probably new data to the same buffer again */
77 map_len = ION_BUFFER_LEN;
78 write_buffer(map_buf, map_len);
79
80err_import:
81 ion_close_buffer_fd(&info);
82err_fd:
83err_recv:
84err_socket:
85 closesocket(sockfd, SOCKET_NAME);
86
87 return ret;
88}
diff --git a/tools/testing/selftests/android/ion/ionutils.c b/tools/testing/selftests/android/ion/ionutils.c
new file mode 100644
index 000000000000..ce69c14f51fa
--- /dev/null
+++ b/tools/testing/selftests/android/ion/ionutils.c
@@ -0,0 +1,259 @@
1#include <stdio.h>
2#include <string.h>
3#include <unistd.h>
4#include <fcntl.h>
5#include <errno.h>
6//#include <stdint.h>
7#include <sys/ioctl.h>
8#include <sys/mman.h>
9#include "ionutils.h"
10#include "ipcsocket.h"
11
12
13void write_buffer(void *buffer, unsigned long len)
14{
15 int i;
16 unsigned char *ptr = (unsigned char *)buffer;
17
18 if (!ptr) {
19 fprintf(stderr, "<%s>: Invalid buffer...\n", __func__);
20 return;
21 }
22
23 printf("Fill buffer content:\n");
24 memset(ptr, 0xfd, len);
25 for (i = 0; i < len; i++)
26 printf("0x%x ", ptr[i]);
27 printf("\n");
28}
29
30void read_buffer(void *buffer, unsigned long len)
31{
32 int i;
33 unsigned char *ptr = (unsigned char *)buffer;
34
35 if (!ptr) {
36 fprintf(stderr, "<%s>: Invalid buffer...\n", __func__);
37 return;
38 }
39
40 printf("Read buffer content:\n");
41 for (i = 0; i < len; i++)
42 printf("0x%x ", ptr[i]);
43 printf("\n");
44}
45
46int ion_export_buffer_fd(struct ion_buffer_info *ion_info)
47{
48 int i, ret, ionfd, buffer_fd;
49 unsigned int heap_id;
50 unsigned long maplen;
51 unsigned char *map_buffer;
52 struct ion_allocation_data alloc_data;
53 struct ion_heap_query query;
54 struct ion_heap_data heap_data[MAX_HEAP_COUNT];
55
56 if (!ion_info) {
57 fprintf(stderr, "<%s>: Invalid ion info\n", __func__);
58 return -1;
59 }
60
61 /* Create an ION client */
62 ionfd = open(ION_DEVICE, O_RDWR);
63 if (ionfd < 0) {
64 fprintf(stderr, "<%s>: Failed to open ion client: %s\n",
65 __func__, strerror(errno));
66 return -1;
67 }
68
69 memset(&query, 0, sizeof(query));
70 query.cnt = MAX_HEAP_COUNT;
71 query.heaps = (unsigned long int)&heap_data[0];
72 /* Query ION heap_id_mask from ION heap */
73 ret = ioctl(ionfd, ION_IOC_HEAP_QUERY, &query);
74 if (ret < 0) {
75 fprintf(stderr, "<%s>: Failed: ION_IOC_HEAP_QUERY: %s\n",
76 __func__, strerror(errno));
77 goto err_query;
78 }
79
80 heap_id = MAX_HEAP_COUNT + 1;
81 for (i = 0; i < query.cnt; i++) {
82 if (heap_data[i].type == ion_info->heap_type) {
83 printf("--------------------------------------\n");
84 printf("heap type: %d\n", heap_data[i].type);
85 printf(" heap id: %d\n", heap_data[i].heap_id);
86 printf("heap name: %s\n", heap_data[i].name);
87 printf("--------------------------------------\n");
88 heap_id = heap_data[i].heap_id;
89 break;
90 }
91 }
92
93 if (heap_id > MAX_HEAP_COUNT) {
94 fprintf(stderr, "<%s>: ERROR: heap type does not exists\n",
95 __func__);
96 goto err_heap;
97 }
98
99 alloc_data.len = ion_info->heap_size;
100 alloc_data.heap_id_mask = 1 << heap_id;
101 alloc_data.flags = ion_info->flag_type;
102
103 /* Allocate memory for this ION client as per heap_type */
104 ret = ioctl(ionfd, ION_IOC_ALLOC, &alloc_data);
105 if (ret < 0) {
106 fprintf(stderr, "<%s>: Failed: ION_IOC_ALLOC: %s\n",
107 __func__, strerror(errno));
108 goto err_alloc;
109 }
110
111 /* This will return a valid buffer fd */
112 buffer_fd = alloc_data.fd;
113 maplen = alloc_data.len;
114
115 if (buffer_fd < 0 || maplen <= 0) {
116 fprintf(stderr, "<%s>: Invalid map data, fd: %d, len: %ld\n",
117 __func__, buffer_fd, maplen);
118 goto err_fd_data;
119 }
120
121 /* Create memory mapped buffer for the buffer fd */
122 map_buffer = (unsigned char *)mmap(NULL, maplen, PROT_READ|PROT_WRITE,
123 MAP_SHARED, buffer_fd, 0);
124 if (map_buffer == MAP_FAILED) {
125 fprintf(stderr, "<%s>: Failed: mmap: %s\n",
126 __func__, strerror(errno));
127 goto err_mmap;
128 }
129
130 ion_info->ionfd = ionfd;
131 ion_info->buffd = buffer_fd;
132 ion_info->buffer = map_buffer;
133 ion_info->buflen = maplen;
134
135 return 0;
136
137 munmap(map_buffer, maplen);
138
139err_fd_data:
140err_mmap:
141 /* in case of error: close the buffer fd */
142 if (buffer_fd)
143 close(buffer_fd);
144
145err_query:
146err_heap:
147err_alloc:
148 /* In case of error: close the ion client fd */
149 if (ionfd)
150 close(ionfd);
151
152 return -1;
153}
154
155int ion_import_buffer_fd(struct ion_buffer_info *ion_info)
156{
157 int buffd;
158 unsigned char *map_buf;
159 unsigned long map_len;
160
161 if (!ion_info) {
162 fprintf(stderr, "<%s>: Invalid ion info\n", __func__);
163 return -1;
164 }
165
166 map_len = ion_info->buflen;
167 buffd = ion_info->buffd;
168
169 if (buffd < 0 || map_len <= 0) {
170 fprintf(stderr, "<%s>: Invalid map data, fd: %d, len: %ld\n",
171 __func__, buffd, map_len);
172 goto err_buffd;
173 }
174
175 map_buf = (unsigned char *)mmap(NULL, map_len, PROT_READ|PROT_WRITE,
176 MAP_SHARED, buffd, 0);
177 if (map_buf == MAP_FAILED) {
178 printf("<%s>: Failed - mmap: %s\n",
179 __func__, strerror(errno));
180 goto err_mmap;
181 }
182
183 ion_info->buffer = map_buf;
184 ion_info->buflen = map_len;
185
186 return 0;
187
188err_mmap:
189 if (buffd)
190 close(buffd);
191
192err_buffd:
193 return -1;
194}
195
196void ion_close_buffer_fd(struct ion_buffer_info *ion_info)
197{
198 if (ion_info) {
199 /* unmap the buffer properly in the end */
200 munmap(ion_info->buffer, ion_info->buflen);
201 /* close the buffer fd */
202 if (ion_info->buffd > 0)
203 close(ion_info->buffd);
204 /* Finally, close the client fd */
205 if (ion_info->ionfd > 0)
206 close(ion_info->ionfd);
207 printf("<%s>: buffer release successfully....\n", __func__);
208 }
209}
210
211int socket_send_fd(struct socket_info *info)
212{
213 int status;
214 int fd, sockfd;
215 struct socketdata skdata;
216
217 if (!info) {
218 fprintf(stderr, "<%s>: Invalid socket info\n", __func__);
219 return -1;
220 }
221
222 sockfd = info->sockfd;
223 fd = info->datafd;
224 memset(&skdata, 0, sizeof(skdata));
225 skdata.data = fd;
226 skdata.len = sizeof(skdata.data);
227 status = sendtosocket(sockfd, &skdata);
228 if (status < 0) {
229 fprintf(stderr, "<%s>: Failed: sendtosocket\n", __func__);
230 return -1;
231 }
232
233 return 0;
234}
235
236int socket_receive_fd(struct socket_info *info)
237{
238 int status;
239 int fd, sockfd;
240 struct socketdata skdata;
241
242 if (!info) {
243 fprintf(stderr, "<%s>: Invalid socket info\n", __func__);
244 return -1;
245 }
246
247 sockfd = info->sockfd;
248 memset(&skdata, 0, sizeof(skdata));
249 status = receivefromsocket(sockfd, &skdata);
250 if (status < 0) {
251 fprintf(stderr, "<%s>: Failed: receivefromsocket\n", __func__);
252 return -1;
253 }
254
255 fd = (int)skdata.data;
256 info->datafd = fd;
257
258 return status;
259}
diff --git a/tools/testing/selftests/android/ion/ionutils.h b/tools/testing/selftests/android/ion/ionutils.h
new file mode 100644
index 000000000000..9941eb858576
--- /dev/null
+++ b/tools/testing/selftests/android/ion/ionutils.h
@@ -0,0 +1,55 @@
1#ifndef __ION_UTILS_H
2#define __ION_UTILS_H
3
4#include "ion.h"
5
6#define SOCKET_NAME "ion_socket"
7#define ION_DEVICE "/dev/ion"
8
9#define ION_BUFFER_LEN 4096
10#define MAX_HEAP_COUNT ION_HEAP_TYPE_CUSTOM
11
12struct socket_info {
13 int sockfd;
14 int datafd;
15 unsigned long buflen;
16};
17
18struct ion_buffer_info {
19 int ionfd;
20 int buffd;
21 unsigned int heap_type;
22 unsigned int flag_type;
23 unsigned long heap_size;
24 unsigned long buflen;
25 unsigned char *buffer;
26};
27
28
29/* This is used to fill the data into the mapped buffer */
30void write_buffer(void *buffer, unsigned long len);
31
32/* This is used to read the data from the exported buffer */
33void read_buffer(void *buffer, unsigned long len);
34
35/* This is used to create an ION buffer FD for the kernel buffer
36 * So you can export this same buffer to others in the form of FD
37 */
38int ion_export_buffer_fd(struct ion_buffer_info *ion_info);
39
40/* This is used to import or map an exported FD.
41 * So we point to same buffer without making a copy. Hence zero-copy.
42 */
43int ion_import_buffer_fd(struct ion_buffer_info *ion_info);
44
45/* This is used to close all references for the ION client */
46void ion_close_buffer_fd(struct ion_buffer_info *ion_info);
47
48/* This is used to send FD to another process using socket IPC */
49int socket_send_fd(struct socket_info *skinfo);
50
51/* This is used to receive FD from another process using socket IPC */
52int socket_receive_fd(struct socket_info *skinfo);
53
54
55#endif
diff --git a/tools/testing/selftests/android/ion/ipcsocket.c b/tools/testing/selftests/android/ion/ipcsocket.c
new file mode 100644
index 000000000000..7dc521002095
--- /dev/null
+++ b/tools/testing/selftests/android/ion/ipcsocket.c
@@ -0,0 +1,227 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <sys/types.h>
6#include <sys/socket.h>
7#include <sys/time.h>
8#include <sys/un.h>
9#include <errno.h>
10
11#include "ipcsocket.h"
12
13
14int opensocket(int *sockfd, const char *name, int connecttype)
15{
16 int ret, temp = 1;
17
18 if (!name || strlen(name) > MAX_SOCK_NAME_LEN) {
19 fprintf(stderr, "<%s>: Invalid socket name.\n", __func__);
20 return -1;
21 }
22
23 ret = socket(PF_LOCAL, SOCK_STREAM, 0);
24 if (ret < 0) {
25 fprintf(stderr, "<%s>: Failed socket: <%s>\n",
26 __func__, strerror(errno));
27 return ret;
28 }
29
30 *sockfd = ret;
31 if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR,
32 (char *)&temp, sizeof(int)) < 0) {
33 fprintf(stderr, "<%s>: Failed setsockopt: <%s>\n",
34 __func__, strerror(errno));
35 goto err;
36 }
37
38 sprintf(sock_name, "/tmp/%s", name);
39
40 if (connecttype == 1) {
41 /* This is for Server connection */
42 struct sockaddr_un skaddr;
43 int clientfd;
44 socklen_t sklen;
45
46 unlink(sock_name);
47 memset(&skaddr, 0, sizeof(skaddr));
48 skaddr.sun_family = AF_LOCAL;
49 strcpy(skaddr.sun_path, sock_name);
50
51 ret = bind(*sockfd, (struct sockaddr *)&skaddr,
52 SUN_LEN(&skaddr));
53 if (ret < 0) {
54 fprintf(stderr, "<%s>: Failed bind: <%s>\n",
55 __func__, strerror(errno));
56 goto err;
57 }
58
59 ret = listen(*sockfd, 5);
60 if (ret < 0) {
61 fprintf(stderr, "<%s>: Failed listen: <%s>\n",
62 __func__, strerror(errno));
63 goto err;
64 }
65
66 memset(&skaddr, 0, sizeof(skaddr));
67 sklen = sizeof(skaddr);
68
69 ret = accept(*sockfd, (struct sockaddr *)&skaddr,
70 (socklen_t *)&sklen);
71 if (ret < 0) {
72 fprintf(stderr, "<%s>: Failed accept: <%s>\n",
73 __func__, strerror(errno));
74 goto err;
75 }
76
77 clientfd = ret;
78 *sockfd = clientfd;
79 } else {
80 /* This is for client connection */
81 struct sockaddr_un skaddr;
82
83 memset(&skaddr, 0, sizeof(skaddr));
84 skaddr.sun_family = AF_LOCAL;
85 strcpy(skaddr.sun_path, sock_name);
86
87 ret = connect(*sockfd, (struct sockaddr *)&skaddr,
88 SUN_LEN(&skaddr));
89 if (ret < 0) {
90 fprintf(stderr, "<%s>: Failed connect: <%s>\n",
91 __func__, strerror(errno));
92 goto err;
93 }
94 }
95
96 return 0;
97
98err:
99 if (*sockfd)
100 close(*sockfd);
101
102 return ret;
103}
104
105int sendtosocket(int sockfd, struct socketdata *skdata)
106{
107 int ret, buffd;
108 unsigned int len;
109 char cmsg_b[CMSG_SPACE(sizeof(int))];
110 struct cmsghdr *cmsg;
111 struct msghdr msgh;
112 struct iovec iov;
113 struct timeval timeout;
114 fd_set selFDs;
115
116 if (!skdata) {
117 fprintf(stderr, "<%s>: socketdata is NULL\n", __func__);
118 return -1;
119 }
120
121 FD_ZERO(&selFDs);
122 FD_SET(0, &selFDs);
123 FD_SET(sockfd, &selFDs);
124 timeout.tv_sec = 20;
125 timeout.tv_usec = 0;
126
127 ret = select(sockfd+1, NULL, &selFDs, NULL, &timeout);
128 if (ret < 0) {
129 fprintf(stderr, "<%s>: Failed select: <%s>\n",
130 __func__, strerror(errno));
131 return -1;
132 }
133
134 if (FD_ISSET(sockfd, &selFDs)) {
135 buffd = skdata->data;
136 len = skdata->len;
137 memset(&msgh, 0, sizeof(msgh));
138 msgh.msg_control = &cmsg_b;
139 msgh.msg_controllen = CMSG_LEN(len);
140 iov.iov_base = "OK";
141 iov.iov_len = 2;
142 msgh.msg_iov = &iov;
143 msgh.msg_iovlen = 1;
144 cmsg = CMSG_FIRSTHDR(&msgh);
145 cmsg->cmsg_level = SOL_SOCKET;
146 cmsg->cmsg_type = SCM_RIGHTS;
147 cmsg->cmsg_len = CMSG_LEN(len);
148 memcpy(CMSG_DATA(cmsg), &buffd, len);
149
150 ret = sendmsg(sockfd, &msgh, MSG_DONTWAIT);
151 if (ret < 0) {
152 fprintf(stderr, "<%s>: Failed sendmsg: <%s>\n",
153 __func__, strerror(errno));
154 return -1;
155 }
156 }
157
158 return 0;
159}
160
161int receivefromsocket(int sockfd, struct socketdata *skdata)
162{
163 int ret, buffd;
164 unsigned int len = 0;
165 char cmsg_b[CMSG_SPACE(sizeof(int))];
166 struct cmsghdr *cmsg;
167 struct msghdr msgh;
168 struct iovec iov;
169 fd_set recvFDs;
170 char data[32];
171
172 if (!skdata) {
173 fprintf(stderr, "<%s>: socketdata is NULL\n", __func__);
174 return -1;
175 }
176
177 FD_ZERO(&recvFDs);
178 FD_SET(0, &recvFDs);
179 FD_SET(sockfd, &recvFDs);
180
181 ret = select(sockfd+1, &recvFDs, NULL, NULL, NULL);
182 if (ret < 0) {
183 fprintf(stderr, "<%s>: Failed select: <%s>\n",
184 __func__, strerror(errno));
185 return -1;
186 }
187
188 if (FD_ISSET(sockfd, &recvFDs)) {
189 len = sizeof(buffd);
190 memset(&msgh, 0, sizeof(msgh));
191 msgh.msg_control = &cmsg_b;
192 msgh.msg_controllen = CMSG_LEN(len);
193 iov.iov_base = data;
194 iov.iov_len = sizeof(data)-1;
195 msgh.msg_iov = &iov;
196 msgh.msg_iovlen = 1;
197 cmsg = CMSG_FIRSTHDR(&msgh);
198 cmsg->cmsg_level = SOL_SOCKET;
199 cmsg->cmsg_type = SCM_RIGHTS;
200 cmsg->cmsg_len = CMSG_LEN(len);
201
202 ret = recvmsg(sockfd, &msgh, MSG_DONTWAIT);
203 if (ret < 0) {
204 fprintf(stderr, "<%s>: Failed recvmsg: <%s>\n",
205 __func__, strerror(errno));
206 return -1;
207 }
208
209 memcpy(&buffd, CMSG_DATA(cmsg), len);
210 skdata->data = buffd;
211 skdata->len = len;
212 }
213 return 0;
214}
215
216int closesocket(int sockfd, char *name)
217{
218 char sockname[MAX_SOCK_NAME_LEN];
219
220 if (sockfd)
221 close(sockfd);
222 sprintf(sockname, "/tmp/%s", name);
223 unlink(sockname);
224 shutdown(sockfd, 2);
225
226 return 0;
227}
diff --git a/tools/testing/selftests/android/ion/ipcsocket.h b/tools/testing/selftests/android/ion/ipcsocket.h
new file mode 100644
index 000000000000..b3e84498a8a1
--- /dev/null
+++ b/tools/testing/selftests/android/ion/ipcsocket.h
@@ -0,0 +1,35 @@
1
2#ifndef _IPCSOCKET_H
3#define _IPCSOCKET_H
4
5
6#define MAX_SOCK_NAME_LEN 64
7
8char sock_name[MAX_SOCK_NAME_LEN];
9
10/* This structure is responsible for holding the IPC data
11 * data: hold the buffer fd
12 * len: just the length of 32-bit integer fd
13 */
14struct socketdata {
15 int data;
16 unsigned int len;
17};
18
19/* This API is used to open the IPC socket connection
20 * name: implies a unique socket name in the system
21 * connecttype: implies server(0) or client(1)
22 */
23int opensocket(int *sockfd, const char *name, int connecttype);
24
25/* This is the API to send socket data over IPC socket */
26int sendtosocket(int sockfd, struct socketdata *data);
27
28/* This is the API to receive socket data over IPC socket */
29int receivefromsocket(int sockfd, struct socketdata *data);
30
31/* This is the API to close the socket connection */
32int closesocket(int sockfd, char *name);
33
34
35#endif
diff --git a/tools/testing/selftests/android/run.sh b/tools/testing/selftests/android/run.sh
new file mode 100755
index 000000000000..dd8edf291454
--- /dev/null
+++ b/tools/testing/selftests/android/run.sh
@@ -0,0 +1,3 @@
1#!/bin/sh
2
3(cd ion; ./ion_test.sh)
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 153c3a181a4c..333a48655ee0 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1LIBDIR := ../../../lib 2LIBDIR := ../../../lib
2BPFDIR := $(LIBDIR)/bpf 3BPFDIR := $(LIBDIR)/bpf
3APIDIR := ../../../include/uapi 4APIDIR := ../../../include/uapi
@@ -12,16 +13,17 @@ CFLAGS += -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(GENDIR) $(GENFLAGS) -I../../../i
12LDLIBS += -lcap -lelf 13LDLIBS += -lcap -lelf
13 14
14TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \ 15TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
15 test_align 16 test_align test_verifier_log test_dev_cgroup
16 17
17TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \ 18TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \
18 test_pkt_md_access.o 19 test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \
20 sockmap_verdict_prog.o dev_cgroup.o
19 21
20TEST_PROGS := test_kmod.sh 22TEST_PROGS := test_kmod.sh test_xdp_redirect.sh test_xdp_meta.sh
21 23
22include ../lib.mk 24include ../lib.mk
23 25
24BPFOBJ := $(OUTPUT)/libbpf.a 26BPFOBJ := $(OUTPUT)/libbpf.a $(OUTPUT)/cgroup_helpers.c
25 27
26$(TEST_GEN_PROGS): $(BPFOBJ) 28$(TEST_GEN_PROGS): $(BPFOBJ)
27 29
@@ -34,8 +36,20 @@ $(BPFOBJ): force
34 $(MAKE) -C $(BPFDIR) OUTPUT=$(OUTPUT)/ 36 $(MAKE) -C $(BPFDIR) OUTPUT=$(OUTPUT)/
35 37
36CLANG ?= clang 38CLANG ?= clang
39LLC ?= llc
40
41PROBE := $(shell llc -march=bpf -mcpu=probe -filetype=null /dev/null 2>&1)
42
43# Let newer LLVM versions transparently probe the kernel for availability
44# of full BPF instruction set.
45ifeq ($(PROBE),)
46 CPU ?= probe
47else
48 CPU ?= generic
49endif
37 50
38%.o: %.c 51%.o: %.c
39 $(CLANG) -I. -I./include/uapi -I../../../include/uapi \ 52 $(CLANG) -I. -I./include/uapi -I../../../include/uapi \
40 -Wno-compare-distinct-pointer-types \ 53 -Wno-compare-distinct-pointer-types \
41 -O2 -target bpf -c $< -o $@ 54 -O2 -target bpf -emit-llvm -c $< -o - | \
55 $(LLC) -march=bpf -mcpu=$(CPU) -filetype=obj -o $@
diff --git a/tools/testing/selftests/bpf/bpf_endian.h b/tools/testing/selftests/bpf/bpf_endian.h
index 74af266aa512..b25595ea4a78 100644
--- a/tools/testing/selftests/bpf/bpf_endian.h
+++ b/tools/testing/selftests/bpf/bpf_endian.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __BPF_ENDIAN__ 2#ifndef __BPF_ENDIAN__
2#define __BPF_ENDIAN__ 3#define __BPF_ENDIAN__
3 4
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index d50ac342dc92..fd9a17fa8a8b 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __BPF_HELPERS_H 2#ifndef __BPF_HELPERS_H
2#define __BPF_HELPERS_H 3#define __BPF_HELPERS_H
3 4
@@ -38,6 +39,8 @@ static int (*bpf_clone_redirect)(void *ctx, int ifindex, int flags) =
38 (void *) BPF_FUNC_clone_redirect; 39 (void *) BPF_FUNC_clone_redirect;
39static int (*bpf_redirect)(int ifindex, int flags) = 40static int (*bpf_redirect)(int ifindex, int flags) =
40 (void *) BPF_FUNC_redirect; 41 (void *) BPF_FUNC_redirect;
42static int (*bpf_redirect_map)(void *map, int key, int flags) =
43 (void *) BPF_FUNC_redirect_map;
41static int (*bpf_perf_event_output)(void *ctx, void *map, 44static int (*bpf_perf_event_output)(void *ctx, void *map,
42 unsigned long long flags, void *data, 45 unsigned long long flags, void *data,
43 int size) = 46 int size) =
@@ -60,9 +63,26 @@ static unsigned long long (*bpf_get_prandom_u32)(void) =
60 (void *) BPF_FUNC_get_prandom_u32; 63 (void *) BPF_FUNC_get_prandom_u32;
61static int (*bpf_xdp_adjust_head)(void *ctx, int offset) = 64static int (*bpf_xdp_adjust_head)(void *ctx, int offset) =
62 (void *) BPF_FUNC_xdp_adjust_head; 65 (void *) BPF_FUNC_xdp_adjust_head;
66static int (*bpf_xdp_adjust_meta)(void *ctx, int offset) =
67 (void *) BPF_FUNC_xdp_adjust_meta;
63static int (*bpf_setsockopt)(void *ctx, int level, int optname, void *optval, 68static int (*bpf_setsockopt)(void *ctx, int level, int optname, void *optval,
64 int optlen) = 69 int optlen) =
65 (void *) BPF_FUNC_setsockopt; 70 (void *) BPF_FUNC_setsockopt;
71static int (*bpf_getsockopt)(void *ctx, int level, int optname, void *optval,
72 int optlen) =
73 (void *) BPF_FUNC_getsockopt;
74static int (*bpf_sk_redirect_map)(void *ctx, void *map, int key, int flags) =
75 (void *) BPF_FUNC_sk_redirect_map;
76static int (*bpf_sock_map_update)(void *map, void *key, void *value,
77 unsigned long long flags) =
78 (void *) BPF_FUNC_sock_map_update;
79static int (*bpf_perf_event_read_value)(void *map, unsigned long long flags,
80 void *buf, unsigned int buf_size) =
81 (void *) BPF_FUNC_perf_event_read_value;
82static int (*bpf_perf_prog_read_value)(void *ctx, void *buf,
83 unsigned int buf_size) =
84 (void *) BPF_FUNC_perf_prog_read_value;
85
66 86
67/* llvm builtin functions that eBPF C program may use to 87/* llvm builtin functions that eBPF C program may use to
68 * emit BPF_LD_ABS and BPF_LD_IND instructions 88 * emit BPF_LD_ABS and BPF_LD_IND instructions
@@ -85,6 +105,7 @@ struct bpf_map_def {
85 unsigned int max_entries; 105 unsigned int max_entries;
86 unsigned int map_flags; 106 unsigned int map_flags;
87 unsigned int inner_map_idx; 107 unsigned int inner_map_idx;
108 unsigned int numa_node;
88}; 109};
89 110
90static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) = 111static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) =
@@ -100,7 +121,47 @@ static int (*bpf_skb_under_cgroup)(void *ctx, void *map, int index) =
100static int (*bpf_skb_change_head)(void *, int len, int flags) = 121static int (*bpf_skb_change_head)(void *, int len, int flags) =
101 (void *) BPF_FUNC_skb_change_head; 122 (void *) BPF_FUNC_skb_change_head;
102 123
124/* Scan the ARCH passed in from ARCH env variable (see Makefile) */
125#if defined(__TARGET_ARCH_x86)
126 #define bpf_target_x86
127 #define bpf_target_defined
128#elif defined(__TARGET_ARCH_s930x)
129 #define bpf_target_s930x
130 #define bpf_target_defined
131#elif defined(__TARGET_ARCH_arm64)
132 #define bpf_target_arm64
133 #define bpf_target_defined
134#elif defined(__TARGET_ARCH_mips)
135 #define bpf_target_mips
136 #define bpf_target_defined
137#elif defined(__TARGET_ARCH_powerpc)
138 #define bpf_target_powerpc
139 #define bpf_target_defined
140#elif defined(__TARGET_ARCH_sparc)
141 #define bpf_target_sparc
142 #define bpf_target_defined
143#else
144 #undef bpf_target_defined
145#endif
146
147/* Fall back to what the compiler says */
148#ifndef bpf_target_defined
103#if defined(__x86_64__) 149#if defined(__x86_64__)
150 #define bpf_target_x86
151#elif defined(__s390x__)
152 #define bpf_target_s930x
153#elif defined(__aarch64__)
154 #define bpf_target_arm64
155#elif defined(__mips__)
156 #define bpf_target_mips
157#elif defined(__powerpc__)
158 #define bpf_target_powerpc
159#elif defined(__sparc__)
160 #define bpf_target_sparc
161#endif
162#endif
163
164#if defined(bpf_target_x86)
104 165
105#define PT_REGS_PARM1(x) ((x)->di) 166#define PT_REGS_PARM1(x) ((x)->di)
106#define PT_REGS_PARM2(x) ((x)->si) 167#define PT_REGS_PARM2(x) ((x)->si)
@@ -113,7 +174,7 @@ static int (*bpf_skb_change_head)(void *, int len, int flags) =
113#define PT_REGS_SP(x) ((x)->sp) 174#define PT_REGS_SP(x) ((x)->sp)
114#define PT_REGS_IP(x) ((x)->ip) 175#define PT_REGS_IP(x) ((x)->ip)
115 176
116#elif defined(__s390x__) 177#elif defined(bpf_target_s390x)
117 178
118#define PT_REGS_PARM1(x) ((x)->gprs[2]) 179#define PT_REGS_PARM1(x) ((x)->gprs[2])
119#define PT_REGS_PARM2(x) ((x)->gprs[3]) 180#define PT_REGS_PARM2(x) ((x)->gprs[3])
@@ -126,7 +187,7 @@ static int (*bpf_skb_change_head)(void *, int len, int flags) =
126#define PT_REGS_SP(x) ((x)->gprs[15]) 187#define PT_REGS_SP(x) ((x)->gprs[15])
127#define PT_REGS_IP(x) ((x)->psw.addr) 188#define PT_REGS_IP(x) ((x)->psw.addr)
128 189
129#elif defined(__aarch64__) 190#elif defined(bpf_target_arm64)
130 191
131#define PT_REGS_PARM1(x) ((x)->regs[0]) 192#define PT_REGS_PARM1(x) ((x)->regs[0])
132#define PT_REGS_PARM2(x) ((x)->regs[1]) 193#define PT_REGS_PARM2(x) ((x)->regs[1])
@@ -139,7 +200,7 @@ static int (*bpf_skb_change_head)(void *, int len, int flags) =
139#define PT_REGS_SP(x) ((x)->sp) 200#define PT_REGS_SP(x) ((x)->sp)
140#define PT_REGS_IP(x) ((x)->pc) 201#define PT_REGS_IP(x) ((x)->pc)
141 202
142#elif defined(__mips__) 203#elif defined(bpf_target_mips)
143 204
144#define PT_REGS_PARM1(x) ((x)->regs[4]) 205#define PT_REGS_PARM1(x) ((x)->regs[4])
145#define PT_REGS_PARM2(x) ((x)->regs[5]) 206#define PT_REGS_PARM2(x) ((x)->regs[5])
@@ -152,7 +213,7 @@ static int (*bpf_skb_change_head)(void *, int len, int flags) =
152#define PT_REGS_SP(x) ((x)->regs[29]) 213#define PT_REGS_SP(x) ((x)->regs[29])
153#define PT_REGS_IP(x) ((x)->cp0_epc) 214#define PT_REGS_IP(x) ((x)->cp0_epc)
154 215
155#elif defined(__powerpc__) 216#elif defined(bpf_target_powerpc)
156 217
157#define PT_REGS_PARM1(x) ((x)->gpr[3]) 218#define PT_REGS_PARM1(x) ((x)->gpr[3])
158#define PT_REGS_PARM2(x) ((x)->gpr[4]) 219#define PT_REGS_PARM2(x) ((x)->gpr[4])
@@ -163,7 +224,7 @@ static int (*bpf_skb_change_head)(void *, int len, int flags) =
163#define PT_REGS_SP(x) ((x)->sp) 224#define PT_REGS_SP(x) ((x)->sp)
164#define PT_REGS_IP(x) ((x)->nip) 225#define PT_REGS_IP(x) ((x)->nip)
165 226
166#elif defined(__sparc__) 227#elif defined(bpf_target_sparc)
167 228
168#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0]) 229#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0])
169#define PT_REGS_PARM2(x) ((x)->u_regs[UREG_I1]) 230#define PT_REGS_PARM2(x) ((x)->u_regs[UREG_I1])
@@ -173,6 +234,8 @@ static int (*bpf_skb_change_head)(void *, int len, int flags) =
173#define PT_REGS_RET(x) ((x)->u_regs[UREG_I7]) 234#define PT_REGS_RET(x) ((x)->u_regs[UREG_I7])
174#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0]) 235#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0])
175#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP]) 236#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP])
237
238/* Should this also be a bpf_target check for the sparc case? */
176#if defined(__arch64__) 239#if defined(__arch64__)
177#define PT_REGS_IP(x) ((x)->tpc) 240#define PT_REGS_IP(x) ((x)->tpc)
178#else 241#else
@@ -181,10 +244,10 @@ static int (*bpf_skb_change_head)(void *, int len, int flags) =
181 244
182#endif 245#endif
183 246
184#ifdef __powerpc__ 247#ifdef bpf_target_powerpc
185#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; }) 248#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; })
186#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP 249#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
187#elif defined(__sparc__) 250#elif bpf_target_sparc
188#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); }) 251#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); })
189#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP 252#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
190#else 253#else
diff --git a/tools/testing/selftests/bpf/bpf_util.h b/tools/testing/selftests/bpf/bpf_util.h
index 20ecbaa0d85d..d0811b3d6a6f 100644
--- a/tools/testing/selftests/bpf/bpf_util.h
+++ b/tools/testing/selftests/bpf/bpf_util.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __BPF_UTIL__ 2#ifndef __BPF_UTIL__
2#define __BPF_UTIL__ 3#define __BPF_UTIL__
3 4
@@ -12,6 +13,7 @@ static inline unsigned int bpf_num_possible_cpus(void)
12 unsigned int start, end, possible_cpus = 0; 13 unsigned int start, end, possible_cpus = 0;
13 char buff[128]; 14 char buff[128];
14 FILE *fp; 15 FILE *fp;
16 int n;
15 17
16 fp = fopen(fcpu, "r"); 18 fp = fopen(fcpu, "r");
17 if (!fp) { 19 if (!fp) {
@@ -20,17 +22,17 @@ static inline unsigned int bpf_num_possible_cpus(void)
20 } 22 }
21 23
22 while (fgets(buff, sizeof(buff), fp)) { 24 while (fgets(buff, sizeof(buff), fp)) {
23 if (sscanf(buff, "%u-%u", &start, &end) == 2) { 25 n = sscanf(buff, "%u-%u", &start, &end);
24 possible_cpus = start == 0 ? end + 1 : 0; 26 if (n == 0) {
25 break; 27 printf("Failed to retrieve # possible CPUs!\n");
28 exit(1);
29 } else if (n == 1) {
30 end = start;
26 } 31 }
32 possible_cpus = start == 0 ? end + 1 : 0;
33 break;
27 } 34 }
28
29 fclose(fp); 35 fclose(fp);
30 if (!possible_cpus) {
31 printf("Failed to retrieve # possible CPUs!\n");
32 exit(1);
33 }
34 36
35 return possible_cpus; 37 return possible_cpus;
36} 38}
diff --git a/tools/testing/selftests/bpf/cgroup_helpers.c b/tools/testing/selftests/bpf/cgroup_helpers.c
new file mode 100644
index 000000000000..f3bca3ade0f3
--- /dev/null
+++ b/tools/testing/selftests/bpf/cgroup_helpers.c
@@ -0,0 +1,178 @@
1// SPDX-License-Identifier: GPL-2.0
2#define _GNU_SOURCE
3#include <sched.h>
4#include <sys/mount.h>
5#include <sys/stat.h>
6#include <sys/types.h>
7#include <linux/limits.h>
8#include <stdio.h>
9#include <linux/sched.h>
10#include <fcntl.h>
11#include <unistd.h>
12#include <ftw.h>
13
14
15#include "cgroup_helpers.h"
16
17/*
18 * To avoid relying on the system setup, when setup_cgroup_env is called
19 * we create a new mount namespace, and cgroup namespace. The cgroup2
20 * root is mounted at CGROUP_MOUNT_PATH
21 *
22 * Unfortunately, most people don't have cgroupv2 enabled at this point in time.
23 * It's easier to create our own mount namespace and manage it ourselves.
24 *
25 * We assume /mnt exists.
26 */
27
28#define WALK_FD_LIMIT 16
29#define CGROUP_MOUNT_PATH "/mnt"
30#define CGROUP_WORK_DIR "/cgroup-test-work-dir"
31#define format_cgroup_path(buf, path) \
32 snprintf(buf, sizeof(buf), "%s%s%s", CGROUP_MOUNT_PATH, \
33 CGROUP_WORK_DIR, path)
34
35/**
36 * setup_cgroup_environment() - Setup the cgroup environment
37 *
38 * After calling this function, cleanup_cgroup_environment should be called
39 * once testing is complete.
40 *
41 * This function will print an error to stderr and return 1 if it is unable
42 * to setup the cgroup environment. If setup is successful, 0 is returned.
43 */
44int setup_cgroup_environment(void)
45{
46 char cgroup_workdir[PATH_MAX + 1];
47
48 format_cgroup_path(cgroup_workdir, "");
49
50 if (unshare(CLONE_NEWNS)) {
51 log_err("unshare");
52 return 1;
53 }
54
55 if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL)) {
56 log_err("mount fakeroot");
57 return 1;
58 }
59
60 if (mount("none", CGROUP_MOUNT_PATH, "cgroup2", 0, NULL) && errno != EBUSY) {
61 log_err("mount cgroup2");
62 return 1;
63 }
64
65 /* Cleanup existing failed runs, now that the environment is setup */
66 cleanup_cgroup_environment();
67
68 if (mkdir(cgroup_workdir, 0777) && errno != EEXIST) {
69 log_err("mkdir cgroup work dir");
70 return 1;
71 }
72
73 return 0;
74}
75
76static int nftwfunc(const char *filename, const struct stat *statptr,
77 int fileflags, struct FTW *pfwt)
78{
79 if ((fileflags & FTW_D) && rmdir(filename))
80 log_err("Removing cgroup: %s", filename);
81 return 0;
82}
83
84
85static int join_cgroup_from_top(char *cgroup_path)
86{
87 char cgroup_procs_path[PATH_MAX + 1];
88 pid_t pid = getpid();
89 int fd, rc = 0;
90
91 snprintf(cgroup_procs_path, sizeof(cgroup_procs_path),
92 "%s/cgroup.procs", cgroup_path);
93
94 fd = open(cgroup_procs_path, O_WRONLY);
95 if (fd < 0) {
96 log_err("Opening Cgroup Procs: %s", cgroup_procs_path);
97 return 1;
98 }
99
100 if (dprintf(fd, "%d\n", pid) < 0) {
101 log_err("Joining Cgroup");
102 rc = 1;
103 }
104
105 close(fd);
106 return rc;
107}
108
109/**
110 * join_cgroup() - Join a cgroup
111 * @path: The cgroup path, relative to the workdir, to join
112 *
113 * This function expects a cgroup to already be created, relative to the cgroup
114 * work dir, and it joins it. For example, passing "/my-cgroup" as the path
115 * would actually put the calling process into the cgroup
116 * "/cgroup-test-work-dir/my-cgroup"
117 *
118 * On success, it returns 0, otherwise on failure it returns 1.
119 */
120int join_cgroup(char *path)
121{
122 char cgroup_path[PATH_MAX + 1];
123
124 format_cgroup_path(cgroup_path, path);
125 return join_cgroup_from_top(cgroup_path);
126}
127
128/**
129 * cleanup_cgroup_environment() - Cleanup Cgroup Testing Environment
130 *
131 * This is an idempotent function to delete all temporary cgroups that
132 * have been created during the test, including the cgroup testing work
133 * directory.
134 *
135 * At call time, it moves the calling process to the root cgroup, and then
136 * runs the deletion process. It is idempotent, and should not fail, unless
137 * a process is lingering.
138 *
139 * On failure, it will print an error to stderr, and try to continue.
140 */
141void cleanup_cgroup_environment(void)
142{
143 char cgroup_workdir[PATH_MAX + 1];
144
145 format_cgroup_path(cgroup_workdir, "");
146 join_cgroup_from_top(CGROUP_MOUNT_PATH);
147 nftw(cgroup_workdir, nftwfunc, WALK_FD_LIMIT, FTW_DEPTH | FTW_MOUNT);
148}
149
150/**
151 * create_and_get_cgroup() - Create a cgroup, relative to workdir, and get the FD
152 * @path: The cgroup path, relative to the workdir, to join
153 *
154 * This function creates a cgroup under the top level workdir and returns the
155 * file descriptor. It is idempotent.
156 *
157 * On success, it returns the file descriptor. On failure it returns 0.
158 * If there is a failure, it prints the error to stderr.
159 */
160int create_and_get_cgroup(char *path)
161{
162 char cgroup_path[PATH_MAX + 1];
163 int fd;
164
165 format_cgroup_path(cgroup_path, path);
166 if (mkdir(cgroup_path, 0777) && errno != EEXIST) {
167 log_err("mkdiring cgroup %s .. %s", path, cgroup_path);
168 return 0;
169 }
170
171 fd = open(cgroup_path, O_RDONLY);
172 if (fd < 0) {
173 log_err("Opening Cgroup");
174 return 0;
175 }
176
177 return fd;
178}
diff --git a/tools/testing/selftests/bpf/cgroup_helpers.h b/tools/testing/selftests/bpf/cgroup_helpers.h
new file mode 100644
index 000000000000..06485e0002b3
--- /dev/null
+++ b/tools/testing/selftests/bpf/cgroup_helpers.h
@@ -0,0 +1,17 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef __CGROUP_HELPERS_H
3#define __CGROUP_HELPERS_H
4#include <errno.h>
5#include <string.h>
6
7#define clean_errno() (errno == 0 ? "None" : strerror(errno))
8#define log_err(MSG, ...) fprintf(stderr, "(%s:%d: errno: %s) " MSG "\n", \
9 __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
10
11
12int create_and_get_cgroup(char *path);
13int join_cgroup(char *path);
14int setup_cgroup_environment(void);
15void cleanup_cgroup_environment(void);
16
17#endif
diff --git a/tools/testing/selftests/bpf/dev_cgroup.c b/tools/testing/selftests/bpf/dev_cgroup.c
new file mode 100644
index 000000000000..ce41a3475f27
--- /dev/null
+++ b/tools/testing/selftests/bpf/dev_cgroup.c
@@ -0,0 +1,60 @@
1/* Copyright (c) 2017 Facebook
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
8#include <linux/bpf.h>
9#include <linux/version.h>
10#include "bpf_helpers.h"
11
12SEC("cgroup/dev")
13int bpf_prog1(struct bpf_cgroup_dev_ctx *ctx)
14{
15 short type = ctx->access_type & 0xFFFF;
16#ifdef DEBUG
17 short access = ctx->access_type >> 16;
18 char fmt[] = " %d:%d \n";
19
20 switch (type) {
21 case BPF_DEVCG_DEV_BLOCK:
22 fmt[0] = 'b';
23 break;
24 case BPF_DEVCG_DEV_CHAR:
25 fmt[0] = 'c';
26 break;
27 default:
28 fmt[0] = '?';
29 break;
30 }
31
32 if (access & BPF_DEVCG_ACC_READ)
33 fmt[8] = 'r';
34
35 if (access & BPF_DEVCG_ACC_WRITE)
36 fmt[9] = 'w';
37
38 if (access & BPF_DEVCG_ACC_MKNOD)
39 fmt[10] = 'm';
40
41 bpf_trace_printk(fmt, sizeof(fmt), ctx->major, ctx->minor);
42#endif
43
44 /* Allow access to /dev/zero and /dev/random.
45 * Forbid everything else.
46 */
47 if (ctx->major != 1 || type != BPF_DEVCG_DEV_CHAR)
48 return 0;
49
50 switch (ctx->minor) {
51 case 5: /* 1:5 /dev/zero */
52 case 9: /* 1:9 /dev/urandom */
53 return 1;
54 }
55
56 return 0;
57}
58
59char _license[] SEC("license") = "GPL";
60__u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/testing/selftests/bpf/include/uapi/linux/types.h b/tools/testing/selftests/bpf/include/uapi/linux/types.h
index 51841848fbfe..91fa51a9c31d 100644
--- a/tools/testing/selftests/bpf/include/uapi/linux/types.h
+++ b/tools/testing/selftests/bpf/include/uapi/linux/types.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _UAPI_LINUX_TYPES_H 2#ifndef _UAPI_LINUX_TYPES_H
2#define _UAPI_LINUX_TYPES_H 3#define _UAPI_LINUX_TYPES_H
3 4
diff --git a/tools/testing/selftests/bpf/sockmap_parse_prog.c b/tools/testing/selftests/bpf/sockmap_parse_prog.c
new file mode 100644
index 000000000000..a1dec2b6d9c5
--- /dev/null
+++ b/tools/testing/selftests/bpf/sockmap_parse_prog.c
@@ -0,0 +1,35 @@
1#include <linux/bpf.h>
2#include "bpf_helpers.h"
3#include "bpf_util.h"
4#include "bpf_endian.h"
5
6int _version SEC("version") = 1;
7
8#define bpf_printk(fmt, ...) \
9({ \
10 char ____fmt[] = fmt; \
11 bpf_trace_printk(____fmt, sizeof(____fmt), \
12 ##__VA_ARGS__); \
13})
14
15SEC("sk_skb1")
16int bpf_prog1(struct __sk_buff *skb)
17{
18 void *data_end = (void *)(long) skb->data_end;
19 void *data = (void *)(long) skb->data;
20 __u32 lport = skb->local_port;
21 __u32 rport = skb->remote_port;
22 __u8 *d = data;
23
24 if (data + 10 > data_end)
25 return skb->len;
26
27 /* This write/read is a bit pointless but tests the verifier and
28 * strparser handler for read/write pkt data and access into sk
29 * fields.
30 */
31 d[7] = 1;
32 return skb->len;
33}
34
35char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/sockmap_verdict_prog.c b/tools/testing/selftests/bpf/sockmap_verdict_prog.c
new file mode 100644
index 000000000000..d7bea972cb21
--- /dev/null
+++ b/tools/testing/selftests/bpf/sockmap_verdict_prog.c
@@ -0,0 +1,66 @@
1#include <linux/bpf.h>
2#include "bpf_helpers.h"
3#include "bpf_util.h"
4#include "bpf_endian.h"
5
6int _version SEC("version") = 1;
7
8#define bpf_printk(fmt, ...) \
9({ \
10 char ____fmt[] = fmt; \
11 bpf_trace_printk(____fmt, sizeof(____fmt), \
12 ##__VA_ARGS__); \
13})
14
15struct bpf_map_def SEC("maps") sock_map_rx = {
16 .type = BPF_MAP_TYPE_SOCKMAP,
17 .key_size = sizeof(int),
18 .value_size = sizeof(int),
19 .max_entries = 20,
20};
21
22struct bpf_map_def SEC("maps") sock_map_tx = {
23 .type = BPF_MAP_TYPE_SOCKMAP,
24 .key_size = sizeof(int),
25 .value_size = sizeof(int),
26 .max_entries = 20,
27};
28
29struct bpf_map_def SEC("maps") sock_map_break = {
30 .type = BPF_MAP_TYPE_ARRAY,
31 .key_size = sizeof(int),
32 .value_size = sizeof(int),
33 .max_entries = 20,
34};
35
36SEC("sk_skb2")
37int bpf_prog2(struct __sk_buff *skb)
38{
39 void *data_end = (void *)(long) skb->data_end;
40 void *data = (void *)(long) skb->data;
41 __u32 lport = skb->local_port;
42 __u32 rport = skb->remote_port;
43 __u8 *d = data;
44 __u8 sk, map;
45
46 if (data + 8 > data_end)
47 return SK_DROP;
48
49 map = d[0];
50 sk = d[1];
51
52 d[0] = 0xd;
53 d[1] = 0xe;
54 d[2] = 0xa;
55 d[3] = 0xd;
56 d[4] = 0xb;
57 d[5] = 0xe;
58 d[6] = 0xe;
59 d[7] = 0xf;
60
61 if (!map)
62 return bpf_sk_redirect_map(skb, &sock_map_rx, sk, 0);
63 return bpf_sk_redirect_map(skb, &sock_map_tx, sk, 0);
64}
65
66char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/test_align.c b/tools/testing/selftests/bpf/test_align.c
index 29793694cbc7..8591c89c0828 100644
--- a/tools/testing/selftests/bpf/test_align.c
+++ b/tools/testing/selftests/bpf/test_align.c
@@ -27,6 +27,11 @@
27#define MAX_INSNS 512 27#define MAX_INSNS 512
28#define MAX_MATCHES 16 28#define MAX_MATCHES 16
29 29
30struct bpf_reg_match {
31 unsigned int line;
32 const char *match;
33};
34
30struct bpf_align_test { 35struct bpf_align_test {
31 const char *descr; 36 const char *descr;
32 struct bpf_insn insns[MAX_INSNS]; 37 struct bpf_insn insns[MAX_INSNS];
@@ -36,10 +41,14 @@ struct bpf_align_test {
36 REJECT 41 REJECT
37 } result; 42 } result;
38 enum bpf_prog_type prog_type; 43 enum bpf_prog_type prog_type;
39 const char *matches[MAX_MATCHES]; 44 /* Matches must be in order of increasing line */
45 struct bpf_reg_match matches[MAX_MATCHES];
40}; 46};
41 47
42static struct bpf_align_test tests[] = { 48static struct bpf_align_test tests[] = {
49 /* Four tests of known constants. These aren't staggeringly
50 * interesting since we track exact values now.
51 */
43 { 52 {
44 .descr = "mov", 53 .descr = "mov",
45 .insns = { 54 .insns = {
@@ -53,11 +62,13 @@ static struct bpf_align_test tests[] = {
53 }, 62 },
54 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 63 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
55 .matches = { 64 .matches = {
56 "1: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp", 65 {1, "R1=ctx(id=0,off=0,imm=0)"},
57 "2: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp", 66 {1, "R10=fp0"},
58 "3: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp", 67 {1, "R3=inv2"},
59 "4: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp", 68 {2, "R3=inv4"},
60 "5: R1=ctx R3=imm32,min_value=32,max_value=32,min_align=32 R10=fp", 69 {3, "R3=inv8"},
70 {4, "R3=inv16"},
71 {5, "R3=inv32"},
61 }, 72 },
62 }, 73 },
63 { 74 {
@@ -79,17 +90,19 @@ static struct bpf_align_test tests[] = {
79 }, 90 },
80 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 91 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
81 .matches = { 92 .matches = {
82 "1: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp", 93 {1, "R1=ctx(id=0,off=0,imm=0)"},
83 "2: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp", 94 {1, "R10=fp0"},
84 "3: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp", 95 {1, "R3=inv1"},
85 "4: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp", 96 {2, "R3=inv2"},
86 "5: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp", 97 {3, "R3=inv4"},
87 "6: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp", 98 {4, "R3=inv8"},
88 "7: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm32,min_value=32,max_value=32,min_align=32 R10=fp", 99 {5, "R3=inv16"},
89 "8: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm16,min_value=16,max_value=16,min_align=16 R10=fp", 100 {6, "R3=inv1"},
90 "9: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp", 101 {7, "R4=inv32"},
91 "10: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm4,min_value=4,max_value=4,min_align=4 R10=fp", 102 {8, "R4=inv16"},
92 "11: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm2,min_value=2,max_value=2,min_align=2 R10=fp", 103 {9, "R4=inv8"},
104 {10, "R4=inv4"},
105 {11, "R4=inv2"},
93 }, 106 },
94 }, 107 },
95 { 108 {
@@ -106,12 +119,14 @@ static struct bpf_align_test tests[] = {
106 }, 119 },
107 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 120 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
108 .matches = { 121 .matches = {
109 "1: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp", 122 {1, "R1=ctx(id=0,off=0,imm=0)"},
110 "2: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=4 R10=fp", 123 {1, "R10=fp0"},
111 "3: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R10=fp", 124 {1, "R3=inv4"},
112 "4: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp", 125 {2, "R3=inv8"},
113 "5: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm12,min_value=12,max_value=12,min_align=4 R10=fp", 126 {3, "R3=inv10"},
114 "6: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm14,min_value=14,max_value=14,min_align=2 R10=fp", 127 {4, "R4=inv8"},
128 {5, "R4=inv12"},
129 {6, "R4=inv14"},
115 }, 130 },
116 }, 131 },
117 { 132 {
@@ -126,13 +141,16 @@ static struct bpf_align_test tests[] = {
126 }, 141 },
127 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 142 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
128 .matches = { 143 .matches = {
129 "1: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp", 144 {1, "R1=ctx(id=0,off=0,imm=0)"},
130 "2: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp", 145 {1, "R10=fp0"},
131 "3: R1=ctx R3=imm14,min_value=14,max_value=14,min_align=2 R10=fp", 146 {1, "R3=inv7"},
132 "4: R1=ctx R3=imm56,min_value=56,max_value=56,min_align=4 R10=fp", 147 {2, "R3=inv7"},
148 {3, "R3=inv14"},
149 {4, "R3=inv56"},
133 }, 150 },
134 }, 151 },
135 152
153 /* Tests using unknown values */
136#define PREP_PKT_POINTERS \ 154#define PREP_PKT_POINTERS \
137 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, \ 155 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, \
138 offsetof(struct __sk_buff, data)), \ 156 offsetof(struct __sk_buff, data)), \
@@ -166,17 +184,19 @@ static struct bpf_align_test tests[] = {
166 }, 184 },
167 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 185 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
168 .matches = { 186 .matches = {
169 "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp", 187 {7, "R0=pkt(id=0,off=8,r=8,imm=0)"},
170 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv55,min_align=2 R10=fp", 188 {7, "R3=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
171 "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv54,min_align=4 R10=fp", 189 {8, "R3=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
172 "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv53,min_align=8 R10=fp", 190 {9, "R3=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
173 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv52,min_align=16 R10=fp", 191 {10, "R3=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
174 "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv56 R10=fp", 192 {11, "R3=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
175 "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv51,min_align=32 R10=fp", 193 {18, "R3=pkt_end(id=0,off=0,imm=0)"},
176 "20: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv52,min_align=16 R10=fp", 194 {18, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
177 "21: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv53,min_align=8 R10=fp", 195 {19, "R4=inv(id=0,umax_value=8160,var_off=(0x0; 0x1fe0))"},
178 "22: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv54,min_align=4 R10=fp", 196 {20, "R4=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
179 "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv55,min_align=2 R10=fp", 197 {21, "R4=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
198 {22, "R4=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
199 {23, "R4=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
180 }, 200 },
181 }, 201 },
182 { 202 {
@@ -197,16 +217,16 @@ static struct bpf_align_test tests[] = {
197 }, 217 },
198 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 218 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
199 .matches = { 219 .matches = {
200 "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp", 220 {7, "R3=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
201 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp", 221 {8, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
202 "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv55,min_align=1 R10=fp", 222 {9, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
203 "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp", 223 {10, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
204 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv54,min_align=2 R10=fp", 224 {11, "R4=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
205 "12: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp", 225 {12, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
206 "13: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv53,min_align=4 R10=fp", 226 {13, "R4=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
207 "14: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp", 227 {14, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
208 "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv52,min_align=8 R10=fp", 228 {15, "R4=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
209 "16: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv50,min_align=8 R10=fp" 229 {16, "R4=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
210 }, 230 },
211 }, 231 },
212 { 232 {
@@ -237,12 +257,14 @@ static struct bpf_align_test tests[] = {
237 }, 257 },
238 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 258 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
239 .matches = { 259 .matches = {
240 "4: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=0,r=0) R10=fp", 260 {4, "R5=pkt(id=0,off=0,r=0,imm=0)"},
241 "5: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=14,r=0) R10=fp", 261 {5, "R5=pkt(id=0,off=14,r=0,imm=0)"},
242 "6: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R4=pkt(id=0,off=14,r=0) R5=pkt(id=0,off=14,r=0) R10=fp", 262 {6, "R4=pkt(id=0,off=14,r=0,imm=0)"},
243 "10: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv56 R5=pkt(id=0,off=14,r=18) R10=fp", 263 {10, "R2=pkt(id=0,off=0,r=18,imm=0)"},
244 "14: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp", 264 {10, "R5=pkt(id=0,off=14,r=18,imm=0)"},
245 "15: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp", 265 {10, "R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
266 {14, "R4=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"},
267 {15, "R4=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"},
246 }, 268 },
247 }, 269 },
248 { 270 {
@@ -297,62 +319,286 @@ static struct bpf_align_test tests[] = {
297 /* Calculated offset in R6 has unknown value, but known 319 /* Calculated offset in R6 has unknown value, but known
298 * alignment of 4. 320 * alignment of 4.
299 */ 321 */
300 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R6=inv54,min_align=4 R10=fp", 322 {8, "R2=pkt(id=0,off=0,r=8,imm=0)"},
301 323 {8, "R6=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
302 /* Offset is added to packet pointer R5, resulting in known 324 /* Offset is added to packet pointer R5, resulting in
303 * auxiliary alignment and offset. 325 * known fixed offset, and variable offset from R6.
304 */ 326 */
305 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R5=pkt(id=1,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp", 327 {11, "R5=pkt(id=1,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
306
307 /* At the time the word size load is performed from R5, 328 /* At the time the word size load is performed from R5,
308 * it's total offset is NET_IP_ALIGN + reg->off (0) + 329 * it's total offset is NET_IP_ALIGN + reg->off (0) +
309 * reg->aux_off (14) which is 16. Then the variable 330 * reg->aux_off (14) which is 16. Then the variable
310 * offset is considered using reg->aux_off_align which 331 * offset is considered using reg->aux_off_align which
311 * is 4 and meets the load's requirements. 332 * is 4 and meets the load's requirements.
312 */ 333 */
313 "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=1,off=4,r=4),aux_off=14,aux_off_align=4 R5=pkt(id=1,off=0,r=4),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp", 334 {15, "R4=pkt(id=1,off=18,r=18,umax_value=1020,var_off=(0x0; 0x3fc))"},
314 335 {15, "R5=pkt(id=1,off=14,r=18,umax_value=1020,var_off=(0x0; 0x3fc))"},
315
316 /* Variable offset is added to R5 packet pointer, 336 /* Variable offset is added to R5 packet pointer,
317 * resulting in auxiliary alignment of 4. 337 * resulting in auxiliary alignment of 4.
318 */ 338 */
319 "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=0,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp", 339 {18, "R5=pkt(id=2,off=0,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
320
321 /* Constant offset is added to R5, resulting in 340 /* Constant offset is added to R5, resulting in
322 * reg->off of 14. 341 * reg->off of 14.
323 */ 342 */
324 "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=14,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp", 343 {19, "R5=pkt(id=2,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
325
326 /* At the time the word size load is performed from R5, 344 /* At the time the word size load is performed from R5,
327 * it's total offset is NET_IP_ALIGN + reg->off (14) which 345 * its total fixed offset is NET_IP_ALIGN + reg->off
328 * is 16. Then the variable offset is considered using 346 * (14) which is 16. Then the variable offset is 4-byte
329 * reg->aux_off_align which is 4 and meets the load's 347 * aligned, so the total offset is 4-byte aligned and
330 * requirements. 348 * meets the load's requirements.
331 */ 349 */
332 "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=2,off=18,r=18),aux_off_align=4 R5=pkt(id=2,off=14,r=18),aux_off_align=4 R6=inv54,min_align=4 R10=fp", 350 {23, "R4=pkt(id=2,off=18,r=18,umax_value=1020,var_off=(0x0; 0x3fc))"},
333 351 {23, "R5=pkt(id=2,off=14,r=18,umax_value=1020,var_off=(0x0; 0x3fc))"},
334 /* Constant offset is added to R5 packet pointer, 352 /* Constant offset is added to R5 packet pointer,
335 * resulting in reg->off value of 14. 353 * resulting in reg->off value of 14.
336 */ 354 */
337 "26: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=0,off=14,r=8) R6=inv54,min_align=4 R10=fp", 355 {26, "R5=pkt(id=0,off=14,r=8"},
338 /* Variable offset is added to R5, resulting in an 356 /* Variable offset is added to R5, resulting in a
339 * auxiliary offset of 14, and an auxiliary alignment of 4. 357 * variable offset of (4n).
340 */ 358 */
341 "27: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp", 359 {27, "R5=pkt(id=3,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
342 /* Constant is added to R5 again, setting reg->off to 4. */ 360 /* Constant is added to R5 again, setting reg->off to 18. */
343 "28: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=4,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp", 361 {28, "R5=pkt(id=3,off=18,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
344 /* And once more we add a variable, which causes an accumulation 362 /* And once more we add a variable; resulting var_off
345 * of reg->off into reg->aux_off_align, with resulting value of 363 * is still (4n), fixed offset is not changed.
346 * 18. The auxiliary alignment stays at 4. 364 * Also, we create a new reg->id.
347 */ 365 */
348 "29: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=4,off=0,r=0),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp", 366 {29, "R5=pkt(id=4,off=18,r=0,umax_value=2040,var_off=(0x0; 0x7fc))"},
349 /* At the time the word size load is performed from R5, 367 /* At the time the word size load is performed from R5,
350 * it's total offset is NET_IP_ALIGN + reg->off (0) + 368 * its total fixed offset is NET_IP_ALIGN + reg->off (18)
351 * reg->aux_off (18) which is 20. Then the variable offset 369 * which is 20. Then the variable offset is (4n), so
352 * is considered using reg->aux_off_align which is 4 and meets 370 * the total offset is 4-byte aligned and meets the
353 * the load's requirements. 371 * load's requirements.
372 */
373 {33, "R4=pkt(id=4,off=22,r=22,umax_value=2040,var_off=(0x0; 0x7fc))"},
374 {33, "R5=pkt(id=4,off=18,r=22,umax_value=2040,var_off=(0x0; 0x7fc))"},
375 },
376 },
377 {
378 .descr = "packet variable offset 2",
379 .insns = {
380 /* Create an unknown offset, (4n+2)-aligned */
381 LOAD_UNKNOWN(BPF_REG_6),
382 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
383 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 14),
384 /* Add it to the packet pointer */
385 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
386 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
387 /* Check bounds and perform a read */
388 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
389 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
390 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
391 BPF_EXIT_INSN(),
392 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
393 /* Make a (4n) offset from the value we just read */
394 BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 0xff),
395 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
396 /* Add it to the packet pointer */
397 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
398 /* Check bounds and perform a read */
399 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
400 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
401 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
402 BPF_EXIT_INSN(),
403 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
404 BPF_MOV64_IMM(BPF_REG_0, 0),
405 BPF_EXIT_INSN(),
406 },
407 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
408 .matches = {
409 /* Calculated offset in R6 has unknown value, but known
410 * alignment of 4.
411 */
412 {8, "R2=pkt(id=0,off=0,r=8,imm=0)"},
413 {8, "R6=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
414 /* Adding 14 makes R6 be (4n+2) */
415 {9, "R6=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
416 /* Packet pointer has (4n+2) offset */
417 {11, "R5=pkt(id=1,off=0,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
418 {13, "R4=pkt(id=1,off=4,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
419 /* At the time the word size load is performed from R5,
420 * its total fixed offset is NET_IP_ALIGN + reg->off (0)
421 * which is 2. Then the variable offset is (4n+2), so
422 * the total offset is 4-byte aligned and meets the
423 * load's requirements.
424 */
425 {15, "R5=pkt(id=1,off=0,r=4,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
426 /* Newly read value in R6 was shifted left by 2, so has
427 * known alignment of 4.
428 */
429 {18, "R6=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
430 /* Added (4n) to packet pointer's (4n+2) var_off, giving
431 * another (4n+2).
432 */
433 {19, "R5=pkt(id=2,off=0,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc))"},
434 {21, "R4=pkt(id=2,off=4,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc))"},
435 /* At the time the word size load is performed from R5,
436 * its total fixed offset is NET_IP_ALIGN + reg->off (0)
437 * which is 2. Then the variable offset is (4n+2), so
438 * the total offset is 4-byte aligned and meets the
439 * load's requirements.
440 */
441 {23, "R5=pkt(id=2,off=0,r=4,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc))"},
442 },
443 },
444 {
445 .descr = "dubious pointer arithmetic",
446 .insns = {
447 PREP_PKT_POINTERS,
448 BPF_MOV64_IMM(BPF_REG_0, 0),
449 /* ptr & const => unknown & const */
450 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
451 BPF_ALU64_IMM(BPF_AND, BPF_REG_5, 0x40),
452 /* ptr << const => unknown << const */
453 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
454 BPF_ALU64_IMM(BPF_LSH, BPF_REG_5, 2),
455 /* We have a (4n) value. Let's make a packet offset
456 * out of it. First add 14, to make it a (4n+2)
457 */
458 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
459 /* Then make sure it's nonnegative */
460 BPF_JMP_IMM(BPF_JSGE, BPF_REG_5, 0, 1),
461 BPF_EXIT_INSN(),
462 /* Add it to packet pointer */
463 BPF_MOV64_REG(BPF_REG_6, BPF_REG_2),
464 BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_5),
465 /* Check bounds and perform a read */
466 BPF_MOV64_REG(BPF_REG_4, BPF_REG_6),
467 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
468 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
469 BPF_EXIT_INSN(),
470 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_6, 0),
471 BPF_EXIT_INSN(),
472 },
473 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
474 .result = REJECT,
475 .matches = {
476 {4, "R5=pkt(id=0,off=0,r=0,imm=0)"},
477 /* ptr & 0x40 == either 0 or 0x40 */
478 {5, "R5=inv(id=0,umax_value=64,var_off=(0x0; 0x40))"},
479 /* ptr << 2 == unknown, (4n) */
480 {7, "R5=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc))"},
481 /* (4n) + 14 == (4n+2). We blow our bounds, because
482 * the add could overflow.
483 */
484 {8, "R5=inv(id=0,var_off=(0x2; 0xfffffffffffffffc))"},
485 /* Checked s>=0 */
486 {10, "R5=inv(id=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
487 /* packet pointer + nonnegative (4n+2) */
488 {12, "R6=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
489 {14, "R4=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
490 /* NET_IP_ALIGN + (4n+2) == (4n), alignment is fine.
491 * We checked the bounds, but it might have been able
492 * to overflow if the packet pointer started in the
493 * upper half of the address space.
494 * So we did not get a 'range' on R6, and the access
495 * attempt will fail.
496 */
497 {16, "R6=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
498 }
499 },
500 {
501 .descr = "variable subtraction",
502 .insns = {
503 /* Create an unknown offset, (4n+2)-aligned */
504 LOAD_UNKNOWN(BPF_REG_6),
505 BPF_MOV64_REG(BPF_REG_7, BPF_REG_6),
506 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
507 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 14),
508 /* Create another unknown, (4n)-aligned, and subtract
509 * it from the first one
510 */
511 BPF_ALU64_IMM(BPF_LSH, BPF_REG_7, 2),
512 BPF_ALU64_REG(BPF_SUB, BPF_REG_6, BPF_REG_7),
513 /* Bounds-check the result */
514 BPF_JMP_IMM(BPF_JSGE, BPF_REG_6, 0, 1),
515 BPF_EXIT_INSN(),
516 /* Add it to the packet pointer */
517 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
518 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
519 /* Check bounds and perform a read */
520 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
521 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
522 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
523 BPF_EXIT_INSN(),
524 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
525 BPF_EXIT_INSN(),
526 },
527 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
528 .matches = {
529 /* Calculated offset in R6 has unknown value, but known
530 * alignment of 4.
531 */
532 {7, "R2=pkt(id=0,off=0,r=8,imm=0)"},
533 {9, "R6=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
534 /* Adding 14 makes R6 be (4n+2) */
535 {10, "R6=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
536 /* New unknown value in R7 is (4n) */
537 {11, "R7=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
538 /* Subtracting it from R6 blows our unsigned bounds */
539 {12, "R6=inv(id=0,smin_value=-1006,smax_value=1034,var_off=(0x2; 0xfffffffffffffffc))"},
540 /* Checked s>= 0 */
541 {14, "R6=inv(id=0,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},
542 /* At the time the word size load is performed from R5,
543 * its total fixed offset is NET_IP_ALIGN + reg->off (0)
544 * which is 2. Then the variable offset is (4n+2), so
545 * the total offset is 4-byte aligned and meets the
546 * load's requirements.
547 */
548 {20, "R5=pkt(id=1,off=0,r=4,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},
549 },
550 },
551 {
552 .descr = "pointer variable subtraction",
553 .insns = {
554 /* Create an unknown offset, (4n+2)-aligned and bounded
555 * to [14,74]
556 */
557 LOAD_UNKNOWN(BPF_REG_6),
558 BPF_MOV64_REG(BPF_REG_7, BPF_REG_6),
559 BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 0xf),
560 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
561 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 14),
562 /* Subtract it from the packet pointer */
563 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
564 BPF_ALU64_REG(BPF_SUB, BPF_REG_5, BPF_REG_6),
565 /* Create another unknown, (4n)-aligned and >= 74.
566 * That in fact means >= 76, since 74 % 4 == 2
354 */ 567 */
355 "33: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=4,off=4,r=4),aux_off=18,aux_off_align=4 R5=pkt(id=4,off=0,r=4),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp", 568 BPF_ALU64_IMM(BPF_LSH, BPF_REG_7, 2),
569 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 76),
570 /* Add it to the packet pointer */
571 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_7),
572 /* Check bounds and perform a read */
573 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
574 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
575 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
576 BPF_EXIT_INSN(),
577 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
578 BPF_EXIT_INSN(),
579 },
580 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
581 .matches = {
582 /* Calculated offset in R6 has unknown value, but known
583 * alignment of 4.
584 */
585 {7, "R2=pkt(id=0,off=0,r=8,imm=0)"},
586 {10, "R6=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"},
587 /* Adding 14 makes R6 be (4n+2) */
588 {11, "R6=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"},
589 /* Subtracting from packet pointer overflows ubounds */
590 {13, "R5=pkt(id=1,off=0,r=8,umin_value=18446744073709551542,umax_value=18446744073709551602,var_off=(0xffffffffffffff82; 0x7c))"},
591 /* New unknown value in R7 is (4n), >= 76 */
592 {15, "R7=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"},
593 /* Adding it to packet pointer gives nice bounds again */
594 {16, "R5=pkt(id=2,off=0,r=0,umin_value=2,umax_value=1082,var_off=(0x2; 0x7fc))"},
595 /* At the time the word size load is performed from R5,
596 * its total fixed offset is NET_IP_ALIGN + reg->off (0)
597 * which is 2. Then the variable offset is (4n+2), so
598 * the total offset is 4-byte aligned and meets the
599 * load's requirements.
600 */
601 {20, "R5=pkt(id=2,off=0,r=4,umin_value=2,umax_value=1082,var_off=(0x2; 0x7fc))"},
356 }, 602 },
357 }, 603 },
358}; 604};
@@ -373,6 +619,9 @@ static int do_test_single(struct bpf_align_test *test)
373{ 619{
374 struct bpf_insn *prog = test->insns; 620 struct bpf_insn *prog = test->insns;
375 int prog_type = test->prog_type; 621 int prog_type = test->prog_type;
622 char bpf_vlog_copy[32768];
623 const char *line_ptr;
624 int cur_line = -1;
376 int prog_len, i; 625 int prog_len, i;
377 int fd_prog; 626 int fd_prog;
378 int ret; 627 int ret;
@@ -381,26 +630,49 @@ static int do_test_single(struct bpf_align_test *test)
381 fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, 630 fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
382 prog, prog_len, 1, "GPL", 0, 631 prog, prog_len, 1, "GPL", 0,
383 bpf_vlog, sizeof(bpf_vlog), 2); 632 bpf_vlog, sizeof(bpf_vlog), 2);
384 if (fd_prog < 0) { 633 if (fd_prog < 0 && test->result != REJECT) {
385 printf("Failed to load program.\n"); 634 printf("Failed to load program.\n");
386 printf("%s", bpf_vlog); 635 printf("%s", bpf_vlog);
387 ret = 1; 636 ret = 1;
637 } else if (fd_prog >= 0 && test->result == REJECT) {
638 printf("Unexpected success to load!\n");
639 printf("%s", bpf_vlog);
640 ret = 1;
641 close(fd_prog);
388 } else { 642 } else {
389 ret = 0; 643 ret = 0;
644 /* We make a local copy so that we can strtok() it */
645 strncpy(bpf_vlog_copy, bpf_vlog, sizeof(bpf_vlog_copy));
646 line_ptr = strtok(bpf_vlog_copy, "\n");
390 for (i = 0; i < MAX_MATCHES; i++) { 647 for (i = 0; i < MAX_MATCHES; i++) {
391 const char *t, *m = test->matches[i]; 648 struct bpf_reg_match m = test->matches[i];
392 649
393 if (!m) 650 if (!m.match)
394 break; 651 break;
395 t = strstr(bpf_vlog, m); 652 while (line_ptr) {
396 if (!t) { 653 cur_line = -1;
397 printf("Failed to find match: %s\n", m); 654 sscanf(line_ptr, "%u: ", &cur_line);
655 if (cur_line == m.line)
656 break;
657 line_ptr = strtok(NULL, "\n");
658 }
659 if (!line_ptr) {
660 printf("Failed to find line %u for match: %s\n",
661 m.line, m.match);
662 ret = 1;
663 printf("%s", bpf_vlog);
664 break;
665 }
666 if (!strstr(line_ptr, m.match)) {
667 printf("Failed to find match %u: %s\n",
668 m.line, m.match);
398 ret = 1; 669 ret = 1;
399 printf("%s", bpf_vlog); 670 printf("%s", bpf_vlog);
400 break; 671 break;
401 } 672 }
402 } 673 }
403 close(fd_prog); 674 if (fd_prog >= 0)
675 close(fd_prog);
404 } 676 }
405 return ret; 677 return ret;
406} 678}
diff --git a/tools/testing/selftests/bpf/test_dev_cgroup.c b/tools/testing/selftests/bpf/test_dev_cgroup.c
new file mode 100644
index 000000000000..02c85d6c89b0
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_dev_cgroup.c
@@ -0,0 +1,93 @@
1/* Copyright (c) 2017 Facebook
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
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <errno.h>
12#include <assert.h>
13
14#include <linux/bpf.h>
15#include <bpf/bpf.h>
16#include <bpf/libbpf.h>
17
18#include "cgroup_helpers.h"
19
20#define DEV_CGROUP_PROG "./dev_cgroup.o"
21
22#define TEST_CGROUP "test-bpf-based-device-cgroup/"
23
24int main(int argc, char **argv)
25{
26 struct bpf_object *obj;
27 int error = EXIT_FAILURE;
28 int prog_fd, cgroup_fd;
29 __u32 prog_cnt;
30
31 if (bpf_prog_load(DEV_CGROUP_PROG, BPF_PROG_TYPE_CGROUP_DEVICE,
32 &obj, &prog_fd)) {
33 printf("Failed to load DEV_CGROUP program\n");
34 goto err;
35 }
36
37 if (setup_cgroup_environment()) {
38 printf("Failed to load DEV_CGROUP program\n");
39 goto err;
40 }
41
42 /* Create a cgroup, get fd, and join it */
43 cgroup_fd = create_and_get_cgroup(TEST_CGROUP);
44 if (!cgroup_fd) {
45 printf("Failed to create test cgroup\n");
46 goto err;
47 }
48
49 if (join_cgroup(TEST_CGROUP)) {
50 printf("Failed to join cgroup\n");
51 goto err;
52 }
53
54 /* Attach bpf program */
55 if (bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE, 0)) {
56 printf("Failed to attach DEV_CGROUP program");
57 goto err;
58 }
59
60 if (bpf_prog_query(cgroup_fd, BPF_CGROUP_DEVICE, 0, NULL, NULL,
61 &prog_cnt)) {
62 printf("Failed to query attached programs");
63 goto err;
64 }
65
66 /* All operations with /dev/zero and and /dev/urandom are allowed,
67 * everything else is forbidden.
68 */
69 assert(system("rm -f /tmp/test_dev_cgroup_null") == 0);
70 assert(system("mknod /tmp/test_dev_cgroup_null c 1 3"));
71 assert(system("rm -f /tmp/test_dev_cgroup_null") == 0);
72
73 /* /dev/zero is whitelisted */
74 assert(system("rm -f /tmp/test_dev_cgroup_zero") == 0);
75 assert(system("mknod /tmp/test_dev_cgroup_zero c 1 5") == 0);
76 assert(system("rm -f /tmp/test_dev_cgroup_zero") == 0);
77
78 assert(system("dd if=/dev/urandom of=/dev/zero count=64") == 0);
79
80 /* src is allowed, target is forbidden */
81 assert(system("dd if=/dev/urandom of=/dev/full count=64"));
82
83 /* src is forbidden, target is allowed */
84 assert(system("dd if=/dev/random of=/dev/zero count=64"));
85
86 error = 0;
87 printf("test_dev_cgroup:PASS\n");
88
89err:
90 cleanup_cgroup_environment();
91
92 return error;
93}
diff --git a/tools/testing/selftests/bpf/test_kmod.sh b/tools/testing/selftests/bpf/test_kmod.sh
index 6d58cca8e235..ed4774d8d6ed 100755
--- a/tools/testing/selftests/bpf/test_kmod.sh
+++ b/tools/testing/selftests/bpf/test_kmod.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2 3
3SRC_TREE=../../../../ 4SRC_TREE=../../../../
4 5
diff --git a/tools/testing/selftests/bpf/test_lpm_map.c b/tools/testing/selftests/bpf/test_lpm_map.c
index e97565243d59..f61480641b6e 100644
--- a/tools/testing/selftests/bpf/test_lpm_map.c
+++ b/tools/testing/selftests/bpf/test_lpm_map.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Randomized tests for eBPF longest-prefix-match maps 3 * Randomized tests for eBPF longest-prefix-match maps
3 * 4 *
@@ -31,6 +32,10 @@ struct tlpm_node {
31 uint8_t key[]; 32 uint8_t key[];
32}; 33};
33 34
35static struct tlpm_node *tlpm_match(struct tlpm_node *list,
36 const uint8_t *key,
37 size_t n_bits);
38
34static struct tlpm_node *tlpm_add(struct tlpm_node *list, 39static struct tlpm_node *tlpm_add(struct tlpm_node *list,
35 const uint8_t *key, 40 const uint8_t *key,
36 size_t n_bits) 41 size_t n_bits)
@@ -38,9 +43,17 @@ static struct tlpm_node *tlpm_add(struct tlpm_node *list,
38 struct tlpm_node *node; 43 struct tlpm_node *node;
39 size_t n; 44 size_t n;
40 45
46 n = (n_bits + 7) / 8;
47
48 /* 'overwrite' an equivalent entry if one already exists */
49 node = tlpm_match(list, key, n_bits);
50 if (node && node->n_bits == n_bits) {
51 memcpy(node->key, key, n);
52 return list;
53 }
54
41 /* add new entry with @key/@n_bits to @list and return new head */ 55 /* add new entry with @key/@n_bits to @list and return new head */
42 56
43 n = (n_bits + 7) / 8;
44 node = malloc(sizeof(*node) + n); 57 node = malloc(sizeof(*node) + n);
45 assert(node); 58 assert(node);
46 59
@@ -92,6 +105,34 @@ static struct tlpm_node *tlpm_match(struct tlpm_node *list,
92 return best; 105 return best;
93} 106}
94 107
108static struct tlpm_node *tlpm_delete(struct tlpm_node *list,
109 const uint8_t *key,
110 size_t n_bits)
111{
112 struct tlpm_node *best = tlpm_match(list, key, n_bits);
113 struct tlpm_node *node;
114
115 if (!best || best->n_bits != n_bits)
116 return list;
117
118 if (best == list) {
119 node = best->next;
120 free(best);
121 return node;
122 }
123
124 for (node = list; node; node = node->next) {
125 if (node->next == best) {
126 node->next = best->next;
127 free(best);
128 return list;
129 }
130 }
131 /* should never get here */
132 assert(0);
133 return list;
134}
135
95static void test_lpm_basic(void) 136static void test_lpm_basic(void)
96{ 137{
97 struct tlpm_node *list = NULL, *t1, *t2; 138 struct tlpm_node *list = NULL, *t1, *t2;
@@ -114,6 +155,13 @@ static void test_lpm_basic(void)
114 assert(t1 == tlpm_match(list, (uint8_t[]){ 0xff, 0xff }, 15)); 155 assert(t1 == tlpm_match(list, (uint8_t[]){ 0xff, 0xff }, 15));
115 assert(!tlpm_match(list, (uint8_t[]){ 0x7f, 0xff }, 16)); 156 assert(!tlpm_match(list, (uint8_t[]){ 0x7f, 0xff }, 16));
116 157
158 list = tlpm_delete(list, (uint8_t[]){ 0xff, 0xff }, 16);
159 assert(t1 == tlpm_match(list, (uint8_t[]){ 0xff }, 8));
160 assert(t1 == tlpm_match(list, (uint8_t[]){ 0xff, 0xff }, 16));
161
162 list = tlpm_delete(list, (uint8_t[]){ 0xff }, 8);
163 assert(!tlpm_match(list, (uint8_t[]){ 0xff }, 8));
164
117 tlpm_clear(list); 165 tlpm_clear(list);
118} 166}
119 167
@@ -158,7 +206,7 @@ static void test_lpm_order(void)
158 206
159static void test_lpm_map(int keysize) 207static void test_lpm_map(int keysize)
160{ 208{
161 size_t i, j, n_matches, n_nodes, n_lookups; 209 size_t i, j, n_matches, n_matches_after_delete, n_nodes, n_lookups;
162 struct tlpm_node *t, *list = NULL; 210 struct tlpm_node *t, *list = NULL;
163 struct bpf_lpm_trie_key *key; 211 struct bpf_lpm_trie_key *key;
164 uint8_t *data, *value; 212 uint8_t *data, *value;
@@ -170,6 +218,7 @@ static void test_lpm_map(int keysize)
170 */ 218 */
171 219
172 n_matches = 0; 220 n_matches = 0;
221 n_matches_after_delete = 0;
173 n_nodes = 1 << 8; 222 n_nodes = 1 << 8;
174 n_lookups = 1 << 16; 223 n_lookups = 1 << 16;
175 224
@@ -223,15 +272,54 @@ static void test_lpm_map(int keysize)
223 } 272 }
224 } 273 }
225 274
275 /* Remove the first half of the elements in the tlpm and the
276 * corresponding nodes from the bpf-lpm. Then run the same
277 * large number of random lookups in both and make sure they match.
278 * Note: we need to count the number of nodes actually inserted
279 * since there may have been duplicates.
280 */
281 for (i = 0, t = list; t; i++, t = t->next)
282 ;
283 for (j = 0; j < i / 2; ++j) {
284 key->prefixlen = list->n_bits;
285 memcpy(key->data, list->key, keysize);
286 r = bpf_map_delete_elem(map, key);
287 assert(!r);
288 list = tlpm_delete(list, list->key, list->n_bits);
289 assert(list);
290 }
291 for (i = 0; i < n_lookups; ++i) {
292 for (j = 0; j < keysize; ++j)
293 data[j] = rand() & 0xff;
294
295 t = tlpm_match(list, data, 8 * keysize);
296
297 key->prefixlen = 8 * keysize;
298 memcpy(key->data, data, keysize);
299 r = bpf_map_lookup_elem(map, key, value);
300 assert(!r || errno == ENOENT);
301 assert(!t == !!r);
302
303 if (t) {
304 ++n_matches_after_delete;
305 assert(t->n_bits == value[keysize]);
306 for (j = 0; j < t->n_bits; ++j)
307 assert((t->key[j / 8] & (1 << (7 - j % 8))) ==
308 (value[j / 8] & (1 << (7 - j % 8))));
309 }
310 }
311
226 close(map); 312 close(map);
227 tlpm_clear(list); 313 tlpm_clear(list);
228 314
229 /* With 255 random nodes in the map, we are pretty likely to match 315 /* With 255 random nodes in the map, we are pretty likely to match
230 * something on every lookup. For statistics, use this: 316 * something on every lookup. For statistics, use this:
231 * 317 *
232 * printf(" nodes: %zu\n" 318 * printf(" nodes: %zu\n"
233 * "lookups: %zu\n" 319 * " lookups: %zu\n"
234 * "matches: %zu\n", n_nodes, n_lookups, n_matches); 320 * " matches: %zu\n"
321 * "matches(delete): %zu\n",
322 * n_nodes, n_lookups, n_matches, n_matches_after_delete);
235 */ 323 */
236} 324}
237 325
@@ -331,6 +419,108 @@ static void test_lpm_ipaddr(void)
331 close(map_fd_ipv6); 419 close(map_fd_ipv6);
332} 420}
333 421
422static void test_lpm_delete(void)
423{
424 struct bpf_lpm_trie_key *key;
425 size_t key_size;
426 int map_fd;
427 __u64 value;
428
429 key_size = sizeof(*key) + sizeof(__u32);
430 key = alloca(key_size);
431
432 map_fd = bpf_create_map(BPF_MAP_TYPE_LPM_TRIE,
433 key_size, sizeof(value),
434 100, BPF_F_NO_PREALLOC);
435 assert(map_fd >= 0);
436
437 /* Add nodes:
438 * 192.168.0.0/16 (1)
439 * 192.168.0.0/24 (2)
440 * 192.168.128.0/24 (3)
441 * 192.168.1.0/24 (4)
442 *
443 * (1)
444 * / \
445 * (IM) (3)
446 * / \
447 * (2) (4)
448 */
449 value = 1;
450 key->prefixlen = 16;
451 inet_pton(AF_INET, "192.168.0.0", key->data);
452 assert(bpf_map_update_elem(map_fd, key, &value, 0) == 0);
453
454 value = 2;
455 key->prefixlen = 24;
456 inet_pton(AF_INET, "192.168.0.0", key->data);
457 assert(bpf_map_update_elem(map_fd, key, &value, 0) == 0);
458
459 value = 3;
460 key->prefixlen = 24;
461 inet_pton(AF_INET, "192.168.128.0", key->data);
462 assert(bpf_map_update_elem(map_fd, key, &value, 0) == 0);
463
464 value = 4;
465 key->prefixlen = 24;
466 inet_pton(AF_INET, "192.168.1.0", key->data);
467 assert(bpf_map_update_elem(map_fd, key, &value, 0) == 0);
468
469 /* remove non-existent node */
470 key->prefixlen = 32;
471 inet_pton(AF_INET, "10.0.0.1", key->data);
472 assert(bpf_map_lookup_elem(map_fd, key, &value) == -1 &&
473 errno == ENOENT);
474
475 /* assert initial lookup */
476 key->prefixlen = 32;
477 inet_pton(AF_INET, "192.168.0.1", key->data);
478 assert(bpf_map_lookup_elem(map_fd, key, &value) == 0);
479 assert(value == 2);
480
481 /* remove leaf node */
482 key->prefixlen = 24;
483 inet_pton(AF_INET, "192.168.0.0", key->data);
484 assert(bpf_map_delete_elem(map_fd, key) == 0);
485
486 key->prefixlen = 32;
487 inet_pton(AF_INET, "192.168.0.1", key->data);
488 assert(bpf_map_lookup_elem(map_fd, key, &value) == 0);
489 assert(value == 1);
490
491 /* remove leaf (and intermediary) node */
492 key->prefixlen = 24;
493 inet_pton(AF_INET, "192.168.1.0", key->data);
494 assert(bpf_map_delete_elem(map_fd, key) == 0);
495
496 key->prefixlen = 32;
497 inet_pton(AF_INET, "192.168.1.1", key->data);
498 assert(bpf_map_lookup_elem(map_fd, key, &value) == 0);
499 assert(value == 1);
500
501 /* remove root node */
502 key->prefixlen = 16;
503 inet_pton(AF_INET, "192.168.0.0", key->data);
504 assert(bpf_map_delete_elem(map_fd, key) == 0);
505
506 key->prefixlen = 32;
507 inet_pton(AF_INET, "192.168.128.1", key->data);
508 assert(bpf_map_lookup_elem(map_fd, key, &value) == 0);
509 assert(value == 3);
510
511 /* remove last node */
512 key->prefixlen = 24;
513 inet_pton(AF_INET, "192.168.128.0", key->data);
514 assert(bpf_map_delete_elem(map_fd, key) == 0);
515
516 key->prefixlen = 32;
517 inet_pton(AF_INET, "192.168.128.1", key->data);
518 assert(bpf_map_lookup_elem(map_fd, key, &value) == -1 &&
519 errno == ENOENT);
520
521 close(map_fd);
522}
523
334int main(void) 524int main(void)
335{ 525{
336 struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY }; 526 struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY };
@@ -353,6 +543,8 @@ int main(void)
353 543
354 test_lpm_ipaddr(); 544 test_lpm_ipaddr();
355 545
546 test_lpm_delete();
547
356 printf("test_lpm: OK\n"); 548 printf("test_lpm: OK\n");
357 return 0; 549 return 0;
358} 550}
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 79601c81e169..040356ecc862 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -22,6 +22,7 @@
22#include <linux/bpf.h> 22#include <linux/bpf.h>
23 23
24#include <bpf/bpf.h> 24#include <bpf/bpf.h>
25#include <bpf/libbpf.h>
25#include "bpf_util.h" 26#include "bpf_util.h"
26 27
27static int map_flags; 28static int map_flags;
@@ -438,6 +439,454 @@ static void test_arraymap_percpu_many_keys(void)
438 close(fd); 439 close(fd);
439} 440}
440 441
442static void test_devmap(int task, void *data)
443{
444 int fd;
445 __u32 key, value;
446
447 fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP, sizeof(key), sizeof(value),
448 2, 0);
449 if (fd < 0) {
450 printf("Failed to create arraymap '%s'!\n", strerror(errno));
451 exit(1);
452 }
453
454 close(fd);
455}
456
457#include <sys/socket.h>
458#include <sys/ioctl.h>
459#include <arpa/inet.h>
460#include <sys/select.h>
461#include <linux/err.h>
462#define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o"
463#define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o"
464static void test_sockmap(int tasks, void *data)
465{
466 int one = 1, map_fd_rx, map_fd_tx, map_fd_break, s, sc, rc;
467 struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_break;
468 int ports[] = {50200, 50201, 50202, 50204};
469 int err, i, fd, udp, sfd[6] = {0xdeadbeef};
470 u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0};
471 int parse_prog, verdict_prog;
472 struct sockaddr_in addr;
473 struct bpf_object *obj;
474 struct timeval to;
475 __u32 key, value;
476 pid_t pid[tasks];
477 fd_set w;
478
479 /* Create some sockets to use with sockmap */
480 for (i = 0; i < 2; i++) {
481 sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
482 if (sfd[i] < 0)
483 goto out;
484 err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
485 (char *)&one, sizeof(one));
486 if (err) {
487 printf("failed to setsockopt\n");
488 goto out;
489 }
490 err = ioctl(sfd[i], FIONBIO, (char *)&one);
491 if (err < 0) {
492 printf("failed to ioctl\n");
493 goto out;
494 }
495 memset(&addr, 0, sizeof(struct sockaddr_in));
496 addr.sin_family = AF_INET;
497 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
498 addr.sin_port = htons(ports[i]);
499 err = bind(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
500 if (err < 0) {
501 printf("failed to bind: err %i: %i:%i\n",
502 err, i, sfd[i]);
503 goto out;
504 }
505 err = listen(sfd[i], 32);
506 if (err < 0) {
507 printf("failed to listen\n");
508 goto out;
509 }
510 }
511
512 for (i = 2; i < 4; i++) {
513 sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
514 if (sfd[i] < 0)
515 goto out;
516 err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
517 (char *)&one, sizeof(one));
518 if (err) {
519 printf("set sock opt\n");
520 goto out;
521 }
522 memset(&addr, 0, sizeof(struct sockaddr_in));
523 addr.sin_family = AF_INET;
524 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
525 addr.sin_port = htons(ports[i - 2]);
526 err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
527 if (err) {
528 printf("failed to connect\n");
529 goto out;
530 }
531 }
532
533
534 for (i = 4; i < 6; i++) {
535 sfd[i] = accept(sfd[i - 4], NULL, NULL);
536 if (sfd[i] < 0) {
537 printf("accept failed\n");
538 goto out;
539 }
540 }
541
542 /* Test sockmap with connected sockets */
543 fd = bpf_create_map(BPF_MAP_TYPE_SOCKMAP,
544 sizeof(key), sizeof(value),
545 6, 0);
546 if (fd < 0) {
547 printf("Failed to create sockmap %i\n", fd);
548 goto out_sockmap;
549 }
550
551 /* Test update with unsupported UDP socket */
552 udp = socket(AF_INET, SOCK_DGRAM, 0);
553 i = 0;
554 err = bpf_map_update_elem(fd, &i, &udp, BPF_ANY);
555 if (!err) {
556 printf("Failed socket SOCK_DGRAM allowed '%i:%i'\n",
557 i, udp);
558 goto out_sockmap;
559 }
560
561 /* Test update without programs */
562 for (i = 0; i < 6; i++) {
563 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
564 if (err) {
565 printf("Failed noprog update sockmap '%i:%i'\n",
566 i, sfd[i]);
567 goto out_sockmap;
568 }
569 }
570
571 /* Test attaching/detaching bad fds */
572 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0);
573 if (!err) {
574 printf("Failed invalid parser prog attach\n");
575 goto out_sockmap;
576 }
577
578 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0);
579 if (!err) {
580 printf("Failed invalid verdict prog attach\n");
581 goto out_sockmap;
582 }
583
584 err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
585 if (!err) {
586 printf("Failed unknown prog attach\n");
587 goto out_sockmap;
588 }
589
590 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
591 if (err) {
592 printf("Failed empty parser prog detach\n");
593 goto out_sockmap;
594 }
595
596 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
597 if (err) {
598 printf("Failed empty verdict prog detach\n");
599 goto out_sockmap;
600 }
601
602 err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
603 if (!err) {
604 printf("Detach invalid prog successful\n");
605 goto out_sockmap;
606 }
607
608 /* Load SK_SKB program and Attach */
609 err = bpf_prog_load(SOCKMAP_PARSE_PROG,
610 BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog);
611 if (err) {
612 printf("Failed to load SK_SKB parse prog\n");
613 goto out_sockmap;
614 }
615
616 err = bpf_prog_load(SOCKMAP_VERDICT_PROG,
617 BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog);
618 if (err) {
619 printf("Failed to load SK_SKB verdict prog\n");
620 goto out_sockmap;
621 }
622
623 bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx");
624 if (IS_ERR(bpf_map_rx)) {
625 printf("Failed to load map rx from verdict prog\n");
626 goto out_sockmap;
627 }
628
629 map_fd_rx = bpf_map__fd(bpf_map_rx);
630 if (map_fd_rx < 0) {
631 printf("Failed to get map fd\n");
632 goto out_sockmap;
633 }
634
635 bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx");
636 if (IS_ERR(bpf_map_tx)) {
637 printf("Failed to load map tx from verdict prog\n");
638 goto out_sockmap;
639 }
640
641 map_fd_tx = bpf_map__fd(bpf_map_tx);
642 if (map_fd_tx < 0) {
643 printf("Failed to get map tx fd\n");
644 goto out_sockmap;
645 }
646
647 bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break");
648 if (IS_ERR(bpf_map_break)) {
649 printf("Failed to load map tx from verdict prog\n");
650 goto out_sockmap;
651 }
652
653 map_fd_break = bpf_map__fd(bpf_map_break);
654 if (map_fd_break < 0) {
655 printf("Failed to get map tx fd\n");
656 goto out_sockmap;
657 }
658
659 err = bpf_prog_attach(parse_prog, map_fd_break,
660 BPF_SK_SKB_STREAM_PARSER, 0);
661 if (!err) {
662 printf("Allowed attaching SK_SKB program to invalid map\n");
663 goto out_sockmap;
664 }
665
666 err = bpf_prog_attach(parse_prog, map_fd_rx,
667 BPF_SK_SKB_STREAM_PARSER, 0);
668 if (err) {
669 printf("Failed stream parser bpf prog attach\n");
670 goto out_sockmap;
671 }
672
673 err = bpf_prog_attach(verdict_prog, map_fd_rx,
674 BPF_SK_SKB_STREAM_VERDICT, 0);
675 if (err) {
676 printf("Failed stream verdict bpf prog attach\n");
677 goto out_sockmap;
678 }
679
680 err = bpf_prog_attach(verdict_prog, map_fd_rx,
681 __MAX_BPF_ATTACH_TYPE, 0);
682 if (!err) {
683 printf("Attached unknown bpf prog\n");
684 goto out_sockmap;
685 }
686
687 /* Test map update elem afterwards fd lives in fd and map_fd */
688 for (i = 0; i < 6; i++) {
689 err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY);
690 if (err) {
691 printf("Failed map_fd_rx update sockmap %i '%i:%i'\n",
692 err, i, sfd[i]);
693 goto out_sockmap;
694 }
695 err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY);
696 if (err) {
697 printf("Failed map_fd_tx update sockmap %i '%i:%i'\n",
698 err, i, sfd[i]);
699 goto out_sockmap;
700 }
701 }
702
703 /* Test map delete elem and remove send/recv sockets */
704 for (i = 2; i < 4; i++) {
705 err = bpf_map_delete_elem(map_fd_rx, &i);
706 if (err) {
707 printf("Failed delete sockmap rx %i '%i:%i'\n",
708 err, i, sfd[i]);
709 goto out_sockmap;
710 }
711 err = bpf_map_delete_elem(map_fd_tx, &i);
712 if (err) {
713 printf("Failed delete sockmap tx %i '%i:%i'\n",
714 err, i, sfd[i]);
715 goto out_sockmap;
716 }
717 }
718
719 /* Test map send/recv */
720 for (i = 0; i < 2; i++) {
721 buf[0] = i;
722 buf[1] = 0x5;
723 sc = send(sfd[2], buf, 20, 0);
724 if (sc < 0) {
725 printf("Failed sockmap send\n");
726 goto out_sockmap;
727 }
728
729 FD_ZERO(&w);
730 FD_SET(sfd[3], &w);
731 to.tv_sec = 1;
732 to.tv_usec = 0;
733 s = select(sfd[3] + 1, &w, NULL, NULL, &to);
734 if (s == -1) {
735 perror("Failed sockmap select()");
736 goto out_sockmap;
737 } else if (!s) {
738 printf("Failed sockmap unexpected timeout\n");
739 goto out_sockmap;
740 }
741
742 if (!FD_ISSET(sfd[3], &w)) {
743 printf("Failed sockmap select/recv\n");
744 goto out_sockmap;
745 }
746
747 rc = recv(sfd[3], buf, sizeof(buf), 0);
748 if (rc < 0) {
749 printf("Failed sockmap recv\n");
750 goto out_sockmap;
751 }
752 }
753
754 /* Negative null entry lookup from datapath should be dropped */
755 buf[0] = 1;
756 buf[1] = 12;
757 sc = send(sfd[2], buf, 20, 0);
758 if (sc < 0) {
759 printf("Failed sockmap send\n");
760 goto out_sockmap;
761 }
762
763 /* Push fd into same slot */
764 i = 2;
765 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
766 if (!err) {
767 printf("Failed allowed sockmap dup slot BPF_NOEXIST\n");
768 goto out_sockmap;
769 }
770
771 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
772 if (err) {
773 printf("Failed sockmap update new slot BPF_ANY\n");
774 goto out_sockmap;
775 }
776
777 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
778 if (err) {
779 printf("Failed sockmap update new slot BPF_EXIST\n");
780 goto out_sockmap;
781 }
782
783 /* Delete the elems without programs */
784 for (i = 0; i < 6; i++) {
785 err = bpf_map_delete_elem(fd, &i);
786 if (err) {
787 printf("Failed delete sockmap %i '%i:%i'\n",
788 err, i, sfd[i]);
789 }
790 }
791
792 /* Test having multiple maps open and set with programs on same fds */
793 err = bpf_prog_attach(parse_prog, fd,
794 BPF_SK_SKB_STREAM_PARSER, 0);
795 if (err) {
796 printf("Failed fd bpf parse prog attach\n");
797 goto out_sockmap;
798 }
799 err = bpf_prog_attach(verdict_prog, fd,
800 BPF_SK_SKB_STREAM_VERDICT, 0);
801 if (err) {
802 printf("Failed fd bpf verdict prog attach\n");
803 goto out_sockmap;
804 }
805
806 for (i = 4; i < 6; i++) {
807 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
808 if (!err) {
809 printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n",
810 err, i, sfd[i]);
811 goto out_sockmap;
812 }
813 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
814 if (!err) {
815 printf("Failed allowed duplicate program in update NOEXIST sockmap %i '%i:%i'\n",
816 err, i, sfd[i]);
817 goto out_sockmap;
818 }
819 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
820 if (!err) {
821 printf("Failed allowed duplicate program in update EXIST sockmap %i '%i:%i'\n",
822 err, i, sfd[i]);
823 goto out_sockmap;
824 }
825 }
826
827 /* Test tasks number of forked operations */
828 for (i = 0; i < tasks; i++) {
829 pid[i] = fork();
830 if (pid[i] == 0) {
831 for (i = 0; i < 6; i++) {
832 bpf_map_delete_elem(map_fd_tx, &i);
833 bpf_map_delete_elem(map_fd_rx, &i);
834 bpf_map_update_elem(map_fd_tx, &i,
835 &sfd[i], BPF_ANY);
836 bpf_map_update_elem(map_fd_rx, &i,
837 &sfd[i], BPF_ANY);
838 }
839 exit(0);
840 } else if (pid[i] == -1) {
841 printf("Couldn't spawn #%d process!\n", i);
842 exit(1);
843 }
844 }
845
846 for (i = 0; i < tasks; i++) {
847 int status;
848
849 assert(waitpid(pid[i], &status, 0) == pid[i]);
850 assert(status == 0);
851 }
852
853 err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
854 if (!err) {
855 printf("Detached an invalid prog type.\n");
856 goto out_sockmap;
857 }
858
859 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
860 if (err) {
861 printf("Failed parser prog detach\n");
862 goto out_sockmap;
863 }
864
865 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
866 if (err) {
867 printf("Failed parser prog detach\n");
868 goto out_sockmap;
869 }
870
871 /* Test map close sockets */
872 for (i = 0; i < 6; i++)
873 close(sfd[i]);
874 close(fd);
875 close(map_fd_rx);
876 bpf_object__close(obj);
877 return;
878out:
879 for (i = 0; i < 6; i++)
880 close(sfd[i]);
881 printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno));
882 exit(1);
883out_sockmap:
884 for (i = 0; i < 6; i++)
885 close(sfd[i]);
886 close(fd);
887 exit(1);
888}
889
441#define MAP_SIZE (32 * 1024) 890#define MAP_SIZE (32 * 1024)
442 891
443static void test_map_large(void) 892static void test_map_large(void)
@@ -594,6 +1043,51 @@ static void test_map_parallel(void)
594 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 1043 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
595} 1044}
596 1045
1046static void test_map_rdonly(void)
1047{
1048 int fd, key = 0, value = 0;
1049
1050 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
1051 MAP_SIZE, map_flags | BPF_F_RDONLY);
1052 if (fd < 0) {
1053 printf("Failed to create map for read only test '%s'!\n",
1054 strerror(errno));
1055 exit(1);
1056 }
1057
1058 key = 1;
1059 value = 1234;
1060 /* Insert key=1 element. */
1061 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == -1 &&
1062 errno == EPERM);
1063
1064 /* Check that key=2 is not found. */
1065 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
1066 assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == ENOENT);
1067}
1068
1069static void test_map_wronly(void)
1070{
1071 int fd, key = 0, value = 0;
1072
1073 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
1074 MAP_SIZE, map_flags | BPF_F_WRONLY);
1075 if (fd < 0) {
1076 printf("Failed to create map for read only test '%s'!\n",
1077 strerror(errno));
1078 exit(1);
1079 }
1080
1081 key = 1;
1082 value = 1234;
1083 /* Insert key=1 element. */
1084 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
1085
1086 /* Check that key=2 is not found. */
1087 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == EPERM);
1088 assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == EPERM);
1089}
1090
597static void run_all_tests(void) 1091static void run_all_tests(void)
598{ 1092{
599 test_hashmap(0, NULL); 1093 test_hashmap(0, NULL);
@@ -605,9 +1099,15 @@ static void run_all_tests(void)
605 1099
606 test_arraymap_percpu_many_keys(); 1100 test_arraymap_percpu_many_keys();
607 1101
1102 test_devmap(0, NULL);
1103 test_sockmap(0, NULL);
1104
608 test_map_large(); 1105 test_map_large();
609 test_map_parallel(); 1106 test_map_parallel();
610 test_map_stress(); 1107 test_map_stress();
1108
1109 test_map_rdonly();
1110 test_map_wronly();
611} 1111}
612 1112
613int main(void) 1113int main(void)
diff --git a/tools/testing/selftests/bpf/test_pkt_md_access.c b/tools/testing/selftests/bpf/test_pkt_md_access.c
index 71729d47eb85..7956302ecdf2 100644
--- a/tools/testing/selftests/bpf/test_pkt_md_access.c
+++ b/tools/testing/selftests/bpf/test_pkt_md_access.c
@@ -12,12 +12,23 @@
12 12
13int _version SEC("version") = 1; 13int _version SEC("version") = 1;
14 14
15#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
15#define TEST_FIELD(TYPE, FIELD, MASK) \ 16#define TEST_FIELD(TYPE, FIELD, MASK) \
16 { \ 17 { \
17 TYPE tmp = *(volatile TYPE *)&skb->FIELD; \ 18 TYPE tmp = *(volatile TYPE *)&skb->FIELD; \
18 if (tmp != ((*(volatile __u32 *)&skb->FIELD) & MASK)) \ 19 if (tmp != ((*(volatile __u32 *)&skb->FIELD) & MASK)) \
19 return TC_ACT_SHOT; \ 20 return TC_ACT_SHOT; \
20 } 21 }
22#else
23#define TEST_FIELD_OFFSET(a, b) ((sizeof(a) - sizeof(b)) / sizeof(b))
24#define TEST_FIELD(TYPE, FIELD, MASK) \
25 { \
26 TYPE tmp = *((volatile TYPE *)&skb->FIELD + \
27 TEST_FIELD_OFFSET(skb->FIELD, TYPE)); \
28 if (tmp != ((*(volatile __u32 *)&skb->FIELD) & MASK)) \
29 return TC_ACT_SHOT; \
30 }
31#endif
21 32
22SEC("test1") 33SEC("test1")
23int process(struct __sk_buff *skb) 34int process(struct __sk_buff *skb)
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index 5855cd3d3d45..69427531408d 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -10,6 +10,7 @@
10#include <string.h> 10#include <string.h>
11#include <assert.h> 11#include <assert.h>
12#include <stdlib.h> 12#include <stdlib.h>
13#include <time.h>
13 14
14#include <linux/types.h> 15#include <linux/types.h>
15typedef __u16 __sum16; 16typedef __u16 __sum16;
@@ -19,6 +20,8 @@ typedef __u16 __sum16;
19#include <linux/ip.h> 20#include <linux/ip.h>
20#include <linux/ipv6.h> 21#include <linux/ipv6.h>
21#include <linux/tcp.h> 22#include <linux/tcp.h>
23#include <linux/filter.h>
24#include <linux/unistd.h>
22 25
23#include <sys/wait.h> 26#include <sys/wait.h>
24#include <sys/resource.h> 27#include <sys/resource.h>
@@ -75,39 +78,6 @@ static struct {
75 __ret; \ 78 __ret; \
76}) 79})
77 80
78static int bpf_prog_load(const char *file, enum bpf_prog_type type,
79 struct bpf_object **pobj, int *prog_fd)
80{
81 struct bpf_program *prog;
82 struct bpf_object *obj;
83 int err;
84
85 obj = bpf_object__open(file);
86 if (IS_ERR(obj)) {
87 error_cnt++;
88 return -ENOENT;
89 }
90
91 prog = bpf_program__next(NULL, obj);
92 if (!prog) {
93 bpf_object__close(obj);
94 error_cnt++;
95 return -ENOENT;
96 }
97
98 bpf_program__set_type(prog, type);
99 err = bpf_object__load(obj);
100 if (err) {
101 bpf_object__close(obj);
102 error_cnt++;
103 return -EINVAL;
104 }
105
106 *pobj = obj;
107 *prog_fd = bpf_program__fd(prog);
108 return 0;
109}
110
111static int bpf_find_map(const char *test, struct bpf_object *obj, 81static int bpf_find_map(const char *test, struct bpf_object *obj,
112 const char *name) 82 const char *name)
113{ 83{
@@ -130,8 +100,10 @@ static void test_pkt_access(void)
130 int err, prog_fd; 100 int err, prog_fd;
131 101
132 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd); 102 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
133 if (err) 103 if (err) {
104 error_cnt++;
134 return; 105 return;
106 }
135 107
136 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v4, sizeof(pkt_v4), 108 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v4, sizeof(pkt_v4),
137 NULL, NULL, &retval, &duration); 109 NULL, NULL, &retval, &duration);
@@ -162,8 +134,10 @@ static void test_xdp(void)
162 int err, prog_fd, map_fd; 134 int err, prog_fd, map_fd;
163 135
164 err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd); 136 err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
165 if (err) 137 if (err) {
138 error_cnt++;
166 return; 139 return;
140 }
167 141
168 map_fd = bpf_find_map(__func__, obj, "vip2tnl"); 142 map_fd = bpf_find_map(__func__, obj, "vip2tnl");
169 if (map_fd < 0) 143 if (map_fd < 0)
@@ -223,8 +197,10 @@ static void test_l4lb(void)
223 u32 *magic = (u32 *)buf; 197 u32 *magic = (u32 *)buf;
224 198
225 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd); 199 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
226 if (err) 200 if (err) {
201 error_cnt++;
227 return; 202 return;
203 }
228 204
229 map_fd = bpf_find_map(__func__, obj, "vip_map"); 205 map_fd = bpf_find_map(__func__, obj, "vip_map");
230 if (map_fd < 0) 206 if (map_fd < 0)
@@ -280,8 +256,10 @@ static void test_tcp_estats(void)
280 256
281 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd); 257 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
282 CHECK(err, "", "err %d errno %d\n", err, errno); 258 CHECK(err, "", "err %d errno %d\n", err, errno);
283 if (err) 259 if (err) {
260 error_cnt++;
284 return; 261 return;
262 }
285 263
286 bpf_object__close(obj); 264 bpf_object__close(obj);
287} 265}
@@ -298,16 +276,26 @@ static void test_bpf_obj_id(void)
298 const int nr_iters = 2; 276 const int nr_iters = 2;
299 const char *file = "./test_obj_id.o"; 277 const char *file = "./test_obj_id.o";
300 const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable"; 278 const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
279 const char *expected_prog_name = "test_obj_id";
280 const char *expected_map_name = "test_map_id";
281 const __u64 nsec_per_sec = 1000000000;
301 282
302 struct bpf_object *objs[nr_iters]; 283 struct bpf_object *objs[nr_iters];
303 int prog_fds[nr_iters], map_fds[nr_iters]; 284 int prog_fds[nr_iters], map_fds[nr_iters];
304 /* +1 to test for the info_len returned by kernel */ 285 /* +1 to test for the info_len returned by kernel */
305 struct bpf_prog_info prog_infos[nr_iters + 1]; 286 struct bpf_prog_info prog_infos[nr_iters + 1];
306 struct bpf_map_info map_infos[nr_iters + 1]; 287 struct bpf_map_info map_infos[nr_iters + 1];
307 char jited_insns[128], xlated_insns[128]; 288 /* Each prog only uses one map. +1 to test nr_map_ids
289 * returned by kernel.
290 */
291 __u32 map_ids[nr_iters + 1];
292 char jited_insns[128], xlated_insns[128], zeros[128];
308 __u32 i, next_id, info_len, nr_id_found, duration = 0; 293 __u32 i, next_id, info_len, nr_id_found, duration = 0;
294 struct timespec real_time_ts, boot_time_ts;
309 int sysctl_fd, jit_enabled = 0, err = 0; 295 int sysctl_fd, jit_enabled = 0, err = 0;
310 __u64 array_value; 296 __u64 array_value;
297 uid_t my_uid = getuid();
298 time_t now, load_time;
311 299
312 sysctl_fd = open(jit_sysctl, 0, O_RDONLY); 300 sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
313 if (sysctl_fd != -1) { 301 if (sysctl_fd != -1) {
@@ -330,37 +318,19 @@ static void test_bpf_obj_id(void)
330 objs[i] = NULL; 318 objs[i] = NULL;
331 319
332 /* Check bpf_obj_get_info_by_fd() */ 320 /* Check bpf_obj_get_info_by_fd() */
321 bzero(zeros, sizeof(zeros));
333 for (i = 0; i < nr_iters; i++) { 322 for (i = 0; i < nr_iters; i++) {
323 now = time(NULL);
334 err = bpf_prog_load(file, BPF_PROG_TYPE_SOCKET_FILTER, 324 err = bpf_prog_load(file, BPF_PROG_TYPE_SOCKET_FILTER,
335 &objs[i], &prog_fds[i]); 325 &objs[i], &prog_fds[i]);
336 /* test_obj_id.o is a dumb prog. It should never fail 326 /* test_obj_id.o is a dumb prog. It should never fail
337 * to load. 327 * to load.
338 */ 328 */
329 if (err)
330 error_cnt++;
339 assert(!err); 331 assert(!err);
340 332
341 /* Check getting prog info */ 333 /* Insert a magic value to the map */
342 info_len = sizeof(struct bpf_prog_info) * 2;
343 prog_infos[i].jited_prog_insns = ptr_to_u64(jited_insns);
344 prog_infos[i].jited_prog_len = sizeof(jited_insns);
345 prog_infos[i].xlated_prog_insns = ptr_to_u64(xlated_insns);
346 prog_infos[i].xlated_prog_len = sizeof(xlated_insns);
347 err = bpf_obj_get_info_by_fd(prog_fds[i], &prog_infos[i],
348 &info_len);
349 if (CHECK(err ||
350 prog_infos[i].type != BPF_PROG_TYPE_SOCKET_FILTER ||
351 info_len != sizeof(struct bpf_prog_info) ||
352 (jit_enabled && !prog_infos[i].jited_prog_len) ||
353 !prog_infos[i].xlated_prog_len,
354 "get-prog-info(fd)",
355 "err %d errno %d i %d type %d(%d) info_len %u(%lu) jit_enabled %d jited_prog_len %u xlated_prog_len %u\n",
356 err, errno, i,
357 prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER,
358 info_len, sizeof(struct bpf_prog_info),
359 jit_enabled,
360 prog_infos[i].jited_prog_len,
361 prog_infos[i].xlated_prog_len))
362 goto done;
363
364 map_fds[i] = bpf_find_map(__func__, objs[i], "test_map_id"); 334 map_fds[i] = bpf_find_map(__func__, objs[i], "test_map_id");
365 assert(map_fds[i] >= 0); 335 assert(map_fds[i] >= 0);
366 err = bpf_map_update_elem(map_fds[i], &array_key, 336 err = bpf_map_update_elem(map_fds[i], &array_key,
@@ -369,6 +339,7 @@ static void test_bpf_obj_id(void)
369 339
370 /* Check getting map info */ 340 /* Check getting map info */
371 info_len = sizeof(struct bpf_map_info) * 2; 341 info_len = sizeof(struct bpf_map_info) * 2;
342 bzero(&map_infos[i], info_len);
372 err = bpf_obj_get_info_by_fd(map_fds[i], &map_infos[i], 343 err = bpf_obj_get_info_by_fd(map_fds[i], &map_infos[i],
373 &info_len); 344 &info_len);
374 if (CHECK(err || 345 if (CHECK(err ||
@@ -377,16 +348,67 @@ static void test_bpf_obj_id(void)
377 map_infos[i].value_size != sizeof(__u64) || 348 map_infos[i].value_size != sizeof(__u64) ||
378 map_infos[i].max_entries != 1 || 349 map_infos[i].max_entries != 1 ||
379 map_infos[i].map_flags != 0 || 350 map_infos[i].map_flags != 0 ||
380 info_len != sizeof(struct bpf_map_info), 351 info_len != sizeof(struct bpf_map_info) ||
352 strcmp((char *)map_infos[i].name, expected_map_name),
381 "get-map-info(fd)", 353 "get-map-info(fd)",
382 "err %d errno %d type %d(%d) info_len %u(%lu) key_size %u value_size %u max_entries %u map_flags %X\n", 354 "err %d errno %d type %d(%d) info_len %u(%lu) key_size %u value_size %u max_entries %u map_flags %X name %s(%s)\n",
383 err, errno, 355 err, errno,
384 map_infos[i].type, BPF_MAP_TYPE_ARRAY, 356 map_infos[i].type, BPF_MAP_TYPE_ARRAY,
385 info_len, sizeof(struct bpf_map_info), 357 info_len, sizeof(struct bpf_map_info),
386 map_infos[i].key_size, 358 map_infos[i].key_size,
387 map_infos[i].value_size, 359 map_infos[i].value_size,
388 map_infos[i].max_entries, 360 map_infos[i].max_entries,
389 map_infos[i].map_flags)) 361 map_infos[i].map_flags,
362 map_infos[i].name, expected_map_name))
363 goto done;
364
365 /* Check getting prog info */
366 info_len = sizeof(struct bpf_prog_info) * 2;
367 bzero(&prog_infos[i], info_len);
368 bzero(jited_insns, sizeof(jited_insns));
369 bzero(xlated_insns, sizeof(xlated_insns));
370 prog_infos[i].jited_prog_insns = ptr_to_u64(jited_insns);
371 prog_infos[i].jited_prog_len = sizeof(jited_insns);
372 prog_infos[i].xlated_prog_insns = ptr_to_u64(xlated_insns);
373 prog_infos[i].xlated_prog_len = sizeof(xlated_insns);
374 prog_infos[i].map_ids = ptr_to_u64(map_ids + i);
375 prog_infos[i].nr_map_ids = 2;
376 err = clock_gettime(CLOCK_REALTIME, &real_time_ts);
377 assert(!err);
378 err = clock_gettime(CLOCK_BOOTTIME, &boot_time_ts);
379 assert(!err);
380 err = bpf_obj_get_info_by_fd(prog_fds[i], &prog_infos[i],
381 &info_len);
382 load_time = (real_time_ts.tv_sec - boot_time_ts.tv_sec)
383 + (prog_infos[i].load_time / nsec_per_sec);
384 if (CHECK(err ||
385 prog_infos[i].type != BPF_PROG_TYPE_SOCKET_FILTER ||
386 info_len != sizeof(struct bpf_prog_info) ||
387 (jit_enabled && !prog_infos[i].jited_prog_len) ||
388 (jit_enabled &&
389 !memcmp(jited_insns, zeros, sizeof(zeros))) ||
390 !prog_infos[i].xlated_prog_len ||
391 !memcmp(xlated_insns, zeros, sizeof(zeros)) ||
392 load_time < now - 60 || load_time > now + 60 ||
393 prog_infos[i].created_by_uid != my_uid ||
394 prog_infos[i].nr_map_ids != 1 ||
395 *(int *)prog_infos[i].map_ids != map_infos[i].id ||
396 strcmp((char *)prog_infos[i].name, expected_prog_name),
397 "get-prog-info(fd)",
398 "err %d errno %d i %d type %d(%d) info_len %u(%lu) jit_enabled %d jited_prog_len %u xlated_prog_len %u jited_prog %d xlated_prog %d load_time %lu(%lu) uid %u(%u) nr_map_ids %u(%u) map_id %u(%u) name %s(%s)\n",
399 err, errno, i,
400 prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER,
401 info_len, sizeof(struct bpf_prog_info),
402 jit_enabled,
403 prog_infos[i].jited_prog_len,
404 prog_infos[i].xlated_prog_len,
405 !!memcmp(jited_insns, zeros, sizeof(zeros)),
406 !!memcmp(xlated_insns, zeros, sizeof(zeros)),
407 load_time, now,
408 prog_infos[i].created_by_uid, my_uid,
409 prog_infos[i].nr_map_ids, 1,
410 *(int *)prog_infos[i].map_ids, map_infos[i].id,
411 prog_infos[i].name, expected_prog_name))
390 goto done; 412 goto done;
391 } 413 }
392 414
@@ -394,7 +416,8 @@ static void test_bpf_obj_id(void)
394 nr_id_found = 0; 416 nr_id_found = 0;
395 next_id = 0; 417 next_id = 0;
396 while (!bpf_prog_get_next_id(next_id, &next_id)) { 418 while (!bpf_prog_get_next_id(next_id, &next_id)) {
397 struct bpf_prog_info prog_info; 419 struct bpf_prog_info prog_info = {};
420 __u32 saved_map_id;
398 int prog_fd; 421 int prog_fd;
399 422
400 info_len = sizeof(prog_info); 423 info_len = sizeof(prog_info);
@@ -417,14 +440,33 @@ static void test_bpf_obj_id(void)
417 440
418 nr_id_found++; 441 nr_id_found++;
419 442
443 /* Negative test:
444 * prog_info.nr_map_ids = 1
445 * prog_info.map_ids = NULL
446 */
447 prog_info.nr_map_ids = 1;
420 err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len); 448 err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len);
449 if (CHECK(!err || errno != EFAULT,
450 "get-prog-fd-bad-nr-map-ids", "err %d errno %d(%d)",
451 err, errno, EFAULT))
452 break;
453 bzero(&prog_info, sizeof(prog_info));
454 info_len = sizeof(prog_info);
455
456 saved_map_id = *(int *)(prog_infos[i].map_ids);
457 prog_info.map_ids = prog_infos[i].map_ids;
458 prog_info.nr_map_ids = 2;
459 err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len);
460 prog_infos[i].jited_prog_insns = 0;
461 prog_infos[i].xlated_prog_insns = 0;
421 CHECK(err || info_len != sizeof(struct bpf_prog_info) || 462 CHECK(err || info_len != sizeof(struct bpf_prog_info) ||
422 memcmp(&prog_info, &prog_infos[i], info_len), 463 memcmp(&prog_info, &prog_infos[i], info_len) ||
464 *(int *)prog_info.map_ids != saved_map_id,
423 "get-prog-info(next_id->fd)", 465 "get-prog-info(next_id->fd)",
424 "err %d errno %d info_len %u(%lu) memcmp %d\n", 466 "err %d errno %d info_len %u(%lu) memcmp %d map_id %u(%u)\n",
425 err, errno, info_len, sizeof(struct bpf_prog_info), 467 err, errno, info_len, sizeof(struct bpf_prog_info),
426 memcmp(&prog_info, &prog_infos[i], info_len)); 468 memcmp(&prog_info, &prog_infos[i], info_len),
427 469 *(int *)prog_info.map_ids, saved_map_id);
428 close(prog_fd); 470 close(prog_fd);
429 } 471 }
430 CHECK(nr_id_found != nr_iters, 472 CHECK(nr_id_found != nr_iters,
@@ -436,7 +478,7 @@ static void test_bpf_obj_id(void)
436 nr_id_found = 0; 478 nr_id_found = 0;
437 next_id = 0; 479 next_id = 0;
438 while (!bpf_map_get_next_id(next_id, &next_id)) { 480 while (!bpf_map_get_next_id(next_id, &next_id)) {
439 struct bpf_map_info map_info; 481 struct bpf_map_info map_info = {};
440 int map_fd; 482 int map_fd;
441 483
442 info_len = sizeof(map_info); 484 info_len = sizeof(map_info);
@@ -492,8 +534,10 @@ static void test_pkt_md_access(void)
492 int err, prog_fd; 534 int err, prog_fd;
493 535
494 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd); 536 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
495 if (err) 537 if (err) {
538 error_cnt++;
496 return; 539 return;
540 }
497 541
498 err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4), 542 err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4),
499 NULL, NULL, &retval, &duration); 543 NULL, NULL, &retval, &duration);
@@ -504,6 +548,75 @@ static void test_pkt_md_access(void)
504 bpf_object__close(obj); 548 bpf_object__close(obj);
505} 549}
506 550
551static void test_obj_name(void)
552{
553 struct {
554 const char *name;
555 int success;
556 int expected_errno;
557 } tests[] = {
558 { "", 1, 0 },
559 { "_123456789ABCDE", 1, 0 },
560 { "_123456789ABCDEF", 0, EINVAL },
561 { "_123456789ABCD\n", 0, EINVAL },
562 };
563 struct bpf_insn prog[] = {
564 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
565 BPF_EXIT_INSN(),
566 };
567 __u32 duration = 0;
568 int i;
569
570 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
571 size_t name_len = strlen(tests[i].name) + 1;
572 union bpf_attr attr;
573 size_t ncopy;
574 int fd;
575
576 /* test different attr.prog_name during BPF_PROG_LOAD */
577 ncopy = name_len < sizeof(attr.prog_name) ?
578 name_len : sizeof(attr.prog_name);
579 bzero(&attr, sizeof(attr));
580 attr.prog_type = BPF_PROG_TYPE_SCHED_CLS;
581 attr.insn_cnt = 2;
582 attr.insns = ptr_to_u64(prog);
583 attr.license = ptr_to_u64("");
584 memcpy(attr.prog_name, tests[i].name, ncopy);
585
586 fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
587 CHECK((tests[i].success && fd < 0) ||
588 (!tests[i].success && fd != -1) ||
589 (!tests[i].success && errno != tests[i].expected_errno),
590 "check-bpf-prog-name",
591 "fd %d(%d) errno %d(%d)\n",
592 fd, tests[i].success, errno, tests[i].expected_errno);
593
594 if (fd != -1)
595 close(fd);
596
597 /* test different attr.map_name during BPF_MAP_CREATE */
598 ncopy = name_len < sizeof(attr.map_name) ?
599 name_len : sizeof(attr.map_name);
600 bzero(&attr, sizeof(attr));
601 attr.map_type = BPF_MAP_TYPE_ARRAY;
602 attr.key_size = 4;
603 attr.value_size = 4;
604 attr.max_entries = 1;
605 attr.map_flags = 0;
606 memcpy(attr.map_name, tests[i].name, ncopy);
607 fd = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
608 CHECK((tests[i].success && fd < 0) ||
609 (!tests[i].success && fd != -1) ||
610 (!tests[i].success && errno != tests[i].expected_errno),
611 "check-bpf-map-name",
612 "fd %d(%d) errno %d(%d)\n",
613 fd, tests[i].success, errno, tests[i].expected_errno);
614
615 if (fd != -1)
616 close(fd);
617 }
618}
619
507int main(void) 620int main(void)
508{ 621{
509 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY }; 622 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
@@ -516,6 +629,7 @@ int main(void)
516 test_tcp_estats(); 629 test_tcp_estats();
517 test_bpf_obj_id(); 630 test_bpf_obj_id();
518 test_pkt_md_access(); 631 test_pkt_md_access();
632 test_obj_name();
519 633
520 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt); 634 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt);
521 return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; 635 return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/tools/testing/selftests/bpf/test_tag.c b/tools/testing/selftests/bpf/test_tag.c
index de409fc50c35..8b201895c569 100644
--- a/tools/testing/selftests/bpf/test_tag.c
+++ b/tools/testing/selftests/bpf/test_tag.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdint.h> 2#include <stdint.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <stdlib.h> 4#include <stdlib.h>
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index af7d173910f4..3c64f30cf63c 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -8,6 +8,7 @@
8 * License as published by the Free Software Foundation. 8 * License as published by the Free Software Foundation.
9 */ 9 */
10 10
11#include <endian.h>
11#include <asm/types.h> 12#include <asm/types.h>
12#include <linux/types.h> 13#include <linux/types.h>
13#include <stdint.h> 14#include <stdint.h>
@@ -421,7 +422,7 @@ static struct bpf_test tests[] = {
421 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0), 422 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
422 BPF_EXIT_INSN(), 423 BPF_EXIT_INSN(),
423 }, 424 },
424 .errstr_unpriv = "R1 pointer arithmetic", 425 .errstr_unpriv = "R1 subtraction from stack pointer",
425 .result_unpriv = REJECT, 426 .result_unpriv = REJECT,
426 .errstr = "R1 invalid mem access", 427 .errstr = "R1 invalid mem access",
427 .result = REJECT, 428 .result = REJECT,
@@ -603,8 +604,9 @@ static struct bpf_test tests[] = {
603 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4), 604 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4),
604 BPF_EXIT_INSN(), 605 BPF_EXIT_INSN(),
605 }, 606 },
606 .errstr = "misaligned access", 607 .errstr = "misaligned stack access",
607 .result = REJECT, 608 .result = REJECT,
609 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
608 }, 610 },
609 { 611 {
610 "invalid map_fd for function call", 612 "invalid map_fd for function call",
@@ -650,8 +652,9 @@ static struct bpf_test tests[] = {
650 BPF_EXIT_INSN(), 652 BPF_EXIT_INSN(),
651 }, 653 },
652 .fixup_map1 = { 3 }, 654 .fixup_map1 = { 3 },
653 .errstr = "misaligned access", 655 .errstr = "misaligned value access",
654 .result = REJECT, 656 .result = REJECT,
657 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
655 }, 658 },
656 { 659 {
657 "sometimes access memory with incorrect alignment", 660 "sometimes access memory with incorrect alignment",
@@ -672,6 +675,7 @@ static struct bpf_test tests[] = {
672 .errstr = "R0 invalid mem access", 675 .errstr = "R0 invalid mem access",
673 .errstr_unpriv = "R0 leaks addr", 676 .errstr_unpriv = "R0 leaks addr",
674 .result = REJECT, 677 .result = REJECT,
678 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
675 }, 679 },
676 { 680 {
677 "jump test 1", 681 "jump test 1",
@@ -963,6 +967,268 @@ static struct bpf_test tests[] = {
963 .result = REJECT, 967 .result = REJECT,
964 }, 968 },
965 { 969 {
970 "invalid access __sk_buff family",
971 .insns = {
972 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
973 offsetof(struct __sk_buff, family)),
974 BPF_EXIT_INSN(),
975 },
976 .errstr = "invalid bpf_context access",
977 .result = REJECT,
978 },
979 {
980 "invalid access __sk_buff remote_ip4",
981 .insns = {
982 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
983 offsetof(struct __sk_buff, remote_ip4)),
984 BPF_EXIT_INSN(),
985 },
986 .errstr = "invalid bpf_context access",
987 .result = REJECT,
988 },
989 {
990 "invalid access __sk_buff local_ip4",
991 .insns = {
992 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
993 offsetof(struct __sk_buff, local_ip4)),
994 BPF_EXIT_INSN(),
995 },
996 .errstr = "invalid bpf_context access",
997 .result = REJECT,
998 },
999 {
1000 "invalid access __sk_buff remote_ip6",
1001 .insns = {
1002 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1003 offsetof(struct __sk_buff, remote_ip6)),
1004 BPF_EXIT_INSN(),
1005 },
1006 .errstr = "invalid bpf_context access",
1007 .result = REJECT,
1008 },
1009 {
1010 "invalid access __sk_buff local_ip6",
1011 .insns = {
1012 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1013 offsetof(struct __sk_buff, local_ip6)),
1014 BPF_EXIT_INSN(),
1015 },
1016 .errstr = "invalid bpf_context access",
1017 .result = REJECT,
1018 },
1019 {
1020 "invalid access __sk_buff remote_port",
1021 .insns = {
1022 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1023 offsetof(struct __sk_buff, remote_port)),
1024 BPF_EXIT_INSN(),
1025 },
1026 .errstr = "invalid bpf_context access",
1027 .result = REJECT,
1028 },
1029 {
1030 "invalid access __sk_buff remote_port",
1031 .insns = {
1032 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1033 offsetof(struct __sk_buff, local_port)),
1034 BPF_EXIT_INSN(),
1035 },
1036 .errstr = "invalid bpf_context access",
1037 .result = REJECT,
1038 },
1039 {
1040 "valid access __sk_buff family",
1041 .insns = {
1042 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1043 offsetof(struct __sk_buff, family)),
1044 BPF_EXIT_INSN(),
1045 },
1046 .result = ACCEPT,
1047 .prog_type = BPF_PROG_TYPE_SK_SKB,
1048 },
1049 {
1050 "valid access __sk_buff remote_ip4",
1051 .insns = {
1052 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1053 offsetof(struct __sk_buff, remote_ip4)),
1054 BPF_EXIT_INSN(),
1055 },
1056 .result = ACCEPT,
1057 .prog_type = BPF_PROG_TYPE_SK_SKB,
1058 },
1059 {
1060 "valid access __sk_buff local_ip4",
1061 .insns = {
1062 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1063 offsetof(struct __sk_buff, local_ip4)),
1064 BPF_EXIT_INSN(),
1065 },
1066 .result = ACCEPT,
1067 .prog_type = BPF_PROG_TYPE_SK_SKB,
1068 },
1069 {
1070 "valid access __sk_buff remote_ip6",
1071 .insns = {
1072 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1073 offsetof(struct __sk_buff, remote_ip6[0])),
1074 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1075 offsetof(struct __sk_buff, remote_ip6[1])),
1076 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1077 offsetof(struct __sk_buff, remote_ip6[2])),
1078 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1079 offsetof(struct __sk_buff, remote_ip6[3])),
1080 BPF_EXIT_INSN(),
1081 },
1082 .result = ACCEPT,
1083 .prog_type = BPF_PROG_TYPE_SK_SKB,
1084 },
1085 {
1086 "valid access __sk_buff local_ip6",
1087 .insns = {
1088 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1089 offsetof(struct __sk_buff, local_ip6[0])),
1090 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1091 offsetof(struct __sk_buff, local_ip6[1])),
1092 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1093 offsetof(struct __sk_buff, local_ip6[2])),
1094 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1095 offsetof(struct __sk_buff, local_ip6[3])),
1096 BPF_EXIT_INSN(),
1097 },
1098 .result = ACCEPT,
1099 .prog_type = BPF_PROG_TYPE_SK_SKB,
1100 },
1101 {
1102 "valid access __sk_buff remote_port",
1103 .insns = {
1104 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1105 offsetof(struct __sk_buff, remote_port)),
1106 BPF_EXIT_INSN(),
1107 },
1108 .result = ACCEPT,
1109 .prog_type = BPF_PROG_TYPE_SK_SKB,
1110 },
1111 {
1112 "valid access __sk_buff remote_port",
1113 .insns = {
1114 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1115 offsetof(struct __sk_buff, local_port)),
1116 BPF_EXIT_INSN(),
1117 },
1118 .result = ACCEPT,
1119 .prog_type = BPF_PROG_TYPE_SK_SKB,
1120 },
1121 {
1122 "invalid access of tc_classid for SK_SKB",
1123 .insns = {
1124 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1125 offsetof(struct __sk_buff, tc_classid)),
1126 BPF_EXIT_INSN(),
1127 },
1128 .result = REJECT,
1129 .prog_type = BPF_PROG_TYPE_SK_SKB,
1130 .errstr = "invalid bpf_context access",
1131 },
1132 {
1133 "invalid access of skb->mark for SK_SKB",
1134 .insns = {
1135 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1136 offsetof(struct __sk_buff, mark)),
1137 BPF_EXIT_INSN(),
1138 },
1139 .result = REJECT,
1140 .prog_type = BPF_PROG_TYPE_SK_SKB,
1141 .errstr = "invalid bpf_context access",
1142 },
1143 {
1144 "check skb->mark is not writeable by SK_SKB",
1145 .insns = {
1146 BPF_MOV64_IMM(BPF_REG_0, 0),
1147 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1148 offsetof(struct __sk_buff, mark)),
1149 BPF_EXIT_INSN(),
1150 },
1151 .result = REJECT,
1152 .prog_type = BPF_PROG_TYPE_SK_SKB,
1153 .errstr = "invalid bpf_context access",
1154 },
1155 {
1156 "check skb->tc_index is writeable by SK_SKB",
1157 .insns = {
1158 BPF_MOV64_IMM(BPF_REG_0, 0),
1159 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1160 offsetof(struct __sk_buff, tc_index)),
1161 BPF_EXIT_INSN(),
1162 },
1163 .result = ACCEPT,
1164 .prog_type = BPF_PROG_TYPE_SK_SKB,
1165 },
1166 {
1167 "check skb->priority is writeable by SK_SKB",
1168 .insns = {
1169 BPF_MOV64_IMM(BPF_REG_0, 0),
1170 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1171 offsetof(struct __sk_buff, priority)),
1172 BPF_EXIT_INSN(),
1173 },
1174 .result = ACCEPT,
1175 .prog_type = BPF_PROG_TYPE_SK_SKB,
1176 },
1177 {
1178 "direct packet read for SK_SKB",
1179 .insns = {
1180 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
1181 offsetof(struct __sk_buff, data)),
1182 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
1183 offsetof(struct __sk_buff, data_end)),
1184 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
1185 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
1186 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
1187 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
1188 BPF_MOV64_IMM(BPF_REG_0, 0),
1189 BPF_EXIT_INSN(),
1190 },
1191 .result = ACCEPT,
1192 .prog_type = BPF_PROG_TYPE_SK_SKB,
1193 },
1194 {
1195 "direct packet write for SK_SKB",
1196 .insns = {
1197 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
1198 offsetof(struct __sk_buff, data)),
1199 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
1200 offsetof(struct __sk_buff, data_end)),
1201 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
1202 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
1203 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
1204 BPF_STX_MEM(BPF_B, BPF_REG_2, BPF_REG_2, 0),
1205 BPF_MOV64_IMM(BPF_REG_0, 0),
1206 BPF_EXIT_INSN(),
1207 },
1208 .result = ACCEPT,
1209 .prog_type = BPF_PROG_TYPE_SK_SKB,
1210 },
1211 {
1212 "overlapping checks for direct packet access SK_SKB",
1213 .insns = {
1214 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
1215 offsetof(struct __sk_buff, data)),
1216 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
1217 offsetof(struct __sk_buff, data_end)),
1218 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
1219 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
1220 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 4),
1221 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
1222 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6),
1223 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
1224 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_2, 6),
1225 BPF_MOV64_IMM(BPF_REG_0, 0),
1226 BPF_EXIT_INSN(),
1227 },
1228 .result = ACCEPT,
1229 .prog_type = BPF_PROG_TYPE_SK_SKB,
1230 },
1231 {
966 "check skb->mark is not writeable by sockets", 1232 "check skb->mark is not writeable by sockets",
967 .insns = { 1233 .insns = {
968 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 1234 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
@@ -1098,7 +1364,7 @@ static struct bpf_test tests[] = {
1098 "check skb->hash byte load permitted", 1364 "check skb->hash byte load permitted",
1099 .insns = { 1365 .insns = {
1100 BPF_MOV64_IMM(BPF_REG_0, 0), 1366 BPF_MOV64_IMM(BPF_REG_0, 0),
1101#ifdef __LITTLE_ENDIAN 1367#if __BYTE_ORDER == __LITTLE_ENDIAN
1102 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 1368 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
1103 offsetof(struct __sk_buff, hash)), 1369 offsetof(struct __sk_buff, hash)),
1104#else 1370#else
@@ -1135,7 +1401,7 @@ static struct bpf_test tests[] = {
1135 "check skb->hash byte load not permitted 3", 1401 "check skb->hash byte load not permitted 3",
1136 .insns = { 1402 .insns = {
1137 BPF_MOV64_IMM(BPF_REG_0, 0), 1403 BPF_MOV64_IMM(BPF_REG_0, 0),
1138#ifdef __LITTLE_ENDIAN 1404#if __BYTE_ORDER == __LITTLE_ENDIAN
1139 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 1405 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
1140 offsetof(struct __sk_buff, hash) + 3), 1406 offsetof(struct __sk_buff, hash) + 3),
1141#else 1407#else
@@ -1215,8 +1481,9 @@ static struct bpf_test tests[] = {
1215 offsetof(struct __sk_buff, cb[0]) + 1), 1481 offsetof(struct __sk_buff, cb[0]) + 1),
1216 BPF_EXIT_INSN(), 1482 BPF_EXIT_INSN(),
1217 }, 1483 },
1218 .errstr = "misaligned access", 1484 .errstr = "misaligned context access",
1219 .result = REJECT, 1485 .result = REJECT,
1486 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1220 }, 1487 },
1221 { 1488 {
1222 "check __sk_buff->hash, offset 0, half store not permitted", 1489 "check __sk_buff->hash, offset 0, half store not permitted",
@@ -1244,7 +1511,7 @@ static struct bpf_test tests[] = {
1244 "check skb->hash half load permitted", 1511 "check skb->hash half load permitted",
1245 .insns = { 1512 .insns = {
1246 BPF_MOV64_IMM(BPF_REG_0, 0), 1513 BPF_MOV64_IMM(BPF_REG_0, 0),
1247#ifdef __LITTLE_ENDIAN 1514#if __BYTE_ORDER == __LITTLE_ENDIAN
1248 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 1515 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1249 offsetof(struct __sk_buff, hash)), 1516 offsetof(struct __sk_buff, hash)),
1250#else 1517#else
@@ -1259,7 +1526,7 @@ static struct bpf_test tests[] = {
1259 "check skb->hash half load not permitted", 1526 "check skb->hash half load not permitted",
1260 .insns = { 1527 .insns = {
1261 BPF_MOV64_IMM(BPF_REG_0, 0), 1528 BPF_MOV64_IMM(BPF_REG_0, 0),
1262#ifdef __LITTLE_ENDIAN 1529#if __BYTE_ORDER == __LITTLE_ENDIAN
1263 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 1530 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1264 offsetof(struct __sk_buff, hash) + 2), 1531 offsetof(struct __sk_buff, hash) + 2),
1265#else 1532#else
@@ -1319,8 +1586,9 @@ static struct bpf_test tests[] = {
1319 offsetof(struct __sk_buff, cb[0]) + 2), 1586 offsetof(struct __sk_buff, cb[0]) + 2),
1320 BPF_EXIT_INSN(), 1587 BPF_EXIT_INSN(),
1321 }, 1588 },
1322 .errstr = "misaligned access", 1589 .errstr = "misaligned context access",
1323 .result = REJECT, 1590 .result = REJECT,
1591 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1324 }, 1592 },
1325 { 1593 {
1326 "check cb access: word, unaligned 2", 1594 "check cb access: word, unaligned 2",
@@ -1330,8 +1598,9 @@ static struct bpf_test tests[] = {
1330 offsetof(struct __sk_buff, cb[4]) + 1), 1598 offsetof(struct __sk_buff, cb[4]) + 1),
1331 BPF_EXIT_INSN(), 1599 BPF_EXIT_INSN(),
1332 }, 1600 },
1333 .errstr = "misaligned access", 1601 .errstr = "misaligned context access",
1334 .result = REJECT, 1602 .result = REJECT,
1603 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1335 }, 1604 },
1336 { 1605 {
1337 "check cb access: word, unaligned 3", 1606 "check cb access: word, unaligned 3",
@@ -1341,8 +1610,9 @@ static struct bpf_test tests[] = {
1341 offsetof(struct __sk_buff, cb[4]) + 2), 1610 offsetof(struct __sk_buff, cb[4]) + 2),
1342 BPF_EXIT_INSN(), 1611 BPF_EXIT_INSN(),
1343 }, 1612 },
1344 .errstr = "misaligned access", 1613 .errstr = "misaligned context access",
1345 .result = REJECT, 1614 .result = REJECT,
1615 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1346 }, 1616 },
1347 { 1617 {
1348 "check cb access: word, unaligned 4", 1618 "check cb access: word, unaligned 4",
@@ -1352,8 +1622,9 @@ static struct bpf_test tests[] = {
1352 offsetof(struct __sk_buff, cb[4]) + 3), 1622 offsetof(struct __sk_buff, cb[4]) + 3),
1353 BPF_EXIT_INSN(), 1623 BPF_EXIT_INSN(),
1354 }, 1624 },
1355 .errstr = "misaligned access", 1625 .errstr = "misaligned context access",
1356 .result = REJECT, 1626 .result = REJECT,
1627 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1357 }, 1628 },
1358 { 1629 {
1359 "check cb access: double", 1630 "check cb access: double",
@@ -1379,8 +1650,9 @@ static struct bpf_test tests[] = {
1379 offsetof(struct __sk_buff, cb[1])), 1650 offsetof(struct __sk_buff, cb[1])),
1380 BPF_EXIT_INSN(), 1651 BPF_EXIT_INSN(),
1381 }, 1652 },
1382 .errstr = "misaligned access", 1653 .errstr = "misaligned context access",
1383 .result = REJECT, 1654 .result = REJECT,
1655 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1384 }, 1656 },
1385 { 1657 {
1386 "check cb access: double, unaligned 2", 1658 "check cb access: double, unaligned 2",
@@ -1390,8 +1662,9 @@ static struct bpf_test tests[] = {
1390 offsetof(struct __sk_buff, cb[3])), 1662 offsetof(struct __sk_buff, cb[3])),
1391 BPF_EXIT_INSN(), 1663 BPF_EXIT_INSN(),
1392 }, 1664 },
1393 .errstr = "misaligned access", 1665 .errstr = "misaligned context access",
1394 .result = REJECT, 1666 .result = REJECT,
1667 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1395 }, 1668 },
1396 { 1669 {
1397 "check cb access: double, oob 1", 1670 "check cb access: double, oob 1",
@@ -1523,7 +1796,8 @@ static struct bpf_test tests[] = {
1523 BPF_EXIT_INSN(), 1796 BPF_EXIT_INSN(),
1524 }, 1797 },
1525 .result = REJECT, 1798 .result = REJECT,
1526 .errstr = "misaligned access off -6 size 8", 1799 .errstr = "misaligned stack access off (0x0; 0x0)+-8+2 size 8",
1800 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1527 }, 1801 },
1528 { 1802 {
1529 "PTR_TO_STACK store/load - bad alignment on reg", 1803 "PTR_TO_STACK store/load - bad alignment on reg",
@@ -1535,7 +1809,8 @@ static struct bpf_test tests[] = {
1535 BPF_EXIT_INSN(), 1809 BPF_EXIT_INSN(),
1536 }, 1810 },
1537 .result = REJECT, 1811 .result = REJECT,
1538 .errstr = "misaligned access off -2 size 8", 1812 .errstr = "misaligned stack access off (0x0; 0x0)+-10+8 size 8",
1813 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1539 }, 1814 },
1540 { 1815 {
1541 "PTR_TO_STACK store/load - out of bounds low", 1816 "PTR_TO_STACK store/load - out of bounds low",
@@ -1579,8 +1854,6 @@ static struct bpf_test tests[] = {
1579 BPF_EXIT_INSN(), 1854 BPF_EXIT_INSN(),
1580 }, 1855 },
1581 .result = ACCEPT, 1856 .result = ACCEPT,
1582 .result_unpriv = REJECT,
1583 .errstr_unpriv = "R1 pointer arithmetic",
1584 }, 1857 },
1585 { 1858 {
1586 "unpriv: add pointer to pointer", 1859 "unpriv: add pointer to pointer",
@@ -1591,7 +1864,7 @@ static struct bpf_test tests[] = {
1591 }, 1864 },
1592 .result = ACCEPT, 1865 .result = ACCEPT,
1593 .result_unpriv = REJECT, 1866 .result_unpriv = REJECT,
1594 .errstr_unpriv = "R1 pointer arithmetic", 1867 .errstr_unpriv = "R1 pointer += pointer",
1595 }, 1868 },
1596 { 1869 {
1597 "unpriv: neg pointer", 1870 "unpriv: neg pointer",
@@ -1932,10 +2205,7 @@ static struct bpf_test tests[] = {
1932 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8), 2205 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8),
1933 BPF_EXIT_INSN(), 2206 BPF_EXIT_INSN(),
1934 }, 2207 },
1935 .errstr_unpriv = "pointer arithmetic prohibited", 2208 .result = ACCEPT,
1936 .result_unpriv = REJECT,
1937 .errstr = "R1 invalid mem access",
1938 .result = REJECT,
1939 }, 2209 },
1940 { 2210 {
1941 "unpriv: cmp of stack pointer", 2211 "unpriv: cmp of stack pointer",
@@ -1999,7 +2269,7 @@ static struct bpf_test tests[] = {
1999 BPF_EXIT_INSN(), 2269 BPF_EXIT_INSN(),
2000 }, 2270 },
2001 .result = REJECT, 2271 .result = REJECT,
2002 .errstr = "invalid stack type R3", 2272 .errstr = "R4 min value is negative",
2003 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2273 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2004 }, 2274 },
2005 { 2275 {
@@ -2016,7 +2286,7 @@ static struct bpf_test tests[] = {
2016 BPF_EXIT_INSN(), 2286 BPF_EXIT_INSN(),
2017 }, 2287 },
2018 .result = REJECT, 2288 .result = REJECT,
2019 .errstr = "invalid stack type R3", 2289 .errstr = "R4 min value is negative",
2020 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2290 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2021 }, 2291 },
2022 { 2292 {
@@ -2218,7 +2488,7 @@ static struct bpf_test tests[] = {
2218 BPF_EXIT_INSN(), 2488 BPF_EXIT_INSN(),
2219 }, 2489 },
2220 .result = REJECT, 2490 .result = REJECT,
2221 .errstr = "invalid stack type R3 off=-1 access_size=-1", 2491 .errstr = "R4 min value is negative",
2222 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2492 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2223 }, 2493 },
2224 { 2494 {
@@ -2235,7 +2505,7 @@ static struct bpf_test tests[] = {
2235 BPF_EXIT_INSN(), 2505 BPF_EXIT_INSN(),
2236 }, 2506 },
2237 .result = REJECT, 2507 .result = REJECT,
2238 .errstr = "invalid stack type R3 off=-1 access_size=2147483647", 2508 .errstr = "R4 unbounded memory access, use 'var &= const' or 'if (var < const)'",
2239 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2509 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2240 }, 2510 },
2241 { 2511 {
@@ -2252,7 +2522,7 @@ static struct bpf_test tests[] = {
2252 BPF_EXIT_INSN(), 2522 BPF_EXIT_INSN(),
2253 }, 2523 },
2254 .result = REJECT, 2524 .result = REJECT,
2255 .errstr = "invalid stack type R3 off=-512 access_size=2147483647", 2525 .errstr = "R4 unbounded memory access, use 'var &= const' or 'if (var < const)'",
2256 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2526 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2257 }, 2527 },
2258 { 2528 {
@@ -2323,8 +2593,8 @@ static struct bpf_test tests[] = {
2323 offsetof(struct __sk_buff, data)), 2593 offsetof(struct __sk_buff, data)),
2324 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_4), 2594 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_4),
2325 BPF_MOV64_REG(BPF_REG_2, BPF_REG_1), 2595 BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
2326 BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 48), 2596 BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 49),
2327 BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 48), 2597 BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 49),
2328 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_2), 2598 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_2),
2329 BPF_MOV64_REG(BPF_REG_2, BPF_REG_3), 2599 BPF_MOV64_REG(BPF_REG_2, BPF_REG_3),
2330 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 8), 2600 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 8),
@@ -2652,7 +2922,7 @@ static struct bpf_test tests[] = {
2652 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1), 2922 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
2653 BPF_JMP_A(-6), 2923 BPF_JMP_A(-6),
2654 }, 2924 },
2655 .errstr = "misaligned packet access off 2+15+-4 size 4", 2925 .errstr = "misaligned packet access off 2+(0x0; 0x0)+15+-4 size 4",
2656 .result = REJECT, 2926 .result = REJECT,
2657 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2927 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2658 .flags = F_LOAD_WITH_STRICT_ALIGNMENT, 2928 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
@@ -2703,11 +2973,11 @@ static struct bpf_test tests[] = {
2703 BPF_MOV64_IMM(BPF_REG_0, 0xffffffff), 2973 BPF_MOV64_IMM(BPF_REG_0, 0xffffffff),
2704 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8), 2974 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
2705 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), 2975 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
2706 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffff), 2976 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0x7fff),
2707 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0), 2977 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
2708 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2), 2978 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2),
2709 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4), 2979 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4),
2710 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0xffff - 1), 2980 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0x7fff - 1),
2711 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1), 2981 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1),
2712 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0), 2982 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
2713 BPF_MOV64_IMM(BPF_REG_0, 0), 2983 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -2729,10 +2999,10 @@ static struct bpf_test tests[] = {
2729 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff), 2999 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff),
2730 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_4, -8), 3000 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_4, -8),
2731 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8), 3001 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8),
2732 BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 0xffff), 3002 BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 0x7fff),
2733 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2), 3003 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2),
2734 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4), 3004 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4),
2735 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0xffff - 1), 3005 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0x7fff - 1),
2736 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1), 3006 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1),
2737 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0), 3007 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
2738 BPF_MOV64_IMM(BPF_REG_0, 0), 3008 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -2758,7 +3028,7 @@ static struct bpf_test tests[] = {
2758 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff), 3028 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff),
2759 BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_4, -8), 3029 BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_4, -8),
2760 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8), 3030 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8),
2761 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 48), 3031 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 49),
2762 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2), 3032 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2),
2763 BPF_MOV64_REG(BPF_REG_0, BPF_REG_4), 3033 BPF_MOV64_REG(BPF_REG_0, BPF_REG_4),
2764 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2), 3034 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2),
@@ -2795,7 +3065,7 @@ static struct bpf_test tests[] = {
2795 }, 3065 },
2796 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3066 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2797 .result = REJECT, 3067 .result = REJECT,
2798 .errstr = "cannot add integer value with 47 upper zero bits to ptr_to_packet", 3068 .errstr = "invalid access to packet, off=0 size=8, R5(id=1,off=0,r=0)",
2799 }, 3069 },
2800 { 3070 {
2801 "direct packet access: test24 (x += pkt_ptr, 5)", 3071 "direct packet access: test24 (x += pkt_ptr, 5)",
@@ -2813,7 +3083,7 @@ static struct bpf_test tests[] = {
2813 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_4), 3083 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_4),
2814 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2), 3084 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
2815 BPF_MOV64_REG(BPF_REG_5, BPF_REG_0), 3085 BPF_MOV64_REG(BPF_REG_5, BPF_REG_0),
2816 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0xffff - 1), 3086 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x7fff - 1),
2817 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1), 3087 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
2818 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_0, 0), 3088 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_0, 0),
2819 BPF_MOV64_IMM(BPF_REG_0, 0), 3089 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -2823,6 +3093,79 @@ static struct bpf_test tests[] = {
2823 .result = ACCEPT, 3093 .result = ACCEPT,
2824 }, 3094 },
2825 { 3095 {
3096 "direct packet access: test25 (marking on <, good access)",
3097 .insns = {
3098 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
3099 offsetof(struct __sk_buff, data)),
3100 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
3101 offsetof(struct __sk_buff, data_end)),
3102 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3103 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
3104 BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_3, 2),
3105 BPF_MOV64_IMM(BPF_REG_0, 0),
3106 BPF_EXIT_INSN(),
3107 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
3108 BPF_JMP_IMM(BPF_JA, 0, 0, -4),
3109 },
3110 .result = ACCEPT,
3111 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3112 },
3113 {
3114 "direct packet access: test26 (marking on <, bad access)",
3115 .insns = {
3116 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
3117 offsetof(struct __sk_buff, data)),
3118 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
3119 offsetof(struct __sk_buff, data_end)),
3120 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3121 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
3122 BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_3, 3),
3123 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
3124 BPF_MOV64_IMM(BPF_REG_0, 0),
3125 BPF_EXIT_INSN(),
3126 BPF_JMP_IMM(BPF_JA, 0, 0, -3),
3127 },
3128 .result = REJECT,
3129 .errstr = "invalid access to packet",
3130 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3131 },
3132 {
3133 "direct packet access: test27 (marking on <=, good access)",
3134 .insns = {
3135 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
3136 offsetof(struct __sk_buff, data)),
3137 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
3138 offsetof(struct __sk_buff, data_end)),
3139 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3140 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
3141 BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_0, 1),
3142 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
3143 BPF_MOV64_IMM(BPF_REG_0, 1),
3144 BPF_EXIT_INSN(),
3145 },
3146 .result = ACCEPT,
3147 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3148 },
3149 {
3150 "direct packet access: test28 (marking on <=, bad access)",
3151 .insns = {
3152 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
3153 offsetof(struct __sk_buff, data)),
3154 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
3155 offsetof(struct __sk_buff, data_end)),
3156 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3157 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
3158 BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_0, 2),
3159 BPF_MOV64_IMM(BPF_REG_0, 1),
3160 BPF_EXIT_INSN(),
3161 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
3162 BPF_JMP_IMM(BPF_JA, 0, 0, -4),
3163 },
3164 .result = REJECT,
3165 .errstr = "invalid access to packet",
3166 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3167 },
3168 {
2826 "helper access to packet: test1, valid packet_ptr range", 3169 "helper access to packet: test1, valid packet_ptr range",
2827 .insns = { 3170 .insns = {
2828 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 3171 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
@@ -3112,7 +3455,7 @@ static struct bpf_test tests[] = {
3112 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3455 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3113 }, 3456 },
3114 { 3457 {
3115 "helper access to packet: test14, cls helper fail sub", 3458 "helper access to packet: test14, cls helper ok sub",
3116 .insns = { 3459 .insns = {
3117 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3460 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3118 offsetof(struct __sk_buff, data)), 3461 offsetof(struct __sk_buff, data)),
@@ -3132,12 +3475,36 @@ static struct bpf_test tests[] = {
3132 BPF_MOV64_IMM(BPF_REG_0, 0), 3475 BPF_MOV64_IMM(BPF_REG_0, 0),
3133 BPF_EXIT_INSN(), 3476 BPF_EXIT_INSN(),
3134 }, 3477 },
3478 .result = ACCEPT,
3479 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3480 },
3481 {
3482 "helper access to packet: test15, cls helper fail sub",
3483 .insns = {
3484 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3485 offsetof(struct __sk_buff, data)),
3486 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
3487 offsetof(struct __sk_buff, data_end)),
3488 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
3489 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
3490 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7),
3491 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_7, 6),
3492 BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 12),
3493 BPF_MOV64_IMM(BPF_REG_2, 4),
3494 BPF_MOV64_IMM(BPF_REG_3, 0),
3495 BPF_MOV64_IMM(BPF_REG_4, 0),
3496 BPF_MOV64_IMM(BPF_REG_5, 0),
3497 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
3498 BPF_FUNC_csum_diff),
3499 BPF_MOV64_IMM(BPF_REG_0, 0),
3500 BPF_EXIT_INSN(),
3501 },
3135 .result = REJECT, 3502 .result = REJECT,
3136 .errstr = "type=inv expected=fp", 3503 .errstr = "invalid access to packet",
3137 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3504 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3138 }, 3505 },
3139 { 3506 {
3140 "helper access to packet: test15, cls helper fail range 1", 3507 "helper access to packet: test16, cls helper fail range 1",
3141 .insns = { 3508 .insns = {
3142 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3509 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3143 offsetof(struct __sk_buff, data)), 3510 offsetof(struct __sk_buff, data)),
@@ -3162,7 +3529,7 @@ static struct bpf_test tests[] = {
3162 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3529 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3163 }, 3530 },
3164 { 3531 {
3165 "helper access to packet: test16, cls helper fail range 2", 3532 "helper access to packet: test17, cls helper fail range 2",
3166 .insns = { 3533 .insns = {
3167 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3534 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3168 offsetof(struct __sk_buff, data)), 3535 offsetof(struct __sk_buff, data)),
@@ -3183,11 +3550,11 @@ static struct bpf_test tests[] = {
3183 BPF_EXIT_INSN(), 3550 BPF_EXIT_INSN(),
3184 }, 3551 },
3185 .result = REJECT, 3552 .result = REJECT,
3186 .errstr = "invalid access to packet", 3553 .errstr = "R2 min value is negative",
3187 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3554 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3188 }, 3555 },
3189 { 3556 {
3190 "helper access to packet: test17, cls helper fail range 3", 3557 "helper access to packet: test18, cls helper fail range 3",
3191 .insns = { 3558 .insns = {
3192 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3559 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3193 offsetof(struct __sk_buff, data)), 3560 offsetof(struct __sk_buff, data)),
@@ -3208,11 +3575,11 @@ static struct bpf_test tests[] = {
3208 BPF_EXIT_INSN(), 3575 BPF_EXIT_INSN(),
3209 }, 3576 },
3210 .result = REJECT, 3577 .result = REJECT,
3211 .errstr = "invalid access to packet", 3578 .errstr = "R2 min value is negative",
3212 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3579 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3213 }, 3580 },
3214 { 3581 {
3215 "helper access to packet: test18, cls helper fail range zero", 3582 "helper access to packet: test19, cls helper range zero",
3216 .insns = { 3583 .insns = {
3217 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3584 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3218 offsetof(struct __sk_buff, data)), 3585 offsetof(struct __sk_buff, data)),
@@ -3232,12 +3599,11 @@ static struct bpf_test tests[] = {
3232 BPF_MOV64_IMM(BPF_REG_0, 0), 3599 BPF_MOV64_IMM(BPF_REG_0, 0),
3233 BPF_EXIT_INSN(), 3600 BPF_EXIT_INSN(),
3234 }, 3601 },
3235 .result = REJECT, 3602 .result = ACCEPT,
3236 .errstr = "invalid access to packet",
3237 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3603 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3238 }, 3604 },
3239 { 3605 {
3240 "helper access to packet: test19, pkt end as input", 3606 "helper access to packet: test20, pkt end as input",
3241 .insns = { 3607 .insns = {
3242 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3608 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3243 offsetof(struct __sk_buff, data)), 3609 offsetof(struct __sk_buff, data)),
@@ -3262,7 +3628,7 @@ static struct bpf_test tests[] = {
3262 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3628 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3263 }, 3629 },
3264 { 3630 {
3265 "helper access to packet: test20, wrong reg", 3631 "helper access to packet: test21, wrong reg",
3266 .insns = { 3632 .insns = {
3267 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3633 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3268 offsetof(struct __sk_buff, data)), 3634 offsetof(struct __sk_buff, data)),
@@ -3322,7 +3688,7 @@ static struct bpf_test tests[] = {
3322 BPF_EXIT_INSN(), 3688 BPF_EXIT_INSN(),
3323 }, 3689 },
3324 .fixup_map2 = { 3 }, 3690 .fixup_map2 = { 3 },
3325 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3691 .errstr_unpriv = "R0 leaks addr",
3326 .result_unpriv = REJECT, 3692 .result_unpriv = REJECT,
3327 .result = ACCEPT, 3693 .result = ACCEPT,
3328 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3694 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3346,7 +3712,7 @@ static struct bpf_test tests[] = {
3346 BPF_EXIT_INSN(), 3712 BPF_EXIT_INSN(),
3347 }, 3713 },
3348 .fixup_map2 = { 3 }, 3714 .fixup_map2 = { 3 },
3349 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3715 .errstr_unpriv = "R0 leaks addr",
3350 .result_unpriv = REJECT, 3716 .result_unpriv = REJECT,
3351 .result = ACCEPT, 3717 .result = ACCEPT,
3352 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3718 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3374,7 +3740,7 @@ static struct bpf_test tests[] = {
3374 BPF_EXIT_INSN(), 3740 BPF_EXIT_INSN(),
3375 }, 3741 },
3376 .fixup_map2 = { 3 }, 3742 .fixup_map2 = { 3 },
3377 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3743 .errstr_unpriv = "R0 leaks addr",
3378 .result_unpriv = REJECT, 3744 .result_unpriv = REJECT,
3379 .result = ACCEPT, 3745 .result = ACCEPT,
3380 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3746 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3415,9 +3781,7 @@ static struct bpf_test tests[] = {
3415 BPF_EXIT_INSN(), 3781 BPF_EXIT_INSN(),
3416 }, 3782 },
3417 .fixup_map2 = { 3 }, 3783 .fixup_map2 = { 3 },
3418 .errstr_unpriv = "R0 pointer arithmetic prohibited",
3419 .errstr = "R0 min value is outside of the array range", 3784 .errstr = "R0 min value is outside of the array range",
3420 .result_unpriv = REJECT,
3421 .result = REJECT, 3785 .result = REJECT,
3422 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3786 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3423 }, 3787 },
@@ -3439,9 +3803,7 @@ static struct bpf_test tests[] = {
3439 BPF_EXIT_INSN(), 3803 BPF_EXIT_INSN(),
3440 }, 3804 },
3441 .fixup_map2 = { 3 }, 3805 .fixup_map2 = { 3 },
3442 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3806 .errstr = "R0 unbounded memory access, make sure to bounds check any array access into a map",
3443 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
3444 .result_unpriv = REJECT,
3445 .result = REJECT, 3807 .result = REJECT,
3446 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3808 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3447 }, 3809 },
@@ -3455,7 +3817,7 @@ static struct bpf_test tests[] = {
3455 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 3817 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
3456 BPF_FUNC_map_lookup_elem), 3818 BPF_FUNC_map_lookup_elem),
3457 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7), 3819 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
3458 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0), 3820 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
3459 BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES), 3821 BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES),
3460 BPF_JMP_REG(BPF_JSGT, BPF_REG_2, BPF_REG_1, 1), 3822 BPF_JMP_REG(BPF_JSGT, BPF_REG_2, BPF_REG_1, 1),
3461 BPF_MOV32_IMM(BPF_REG_1, 0), 3823 BPF_MOV32_IMM(BPF_REG_1, 0),
@@ -3466,8 +3828,8 @@ static struct bpf_test tests[] = {
3466 BPF_EXIT_INSN(), 3828 BPF_EXIT_INSN(),
3467 }, 3829 },
3468 .fixup_map2 = { 3 }, 3830 .fixup_map2 = { 3 },
3469 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3831 .errstr_unpriv = "R0 leaks addr",
3470 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", 3832 .errstr = "R0 unbounded memory access",
3471 .result_unpriv = REJECT, 3833 .result_unpriv = REJECT,
3472 .result = REJECT, 3834 .result = REJECT,
3473 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3835 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3493,7 +3855,7 @@ static struct bpf_test tests[] = {
3493 BPF_EXIT_INSN(), 3855 BPF_EXIT_INSN(),
3494 }, 3856 },
3495 .fixup_map2 = { 3 }, 3857 .fixup_map2 = { 3 },
3496 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3858 .errstr_unpriv = "R0 leaks addr",
3497 .errstr = "invalid access to map value, value_size=48 off=44 size=8", 3859 .errstr = "invalid access to map value, value_size=48 off=44 size=8",
3498 .result_unpriv = REJECT, 3860 .result_unpriv = REJECT,
3499 .result = REJECT, 3861 .result = REJECT,
@@ -3523,8 +3885,8 @@ static struct bpf_test tests[] = {
3523 BPF_EXIT_INSN(), 3885 BPF_EXIT_INSN(),
3524 }, 3886 },
3525 .fixup_map2 = { 3, 11 }, 3887 .fixup_map2 = { 3, 11 },
3526 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3888 .errstr_unpriv = "R0 pointer += pointer",
3527 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", 3889 .errstr = "R0 invalid mem access 'inv'",
3528 .result_unpriv = REJECT, 3890 .result_unpriv = REJECT,
3529 .result = REJECT, 3891 .result = REJECT,
3530 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3892 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3666,34 +4028,6 @@ static struct bpf_test tests[] = {
3666 .prog_type = BPF_PROG_TYPE_SCHED_CLS 4028 .prog_type = BPF_PROG_TYPE_SCHED_CLS
3667 }, 4029 },
3668 { 4030 {
3669 "multiple registers share map_lookup_elem bad reg type",
3670 .insns = {
3671 BPF_MOV64_IMM(BPF_REG_1, 10),
3672 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
3673 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3674 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3675 BPF_LD_MAP_FD(BPF_REG_1, 0),
3676 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
3677 BPF_FUNC_map_lookup_elem),
3678 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
3679 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
3680 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
3681 BPF_MOV64_REG(BPF_REG_5, BPF_REG_0),
3682 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
3683 BPF_MOV64_IMM(BPF_REG_1, 1),
3684 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
3685 BPF_MOV64_IMM(BPF_REG_1, 2),
3686 BPF_JMP_IMM(BPF_JEQ, BPF_REG_3, 0, 1),
3687 BPF_ST_MEM(BPF_DW, BPF_REG_3, 0, 0),
3688 BPF_MOV64_IMM(BPF_REG_1, 3),
3689 BPF_EXIT_INSN(),
3690 },
3691 .fixup_map1 = { 4 },
3692 .result = REJECT,
3693 .errstr = "R3 invalid mem access 'inv'",
3694 .prog_type = BPF_PROG_TYPE_SCHED_CLS
3695 },
3696 {
3697 "invalid map access from else condition", 4031 "invalid map access from else condition",
3698 .insns = { 4032 .insns = {
3699 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 4033 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
@@ -3711,9 +4045,9 @@ static struct bpf_test tests[] = {
3711 BPF_EXIT_INSN(), 4045 BPF_EXIT_INSN(),
3712 }, 4046 },
3713 .fixup_map2 = { 3 }, 4047 .fixup_map2 = { 3 },
3714 .errstr = "R0 unbounded memory access, make sure to bounds check any array access into a map", 4048 .errstr = "R0 unbounded memory access",
3715 .result = REJECT, 4049 .result = REJECT,
3716 .errstr_unpriv = "R0 pointer arithmetic prohibited", 4050 .errstr_unpriv = "R0 leaks addr",
3717 .result_unpriv = REJECT, 4051 .result_unpriv = REJECT,
3718 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 4052 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3719 }, 4053 },
@@ -4043,11 +4377,10 @@ static struct bpf_test tests[] = {
4043 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), 4377 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4044 BPF_LD_MAP_FD(BPF_REG_1, 0), 4378 BPF_LD_MAP_FD(BPF_REG_1, 0),
4045 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 4379 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4046 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4), 4380 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
4047 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 4381 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4048 BPF_MOV64_IMM(BPF_REG_2, 0), 4382 BPF_MOV64_IMM(BPF_REG_2, 0),
4049 BPF_MOV64_IMM(BPF_REG_3, 0), 4383 BPF_EMIT_CALL(BPF_FUNC_trace_printk),
4050 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4051 BPF_EXIT_INSN(), 4384 BPF_EXIT_INSN(),
4052 }, 4385 },
4053 .fixup_map2 = { 3 }, 4386 .fixup_map2 = { 3 },
@@ -4091,7 +4424,7 @@ static struct bpf_test tests[] = {
4091 BPF_EXIT_INSN(), 4424 BPF_EXIT_INSN(),
4092 }, 4425 },
4093 .fixup_map2 = { 3 }, 4426 .fixup_map2 = { 3 },
4094 .errstr = "invalid access to map value, value_size=48 off=0 size=-8", 4427 .errstr = "R2 min value is negative",
4095 .result = REJECT, 4428 .result = REJECT,
4096 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4429 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4097 }, 4430 },
@@ -4147,17 +4480,16 @@ static struct bpf_test tests[] = {
4147 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), 4480 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4148 BPF_LD_MAP_FD(BPF_REG_1, 0), 4481 BPF_LD_MAP_FD(BPF_REG_1, 0),
4149 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 4482 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4150 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5), 4483 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4151 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 4484 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4152 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 4485 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1,
4153 offsetof(struct test_val, foo)), 4486 offsetof(struct test_val, foo)),
4154 BPF_MOV64_IMM(BPF_REG_2, 0), 4487 BPF_MOV64_IMM(BPF_REG_2, 0),
4155 BPF_MOV64_IMM(BPF_REG_3, 0), 4488 BPF_EMIT_CALL(BPF_FUNC_trace_printk),
4156 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4157 BPF_EXIT_INSN(), 4489 BPF_EXIT_INSN(),
4158 }, 4490 },
4159 .fixup_map2 = { 3 }, 4491 .fixup_map2 = { 3 },
4160 .errstr = "R1 min value is outside of the array range", 4492 .errstr = "invalid access to map value, value_size=48 off=4 size=0",
4161 .result = REJECT, 4493 .result = REJECT,
4162 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4494 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4163 }, 4495 },
@@ -4203,7 +4535,7 @@ static struct bpf_test tests[] = {
4203 BPF_EXIT_INSN(), 4535 BPF_EXIT_INSN(),
4204 }, 4536 },
4205 .fixup_map2 = { 3 }, 4537 .fixup_map2 = { 3 },
4206 .errstr = "invalid access to map value, value_size=48 off=4 size=-8", 4538 .errstr = "R2 min value is negative",
4207 .result = REJECT, 4539 .result = REJECT,
4208 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4540 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4209 }, 4541 },
@@ -4225,7 +4557,7 @@ static struct bpf_test tests[] = {
4225 BPF_EXIT_INSN(), 4557 BPF_EXIT_INSN(),
4226 }, 4558 },
4227 .fixup_map2 = { 3 }, 4559 .fixup_map2 = { 3 },
4228 .errstr = "R1 min value is outside of the array range", 4560 .errstr = "R2 min value is negative",
4229 .result = REJECT, 4561 .result = REJECT,
4230 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4562 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4231 }, 4563 },
@@ -4283,13 +4615,12 @@ static struct bpf_test tests[] = {
4283 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), 4615 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4284 BPF_LD_MAP_FD(BPF_REG_1, 0), 4616 BPF_LD_MAP_FD(BPF_REG_1, 0),
4285 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 4617 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4286 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6), 4618 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
4287 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 4619 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4288 BPF_MOV64_IMM(BPF_REG_3, 0), 4620 BPF_MOV64_IMM(BPF_REG_3, 0),
4289 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3), 4621 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4290 BPF_MOV64_IMM(BPF_REG_2, 0), 4622 BPF_MOV64_IMM(BPF_REG_2, 0),
4291 BPF_MOV64_IMM(BPF_REG_3, 0), 4623 BPF_EMIT_CALL(BPF_FUNC_trace_printk),
4292 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4293 BPF_EXIT_INSN(), 4624 BPF_EXIT_INSN(),
4294 }, 4625 },
4295 .fixup_map2 = { 3 }, 4626 .fixup_map2 = { 3 },
@@ -4341,7 +4672,7 @@ static struct bpf_test tests[] = {
4341 BPF_EXIT_INSN(), 4672 BPF_EXIT_INSN(),
4342 }, 4673 },
4343 .fixup_map2 = { 3 }, 4674 .fixup_map2 = { 3 },
4344 .errstr = "invalid access to map value, value_size=48 off=4 size=-8", 4675 .errstr = "R2 min value is negative",
4345 .result = REJECT, 4676 .result = REJECT,
4346 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4677 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4347 }, 4678 },
@@ -4364,7 +4695,7 @@ static struct bpf_test tests[] = {
4364 BPF_EXIT_INSN(), 4695 BPF_EXIT_INSN(),
4365 }, 4696 },
4366 .fixup_map2 = { 3 }, 4697 .fixup_map2 = { 3 },
4367 .errstr = "R1 min value is outside of the array range", 4698 .errstr = "R2 min value is negative",
4368 .result = REJECT, 4699 .result = REJECT,
4369 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4700 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4370 }, 4701 },
@@ -4424,15 +4755,14 @@ static struct bpf_test tests[] = {
4424 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), 4755 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4425 BPF_LD_MAP_FD(BPF_REG_1, 0), 4756 BPF_LD_MAP_FD(BPF_REG_1, 0),
4426 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 4757 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4427 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7), 4758 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
4428 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 4759 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4429 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0), 4760 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4430 BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 4761 BPF_JMP_IMM(BPF_JGT, BPF_REG_3,
4431 offsetof(struct test_val, foo), 4), 4762 offsetof(struct test_val, foo), 3),
4432 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3), 4763 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4433 BPF_MOV64_IMM(BPF_REG_2, 0), 4764 BPF_MOV64_IMM(BPF_REG_2, 0),
4434 BPF_MOV64_IMM(BPF_REG_3, 0), 4765 BPF_EMIT_CALL(BPF_FUNC_trace_printk),
4435 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4436 BPF_EXIT_INSN(), 4766 BPF_EXIT_INSN(),
4437 }, 4767 },
4438 .fixup_map2 = { 3 }, 4768 .fixup_map2 = { 3 },
@@ -4452,13 +4782,13 @@ static struct bpf_test tests[] = {
4452 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 4782 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4453 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0), 4783 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4454 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3), 4784 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4455 BPF_MOV64_IMM(BPF_REG_2, 0), 4785 BPF_MOV64_IMM(BPF_REG_2, 1),
4456 BPF_MOV64_IMM(BPF_REG_3, 0), 4786 BPF_MOV64_IMM(BPF_REG_3, 0),
4457 BPF_EMIT_CALL(BPF_FUNC_probe_read), 4787 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4458 BPF_EXIT_INSN(), 4788 BPF_EXIT_INSN(),
4459 }, 4789 },
4460 .fixup_map2 = { 3 }, 4790 .fixup_map2 = { 3 },
4461 .errstr = "R1 min value is negative, either use unsigned index or do a if (index >=0) check", 4791 .errstr = "R1 unbounded memory access",
4462 .result = REJECT, 4792 .result = REJECT,
4463 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4793 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4464 }, 4794 },
@@ -4489,6 +4819,246 @@ static struct bpf_test tests[] = {
4489 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4819 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4490 }, 4820 },
4491 { 4821 {
4822 "helper access to map: bounds check using <, good access",
4823 .insns = {
4824 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4825 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4826 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4827 BPF_LD_MAP_FD(BPF_REG_1, 0),
4828 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4829 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4830 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4831 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4832 BPF_JMP_IMM(BPF_JLT, BPF_REG_3, 32, 2),
4833 BPF_MOV64_IMM(BPF_REG_0, 0),
4834 BPF_EXIT_INSN(),
4835 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4836 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4837 BPF_MOV64_IMM(BPF_REG_0, 0),
4838 BPF_EXIT_INSN(),
4839 },
4840 .fixup_map2 = { 3 },
4841 .result = ACCEPT,
4842 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4843 },
4844 {
4845 "helper access to map: bounds check using <, bad access",
4846 .insns = {
4847 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4848 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4849 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4850 BPF_LD_MAP_FD(BPF_REG_1, 0),
4851 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4852 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4853 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4854 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4855 BPF_JMP_IMM(BPF_JLT, BPF_REG_3, 32, 4),
4856 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4857 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4858 BPF_MOV64_IMM(BPF_REG_0, 0),
4859 BPF_EXIT_INSN(),
4860 BPF_MOV64_IMM(BPF_REG_0, 0),
4861 BPF_EXIT_INSN(),
4862 },
4863 .fixup_map2 = { 3 },
4864 .result = REJECT,
4865 .errstr = "R1 unbounded memory access",
4866 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4867 },
4868 {
4869 "helper access to map: bounds check using <=, good access",
4870 .insns = {
4871 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4872 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4873 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4874 BPF_LD_MAP_FD(BPF_REG_1, 0),
4875 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4876 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4877 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4878 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4879 BPF_JMP_IMM(BPF_JLE, BPF_REG_3, 32, 2),
4880 BPF_MOV64_IMM(BPF_REG_0, 0),
4881 BPF_EXIT_INSN(),
4882 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4883 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4884 BPF_MOV64_IMM(BPF_REG_0, 0),
4885 BPF_EXIT_INSN(),
4886 },
4887 .fixup_map2 = { 3 },
4888 .result = ACCEPT,
4889 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4890 },
4891 {
4892 "helper access to map: bounds check using <=, bad access",
4893 .insns = {
4894 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4895 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4896 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4897 BPF_LD_MAP_FD(BPF_REG_1, 0),
4898 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4899 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4900 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4901 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4902 BPF_JMP_IMM(BPF_JLE, BPF_REG_3, 32, 4),
4903 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4904 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4905 BPF_MOV64_IMM(BPF_REG_0, 0),
4906 BPF_EXIT_INSN(),
4907 BPF_MOV64_IMM(BPF_REG_0, 0),
4908 BPF_EXIT_INSN(),
4909 },
4910 .fixup_map2 = { 3 },
4911 .result = REJECT,
4912 .errstr = "R1 unbounded memory access",
4913 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4914 },
4915 {
4916 "helper access to map: bounds check using s<, good access",
4917 .insns = {
4918 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4919 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4920 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4921 BPF_LD_MAP_FD(BPF_REG_1, 0),
4922 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4923 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4924 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4925 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4926 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, 32, 2),
4927 BPF_MOV64_IMM(BPF_REG_0, 0),
4928 BPF_EXIT_INSN(),
4929 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, 0, -3),
4930 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4931 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4932 BPF_MOV64_IMM(BPF_REG_0, 0),
4933 BPF_EXIT_INSN(),
4934 },
4935 .fixup_map2 = { 3 },
4936 .result = ACCEPT,
4937 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4938 },
4939 {
4940 "helper access to map: bounds check using s<, good access 2",
4941 .insns = {
4942 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4943 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4944 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4945 BPF_LD_MAP_FD(BPF_REG_1, 0),
4946 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4947 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4948 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4949 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4950 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, 32, 2),
4951 BPF_MOV64_IMM(BPF_REG_0, 0),
4952 BPF_EXIT_INSN(),
4953 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, -3, -3),
4954 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4955 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4956 BPF_MOV64_IMM(BPF_REG_0, 0),
4957 BPF_EXIT_INSN(),
4958 },
4959 .fixup_map2 = { 3 },
4960 .result = ACCEPT,
4961 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4962 },
4963 {
4964 "helper access to map: bounds check using s<, bad access",
4965 .insns = {
4966 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4967 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4968 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4969 BPF_LD_MAP_FD(BPF_REG_1, 0),
4970 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4971 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4972 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4973 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, 0),
4974 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, 32, 2),
4975 BPF_MOV64_IMM(BPF_REG_0, 0),
4976 BPF_EXIT_INSN(),
4977 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, -3, -3),
4978 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4979 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4980 BPF_MOV64_IMM(BPF_REG_0, 0),
4981 BPF_EXIT_INSN(),
4982 },
4983 .fixup_map2 = { 3 },
4984 .result = REJECT,
4985 .errstr = "R1 min value is negative",
4986 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4987 },
4988 {
4989 "helper access to map: bounds check using s<=, good access",
4990 .insns = {
4991 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4992 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4993 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4994 BPF_LD_MAP_FD(BPF_REG_1, 0),
4995 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4996 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4997 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4998 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4999 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, 32, 2),
5000 BPF_MOV64_IMM(BPF_REG_0, 0),
5001 BPF_EXIT_INSN(),
5002 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, 0, -3),
5003 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
5004 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
5005 BPF_MOV64_IMM(BPF_REG_0, 0),
5006 BPF_EXIT_INSN(),
5007 },
5008 .fixup_map2 = { 3 },
5009 .result = ACCEPT,
5010 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5011 },
5012 {
5013 "helper access to map: bounds check using s<=, good access 2",
5014 .insns = {
5015 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5016 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5017 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
5018 BPF_LD_MAP_FD(BPF_REG_1, 0),
5019 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
5020 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
5021 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
5022 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
5023 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, 32, 2),
5024 BPF_MOV64_IMM(BPF_REG_0, 0),
5025 BPF_EXIT_INSN(),
5026 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, -3, -3),
5027 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
5028 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
5029 BPF_MOV64_IMM(BPF_REG_0, 0),
5030 BPF_EXIT_INSN(),
5031 },
5032 .fixup_map2 = { 3 },
5033 .result = ACCEPT,
5034 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5035 },
5036 {
5037 "helper access to map: bounds check using s<=, bad access",
5038 .insns = {
5039 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5040 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5041 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
5042 BPF_LD_MAP_FD(BPF_REG_1, 0),
5043 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
5044 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
5045 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
5046 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, 0),
5047 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, 32, 2),
5048 BPF_MOV64_IMM(BPF_REG_0, 0),
5049 BPF_EXIT_INSN(),
5050 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, -3, -3),
5051 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
5052 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
5053 BPF_MOV64_IMM(BPF_REG_0, 0),
5054 BPF_EXIT_INSN(),
5055 },
5056 .fixup_map2 = { 3 },
5057 .result = REJECT,
5058 .errstr = "R1 min value is negative",
5059 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5060 },
5061 {
4492 "map element value is preserved across register spilling", 5062 "map element value is preserved across register spilling",
4493 .insns = { 5063 .insns = {
4494 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 5064 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -4578,7 +5148,7 @@ static struct bpf_test tests[] = {
4578 BPF_EXIT_INSN(), 5148 BPF_EXIT_INSN(),
4579 }, 5149 },
4580 .fixup_map2 = { 3 }, 5150 .fixup_map2 = { 3 },
4581 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5151 .errstr_unpriv = "R0 leaks addr",
4582 .result = ACCEPT, 5152 .result = ACCEPT,
4583 .result_unpriv = REJECT, 5153 .result_unpriv = REJECT,
4584 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5154 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -4606,7 +5176,7 @@ static struct bpf_test tests[] = {
4606 BPF_EXIT_INSN(), 5176 BPF_EXIT_INSN(),
4607 }, 5177 },
4608 .fixup_map2 = { 3 }, 5178 .fixup_map2 = { 3 },
4609 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5179 .errstr_unpriv = "R0 leaks addr",
4610 .result = ACCEPT, 5180 .result = ACCEPT,
4611 .result_unpriv = REJECT, 5181 .result_unpriv = REJECT,
4612 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5182 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -4625,7 +5195,7 @@ static struct bpf_test tests[] = {
4625 BPF_EXIT_INSN(), 5195 BPF_EXIT_INSN(),
4626 }, 5196 },
4627 .fixup_map2 = { 3 }, 5197 .fixup_map2 = { 3 },
4628 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5198 .errstr_unpriv = "R0 bitwise operator &= on pointer",
4629 .errstr = "invalid mem access 'inv'", 5199 .errstr = "invalid mem access 'inv'",
4630 .result = REJECT, 5200 .result = REJECT,
4631 .result_unpriv = REJECT, 5201 .result_unpriv = REJECT,
@@ -4644,7 +5214,7 @@ static struct bpf_test tests[] = {
4644 BPF_EXIT_INSN(), 5214 BPF_EXIT_INSN(),
4645 }, 5215 },
4646 .fixup_map2 = { 3 }, 5216 .fixup_map2 = { 3 },
4647 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5217 .errstr_unpriv = "R0 32-bit pointer arithmetic prohibited",
4648 .errstr = "invalid mem access 'inv'", 5218 .errstr = "invalid mem access 'inv'",
4649 .result = REJECT, 5219 .result = REJECT,
4650 .result_unpriv = REJECT, 5220 .result_unpriv = REJECT,
@@ -4663,7 +5233,7 @@ static struct bpf_test tests[] = {
4663 BPF_EXIT_INSN(), 5233 BPF_EXIT_INSN(),
4664 }, 5234 },
4665 .fixup_map2 = { 3 }, 5235 .fixup_map2 = { 3 },
4666 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5236 .errstr_unpriv = "R0 pointer arithmetic with /= operator",
4667 .errstr = "invalid mem access 'inv'", 5237 .errstr = "invalid mem access 'inv'",
4668 .result = REJECT, 5238 .result = REJECT,
4669 .result_unpriv = REJECT, 5239 .result_unpriv = REJECT,
@@ -4706,10 +5276,8 @@ static struct bpf_test tests[] = {
4706 BPF_EXIT_INSN(), 5276 BPF_EXIT_INSN(),
4707 }, 5277 },
4708 .fixup_map2 = { 3 }, 5278 .fixup_map2 = { 3 },
4709 .errstr_unpriv = "R0 invalid mem access 'inv'",
4710 .errstr = "R0 invalid mem access 'inv'", 5279 .errstr = "R0 invalid mem access 'inv'",
4711 .result = REJECT, 5280 .result = REJECT,
4712 .result_unpriv = REJECT,
4713 }, 5281 },
4714 { 5282 {
4715 "map element value is preserved across register spilling", 5283 "map element value is preserved across register spilling",
@@ -4731,7 +5299,7 @@ static struct bpf_test tests[] = {
4731 BPF_EXIT_INSN(), 5299 BPF_EXIT_INSN(),
4732 }, 5300 },
4733 .fixup_map2 = { 3 }, 5301 .fixup_map2 = { 3 },
4734 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5302 .errstr_unpriv = "R0 leaks addr",
4735 .result = ACCEPT, 5303 .result = ACCEPT,
4736 .result_unpriv = REJECT, 5304 .result_unpriv = REJECT,
4737 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5305 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -4777,7 +5345,7 @@ static struct bpf_test tests[] = {
4777 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5345 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4778 BPF_EXIT_INSN(), 5346 BPF_EXIT_INSN(),
4779 }, 5347 },
4780 .errstr = "invalid stack type R1 off=-64 access_size=0", 5348 .errstr = "invalid indirect read from stack off -64+0 size 64",
4781 .result = REJECT, 5349 .result = REJECT,
4782 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5350 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4783 }, 5351 },
@@ -4913,7 +5481,8 @@ static struct bpf_test tests[] = {
4913 BPF_MOV64_IMM(BPF_REG_0, 0), 5481 BPF_MOV64_IMM(BPF_REG_0, 0),
4914 BPF_EXIT_INSN(), 5482 BPF_EXIT_INSN(),
4915 }, 5483 },
4916 .errstr = "R2 unbounded memory access", 5484 /* because max wasn't checked, signed min is negative */
5485 .errstr = "R2 min value is negative, either use unsigned or 'var &= const'",
4917 .result = REJECT, 5486 .result = REJECT,
4918 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5487 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4919 }, 5488 },
@@ -4931,7 +5500,7 @@ static struct bpf_test tests[] = {
4931 BPF_MOV64_IMM(BPF_REG_0, 0), 5500 BPF_MOV64_IMM(BPF_REG_0, 0),
4932 BPF_EXIT_INSN(), 5501 BPF_EXIT_INSN(),
4933 }, 5502 },
4934 .errstr = "invalid stack type R1 off=-64 access_size=0", 5503 .errstr = "invalid indirect read from stack off -64+0 size 64",
4935 .result = REJECT, 5504 .result = REJECT,
4936 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5505 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4937 }, 5506 },
@@ -5062,7 +5631,21 @@ static struct bpf_test tests[] = {
5062 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5631 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5063 }, 5632 },
5064 { 5633 {
5065 "helper access to variable memory: size > 0 not allowed on NULL", 5634 "helper access to variable memory: size = 0 allowed on NULL (ARG_PTR_TO_MEM_OR_NULL)",
5635 .insns = {
5636 BPF_MOV64_IMM(BPF_REG_1, 0),
5637 BPF_MOV64_IMM(BPF_REG_2, 0),
5638 BPF_MOV64_IMM(BPF_REG_3, 0),
5639 BPF_MOV64_IMM(BPF_REG_4, 0),
5640 BPF_MOV64_IMM(BPF_REG_5, 0),
5641 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
5642 BPF_EXIT_INSN(),
5643 },
5644 .result = ACCEPT,
5645 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
5646 },
5647 {
5648 "helper access to variable memory: size > 0 not allowed on NULL (ARG_PTR_TO_MEM_OR_NULL)",
5066 .insns = { 5649 .insns = {
5067 BPF_MOV64_IMM(BPF_REG_1, 0), 5650 BPF_MOV64_IMM(BPF_REG_1, 0),
5068 BPF_MOV64_IMM(BPF_REG_2, 0), 5651 BPF_MOV64_IMM(BPF_REG_2, 0),
@@ -5075,12 +5658,12 @@ static struct bpf_test tests[] = {
5075 BPF_EMIT_CALL(BPF_FUNC_csum_diff), 5658 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
5076 BPF_EXIT_INSN(), 5659 BPF_EXIT_INSN(),
5077 }, 5660 },
5078 .errstr = "R1 type=imm expected=fp", 5661 .errstr = "R1 type=inv expected=fp",
5079 .result = REJECT, 5662 .result = REJECT,
5080 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 5663 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
5081 }, 5664 },
5082 { 5665 {
5083 "helper access to variable memory: size = 0 not allowed on != NULL", 5666 "helper access to variable memory: size = 0 allowed on != NULL stack pointer (ARG_PTR_TO_MEM_OR_NULL)",
5084 .insns = { 5667 .insns = {
5085 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 5668 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
5086 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 5669 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
@@ -5093,11 +5676,201 @@ static struct bpf_test tests[] = {
5093 BPF_EMIT_CALL(BPF_FUNC_csum_diff), 5676 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
5094 BPF_EXIT_INSN(), 5677 BPF_EXIT_INSN(),
5095 }, 5678 },
5096 .errstr = "invalid stack type R1 off=-8 access_size=0", 5679 .result = ACCEPT,
5097 .result = REJECT,
5098 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 5680 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
5099 }, 5681 },
5100 { 5682 {
5683 "helper access to variable memory: size = 0 allowed on != NULL map pointer (ARG_PTR_TO_MEM_OR_NULL)",
5684 .insns = {
5685 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5686 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5687 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5688 BPF_LD_MAP_FD(BPF_REG_1, 0),
5689 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5690 BPF_FUNC_map_lookup_elem),
5691 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
5692 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
5693 BPF_MOV64_IMM(BPF_REG_2, 0),
5694 BPF_MOV64_IMM(BPF_REG_3, 0),
5695 BPF_MOV64_IMM(BPF_REG_4, 0),
5696 BPF_MOV64_IMM(BPF_REG_5, 0),
5697 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
5698 BPF_EXIT_INSN(),
5699 },
5700 .fixup_map1 = { 3 },
5701 .result = ACCEPT,
5702 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
5703 },
5704 {
5705 "helper access to variable memory: size possible = 0 allowed on != NULL stack pointer (ARG_PTR_TO_MEM_OR_NULL)",
5706 .insns = {
5707 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5708 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5709 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5710 BPF_LD_MAP_FD(BPF_REG_1, 0),
5711 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5712 BPF_FUNC_map_lookup_elem),
5713 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
5714 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
5715 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 8, 7),
5716 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
5717 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
5718 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, 0),
5719 BPF_MOV64_IMM(BPF_REG_3, 0),
5720 BPF_MOV64_IMM(BPF_REG_4, 0),
5721 BPF_MOV64_IMM(BPF_REG_5, 0),
5722 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
5723 BPF_EXIT_INSN(),
5724 },
5725 .fixup_map1 = { 3 },
5726 .result = ACCEPT,
5727 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
5728 },
5729 {
5730 "helper access to variable memory: size possible = 0 allowed on != NULL map pointer (ARG_PTR_TO_MEM_OR_NULL)",
5731 .insns = {
5732 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5733 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5734 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5735 BPF_LD_MAP_FD(BPF_REG_1, 0),
5736 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5737 BPF_FUNC_map_lookup_elem),
5738 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
5739 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
5740 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
5741 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 8, 4),
5742 BPF_MOV64_IMM(BPF_REG_3, 0),
5743 BPF_MOV64_IMM(BPF_REG_4, 0),
5744 BPF_MOV64_IMM(BPF_REG_5, 0),
5745 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
5746 BPF_EXIT_INSN(),
5747 },
5748 .fixup_map1 = { 3 },
5749 .result = ACCEPT,
5750 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
5751 },
5752 {
5753 "helper access to variable memory: size possible = 0 allowed on != NULL packet pointer (ARG_PTR_TO_MEM_OR_NULL)",
5754 .insns = {
5755 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
5756 offsetof(struct __sk_buff, data)),
5757 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
5758 offsetof(struct __sk_buff, data_end)),
5759 BPF_MOV64_REG(BPF_REG_0, BPF_REG_6),
5760 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
5761 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 7),
5762 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
5763 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 0),
5764 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 8, 4),
5765 BPF_MOV64_IMM(BPF_REG_3, 0),
5766 BPF_MOV64_IMM(BPF_REG_4, 0),
5767 BPF_MOV64_IMM(BPF_REG_5, 0),
5768 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
5769 BPF_EXIT_INSN(),
5770 },
5771 .result = ACCEPT,
5772 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
5773 },
5774 {
5775 "helper access to variable memory: size = 0 not allowed on NULL (!ARG_PTR_TO_MEM_OR_NULL)",
5776 .insns = {
5777 BPF_MOV64_IMM(BPF_REG_1, 0),
5778 BPF_MOV64_IMM(BPF_REG_2, 0),
5779 BPF_MOV64_IMM(BPF_REG_3, 0),
5780 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5781 BPF_EXIT_INSN(),
5782 },
5783 .errstr = "R1 type=inv expected=fp",
5784 .result = REJECT,
5785 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5786 },
5787 {
5788 "helper access to variable memory: size > 0 not allowed on NULL (!ARG_PTR_TO_MEM_OR_NULL)",
5789 .insns = {
5790 BPF_MOV64_IMM(BPF_REG_1, 0),
5791 BPF_MOV64_IMM(BPF_REG_2, 1),
5792 BPF_MOV64_IMM(BPF_REG_3, 0),
5793 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5794 BPF_EXIT_INSN(),
5795 },
5796 .errstr = "R1 type=inv expected=fp",
5797 .result = REJECT,
5798 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5799 },
5800 {
5801 "helper access to variable memory: size = 0 allowed on != NULL stack pointer (!ARG_PTR_TO_MEM_OR_NULL)",
5802 .insns = {
5803 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
5804 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
5805 BPF_MOV64_IMM(BPF_REG_2, 0),
5806 BPF_MOV64_IMM(BPF_REG_3, 0),
5807 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5808 BPF_EXIT_INSN(),
5809 },
5810 .result = ACCEPT,
5811 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5812 },
5813 {
5814 "helper access to variable memory: size = 0 allowed on != NULL map pointer (!ARG_PTR_TO_MEM_OR_NULL)",
5815 .insns = {
5816 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5817 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5818 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5819 BPF_LD_MAP_FD(BPF_REG_1, 0),
5820 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
5821 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
5822 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
5823 BPF_MOV64_IMM(BPF_REG_2, 0),
5824 BPF_MOV64_IMM(BPF_REG_3, 0),
5825 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5826 BPF_EXIT_INSN(),
5827 },
5828 .fixup_map1 = { 3 },
5829 .result = ACCEPT,
5830 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5831 },
5832 {
5833 "helper access to variable memory: size possible = 0 allowed on != NULL stack pointer (!ARG_PTR_TO_MEM_OR_NULL)",
5834 .insns = {
5835 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5836 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5837 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5838 BPF_LD_MAP_FD(BPF_REG_1, 0),
5839 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
5840 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
5841 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
5842 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 8, 4),
5843 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
5844 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
5845 BPF_MOV64_IMM(BPF_REG_3, 0),
5846 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5847 BPF_EXIT_INSN(),
5848 },
5849 .fixup_map1 = { 3 },
5850 .result = ACCEPT,
5851 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5852 },
5853 {
5854 "helper access to variable memory: size possible = 0 allowed on != NULL map pointer (!ARG_PTR_TO_MEM_OR_NULL)",
5855 .insns = {
5856 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5857 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5858 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5859 BPF_LD_MAP_FD(BPF_REG_1, 0),
5860 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
5861 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
5862 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
5863 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
5864 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 8, 2),
5865 BPF_MOV64_IMM(BPF_REG_3, 0),
5866 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5867 BPF_EXIT_INSN(),
5868 },
5869 .fixup_map1 = { 3 },
5870 .result = ACCEPT,
5871 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5872 },
5873 {
5101 "helper access to variable memory: 8 bytes leak", 5874 "helper access to variable memory: 8 bytes leak",
5102 .insns = { 5875 .insns = {
5103 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 5876 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
@@ -5160,7 +5933,7 @@ static struct bpf_test tests[] = {
5160 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 5933 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5161 BPF_FUNC_map_lookup_elem), 5934 BPF_FUNC_map_lookup_elem),
5162 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4), 5935 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
5163 BPF_MOV64_IMM(BPF_REG_1, 6), 5936 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
5164 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, -4), 5937 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, -4),
5165 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2), 5938 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
5166 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 5939 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
@@ -5169,10 +5942,8 @@ static struct bpf_test tests[] = {
5169 BPF_EXIT_INSN(), 5942 BPF_EXIT_INSN(),
5170 }, 5943 },
5171 .fixup_map2 = { 3 }, 5944 .fixup_map2 = { 3 },
5172 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5945 .errstr = "R0 max value is outside of the array range",
5173 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
5174 .result = REJECT, 5946 .result = REJECT,
5175 .result_unpriv = REJECT,
5176 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5947 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
5177 }, 5948 },
5178 { 5949 {
@@ -5201,10 +5972,8 @@ static struct bpf_test tests[] = {
5201 BPF_EXIT_INSN(), 5972 BPF_EXIT_INSN(),
5202 }, 5973 },
5203 .fixup_map2 = { 3 }, 5974 .fixup_map2 = { 3 },
5204 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5975 .errstr = "R0 max value is outside of the array range",
5205 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
5206 .result = REJECT, 5976 .result = REJECT,
5207 .result_unpriv = REJECT,
5208 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5977 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
5209 }, 5978 },
5210 { 5979 {
@@ -5251,7 +6020,7 @@ static struct bpf_test tests[] = {
5251 }, 6020 },
5252 .fixup_map_in_map = { 3 }, 6021 .fixup_map_in_map = { 3 },
5253 .errstr = "R1 type=inv expected=map_ptr", 6022 .errstr = "R1 type=inv expected=map_ptr",
5254 .errstr_unpriv = "R1 pointer arithmetic prohibited", 6023 .errstr_unpriv = "R1 pointer arithmetic on CONST_PTR_TO_MAP prohibited",
5255 .result = REJECT, 6024 .result = REJECT,
5256 }, 6025 },
5257 { 6026 {
@@ -5422,7 +6191,7 @@ static struct bpf_test tests[] = {
5422 "check bpf_perf_event_data->sample_period byte load permitted", 6191 "check bpf_perf_event_data->sample_period byte load permitted",
5423 .insns = { 6192 .insns = {
5424 BPF_MOV64_IMM(BPF_REG_0, 0), 6193 BPF_MOV64_IMM(BPF_REG_0, 0),
5425#ifdef __LITTLE_ENDIAN 6194#if __BYTE_ORDER == __LITTLE_ENDIAN
5426 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 6195 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
5427 offsetof(struct bpf_perf_event_data, sample_period)), 6196 offsetof(struct bpf_perf_event_data, sample_period)),
5428#else 6197#else
@@ -5438,7 +6207,7 @@ static struct bpf_test tests[] = {
5438 "check bpf_perf_event_data->sample_period half load permitted", 6207 "check bpf_perf_event_data->sample_period half load permitted",
5439 .insns = { 6208 .insns = {
5440 BPF_MOV64_IMM(BPF_REG_0, 0), 6209 BPF_MOV64_IMM(BPF_REG_0, 0),
5441#ifdef __LITTLE_ENDIAN 6210#if __BYTE_ORDER == __LITTLE_ENDIAN
5442 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 6211 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
5443 offsetof(struct bpf_perf_event_data, sample_period)), 6212 offsetof(struct bpf_perf_event_data, sample_period)),
5444#else 6213#else
@@ -5454,7 +6223,7 @@ static struct bpf_test tests[] = {
5454 "check bpf_perf_event_data->sample_period word load permitted", 6223 "check bpf_perf_event_data->sample_period word load permitted",
5455 .insns = { 6224 .insns = {
5456 BPF_MOV64_IMM(BPF_REG_0, 0), 6225 BPF_MOV64_IMM(BPF_REG_0, 0),
5457#ifdef __LITTLE_ENDIAN 6226#if __BYTE_ORDER == __LITTLE_ENDIAN
5458 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 6227 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
5459 offsetof(struct bpf_perf_event_data, sample_period)), 6228 offsetof(struct bpf_perf_event_data, sample_period)),
5460#else 6229#else
@@ -5481,7 +6250,7 @@ static struct bpf_test tests[] = {
5481 "check skb->data half load not permitted", 6250 "check skb->data half load not permitted",
5482 .insns = { 6251 .insns = {
5483 BPF_MOV64_IMM(BPF_REG_0, 0), 6252 BPF_MOV64_IMM(BPF_REG_0, 0),
5484#ifdef __LITTLE_ENDIAN 6253#if __BYTE_ORDER == __LITTLE_ENDIAN
5485 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 6254 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
5486 offsetof(struct __sk_buff, data)), 6255 offsetof(struct __sk_buff, data)),
5487#else 6256#else
@@ -5497,7 +6266,7 @@ static struct bpf_test tests[] = {
5497 "check skb->tc_classid half load not permitted for lwt prog", 6266 "check skb->tc_classid half load not permitted for lwt prog",
5498 .insns = { 6267 .insns = {
5499 BPF_MOV64_IMM(BPF_REG_0, 0), 6268 BPF_MOV64_IMM(BPF_REG_0, 0),
5500#ifdef __LITTLE_ENDIAN 6269#if __BYTE_ORDER == __LITTLE_ENDIAN
5501 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 6270 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
5502 offsetof(struct __sk_buff, tc_classid)), 6271 offsetof(struct __sk_buff, tc_classid)),
5503#else 6272#else
@@ -5531,10 +6300,8 @@ static struct bpf_test tests[] = {
5531 BPF_EXIT_INSN(), 6300 BPF_EXIT_INSN(),
5532 }, 6301 },
5533 .fixup_map1 = { 3 }, 6302 .fixup_map1 = { 3 },
5534 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5535 .errstr = "R0 min value is negative", 6303 .errstr = "R0 min value is negative",
5536 .result = REJECT, 6304 .result = REJECT,
5537 .result_unpriv = REJECT,
5538 }, 6305 },
5539 { 6306 {
5540 "bounds checks mixing signed and unsigned", 6307 "bounds checks mixing signed and unsigned",
@@ -5557,10 +6324,8 @@ static struct bpf_test tests[] = {
5557 BPF_EXIT_INSN(), 6324 BPF_EXIT_INSN(),
5558 }, 6325 },
5559 .fixup_map1 = { 3 }, 6326 .fixup_map1 = { 3 },
5560 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5561 .errstr = "R0 min value is negative", 6327 .errstr = "R0 min value is negative",
5562 .result = REJECT, 6328 .result = REJECT,
5563 .result_unpriv = REJECT,
5564 }, 6329 },
5565 { 6330 {
5566 "bounds checks mixing signed and unsigned, variant 2", 6331 "bounds checks mixing signed and unsigned, variant 2",
@@ -5585,10 +6350,8 @@ static struct bpf_test tests[] = {
5585 BPF_EXIT_INSN(), 6350 BPF_EXIT_INSN(),
5586 }, 6351 },
5587 .fixup_map1 = { 3 }, 6352 .fixup_map1 = { 3 },
5588 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5589 .errstr = "R8 invalid mem access 'inv'", 6353 .errstr = "R8 invalid mem access 'inv'",
5590 .result = REJECT, 6354 .result = REJECT,
5591 .result_unpriv = REJECT,
5592 }, 6355 },
5593 { 6356 {
5594 "bounds checks mixing signed and unsigned, variant 3", 6357 "bounds checks mixing signed and unsigned, variant 3",
@@ -5612,10 +6375,8 @@ static struct bpf_test tests[] = {
5612 BPF_EXIT_INSN(), 6375 BPF_EXIT_INSN(),
5613 }, 6376 },
5614 .fixup_map1 = { 3 }, 6377 .fixup_map1 = { 3 },
5615 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5616 .errstr = "R8 invalid mem access 'inv'", 6378 .errstr = "R8 invalid mem access 'inv'",
5617 .result = REJECT, 6379 .result = REJECT,
5618 .result_unpriv = REJECT,
5619 }, 6380 },
5620 { 6381 {
5621 "bounds checks mixing signed and unsigned, variant 4", 6382 "bounds checks mixing signed and unsigned, variant 4",
@@ -5638,10 +6399,7 @@ static struct bpf_test tests[] = {
5638 BPF_EXIT_INSN(), 6399 BPF_EXIT_INSN(),
5639 }, 6400 },
5640 .fixup_map1 = { 3 }, 6401 .fixup_map1 = { 3 },
5641 .errstr_unpriv = "R0 pointer arithmetic prohibited", 6402 .result = ACCEPT,
5642 .errstr = "R0 min value is negative",
5643 .result = REJECT,
5644 .result_unpriv = REJECT,
5645 }, 6403 },
5646 { 6404 {
5647 "bounds checks mixing signed and unsigned, variant 5", 6405 "bounds checks mixing signed and unsigned, variant 5",
@@ -5665,10 +6423,8 @@ static struct bpf_test tests[] = {
5665 BPF_EXIT_INSN(), 6423 BPF_EXIT_INSN(),
5666 }, 6424 },
5667 .fixup_map1 = { 3 }, 6425 .fixup_map1 = { 3 },
5668 .errstr_unpriv = "R0 pointer arithmetic prohibited", 6426 .errstr = "R0 min value is negative",
5669 .errstr = "R0 invalid mem access",
5670 .result = REJECT, 6427 .result = REJECT,
5671 .result_unpriv = REJECT,
5672 }, 6428 },
5673 { 6429 {
5674 "bounds checks mixing signed and unsigned, variant 6", 6430 "bounds checks mixing signed and unsigned, variant 6",
@@ -5689,10 +6445,8 @@ static struct bpf_test tests[] = {
5689 BPF_MOV64_IMM(BPF_REG_0, 0), 6445 BPF_MOV64_IMM(BPF_REG_0, 0),
5690 BPF_EXIT_INSN(), 6446 BPF_EXIT_INSN(),
5691 }, 6447 },
5692 .errstr_unpriv = "R4 min value is negative, either use unsigned",
5693 .errstr = "R4 min value is negative, either use unsigned", 6448 .errstr = "R4 min value is negative, either use unsigned",
5694 .result = REJECT, 6449 .result = REJECT,
5695 .result_unpriv = REJECT,
5696 }, 6450 },
5697 { 6451 {
5698 "bounds checks mixing signed and unsigned, variant 7", 6452 "bounds checks mixing signed and unsigned, variant 7",
@@ -5715,10 +6469,7 @@ static struct bpf_test tests[] = {
5715 BPF_EXIT_INSN(), 6469 BPF_EXIT_INSN(),
5716 }, 6470 },
5717 .fixup_map1 = { 3 }, 6471 .fixup_map1 = { 3 },
5718 .errstr_unpriv = "R0 pointer arithmetic prohibited", 6472 .result = ACCEPT,
5719 .errstr = "R0 min value is negative",
5720 .result = REJECT,
5721 .result_unpriv = REJECT,
5722 }, 6473 },
5723 { 6474 {
5724 "bounds checks mixing signed and unsigned, variant 8", 6475 "bounds checks mixing signed and unsigned, variant 8",
@@ -5729,32 +6480,6 @@ static struct bpf_test tests[] = {
5729 BPF_LD_MAP_FD(BPF_REG_1, 0), 6480 BPF_LD_MAP_FD(BPF_REG_1, 0),
5730 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 6481 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5731 BPF_FUNC_map_lookup_elem), 6482 BPF_FUNC_map_lookup_elem),
5732 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
5733 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
5734 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
5735 BPF_MOV64_IMM(BPF_REG_2, 1024 * 1024 * 1024 + 1),
5736 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 3),
5737 BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 1, 2),
5738 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
5739 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
5740 BPF_MOV64_IMM(BPF_REG_0, 0),
5741 BPF_EXIT_INSN(),
5742 },
5743 .fixup_map1 = { 3 },
5744 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5745 .errstr = "R0 min value is negative",
5746 .result = REJECT,
5747 .result_unpriv = REJECT,
5748 },
5749 {
5750 "bounds checks mixing signed and unsigned, variant 9",
5751 .insns = {
5752 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5753 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5754 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5755 BPF_LD_MAP_FD(BPF_REG_1, 0),
5756 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5757 BPF_FUNC_map_lookup_elem),
5758 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9), 6483 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
5759 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8), 6484 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
5760 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16), 6485 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
@@ -5769,13 +6494,11 @@ static struct bpf_test tests[] = {
5769 BPF_EXIT_INSN(), 6494 BPF_EXIT_INSN(),
5770 }, 6495 },
5771 .fixup_map1 = { 3 }, 6496 .fixup_map1 = { 3 },
5772 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5773 .errstr = "R0 min value is negative", 6497 .errstr = "R0 min value is negative",
5774 .result = REJECT, 6498 .result = REJECT,
5775 .result_unpriv = REJECT,
5776 }, 6499 },
5777 { 6500 {
5778 "bounds checks mixing signed and unsigned, variant 10", 6501 "bounds checks mixing signed and unsigned, variant 9",
5779 .insns = { 6502 .insns = {
5780 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6503 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5781 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6504 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -5797,13 +6520,10 @@ static struct bpf_test tests[] = {
5797 BPF_EXIT_INSN(), 6520 BPF_EXIT_INSN(),
5798 }, 6521 },
5799 .fixup_map1 = { 3 }, 6522 .fixup_map1 = { 3 },
5800 .errstr_unpriv = "R0 pointer arithmetic prohibited", 6523 .result = ACCEPT,
5801 .errstr = "R0 min value is negative",
5802 .result = REJECT,
5803 .result_unpriv = REJECT,
5804 }, 6524 },
5805 { 6525 {
5806 "bounds checks mixing signed and unsigned, variant 11", 6526 "bounds checks mixing signed and unsigned, variant 10",
5807 .insns = { 6527 .insns = {
5808 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6528 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5809 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6529 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -5825,13 +6545,11 @@ static struct bpf_test tests[] = {
5825 BPF_EXIT_INSN(), 6545 BPF_EXIT_INSN(),
5826 }, 6546 },
5827 .fixup_map1 = { 3 }, 6547 .fixup_map1 = { 3 },
5828 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5829 .errstr = "R0 min value is negative", 6548 .errstr = "R0 min value is negative",
5830 .result = REJECT, 6549 .result = REJECT,
5831 .result_unpriv = REJECT,
5832 }, 6550 },
5833 { 6551 {
5834 "bounds checks mixing signed and unsigned, variant 12", 6552 "bounds checks mixing signed and unsigned, variant 11",
5835 .insns = { 6553 .insns = {
5836 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6554 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5837 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6555 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -5854,13 +6572,11 @@ static struct bpf_test tests[] = {
5854 BPF_EXIT_INSN(), 6572 BPF_EXIT_INSN(),
5855 }, 6573 },
5856 .fixup_map1 = { 3 }, 6574 .fixup_map1 = { 3 },
5857 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5858 .errstr = "R0 min value is negative", 6575 .errstr = "R0 min value is negative",
5859 .result = REJECT, 6576 .result = REJECT,
5860 .result_unpriv = REJECT,
5861 }, 6577 },
5862 { 6578 {
5863 "bounds checks mixing signed and unsigned, variant 13", 6579 "bounds checks mixing signed and unsigned, variant 12",
5864 .insns = { 6580 .insns = {
5865 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6581 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5866 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6582 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -5882,13 +6598,11 @@ static struct bpf_test tests[] = {
5882 BPF_EXIT_INSN(), 6598 BPF_EXIT_INSN(),
5883 }, 6599 },
5884 .fixup_map1 = { 3 }, 6600 .fixup_map1 = { 3 },
5885 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5886 .errstr = "R0 min value is negative", 6601 .errstr = "R0 min value is negative",
5887 .result = REJECT, 6602 .result = REJECT,
5888 .result_unpriv = REJECT,
5889 }, 6603 },
5890 { 6604 {
5891 "bounds checks mixing signed and unsigned, variant 14", 6605 "bounds checks mixing signed and unsigned, variant 13",
5892 .insns = { 6606 .insns = {
5893 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6607 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5894 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6608 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -5913,13 +6627,11 @@ static struct bpf_test tests[] = {
5913 BPF_EXIT_INSN(), 6627 BPF_EXIT_INSN(),
5914 }, 6628 },
5915 .fixup_map1 = { 3 }, 6629 .fixup_map1 = { 3 },
5916 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5917 .errstr = "R0 min value is negative", 6630 .errstr = "R0 min value is negative",
5918 .result = REJECT, 6631 .result = REJECT,
5919 .result_unpriv = REJECT,
5920 }, 6632 },
5921 { 6633 {
5922 "bounds checks mixing signed and unsigned, variant 15", 6634 "bounds checks mixing signed and unsigned, variant 14",
5923 .insns = { 6635 .insns = {
5924 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1, 6636 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1,
5925 offsetof(struct __sk_buff, mark)), 6637 offsetof(struct __sk_buff, mark)),
@@ -5945,13 +6657,11 @@ static struct bpf_test tests[] = {
5945 BPF_JMP_IMM(BPF_JA, 0, 0, -7), 6657 BPF_JMP_IMM(BPF_JA, 0, 0, -7),
5946 }, 6658 },
5947 .fixup_map1 = { 4 }, 6659 .fixup_map1 = { 4 },
5948 .errstr_unpriv = "R0 pointer arithmetic prohibited",
5949 .errstr = "R0 min value is negative", 6660 .errstr = "R0 min value is negative",
5950 .result = REJECT, 6661 .result = REJECT,
5951 .result_unpriv = REJECT,
5952 }, 6662 },
5953 { 6663 {
5954 "bounds checks mixing signed and unsigned, variant 16", 6664 "bounds checks mixing signed and unsigned, variant 15",
5955 .insns = { 6665 .insns = {
5956 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6666 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5957 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6667 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -5975,11 +6685,1418 @@ static struct bpf_test tests[] = {
5975 BPF_EXIT_INSN(), 6685 BPF_EXIT_INSN(),
5976 }, 6686 },
5977 .fixup_map1 = { 3 }, 6687 .fixup_map1 = { 3 },
5978 .errstr_unpriv = "R0 pointer arithmetic prohibited", 6688 .errstr_unpriv = "R0 pointer comparison prohibited",
5979 .errstr = "R0 min value is negative", 6689 .errstr = "R0 min value is negative",
5980 .result = REJECT, 6690 .result = REJECT,
5981 .result_unpriv = REJECT, 6691 .result_unpriv = REJECT,
5982 }, 6692 },
6693 {
6694 "subtraction bounds (map value) variant 1",
6695 .insns = {
6696 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6697 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6698 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6699 BPF_LD_MAP_FD(BPF_REG_1, 0),
6700 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6701 BPF_FUNC_map_lookup_elem),
6702 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
6703 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6704 BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0xff, 7),
6705 BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_0, 1),
6706 BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 0xff, 5),
6707 BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_3),
6708 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 56),
6709 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6710 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
6711 BPF_EXIT_INSN(),
6712 BPF_MOV64_IMM(BPF_REG_0, 0),
6713 BPF_EXIT_INSN(),
6714 },
6715 .fixup_map1 = { 3 },
6716 .errstr = "R0 max value is outside of the array range",
6717 .result = REJECT,
6718 },
6719 {
6720 "subtraction bounds (map value) variant 2",
6721 .insns = {
6722 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6723 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6724 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6725 BPF_LD_MAP_FD(BPF_REG_1, 0),
6726 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6727 BPF_FUNC_map_lookup_elem),
6728 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
6729 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6730 BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0xff, 6),
6731 BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_0, 1),
6732 BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 0xff, 4),
6733 BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_3),
6734 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6735 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
6736 BPF_EXIT_INSN(),
6737 BPF_MOV64_IMM(BPF_REG_0, 0),
6738 BPF_EXIT_INSN(),
6739 },
6740 .fixup_map1 = { 3 },
6741 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
6742 .result = REJECT,
6743 },
6744 {
6745 "variable-offset ctx access",
6746 .insns = {
6747 /* Get an unknown value */
6748 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
6749 /* Make it small and 4-byte aligned */
6750 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
6751 /* add it to skb. We now have either &skb->len or
6752 * &skb->pkt_type, but we don't know which
6753 */
6754 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2),
6755 /* dereference it */
6756 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
6757 BPF_EXIT_INSN(),
6758 },
6759 .errstr = "variable ctx access var_off=(0x0; 0x4)",
6760 .result = REJECT,
6761 .prog_type = BPF_PROG_TYPE_LWT_IN,
6762 },
6763 {
6764 "variable-offset stack access",
6765 .insns = {
6766 /* Fill the top 8 bytes of the stack */
6767 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6768 /* Get an unknown value */
6769 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
6770 /* Make it small and 4-byte aligned */
6771 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
6772 BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 8),
6773 /* add it to fp. We now have either fp-4 or fp-8, but
6774 * we don't know which
6775 */
6776 BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
6777 /* dereference it */
6778 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_2, 0),
6779 BPF_EXIT_INSN(),
6780 },
6781 .errstr = "variable stack access var_off=(0xfffffffffffffff8; 0x4)",
6782 .result = REJECT,
6783 .prog_type = BPF_PROG_TYPE_LWT_IN,
6784 },
6785 {
6786 "liveness pruning and write screening",
6787 .insns = {
6788 /* Get an unknown value */
6789 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
6790 /* branch conditions teach us nothing about R2 */
6791 BPF_JMP_IMM(BPF_JGE, BPF_REG_2, 0, 1),
6792 BPF_MOV64_IMM(BPF_REG_0, 0),
6793 BPF_JMP_IMM(BPF_JGE, BPF_REG_2, 0, 1),
6794 BPF_MOV64_IMM(BPF_REG_0, 0),
6795 BPF_EXIT_INSN(),
6796 },
6797 .errstr = "R0 !read_ok",
6798 .result = REJECT,
6799 .prog_type = BPF_PROG_TYPE_LWT_IN,
6800 },
6801 {
6802 "varlen_map_value_access pruning",
6803 .insns = {
6804 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6805 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6806 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6807 BPF_LD_MAP_FD(BPF_REG_1, 0),
6808 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6809 BPF_FUNC_map_lookup_elem),
6810 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
6811 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
6812 BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES),
6813 BPF_JMP_REG(BPF_JSGT, BPF_REG_2, BPF_REG_1, 1),
6814 BPF_MOV32_IMM(BPF_REG_1, 0),
6815 BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2),
6816 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6817 BPF_JMP_IMM(BPF_JA, 0, 0, 0),
6818 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
6819 offsetof(struct test_val, foo)),
6820 BPF_EXIT_INSN(),
6821 },
6822 .fixup_map2 = { 3 },
6823 .errstr_unpriv = "R0 leaks addr",
6824 .errstr = "R0 unbounded memory access",
6825 .result_unpriv = REJECT,
6826 .result = REJECT,
6827 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
6828 },
6829 {
6830 "invalid 64-bit BPF_END",
6831 .insns = {
6832 BPF_MOV32_IMM(BPF_REG_0, 0),
6833 {
6834 .code = BPF_ALU64 | BPF_END | BPF_TO_LE,
6835 .dst_reg = BPF_REG_0,
6836 .src_reg = 0,
6837 .off = 0,
6838 .imm = 32,
6839 },
6840 BPF_EXIT_INSN(),
6841 },
6842 .errstr = "BPF_END uses reserved fields",
6843 .result = REJECT,
6844 },
6845 {
6846 "meta access, test1",
6847 .insns = {
6848 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
6849 offsetof(struct xdp_md, data_meta)),
6850 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
6851 offsetof(struct xdp_md, data)),
6852 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
6853 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
6854 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
6855 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
6856 BPF_MOV64_IMM(BPF_REG_0, 0),
6857 BPF_EXIT_INSN(),
6858 },
6859 .result = ACCEPT,
6860 .prog_type = BPF_PROG_TYPE_XDP,
6861 },
6862 {
6863 "meta access, test2",
6864 .insns = {
6865 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
6866 offsetof(struct xdp_md, data_meta)),
6867 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
6868 offsetof(struct xdp_md, data)),
6869 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
6870 BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 8),
6871 BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
6872 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 8),
6873 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1),
6874 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
6875 BPF_MOV64_IMM(BPF_REG_0, 0),
6876 BPF_EXIT_INSN(),
6877 },
6878 .result = REJECT,
6879 .errstr = "invalid access to packet, off=-8",
6880 .prog_type = BPF_PROG_TYPE_XDP,
6881 },
6882 {
6883 "meta access, test3",
6884 .insns = {
6885 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
6886 offsetof(struct xdp_md, data_meta)),
6887 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
6888 offsetof(struct xdp_md, data_end)),
6889 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
6890 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
6891 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
6892 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
6893 BPF_MOV64_IMM(BPF_REG_0, 0),
6894 BPF_EXIT_INSN(),
6895 },
6896 .result = REJECT,
6897 .errstr = "invalid access to packet",
6898 .prog_type = BPF_PROG_TYPE_XDP,
6899 },
6900 {
6901 "meta access, test4",
6902 .insns = {
6903 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
6904 offsetof(struct xdp_md, data_meta)),
6905 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
6906 offsetof(struct xdp_md, data_end)),
6907 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1,
6908 offsetof(struct xdp_md, data)),
6909 BPF_MOV64_REG(BPF_REG_0, BPF_REG_4),
6910 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
6911 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
6912 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
6913 BPF_MOV64_IMM(BPF_REG_0, 0),
6914 BPF_EXIT_INSN(),
6915 },
6916 .result = REJECT,
6917 .errstr = "invalid access to packet",
6918 .prog_type = BPF_PROG_TYPE_XDP,
6919 },
6920 {
6921 "meta access, test5",
6922 .insns = {
6923 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
6924 offsetof(struct xdp_md, data_meta)),
6925 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1,
6926 offsetof(struct xdp_md, data)),
6927 BPF_MOV64_REG(BPF_REG_0, BPF_REG_3),
6928 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
6929 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_4, 3),
6930 BPF_MOV64_IMM(BPF_REG_2, -8),
6931 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6932 BPF_FUNC_xdp_adjust_meta),
6933 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_3, 0),
6934 BPF_MOV64_IMM(BPF_REG_0, 0),
6935 BPF_EXIT_INSN(),
6936 },
6937 .result = REJECT,
6938 .errstr = "R3 !read_ok",
6939 .prog_type = BPF_PROG_TYPE_XDP,
6940 },
6941 {
6942 "meta access, test6",
6943 .insns = {
6944 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
6945 offsetof(struct xdp_md, data_meta)),
6946 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
6947 offsetof(struct xdp_md, data)),
6948 BPF_MOV64_REG(BPF_REG_0, BPF_REG_3),
6949 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
6950 BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
6951 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 8),
6952 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_0, 1),
6953 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
6954 BPF_MOV64_IMM(BPF_REG_0, 0),
6955 BPF_EXIT_INSN(),
6956 },
6957 .result = REJECT,
6958 .errstr = "invalid access to packet",
6959 .prog_type = BPF_PROG_TYPE_XDP,
6960 },
6961 {
6962 "meta access, test7",
6963 .insns = {
6964 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
6965 offsetof(struct xdp_md, data_meta)),
6966 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
6967 offsetof(struct xdp_md, data)),
6968 BPF_MOV64_REG(BPF_REG_0, BPF_REG_3),
6969 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
6970 BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
6971 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 8),
6972 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1),
6973 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
6974 BPF_MOV64_IMM(BPF_REG_0, 0),
6975 BPF_EXIT_INSN(),
6976 },
6977 .result = ACCEPT,
6978 .prog_type = BPF_PROG_TYPE_XDP,
6979 },
6980 {
6981 "meta access, test8",
6982 .insns = {
6983 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
6984 offsetof(struct xdp_md, data_meta)),
6985 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
6986 offsetof(struct xdp_md, data)),
6987 BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
6988 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0xFFFF),
6989 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1),
6990 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
6991 BPF_MOV64_IMM(BPF_REG_0, 0),
6992 BPF_EXIT_INSN(),
6993 },
6994 .result = ACCEPT,
6995 .prog_type = BPF_PROG_TYPE_XDP,
6996 },
6997 {
6998 "meta access, test9",
6999 .insns = {
7000 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7001 offsetof(struct xdp_md, data_meta)),
7002 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7003 offsetof(struct xdp_md, data)),
7004 BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
7005 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0xFFFF),
7006 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 1),
7007 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1),
7008 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
7009 BPF_MOV64_IMM(BPF_REG_0, 0),
7010 BPF_EXIT_INSN(),
7011 },
7012 .result = REJECT,
7013 .errstr = "invalid access to packet",
7014 .prog_type = BPF_PROG_TYPE_XDP,
7015 },
7016 {
7017 "meta access, test10",
7018 .insns = {
7019 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7020 offsetof(struct xdp_md, data_meta)),
7021 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7022 offsetof(struct xdp_md, data)),
7023 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1,
7024 offsetof(struct xdp_md, data_end)),
7025 BPF_MOV64_IMM(BPF_REG_5, 42),
7026 BPF_MOV64_IMM(BPF_REG_6, 24),
7027 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_5, -8),
7028 BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_6, -8),
7029 BPF_LDX_MEM(BPF_DW, BPF_REG_5, BPF_REG_10, -8),
7030 BPF_JMP_IMM(BPF_JGT, BPF_REG_5, 100, 6),
7031 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_5),
7032 BPF_MOV64_REG(BPF_REG_5, BPF_REG_3),
7033 BPF_MOV64_REG(BPF_REG_6, BPF_REG_2),
7034 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 8),
7035 BPF_JMP_REG(BPF_JGT, BPF_REG_6, BPF_REG_5, 1),
7036 BPF_LDX_MEM(BPF_B, BPF_REG_2, BPF_REG_2, 0),
7037 BPF_MOV64_IMM(BPF_REG_0, 0),
7038 BPF_EXIT_INSN(),
7039 },
7040 .result = REJECT,
7041 .errstr = "invalid access to packet",
7042 .prog_type = BPF_PROG_TYPE_XDP,
7043 },
7044 {
7045 "meta access, test11",
7046 .insns = {
7047 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7048 offsetof(struct xdp_md, data_meta)),
7049 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7050 offsetof(struct xdp_md, data)),
7051 BPF_MOV64_IMM(BPF_REG_5, 42),
7052 BPF_MOV64_IMM(BPF_REG_6, 24),
7053 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_5, -8),
7054 BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_6, -8),
7055 BPF_LDX_MEM(BPF_DW, BPF_REG_5, BPF_REG_10, -8),
7056 BPF_JMP_IMM(BPF_JGT, BPF_REG_5, 100, 6),
7057 BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_5),
7058 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
7059 BPF_MOV64_REG(BPF_REG_6, BPF_REG_2),
7060 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 8),
7061 BPF_JMP_REG(BPF_JGT, BPF_REG_6, BPF_REG_3, 1),
7062 BPF_LDX_MEM(BPF_B, BPF_REG_5, BPF_REG_5, 0),
7063 BPF_MOV64_IMM(BPF_REG_0, 0),
7064 BPF_EXIT_INSN(),
7065 },
7066 .result = ACCEPT,
7067 .prog_type = BPF_PROG_TYPE_XDP,
7068 },
7069 {
7070 "meta access, test12",
7071 .insns = {
7072 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7073 offsetof(struct xdp_md, data_meta)),
7074 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7075 offsetof(struct xdp_md, data)),
7076 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1,
7077 offsetof(struct xdp_md, data_end)),
7078 BPF_MOV64_REG(BPF_REG_5, BPF_REG_3),
7079 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 16),
7080 BPF_JMP_REG(BPF_JGT, BPF_REG_5, BPF_REG_4, 5),
7081 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_3, 0),
7082 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
7083 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 16),
7084 BPF_JMP_REG(BPF_JGT, BPF_REG_5, BPF_REG_3, 1),
7085 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
7086 BPF_MOV64_IMM(BPF_REG_0, 0),
7087 BPF_EXIT_INSN(),
7088 },
7089 .result = ACCEPT,
7090 .prog_type = BPF_PROG_TYPE_XDP,
7091 },
7092 {
7093 "arithmetic ops make PTR_TO_CTX unusable",
7094 .insns = {
7095 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1,
7096 offsetof(struct __sk_buff, data) -
7097 offsetof(struct __sk_buff, mark)),
7098 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
7099 offsetof(struct __sk_buff, mark)),
7100 BPF_EXIT_INSN(),
7101 },
7102 .errstr = "dereference of modified ctx ptr R1 off=68+8, ctx+const is allowed, ctx+const+const is not",
7103 .result = REJECT,
7104 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
7105 },
7106 {
7107 "XDP pkt read, pkt_end mangling, bad access 1",
7108 .insns = {
7109 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7110 offsetof(struct xdp_md, data)),
7111 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7112 offsetof(struct xdp_md, data_end)),
7113 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7114 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7115 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 8),
7116 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
7117 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7118 BPF_MOV64_IMM(BPF_REG_0, 0),
7119 BPF_EXIT_INSN(),
7120 },
7121 .errstr = "R1 offset is outside of the packet",
7122 .result = REJECT,
7123 .prog_type = BPF_PROG_TYPE_XDP,
7124 },
7125 {
7126 "XDP pkt read, pkt_end mangling, bad access 2",
7127 .insns = {
7128 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7129 offsetof(struct xdp_md, data)),
7130 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7131 offsetof(struct xdp_md, data_end)),
7132 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7133 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7134 BPF_ALU64_IMM(BPF_SUB, BPF_REG_3, 8),
7135 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
7136 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7137 BPF_MOV64_IMM(BPF_REG_0, 0),
7138 BPF_EXIT_INSN(),
7139 },
7140 .errstr = "R1 offset is outside of the packet",
7141 .result = REJECT,
7142 .prog_type = BPF_PROG_TYPE_XDP,
7143 },
7144 {
7145 "XDP pkt read, pkt_data' > pkt_end, good access",
7146 .insns = {
7147 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7148 offsetof(struct xdp_md, data)),
7149 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7150 offsetof(struct xdp_md, data_end)),
7151 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7152 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7153 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
7154 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7155 BPF_MOV64_IMM(BPF_REG_0, 0),
7156 BPF_EXIT_INSN(),
7157 },
7158 .result = ACCEPT,
7159 .prog_type = BPF_PROG_TYPE_XDP,
7160 },
7161 {
7162 "XDP pkt read, pkt_data' > pkt_end, bad access 1",
7163 .insns = {
7164 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7165 offsetof(struct xdp_md, data)),
7166 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7167 offsetof(struct xdp_md, data_end)),
7168 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7169 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7170 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
7171 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -4),
7172 BPF_MOV64_IMM(BPF_REG_0, 0),
7173 BPF_EXIT_INSN(),
7174 },
7175 .errstr = "R1 offset is outside of the packet",
7176 .result = REJECT,
7177 .prog_type = BPF_PROG_TYPE_XDP,
7178 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7179 },
7180 {
7181 "XDP pkt read, pkt_data' > pkt_end, bad access 2",
7182 .insns = {
7183 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7184 offsetof(struct xdp_md, data)),
7185 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7186 offsetof(struct xdp_md, data_end)),
7187 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7188 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7189 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 0),
7190 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7191 BPF_MOV64_IMM(BPF_REG_0, 0),
7192 BPF_EXIT_INSN(),
7193 },
7194 .errstr = "R1 offset is outside of the packet",
7195 .result = REJECT,
7196 .prog_type = BPF_PROG_TYPE_XDP,
7197 },
7198 {
7199 "XDP pkt read, pkt_end > pkt_data', good access",
7200 .insns = {
7201 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7202 offsetof(struct xdp_md, data)),
7203 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7204 offsetof(struct xdp_md, data_end)),
7205 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7206 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7207 BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1),
7208 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7209 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -5),
7210 BPF_MOV64_IMM(BPF_REG_0, 0),
7211 BPF_EXIT_INSN(),
7212 },
7213 .result = ACCEPT,
7214 .prog_type = BPF_PROG_TYPE_XDP,
7215 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7216 },
7217 {
7218 "XDP pkt read, pkt_end > pkt_data', bad access 1",
7219 .insns = {
7220 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7221 offsetof(struct xdp_md, data)),
7222 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7223 offsetof(struct xdp_md, data_end)),
7224 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7225 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7226 BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1),
7227 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7228 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7229 BPF_MOV64_IMM(BPF_REG_0, 0),
7230 BPF_EXIT_INSN(),
7231 },
7232 .errstr = "R1 offset is outside of the packet",
7233 .result = REJECT,
7234 .prog_type = BPF_PROG_TYPE_XDP,
7235 },
7236 {
7237 "XDP pkt read, pkt_end > pkt_data', bad access 2",
7238 .insns = {
7239 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7240 offsetof(struct xdp_md, data)),
7241 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7242 offsetof(struct xdp_md, data_end)),
7243 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7244 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7245 BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1),
7246 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7247 BPF_MOV64_IMM(BPF_REG_0, 0),
7248 BPF_EXIT_INSN(),
7249 },
7250 .errstr = "R1 offset is outside of the packet",
7251 .result = REJECT,
7252 .prog_type = BPF_PROG_TYPE_XDP,
7253 },
7254 {
7255 "XDP pkt read, pkt_data' < pkt_end, good access",
7256 .insns = {
7257 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7258 offsetof(struct xdp_md, data)),
7259 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7260 offsetof(struct xdp_md, data_end)),
7261 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7262 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7263 BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1),
7264 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7265 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -5),
7266 BPF_MOV64_IMM(BPF_REG_0, 0),
7267 BPF_EXIT_INSN(),
7268 },
7269 .result = ACCEPT,
7270 .prog_type = BPF_PROG_TYPE_XDP,
7271 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7272 },
7273 {
7274 "XDP pkt read, pkt_data' < pkt_end, bad access 1",
7275 .insns = {
7276 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7277 offsetof(struct xdp_md, data)),
7278 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7279 offsetof(struct xdp_md, data_end)),
7280 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7281 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7282 BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1),
7283 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7284 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7285 BPF_MOV64_IMM(BPF_REG_0, 0),
7286 BPF_EXIT_INSN(),
7287 },
7288 .errstr = "R1 offset is outside of the packet",
7289 .result = REJECT,
7290 .prog_type = BPF_PROG_TYPE_XDP,
7291 },
7292 {
7293 "XDP pkt read, pkt_data' < pkt_end, bad access 2",
7294 .insns = {
7295 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7296 offsetof(struct xdp_md, data)),
7297 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7298 offsetof(struct xdp_md, data_end)),
7299 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7300 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7301 BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1),
7302 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7303 BPF_MOV64_IMM(BPF_REG_0, 0),
7304 BPF_EXIT_INSN(),
7305 },
7306 .errstr = "R1 offset is outside of the packet",
7307 .result = REJECT,
7308 .prog_type = BPF_PROG_TYPE_XDP,
7309 },
7310 {
7311 "XDP pkt read, pkt_end < pkt_data', good access",
7312 .insns = {
7313 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7314 offsetof(struct xdp_md, data)),
7315 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7316 offsetof(struct xdp_md, data_end)),
7317 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7318 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7319 BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1),
7320 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7321 BPF_MOV64_IMM(BPF_REG_0, 0),
7322 BPF_EXIT_INSN(),
7323 },
7324 .result = ACCEPT,
7325 .prog_type = BPF_PROG_TYPE_XDP,
7326 },
7327 {
7328 "XDP pkt read, pkt_end < pkt_data', bad access 1",
7329 .insns = {
7330 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7331 offsetof(struct xdp_md, data)),
7332 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7333 offsetof(struct xdp_md, data_end)),
7334 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7335 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7336 BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1),
7337 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -4),
7338 BPF_MOV64_IMM(BPF_REG_0, 0),
7339 BPF_EXIT_INSN(),
7340 },
7341 .errstr = "R1 offset is outside of the packet",
7342 .result = REJECT,
7343 .prog_type = BPF_PROG_TYPE_XDP,
7344 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7345 },
7346 {
7347 "XDP pkt read, pkt_end < pkt_data', bad access 2",
7348 .insns = {
7349 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7350 offsetof(struct xdp_md, data)),
7351 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7352 offsetof(struct xdp_md, data_end)),
7353 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7354 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7355 BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 0),
7356 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7357 BPF_MOV64_IMM(BPF_REG_0, 0),
7358 BPF_EXIT_INSN(),
7359 },
7360 .errstr = "R1 offset is outside of the packet",
7361 .result = REJECT,
7362 .prog_type = BPF_PROG_TYPE_XDP,
7363 },
7364 {
7365 "XDP pkt read, pkt_data' >= pkt_end, good access",
7366 .insns = {
7367 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7368 offsetof(struct xdp_md, data)),
7369 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7370 offsetof(struct xdp_md, data_end)),
7371 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7372 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7373 BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1),
7374 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -5),
7375 BPF_MOV64_IMM(BPF_REG_0, 0),
7376 BPF_EXIT_INSN(),
7377 },
7378 .result = ACCEPT,
7379 .prog_type = BPF_PROG_TYPE_XDP,
7380 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7381 },
7382 {
7383 "XDP pkt read, pkt_data' >= pkt_end, bad access 1",
7384 .insns = {
7385 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7386 offsetof(struct xdp_md, data)),
7387 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7388 offsetof(struct xdp_md, data_end)),
7389 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7390 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7391 BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1),
7392 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7393 BPF_MOV64_IMM(BPF_REG_0, 0),
7394 BPF_EXIT_INSN(),
7395 },
7396 .errstr = "R1 offset is outside of the packet",
7397 .result = REJECT,
7398 .prog_type = BPF_PROG_TYPE_XDP,
7399 },
7400 {
7401 "XDP pkt read, pkt_data' >= pkt_end, bad access 2",
7402 .insns = {
7403 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7404 offsetof(struct xdp_md, data)),
7405 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7406 offsetof(struct xdp_md, data_end)),
7407 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7408 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7409 BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 0),
7410 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -5),
7411 BPF_MOV64_IMM(BPF_REG_0, 0),
7412 BPF_EXIT_INSN(),
7413 },
7414 .errstr = "R1 offset is outside of the packet",
7415 .result = REJECT,
7416 .prog_type = BPF_PROG_TYPE_XDP,
7417 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7418 },
7419 {
7420 "XDP pkt read, pkt_end >= pkt_data', good access",
7421 .insns = {
7422 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7423 offsetof(struct xdp_md, data)),
7424 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7425 offsetof(struct xdp_md, data_end)),
7426 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7427 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7428 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1),
7429 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7430 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7431 BPF_MOV64_IMM(BPF_REG_0, 0),
7432 BPF_EXIT_INSN(),
7433 },
7434 .result = ACCEPT,
7435 .prog_type = BPF_PROG_TYPE_XDP,
7436 },
7437 {
7438 "XDP pkt read, pkt_end >= pkt_data', bad access 1",
7439 .insns = {
7440 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7441 offsetof(struct xdp_md, data)),
7442 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7443 offsetof(struct xdp_md, data_end)),
7444 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7445 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7446 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1),
7447 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7448 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -4),
7449 BPF_MOV64_IMM(BPF_REG_0, 0),
7450 BPF_EXIT_INSN(),
7451 },
7452 .errstr = "R1 offset is outside of the packet",
7453 .result = REJECT,
7454 .prog_type = BPF_PROG_TYPE_XDP,
7455 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7456 },
7457 {
7458 "XDP pkt read, pkt_end >= pkt_data', bad access 2",
7459 .insns = {
7460 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7461 offsetof(struct xdp_md, data)),
7462 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7463 offsetof(struct xdp_md, data_end)),
7464 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7465 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7466 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1),
7467 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7468 BPF_MOV64_IMM(BPF_REG_0, 0),
7469 BPF_EXIT_INSN(),
7470 },
7471 .errstr = "R1 offset is outside of the packet",
7472 .result = REJECT,
7473 .prog_type = BPF_PROG_TYPE_XDP,
7474 },
7475 {
7476 "XDP pkt read, pkt_data' <= pkt_end, good access",
7477 .insns = {
7478 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7479 offsetof(struct xdp_md, data)),
7480 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7481 offsetof(struct xdp_md, data_end)),
7482 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7483 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7484 BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1),
7485 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7486 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7487 BPF_MOV64_IMM(BPF_REG_0, 0),
7488 BPF_EXIT_INSN(),
7489 },
7490 .result = ACCEPT,
7491 .prog_type = BPF_PROG_TYPE_XDP,
7492 },
7493 {
7494 "XDP pkt read, pkt_data' <= pkt_end, bad access 1",
7495 .insns = {
7496 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7497 offsetof(struct xdp_md, data)),
7498 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7499 offsetof(struct xdp_md, data_end)),
7500 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7501 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7502 BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1),
7503 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7504 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -4),
7505 BPF_MOV64_IMM(BPF_REG_0, 0),
7506 BPF_EXIT_INSN(),
7507 },
7508 .errstr = "R1 offset is outside of the packet",
7509 .result = REJECT,
7510 .prog_type = BPF_PROG_TYPE_XDP,
7511 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7512 },
7513 {
7514 "XDP pkt read, pkt_data' <= pkt_end, bad access 2",
7515 .insns = {
7516 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7517 offsetof(struct xdp_md, data)),
7518 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7519 offsetof(struct xdp_md, data_end)),
7520 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7521 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7522 BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1),
7523 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7524 BPF_MOV64_IMM(BPF_REG_0, 0),
7525 BPF_EXIT_INSN(),
7526 },
7527 .errstr = "R1 offset is outside of the packet",
7528 .result = REJECT,
7529 .prog_type = BPF_PROG_TYPE_XDP,
7530 },
7531 {
7532 "XDP pkt read, pkt_end <= pkt_data', good access",
7533 .insns = {
7534 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7535 offsetof(struct xdp_md, data)),
7536 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7537 offsetof(struct xdp_md, data_end)),
7538 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7539 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7540 BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1),
7541 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -5),
7542 BPF_MOV64_IMM(BPF_REG_0, 0),
7543 BPF_EXIT_INSN(),
7544 },
7545 .result = ACCEPT,
7546 .prog_type = BPF_PROG_TYPE_XDP,
7547 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7548 },
7549 {
7550 "XDP pkt read, pkt_end <= pkt_data', bad access 1",
7551 .insns = {
7552 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7553 offsetof(struct xdp_md, data)),
7554 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7555 offsetof(struct xdp_md, data_end)),
7556 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7557 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7558 BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1),
7559 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7560 BPF_MOV64_IMM(BPF_REG_0, 0),
7561 BPF_EXIT_INSN(),
7562 },
7563 .errstr = "R1 offset is outside of the packet",
7564 .result = REJECT,
7565 .prog_type = BPF_PROG_TYPE_XDP,
7566 },
7567 {
7568 "XDP pkt read, pkt_end <= pkt_data', bad access 2",
7569 .insns = {
7570 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7571 offsetof(struct xdp_md, data)),
7572 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7573 offsetof(struct xdp_md, data_end)),
7574 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7575 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7576 BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 0),
7577 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -5),
7578 BPF_MOV64_IMM(BPF_REG_0, 0),
7579 BPF_EXIT_INSN(),
7580 },
7581 .errstr = "R1 offset is outside of the packet",
7582 .result = REJECT,
7583 .prog_type = BPF_PROG_TYPE_XDP,
7584 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7585 },
7586 {
7587 "XDP pkt read, pkt_meta' > pkt_data, good access",
7588 .insns = {
7589 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7590 offsetof(struct xdp_md, data_meta)),
7591 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7592 offsetof(struct xdp_md, data)),
7593 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7594 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7595 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
7596 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7597 BPF_MOV64_IMM(BPF_REG_0, 0),
7598 BPF_EXIT_INSN(),
7599 },
7600 .result = ACCEPT,
7601 .prog_type = BPF_PROG_TYPE_XDP,
7602 },
7603 {
7604 "XDP pkt read, pkt_meta' > pkt_data, bad access 1",
7605 .insns = {
7606 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7607 offsetof(struct xdp_md, data_meta)),
7608 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7609 offsetof(struct xdp_md, data)),
7610 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7611 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7612 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
7613 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -4),
7614 BPF_MOV64_IMM(BPF_REG_0, 0),
7615 BPF_EXIT_INSN(),
7616 },
7617 .errstr = "R1 offset is outside of the packet",
7618 .result = REJECT,
7619 .prog_type = BPF_PROG_TYPE_XDP,
7620 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7621 },
7622 {
7623 "XDP pkt read, pkt_meta' > pkt_data, bad access 2",
7624 .insns = {
7625 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7626 offsetof(struct xdp_md, data_meta)),
7627 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7628 offsetof(struct xdp_md, data)),
7629 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7630 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7631 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 0),
7632 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7633 BPF_MOV64_IMM(BPF_REG_0, 0),
7634 BPF_EXIT_INSN(),
7635 },
7636 .errstr = "R1 offset is outside of the packet",
7637 .result = REJECT,
7638 .prog_type = BPF_PROG_TYPE_XDP,
7639 },
7640 {
7641 "XDP pkt read, pkt_data > pkt_meta', good access",
7642 .insns = {
7643 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7644 offsetof(struct xdp_md, data_meta)),
7645 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7646 offsetof(struct xdp_md, data)),
7647 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7648 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7649 BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1),
7650 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7651 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -5),
7652 BPF_MOV64_IMM(BPF_REG_0, 0),
7653 BPF_EXIT_INSN(),
7654 },
7655 .result = ACCEPT,
7656 .prog_type = BPF_PROG_TYPE_XDP,
7657 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7658 },
7659 {
7660 "XDP pkt read, pkt_data > pkt_meta', bad access 1",
7661 .insns = {
7662 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7663 offsetof(struct xdp_md, data_meta)),
7664 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7665 offsetof(struct xdp_md, data)),
7666 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7667 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7668 BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1),
7669 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7670 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7671 BPF_MOV64_IMM(BPF_REG_0, 0),
7672 BPF_EXIT_INSN(),
7673 },
7674 .errstr = "R1 offset is outside of the packet",
7675 .result = REJECT,
7676 .prog_type = BPF_PROG_TYPE_XDP,
7677 },
7678 {
7679 "XDP pkt read, pkt_data > pkt_meta', bad access 2",
7680 .insns = {
7681 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7682 offsetof(struct xdp_md, data_meta)),
7683 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7684 offsetof(struct xdp_md, data)),
7685 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7686 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7687 BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1),
7688 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7689 BPF_MOV64_IMM(BPF_REG_0, 0),
7690 BPF_EXIT_INSN(),
7691 },
7692 .errstr = "R1 offset is outside of the packet",
7693 .result = REJECT,
7694 .prog_type = BPF_PROG_TYPE_XDP,
7695 },
7696 {
7697 "XDP pkt read, pkt_meta' < pkt_data, good access",
7698 .insns = {
7699 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7700 offsetof(struct xdp_md, data_meta)),
7701 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7702 offsetof(struct xdp_md, data)),
7703 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7704 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7705 BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1),
7706 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7707 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -5),
7708 BPF_MOV64_IMM(BPF_REG_0, 0),
7709 BPF_EXIT_INSN(),
7710 },
7711 .result = ACCEPT,
7712 .prog_type = BPF_PROG_TYPE_XDP,
7713 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7714 },
7715 {
7716 "XDP pkt read, pkt_meta' < pkt_data, bad access 1",
7717 .insns = {
7718 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7719 offsetof(struct xdp_md, data_meta)),
7720 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7721 offsetof(struct xdp_md, data)),
7722 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7723 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7724 BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1),
7725 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7726 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7727 BPF_MOV64_IMM(BPF_REG_0, 0),
7728 BPF_EXIT_INSN(),
7729 },
7730 .errstr = "R1 offset is outside of the packet",
7731 .result = REJECT,
7732 .prog_type = BPF_PROG_TYPE_XDP,
7733 },
7734 {
7735 "XDP pkt read, pkt_meta' < pkt_data, bad access 2",
7736 .insns = {
7737 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7738 offsetof(struct xdp_md, data_meta)),
7739 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7740 offsetof(struct xdp_md, data)),
7741 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7742 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7743 BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1),
7744 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7745 BPF_MOV64_IMM(BPF_REG_0, 0),
7746 BPF_EXIT_INSN(),
7747 },
7748 .errstr = "R1 offset is outside of the packet",
7749 .result = REJECT,
7750 .prog_type = BPF_PROG_TYPE_XDP,
7751 },
7752 {
7753 "XDP pkt read, pkt_data < pkt_meta', good access",
7754 .insns = {
7755 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7756 offsetof(struct xdp_md, data_meta)),
7757 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7758 offsetof(struct xdp_md, data)),
7759 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7760 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7761 BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1),
7762 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7763 BPF_MOV64_IMM(BPF_REG_0, 0),
7764 BPF_EXIT_INSN(),
7765 },
7766 .result = ACCEPT,
7767 .prog_type = BPF_PROG_TYPE_XDP,
7768 },
7769 {
7770 "XDP pkt read, pkt_data < pkt_meta', bad access 1",
7771 .insns = {
7772 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7773 offsetof(struct xdp_md, data_meta)),
7774 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7775 offsetof(struct xdp_md, data)),
7776 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7777 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7778 BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1),
7779 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -4),
7780 BPF_MOV64_IMM(BPF_REG_0, 0),
7781 BPF_EXIT_INSN(),
7782 },
7783 .errstr = "R1 offset is outside of the packet",
7784 .result = REJECT,
7785 .prog_type = BPF_PROG_TYPE_XDP,
7786 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7787 },
7788 {
7789 "XDP pkt read, pkt_data < pkt_meta', bad access 2",
7790 .insns = {
7791 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7792 offsetof(struct xdp_md, data_meta)),
7793 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7794 offsetof(struct xdp_md, data)),
7795 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7796 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7797 BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 0),
7798 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7799 BPF_MOV64_IMM(BPF_REG_0, 0),
7800 BPF_EXIT_INSN(),
7801 },
7802 .errstr = "R1 offset is outside of the packet",
7803 .result = REJECT,
7804 .prog_type = BPF_PROG_TYPE_XDP,
7805 },
7806 {
7807 "XDP pkt read, pkt_meta' >= pkt_data, good access",
7808 .insns = {
7809 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7810 offsetof(struct xdp_md, data_meta)),
7811 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7812 offsetof(struct xdp_md, data)),
7813 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7814 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7815 BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1),
7816 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -5),
7817 BPF_MOV64_IMM(BPF_REG_0, 0),
7818 BPF_EXIT_INSN(),
7819 },
7820 .result = ACCEPT,
7821 .prog_type = BPF_PROG_TYPE_XDP,
7822 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7823 },
7824 {
7825 "XDP pkt read, pkt_meta' >= pkt_data, bad access 1",
7826 .insns = {
7827 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7828 offsetof(struct xdp_md, data_meta)),
7829 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7830 offsetof(struct xdp_md, data)),
7831 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7832 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7833 BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1),
7834 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7835 BPF_MOV64_IMM(BPF_REG_0, 0),
7836 BPF_EXIT_INSN(),
7837 },
7838 .errstr = "R1 offset is outside of the packet",
7839 .result = REJECT,
7840 .prog_type = BPF_PROG_TYPE_XDP,
7841 },
7842 {
7843 "XDP pkt read, pkt_meta' >= pkt_data, bad access 2",
7844 .insns = {
7845 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7846 offsetof(struct xdp_md, data_meta)),
7847 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7848 offsetof(struct xdp_md, data)),
7849 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7850 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7851 BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 0),
7852 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -5),
7853 BPF_MOV64_IMM(BPF_REG_0, 0),
7854 BPF_EXIT_INSN(),
7855 },
7856 .errstr = "R1 offset is outside of the packet",
7857 .result = REJECT,
7858 .prog_type = BPF_PROG_TYPE_XDP,
7859 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7860 },
7861 {
7862 "XDP pkt read, pkt_data >= pkt_meta', good access",
7863 .insns = {
7864 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7865 offsetof(struct xdp_md, data_meta)),
7866 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7867 offsetof(struct xdp_md, data)),
7868 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7869 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7870 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1),
7871 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7872 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7873 BPF_MOV64_IMM(BPF_REG_0, 0),
7874 BPF_EXIT_INSN(),
7875 },
7876 .result = ACCEPT,
7877 .prog_type = BPF_PROG_TYPE_XDP,
7878 },
7879 {
7880 "XDP pkt read, pkt_data >= pkt_meta', bad access 1",
7881 .insns = {
7882 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7883 offsetof(struct xdp_md, data_meta)),
7884 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7885 offsetof(struct xdp_md, data)),
7886 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7887 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7888 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1),
7889 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7890 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -4),
7891 BPF_MOV64_IMM(BPF_REG_0, 0),
7892 BPF_EXIT_INSN(),
7893 },
7894 .errstr = "R1 offset is outside of the packet",
7895 .result = REJECT,
7896 .prog_type = BPF_PROG_TYPE_XDP,
7897 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7898 },
7899 {
7900 "XDP pkt read, pkt_data >= pkt_meta', bad access 2",
7901 .insns = {
7902 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7903 offsetof(struct xdp_md, data_meta)),
7904 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7905 offsetof(struct xdp_md, data)),
7906 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7907 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7908 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1),
7909 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7910 BPF_MOV64_IMM(BPF_REG_0, 0),
7911 BPF_EXIT_INSN(),
7912 },
7913 .errstr = "R1 offset is outside of the packet",
7914 .result = REJECT,
7915 .prog_type = BPF_PROG_TYPE_XDP,
7916 },
7917 {
7918 "XDP pkt read, pkt_meta' <= pkt_data, good access",
7919 .insns = {
7920 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7921 offsetof(struct xdp_md, data_meta)),
7922 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7923 offsetof(struct xdp_md, data)),
7924 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7925 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7926 BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1),
7927 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7928 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7929 BPF_MOV64_IMM(BPF_REG_0, 0),
7930 BPF_EXIT_INSN(),
7931 },
7932 .result = ACCEPT,
7933 .prog_type = BPF_PROG_TYPE_XDP,
7934 },
7935 {
7936 "XDP pkt read, pkt_meta' <= pkt_data, bad access 1",
7937 .insns = {
7938 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7939 offsetof(struct xdp_md, data_meta)),
7940 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7941 offsetof(struct xdp_md, data)),
7942 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7943 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7944 BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1),
7945 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
7946 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -4),
7947 BPF_MOV64_IMM(BPF_REG_0, 0),
7948 BPF_EXIT_INSN(),
7949 },
7950 .errstr = "R1 offset is outside of the packet",
7951 .result = REJECT,
7952 .prog_type = BPF_PROG_TYPE_XDP,
7953 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7954 },
7955 {
7956 "XDP pkt read, pkt_meta' <= pkt_data, bad access 2",
7957 .insns = {
7958 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7959 offsetof(struct xdp_md, data_meta)),
7960 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7961 offsetof(struct xdp_md, data)),
7962 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7963 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7964 BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1),
7965 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
7966 BPF_MOV64_IMM(BPF_REG_0, 0),
7967 BPF_EXIT_INSN(),
7968 },
7969 .errstr = "R1 offset is outside of the packet",
7970 .result = REJECT,
7971 .prog_type = BPF_PROG_TYPE_XDP,
7972 },
7973 {
7974 "XDP pkt read, pkt_data <= pkt_meta', good access",
7975 .insns = {
7976 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7977 offsetof(struct xdp_md, data_meta)),
7978 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7979 offsetof(struct xdp_md, data)),
7980 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7981 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
7982 BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1),
7983 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -5),
7984 BPF_MOV64_IMM(BPF_REG_0, 0),
7985 BPF_EXIT_INSN(),
7986 },
7987 .result = ACCEPT,
7988 .prog_type = BPF_PROG_TYPE_XDP,
7989 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
7990 },
7991 {
7992 "XDP pkt read, pkt_data <= pkt_meta', bad access 1",
7993 .insns = {
7994 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7995 offsetof(struct xdp_md, data_meta)),
7996 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
7997 offsetof(struct xdp_md, data)),
7998 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
7999 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
8000 BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1),
8001 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8),
8002 BPF_MOV64_IMM(BPF_REG_0, 0),
8003 BPF_EXIT_INSN(),
8004 },
8005 .errstr = "R1 offset is outside of the packet",
8006 .result = REJECT,
8007 .prog_type = BPF_PROG_TYPE_XDP,
8008 },
8009 {
8010 "XDP pkt read, pkt_data <= pkt_meta', bad access 2",
8011 .insns = {
8012 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
8013 offsetof(struct xdp_md, data_meta)),
8014 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
8015 offsetof(struct xdp_md, data)),
8016 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
8017 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
8018 BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 0),
8019 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -5),
8020 BPF_MOV64_IMM(BPF_REG_0, 0),
8021 BPF_EXIT_INSN(),
8022 },
8023 .errstr = "R1 offset is outside of the packet",
8024 .result = REJECT,
8025 .prog_type = BPF_PROG_TYPE_XDP,
8026 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
8027 },
8028 {
8029 "bpf_exit with invalid return code. test1",
8030 .insns = {
8031 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
8032 BPF_EXIT_INSN(),
8033 },
8034 .errstr = "R0 has value (0x0; 0xffffffff)",
8035 .result = REJECT,
8036 .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
8037 },
8038 {
8039 "bpf_exit with invalid return code. test2",
8040 .insns = {
8041 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
8042 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
8043 BPF_EXIT_INSN(),
8044 },
8045 .result = ACCEPT,
8046 .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
8047 },
8048 {
8049 "bpf_exit with invalid return code. test3",
8050 .insns = {
8051 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
8052 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 3),
8053 BPF_EXIT_INSN(),
8054 },
8055 .errstr = "R0 has value (0x0; 0x3)",
8056 .result = REJECT,
8057 .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
8058 },
8059 {
8060 "bpf_exit with invalid return code. test4",
8061 .insns = {
8062 BPF_MOV64_IMM(BPF_REG_0, 1),
8063 BPF_EXIT_INSN(),
8064 },
8065 .result = ACCEPT,
8066 .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
8067 },
8068 {
8069 "bpf_exit with invalid return code. test5",
8070 .insns = {
8071 BPF_MOV64_IMM(BPF_REG_0, 2),
8072 BPF_EXIT_INSN(),
8073 },
8074 .errstr = "R0 has value (0x2; 0x0)",
8075 .result = REJECT,
8076 .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
8077 },
8078 {
8079 "bpf_exit with invalid return code. test6",
8080 .insns = {
8081 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
8082 BPF_EXIT_INSN(),
8083 },
8084 .errstr = "R0 is not a known value (ctx)",
8085 .result = REJECT,
8086 .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
8087 },
8088 {
8089 "bpf_exit with invalid return code. test7",
8090 .insns = {
8091 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
8092 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 4),
8093 BPF_ALU64_REG(BPF_MUL, BPF_REG_0, BPF_REG_2),
8094 BPF_EXIT_INSN(),
8095 },
8096 .errstr = "R0 has unknown scalar value",
8097 .result = REJECT,
8098 .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
8099 },
5983}; 8100};
5984 8101
5985static int probe_filter_length(const struct bpf_insn *fp) 8102static int probe_filter_length(const struct bpf_insn *fp)
@@ -6027,7 +8144,7 @@ static int create_map_in_map(void)
6027 return inner_map_fd; 8144 return inner_map_fd;
6028 } 8145 }
6029 8146
6030 outer_map_fd = bpf_create_map_in_map(BPF_MAP_TYPE_ARRAY_OF_MAPS, 8147 outer_map_fd = bpf_create_map_in_map(BPF_MAP_TYPE_ARRAY_OF_MAPS, NULL,
6031 sizeof(int), inner_map_fd, 1, 0); 8148 sizeof(int), inner_map_fd, 1, 0);
6032 if (outer_map_fd < 0) 8149 if (outer_map_fd < 0)
6033 printf("Failed to create array of maps '%s'!\n", 8150 printf("Failed to create array of maps '%s'!\n",
diff --git a/tools/testing/selftests/bpf/test_verifier_log.c b/tools/testing/selftests/bpf/test_verifier_log.c
new file mode 100644
index 000000000000..3cc0b561489e
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_verifier_log.c
@@ -0,0 +1,171 @@
1#include <errno.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <string.h>
5#include <unistd.h>
6
7#include <linux/bpf.h>
8#include <linux/filter.h>
9#include <linux/unistd.h>
10
11#include <bpf/bpf.h>
12
13#define LOG_SIZE (1 << 20)
14
15#define err(str...) printf("ERROR: " str)
16
17static const struct bpf_insn code_sample[] = {
18 /* We need a few instructions to pass the min log length */
19 BPF_MOV64_IMM(BPF_REG_0, 0),
20 BPF_MOV64_IMM(BPF_REG_0, 0),
21 BPF_MOV64_IMM(BPF_REG_0, 0),
22 BPF_MOV64_IMM(BPF_REG_0, 0),
23 BPF_MOV64_IMM(BPF_REG_0, 0),
24 BPF_MOV64_IMM(BPF_REG_0, 0),
25 BPF_MOV64_IMM(BPF_REG_0, 0),
26 BPF_MOV64_IMM(BPF_REG_0, 0),
27 BPF_MOV64_IMM(BPF_REG_0, 0),
28 BPF_MOV64_IMM(BPF_REG_0, 0),
29 BPF_MOV64_IMM(BPF_REG_0, 0),
30 BPF_MOV64_IMM(BPF_REG_0, 0),
31 BPF_MOV64_IMM(BPF_REG_0, 0),
32 BPF_MOV64_IMM(BPF_REG_0, 0),
33 BPF_MOV64_IMM(BPF_REG_0, 0),
34 BPF_MOV64_IMM(BPF_REG_0, 0),
35 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
36 BPF_FUNC_map_lookup_elem),
37 BPF_EXIT_INSN(),
38};
39
40static inline __u64 ptr_to_u64(const void *ptr)
41{
42 return (__u64) (unsigned long) ptr;
43}
44
45static int load(char *log, size_t log_len, int log_level)
46{
47 union bpf_attr attr;
48
49 bzero(&attr, sizeof(attr));
50 attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
51 attr.insn_cnt = (__u32)(sizeof(code_sample) / sizeof(struct bpf_insn));
52 attr.insns = ptr_to_u64(code_sample);
53 attr.license = ptr_to_u64("GPL");
54 attr.log_buf = ptr_to_u64(log);
55 attr.log_size = log_len;
56 attr.log_level = log_level;
57
58 return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
59}
60
61static void check_ret(int ret, int exp_errno)
62{
63 if (ret > 0) {
64 close(ret);
65 err("broken sample loaded successfully!?\n");
66 exit(1);
67 }
68
69 if (!ret || errno != exp_errno) {
70 err("Program load returned: ret:%d/errno:%d, expected ret:%d/errno:%d\n",
71 ret, errno, -1, exp_errno);
72 exit(1);
73 }
74}
75
76static void check_ones(const char *buf, size_t len, const char *msg)
77{
78 while (len--)
79 if (buf[len] != 1) {
80 err("%s", msg);
81 exit(1);
82 }
83}
84
85static void test_log_good(char *log, size_t buf_len, size_t log_len,
86 size_t exp_len, int exp_errno, const char *full_log)
87{
88 size_t len;
89 int ret;
90
91 memset(log, 1, buf_len);
92
93 ret = load(log, log_len, 1);
94 check_ret(ret, exp_errno);
95
96 len = strnlen(log, buf_len);
97 if (len == buf_len) {
98 err("verifier did not NULL terminate the log\n");
99 exit(1);
100 }
101 if (exp_len && len != exp_len) {
102 err("incorrect log length expected:%zd have:%zd\n",
103 exp_len, len);
104 exit(1);
105 }
106
107 if (strchr(log, 1)) {
108 err("verifier leaked a byte through\n");
109 exit(1);
110 }
111
112 check_ones(log + len + 1, buf_len - len - 1,
113 "verifier wrote bytes past NULL termination\n");
114
115 if (memcmp(full_log, log, LOG_SIZE)) {
116 err("log did not match expected output\n");
117 exit(1);
118 }
119}
120
121static void test_log_bad(char *log, size_t log_len, int log_level)
122{
123 int ret;
124
125 ret = load(log, log_len, log_level);
126 check_ret(ret, EINVAL);
127 if (log)
128 check_ones(log, LOG_SIZE,
129 "verifier touched log with bad parameters\n");
130}
131
132int main(int argc, char **argv)
133{
134 char full_log[LOG_SIZE];
135 char log[LOG_SIZE];
136 size_t want_len;
137 int i;
138
139 memset(log, 1, LOG_SIZE);
140
141 /* Test incorrect attr */
142 printf("Test log_level 0...\n");
143 test_log_bad(log, LOG_SIZE, 0);
144
145 printf("Test log_size < 128...\n");
146 test_log_bad(log, 15, 1);
147
148 printf("Test log_buff = NULL...\n");
149 test_log_bad(NULL, LOG_SIZE, 1);
150
151 /* Test with log big enough */
152 printf("Test oversized buffer...\n");
153 test_log_good(full_log, LOG_SIZE, LOG_SIZE, 0, EACCES, full_log);
154
155 want_len = strlen(full_log);
156
157 printf("Test exact buffer...\n");
158 test_log_good(log, LOG_SIZE, want_len + 2, want_len, EACCES, full_log);
159
160 printf("Test undersized buffers...\n");
161 for (i = 0; i < 64; i++) {
162 full_log[want_len - i + 1] = 1;
163 full_log[want_len - i] = 0;
164
165 test_log_good(log, LOG_SIZE, want_len + 1 - i, want_len - i,
166 ENOSPC, full_log);
167 }
168
169 printf("test_verifier_log: OK\n");
170 return 0;
171}
diff --git a/tools/testing/selftests/bpf/test_xdp_meta.c b/tools/testing/selftests/bpf/test_xdp_meta.c
new file mode 100644
index 000000000000..8d0182650653
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_xdp_meta.c
@@ -0,0 +1,53 @@
1#include <linux/bpf.h>
2#include <linux/if_ether.h>
3#include <linux/pkt_cls.h>
4
5#include "bpf_helpers.h"
6
7#define __round_mask(x, y) ((__typeof__(x))((y) - 1))
8#define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1)
9#define ctx_ptr(ctx, mem) (void *)(unsigned long)ctx->mem
10
11SEC("t")
12int ing_cls(struct __sk_buff *ctx)
13{
14 __u8 *data, *data_meta, *data_end;
15 __u32 diff = 0;
16
17 data_meta = ctx_ptr(ctx, data_meta);
18 data_end = ctx_ptr(ctx, data_end);
19 data = ctx_ptr(ctx, data);
20
21 if (data + ETH_ALEN > data_end ||
22 data_meta + round_up(ETH_ALEN, 4) > data)
23 return TC_ACT_SHOT;
24
25 diff |= ((__u32 *)data_meta)[0] ^ ((__u32 *)data)[0];
26 diff |= ((__u16 *)data_meta)[2] ^ ((__u16 *)data)[2];
27
28 return diff ? TC_ACT_SHOT : TC_ACT_OK;
29}
30
31SEC("x")
32int ing_xdp(struct xdp_md *ctx)
33{
34 __u8 *data, *data_meta, *data_end;
35 int ret;
36
37 ret = bpf_xdp_adjust_meta(ctx, -round_up(ETH_ALEN, 4));
38 if (ret < 0)
39 return XDP_DROP;
40
41 data_meta = ctx_ptr(ctx, data_meta);
42 data_end = ctx_ptr(ctx, data_end);
43 data = ctx_ptr(ctx, data);
44
45 if (data + ETH_ALEN > data_end ||
46 data_meta + round_up(ETH_ALEN, 4) > data)
47 return XDP_DROP;
48
49 __builtin_memcpy(data_meta, data, ETH_ALEN);
50 return XDP_PASS;
51}
52
53char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/test_xdp_meta.sh b/tools/testing/selftests/bpf/test_xdp_meta.sh
new file mode 100755
index 000000000000..307aa856cee3
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_xdp_meta.sh
@@ -0,0 +1,51 @@
1#!/bin/sh
2
3cleanup()
4{
5 if [ "$?" = "0" ]; then
6 echo "selftests: test_xdp_meta [PASS]";
7 else
8 echo "selftests: test_xdp_meta [FAILED]";
9 fi
10
11 set +e
12 ip netns del ns1 2> /dev/null
13 ip netns del ns2 2> /dev/null
14}
15
16ip link set dev lo xdp off 2>/dev/null > /dev/null
17if [ $? -ne 0 ];then
18 echo "selftests: [SKIP] Could not run test without the ip xdp support"
19 exit 0
20fi
21set -e
22
23ip netns add ns1
24ip netns add ns2
25
26trap cleanup 0 2 3 6 9
27
28ip link add veth1 type veth peer name veth2
29
30ip link set veth1 netns ns1
31ip link set veth2 netns ns2
32
33ip netns exec ns1 ip addr add 10.1.1.11/24 dev veth1
34ip netns exec ns2 ip addr add 10.1.1.22/24 dev veth2
35
36ip netns exec ns1 tc qdisc add dev veth1 clsact
37ip netns exec ns2 tc qdisc add dev veth2 clsact
38
39ip netns exec ns1 tc filter add dev veth1 ingress bpf da obj test_xdp_meta.o sec t
40ip netns exec ns2 tc filter add dev veth2 ingress bpf da obj test_xdp_meta.o sec t
41
42ip netns exec ns1 ip link set dev veth1 xdp obj test_xdp_meta.o sec x
43ip netns exec ns2 ip link set dev veth2 xdp obj test_xdp_meta.o sec x
44
45ip netns exec ns1 ip link set dev veth1 up
46ip netns exec ns2 ip link set dev veth2 up
47
48ip netns exec ns1 ping -c 1 10.1.1.22
49ip netns exec ns2 ping -c 1 10.1.1.11
50
51exit 0
diff --git a/tools/testing/selftests/bpf/test_xdp_redirect.c b/tools/testing/selftests/bpf/test_xdp_redirect.c
new file mode 100644
index 000000000000..ef9e704be140
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_xdp_redirect.c
@@ -0,0 +1,28 @@
1/* Copyright (c) 2017 VMware
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 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
11 */
12#include <linux/bpf.h>
13#include "bpf_helpers.h"
14
15int _version SEC("version") = 1;
16
17SEC("redirect_to_111")
18int xdp_redirect_to_111(struct xdp_md *xdp)
19{
20 return bpf_redirect(111, 0);
21}
22SEC("redirect_to_222")
23int xdp_redirect_to_222(struct xdp_md *xdp)
24{
25 return bpf_redirect(222, 0);
26}
27
28char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/test_xdp_redirect.sh b/tools/testing/selftests/bpf/test_xdp_redirect.sh
new file mode 100755
index 000000000000..344a3656dea6
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_xdp_redirect.sh
@@ -0,0 +1,59 @@
1#!/bin/sh
2# Create 2 namespaces with two veth peers, and
3# forward packets in-between using generic XDP
4#
5# NS1(veth11) NS2(veth22)
6# | |
7# | |
8# (veth1, ------ (veth2,
9# id:111) id:222)
10# | xdp forwarding |
11# ------------------
12
13cleanup()
14{
15 if [ "$?" = "0" ]; then
16 echo "selftests: test_xdp_redirect [PASS]";
17 else
18 echo "selftests: test_xdp_redirect [FAILED]";
19 fi
20
21 set +e
22 ip netns del ns1 2> /dev/null
23 ip netns del ns2 2> /dev/null
24}
25
26ip link set dev lo xdpgeneric off 2>/dev/null > /dev/null
27if [ $? -ne 0 ];then
28 echo "selftests: [SKIP] Could not run test without the ip xdpgeneric support"
29 exit 0
30fi
31set -e
32
33ip netns add ns1
34ip netns add ns2
35
36trap cleanup 0 2 3 6 9
37
38ip link add veth1 index 111 type veth peer name veth11
39ip link add veth2 index 222 type veth peer name veth22
40
41ip link set veth11 netns ns1
42ip link set veth22 netns ns2
43
44ip link set veth1 up
45ip link set veth2 up
46
47ip netns exec ns1 ip addr add 10.1.1.11/24 dev veth11
48ip netns exec ns2 ip addr add 10.1.1.22/24 dev veth22
49
50ip netns exec ns1 ip link set dev veth11 up
51ip netns exec ns2 ip link set dev veth22 up
52
53ip link set dev veth1 xdpgeneric obj test_xdp_redirect.o sec redirect_to_222
54ip link set dev veth2 xdpgeneric obj test_xdp_redirect.o sec redirect_to_111
55
56ip netns exec ns1 ping -c 1 10.1.1.22
57ip netns exec ns2 ping -c 1 10.1.1.11
58
59exit 0
diff --git a/tools/testing/selftests/breakpoints/Makefile b/tools/testing/selftests/breakpoints/Makefile
index 6b214b7b10fb..9ec2c78de8ca 100644
--- a/tools/testing/selftests/breakpoints/Makefile
+++ b/tools/testing/selftests/breakpoints/Makefile
@@ -1,15 +1,16 @@
1# SPDX-License-Identifier: GPL-2.0
1# Taken from perf makefile 2# Taken from perf makefile
2uname_M := $(shell uname -m 2>/dev/null || echo not) 3uname_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/) 4ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
4 5
6TEST_GEN_PROGS := step_after_suspend_test
7
5ifeq ($(ARCH),x86) 8ifeq ($(ARCH),x86)
6TEST_GEN_PROGS := breakpoint_test 9TEST_GEN_PROGS += breakpoint_test
7endif 10endif
8ifneq (,$(filter $(ARCH),aarch64 arm64)) 11ifneq (,$(filter $(ARCH),aarch64 arm64))
9TEST_GEN_PROGS := breakpoint_test_arm64 12TEST_GEN_PROGS += breakpoint_test_arm64
10endif 13endif
11 14
12TEST_GEN_PROGS += step_after_suspend_test
13
14include ../lib.mk 15include ../lib.mk
15 16
diff --git a/tools/testing/selftests/breakpoints/breakpoint_test.c b/tools/testing/selftests/breakpoints/breakpoint_test.c
index f63356151ad4..901b85ea6a59 100644
--- a/tools/testing/selftests/breakpoints/breakpoint_test.c
+++ b/tools/testing/selftests/breakpoints/breakpoint_test.c
@@ -367,11 +367,11 @@ static void launch_tests(void)
367 367
368 /* Icebp traps */ 368 /* Icebp traps */
369 ptrace(PTRACE_CONT, child_pid, NULL, 0); 369 ptrace(PTRACE_CONT, child_pid, NULL, 0);
370 check_success("Test icebp"); 370 check_success("Test icebp\n");
371 371
372 /* Int 3 traps */ 372 /* Int 3 traps */
373 ptrace(PTRACE_CONT, child_pid, NULL, 0); 373 ptrace(PTRACE_CONT, child_pid, NULL, 0);
374 check_success("Test int 3 trap"); 374 check_success("Test int 3 trap\n");
375 375
376 ptrace(PTRACE_CONT, child_pid, NULL, 0); 376 ptrace(PTRACE_CONT, child_pid, NULL, 0);
377} 377}
diff --git a/tools/testing/selftests/breakpoints/breakpoint_test_arm64.c b/tools/testing/selftests/breakpoints/breakpoint_test_arm64.c
index 960d02100c26..2d95e5adde72 100644
--- a/tools/testing/selftests/breakpoints/breakpoint_test_arm64.c
+++ b/tools/testing/selftests/breakpoints/breakpoint_test_arm64.c
@@ -19,6 +19,7 @@
19 19
20#define _GNU_SOURCE 20#define _GNU_SOURCE
21 21
22#include <asm/ptrace.h>
22#include <sys/types.h> 23#include <sys/types.h>
23#include <sys/wait.h> 24#include <sys/wait.h>
24#include <sys/ptrace.h> 25#include <sys/ptrace.h>
diff --git a/tools/testing/selftests/capabilities/Makefile b/tools/testing/selftests/capabilities/Makefile
index 29b8adfdac71..6e9d98d457d5 100644
--- a/tools/testing/selftests/capabilities/Makefile
+++ b/tools/testing/selftests/capabilities/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1TEST_GEN_FILES := validate_cap 2TEST_GEN_FILES := validate_cap
2TEST_GEN_PROGS := test_execve 3TEST_GEN_PROGS := test_execve
3 4
diff --git a/tools/testing/selftests/capabilities/test_execve.c b/tools/testing/selftests/capabilities/test_execve.c
index 763f37fecfb8..3ab39a61b95b 100644
--- a/tools/testing/selftests/capabilities/test_execve.c
+++ b/tools/testing/selftests/capabilities/test_execve.c
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2 3
3#include <cap-ng.h> 4#include <cap-ng.h>
4#include <err.h>
5#include <linux/capability.h> 5#include <linux/capability.h>
6#include <stdbool.h> 6#include <stdbool.h>
7#include <string.h> 7#include <string.h>
@@ -18,6 +18,8 @@
18#include <sys/prctl.h> 18#include <sys/prctl.h>
19#include <sys/stat.h> 19#include <sys/stat.h>
20 20
21#include "../kselftest.h"
22
21#ifndef PR_CAP_AMBIENT 23#ifndef PR_CAP_AMBIENT
22#define PR_CAP_AMBIENT 47 24#define PR_CAP_AMBIENT 47
23# define PR_CAP_AMBIENT_IS_SET 1 25# define PR_CAP_AMBIENT_IS_SET 1
@@ -27,6 +29,7 @@
27#endif 29#endif
28 30
29static int nerrs; 31static int nerrs;
32static pid_t mpid; /* main() pid is used to avoid duplicate test counts */
30 33
31static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap) 34static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap)
32{ 35{
@@ -36,29 +39,32 @@ static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list
36 int buf_len; 39 int buf_len;
37 40
38 buf_len = vsnprintf(buf, sizeof(buf), fmt, ap); 41 buf_len = vsnprintf(buf, sizeof(buf), fmt, ap);
39 if (buf_len < 0) { 42 if (buf_len < 0)
40 err(1, "vsnprintf failed"); 43 ksft_exit_fail_msg("vsnprintf failed - %s\n", strerror(errno));
41 } 44
42 if (buf_len >= sizeof(buf)) { 45 if (buf_len >= sizeof(buf))
43 errx(1, "vsnprintf output truncated"); 46 ksft_exit_fail_msg("vsnprintf output truncated\n");
44 } 47
45 48
46 fd = open(filename, O_WRONLY); 49 fd = open(filename, O_WRONLY);
47 if (fd < 0) { 50 if (fd < 0) {
48 if ((errno == ENOENT) && enoent_ok) 51 if ((errno == ENOENT) && enoent_ok)
49 return; 52 return;
50 err(1, "open of %s failed", filename); 53 ksft_exit_fail_msg("open of %s failed - %s\n",
54 filename, strerror(errno));
51 } 55 }
52 written = write(fd, buf, buf_len); 56 written = write(fd, buf, buf_len);
53 if (written != buf_len) { 57 if (written != buf_len) {
54 if (written >= 0) { 58 if (written >= 0) {
55 errx(1, "short write to %s", filename); 59 ksft_exit_fail_msg("short write to %s\n", filename);
56 } else { 60 } else {
57 err(1, "write to %s failed", filename); 61 ksft_exit_fail_msg("write to %s failed - %s\n",
62 filename, strerror(errno));
58 } 63 }
59 } 64 }
60 if (close(fd) != 0) { 65 if (close(fd) != 0) {
61 err(1, "close of %s failed", filename); 66 ksft_exit_fail_msg("close of %s failed - %s\n",
67 filename, strerror(errno));
62 } 68 }
63} 69}
64 70
@@ -95,11 +101,12 @@ static bool create_and_enter_ns(uid_t inner_uid)
95 */ 101 */
96 102
97 if (unshare(CLONE_NEWNS) == 0) { 103 if (unshare(CLONE_NEWNS) == 0) {
98 printf("[NOTE]\tUsing global UIDs for tests\n"); 104 ksft_print_msg("[NOTE]\tUsing global UIDs for tests\n");
99 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) 105 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0)
100 err(1, "PR_SET_KEEPCAPS"); 106 ksft_exit_fail_msg("PR_SET_KEEPCAPS - %s\n",
107 strerror(errno));
101 if (setresuid(inner_uid, inner_uid, -1) != 0) 108 if (setresuid(inner_uid, inner_uid, -1) != 0)
102 err(1, "setresuid"); 109 ksft_exit_fail_msg("setresuid - %s\n", strerror(errno));
103 110
104 // Re-enable effective caps 111 // Re-enable effective caps
105 capng_get_caps_process(); 112 capng_get_caps_process();
@@ -107,22 +114,24 @@ static bool create_and_enter_ns(uid_t inner_uid)
107 if (capng_have_capability(CAPNG_PERMITTED, i)) 114 if (capng_have_capability(CAPNG_PERMITTED, i))
108 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, i); 115 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, i);
109 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 116 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
110 err(1, "capng_apply"); 117 ksft_exit_fail_msg(
118 "capng_apply - %s\n", strerror(errno));
111 119
112 have_outer_privilege = true; 120 have_outer_privilege = true;
113 } else if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == 0) { 121 } else if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == 0) {
114 printf("[NOTE]\tUsing a user namespace for tests\n"); 122 ksft_print_msg("[NOTE]\tUsing a user namespace for tests\n");
115 maybe_write_file("/proc/self/setgroups", "deny"); 123 maybe_write_file("/proc/self/setgroups", "deny");
116 write_file("/proc/self/uid_map", "%d %d 1", inner_uid, outer_uid); 124 write_file("/proc/self/uid_map", "%d %d 1", inner_uid, outer_uid);
117 write_file("/proc/self/gid_map", "0 %d 1", outer_gid); 125 write_file("/proc/self/gid_map", "0 %d 1", outer_gid);
118 126
119 have_outer_privilege = false; 127 have_outer_privilege = false;
120 } else { 128 } else {
121 errx(1, "must be root or be able to create a userns"); 129 ksft_exit_skip("must be root or be able to create a userns\n");
122 } 130 }
123 131
124 if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0) 132 if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0)
125 err(1, "remount everything private"); 133 ksft_exit_fail_msg("remount everything private - %s\n",
134 strerror(errno));
126 135
127 return have_outer_privilege; 136 return have_outer_privilege;
128} 137}
@@ -131,20 +140,22 @@ static void chdir_to_tmpfs(void)
131{ 140{
132 char cwd[PATH_MAX]; 141 char cwd[PATH_MAX];
133 if (getcwd(cwd, sizeof(cwd)) != cwd) 142 if (getcwd(cwd, sizeof(cwd)) != cwd)
134 err(1, "getcwd"); 143 ksft_exit_fail_msg("getcwd - %s\n", strerror(errno));
135 144
136 if (mount("private_tmp", ".", "tmpfs", 0, "mode=0777") != 0) 145 if (mount("private_tmp", ".", "tmpfs", 0, "mode=0777") != 0)
137 err(1, "mount private tmpfs"); 146 ksft_exit_fail_msg("mount private tmpfs - %s\n",
147 strerror(errno));
138 148
139 if (chdir(cwd) != 0) 149 if (chdir(cwd) != 0)
140 err(1, "chdir to private tmpfs"); 150 ksft_exit_fail_msg("chdir to private tmpfs - %s\n",
151 strerror(errno));
141} 152}
142 153
143static void copy_fromat_to(int fromfd, const char *fromname, const char *toname) 154static void copy_fromat_to(int fromfd, const char *fromname, const char *toname)
144{ 155{
145 int from = openat(fromfd, fromname, O_RDONLY); 156 int from = openat(fromfd, fromname, O_RDONLY);
146 if (from == -1) 157 if (from == -1)
147 err(1, "open copy source"); 158 ksft_exit_fail_msg("open copy source - %s\n", strerror(errno));
148 159
149 int to = open(toname, O_CREAT | O_WRONLY | O_EXCL, 0700); 160 int to = open(toname, O_CREAT | O_WRONLY | O_EXCL, 0700);
150 161
@@ -154,10 +165,11 @@ static void copy_fromat_to(int fromfd, const char *fromname, const char *toname)
154 if (sz == 0) 165 if (sz == 0)
155 break; 166 break;
156 if (sz < 0) 167 if (sz < 0)
157 err(1, "read"); 168 ksft_exit_fail_msg("read - %s\n", strerror(errno));
158 169
159 if (write(to, buf, sz) != sz) 170 if (write(to, buf, sz) != sz)
160 err(1, "write"); /* no short writes on tmpfs */ 171 /* no short writes on tmpfs */
172 ksft_exit_fail_msg("write - %s\n", strerror(errno));
161 } 173 }
162 174
163 close(from); 175 close(from);
@@ -174,18 +186,20 @@ static bool fork_wait(void)
174 int status; 186 int status;
175 if (waitpid(child, &status, 0) != child || 187 if (waitpid(child, &status, 0) != child ||
176 !WIFEXITED(status)) { 188 !WIFEXITED(status)) {
177 printf("[FAIL]\tChild died\n"); 189 ksft_print_msg("Child died\n");
178 nerrs++; 190 nerrs++;
179 } else if (WEXITSTATUS(status) != 0) { 191 } else if (WEXITSTATUS(status) != 0) {
180 printf("[FAIL]\tChild failed\n"); 192 ksft_print_msg("Child failed\n");
181 nerrs++; 193 nerrs++;
182 } else { 194 } else {
183 printf("[OK]\tChild succeeded\n"); 195 /* don't print this message for mpid */
196 if (getpid() != mpid)
197 ksft_test_result_pass("Passed\n");
184 } 198 }
185
186 return false; 199 return false;
187 } else { 200 } else {
188 err(1, "fork"); 201 ksft_exit_fail_msg("fork - %s\n", strerror(errno));
202 return false;
189 } 203 }
190} 204}
191 205
@@ -195,7 +209,7 @@ static void exec_other_validate_cap(const char *name,
195 execl(name, name, (eff ? "1" : "0"), 209 execl(name, name, (eff ? "1" : "0"),
196 (perm ? "1" : "0"), (inh ? "1" : "0"), (ambient ? "1" : "0"), 210 (perm ? "1" : "0"), (inh ? "1" : "0"), (ambient ? "1" : "0"),
197 NULL); 211 NULL);
198 err(1, "execl"); 212 ksft_exit_fail_msg("execl - %s\n", strerror(errno));
199} 213}
200 214
201static void exec_validate_cap(bool eff, bool perm, bool inh, bool ambient) 215static void exec_validate_cap(bool eff, bool perm, bool inh, bool ambient)
@@ -209,7 +223,8 @@ static int do_tests(int uid, const char *our_path)
209 223
210 int ourpath_fd = open(our_path, O_RDONLY | O_DIRECTORY); 224 int ourpath_fd = open(our_path, O_RDONLY | O_DIRECTORY);
211 if (ourpath_fd == -1) 225 if (ourpath_fd == -1)
212 err(1, "open '%s'", our_path); 226 ksft_exit_fail_msg("open '%s' - %s\n",
227 our_path, strerror(errno));
213 228
214 chdir_to_tmpfs(); 229 chdir_to_tmpfs();
215 230
@@ -221,30 +236,30 @@ static int do_tests(int uid, const char *our_path)
221 copy_fromat_to(ourpath_fd, "validate_cap", 236 copy_fromat_to(ourpath_fd, "validate_cap",
222 "validate_cap_suidroot"); 237 "validate_cap_suidroot");
223 if (chown("validate_cap_suidroot", 0, -1) != 0) 238 if (chown("validate_cap_suidroot", 0, -1) != 0)
224 err(1, "chown"); 239 ksft_exit_fail_msg("chown - %s\n", strerror(errno));
225 if (chmod("validate_cap_suidroot", S_ISUID | 0700) != 0) 240 if (chmod("validate_cap_suidroot", S_ISUID | 0700) != 0)
226 err(1, "chmod"); 241 ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
227 242
228 copy_fromat_to(ourpath_fd, "validate_cap", 243 copy_fromat_to(ourpath_fd, "validate_cap",
229 "validate_cap_suidnonroot"); 244 "validate_cap_suidnonroot");
230 if (chown("validate_cap_suidnonroot", uid + 1, -1) != 0) 245 if (chown("validate_cap_suidnonroot", uid + 1, -1) != 0)
231 err(1, "chown"); 246 ksft_exit_fail_msg("chown - %s\n", strerror(errno));
232 if (chmod("validate_cap_suidnonroot", S_ISUID | 0700) != 0) 247 if (chmod("validate_cap_suidnonroot", S_ISUID | 0700) != 0)
233 err(1, "chmod"); 248 ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
234 249
235 copy_fromat_to(ourpath_fd, "validate_cap", 250 copy_fromat_to(ourpath_fd, "validate_cap",
236 "validate_cap_sgidroot"); 251 "validate_cap_sgidroot");
237 if (chown("validate_cap_sgidroot", -1, 0) != 0) 252 if (chown("validate_cap_sgidroot", -1, 0) != 0)
238 err(1, "chown"); 253 ksft_exit_fail_msg("chown - %s\n", strerror(errno));
239 if (chmod("validate_cap_sgidroot", S_ISGID | 0710) != 0) 254 if (chmod("validate_cap_sgidroot", S_ISGID | 0710) != 0)
240 err(1, "chmod"); 255 ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
241 256
242 copy_fromat_to(ourpath_fd, "validate_cap", 257 copy_fromat_to(ourpath_fd, "validate_cap",
243 "validate_cap_sgidnonroot"); 258 "validate_cap_sgidnonroot");
244 if (chown("validate_cap_sgidnonroot", -1, gid + 1) != 0) 259 if (chown("validate_cap_sgidnonroot", -1, gid + 1) != 0)
245 err(1, "chown"); 260 ksft_exit_fail_msg("chown - %s\n", strerror(errno));
246 if (chmod("validate_cap_sgidnonroot", S_ISGID | 0710) != 0) 261 if (chmod("validate_cap_sgidnonroot", S_ISGID | 0710) != 0)
247 err(1, "chmod"); 262 ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
248 } 263 }
249 264
250 capng_get_caps_process(); 265 capng_get_caps_process();
@@ -252,147 +267,162 @@ static int do_tests(int uid, const char *our_path)
252 /* Make sure that i starts out clear */ 267 /* Make sure that i starts out clear */
253 capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); 268 capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
254 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 269 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
255 err(1, "capng_apply"); 270 ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
256 271
257 if (uid == 0) { 272 if (uid == 0) {
258 printf("[RUN]\tRoot => ep\n"); 273 ksft_print_msg("[RUN]\tRoot => ep\n");
259 if (fork_wait()) 274 if (fork_wait())
260 exec_validate_cap(true, true, false, false); 275 exec_validate_cap(true, true, false, false);
261 } else { 276 } else {
262 printf("[RUN]\tNon-root => no caps\n"); 277 ksft_print_msg("[RUN]\tNon-root => no caps\n");
263 if (fork_wait()) 278 if (fork_wait())
264 exec_validate_cap(false, false, false, false); 279 exec_validate_cap(false, false, false, false);
265 } 280 }
266 281
267 printf("[OK]\tCheck cap_ambient manipulation rules\n"); 282 ksft_print_msg("Check cap_ambient manipulation rules\n");
268 283
269 /* We should not be able to add ambient caps yet. */ 284 /* We should not be able to add ambient caps yet. */
270 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != -1 || errno != EPERM) { 285 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != -1 || errno != EPERM) {
271 if (errno == EINVAL) 286 if (errno == EINVAL)
272 printf("[FAIL]\tPR_CAP_AMBIENT_RAISE isn't supported\n"); 287 ksft_test_result_fail(
288 "PR_CAP_AMBIENT_RAISE isn't supported\n");
273 else 289 else
274 printf("[FAIL]\tPR_CAP_AMBIENT_RAISE should have failed eith EPERM on a non-inheritable cap\n"); 290 ksft_test_result_fail(
291 "PR_CAP_AMBIENT_RAISE should have failed eith EPERM on a non-inheritable cap\n");
275 return 1; 292 return 1;
276 } 293 }
277 printf("[OK]\tPR_CAP_AMBIENT_RAISE failed on non-inheritable cap\n"); 294 ksft_test_result_pass(
295 "PR_CAP_AMBIENT_RAISE failed on non-inheritable cap\n");
278 296
279 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_RAW); 297 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_RAW);
280 capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_NET_RAW); 298 capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_NET_RAW);
281 capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_NET_RAW); 299 capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_NET_RAW);
282 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 300 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
283 err(1, "capng_apply"); 301 ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
284 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_RAW, 0, 0, 0) != -1 || errno != EPERM) { 302 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_RAW, 0, 0, 0) != -1 || errno != EPERM) {
285 printf("[FAIL]\tPR_CAP_AMBIENT_RAISE should have failed on a non-permitted cap\n"); 303 ksft_test_result_fail(
304 "PR_CAP_AMBIENT_RAISE should have failed on a non-permitted cap\n");
286 return 1; 305 return 1;
287 } 306 }
288 printf("[OK]\tPR_CAP_AMBIENT_RAISE failed on non-permitted cap\n"); 307 ksft_test_result_pass(
308 "PR_CAP_AMBIENT_RAISE failed on non-permitted cap\n");
289 309
290 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); 310 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
291 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 311 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
292 err(1, "capng_apply"); 312 ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
293 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) { 313 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) {
294 printf("[FAIL]\tPR_CAP_AMBIENT_RAISE should have succeeded\n"); 314 ksft_test_result_fail(
315 "PR_CAP_AMBIENT_RAISE should have succeeded\n");
295 return 1; 316 return 1;
296 } 317 }
297 printf("[OK]\tPR_CAP_AMBIENT_RAISE worked\n"); 318 ksft_test_result_pass("PR_CAP_AMBIENT_RAISE worked\n");
298 319
299 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 1) { 320 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 1) {
300 printf("[FAIL]\tPR_CAP_AMBIENT_IS_SET is broken\n"); 321 ksft_test_result_fail("PR_CAP_AMBIENT_IS_SET is broken\n");
301 return 1; 322 return 1;
302 } 323 }
303 324
304 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0, 0) != 0) 325 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0, 0) != 0)
305 err(1, "PR_CAP_AMBIENT_CLEAR_ALL"); 326 ksft_exit_fail_msg("PR_CAP_AMBIENT_CLEAR_ALL - %s\n",
327 strerror(errno));
306 328
307 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) { 329 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) {
308 printf("[FAIL]\tPR_CAP_AMBIENT_CLEAR_ALL didn't work\n"); 330 ksft_test_result_fail(
331 "PR_CAP_AMBIENT_CLEAR_ALL didn't work\n");
309 return 1; 332 return 1;
310 } 333 }
311 334
312 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) 335 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0)
313 err(1, "PR_CAP_AMBIENT_RAISE"); 336 ksft_exit_fail_msg("PR_CAP_AMBIENT_RAISE - %s\n",
337 strerror(errno));
314 338
315 capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); 339 capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
316 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 340 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
317 err(1, "capng_apply"); 341 ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
318 342
319 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) { 343 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) {
320 printf("[FAIL]\tDropping I should have dropped A\n"); 344 ksft_test_result_fail("Dropping I should have dropped A\n");
321 return 1; 345 return 1;
322 } 346 }
323 347
324 printf("[OK]\tBasic manipulation appears to work\n"); 348 ksft_test_result_pass("Basic manipulation appears to work\n");
325 349
326 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); 350 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
327 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 351 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
328 err(1, "capng_apply"); 352 ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
329 if (uid == 0) { 353 if (uid == 0) {
330 printf("[RUN]\tRoot +i => eip\n"); 354 ksft_print_msg("[RUN]\tRoot +i => eip\n");
331 if (fork_wait()) 355 if (fork_wait())
332 exec_validate_cap(true, true, true, false); 356 exec_validate_cap(true, true, true, false);
333 } else { 357 } else {
334 printf("[RUN]\tNon-root +i => i\n"); 358 ksft_print_msg("[RUN]\tNon-root +i => i\n");
335 if (fork_wait()) 359 if (fork_wait())
336 exec_validate_cap(false, false, true, false); 360 exec_validate_cap(false, false, true, false);
337 } 361 }
338 362
339 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) 363 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0)
340 err(1, "PR_CAP_AMBIENT_RAISE"); 364 ksft_exit_fail_msg("PR_CAP_AMBIENT_RAISE - %s\n",
365 strerror(errno));
341 366
342 printf("[RUN]\tUID %d +ia => eipa\n", uid); 367 ksft_print_msg("[RUN]\tUID %d +ia => eipa\n", uid);
343 if (fork_wait()) 368 if (fork_wait())
344 exec_validate_cap(true, true, true, true); 369 exec_validate_cap(true, true, true, true);
345 370
346 /* The remaining tests need real privilege */ 371 /* The remaining tests need real privilege */
347 372
348 if (!have_outer_privilege) { 373 if (!have_outer_privilege) {
349 printf("[SKIP]\tSUID/SGID tests (needs privilege)\n"); 374 ksft_test_result_skip("SUID/SGID tests (needs privilege)\n");
350 goto done; 375 goto done;
351 } 376 }
352 377
353 if (uid == 0) { 378 if (uid == 0) {
354 printf("[RUN]\tRoot +ia, suidroot => eipa\n"); 379 ksft_print_msg("[RUN]\tRoot +ia, suidroot => eipa\n");
355 if (fork_wait()) 380 if (fork_wait())
356 exec_other_validate_cap("./validate_cap_suidroot", 381 exec_other_validate_cap("./validate_cap_suidroot",
357 true, true, true, true); 382 true, true, true, true);
358 383
359 printf("[RUN]\tRoot +ia, suidnonroot => ip\n"); 384 ksft_print_msg("[RUN]\tRoot +ia, suidnonroot => ip\n");
360 if (fork_wait()) 385 if (fork_wait())
361 exec_other_validate_cap("./validate_cap_suidnonroot", 386 exec_other_validate_cap("./validate_cap_suidnonroot",
362 false, true, true, false); 387 false, true, true, false);
363 388
364 printf("[RUN]\tRoot +ia, sgidroot => eipa\n"); 389 ksft_print_msg("[RUN]\tRoot +ia, sgidroot => eipa\n");
365 if (fork_wait()) 390 if (fork_wait())
366 exec_other_validate_cap("./validate_cap_sgidroot", 391 exec_other_validate_cap("./validate_cap_sgidroot",
367 true, true, true, true); 392 true, true, true, true);
368 393
369 if (fork_wait()) { 394 if (fork_wait()) {
370 printf("[RUN]\tRoot, gid != 0, +ia, sgidroot => eip\n"); 395 ksft_print_msg(
396 "[RUN]\tRoot, gid != 0, +ia, sgidroot => eip\n");
371 if (setresgid(1, 1, 1) != 0) 397 if (setresgid(1, 1, 1) != 0)
372 err(1, "setresgid"); 398 ksft_exit_fail_msg("setresgid - %s\n",
399 strerror(errno));
373 exec_other_validate_cap("./validate_cap_sgidroot", 400 exec_other_validate_cap("./validate_cap_sgidroot",
374 true, true, true, false); 401 true, true, true, false);
375 } 402 }
376 403
377 printf("[RUN]\tRoot +ia, sgidnonroot => eip\n"); 404 ksft_print_msg("[RUN]\tRoot +ia, sgidnonroot => eip\n");
378 if (fork_wait()) 405 if (fork_wait())
379 exec_other_validate_cap("./validate_cap_sgidnonroot", 406 exec_other_validate_cap("./validate_cap_sgidnonroot",
380 true, true, true, false); 407 true, true, true, false);
381 } else { 408 } else {
382 printf("[RUN]\tNon-root +ia, sgidnonroot => i\n"); 409 ksft_print_msg("[RUN]\tNon-root +ia, sgidnonroot => i\n");
383 exec_other_validate_cap("./validate_cap_sgidnonroot", 410 if (fork_wait())
411 exec_other_validate_cap("./validate_cap_sgidnonroot",
384 false, false, true, false); 412 false, false, true, false);
385 413
386 if (fork_wait()) { 414 if (fork_wait()) {
387 printf("[RUN]\tNon-root +ia, sgidroot => i\n"); 415 ksft_print_msg("[RUN]\tNon-root +ia, sgidroot => i\n");
388 if (setresgid(1, 1, 1) != 0) 416 if (setresgid(1, 1, 1) != 0)
389 err(1, "setresgid"); 417 ksft_exit_fail_msg("setresgid - %s\n",
418 strerror(errno));
390 exec_other_validate_cap("./validate_cap_sgidroot", 419 exec_other_validate_cap("./validate_cap_sgidroot",
391 false, false, true, false); 420 false, false, true, false);
392 } 421 }
393 } 422 }
394 423
395done: 424done:
425 ksft_print_cnts();
396 return nerrs ? 1 : 0; 426 return nerrs ? 1 : 0;
397} 427}
398 428
@@ -400,23 +430,29 @@ int main(int argc, char **argv)
400{ 430{
401 char *tmp1, *tmp2, *our_path; 431 char *tmp1, *tmp2, *our_path;
402 432
433 ksft_print_header();
434
403 /* Find our path */ 435 /* Find our path */
404 tmp1 = strdup(argv[0]); 436 tmp1 = strdup(argv[0]);
405 if (!tmp1) 437 if (!tmp1)
406 err(1, "strdup"); 438 ksft_exit_fail_msg("strdup - %s\n", strerror(errno));
407 tmp2 = dirname(tmp1); 439 tmp2 = dirname(tmp1);
408 our_path = strdup(tmp2); 440 our_path = strdup(tmp2);
409 if (!our_path) 441 if (!our_path)
410 err(1, "strdup"); 442 ksft_exit_fail_msg("strdup - %s\n", strerror(errno));
411 free(tmp1); 443 free(tmp1);
412 444
445 mpid = getpid();
446
413 if (fork_wait()) { 447 if (fork_wait()) {
414 printf("[RUN]\t+++ Tests with uid == 0 +++\n"); 448 ksft_print_msg("[RUN]\t+++ Tests with uid == 0 +++\n");
415 return do_tests(0, our_path); 449 return do_tests(0, our_path);
416 } 450 }
417 451
452 ksft_print_msg("==================================================\n");
453
418 if (fork_wait()) { 454 if (fork_wait()) {
419 printf("[RUN]\t+++ Tests with uid != 0 +++\n"); 455 ksft_print_msg("[RUN]\t+++ Tests with uid != 0 +++\n");
420 return do_tests(1, our_path); 456 return do_tests(1, our_path);
421 } 457 }
422 458
diff --git a/tools/testing/selftests/capabilities/validate_cap.c b/tools/testing/selftests/capabilities/validate_cap.c
index dd3c45f7b23c..cdfc94268fe6 100644
--- a/tools/testing/selftests/capabilities/validate_cap.c
+++ b/tools/testing/selftests/capabilities/validate_cap.c
@@ -1,5 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <cap-ng.h> 2#include <cap-ng.h>
2#include <err.h>
3#include <linux/capability.h> 3#include <linux/capability.h>
4#include <stdbool.h> 4#include <stdbool.h>
5#include <string.h> 5#include <string.h>
@@ -7,6 +7,8 @@
7#include <sys/prctl.h> 7#include <sys/prctl.h>
8#include <sys/auxv.h> 8#include <sys/auxv.h>
9 9
10#include "../kselftest.h"
11
10#ifndef PR_CAP_AMBIENT 12#ifndef PR_CAP_AMBIENT
11#define PR_CAP_AMBIENT 47 13#define PR_CAP_AMBIENT 47
12# define PR_CAP_AMBIENT_IS_SET 1 14# define PR_CAP_AMBIENT_IS_SET 1
@@ -25,8 +27,10 @@ static bool bool_arg(char **argv, int i)
25 return false; 27 return false;
26 else if (!strcmp(argv[i], "1")) 28 else if (!strcmp(argv[i], "1"))
27 return true; 29 return true;
28 else 30 else {
29 errx(1, "wrong argv[%d]", i); 31 ksft_exit_fail_msg("wrong argv[%d]\n", i);
32 return false;
33 }
30} 34}
31 35
32int main(int argc, char **argv) 36int main(int argc, char **argv)
@@ -39,7 +43,7 @@ int main(int argc, char **argv)
39 */ 43 */
40 44
41 if (argc != 5) 45 if (argc != 5)
42 errx(1, "wrong argc"); 46 ksft_exit_fail_msg("wrong argc\n");
43 47
44#ifdef HAVE_GETAUXVAL 48#ifdef HAVE_GETAUXVAL
45 if (getauxval(AT_SECURE)) 49 if (getauxval(AT_SECURE))
@@ -51,23 +55,26 @@ int main(int argc, char **argv)
51 capng_get_caps_process(); 55 capng_get_caps_process();
52 56
53 if (capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 1)) { 57 if (capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 1)) {
54 printf("[FAIL]\tWrong effective state%s\n", atsec); 58 ksft_print_msg("Wrong effective state%s\n", atsec);
55 return 1; 59 return 1;
56 } 60 }
61
57 if (capng_have_capability(CAPNG_PERMITTED, CAP_NET_BIND_SERVICE) != bool_arg(argv, 2)) { 62 if (capng_have_capability(CAPNG_PERMITTED, CAP_NET_BIND_SERVICE) != bool_arg(argv, 2)) {
58 printf("[FAIL]\tWrong permitted state%s\n", atsec); 63 ksft_print_msg("Wrong permitted state%s\n", atsec);
59 return 1; 64 return 1;
60 } 65 }
66
61 if (capng_have_capability(CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 3)) { 67 if (capng_have_capability(CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 3)) {
62 printf("[FAIL]\tWrong inheritable state%s\n", atsec); 68 ksft_print_msg("Wrong inheritable state%s\n", atsec);
63 return 1; 69 return 1;
64 } 70 }
65 71
66 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != bool_arg(argv, 4)) { 72 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != bool_arg(argv, 4)) {
67 printf("[FAIL]\tWrong ambient state%s\n", atsec); 73 ksft_print_msg("Wrong ambient state%s\n", atsec);
68 return 1; 74 return 1;
69 } 75 }
70 76
71 printf("[OK]\tCapabilities after execve were correct\n"); 77 ksft_print_msg("%s: Capabilities after execve were correct\n",
78 "validate_cap:");
72 return 0; 79 return 0;
73} 80}
diff --git a/tools/testing/selftests/cpu-hotplug/Makefile b/tools/testing/selftests/cpu-hotplug/Makefile
index fe1f99101c5d..d8be047ee5b6 100644
--- a/tools/testing/selftests/cpu-hotplug/Makefile
+++ b/tools/testing/selftests/cpu-hotplug/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1all: 2all:
2 3
3TEST_PROGS := cpu-on-off-test.sh 4TEST_PROGS := cpu-on-off-test.sh
diff --git a/tools/testing/selftests/cpu-hotplug/config b/tools/testing/selftests/cpu-hotplug/config
index e6ab090cfbf3..d4aca2ad5069 100644
--- a/tools/testing/selftests/cpu-hotplug/config
+++ b/tools/testing/selftests/cpu-hotplug/config
@@ -1,2 +1 @@
1CONFIG_NOTIFIER_ERROR_INJECTION=y CONFIG_NOTIFIER_ERROR_INJECTION=y
2CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
diff --git a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
index 98b1d6565f2c..f3a8933c1275 100755
--- a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
+++ b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2 3
3SYSFS= 4SYSFS=
4 5
@@ -28,6 +29,12 @@ prerequisite()
28 echo "CPU online/offline summary:" 29 echo "CPU online/offline summary:"
29 online_cpus=`cat $SYSFS/devices/system/cpu/online` 30 online_cpus=`cat $SYSFS/devices/system/cpu/online`
30 online_max=${online_cpus##*-} 31 online_max=${online_cpus##*-}
32
33 if [[ "$online_cpus" = "$online_max" ]]; then
34 echo "$msg: since there is only one cpu: $online_cpus"
35 exit 0
36 fi
37
31 echo -e "\t Cpus in online state: $online_cpus" 38 echo -e "\t Cpus in online state: $online_cpus"
32 39
33 offline_cpus=`cat $SYSFS/devices/system/cpu/offline` 40 offline_cpus=`cat $SYSFS/devices/system/cpu/offline`
@@ -89,8 +96,10 @@ online_cpu_expect_success()
89 96
90 if ! online_cpu $cpu; then 97 if ! online_cpu $cpu; then
91 echo $FUNCNAME $cpu: unexpected fail >&2 98 echo $FUNCNAME $cpu: unexpected fail >&2
99 exit 1
92 elif ! cpu_is_online $cpu; then 100 elif ! cpu_is_online $cpu; then
93 echo $FUNCNAME $cpu: unexpected offline >&2 101 echo $FUNCNAME $cpu: unexpected offline >&2
102 exit 1
94 fi 103 fi
95} 104}
96 105
@@ -100,8 +109,10 @@ online_cpu_expect_fail()
100 109
101 if online_cpu $cpu 2> /dev/null; then 110 if online_cpu $cpu 2> /dev/null; then
102 echo $FUNCNAME $cpu: unexpected success >&2 111 echo $FUNCNAME $cpu: unexpected success >&2
112 exit 1
103 elif ! cpu_is_offline $cpu; then 113 elif ! cpu_is_offline $cpu; then
104 echo $FUNCNAME $cpu: unexpected online >&2 114 echo $FUNCNAME $cpu: unexpected online >&2
115 exit 1
105 fi 116 fi
106} 117}
107 118
@@ -111,8 +122,10 @@ offline_cpu_expect_success()
111 122
112 if ! offline_cpu $cpu; then 123 if ! offline_cpu $cpu; then
113 echo $FUNCNAME $cpu: unexpected fail >&2 124 echo $FUNCNAME $cpu: unexpected fail >&2
125 exit 1
114 elif ! cpu_is_offline $cpu; then 126 elif ! cpu_is_offline $cpu; then
115 echo $FUNCNAME $cpu: unexpected offline >&2 127 echo $FUNCNAME $cpu: unexpected offline >&2
128 exit 1
116 fi 129 fi
117} 130}
118 131
@@ -122,8 +135,10 @@ offline_cpu_expect_fail()
122 135
123 if offline_cpu $cpu 2> /dev/null; then 136 if offline_cpu $cpu 2> /dev/null; then
124 echo $FUNCNAME $cpu: unexpected success >&2 137 echo $FUNCNAME $cpu: unexpected success >&2
138 exit 1
125 elif ! cpu_is_online $cpu; then 139 elif ! cpu_is_online $cpu; then
126 echo $FUNCNAME $cpu: unexpected offline >&2 140 echo $FUNCNAME $cpu: unexpected offline >&2
141 exit 1
127 fi 142 fi
128} 143}
129 144
diff --git a/tools/testing/selftests/cpufreq/Makefile b/tools/testing/selftests/cpufreq/Makefile
index 3955cd96f3a2..c86ca8342222 100644
--- a/tools/testing/selftests/cpufreq/Makefile
+++ b/tools/testing/selftests/cpufreq/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1all: 2all:
2 3
3TEST_PROGS := main.sh 4TEST_PROGS := main.sh
diff --git a/tools/testing/selftests/cpufreq/cpu.sh b/tools/testing/selftests/cpufreq/cpu.sh
index 8e08a83d65f2..39fdcdfb8e97 100755
--- a/tools/testing/selftests/cpufreq/cpu.sh
+++ b/tools/testing/selftests/cpufreq/cpu.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2# 3#
3# CPU helpers 4# CPU helpers
4 5
diff --git a/tools/testing/selftests/cpufreq/cpufreq.sh b/tools/testing/selftests/cpufreq/cpufreq.sh
index 1ed3832030b4..b583a2fb4504 100755
--- a/tools/testing/selftests/cpufreq/cpufreq.sh
+++ b/tools/testing/selftests/cpufreq/cpufreq.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2 3
3# protect against multiple inclusion 4# protect against multiple inclusion
4if [ $FILE_CPUFREQ ]; then 5if [ $FILE_CPUFREQ ]; then
diff --git a/tools/testing/selftests/cpufreq/governor.sh b/tools/testing/selftests/cpufreq/governor.sh
index def645103555..fe37df79c087 100755
--- a/tools/testing/selftests/cpufreq/governor.sh
+++ b/tools/testing/selftests/cpufreq/governor.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2# 3#
3# Test governors 4# Test governors
4 5
diff --git a/tools/testing/selftests/cpufreq/main.sh b/tools/testing/selftests/cpufreq/main.sh
index 01bac76ac0ec..d83922de9d89 100755
--- a/tools/testing/selftests/cpufreq/main.sh
+++ b/tools/testing/selftests/cpufreq/main.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2 3
3source cpu.sh 4source cpu.sh
4source cpufreq.sh 5source cpufreq.sh
diff --git a/tools/testing/selftests/cpufreq/module.sh b/tools/testing/selftests/cpufreq/module.sh
index 8ff2244a33a1..22563cd122e7 100755
--- a/tools/testing/selftests/cpufreq/module.sh
+++ b/tools/testing/selftests/cpufreq/module.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2# 3#
3# Modules specific tests cases 4# Modules specific tests cases
4 5
diff --git a/tools/testing/selftests/cpufreq/special-tests.sh b/tools/testing/selftests/cpufreq/special-tests.sh
index 58b730f23ef7..8d40505dc468 100755
--- a/tools/testing/selftests/cpufreq/special-tests.sh
+++ b/tools/testing/selftests/cpufreq/special-tests.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2# 3#
3# Special test cases reported by people 4# Special test cases reported by people
4 5
diff --git a/tools/testing/selftests/drivers/gpu/drm_mm.sh b/tools/testing/selftests/drivers/gpu/drm_mm.sh
index 96dd55c92799..b789dc8257e6 100755
--- a/tools/testing/selftests/drivers/gpu/drm_mm.sh
+++ b/tools/testing/selftests/drivers/gpu/drm_mm.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# Runs API tests for struct drm_mm (DRM range manager) 3# Runs API tests for struct drm_mm (DRM range manager)
3 4
4if ! /sbin/modprobe -n -q test-drm_mm; then 5if ! /sbin/modprobe -n -q test-drm_mm; then
diff --git a/tools/testing/selftests/drivers/gpu/i915.sh b/tools/testing/selftests/drivers/gpu/i915.sh
index c06d6e8a8dcc..d3895bc714b7 100755
--- a/tools/testing/selftests/drivers/gpu/i915.sh
+++ b/tools/testing/selftests/drivers/gpu/i915.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# Runs hardware independent tests for i915 (drivers/gpu/drm/i915) 3# Runs hardware independent tests for i915 (drivers/gpu/drm/i915)
3 4
4if ! /sbin/modprobe -q -r i915; then 5if ! /sbin/modprobe -q -r i915; then
diff --git a/tools/testing/selftests/efivarfs/create-read.c b/tools/testing/selftests/efivarfs/create-read.c
index 7feef1880968..9674a19396a3 100644
--- a/tools/testing/selftests/efivarfs/create-read.c
+++ b/tools/testing/selftests/efivarfs/create-read.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <stdint.h> 3#include <stdint.h>
3#include <stdlib.h> 4#include <stdlib.h>
diff --git a/tools/testing/selftests/efivarfs/efivarfs.sh b/tools/testing/selftests/efivarfs/efivarfs.sh
index 057278448515..c6d5790575ae 100755
--- a/tools/testing/selftests/efivarfs/efivarfs.sh
+++ b/tools/testing/selftests/efivarfs/efivarfs.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2 3
3efivarfs_mount=/sys/firmware/efi/efivars 4efivarfs_mount=/sys/firmware/efi/efivars
4test_guid=210be57c-9849-4fc7-a635-e6382d1aec27 5test_guid=210be57c-9849-4fc7-a635-e6382d1aec27
diff --git a/tools/testing/selftests/efivarfs/open-unlink.c b/tools/testing/selftests/efivarfs/open-unlink.c
index 4af74f733036..562742d44ac9 100644
--- a/tools/testing/selftests/efivarfs/open-unlink.c
+++ b/tools/testing/selftests/efivarfs/open-unlink.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <errno.h> 2#include <errno.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <stdint.h> 4#include <stdint.h>
diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftests/exec/Makefile
index 2e13035dff7f..427c41ba5151 100644
--- a/tools/testing/selftests/exec/Makefile
+++ b/tools/testing/selftests/exec/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1CFLAGS = -Wall 2CFLAGS = -Wall
2 3
3TEST_GEN_PROGS := execveat 4TEST_GEN_PROGS := execveat
diff --git a/tools/testing/selftests/exec/execveat.c b/tools/testing/selftests/exec/execveat.c
index 8d5d1d2ee7c1..67cd4597db2b 100644
--- a/tools/testing/selftests/exec/execveat.c
+++ b/tools/testing/selftests/exec/execveat.c
@@ -147,7 +147,7 @@ static void exe_cp(const char *src, const char *dest)
147} 147}
148 148
149#define XX_DIR_LEN 200 149#define XX_DIR_LEN 200
150static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script) 150static int check_execveat_pathmax(int root_dfd, const char *src, int is_script)
151{ 151{
152 int fail = 0; 152 int fail = 0;
153 int ii, count, len; 153 int ii, count, len;
@@ -156,20 +156,30 @@ static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script)
156 156
157 if (*longpath == '\0') { 157 if (*longpath == '\0') {
158 /* Create a filename close to PATH_MAX in length */ 158 /* Create a filename close to PATH_MAX in length */
159 char *cwd = getcwd(NULL, 0);
160
161 if (!cwd) {
162 printf("Failed to getcwd(), errno=%d (%s)\n",
163 errno, strerror(errno));
164 return 2;
165 }
166 strcpy(longpath, cwd);
167 strcat(longpath, "/");
159 memset(longname, 'x', XX_DIR_LEN - 1); 168 memset(longname, 'x', XX_DIR_LEN - 1);
160 longname[XX_DIR_LEN - 1] = '/'; 169 longname[XX_DIR_LEN - 1] = '/';
161 longname[XX_DIR_LEN] = '\0'; 170 longname[XX_DIR_LEN] = '\0';
162 count = (PATH_MAX - 3) / XX_DIR_LEN; 171 count = (PATH_MAX - 3 - strlen(cwd)) / XX_DIR_LEN;
163 for (ii = 0; ii < count; ii++) { 172 for (ii = 0; ii < count; ii++) {
164 strcat(longpath, longname); 173 strcat(longpath, longname);
165 mkdir(longpath, 0755); 174 mkdir(longpath, 0755);
166 } 175 }
167 len = (PATH_MAX - 3) - (count * XX_DIR_LEN); 176 len = (PATH_MAX - 3 - strlen(cwd)) - (count * XX_DIR_LEN);
168 if (len <= 0) 177 if (len <= 0)
169 len = 1; 178 len = 1;
170 memset(longname, 'y', len); 179 memset(longname, 'y', len);
171 longname[len] = '\0'; 180 longname[len] = '\0';
172 strcat(longpath, longname); 181 strcat(longpath, longname);
182 free(cwd);
173 } 183 }
174 exe_cp(src, longpath); 184 exe_cp(src, longpath);
175 185
@@ -190,7 +200,7 @@ static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script)
190 } 200 }
191 201
192 /* 202 /*
193 * Execute as a long pathname relative to ".". If this is a script, 203 * Execute as a long pathname relative to "/". If this is a script,
194 * the interpreter will launch but fail to open the script because its 204 * the interpreter will launch but fail to open the script because its
195 * name ("/dev/fd/5/xxx....") is bigger than PATH_MAX. 205 * name ("/dev/fd/5/xxx....") is bigger than PATH_MAX.
196 * 206 *
@@ -200,10 +210,10 @@ static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script)
200 * the exit status shall be 126."), so allow either. 210 * the exit status shall be 126."), so allow either.
201 */ 211 */
202 if (is_script) 212 if (is_script)
203 fail += check_execveat_invoked_rc(dot_dfd, longpath, 0, 213 fail += check_execveat_invoked_rc(root_dfd, longpath + 1, 0,
204 127, 126); 214 127, 126);
205 else 215 else
206 fail += check_execveat(dot_dfd, longpath, 0); 216 fail += check_execveat(root_dfd, longpath + 1, 0);
207 217
208 return fail; 218 return fail;
209} 219}
@@ -218,6 +228,7 @@ static int run_tests(void)
218 int subdir_dfd_ephemeral = open_or_die("subdir.ephemeral", 228 int subdir_dfd_ephemeral = open_or_die("subdir.ephemeral",
219 O_DIRECTORY|O_RDONLY); 229 O_DIRECTORY|O_RDONLY);
220 int dot_dfd = open_or_die(".", O_DIRECTORY|O_RDONLY); 230 int dot_dfd = open_or_die(".", O_DIRECTORY|O_RDONLY);
231 int root_dfd = open_or_die("/", O_DIRECTORY|O_RDONLY);
221 int dot_dfd_path = open_or_die(".", O_DIRECTORY|O_RDONLY|O_PATH); 232 int dot_dfd_path = open_or_die(".", O_DIRECTORY|O_RDONLY|O_PATH);
222 int dot_dfd_cloexec = open_or_die(".", O_DIRECTORY|O_RDONLY|O_CLOEXEC); 233 int dot_dfd_cloexec = open_or_die(".", O_DIRECTORY|O_RDONLY|O_CLOEXEC);
223 int fd = open_or_die("execveat", O_RDONLY); 234 int fd = open_or_die("execveat", O_RDONLY);
@@ -353,8 +364,8 @@ static int run_tests(void)
353 /* Attempt to execute relative to non-directory => ENOTDIR */ 364 /* Attempt to execute relative to non-directory => ENOTDIR */
354 fail += check_execveat_fail(fd, "execveat", 0, ENOTDIR); 365 fail += check_execveat_fail(fd, "execveat", 0, ENOTDIR);
355 366
356 fail += check_execveat_pathmax(dot_dfd, "execveat", 0); 367 fail += check_execveat_pathmax(root_dfd, "execveat", 0);
357 fail += check_execveat_pathmax(dot_dfd, "script", 1); 368 fail += check_execveat_pathmax(root_dfd, "script", 1);
358 return fail; 369 return fail;
359} 370}
360 371
diff --git a/tools/testing/selftests/filesystems/Makefile b/tools/testing/selftests/filesystems/Makefile
index 0ab11307b414..13a73bf725b5 100644
--- a/tools/testing/selftests/filesystems/Makefile
+++ b/tools/testing/selftests/filesystems/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1TEST_PROGS := dnotify_test 2TEST_PROGS := dnotify_test
2all: $(TEST_PROGS) 3all: $(TEST_PROGS)
3 4
diff --git a/tools/testing/selftests/filesystems/dnotify_test.c b/tools/testing/selftests/filesystems/dnotify_test.c
index 8b37b4a1e18d..c0a9b2d3302d 100644
--- a/tools/testing/selftests/filesystems/dnotify_test.c
+++ b/tools/testing/selftests/filesystems/dnotify_test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE /* needed to get the defines */ 2#define _GNU_SOURCE /* needed to get the defines */
2#include <fcntl.h> /* in glibc 2.2 this has the needed 3#include <fcntl.h> /* in glibc 2.2 this has the needed
3 values defined */ 4 values defined */
diff --git a/tools/testing/selftests/firmware/fw_fallback.sh b/tools/testing/selftests/firmware/fw_fallback.sh
index 2e4c22d5abf7..34a42c68ebfb 100755
--- a/tools/testing/selftests/firmware/fw_fallback.sh
+++ b/tools/testing/selftests/firmware/fw_fallback.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# This validates that the kernel will fall back to using the fallback mechanism 3# This validates that the kernel will fall back to using the fallback mechanism
3# to load firmware it can't find on disk itself. We must request a firmware 4# to load firmware it can't find on disk itself. We must request a firmware
4# that the kernel won't find, and any installed helper (e.g. udev) also 5# that the kernel won't find, and any installed helper (e.g. udev) also
@@ -85,6 +86,11 @@ load_fw_cancel()
85 86
86load_fw_custom() 87load_fw_custom()
87{ 88{
89 if [ ! -e "$DIR"/trigger_custom_fallback ]; then
90 echo "$0: custom fallback trigger not present, ignoring test" >&2
91 return 1
92 fi
93
88 local name="$1" 94 local name="$1"
89 local file="$2" 95 local file="$2"
90 96
@@ -107,11 +113,17 @@ load_fw_custom()
107 113
108 # Wait for request to finish. 114 # Wait for request to finish.
109 wait 115 wait
116 return 0
110} 117}
111 118
112 119
113load_fw_custom_cancel() 120load_fw_custom_cancel()
114{ 121{
122 if [ ! -e "$DIR"/trigger_custom_fallback ]; then
123 echo "$0: canceling custom fallback trigger not present, ignoring test" >&2
124 return 1
125 fi
126
115 local name="$1" 127 local name="$1"
116 local file="$2" 128 local file="$2"
117 129
@@ -132,8 +144,30 @@ load_fw_custom_cancel()
132 144
133 # Wait for request to finish. 145 # Wait for request to finish.
134 wait 146 wait
147 return 0
135} 148}
136 149
150load_fw_fallback_with_child()
151{
152 local name="$1"
153 local file="$2"
154
155 # This is the value already set but we want to be explicit
156 echo 4 >/sys/class/firmware/timeout
157
158 sleep 1 &
159 SECONDS_BEFORE=$(date +%s)
160 echo -n "$name" >"$DIR"/trigger_request 2>/dev/null
161 SECONDS_AFTER=$(date +%s)
162 SECONDS_DELTA=$(($SECONDS_AFTER - $SECONDS_BEFORE))
163 if [ "$SECONDS_DELTA" -lt 4 ]; then
164 RET=1
165 else
166 RET=0
167 fi
168 wait
169 return $RET
170}
137 171
138trap "test_finish" EXIT 172trap "test_finish" EXIT
139 173
@@ -205,20 +239,32 @@ else
205 echo "$0: cancelling fallback mechanism works" 239 echo "$0: cancelling fallback mechanism works"
206fi 240fi
207 241
208load_fw_custom "$NAME" "$FW" 242if load_fw_custom "$NAME" "$FW" ; then
209if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then 243 if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
210 echo "$0: firmware was not loaded" >&2 244 echo "$0: firmware was not loaded" >&2
211 exit 1 245 exit 1
212else 246 else
213 echo "$0: custom fallback loading mechanism works" 247 echo "$0: custom fallback loading mechanism works"
248 fi
214fi 249fi
215 250
216load_fw_custom_cancel "nope-$NAME" "$FW" 251if load_fw_custom_cancel "nope-$NAME" "$FW" ; then
217if diff -q "$FW" /dev/test_firmware >/dev/null ; then 252 if diff -q "$FW" /dev/test_firmware >/dev/null ; then
218 echo "$0: firmware was expected to be cancelled" >&2 253 echo "$0: firmware was expected to be cancelled" >&2
219 exit 1 254 exit 1
255 else
256 echo "$0: cancelling custom fallback mechanism works"
257 fi
258fi
259
260set +e
261load_fw_fallback_with_child "nope-signal-$NAME" "$FW"
262if [ "$?" -eq 0 ]; then
263 echo "$0: SIGCHLD on sync ignored as expected" >&2
220else 264else
221 echo "$0: cancelling custom fallback mechanism works" 265 echo "$0: error - sync firmware request cancelled due to SIGCHLD" >&2
266 exit 1
222fi 267fi
268set -e
223 269
224exit 0 270exit 0
diff --git a/tools/testing/selftests/firmware/fw_filesystem.sh b/tools/testing/selftests/firmware/fw_filesystem.sh
index e35691239350..b1f20fef36c7 100755
--- a/tools/testing/selftests/firmware/fw_filesystem.sh
+++ b/tools/testing/selftests/firmware/fw_filesystem.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# This validates that the kernel will load firmware out of its list of 3# This validates that the kernel will load firmware out of its list of
3# firmware locations on disk. Since the user helper does similar work, 4# firmware locations on disk. Since the user helper does similar work,
4# we reset the custom load directory to a location the user helper doesn't 5# we reset the custom load directory to a location the user helper doesn't
@@ -25,8 +26,9 @@ if [ ! -d $DIR ]; then
25fi 26fi
26 27
27# CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/ 28# CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/
28# These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that 29# These days most distros enable CONFIG_FW_LOADER_USER_HELPER but disable
29# as an indicator for CONFIG_FW_LOADER_USER_HELPER. 30# CONFIG_FW_LOADER_USER_HELPER_FALLBACK. We use /sys/class/firmware/ as an
31# indicator for CONFIG_FW_LOADER_USER_HELPER.
30HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi) 32HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
31 33
32if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then 34if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
@@ -68,9 +70,13 @@ if printf '\000' >"$DIR"/trigger_request 2> /dev/null; then
68 exit 1 70 exit 1
69fi 71fi
70 72
71if printf '\000' >"$DIR"/trigger_async_request 2> /dev/null; then 73if [ ! -e "$DIR"/trigger_async_request ]; then
72 echo "$0: empty filename should not succeed (async)" >&2 74 echo "$0: empty filename: async trigger not present, ignoring test" >&2
73 exit 1 75else
76 if printf '\000' >"$DIR"/trigger_async_request 2> /dev/null; then
77 echo "$0: empty filename should not succeed (async)" >&2
78 exit 1
79 fi
74fi 80fi
75 81
76# Request a firmware that doesn't exist, it should fail. 82# Request a firmware that doesn't exist, it should fail.
@@ -103,17 +109,257 @@ else
103fi 109fi
104 110
105# Try the asynchronous version too 111# Try the asynchronous version too
106if ! echo -n "$NAME" >"$DIR"/trigger_async_request ; then 112if [ ! -e "$DIR"/trigger_async_request ]; then
107 echo "$0: could not trigger async request" >&2 113 echo "$0: firmware loading: async trigger not present, ignoring test" >&2
108 exit 1
109fi
110
111# Verify the contents are what we expect.
112if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
113 echo "$0: firmware was not loaded (async)" >&2
114 exit 1
115else 114else
116 echo "$0: async filesystem loading works" 115 if ! echo -n "$NAME" >"$DIR"/trigger_async_request ; then
116 echo "$0: could not trigger async request" >&2
117 exit 1
118 fi
119
120 # Verify the contents are what we expect.
121 if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
122 echo "$0: firmware was not loaded (async)" >&2
123 exit 1
124 else
125 echo "$0: async filesystem loading works"
126 fi
117fi 127fi
118 128
129### Batched requests tests
130test_config_present()
131{
132 if [ ! -f $DIR/reset ]; then
133 echo "Configuration triggers not present, ignoring test"
134 exit 0
135 fi
136}
137
138# Defaults :
139#
140# send_uevent: 1
141# sync_direct: 0
142# name: test-firmware.bin
143# num_requests: 4
144config_reset()
145{
146 echo 1 > $DIR/reset
147}
148
149release_all_firmware()
150{
151 echo 1 > $DIR/release_all_firmware
152}
153
154config_set_name()
155{
156 echo -n $1 > $DIR/config_name
157}
158
159config_set_sync_direct()
160{
161 echo 1 > $DIR/config_sync_direct
162}
163
164config_unset_sync_direct()
165{
166 echo 0 > $DIR/config_sync_direct
167}
168
169config_set_uevent()
170{
171 echo 1 > $DIR/config_send_uevent
172}
173
174config_unset_uevent()
175{
176 echo 0 > $DIR/config_send_uevent
177}
178
179config_trigger_sync()
180{
181 echo -n 1 > $DIR/trigger_batched_requests 2>/dev/null
182}
183
184config_trigger_async()
185{
186 echo -n 1 > $DIR/trigger_batched_requests_async 2> /dev/null
187}
188
189config_set_read_fw_idx()
190{
191 echo -n $1 > $DIR/config_read_fw_idx 2> /dev/null
192}
193
194read_firmwares()
195{
196 for i in $(seq 0 3); do
197 config_set_read_fw_idx $i
198 # Verify the contents are what we expect.
199 # -Z required for now -- check for yourself, md5sum
200 # on $FW and DIR/read_firmware will yield the same. Even
201 # cmp agrees, so something is off.
202 if ! diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
203 echo "request #$i: firmware was not loaded" >&2
204 exit 1
205 fi
206 done
207}
208
209read_firmwares_expect_nofile()
210{
211 for i in $(seq 0 3); do
212 config_set_read_fw_idx $i
213 # Ensures contents differ
214 if diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
215 echo "request $i: file was not expected to match" >&2
216 exit 1
217 fi
218 done
219}
220
221test_batched_request_firmware_nofile()
222{
223 echo -n "Batched request_firmware() nofile try #$1: "
224 config_reset
225 config_set_name nope-test-firmware.bin
226 config_trigger_sync
227 read_firmwares_expect_nofile
228 release_all_firmware
229 echo "OK"
230}
231
232test_batched_request_firmware_direct_nofile()
233{
234 echo -n "Batched request_firmware_direct() nofile try #$1: "
235 config_reset
236 config_set_name nope-test-firmware.bin
237 config_set_sync_direct
238 config_trigger_sync
239 release_all_firmware
240 echo "OK"
241}
242
243test_request_firmware_nowait_uevent_nofile()
244{
245 echo -n "Batched request_firmware_nowait(uevent=true) nofile try #$1: "
246 config_reset
247 config_set_name nope-test-firmware.bin
248 config_trigger_async
249 release_all_firmware
250 echo "OK"
251}
252
253test_wait_and_cancel_custom_load()
254{
255 if [ "$HAS_FW_LOADER_USER_HELPER" != "yes" ]; then
256 return
257 fi
258 local timeout=10
259 name=$1
260 while [ ! -e "$DIR"/"$name"/loading ]; do
261 sleep 0.1
262 timeout=$(( $timeout - 1 ))
263 if [ "$timeout" -eq 0 ]; then
264 echo "firmware interface never appeared:" >&2
265 echo "$DIR/$name/loading" >&2
266 exit 1
267 fi
268 done
269 echo -1 >"$DIR"/"$name"/loading
270}
271
272test_request_firmware_nowait_custom_nofile()
273{
274 echo -n "Batched request_firmware_nowait(uevent=false) nofile try #$1: "
275 config_unset_uevent
276 config_set_name nope-test-firmware.bin
277 config_trigger_async &
278 test_wait_and_cancel_custom_load nope-test-firmware.bin
279 wait
280 release_all_firmware
281 echo "OK"
282}
283
284test_batched_request_firmware()
285{
286 echo -n "Batched request_firmware() try #$1: "
287 config_reset
288 config_trigger_sync
289 read_firmwares
290 release_all_firmware
291 echo "OK"
292}
293
294test_batched_request_firmware_direct()
295{
296 echo -n "Batched request_firmware_direct() try #$1: "
297 config_reset
298 config_set_sync_direct
299 config_trigger_sync
300 release_all_firmware
301 echo "OK"
302}
303
304test_request_firmware_nowait_uevent()
305{
306 echo -n "Batched request_firmware_nowait(uevent=true) try #$1: "
307 config_reset
308 config_trigger_async
309 release_all_firmware
310 echo "OK"
311}
312
313test_request_firmware_nowait_custom()
314{
315 echo -n "Batched request_firmware_nowait(uevent=false) try #$1: "
316 config_unset_uevent
317 config_trigger_async
318 release_all_firmware
319 echo "OK"
320}
321
322# Only continue if batched request triggers are present on the
323# test-firmware driver
324test_config_present
325
326# test with the file present
327echo
328echo "Testing with the file present..."
329for i in $(seq 1 5); do
330 test_batched_request_firmware $i
331done
332
333for i in $(seq 1 5); do
334 test_batched_request_firmware_direct $i
335done
336
337for i in $(seq 1 5); do
338 test_request_firmware_nowait_uevent $i
339done
340
341for i in $(seq 1 5); do
342 test_request_firmware_nowait_custom $i
343done
344
345# Test for file not found, errors are expected, the failure would be
346# a hung task, which would require a hard reset.
347echo
348echo "Testing with the file missing..."
349for i in $(seq 1 5); do
350 test_batched_request_firmware_nofile $i
351done
352
353for i in $(seq 1 5); do
354 test_batched_request_firmware_direct_nofile $i
355done
356
357for i in $(seq 1 5); do
358 test_request_firmware_nowait_uevent_nofile $i
359done
360
361for i in $(seq 1 5); do
362 test_request_firmware_nowait_custom_nofile $i
363done
364
119exit 0 365exit 0
diff --git a/tools/testing/selftests/ftrace/Makefile b/tools/testing/selftests/ftrace/Makefile
index a8a5e21850e7..cd1f5b3a7774 100644
--- a/tools/testing/selftests/ftrace/Makefile
+++ b/tools/testing/selftests/ftrace/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1all: 2all:
2 3
3TEST_PROGS := ftracetest 4TEST_PROGS := ftracetest
diff --git a/tools/testing/selftests/ftrace/config b/tools/testing/selftests/ftrace/config
index 8a1c9f949fe0..b01924c71c09 100644
--- a/tools/testing/selftests/ftrace/config
+++ b/tools/testing/selftests/ftrace/config
@@ -1,2 +1,6 @@
1CONFIG_KPROBES=y 1CONFIG_KPROBES=y
2CONFIG_FTRACE=y 2CONFIG_FTRACE=y
3CONFIG_FUNCTION_PROFILER=y
4CONFIG_TRACER_SNAPSHOT=y
5CONFIG_STACK_TRACER=y
6CONFIG_HIST_TRIGGERS=y
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index 14a03ea1e21d..f9a9d424c980 100755
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -8,15 +8,18 @@
8# Released under the terms of the GPL v2. 8# Released under the terms of the GPL v2.
9 9
10usage() { # errno [message] 10usage() { # errno [message]
11[ "$2" ] && echo $2 11[ ! -z "$2" ] && echo $2
12echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]" 12echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]"
13echo " Options:" 13echo " Options:"
14echo " -h|--help Show help message" 14echo " -h|--help Show help message"
15echo " -k|--keep Keep passed test logs" 15echo " -k|--keep Keep passed test logs"
16echo " -v|--verbose Increase verbosity of test messages" 16echo " -v|--verbose Increase verbosity of test messages"
17echo " -vv Alias of -v -v (Show all results in stdout)" 17echo " -vv Alias of -v -v (Show all results in stdout)"
18echo " -vvv Alias of -v -v -v (Show all commands immediately)"
19echo " --fail-unsupported Treat UNSUPPORTED as a failure"
18echo " -d|--debug Debug mode (trace all shell commands)" 20echo " -d|--debug Debug mode (trace all shell commands)"
19echo " -l|--logdir <dir> Save logs on the <dir>" 21echo " -l|--logdir <dir> Save logs on the <dir>"
22echo " If <dir> is -, all logs output in console only"
20exit $1 23exit $1
21} 24}
22 25
@@ -47,7 +50,7 @@ parse_opts() { # opts
47 local OPT_TEST_CASES= 50 local OPT_TEST_CASES=
48 local OPT_TEST_DIR= 51 local OPT_TEST_DIR=
49 52
50 while [ "$1" ]; do 53 while [ ! -z "$1" ]; do
51 case "$1" in 54 case "$1" in
52 --help|-h) 55 --help|-h)
53 usage 0 56 usage 0
@@ -56,15 +59,20 @@ parse_opts() { # opts
56 KEEP_LOG=1 59 KEEP_LOG=1
57 shift 1 60 shift 1
58 ;; 61 ;;
59 --verbose|-v|-vv) 62 --verbose|-v|-vv|-vvv)
60 VERBOSE=$((VERBOSE + 1)) 63 VERBOSE=$((VERBOSE + 1))
61 [ $1 = '-vv' ] && VERBOSE=$((VERBOSE + 1)) 64 [ $1 = '-vv' ] && VERBOSE=$((VERBOSE + 1))
65 [ $1 = '-vvv' ] && VERBOSE=$((VERBOSE + 2))
62 shift 1 66 shift 1
63 ;; 67 ;;
64 --debug|-d) 68 --debug|-d)
65 DEBUG=1 69 DEBUG=1
66 shift 1 70 shift 1
67 ;; 71 ;;
72 --fail-unsupported)
73 UNSUPPORTED_RESULT=1
74 shift 1
75 ;;
68 --logdir|-l) 76 --logdir|-l)
69 LOG_DIR=$2 77 LOG_DIR=$2
70 shift 2 78 shift 2
@@ -88,7 +96,7 @@ parse_opts() { # opts
88 ;; 96 ;;
89 esac 97 esac
90 done 98 done
91 if [ "$OPT_TEST_CASES" ]; then 99 if [ ! -z "$OPT_TEST_CASES" ]; then
92 TEST_CASES=$OPT_TEST_CASES 100 TEST_CASES=$OPT_TEST_CASES
93 fi 101 fi
94} 102}
@@ -108,6 +116,7 @@ LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/
108KEEP_LOG=0 116KEEP_LOG=0
109DEBUG=0 117DEBUG=0
110VERBOSE=0 118VERBOSE=0
119UNSUPPORTED_RESULT=0
111# Parse command-line options 120# Parse command-line options
112parse_opts $* 121parse_opts $*
113 122
@@ -119,14 +128,20 @@ if [ -z "$TRACING_DIR" -o ! -d "$TRACING_DIR" ]; then
119fi 128fi
120 129
121# Preparing logs 130# Preparing logs
122LOG_FILE=$LOG_DIR/ftracetest.log 131if [ "x$LOG_DIR" = "x-" ]; then
123mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR" 132 LOG_FILE=
124date > $LOG_FILE 133 date
134else
135 LOG_FILE=$LOG_DIR/ftracetest.log
136 mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR"
137 date > $LOG_FILE
138fi
139
125prlog() { # messages 140prlog() { # messages
126 echo "$@" | tee -a $LOG_FILE 141 [ -z "$LOG_FILE" ] && echo "$@" || echo "$@" | tee -a $LOG_FILE
127} 142}
128catlog() { #file 143catlog() { #file
129 cat $1 | tee -a $LOG_FILE 144 [ -z "$LOG_FILE" ] && cat $1 || cat $1 | tee -a $LOG_FILE
130} 145}
131prlog "=== Ftrace unit tests ===" 146prlog "=== Ftrace unit tests ==="
132 147
@@ -187,7 +202,7 @@ eval_result() { # sigval
187 $UNSUPPORTED) 202 $UNSUPPORTED)
188 prlog " [UNSUPPORTED]" 203 prlog " [UNSUPPORTED]"
189 UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO" 204 UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO"
190 return 1 # this is not a bug, but the result should be reported. 205 return $UNSUPPORTED_RESULT # depends on use case
191 ;; 206 ;;
192 $XFAIL) 207 $XFAIL)
193 prlog " [XFAIL]" 208 prlog " [XFAIL]"
@@ -207,7 +222,14 @@ SIG_RESULT=
207SIG_BASE=36 # Use realtime signals 222SIG_BASE=36 # Use realtime signals
208SIG_PID=$$ 223SIG_PID=$$
209 224
225exit_pass () {
226 exit 0
227}
228
210SIG_FAIL=$((SIG_BASE + FAIL)) 229SIG_FAIL=$((SIG_BASE + FAIL))
230exit_fail () {
231 exit 1
232}
211trap 'SIG_RESULT=$FAIL' $SIG_FAIL 233trap 'SIG_RESULT=$FAIL' $SIG_FAIL
212 234
213SIG_UNRESOLVED=$((SIG_BASE + UNRESOLVED)) 235SIG_UNRESOLVED=$((SIG_BASE + UNRESOLVED))
@@ -247,12 +269,20 @@ __run_test() { # testfile
247# Run one test case 269# Run one test case
248run_test() { # testfile 270run_test() { # testfile
249 local testname=`basename $1` 271 local testname=`basename $1`
250 local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX` 272 if [ ! -z "$LOG_FILE" ] ; then
273 local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX`
274 else
275 local testlog=/proc/self/fd/1
276 fi
251 export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX` 277 export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX`
252 testcase $1 278 testcase $1
253 echo "execute$INSTANCE: "$1 > $testlog 279 echo "execute$INSTANCE: "$1 > $testlog
254 SIG_RESULT=0 280 SIG_RESULT=0
255 if [ $VERBOSE -ge 2 ]; then 281 if [ -z "$LOG_FILE" ]; then
282 __run_test $1 2>&1
283 elif [ $VERBOSE -ge 3 ]; then
284 __run_test $1 | tee -a $testlog 2>&1
285 elif [ $VERBOSE -eq 2 ]; then
256 __run_test $1 2>> $testlog | tee -a $testlog 286 __run_test $1 2>> $testlog | tee -a $testlog
257 else 287 else
258 __run_test $1 >> $testlog 2>&1 288 __run_test $1 >> $testlog 2>&1
@@ -260,9 +290,9 @@ run_test() { # testfile
260 eval_result $SIG_RESULT 290 eval_result $SIG_RESULT
261 if [ $? -eq 0 ]; then 291 if [ $? -eq 0 ]; then
262 # Remove test log if the test was done as it was expected. 292 # Remove test log if the test was done as it was expected.
263 [ $KEEP_LOG -eq 0 ] && rm $testlog 293 [ $KEEP_LOG -eq 0 -a ! -z "$LOG_FILE" ] && rm $testlog
264 else 294 else
265 [ $VERBOSE -ge 1 ] && catlog $testlog 295 [ $VERBOSE -eq 1 -o $VERBOSE -eq 2 ] && catlog $testlog
266 TOTAL_RESULT=1 296 TOTAL_RESULT=1
267 fi 297 fi
268 rm -rf $TMPDIR 298 rm -rf $TMPDIR
diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic2.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic2.tc
index ebfce83f35b4..531e472362df 100644
--- a/tools/testing/selftests/ftrace/test.d/00basic/basic2.tc
+++ b/tools/testing/selftests/ftrace/test.d/00basic/basic2.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Basic test for tracers 3# description: Basic test for tracers
3# flags: instance 4# flags: instance
4test -f available_tracers 5test -f available_tracers
diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic3.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic3.tc
index 9e33f841812f..58a2506f788e 100644
--- a/tools/testing/selftests/ftrace/test.d/00basic/basic3.tc
+++ b/tools/testing/selftests/ftrace/test.d/00basic/basic3.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Basic trace clock test 3# description: Basic trace clock test
3# flags: instance 4# flags: instance
4test -f trace_clock 5test -f trace_clock
diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc
index aa51f6c17359..0696098d6408 100644
--- a/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc
+++ b/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc
@@ -2,4 +2,4 @@
2# description: Basic event tracing check 2# description: Basic event tracing check
3test -f available_events -a -f set_event -a -d events 3test -f available_events -a -f set_event -a -d events
4# check scheduler events are available 4# check scheduler events are available
5grep -q sched available_events && exit 0 || exit $FAIL 5grep -q sched available_events && exit_pass || exit_fail
diff --git a/tools/testing/selftests/ftrace/test.d/event/event-enable.tc b/tools/testing/selftests/ftrace/test.d/event/event-enable.tc
index 283b45ecb199..9daf034186f5 100644
--- a/tools/testing/selftests/ftrace/test.d/event/event-enable.tc
+++ b/tools/testing/selftests/ftrace/test.d/event/event-enable.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: event tracing - enable/disable with event level files 3# description: event tracing - enable/disable with event level files
3# flags: instance 4# flags: instance
4 5
@@ -10,7 +11,7 @@ do_reset() {
10fail() { #msg 11fail() { #msg
11 do_reset 12 do_reset
12 echo $1 13 echo $1
13 exit $FAIL 14 exit_fail
14} 15}
15 16
16yield() { 17yield() {
diff --git a/tools/testing/selftests/ftrace/test.d/event/event-pid.tc b/tools/testing/selftests/ftrace/test.d/event/event-pid.tc
index 96c1a95be4f7..132478b305c2 100644
--- a/tools/testing/selftests/ftrace/test.d/event/event-pid.tc
+++ b/tools/testing/selftests/ftrace/test.d/event/event-pid.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: event tracing - restricts events based on pid 3# description: event tracing - restricts events based on pid
3# flags: instance 4# flags: instance
4 5
@@ -12,7 +13,7 @@ do_reset() {
12fail() { #msg 13fail() { #msg
13 do_reset 14 do_reset
14 echo $1 15 echo $1
15 exit $FAIL 16 exit_fail
16} 17}
17 18
18yield() { 19yield() {
diff --git a/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
index b8fe2e5b9e67..6a37a8642ee6 100644
--- a/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
+++ b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: event tracing - enable/disable with subsystem level files 3# description: event tracing - enable/disable with subsystem level files
3# flags: instance 4# flags: instance
4 5
@@ -10,7 +11,7 @@ do_reset() {
10fail() { #msg 11fail() { #msg
11 do_reset 12 do_reset
12 echo $1 13 echo $1
13 exit $FAIL 14 exit_fail
14} 15}
15 16
16yield() { 17yield() {
diff --git a/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc b/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
index 15e2d3fe1731..4e9b6e2c0219 100644
--- a/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
+++ b/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: event tracing - enable/disable with top level files 3# description: event tracing - enable/disable with top level files
3 4
4do_reset() { 5do_reset() {
@@ -9,7 +10,7 @@ do_reset() {
9fail() { #msg 10fail() { #msg
10 do_reset 11 do_reset
11 echo $1 12 echo $1
12 exit $FAIL 13 exit_fail
13} 14}
14 15
15yield() { 16yield() {
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc
index 15c2dba06ea2..1aec99d108eb 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: ftrace - function graph filters with stack tracer 3# description: ftrace - function graph filters with stack tracer
3 4
4# Make sure that function graph filtering works, and is not 5# Make sure that function graph filtering works, and is not
@@ -27,7 +28,7 @@ do_reset() {
27fail() { # msg 28fail() { # msg
28 do_reset 29 do_reset
29 echo $1 30 echo $1
30 exit $FAIL 31 exit_fail
31} 32}
32 33
33disable_tracing 34disable_tracing
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc
index 0ab2189613ef..9f8d27ca39cf 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: ftrace - function graph filters 3# description: ftrace - function graph filters
3 4
4# Make sure that function graph filtering works 5# Make sure that function graph filtering works
@@ -17,7 +18,7 @@ do_reset() {
17fail() { # msg 18fail() { # msg
18 do_reset 19 do_reset
19 echo $1 20 echo $1
20 exit $FAIL 21 exit_fail
21} 22}
22 23
23disable_tracing 24disable_tracing
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc
index 8095e122daa9..589d52b211b7 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: ftrace - function glob filters 3# description: ftrace - function glob filters
3 4
4# Make sure that function glob matching filter works. 5# Make sure that function glob matching filter works.
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc
index bab5ff7c607e..524ce24b3c22 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: ftrace - function pid filters 3# description: ftrace - function pid filters
3 4
4# Make sure that function pid matching filter works. 5# Make sure that function pid matching filter works.
@@ -50,7 +51,7 @@ do_reset() {
50fail() { # msg 51fail() { # msg
51 do_reset 52 do_reset
52 echo $1 53 echo $1
53 exit $FAIL 54 exit_fail
54} 55}
55 56
56yield() { 57yield() {
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc
index 77dfb6b48186..6fed4cf2db81 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: ftrace - test for function event triggers 3# description: ftrace - test for function event triggers
3# flags: instance 4# flags: instance
4# 5#
@@ -26,7 +27,7 @@ do_reset() {
26fail() { # mesg 27fail() { # mesg
27 do_reset 28 do_reset
28 echo $1 29 echo $1
29 exit $FAIL 30 exit_fail
30} 31}
31 32
32SLEEP_TIME=".1" 33SLEEP_TIME=".1"
@@ -47,8 +48,7 @@ test_event_enabled() {
47 48
48 e=`cat $EVENT_ENABLE` 49 e=`cat $EVENT_ENABLE`
49 if [ "$e" != $val ]; then 50 if [ "$e" != $val ]; then
50 echo "Expected $val but found $e" 51 fail "Expected $val but found $e"
51 exit 1
52 fi 52 fi
53} 53}
54 54
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc
index 7808336d6f50..b2d5a8febfe8 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: ftrace - function profiler with function tracing 3# description: ftrace - function profiler with function tracing
3 4
4# There was a bug after a rewrite of the ftrace infrastructure that 5# There was a bug after a rewrite of the ftrace infrastructure that
@@ -31,7 +32,7 @@ fail() { # mesg
31 reset_tracer 32 reset_tracer
32 echo > set_ftrace_filter 33 echo > set_ftrace_filter
33 echo $1 34 echo $1
34 exit $FAIL 35 exit_fail
35} 36}
36 37
37echo "Testing function tracer with profiler:" 38echo "Testing function tracer with profiler:"
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc
index 113b4d9bc733..0f3f92622e33 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: ftrace - test reading of set_ftrace_filter 3# description: ftrace - test reading of set_ftrace_filter
3# 4#
4# The set_ftrace_filter file of ftrace is used to list functions as well as 5# The set_ftrace_filter file of ftrace is used to list functions as well as
@@ -25,14 +26,14 @@ do_reset() {
25fail() { # mesg 26fail() { # mesg
26 do_reset 27 do_reset
27 echo $1 28 echo $1
28 exit $FAIL 29 exit_fail
29} 30}
30 31
31do_reset 32do_reset
32 33
33FILTER=set_ftrace_filter 34FILTER=set_ftrace_filter
34FUNC1="schedule" 35FUNC1="schedule"
35FUNC2="do_IRQ" 36FUNC2="do_softirq"
36 37
37ALL_FUNCS="#### all functions enabled ####" 38ALL_FUNCS="#### all functions enabled ####"
38 39
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc
index 7a9ab4ff83b6..f6d9ac73268a 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: ftrace - test for function traceon/off triggers 3# description: ftrace - test for function traceon/off triggers
3# flags: instance 4# flags: instance
4# 5#
@@ -26,7 +27,7 @@ do_reset() {
26fail() { # mesg 27fail() { # mesg
27 do_reset 28 do_reset
28 echo $1 29 echo $1
29 exit $FAIL 30 exit_fail
30} 31}
31 32
32SLEEP_TIME=".1" 33SLEEP_TIME=".1"
diff --git a/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
index 8a353314dc9b..4fa0f79144f4 100644
--- a/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
+++ b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Test creation and deletion of trace instances while setting an event 3# description: Test creation and deletion of trace instances while setting an event
3 4
4if [ ! -d instances ] ; then 5if [ ! -d instances ] ; then
@@ -10,7 +11,7 @@ fail() { # mesg
10 rmdir foo 2>/dev/null 11 rmdir foo 2>/dev/null
11 echo $1 12 echo $1
12 set -e 13 set -e
13 exit $FAIL 14 exit_fail
14} 15}
15 16
16cd instances 17cd instances
diff --git a/tools/testing/selftests/ftrace/test.d/instances/instance.tc b/tools/testing/selftests/ftrace/test.d/instances/instance.tc
index 1e1abe0ad354..b84651283bf3 100644
--- a/tools/testing/selftests/ftrace/test.d/instances/instance.tc
+++ b/tools/testing/selftests/ftrace/test.d/instances/instance.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Test creation and deletion of trace instances 3# description: Test creation and deletion of trace instances
3 4
4if [ ! -d instances ] ; then 5if [ ! -d instances ] ; then
@@ -10,7 +11,7 @@ fail() { # mesg
10 rmdir x y z 2>/dev/null 11 rmdir x y z 2>/dev/null
11 echo $1 12 echo $1
12 set -e 13 set -e
13 exit $FAIL 14 exit_fail
14} 15}
15 16
16cd instances 17cd instances
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc b/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc
index c3843ed49bf6..4604d2103c89 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Kprobe dynamic event - adding and removing 3# description: Kprobe dynamic event - adding and removing
3 4
4[ -f kprobe_events ] || exit_unsupported # this is configurable 5[ -f kprobe_events ] || exit_unsupported # this is configurable
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc b/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc
index 74507db8bbc8..bbc443a9190c 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Kprobe dynamic event - busy event check 3# description: Kprobe dynamic event - busy event check
3 4
4[ -f kprobe_events ] || exit_unsupported 5[ -f kprobe_events ] || exit_unsupported
@@ -8,7 +9,7 @@ echo > kprobe_events
8echo p:myevent _do_fork > kprobe_events 9echo p:myevent _do_fork > kprobe_events
9test -d events/kprobes/myevent 10test -d events/kprobes/myevent
10echo 1 > events/kprobes/myevent/enable 11echo 1 > events/kprobes/myevent/enable
11echo > kprobe_events && exit 1 # this must fail 12echo > kprobe_events && exit_fail # this must fail
12echo 0 > events/kprobes/myevent/enable 13echo 0 > events/kprobes/myevent/enable
13echo > kprobe_events # this must succeed 14echo > kprobe_events # this must succeed
14clear_trace 15clear_trace
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc
index 64949d4eda69..8b43c6804fc3 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Kprobe dynamic event with arguments 3# description: Kprobe dynamic event with arguments
3 4
4[ -f kprobe_events ] || exit_unsupported # this is configurable 5[ -f kprobe_events ] || exit_unsupported # this is configurable
@@ -13,5 +14,5 @@ echo 1 > events/kprobes/testprobe/enable
13echo 0 > events/kprobes/testprobe/enable 14echo 0 > events/kprobes/testprobe/enable
14echo "-:testprobe" >> kprobe_events 15echo "-:testprobe" >> kprobe_events
15clear_trace 16clear_trace
16test -d events/kprobes/testprobe && exit 1 || exit 0 17test -d events/kprobes/testprobe && exit_fail || exit_pass
17 18
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc
index c75faefb4fff..2a1755bfc290 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Kprobes event arguments with types 3# description: Kprobes event arguments with types
3 4
4[ -f kprobe_events ] || exit_unsupported # this is configurable 5[ -f kprobe_events ] || exit_unsupported # this is configurable
@@ -34,4 +35,4 @@ check_types $ARGS
34 35
35echo "-:testprobe" >> kprobe_events 36echo "-:testprobe" >> kprobe_events
36clear_trace 37clear_trace
37test -d events/kprobes/testprobe && exit 1 || exit 0 38test -d events/kprobes/testprobe && exit_fail || exit_pass
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc
index b9302cc82c12..2724a1068cb1 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Kprobe event auto/manual naming 3# description: Kprobe event auto/manual naming
3 4
4[ -f kprobe_events ] || exit_unsupported # this is configurable 5[ -f kprobe_events ] || exit_unsupported # this is configurable
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc
index d6f2f4965697..cc4cac0e60f2 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Kprobe dynamic event with function tracer 3# description: Kprobe dynamic event with function tracer
3 4
4[ -f kprobe_events ] || exit_unsupported # this is configurable 5[ -f kprobe_events ] || exit_unsupported # this is configurable
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_module.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_module.tc
index 6d634e4b7680..1e9f75f7a30f 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_module.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_module.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Kprobe dynamic event - probing module 3# description: Kprobe dynamic event - probing module
3 4
4[ -f kprobe_events ] || exit_unsupported # this is configurable 5[ -f kprobe_events ] || exit_unsupported # this is configurable
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc
index 0d09546258fd..321954683aaa 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Kretprobe dynamic event with arguments 3# description: Kretprobe dynamic event with arguments
3 4
4[ -f kprobe_events ] || exit_unsupported # this is configurable 5[ -f kprobe_events ] || exit_unsupported # this is configurable
@@ -13,4 +14,4 @@ echo 1 > events/kprobes/testprobe2/enable
13echo 0 > events/kprobes/testprobe2/enable 14echo 0 > events/kprobes/testprobe2/enable
14echo '-:testprobe2' >> kprobe_events 15echo '-:testprobe2' >> kprobe_events
15clear_trace 16clear_trace
16test -d events/kprobes/testprobe2 && exit 1 || exit 0 17test -d events/kprobes/testprobe2 && exit_fail || exit_pass
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_maxactive.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_maxactive.tc
index 7ec6f2639ad6..7c0290684c43 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_maxactive.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_maxactive.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Kretprobe dynamic event with maxactive 3# description: Kretprobe dynamic event with maxactive
3 4
4[ -f kprobe_events ] || exit_unsupported # this is configurable 5[ -f kprobe_events ] || exit_unsupported # this is configurable
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
index 2a1cb9908746..bb16cf91f1b5 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
@@ -1,6 +1,9 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: Register/unregister many kprobe events 3# description: Register/unregister many kprobe events
3 4
5[ -f kprobe_events ] || exit_unsupported # this is configurable
6
4# ftrace fentry skip size depends on the machine architecture. 7# ftrace fentry skip size depends on the machine architecture.
5# Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc64le 8# Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc64le
6case `uname -m` in 9case `uname -m` in
diff --git a/tools/testing/selftests/ftrace/test.d/template b/tools/testing/selftests/ftrace/test.d/template
index 5448f7abad5f..5c39ceb18a0d 100644
--- a/tools/testing/selftests/ftrace/test.d/template
+++ b/tools/testing/selftests/ftrace/test.d/template
@@ -4,6 +4,7 @@
4# Note that all tests are run with "errexit" option. 4# Note that all tests are run with "errexit" option.
5 5
6exit 0 # Return 0 if the test is passed, otherwise return !0 6exit 0 # Return 0 if the test is passed, otherwise return !0
7# Or you can call exit_pass for passed test, and exit_fail for failed test.
7# If the test could not run because of lack of feature, call exit_unsupported 8# If the test could not run because of lack of feature, call exit_unsupported
8# If the test returned unclear results, call exit_unresolved 9# If the test returned unclear results, call exit_unresolved
9# If the test is a dummy, or a placeholder, call exit_untested 10# If the test is a dummy, or a placeholder, call exit_untested
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc
index c5435adfdd93..28cc355a3a7b 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: event trigger - test event enable/disable trigger 3# description: event trigger - test event enable/disable trigger
3# flags: instance 4# flags: instance
4 5
@@ -11,7 +12,7 @@ do_reset() {
11fail() { #msg 12fail() { #msg
12 do_reset 13 do_reset
13 echo $1 14 echo $1
14 exit $FAIL 15 exit_fail
15} 16}
16 17
17if [ ! -f set_event -o ! -d events/sched ]; then 18if [ ! -f set_event -o ! -d events/sched ]; then
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc
index 48849a8d577f..a48e23eb8a8b 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: event trigger - test trigger filter 3# description: event trigger - test trigger filter
3# flags: instance 4# flags: instance
4 5
@@ -11,7 +12,7 @@ do_reset() {
11fail() { #msg 12fail() { #msg
12 do_reset 13 do_reset
13 echo $1 14 echo $1
14 exit $FAIL 15 exit_fail
15} 16}
16 17
17if [ ! -f set_event -o ! -d events/sched ]; then 18if [ ! -f set_event -o ! -d events/sched ]; then
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 b7f86d10b549..8da80efc44d8 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
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: event trigger - test histogram modifiers 3# description: event trigger - test histogram modifiers
3# flags: instance 4# flags: instance
4 5
@@ -11,7 +12,7 @@ do_reset() {
11fail() { #msg 12fail() { #msg
12 do_reset 13 do_reset
13 echo $1 14 echo $1
14 exit $FAIL 15 exit_fail
15} 16}
16 17
17if [ ! -f set_event -o ! -d events/sched ]; then 18if [ ! -f set_event -o ! -d events/sched ]; then
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 fb66f7d9339d..449fe9ff91a2 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: event trigger - test histogram trigger 3# description: event trigger - test histogram trigger
3# flags: instance 4# flags: instance
4 5
@@ -11,7 +12,7 @@ do_reset() {
11fail() { #msg 12fail() { #msg
12 do_reset 13 do_reset
13 echo $1 14 echo $1
14 exit $FAIL 15 exit_fail
15} 16}
16 17
17if [ ! -f set_event -o ! -d events/sched ]; then 18if [ ! -f set_event -o ! -d events/sched ]; then
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 f9153087dd7c..c5ef8b9d02b3 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: event trigger - test multiple histogram triggers 3# description: event trigger - test multiple histogram triggers
3# flags: instance 4# flags: instance
4 5
@@ -11,7 +12,7 @@ do_reset() {
11fail() { #msg 12fail() { #msg
12 do_reset 13 do_reset
13 echo $1 14 echo $1
14 exit $FAIL 15 exit_fail
15} 16}
16 17
17if [ ! -f set_event -o ! -d events/sched ]; then 18if [ ! -f set_event -o ! -d events/sched ]; then
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
index ed94f0c4e0e4..ed38f0050d77 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: event trigger - test snapshot-trigger 3# description: event trigger - test snapshot-trigger
3 4
4do_reset() { 5do_reset() {
@@ -10,7 +11,7 @@ do_reset() {
10fail() { #msg 11fail() { #msg
11 do_reset 12 do_reset
12 echo $1 13 echo $1
13 exit $FAIL 14 exit_fail
14} 15}
15 16
16if [ ! -f set_event -o ! -d events/sched ]; then 17if [ ! -f set_event -o ! -d events/sched ]; then
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc
index 9fa23b085def..3121d795a868 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: event trigger - test stacktrace-trigger 3# description: event trigger - test stacktrace-trigger
3 4
4do_reset() { 5do_reset() {
@@ -10,7 +11,7 @@ do_reset() {
10fail() { #msg 11fail() { #msg
11 do_reset 12 do_reset
12 echo $1 13 echo $1
13 exit $FAIL 14 exit_fail
14} 15}
15 16
16if [ ! -f set_event -o ! -d events/sched ]; then 17if [ ! -f set_event -o ! -d events/sched ]; then
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc
index 87648e5f987c..c59d9eb546da 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# description: event trigger - test traceon/off trigger 3# description: event trigger - test traceon/off trigger
3 4
4do_reset() { 5do_reset() {
@@ -10,7 +11,7 @@ do_reset() {
10fail() { #msg 11fail() { #msg
11 do_reset 12 do_reset
12 echo $1 13 echo $1
13 exit $FAIL 14 exit_fail
14} 15}
15 16
16if [ ! -f set_event -o ! -d events/sched ]; then 17if [ ! -f set_event -o ! -d events/sched ]; then
diff --git a/tools/testing/selftests/futex/Makefile b/tools/testing/selftests/futex/Makefile
index e2fbb890aef9..cea4adcd42b8 100644
--- a/tools/testing/selftests/futex/Makefile
+++ b/tools/testing/selftests/futex/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1SUBDIRS := functional 2SUBDIRS := functional
2 3
3TEST_PROGS := run.sh 4TEST_PROGS := run.sh
@@ -7,14 +8,17 @@ TEST_PROGS := run.sh
7include ../lib.mk 8include ../lib.mk
8 9
9all: 10all:
10 for DIR in $(SUBDIRS); do \ 11 @for DIR in $(SUBDIRS); do \
11 BUILD_TARGET=$(OUTPUT)/$$DIR; \ 12 BUILD_TARGET=$(OUTPUT)/$$DIR; \
12 mkdir $$BUILD_TARGET -p; \ 13 mkdir $$BUILD_TARGET -p; \
13 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ 14 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
15 if [ -e $$DIR/$(TEST_PROGS) ]; then
16 rsync -a $$DIR/$(TEST_PROGS) $$BUILD_TARGET/;
17 fi
14 done 18 done
15 19
16override define RUN_TESTS 20override define RUN_TESTS
17 @if [ `dirname $(OUTPUT)` = $(PWD) ]; then ./run.sh; fi 21 @cd $(OUTPUT); ./run.sh
18endef 22endef
19 23
20override define INSTALL_RULE 24override define INSTALL_RULE
@@ -33,7 +37,7 @@ override define EMIT_TESTS
33endef 37endef
34 38
35override define CLEAN 39override define CLEAN
36 for DIR in $(SUBDIRS); do \ 40 @for DIR in $(SUBDIRS); do \
37 BUILD_TARGET=$(OUTPUT)/$$DIR; \ 41 BUILD_TARGET=$(OUTPUT)/$$DIR; \
38 mkdir $$BUILD_TARGET -p; \ 42 mkdir $$BUILD_TARGET -p; \
39 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ 43 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
diff --git a/tools/testing/selftests/futex/functional/Makefile b/tools/testing/selftests/futex/functional/Makefile
index a648e7a6cbc3..ff8feca49746 100644
--- a/tools/testing/selftests/futex/functional/Makefile
+++ b/tools/testing/selftests/futex/functional/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1INCLUDES := -I../include -I../../ 2INCLUDES := -I../include -I../../
2CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE -pthread $(INCLUDES) 3CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE -pthread $(INCLUDES)
3LDFLAGS := $(LDFLAGS) -pthread -lrt 4LDFLAGS := $(LDFLAGS) -pthread -lrt
diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi.c b/tools/testing/selftests/futex/functional/futex_requeue_pi.c
index d24ab7421e73..54cd5c414e82 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue_pi.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue_pi.c
@@ -394,9 +394,11 @@ int main(int argc, char *argv[])
394 } 394 }
395 } 395 }
396 396
397 printf("%s: Test requeue functionality\n", basename(argv[0])); 397 ksft_print_header();
398 printf("\tArguments: broadcast=%d locked=%d owner=%d timeout=%ldns\n", 398 ksft_print_msg("%s: Test requeue functionality\n", basename(argv[0]));
399 broadcast, locked, owner, timeout_ns); 399 ksft_print_msg(
400 "\tArguments: broadcast=%d locked=%d owner=%d timeout=%ldns\n",
401 broadcast, locked, owner, timeout_ns);
400 402
401 /* 403 /*
402 * FIXME: unit_test is obsolete now that we parse options and the 404 * FIXME: unit_test is obsolete now that we parse options and the
diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c b/tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c
index e0a798ad0d21..08187a16507f 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c
@@ -78,7 +78,8 @@ int main(int argc, char *argv[])
78 } 78 }
79 } 79 }
80 80
81 printf("%s: Detect mismatched requeue_pi operations\n", 81 ksft_print_header();
82 ksft_print_msg("%s: Detect mismatched requeue_pi operations\n",
82 basename(argv[0])); 83 basename(argv[0]));
83 84
84 if (pthread_create(&child, NULL, blocking_child, NULL)) { 85 if (pthread_create(&child, NULL, blocking_child, NULL)) {
diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c b/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
index 982f83577501..f0542a344d95 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
@@ -143,9 +143,10 @@ int main(int argc, char *argv[])
143 } 143 }
144 } 144 }
145 145
146 printf("%s: Test signal handling during requeue_pi\n", 146 ksft_print_header();
147 ksft_print_msg("%s: Test signal handling during requeue_pi\n",
147 basename(argv[0])); 148 basename(argv[0]));
148 printf("\tArguments: <none>\n"); 149 ksft_print_msg("\tArguments: <none>\n");
149 150
150 sa.sa_handler = handle_signal; 151 sa.sa_handler = handle_signal;
151 sigemptyset(&sa.sa_mask); 152 sigemptyset(&sa.sa_mask);
diff --git a/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c b/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
index bdc48dc047e5..6216de828093 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
@@ -97,8 +97,10 @@ int main(int argc, char **argv)
97 } 97 }
98 } 98 }
99 99
100 printf("%s: Test the futex value of private file mappings in FUTEX_WAIT\n", 100 ksft_print_header();
101 basename(argv[0])); 101 ksft_print_msg(
102 "%s: Test the futex value of private file mappings in FUTEX_WAIT\n",
103 basename(argv[0]));
102 104
103 ret = pthread_create(&thr, NULL, thr_futex_wait, NULL); 105 ret = pthread_create(&thr, NULL, thr_futex_wait, NULL);
104 if (ret < 0) { 106 if (ret < 0) {
diff --git a/tools/testing/selftests/futex/functional/futex_wait_timeout.c b/tools/testing/selftests/futex/functional/futex_wait_timeout.c
index 6aadd560366e..bab3dfe1787f 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_timeout.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_timeout.c
@@ -68,9 +68,10 @@ int main(int argc, char *argv[])
68 } 68 }
69 } 69 }
70 70
71 printf("%s: Block on a futex and wait for timeout\n", 71 ksft_print_header();
72 ksft_print_msg("%s: Block on a futex and wait for timeout\n",
72 basename(argv[0])); 73 basename(argv[0]));
73 printf("\tArguments: timeout=%ldns\n", timeout_ns); 74 ksft_print_msg("\tArguments: timeout=%ldns\n", timeout_ns);
74 75
75 /* initialize timeout */ 76 /* initialize timeout */
76 to.tv_sec = 0; 77 to.tv_sec = 0;
diff --git a/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c b/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
index d237a8b702f0..26975322545b 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
@@ -99,7 +99,8 @@ int main(int argc, char **argv)
99 exit(1); 99 exit(1);
100 } 100 }
101 101
102 printf("%s: Test the uninitialized futex value in FUTEX_WAIT\n", 102 ksft_print_header();
103 ksft_print_msg("%s: Test the uninitialized futex value in FUTEX_WAIT\n",
103 basename(argv[0])); 104 basename(argv[0]));
104 105
105 106
diff --git a/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c b/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
index 9a2c56fa7305..da15a63269b4 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
@@ -64,7 +64,8 @@ int main(int argc, char *argv[])
64 } 64 }
65 } 65 }
66 66
67 printf("%s: Test the unexpected futex value in FUTEX_WAIT\n", 67 ksft_print_header();
68 ksft_print_msg("%s: Test the unexpected futex value in FUTEX_WAIT\n",
68 basename(argv[0])); 69 basename(argv[0]));
69 70
70 info("Calling futex_wait on f1: %u @ %p with val=%u\n", f1, &f1, f1+1); 71 info("Calling futex_wait on f1: %u @ %p with val=%u\n", f1, &f1, f1+1);
diff --git a/tools/testing/selftests/futex/include/logging.h b/tools/testing/selftests/futex/include/logging.h
index 4e7944984fbb..01989644e50a 100644
--- a/tools/testing/selftests/futex/include/logging.h
+++ b/tools/testing/selftests/futex/include/logging.h
@@ -109,22 +109,20 @@ void log_verbosity(int level)
109 */ 109 */
110void print_result(const char *test_name, int ret) 110void print_result(const char *test_name, int ret)
111{ 111{
112 const char *result = "Unknown return code";
113
114 switch (ret) { 112 switch (ret) {
115 case RET_PASS: 113 case RET_PASS:
116 ksft_inc_pass_cnt(); 114 ksft_test_result_pass("%s\n", test_name);
117 result = PASS; 115 ksft_print_cnts();
118 break; 116 return;
119 case RET_ERROR: 117 case RET_ERROR:
120 result = ERROR; 118 ksft_test_result_error("%s\n", test_name);
121 break; 119 ksft_print_cnts();
120 return;
122 case RET_FAIL: 121 case RET_FAIL:
123 ksft_inc_fail_cnt(); 122 ksft_test_result_fail("%s\n", test_name);
124 result = FAIL; 123 ksft_print_cnts();
125 break; 124 return;
126 } 125 }
127 printf("selftests: %s [%s]\n", test_name, result);
128} 126}
129 127
130/* log level macros */ 128/* log level macros */
diff --git a/tools/testing/selftests/gpio/Makefile b/tools/testing/selftests/gpio/Makefile
index 298929df97e6..1bbb47565c55 100644
--- a/tools/testing/selftests/gpio/Makefile
+++ b/tools/testing/selftests/gpio/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1 2
2TEST_PROGS := gpio-mockup.sh 3TEST_PROGS := gpio-mockup.sh
3TEST_FILES := gpio-mockup-sysfs.sh $(BINARIES) 4TEST_FILES := gpio-mockup-sysfs.sh $(BINARIES)
diff --git a/tools/testing/selftests/gpio/gpio-mockup-sysfs.sh b/tools/testing/selftests/gpio/gpio-mockup-sysfs.sh
index 085d7a39899c..dd269d877562 100755
--- a/tools/testing/selftests/gpio/gpio-mockup-sysfs.sh
+++ b/tools/testing/selftests/gpio/gpio-mockup-sysfs.sh
@@ -1,4 +1,5 @@
1 1
2# SPDX-License-Identifier: GPL-2.0
2is_consistent() 3is_consistent()
3{ 4{
4 val= 5 val=
diff --git a/tools/testing/selftests/gpio/gpio-mockup.sh b/tools/testing/selftests/gpio/gpio-mockup.sh
index b183439e058e..183fb932edbd 100755
--- a/tools/testing/selftests/gpio/gpio-mockup.sh
+++ b/tools/testing/selftests/gpio/gpio-mockup.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2 3
3#exit status 4#exit status
4#1: run as non-root user 5#1: run as non-root user
diff --git a/tools/testing/selftests/ia64/Makefile b/tools/testing/selftests/ia64/Makefile
index 2b3de2d3e945..4bce1a84b3a1 100644
--- a/tools/testing/selftests/ia64/Makefile
+++ b/tools/testing/selftests/ia64/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1TEST_PROGS := aliasing-test 2TEST_PROGS := aliasing-test
2 3
3all: $(TEST_PROGS) 4all: $(TEST_PROGS)
diff --git a/tools/testing/selftests/intel_pstate/Makefile b/tools/testing/selftests/intel_pstate/Makefile
index 849a90ffe8dd..5a3f7d37e912 100644
--- a/tools/testing/selftests/intel_pstate/Makefile
+++ b/tools/testing/selftests/intel_pstate/Makefile
@@ -1,7 +1,10 @@
1# SPDX-License-Identifier: GPL-2.0
1CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE 2CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE
2LDLIBS := $(LDLIBS) -lm 3LDLIBS := $(LDLIBS) -lm
3 4
5ifeq (,$(filter $(ARCH),x86))
4TEST_GEN_FILES := msr aperf 6TEST_GEN_FILES := msr aperf
7endif
5 8
6TEST_PROGS := run.sh 9TEST_PROGS := run.sh
7 10
diff --git a/tools/testing/selftests/intel_pstate/aperf.c b/tools/testing/selftests/intel_pstate/aperf.c
index cd72f3dc83e9..d21edea9c560 100644
--- a/tools/testing/selftests/intel_pstate/aperf.c
+++ b/tools/testing/selftests/intel_pstate/aperf.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <math.h> 2#include <math.h>
2#include <unistd.h> 3#include <unistd.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/testing/selftests/intel_pstate/msr.c b/tools/testing/selftests/intel_pstate/msr.c
index abbbfc84d359..88fdd2a4b0a0 100644
--- a/tools/testing/selftests/intel_pstate/msr.c
+++ b/tools/testing/selftests/intel_pstate/msr.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <math.h> 2#include <math.h>
2#include <unistd.h> 3#include <unistd.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/testing/selftests/intel_pstate/run.sh b/tools/testing/selftests/intel_pstate/run.sh
index 7868c106b8b1..c670359becc6 100755
--- a/tools/testing/selftests/intel_pstate/run.sh
+++ b/tools/testing/selftests/intel_pstate/run.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2# 3#
3# This test runs on Intel x86 based hardware which support the intel_pstate 4# This test runs on Intel x86 based hardware which support the intel_pstate
4# driver. The test checks the frequency settings from the maximum turbo 5# driver. The test checks the frequency settings from the maximum turbo
@@ -29,13 +30,12 @@
29 30
30EVALUATE_ONLY=0 31EVALUATE_ONLY=0
31 32
32max_cpus=$(($(nproc)-1)) 33if ! uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ | grep -q x86; then
34 echo "$0 # Skipped: Test can only run on x86 architectures."
35 exit 0
36fi
33 37
34# compile programs 38max_cpus=$(($(nproc)-1))
35gcc aperf.c -Wall -D_GNU_SOURCE -o aperf -lm
36[ $? -ne 0 ] && echo "Problem compiling aperf.c." && exit 1
37gcc -o msr msr.c -lm
38[ $? -ne 0 ] && echo "Problem compiling msr.c." && exit 1
39 39
40function run_test () { 40function run_test () {
41 41
diff --git a/tools/testing/selftests/ipc/Makefile b/tools/testing/selftests/ipc/Makefile
index 30ef4c7f53ea..1c4448a843a4 100644
--- a/tools/testing/selftests/ipc/Makefile
+++ b/tools/testing/selftests/ipc/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1uname_M := $(shell uname -m 2>/dev/null || echo not) 2uname_M := $(shell uname -m 2>/dev/null || echo not)
2ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/) 3ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
3ifeq ($(ARCH),i386) 4ifeq ($(ARCH),i386)
diff --git a/tools/testing/selftests/ipc/msgque.c b/tools/testing/selftests/ipc/msgque.c
index 1b2ce334bb3f..ee9382bdfadc 100644
--- a/tools/testing/selftests/ipc/msgque.c
+++ b/tools/testing/selftests/ipc/msgque.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdlib.h> 2#include <stdlib.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <string.h> 4#include <string.h>
diff --git a/tools/testing/selftests/kcmp/kcmp_test.c b/tools/testing/selftests/kcmp/kcmp_test.c
index a5a4da856dfe..6ea7b9f37a41 100644
--- a/tools/testing/selftests/kcmp/kcmp_test.c
+++ b/tools/testing/selftests/kcmp/kcmp_test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2 3
3#include <stdio.h> 4#include <stdio.h>
@@ -8,7 +9,6 @@
8#include <errno.h> 9#include <errno.h>
9#include <string.h> 10#include <string.h>
10#include <fcntl.h> 11#include <fcntl.h>
11
12#include <linux/unistd.h> 12#include <linux/unistd.h>
13#include <linux/kcmp.h> 13#include <linux/kcmp.h>
14 14
@@ -16,20 +16,28 @@
16#include <sys/types.h> 16#include <sys/types.h>
17#include <sys/stat.h> 17#include <sys/stat.h>
18#include <sys/wait.h> 18#include <sys/wait.h>
19#include <sys/epoll.h>
19 20
20#include "../kselftest.h" 21#include "../kselftest.h"
21 22
22static long sys_kcmp(int pid1, int pid2, int type, int fd1, int fd2) 23static long sys_kcmp(int pid1, int pid2, int type, unsigned long fd1, unsigned long fd2)
23{ 24{
24 return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2); 25 return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2);
25} 26}
26 27
28static const unsigned int duped_num = 64;
29
27int main(int argc, char **argv) 30int main(int argc, char **argv)
28{ 31{
29 const char kpath[] = "kcmp-test-file"; 32 const char kpath[] = "kcmp-test-file";
33 struct kcmp_epoll_slot epoll_slot;
34 struct epoll_event ev;
30 int pid1, pid2; 35 int pid1, pid2;
36 int pipefd[2];
31 int fd1, fd2; 37 int fd1, fd2;
38 int epollfd;
32 int status; 39 int status;
40 int fddup;
33 41
34 fd1 = open(kpath, O_RDWR | O_CREAT | O_TRUNC, 0644); 42 fd1 = open(kpath, O_RDWR | O_CREAT | O_TRUNC, 0644);
35 pid1 = getpid(); 43 pid1 = getpid();
@@ -39,6 +47,37 @@ int main(int argc, char **argv)
39 ksft_exit_fail(); 47 ksft_exit_fail();
40 } 48 }
41 49
50 if (pipe(pipefd)) {
51 perror("Can't create pipe");
52 ksft_exit_fail();
53 }
54
55 epollfd = epoll_create1(0);
56 if (epollfd < 0) {
57 perror("epoll_create1 failed");
58 ksft_exit_fail();
59 }
60
61 memset(&ev, 0xff, sizeof(ev));
62 ev.events = EPOLLIN | EPOLLOUT;
63
64 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd[0], &ev)) {
65 perror("epoll_ctl failed");
66 ksft_exit_fail();
67 }
68
69 fddup = dup2(pipefd[1], duped_num);
70 if (fddup < 0) {
71 perror("dup2 failed");
72 ksft_exit_fail();
73 }
74
75 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fddup, &ev)) {
76 perror("epoll_ctl failed");
77 ksft_exit_fail();
78 }
79 close(fddup);
80
42 pid2 = fork(); 81 pid2 = fork();
43 if (pid2 < 0) { 82 if (pid2 < 0) {
44 perror("fork failed"); 83 perror("fork failed");
@@ -95,6 +134,24 @@ int main(int argc, char **argv)
95 ksft_inc_pass_cnt(); 134 ksft_inc_pass_cnt();
96 } 135 }
97 136
137 /* Compare epoll target */
138 epoll_slot = (struct kcmp_epoll_slot) {
139 .efd = epollfd,
140 .tfd = duped_num,
141 .toff = 0,
142 };
143 ret = sys_kcmp(pid1, pid1, KCMP_EPOLL_TFD, pipefd[1],
144 (unsigned long)(void *)&epoll_slot);
145 if (ret) {
146 printf("FAIL: 0 expected but %d returned (%s)\n",
147 ret, strerror(errno));
148 ksft_inc_fail_cnt();
149 ret = -1;
150 } else {
151 printf("PASS: 0 returned as expected\n");
152 ksft_inc_pass_cnt();
153 }
154
98 ksft_print_cnts(); 155 ksft_print_cnts();
99 156
100 if (ret) 157 if (ret)
diff --git a/tools/testing/selftests/kmod/kmod.sh b/tools/testing/selftests/kmod/kmod.sh
index 8cecae9a8bca..7956ea3be667 100644..100755
--- a/tools/testing/selftests/kmod/kmod.sh
+++ b/tools/testing/selftests/kmod/kmod.sh
@@ -473,8 +473,8 @@ usage()
473 echo " all Runs all tests (default)" 473 echo " all Runs all tests (default)"
474 echo " -t Run test ID the number amount of times is recommended" 474 echo " -t Run test ID the number amount of times is recommended"
475 echo " -w Watch test ID run until it runs into an error" 475 echo " -w Watch test ID run until it runs into an error"
476 echo " -c Run test ID once" 476 echo " -s Run test ID once"
477 echo " -s Run test ID x test-count number of times" 477 echo " -c Run test ID x test-count number of times"
478 echo " -l List all test ID list" 478 echo " -l List all test ID list"
479 echo " -h|--help Help" 479 echo " -h|--help Help"
480 echo 480 echo
diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
index 08e90c2cc5cb..1ae565ed9bf0 100644
--- a/tools/testing/selftests/kselftest.h
+++ b/tools/testing/selftests/kselftest.h
@@ -19,7 +19,8 @@
19#define KSFT_FAIL 1 19#define KSFT_FAIL 1
20#define KSFT_XFAIL 2 20#define KSFT_XFAIL 2
21#define KSFT_XPASS 3 21#define KSFT_XPASS 3
22#define KSFT_SKIP 4 22/* Treat skip as pass */
23#define KSFT_SKIP KSFT_PASS
23 24
24/* counters */ 25/* counters */
25struct ksft_count { 26struct ksft_count {
@@ -28,6 +29,7 @@ struct ksft_count {
28 unsigned int ksft_xfail; 29 unsigned int ksft_xfail;
29 unsigned int ksft_xpass; 30 unsigned int ksft_xpass;
30 unsigned int ksft_xskip; 31 unsigned int ksft_xskip;
32 unsigned int ksft_error;
31}; 33};
32 34
33static struct ksft_count ksft_cnt; 35static struct ksft_count ksft_cnt;
@@ -36,7 +38,7 @@ static inline int ksft_test_num(void)
36{ 38{
37 return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail + 39 return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail +
38 ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass + 40 ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass +
39 ksft_cnt.ksft_xskip; 41 ksft_cnt.ksft_xskip + ksft_cnt.ksft_error;
40} 42}
41 43
42static inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; } 44static inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; }
@@ -44,6 +46,14 @@ static inline void ksft_inc_fail_cnt(void) { ksft_cnt.ksft_fail++; }
44static inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; } 46static inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; }
45static inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; } 47static inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; }
46static inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; } 48static inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; }
49static inline void ksft_inc_error_cnt(void) { ksft_cnt.ksft_error++; }
50
51static inline int ksft_get_pass_cnt(void) { return ksft_cnt.ksft_pass; }
52static inline int ksft_get_fail_cnt(void) { return ksft_cnt.ksft_fail; }
53static inline int ksft_get_xfail_cnt(void) { return ksft_cnt.ksft_xfail; }
54static inline int ksft_get_xpass_cnt(void) { return ksft_cnt.ksft_xpass; }
55static inline int ksft_get_xskip_cnt(void) { return ksft_cnt.ksft_xskip; }
56static inline int ksft_get_error_cnt(void) { return ksft_cnt.ksft_error; }
47 57
48static inline void ksft_print_header(void) 58static inline void ksft_print_header(void)
49{ 59{
@@ -52,6 +62,10 @@ static inline void ksft_print_header(void)
52 62
53static inline void ksft_print_cnts(void) 63static inline void ksft_print_cnts(void)
54{ 64{
65 printf("Pass %d Fail %d Xfail %d Xpass %d Skip %d Error %d\n",
66 ksft_cnt.ksft_pass, ksft_cnt.ksft_fail,
67 ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass,
68 ksft_cnt.ksft_xskip, ksft_cnt.ksft_error);
55 printf("1..%d\n", ksft_test_num()); 69 printf("1..%d\n", ksft_test_num());
56} 70}
57 71
@@ -101,6 +115,18 @@ static inline void ksft_test_result_skip(const char *msg, ...)
101 va_end(args); 115 va_end(args);
102} 116}
103 117
118static inline void ksft_test_result_error(const char *msg, ...)
119{
120 va_list args;
121
122 ksft_cnt.ksft_error++;
123
124 va_start(args, msg);
125 printf("not ok %d # error ", ksft_test_num());
126 vprintf(msg, args);
127 va_end(args);
128}
129
104static inline int ksft_exit_pass(void) 130static inline int ksft_exit_pass(void)
105{ 131{
106 ksft_print_cnts(); 132 ksft_print_cnts();
diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h
index c56f72e07cd7..e81bd28bdd89 100644
--- a/tools/testing/selftests/kselftest_harness.h
+++ b/tools/testing/selftests/kselftest_harness.h
@@ -51,6 +51,9 @@
51#define __KSELFTEST_HARNESS_H 51#define __KSELFTEST_HARNESS_H
52 52
53#define _GNU_SOURCE 53#define _GNU_SOURCE
54#include <asm/types.h>
55#include <errno.h>
56#include <stdbool.h>
54#include <stdint.h> 57#include <stdint.h>
55#include <stdio.h> 58#include <stdio.h>
56#include <stdlib.h> 59#include <stdlib.h>
@@ -84,6 +87,14 @@
84 * E.g., #define TH_LOG_ENABLED 1 87 * E.g., #define TH_LOG_ENABLED 1
85 * 88 *
86 * If no definition is provided, logging is enabled by default. 89 * If no definition is provided, logging is enabled by default.
90 *
91 * If there is no way to print an error message for the process running the
92 * test (e.g. not allowed to write to stderr), it is still possible to get the
93 * ASSERT_* number for which the test failed. This behavior can be enabled by
94 * writing `_metadata->no_print = true;` before the check sequence that is
95 * unable to print. When an error occur, instead of printing an error message
96 * and calling `abort(3)`, the test process call `_exit(2)` with the assert
97 * number as argument, which is then printed by the parent process.
87 */ 98 */
88#define TH_LOG(fmt, ...) do { \ 99#define TH_LOG(fmt, ...) do { \
89 if (TH_LOG_ENABLED) \ 100 if (TH_LOG_ENABLED) \
@@ -555,12 +566,18 @@
555 * return while still providing an optional block to the API consumer. 566 * return while still providing an optional block to the API consumer.
556 */ 567 */
557#define OPTIONAL_HANDLER(_assert) \ 568#define OPTIONAL_HANDLER(_assert) \
558 for (; _metadata->trigger; _metadata->trigger = __bail(_assert)) 569 for (; _metadata->trigger; _metadata->trigger = \
570 __bail(_assert, _metadata->no_print, _metadata->step))
571
572#define __INC_STEP(_metadata) \
573 if (_metadata->passed && _metadata->step < 255) \
574 _metadata->step++;
559 575
560#define __EXPECT(_expected, _seen, _t, _assert) do { \ 576#define __EXPECT(_expected, _seen, _t, _assert) do { \
561 /* Avoid multiple evaluation of the cases */ \ 577 /* Avoid multiple evaluation of the cases */ \
562 __typeof__(_expected) __exp = (_expected); \ 578 __typeof__(_expected) __exp = (_expected); \
563 __typeof__(_seen) __seen = (_seen); \ 579 __typeof__(_seen) __seen = (_seen); \
580 if (_assert) __INC_STEP(_metadata); \
564 if (!(__exp _t __seen)) { \ 581 if (!(__exp _t __seen)) { \
565 unsigned long long __exp_print = (uintptr_t)__exp; \ 582 unsigned long long __exp_print = (uintptr_t)__exp; \
566 unsigned long long __seen_print = (uintptr_t)__seen; \ 583 unsigned long long __seen_print = (uintptr_t)__seen; \
@@ -576,6 +593,7 @@
576#define __EXPECT_STR(_expected, _seen, _t, _assert) do { \ 593#define __EXPECT_STR(_expected, _seen, _t, _assert) do { \
577 const char *__exp = (_expected); \ 594 const char *__exp = (_expected); \
578 const char *__seen = (_seen); \ 595 const char *__seen = (_seen); \
596 if (_assert) __INC_STEP(_metadata); \
579 if (!(strcmp(__exp, __seen) _t 0)) { \ 597 if (!(strcmp(__exp, __seen) _t 0)) { \
580 __TH_LOG("Expected '%s' %s '%s'.", __exp, #_t, __seen); \ 598 __TH_LOG("Expected '%s' %s '%s'.", __exp, #_t, __seen); \
581 _metadata->passed = 0; \ 599 _metadata->passed = 0; \
@@ -590,6 +608,8 @@ struct __test_metadata {
590 int termsig; 608 int termsig;
591 int passed; 609 int passed;
592 int trigger; /* extra handler after the evaluation */ 610 int trigger; /* extra handler after the evaluation */
611 __u8 step;
612 bool no_print; /* manual trigger when TH_LOG_STREAM is not available */
593 struct __test_metadata *prev, *next; 613 struct __test_metadata *prev, *next;
594}; 614};
595 615
@@ -634,10 +654,13 @@ static inline void __register_test(struct __test_metadata *t)
634 } 654 }
635} 655}
636 656
637static inline int __bail(int for_realz) 657static inline int __bail(int for_realz, bool no_print, __u8 step)
638{ 658{
639 if (for_realz) 659 if (for_realz) {
660 if (no_print)
661 _exit(step);
640 abort(); 662 abort();
663 }
641 return 0; 664 return 0;
642} 665}
643 666
@@ -655,18 +678,24 @@ void __run_test(struct __test_metadata *t)
655 t->passed = 0; 678 t->passed = 0;
656 } else if (child_pid == 0) { 679 } else if (child_pid == 0) {
657 t->fn(t); 680 t->fn(t);
658 _exit(t->passed); 681 /* return the step that failed or 0 */
682 _exit(t->passed ? 0 : t->step);
659 } else { 683 } else {
660 /* TODO(wad) add timeout support. */ 684 /* TODO(wad) add timeout support. */
661 waitpid(child_pid, &status, 0); 685 waitpid(child_pid, &status, 0);
662 if (WIFEXITED(status)) { 686 if (WIFEXITED(status)) {
663 t->passed = t->termsig == -1 ? WEXITSTATUS(status) : 0; 687 t->passed = t->termsig == -1 ? !WEXITSTATUS(status) : 0;
664 if (t->termsig != -1) { 688 if (t->termsig != -1) {
665 fprintf(TH_LOG_STREAM, 689 fprintf(TH_LOG_STREAM,
666 "%s: Test exited normally " 690 "%s: Test exited normally "
667 "instead of by signal (code: %d)\n", 691 "instead of by signal (code: %d)\n",
668 t->name, 692 t->name,
669 WEXITSTATUS(status)); 693 WEXITSTATUS(status));
694 } else if (!t->passed) {
695 fprintf(TH_LOG_STREAM,
696 "%s: Test failed at step #%d\n",
697 t->name,
698 WEXITSTATUS(status));
670 } 699 }
671 } else if (WIFSIGNALED(status)) { 700 } else if (WIFSIGNALED(status)) {
672 t->passed = 0; 701 t->passed = 0;
diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk
index 959273c3a52e..5bef05d6ba39 100644
--- a/tools/testing/selftests/lib.mk
+++ b/tools/testing/selftests/lib.mk
@@ -6,20 +6,53 @@ ifeq (0,$(MAKELEVEL))
6OUTPUT := $(shell pwd) 6OUTPUT := $(shell pwd)
7endif 7endif
8 8
9# The following are built by lib.mk common compile rules.
10# TEST_CUSTOM_PROGS should be used by tests that require
11# custom build rule and prevent common build rule use.
12# TEST_PROGS are for test shell scripts.
13# TEST_CUSTOM_PROGS and TEST_PROGS will be run by common run_tests
14# and install targets. Common clean doesn't touch them.
9TEST_GEN_PROGS := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS)) 15TEST_GEN_PROGS := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS))
16TEST_GEN_PROGS_EXTENDED := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS_EXTENDED))
10TEST_GEN_FILES := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_FILES)) 17TEST_GEN_FILES := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_FILES))
11 18
12all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) 19all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES)
13 20
21.ONESHELL:
14define RUN_TESTS 22define RUN_TESTS
15 @for TEST in $(TEST_GEN_PROGS) $(TEST_PROGS); do \ 23 @test_num=`echo 0`;
24 @echo "TAP version 13";
25 @for TEST in $(1); do \
16 BASENAME_TEST=`basename $$TEST`; \ 26 BASENAME_TEST=`basename $$TEST`; \
17 cd `dirname $$TEST`; (./$$BASENAME_TEST && echo "selftests: $$BASENAME_TEST [PASS]") || echo "selftests: $$BASENAME_TEST [FAIL]"; cd -;\ 27 test_num=`echo $$test_num+1 | bc`; \
28 echo "selftests: $$BASENAME_TEST"; \
29 echo "========================================"; \
30 if [ ! -x $$TEST ]; then \
31 echo "selftests: Warning: file $$BASENAME_TEST is not executable, correct this.";\
32 echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; \
33 else \
34 if [ "X$(summary)" != "X" ]; then \
35 cd `dirname $$TEST` > /dev/null; (./$$BASENAME_TEST > /tmp/$$BASENAME_TEST 2>&1 && echo "ok 1..$$test_num selftests: $$BASENAME_TEST [PASS]") || echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; cd - > /dev/null;\
36 else \
37 cd `dirname $$TEST` > /dev/null; (./$$BASENAME_TEST && echo "ok 1..$$test_num selftests: $$BASENAME_TEST [PASS]") || echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; cd - > /dev/null;\
38 fi; \
39 fi; \
18 done; 40 done;
19endef 41endef
20 42
21run_tests: all 43run_tests: all
22 $(RUN_TESTS) 44ifneq ($(KBUILD_SRC),)
45 @if [ "X$(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES)" != "X" ]; then
46 @rsync -aq $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(OUTPUT)
47 fi
48 @if [ "X$(TEST_PROGS)" != "X" ]; then
49 $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(OUTPUT)/$(TEST_PROGS))
50 else
51 $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS))
52 fi
53else
54 $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS))
55endif
23 56
24define INSTALL_RULE 57define INSTALL_RULE
25 @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then \ 58 @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then \
@@ -27,10 +60,10 @@ define INSTALL_RULE
27 echo "rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/"; \ 60 echo "rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/"; \
28 rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/; \ 61 rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/; \
29 fi 62 fi
30 @if [ "X$(TEST_GEN_PROGS)$(TEST_GEN_PROGS_EXTENDED)$(TEST_GEN_FILES)" != "X" ]; then \ 63 @if [ "X$(TEST_GEN_PROGS)$(TEST_CUSTOM_PROGS)$(TEST_GEN_PROGS_EXTENDED)$(TEST_GEN_FILES)" != "X" ]; then \
31 mkdir -p ${INSTALL_PATH}; \ 64 mkdir -p ${INSTALL_PATH}; \
32 echo "rsync -a $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/"; \ 65 echo "rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/"; \
33 rsync -a $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/; \ 66 rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/; \
34 fi 67 fi
35endef 68endef
36 69
@@ -42,15 +75,20 @@ else
42endif 75endif
43 76
44define EMIT_TESTS 77define EMIT_TESTS
45 @for TEST in $(TEST_GEN_PROGS) $(TEST_PROGS); do \ 78 @for TEST in $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS); do \
46 BASENAME_TEST=`basename $$TEST`; \ 79 BASENAME_TEST=`basename $$TEST`; \
47 echo "(./$$BASENAME_TEST && echo \"selftests: $$BASENAME_TEST [PASS]\") || echo \"selftests: $$BASENAME_TEST [FAIL]\""; \ 80 echo "(./$$BASENAME_TEST > /tmp/$$BASENAME_TEST 2>&1 && echo \"selftests: $$BASENAME_TEST [PASS]\") || echo \"selftests: $$BASENAME_TEST [FAIL]\""; \
48 done; 81 done;
49endef 82endef
50 83
51emit_tests: 84emit_tests:
52 $(EMIT_TESTS) 85 $(EMIT_TESTS)
53 86
87# define if isn't already. It is undefined in make O= case.
88ifeq ($(RM),)
89RM := rm -f
90endif
91
54define CLEAN 92define CLEAN
55 $(RM) -r $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(EXTRA_CLEAN) 93 $(RM) -r $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(EXTRA_CLEAN)
56endef 94endef
@@ -58,6 +96,15 @@ endef
58clean: 96clean:
59 $(CLEAN) 97 $(CLEAN)
60 98
99# When make O= with kselftest target from main level
100# the following aren't defined.
101#
102ifneq ($(KBUILD_SRC),)
103LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
104COMPILE.S = $(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
105LINK.S = $(CC) $(ASFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
106endif
107
61$(OUTPUT)/%:%.c 108$(OUTPUT)/%:%.c
62 $(LINK.c) $^ $(LDLIBS) -o $@ 109 $(LINK.c) $^ $(LDLIBS) -o $@
63 110
diff --git a/tools/testing/selftests/lib/bitmap.sh b/tools/testing/selftests/lib/bitmap.sh
index b073c22a3435..4dee4d2a8bbe 100755
--- a/tools/testing/selftests/lib/bitmap.sh
+++ b/tools/testing/selftests/lib/bitmap.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# Runs bitmap infrastructure tests using test_bitmap kernel module 3# Runs bitmap infrastructure tests using test_bitmap kernel module
3if ! /sbin/modprobe -q -n test_bitmap; then 4if ! /sbin/modprobe -q -n test_bitmap; then
4 echo "bitmap: [SKIP]" 5 echo "bitmap: [SKIP]"
diff --git a/tools/testing/selftests/lib/prime_numbers.sh b/tools/testing/selftests/lib/prime_numbers.sh
index da4cbcd766f5..b363994e5e11 100755
--- a/tools/testing/selftests/lib/prime_numbers.sh
+++ b/tools/testing/selftests/lib/prime_numbers.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# Checks fast/slow prime_number generation for inconsistencies 3# Checks fast/slow prime_number generation for inconsistencies
3 4
4if ! /sbin/modprobe -q -r prime_numbers; then 5if ! /sbin/modprobe -q -r prime_numbers; then
diff --git a/tools/testing/selftests/lib/printf.sh b/tools/testing/selftests/lib/printf.sh
index cbf3b124bd94..0c37377fd7d4 100755
--- a/tools/testing/selftests/lib/printf.sh
+++ b/tools/testing/selftests/lib/printf.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# Runs printf infrastructure using test_printf kernel module 3# Runs printf infrastructure using test_printf kernel module
3if ! /sbin/modprobe -q -n test_printf; then 4if ! /sbin/modprobe -q -n test_printf; then
4 echo "printf: [SKIP]" 5 echo "printf: [SKIP]"
diff --git a/tools/testing/selftests/locking/ww_mutex.sh b/tools/testing/selftests/locking/ww_mutex.sh
index 6905da965f3b..2c3d6b1878c2 100644
--- a/tools/testing/selftests/locking/ww_mutex.sh
+++ b/tools/testing/selftests/locking/ww_mutex.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# Runs API tests for struct ww_mutex (Wait/Wound mutexes) 3# Runs API tests for struct ww_mutex (Wait/Wound mutexes)
3 4
4if /sbin/modprobe -q test-ww_mutex; then 5if /sbin/modprobe -q test-ww_mutex; then
diff --git a/tools/testing/selftests/media_tests/Makefile b/tools/testing/selftests/media_tests/Makefile
index 6b34a0199468..be5bd4ffb895 100644
--- a/tools/testing/selftests/media_tests/Makefile
+++ b/tools/testing/selftests/media_tests/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1TEST_PROGS := media_device_test media_device_open video_device_test 2TEST_PROGS := media_device_test media_device_open video_device_test
2all: $(TEST_PROGS) 3all: $(TEST_PROGS)
3 4
diff --git a/tools/testing/selftests/media_tests/bind_unbind_sample.sh b/tools/testing/selftests/media_tests/bind_unbind_sample.sh
index 9f362f10631a..0101c1ec4ff7 100755
--- a/tools/testing/selftests/media_tests/bind_unbind_sample.sh
+++ b/tools/testing/selftests/media_tests/bind_unbind_sample.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2# Find device number in /sys/bus/usb/drivers/drivername 3# Find device number in /sys/bus/usb/drivers/drivername
3# Edit this file to update the driver numer and name 4# Edit this file to update the driver numer and name
4# Example test for uvcvideo driver 5# Example test for uvcvideo driver
diff --git a/tools/testing/selftests/media_tests/open_loop_test.sh b/tools/testing/selftests/media_tests/open_loop_test.sh
index dcd3c17efc17..d4c0179bbe2c 100755
--- a/tools/testing/selftests/media_tests/open_loop_test.sh
+++ b/tools/testing/selftests/media_tests/open_loop_test.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2 i=0 3 i=0
3file=/dev/media$1 4file=/dev/media$1
4 while :; do 5 while :; do
diff --git a/tools/testing/selftests/membarrier/membarrier_test.c b/tools/testing/selftests/membarrier/membarrier_test.c
index 21399fcf1a59..9e674d9514d1 100644
--- a/tools/testing/selftests/membarrier/membarrier_test.c
+++ b/tools/testing/selftests/membarrier/membarrier_test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2#include <linux/membarrier.h> 3#include <linux/membarrier.h>
3#include <syscall.h> 4#include <syscall.h>
diff --git a/tools/testing/selftests/memfd/Makefile b/tools/testing/selftests/memfd/Makefile
index ad8a0897e47f..3926a0409dda 100644
--- a/tools/testing/selftests/memfd/Makefile
+++ b/tools/testing/selftests/memfd/Makefile
@@ -1,9 +1,10 @@
1# SPDX-License-Identifier: GPL-2.0
1CFLAGS += -D_FILE_OFFSET_BITS=64 2CFLAGS += -D_FILE_OFFSET_BITS=64
2CFLAGS += -I../../../../include/uapi/ 3CFLAGS += -I../../../../include/uapi/
3CFLAGS += -I../../../../include/ 4CFLAGS += -I../../../../include/
4CFLAGS += -I../../../../usr/include/ 5CFLAGS += -I../../../../usr/include/
5 6
6TEST_PROGS := run_fuse_test.sh 7TEST_PROGS := run_tests.sh
7TEST_GEN_FILES := memfd_test fuse_mnt fuse_test 8TEST_GEN_FILES := memfd_test fuse_mnt fuse_test
8 9
9fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags) 10fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags)
diff --git a/tools/testing/selftests/memfd/fuse_mnt.c b/tools/testing/selftests/memfd/fuse_mnt.c
index feacf1280fcd..6936f2a001f3 100644
--- a/tools/testing/selftests/memfd/fuse_mnt.c
+++ b/tools/testing/selftests/memfd/fuse_mnt.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * memfd test file-system 3 * memfd test file-system
3 * This file uses FUSE to create a dummy file-system with only one file /memfd. 4 * This file uses FUSE to create a dummy file-system with only one file /memfd.
diff --git a/tools/testing/selftests/memfd/fuse_test.c b/tools/testing/selftests/memfd/fuse_test.c
index 67908b18f035..1ccb7a3eb14b 100644
--- a/tools/testing/selftests/memfd/fuse_test.c
+++ b/tools/testing/selftests/memfd/fuse_test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * memfd GUP test-case 3 * memfd GUP test-case
3 * This tests memfd interactions with get_user_pages(). We require the 4 * This tests memfd interactions with get_user_pages(). We require the
@@ -33,7 +34,7 @@
33#include <unistd.h> 34#include <unistd.h>
34 35
35#define MFD_DEF_SIZE 8192 36#define MFD_DEF_SIZE 8192
36#define STACK_SIZE 65535 37#define STACK_SIZE 65536
37 38
38static int sys_memfd_create(const char *name, 39static int sys_memfd_create(const char *name,
39 unsigned int flags) 40 unsigned int flags)
diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c
index 26546892cd54..132a54f74e88 100644
--- a/tools/testing/selftests/memfd/memfd_test.c
+++ b/tools/testing/selftests/memfd/memfd_test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2#define __EXPORTED_HEADERS__ 3#define __EXPORTED_HEADERS__
3 4
@@ -18,12 +19,48 @@
18#include <sys/wait.h> 19#include <sys/wait.h>
19#include <unistd.h> 20#include <unistd.h>
20 21
22#define MEMFD_STR "memfd:"
23#define SHARED_FT_STR "(shared file-table)"
24
21#define MFD_DEF_SIZE 8192 25#define MFD_DEF_SIZE 8192
22#define STACK_SIZE 65536 26#define STACK_SIZE 65536
23 27
28/*
29 * Default is not to test hugetlbfs
30 */
31static int hugetlbfs_test;
32static size_t mfd_def_size = MFD_DEF_SIZE;
33
34/*
35 * Copied from mlock2-tests.c
36 */
37static unsigned long default_huge_page_size(void)
38{
39 unsigned long hps = 0;
40 char *line = NULL;
41 size_t linelen = 0;
42 FILE *f = fopen("/proc/meminfo", "r");
43
44 if (!f)
45 return 0;
46 while (getline(&line, &linelen, f) > 0) {
47 if (sscanf(line, "Hugepagesize: %lu kB", &hps) == 1) {
48 hps <<= 10;
49 break;
50 }
51 }
52
53 free(line);
54 fclose(f);
55 return hps;
56}
57
24static int sys_memfd_create(const char *name, 58static int sys_memfd_create(const char *name,
25 unsigned int flags) 59 unsigned int flags)
26{ 60{
61 if (hugetlbfs_test)
62 flags |= MFD_HUGETLB;
63
27 return syscall(__NR_memfd_create, name, flags); 64 return syscall(__NR_memfd_create, name, flags);
28} 65}
29 66
@@ -150,7 +187,7 @@ static void *mfd_assert_mmap_shared(int fd)
150 void *p; 187 void *p;
151 188
152 p = mmap(NULL, 189 p = mmap(NULL,
153 MFD_DEF_SIZE, 190 mfd_def_size,
154 PROT_READ | PROT_WRITE, 191 PROT_READ | PROT_WRITE,
155 MAP_SHARED, 192 MAP_SHARED,
156 fd, 193 fd,
@@ -168,7 +205,7 @@ static void *mfd_assert_mmap_private(int fd)
168 void *p; 205 void *p;
169 206
170 p = mmap(NULL, 207 p = mmap(NULL,
171 MFD_DEF_SIZE, 208 mfd_def_size,
172 PROT_READ, 209 PROT_READ,
173 MAP_PRIVATE, 210 MAP_PRIVATE,
174 fd, 211 fd,
@@ -223,7 +260,7 @@ static void mfd_assert_read(int fd)
223 260
224 /* verify PROT_READ *is* allowed */ 261 /* verify PROT_READ *is* allowed */
225 p = mmap(NULL, 262 p = mmap(NULL,
226 MFD_DEF_SIZE, 263 mfd_def_size,
227 PROT_READ, 264 PROT_READ,
228 MAP_PRIVATE, 265 MAP_PRIVATE,
229 fd, 266 fd,
@@ -232,11 +269,11 @@ static void mfd_assert_read(int fd)
232 printf("mmap() failed: %m\n"); 269 printf("mmap() failed: %m\n");
233 abort(); 270 abort();
234 } 271 }
235 munmap(p, MFD_DEF_SIZE); 272 munmap(p, mfd_def_size);
236 273
237 /* verify MAP_PRIVATE is *always* allowed (even writable) */ 274 /* verify MAP_PRIVATE is *always* allowed (even writable) */
238 p = mmap(NULL, 275 p = mmap(NULL,
239 MFD_DEF_SIZE, 276 mfd_def_size,
240 PROT_READ | PROT_WRITE, 277 PROT_READ | PROT_WRITE,
241 MAP_PRIVATE, 278 MAP_PRIVATE,
242 fd, 279 fd,
@@ -245,7 +282,7 @@ static void mfd_assert_read(int fd)
245 printf("mmap() failed: %m\n"); 282 printf("mmap() failed: %m\n");
246 abort(); 283 abort();
247 } 284 }
248 munmap(p, MFD_DEF_SIZE); 285 munmap(p, mfd_def_size);
249} 286}
250 287
251static void mfd_assert_write(int fd) 288static void mfd_assert_write(int fd)
@@ -254,16 +291,22 @@ static void mfd_assert_write(int fd)
254 void *p; 291 void *p;
255 int r; 292 int r;
256 293
257 /* verify write() succeeds */ 294 /*
258 l = write(fd, "\0\0\0\0", 4); 295 * huegtlbfs does not support write, but we want to
259 if (l != 4) { 296 * verify everything else here.
260 printf("write() failed: %m\n"); 297 */
261 abort(); 298 if (!hugetlbfs_test) {
299 /* verify write() succeeds */
300 l = write(fd, "\0\0\0\0", 4);
301 if (l != 4) {
302 printf("write() failed: %m\n");
303 abort();
304 }
262 } 305 }
263 306
264 /* verify PROT_READ | PROT_WRITE is allowed */ 307 /* verify PROT_READ | PROT_WRITE is allowed */
265 p = mmap(NULL, 308 p = mmap(NULL,
266 MFD_DEF_SIZE, 309 mfd_def_size,
267 PROT_READ | PROT_WRITE, 310 PROT_READ | PROT_WRITE,
268 MAP_SHARED, 311 MAP_SHARED,
269 fd, 312 fd,
@@ -273,11 +316,11 @@ static void mfd_assert_write(int fd)
273 abort(); 316 abort();
274 } 317 }
275 *(char *)p = 0; 318 *(char *)p = 0;
276 munmap(p, MFD_DEF_SIZE); 319 munmap(p, mfd_def_size);
277 320
278 /* verify PROT_WRITE is allowed */ 321 /* verify PROT_WRITE is allowed */
279 p = mmap(NULL, 322 p = mmap(NULL,
280 MFD_DEF_SIZE, 323 mfd_def_size,
281 PROT_WRITE, 324 PROT_WRITE,
282 MAP_SHARED, 325 MAP_SHARED,
283 fd, 326 fd,
@@ -287,12 +330,12 @@ static void mfd_assert_write(int fd)
287 abort(); 330 abort();
288 } 331 }
289 *(char *)p = 0; 332 *(char *)p = 0;
290 munmap(p, MFD_DEF_SIZE); 333 munmap(p, mfd_def_size);
291 334
292 /* verify PROT_READ with MAP_SHARED is allowed and a following 335 /* verify PROT_READ with MAP_SHARED is allowed and a following
293 * mprotect(PROT_WRITE) allows writing */ 336 * mprotect(PROT_WRITE) allows writing */
294 p = mmap(NULL, 337 p = mmap(NULL,
295 MFD_DEF_SIZE, 338 mfd_def_size,
296 PROT_READ, 339 PROT_READ,
297 MAP_SHARED, 340 MAP_SHARED,
298 fd, 341 fd,
@@ -302,20 +345,20 @@ static void mfd_assert_write(int fd)
302 abort(); 345 abort();
303 } 346 }
304 347
305 r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE); 348 r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
306 if (r < 0) { 349 if (r < 0) {
307 printf("mprotect() failed: %m\n"); 350 printf("mprotect() failed: %m\n");
308 abort(); 351 abort();
309 } 352 }
310 353
311 *(char *)p = 0; 354 *(char *)p = 0;
312 munmap(p, MFD_DEF_SIZE); 355 munmap(p, mfd_def_size);
313 356
314 /* verify PUNCH_HOLE works */ 357 /* verify PUNCH_HOLE works */
315 r = fallocate(fd, 358 r = fallocate(fd,
316 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 359 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
317 0, 360 0,
318 MFD_DEF_SIZE); 361 mfd_def_size);
319 if (r < 0) { 362 if (r < 0) {
320 printf("fallocate(PUNCH_HOLE) failed: %m\n"); 363 printf("fallocate(PUNCH_HOLE) failed: %m\n");
321 abort(); 364 abort();
@@ -337,7 +380,7 @@ static void mfd_fail_write(int fd)
337 380
338 /* verify PROT_READ | PROT_WRITE is not allowed */ 381 /* verify PROT_READ | PROT_WRITE is not allowed */
339 p = mmap(NULL, 382 p = mmap(NULL,
340 MFD_DEF_SIZE, 383 mfd_def_size,
341 PROT_READ | PROT_WRITE, 384 PROT_READ | PROT_WRITE,
342 MAP_SHARED, 385 MAP_SHARED,
343 fd, 386 fd,
@@ -349,7 +392,7 @@ static void mfd_fail_write(int fd)
349 392
350 /* verify PROT_WRITE is not allowed */ 393 /* verify PROT_WRITE is not allowed */
351 p = mmap(NULL, 394 p = mmap(NULL,
352 MFD_DEF_SIZE, 395 mfd_def_size,
353 PROT_WRITE, 396 PROT_WRITE,
354 MAP_SHARED, 397 MAP_SHARED,
355 fd, 398 fd,
@@ -362,13 +405,13 @@ static void mfd_fail_write(int fd)
362 /* Verify PROT_READ with MAP_SHARED with a following mprotect is not 405 /* Verify PROT_READ with MAP_SHARED with a following mprotect is not
363 * allowed. Note that for r/w the kernel already prevents the mmap. */ 406 * allowed. Note that for r/w the kernel already prevents the mmap. */
364 p = mmap(NULL, 407 p = mmap(NULL,
365 MFD_DEF_SIZE, 408 mfd_def_size,
366 PROT_READ, 409 PROT_READ,
367 MAP_SHARED, 410 MAP_SHARED,
368 fd, 411 fd,
369 0); 412 0);
370 if (p != MAP_FAILED) { 413 if (p != MAP_FAILED) {
371 r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE); 414 r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
372 if (r >= 0) { 415 if (r >= 0) {
373 printf("mmap()+mprotect() didn't fail as expected\n"); 416 printf("mmap()+mprotect() didn't fail as expected\n");
374 abort(); 417 abort();
@@ -379,7 +422,7 @@ static void mfd_fail_write(int fd)
379 r = fallocate(fd, 422 r = fallocate(fd,
380 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 423 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
381 0, 424 0,
382 MFD_DEF_SIZE); 425 mfd_def_size);
383 if (r >= 0) { 426 if (r >= 0) {
384 printf("fallocate(PUNCH_HOLE) didn't fail as expected\n"); 427 printf("fallocate(PUNCH_HOLE) didn't fail as expected\n");
385 abort(); 428 abort();
@@ -390,13 +433,13 @@ static void mfd_assert_shrink(int fd)
390{ 433{
391 int r, fd2; 434 int r, fd2;
392 435
393 r = ftruncate(fd, MFD_DEF_SIZE / 2); 436 r = ftruncate(fd, mfd_def_size / 2);
394 if (r < 0) { 437 if (r < 0) {
395 printf("ftruncate(SHRINK) failed: %m\n"); 438 printf("ftruncate(SHRINK) failed: %m\n");
396 abort(); 439 abort();
397 } 440 }
398 441
399 mfd_assert_size(fd, MFD_DEF_SIZE / 2); 442 mfd_assert_size(fd, mfd_def_size / 2);
400 443
401 fd2 = mfd_assert_open(fd, 444 fd2 = mfd_assert_open(fd,
402 O_RDWR | O_CREAT | O_TRUNC, 445 O_RDWR | O_CREAT | O_TRUNC,
@@ -410,7 +453,7 @@ static void mfd_fail_shrink(int fd)
410{ 453{
411 int r; 454 int r;
412 455
413 r = ftruncate(fd, MFD_DEF_SIZE / 2); 456 r = ftruncate(fd, mfd_def_size / 2);
414 if (r >= 0) { 457 if (r >= 0) {
415 printf("ftruncate(SHRINK) didn't fail as expected\n"); 458 printf("ftruncate(SHRINK) didn't fail as expected\n");
416 abort(); 459 abort();
@@ -425,31 +468,31 @@ static void mfd_assert_grow(int fd)
425{ 468{
426 int r; 469 int r;
427 470
428 r = ftruncate(fd, MFD_DEF_SIZE * 2); 471 r = ftruncate(fd, mfd_def_size * 2);
429 if (r < 0) { 472 if (r < 0) {
430 printf("ftruncate(GROW) failed: %m\n"); 473 printf("ftruncate(GROW) failed: %m\n");
431 abort(); 474 abort();
432 } 475 }
433 476
434 mfd_assert_size(fd, MFD_DEF_SIZE * 2); 477 mfd_assert_size(fd, mfd_def_size * 2);
435 478
436 r = fallocate(fd, 479 r = fallocate(fd,
437 0, 480 0,
438 0, 481 0,
439 MFD_DEF_SIZE * 4); 482 mfd_def_size * 4);
440 if (r < 0) { 483 if (r < 0) {
441 printf("fallocate(ALLOC) failed: %m\n"); 484 printf("fallocate(ALLOC) failed: %m\n");
442 abort(); 485 abort();
443 } 486 }
444 487
445 mfd_assert_size(fd, MFD_DEF_SIZE * 4); 488 mfd_assert_size(fd, mfd_def_size * 4);
446} 489}
447 490
448static void mfd_fail_grow(int fd) 491static void mfd_fail_grow(int fd)
449{ 492{
450 int r; 493 int r;
451 494
452 r = ftruncate(fd, MFD_DEF_SIZE * 2); 495 r = ftruncate(fd, mfd_def_size * 2);
453 if (r >= 0) { 496 if (r >= 0) {
454 printf("ftruncate(GROW) didn't fail as expected\n"); 497 printf("ftruncate(GROW) didn't fail as expected\n");
455 abort(); 498 abort();
@@ -458,7 +501,7 @@ static void mfd_fail_grow(int fd)
458 r = fallocate(fd, 501 r = fallocate(fd,
459 0, 502 0,
460 0, 503 0,
461 MFD_DEF_SIZE * 4); 504 mfd_def_size * 4);
462 if (r >= 0) { 505 if (r >= 0) {
463 printf("fallocate(ALLOC) didn't fail as expected\n"); 506 printf("fallocate(ALLOC) didn't fail as expected\n");
464 abort(); 507 abort();
@@ -467,25 +510,37 @@ static void mfd_fail_grow(int fd)
467 510
468static void mfd_assert_grow_write(int fd) 511static void mfd_assert_grow_write(int fd)
469{ 512{
470 static char buf[MFD_DEF_SIZE * 8]; 513 static char *buf;
471 ssize_t l; 514 ssize_t l;
472 515
473 l = pwrite(fd, buf, sizeof(buf), 0); 516 buf = malloc(mfd_def_size * 8);
474 if (l != sizeof(buf)) { 517 if (!buf) {
518 printf("malloc(%zu) failed: %m\n", mfd_def_size * 8);
519 abort();
520 }
521
522 l = pwrite(fd, buf, mfd_def_size * 8, 0);
523 if (l != (mfd_def_size * 8)) {
475 printf("pwrite() failed: %m\n"); 524 printf("pwrite() failed: %m\n");
476 abort(); 525 abort();
477 } 526 }
478 527
479 mfd_assert_size(fd, MFD_DEF_SIZE * 8); 528 mfd_assert_size(fd, mfd_def_size * 8);
480} 529}
481 530
482static void mfd_fail_grow_write(int fd) 531static void mfd_fail_grow_write(int fd)
483{ 532{
484 static char buf[MFD_DEF_SIZE * 8]; 533 static char *buf;
485 ssize_t l; 534 ssize_t l;
486 535
487 l = pwrite(fd, buf, sizeof(buf), 0); 536 buf = malloc(mfd_def_size * 8);
488 if (l == sizeof(buf)) { 537 if (!buf) {
538 printf("malloc(%zu) failed: %m\n", mfd_def_size * 8);
539 abort();
540 }
541
542 l = pwrite(fd, buf, mfd_def_size * 8, 0);
543 if (l == (mfd_def_size * 8)) {
489 printf("pwrite() didn't fail as expected\n"); 544 printf("pwrite() didn't fail as expected\n");
490 abort(); 545 abort();
491 } 546 }
@@ -543,6 +598,8 @@ static void test_create(void)
543 char buf[2048]; 598 char buf[2048];
544 int fd; 599 int fd;
545 600
601 printf("%s CREATE\n", MEMFD_STR);
602
546 /* test NULL name */ 603 /* test NULL name */
547 mfd_fail_new(NULL, 0); 604 mfd_fail_new(NULL, 0);
548 605
@@ -570,13 +627,18 @@ static void test_create(void)
570 fd = mfd_assert_new("", 0, MFD_CLOEXEC); 627 fd = mfd_assert_new("", 0, MFD_CLOEXEC);
571 close(fd); 628 close(fd);
572 629
573 /* verify MFD_ALLOW_SEALING is allowed */ 630 if (!hugetlbfs_test) {
574 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING); 631 /* verify MFD_ALLOW_SEALING is allowed */
575 close(fd); 632 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING);
576 633 close(fd);
577 /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */ 634
578 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC); 635 /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */
579 close(fd); 636 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC);
637 close(fd);
638 } else {
639 /* sealing is not supported on hugetlbfs */
640 mfd_fail_new("", MFD_ALLOW_SEALING);
641 }
580} 642}
581 643
582/* 644/*
@@ -587,8 +649,14 @@ static void test_basic(void)
587{ 649{
588 int fd; 650 int fd;
589 651
652 /* hugetlbfs does not contain sealing support */
653 if (hugetlbfs_test)
654 return;
655
656 printf("%s BASIC\n", MEMFD_STR);
657
590 fd = mfd_assert_new("kern_memfd_basic", 658 fd = mfd_assert_new("kern_memfd_basic",
591 MFD_DEF_SIZE, 659 mfd_def_size,
592 MFD_CLOEXEC | MFD_ALLOW_SEALING); 660 MFD_CLOEXEC | MFD_ALLOW_SEALING);
593 661
594 /* add basic seals */ 662 /* add basic seals */
@@ -619,7 +687,7 @@ static void test_basic(void)
619 687
620 /* verify sealing does not work without MFD_ALLOW_SEALING */ 688 /* verify sealing does not work without MFD_ALLOW_SEALING */
621 fd = mfd_assert_new("kern_memfd_basic", 689 fd = mfd_assert_new("kern_memfd_basic",
622 MFD_DEF_SIZE, 690 mfd_def_size,
623 MFD_CLOEXEC); 691 MFD_CLOEXEC);
624 mfd_assert_has_seals(fd, F_SEAL_SEAL); 692 mfd_assert_has_seals(fd, F_SEAL_SEAL);
625 mfd_fail_add_seals(fd, F_SEAL_SHRINK | 693 mfd_fail_add_seals(fd, F_SEAL_SHRINK |
@@ -630,6 +698,28 @@ static void test_basic(void)
630} 698}
631 699
632/* 700/*
701 * hugetlbfs doesn't support seals or write, so just verify grow and shrink
702 * on a hugetlbfs file created via memfd_create.
703 */
704static void test_hugetlbfs_grow_shrink(void)
705{
706 int fd;
707
708 printf("%s HUGETLBFS-GROW-SHRINK\n", MEMFD_STR);
709
710 fd = mfd_assert_new("kern_memfd_seal_write",
711 mfd_def_size,
712 MFD_CLOEXEC);
713
714 mfd_assert_read(fd);
715 mfd_assert_write(fd);
716 mfd_assert_shrink(fd);
717 mfd_assert_grow(fd);
718
719 close(fd);
720}
721
722/*
633 * Test SEAL_WRITE 723 * Test SEAL_WRITE
634 * Test whether SEAL_WRITE actually prevents modifications. 724 * Test whether SEAL_WRITE actually prevents modifications.
635 */ 725 */
@@ -637,8 +727,17 @@ static void test_seal_write(void)
637{ 727{
638 int fd; 728 int fd;
639 729
730 /*
731 * hugetlbfs does not contain sealing or write support. Just test
732 * basic grow and shrink via test_hugetlbfs_grow_shrink.
733 */
734 if (hugetlbfs_test)
735 return test_hugetlbfs_grow_shrink();
736
737 printf("%s SEAL-WRITE\n", MEMFD_STR);
738
640 fd = mfd_assert_new("kern_memfd_seal_write", 739 fd = mfd_assert_new("kern_memfd_seal_write",
641 MFD_DEF_SIZE, 740 mfd_def_size,
642 MFD_CLOEXEC | MFD_ALLOW_SEALING); 741 MFD_CLOEXEC | MFD_ALLOW_SEALING);
643 mfd_assert_has_seals(fd, 0); 742 mfd_assert_has_seals(fd, 0);
644 mfd_assert_add_seals(fd, F_SEAL_WRITE); 743 mfd_assert_add_seals(fd, F_SEAL_WRITE);
@@ -661,8 +760,14 @@ static void test_seal_shrink(void)
661{ 760{
662 int fd; 761 int fd;
663 762
763 /* hugetlbfs does not contain sealing support */
764 if (hugetlbfs_test)
765 return;
766
767 printf("%s SEAL-SHRINK\n", MEMFD_STR);
768
664 fd = mfd_assert_new("kern_memfd_seal_shrink", 769 fd = mfd_assert_new("kern_memfd_seal_shrink",
665 MFD_DEF_SIZE, 770 mfd_def_size,
666 MFD_CLOEXEC | MFD_ALLOW_SEALING); 771 MFD_CLOEXEC | MFD_ALLOW_SEALING);
667 mfd_assert_has_seals(fd, 0); 772 mfd_assert_has_seals(fd, 0);
668 mfd_assert_add_seals(fd, F_SEAL_SHRINK); 773 mfd_assert_add_seals(fd, F_SEAL_SHRINK);
@@ -685,8 +790,14 @@ static void test_seal_grow(void)
685{ 790{
686 int fd; 791 int fd;
687 792
793 /* hugetlbfs does not contain sealing support */
794 if (hugetlbfs_test)
795 return;
796
797 printf("%s SEAL-GROW\n", MEMFD_STR);
798
688 fd = mfd_assert_new("kern_memfd_seal_grow", 799 fd = mfd_assert_new("kern_memfd_seal_grow",
689 MFD_DEF_SIZE, 800 mfd_def_size,
690 MFD_CLOEXEC | MFD_ALLOW_SEALING); 801 MFD_CLOEXEC | MFD_ALLOW_SEALING);
691 mfd_assert_has_seals(fd, 0); 802 mfd_assert_has_seals(fd, 0);
692 mfd_assert_add_seals(fd, F_SEAL_GROW); 803 mfd_assert_add_seals(fd, F_SEAL_GROW);
@@ -709,8 +820,14 @@ static void test_seal_resize(void)
709{ 820{
710 int fd; 821 int fd;
711 822
823 /* hugetlbfs does not contain sealing support */
824 if (hugetlbfs_test)
825 return;
826
827 printf("%s SEAL-RESIZE\n", MEMFD_STR);
828
712 fd = mfd_assert_new("kern_memfd_seal_resize", 829 fd = mfd_assert_new("kern_memfd_seal_resize",
713 MFD_DEF_SIZE, 830 mfd_def_size,
714 MFD_CLOEXEC | MFD_ALLOW_SEALING); 831 MFD_CLOEXEC | MFD_ALLOW_SEALING);
715 mfd_assert_has_seals(fd, 0); 832 mfd_assert_has_seals(fd, 0);
716 mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW); 833 mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
@@ -726,15 +843,52 @@ static void test_seal_resize(void)
726} 843}
727 844
728/* 845/*
846 * hugetlbfs does not support seals. Basic test to dup the memfd created
847 * fd and perform some basic operations on it.
848 */
849static void hugetlbfs_dup(char *b_suffix)
850{
851 int fd, fd2;
852
853 printf("%s HUGETLBFS-DUP %s\n", MEMFD_STR, b_suffix);
854
855 fd = mfd_assert_new("kern_memfd_share_dup",
856 mfd_def_size,
857 MFD_CLOEXEC);
858
859 fd2 = mfd_assert_dup(fd);
860
861 mfd_assert_read(fd);
862 mfd_assert_write(fd);
863
864 mfd_assert_shrink(fd2);
865 mfd_assert_grow(fd2);
866
867 close(fd2);
868 close(fd);
869}
870
871/*
729 * Test sharing via dup() 872 * Test sharing via dup()
730 * Test that seals are shared between dupped FDs and they're all equal. 873 * Test that seals are shared between dupped FDs and they're all equal.
731 */ 874 */
732static void test_share_dup(void) 875static void test_share_dup(char *banner, char *b_suffix)
733{ 876{
734 int fd, fd2; 877 int fd, fd2;
735 878
879 /*
880 * hugetlbfs does not contain sealing support. Perform some
881 * basic testing on dup'ed fd instead via hugetlbfs_dup.
882 */
883 if (hugetlbfs_test) {
884 hugetlbfs_dup(b_suffix);
885 return;
886 }
887
888 printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
889
736 fd = mfd_assert_new("kern_memfd_share_dup", 890 fd = mfd_assert_new("kern_memfd_share_dup",
737 MFD_DEF_SIZE, 891 mfd_def_size,
738 MFD_CLOEXEC | MFD_ALLOW_SEALING); 892 MFD_CLOEXEC | MFD_ALLOW_SEALING);
739 mfd_assert_has_seals(fd, 0); 893 mfd_assert_has_seals(fd, 0);
740 894
@@ -768,13 +922,19 @@ static void test_share_dup(void)
768 * Test sealing with active mmap()s 922 * Test sealing with active mmap()s
769 * Modifying seals is only allowed if no other mmap() refs exist. 923 * Modifying seals is only allowed if no other mmap() refs exist.
770 */ 924 */
771static void test_share_mmap(void) 925static void test_share_mmap(char *banner, char *b_suffix)
772{ 926{
773 int fd; 927 int fd;
774 void *p; 928 void *p;
775 929
930 /* hugetlbfs does not contain sealing support */
931 if (hugetlbfs_test)
932 return;
933
934 printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
935
776 fd = mfd_assert_new("kern_memfd_share_mmap", 936 fd = mfd_assert_new("kern_memfd_share_mmap",
777 MFD_DEF_SIZE, 937 mfd_def_size,
778 MFD_CLOEXEC | MFD_ALLOW_SEALING); 938 MFD_CLOEXEC | MFD_ALLOW_SEALING);
779 mfd_assert_has_seals(fd, 0); 939 mfd_assert_has_seals(fd, 0);
780 940
@@ -784,14 +944,40 @@ static void test_share_mmap(void)
784 mfd_assert_has_seals(fd, 0); 944 mfd_assert_has_seals(fd, 0);
785 mfd_assert_add_seals(fd, F_SEAL_SHRINK); 945 mfd_assert_add_seals(fd, F_SEAL_SHRINK);
786 mfd_assert_has_seals(fd, F_SEAL_SHRINK); 946 mfd_assert_has_seals(fd, F_SEAL_SHRINK);
787 munmap(p, MFD_DEF_SIZE); 947 munmap(p, mfd_def_size);
788 948
789 /* readable ref allows sealing */ 949 /* readable ref allows sealing */
790 p = mfd_assert_mmap_private(fd); 950 p = mfd_assert_mmap_private(fd);
791 mfd_assert_add_seals(fd, F_SEAL_WRITE); 951 mfd_assert_add_seals(fd, F_SEAL_WRITE);
792 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK); 952 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
793 munmap(p, MFD_DEF_SIZE); 953 munmap(p, mfd_def_size);
954
955 close(fd);
956}
957
958/*
959 * Basic test to make sure we can open the hugetlbfs fd via /proc and
960 * perform some simple operations on it.
961 */
962static void hugetlbfs_proc_open(char *b_suffix)
963{
964 int fd, fd2;
965
966 printf("%s HUGETLBFS-PROC-OPEN %s\n", MEMFD_STR, b_suffix);
794 967
968 fd = mfd_assert_new("kern_memfd_share_open",
969 mfd_def_size,
970 MFD_CLOEXEC);
971
972 fd2 = mfd_assert_open(fd, O_RDWR, 0);
973
974 mfd_assert_read(fd);
975 mfd_assert_write(fd);
976
977 mfd_assert_shrink(fd2);
978 mfd_assert_grow(fd2);
979
980 close(fd2);
795 close(fd); 981 close(fd);
796} 982}
797 983
@@ -801,12 +987,23 @@ static void test_share_mmap(void)
801 * This is *not* like dup(), but like a real separate open(). Make sure the 987 * This is *not* like dup(), but like a real separate open(). Make sure the
802 * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR. 988 * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
803 */ 989 */
804static void test_share_open(void) 990static void test_share_open(char *banner, char *b_suffix)
805{ 991{
806 int fd, fd2; 992 int fd, fd2;
807 993
994 /*
995 * hugetlbfs does not contain sealing support. So test basic
996 * functionality of using /proc fd via hugetlbfs_proc_open
997 */
998 if (hugetlbfs_test) {
999 hugetlbfs_proc_open(b_suffix);
1000 return;
1001 }
1002
1003 printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
1004
808 fd = mfd_assert_new("kern_memfd_share_open", 1005 fd = mfd_assert_new("kern_memfd_share_open",
809 MFD_DEF_SIZE, 1006 mfd_def_size,
810 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1007 MFD_CLOEXEC | MFD_ALLOW_SEALING);
811 mfd_assert_has_seals(fd, 0); 1008 mfd_assert_has_seals(fd, 0);
812 1009
@@ -841,13 +1038,19 @@ static void test_share_open(void)
841 * Test sharing via fork() 1038 * Test sharing via fork()
842 * Test whether seal-modifications work as expected with forked childs. 1039 * Test whether seal-modifications work as expected with forked childs.
843 */ 1040 */
844static void test_share_fork(void) 1041static void test_share_fork(char *banner, char *b_suffix)
845{ 1042{
846 int fd; 1043 int fd;
847 pid_t pid; 1044 pid_t pid;
848 1045
1046 /* hugetlbfs does not contain sealing support */
1047 if (hugetlbfs_test)
1048 return;
1049
1050 printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
1051
849 fd = mfd_assert_new("kern_memfd_share_fork", 1052 fd = mfd_assert_new("kern_memfd_share_fork",
850 MFD_DEF_SIZE, 1053 mfd_def_size,
851 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1054 MFD_CLOEXEC | MFD_ALLOW_SEALING);
852 mfd_assert_has_seals(fd, 0); 1055 mfd_assert_has_seals(fd, 0);
853 1056
@@ -870,40 +1073,40 @@ int main(int argc, char **argv)
870{ 1073{
871 pid_t pid; 1074 pid_t pid;
872 1075
873 printf("memfd: CREATE\n"); 1076 if (argc == 2) {
1077 if (!strcmp(argv[1], "hugetlbfs")) {
1078 unsigned long hpage_size = default_huge_page_size();
1079
1080 if (!hpage_size) {
1081 printf("Unable to determine huge page size\n");
1082 abort();
1083 }
1084
1085 hugetlbfs_test = 1;
1086 mfd_def_size = hpage_size * 2;
1087 }
1088 }
1089
874 test_create(); 1090 test_create();
875 printf("memfd: BASIC\n");
876 test_basic(); 1091 test_basic();
877 1092
878 printf("memfd: SEAL-WRITE\n");
879 test_seal_write(); 1093 test_seal_write();
880 printf("memfd: SEAL-SHRINK\n");
881 test_seal_shrink(); 1094 test_seal_shrink();
882 printf("memfd: SEAL-GROW\n");
883 test_seal_grow(); 1095 test_seal_grow();
884 printf("memfd: SEAL-RESIZE\n");
885 test_seal_resize(); 1096 test_seal_resize();
886 1097
887 printf("memfd: SHARE-DUP\n"); 1098 test_share_dup("SHARE-DUP", "");
888 test_share_dup(); 1099 test_share_mmap("SHARE-MMAP", "");
889 printf("memfd: SHARE-MMAP\n"); 1100 test_share_open("SHARE-OPEN", "");
890 test_share_mmap(); 1101 test_share_fork("SHARE-FORK", "");
891 printf("memfd: SHARE-OPEN\n");
892 test_share_open();
893 printf("memfd: SHARE-FORK\n");
894 test_share_fork();
895 1102
896 /* Run test-suite in a multi-threaded environment with a shared 1103 /* Run test-suite in a multi-threaded environment with a shared
897 * file-table. */ 1104 * file-table. */
898 pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM); 1105 pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM);
899 printf("memfd: SHARE-DUP (shared file-table)\n"); 1106 test_share_dup("SHARE-DUP", SHARED_FT_STR);
900 test_share_dup(); 1107 test_share_mmap("SHARE-MMAP", SHARED_FT_STR);
901 printf("memfd: SHARE-MMAP (shared file-table)\n"); 1108 test_share_open("SHARE-OPEN", SHARED_FT_STR);
902 test_share_mmap(); 1109 test_share_fork("SHARE-FORK", SHARED_FT_STR);
903 printf("memfd: SHARE-OPEN (shared file-table)\n");
904 test_share_open();
905 printf("memfd: SHARE-FORK (shared file-table)\n");
906 test_share_fork();
907 join_idle_thread(pid); 1110 join_idle_thread(pid);
908 1111
909 printf("memfd: DONE\n"); 1112 printf("memfd: DONE\n");
diff --git a/tools/testing/selftests/memfd/run_fuse_test.sh b/tools/testing/selftests/memfd/run_fuse_test.sh
index 69b930e1e041..407df68dfe27 100755
--- a/tools/testing/selftests/memfd/run_fuse_test.sh
+++ b/tools/testing/selftests/memfd/run_fuse_test.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2 3
3if test -d "./mnt" ; then 4if test -d "./mnt" ; then
4 fusermount -u ./mnt 5 fusermount -u ./mnt
diff --git a/tools/testing/selftests/memfd/run_tests.sh b/tools/testing/selftests/memfd/run_tests.sh
new file mode 100755
index 000000000000..daabb350697c
--- /dev/null
+++ b/tools/testing/selftests/memfd/run_tests.sh
@@ -0,0 +1,69 @@
1#!/bin/bash
2# please run as root
3
4#
5# Normal tests requiring no special resources
6#
7./run_fuse_test.sh
8./memfd_test
9
10#
11# To test memfd_create with hugetlbfs, there needs to be hpages_test
12# huge pages free. Attempt to allocate enough pages to test.
13#
14hpages_test=8
15
16#
17# Get count of free huge pages from /proc/meminfo
18#
19while read name size unit; do
20 if [ "$name" = "HugePages_Free:" ]; then
21 freepgs=$size
22 fi
23done < /proc/meminfo
24
25#
26# If not enough free huge pages for test, attempt to increase
27#
28if [ -n "$freepgs" ] && [ $freepgs -lt $hpages_test ]; then
29 nr_hugepgs=`cat /proc/sys/vm/nr_hugepages`
30 hpages_needed=`expr $hpages_test - $freepgs`
31
32 echo 3 > /proc/sys/vm/drop_caches
33 echo $(( $hpages_needed + $nr_hugepgs )) > /proc/sys/vm/nr_hugepages
34 if [ $? -ne 0 ]; then
35 echo "Please run this test as root"
36 exit 1
37 fi
38 while read name size unit; do
39 if [ "$name" = "HugePages_Free:" ]; then
40 freepgs=$size
41 fi
42 done < /proc/meminfo
43fi
44
45#
46# If still not enough huge pages available, exit. But, give back any huge
47# pages potentially allocated above.
48#
49if [ $freepgs -lt $hpages_test ]; then
50 # nr_hugepgs non-zero only if we attempted to increase
51 if [ -n "$nr_hugepgs" ]; then
52 echo $nr_hugepgs > /proc/sys/vm/nr_hugepages
53 fi
54 printf "Not enough huge pages available (%d < %d)\n" \
55 $freepgs $needpgs
56 exit 1
57fi
58
59#
60# Run the hugetlbfs test
61#
62./memfd_test hugetlbfs
63
64#
65# Give back any huge pages allocated for the test
66#
67if [ -n "$nr_hugepgs" ]; then
68 echo $nr_hugepgs > /proc/sys/vm/nr_hugepages
69fi
diff --git a/tools/testing/selftests/memory-hotplug/Makefile b/tools/testing/selftests/memory-hotplug/Makefile
index afb2624c7048..86636d207adf 100644
--- a/tools/testing/selftests/memory-hotplug/Makefile
+++ b/tools/testing/selftests/memory-hotplug/Makefile
@@ -1,12 +1,13 @@
1# SPDX-License-Identifier: GPL-2.0
1all: 2all:
2 3
3include ../lib.mk 4include ../lib.mk
4 5
5TEST_PROGS := mem-on-off-test.sh 6TEST_PROGS := mem-on-off-test.sh
6override RUN_TESTS := ./mem-on-off-test.sh -r 2 || echo "selftests: memory-hotplug [FAIL]" 7override RUN_TESTS := ./mem-on-off-test.sh -r 2 && echo "selftests: memory-hotplug [PASS]" || echo "selftests: memory-hotplug [FAIL]"
7override EMIT_TESTS := echo "$(RUN_TESTS)" 8override EMIT_TESTS := echo "$(RUN_TESTS)"
8 9
9run_full_test: 10run_full_test:
10 @/bin/bash ./mem-on-off-test.sh || echo "memory-hotplug selftests: [FAIL]" 11 @/bin/bash ./mem-on-off-test.sh && echo "memory-hotplug selftests: [PASS]" || echo "memory-hotplug selftests: [FAIL]"
11 12
12clean: 13clean:
diff --git a/tools/testing/selftests/memory-hotplug/mem-on-off-test.sh b/tools/testing/selftests/memory-hotplug/mem-on-off-test.sh
index 35025ce9ca66..ae2c790d0880 100755
--- a/tools/testing/selftests/memory-hotplug/mem-on-off-test.sh
+++ b/tools/testing/selftests/memory-hotplug/mem-on-off-test.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2 3
3SYSFS= 4SYSFS=
4 5
diff --git a/tools/testing/selftests/mount/Makefile b/tools/testing/selftests/mount/Makefile
index 9093d7ffe87f..e094f71c6dbc 100644
--- a/tools/testing/selftests/mount/Makefile
+++ b/tools/testing/selftests/mount/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# Makefile for mount selftests. 2# Makefile for mount selftests.
2CFLAGS = -Wall \ 3CFLAGS = -Wall \
3 -O2 4 -O2
diff --git a/tools/testing/selftests/mount/unprivileged-remount-test.c b/tools/testing/selftests/mount/unprivileged-remount-test.c
index 517785052f1c..584dc6bc3b06 100644
--- a/tools/testing/selftests/mount/unprivileged-remount-test.c
+++ b/tools/testing/selftests/mount/unprivileged-remount-test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2#include <sched.h> 3#include <sched.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/testing/selftests/mqueue/Makefile b/tools/testing/selftests/mqueue/Makefile
index 79a664aeb8d7..743d3f9e5918 100644
--- a/tools/testing/selftests/mqueue/Makefile
+++ b/tools/testing/selftests/mqueue/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1CFLAGS += -O2 2CFLAGS += -O2
2LDLIBS = -lrt -lpthread -lpopt 3LDLIBS = -lrt -lpthread -lpopt
3TEST_GEN_PROGS := mq_open_tests mq_perf_tests 4TEST_GEN_PROGS := mq_open_tests mq_perf_tests
@@ -5,8 +6,8 @@ TEST_GEN_PROGS := mq_open_tests mq_perf_tests
5include ../lib.mk 6include ../lib.mk
6 7
7override define RUN_TESTS 8override define RUN_TESTS
8 @./mq_open_tests /test1 || echo "selftests: mq_open_tests [FAIL]" 9 @$(OUTPUT)/mq_open_tests /test1 || echo "selftests: mq_open_tests [FAIL]"
9 @./mq_perf_tests || echo "selftests: mq_perf_tests [FAIL]" 10 @$(OUTPUT)/mq_perf_tests || echo "selftests: mq_perf_tests [FAIL]"
10endef 11endef
11 12
12override define EMIT_TESTS 13override define EMIT_TESTS
diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore
index afe109e5508a..c612d6e38c62 100644
--- a/tools/testing/selftests/net/.gitignore
+++ b/tools/testing/selftests/net/.gitignore
@@ -1,3 +1,4 @@
1msg_zerocopy
1socket 2socket
2psock_fanout 3psock_fanout
3psock_tpacket 4psock_tpacket
@@ -5,3 +6,4 @@ reuseport_bpf
5reuseport_bpf_cpu 6reuseport_bpf_cpu
6reuseport_bpf_numa 7reuseport_bpf_numa
7reuseport_dualstack 8reuseport_dualstack
9reuseaddr_conflict
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index f6c9dbf478f8..500c74db746c 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -1,13 +1,14 @@
1# SPDX-License-Identifier: GPL-2.0
1# Makefile for net selftests 2# Makefile for net selftests
2 3
3CFLAGS = -Wall -Wl,--no-as-needed -O2 -g 4CFLAGS = -Wall -Wl,--no-as-needed -O2 -g
4CFLAGS += -I../../../../usr/include/ 5CFLAGS += -I../../../../usr/include/
5 6
6TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh 7TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh
7TEST_GEN_FILES = socket 8TEST_GEN_FILES = socket
8TEST_GEN_FILES += psock_fanout psock_tpacket 9TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy
9TEST_GEN_FILES += reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa 10TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
10TEST_GEN_FILES += reuseport_dualstack 11TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict
11 12
12include ../lib.mk 13include ../lib.mk
13 14
diff --git a/tools/testing/selftests/net/msg_zerocopy.c b/tools/testing/selftests/net/msg_zerocopy.c
new file mode 100644
index 000000000000..3ab6ec403905
--- /dev/null
+++ b/tools/testing/selftests/net/msg_zerocopy.c
@@ -0,0 +1,697 @@
1/* Evaluate MSG_ZEROCOPY
2 *
3 * Send traffic between two processes over one of the supported
4 * protocols and modes:
5 *
6 * PF_INET/PF_INET6
7 * - SOCK_STREAM
8 * - SOCK_DGRAM
9 * - SOCK_DGRAM with UDP_CORK
10 * - SOCK_RAW
11 * - SOCK_RAW with IP_HDRINCL
12 *
13 * PF_PACKET
14 * - SOCK_DGRAM
15 * - SOCK_RAW
16 *
17 * Start this program on two connected hosts, one in send mode and
18 * the other with option '-r' to put it in receiver mode.
19 *
20 * If zerocopy mode ('-z') is enabled, the sender will verify that
21 * the kernel queues completions on the error queue for all zerocopy
22 * transfers.
23 */
24
25#define _GNU_SOURCE
26
27#include <arpa/inet.h>
28#include <error.h>
29#include <errno.h>
30#include <limits.h>
31#include <linux/errqueue.h>
32#include <linux/if_packet.h>
33#include <linux/ipv6.h>
34#include <linux/socket.h>
35#include <linux/sockios.h>
36#include <net/ethernet.h>
37#include <net/if.h>
38#include <netinet/ip.h>
39#include <netinet/ip6.h>
40#include <netinet/tcp.h>
41#include <netinet/udp.h>
42#include <poll.h>
43#include <sched.h>
44#include <stdbool.h>
45#include <stdio.h>
46#include <stdint.h>
47#include <stdlib.h>
48#include <string.h>
49#include <sys/ioctl.h>
50#include <sys/socket.h>
51#include <sys/stat.h>
52#include <sys/time.h>
53#include <sys/types.h>
54#include <sys/wait.h>
55#include <unistd.h>
56
57#ifndef SO_EE_ORIGIN_ZEROCOPY
58#define SO_EE_ORIGIN_ZEROCOPY 5
59#endif
60
61#ifndef SO_ZEROCOPY
62#define SO_ZEROCOPY 60
63#endif
64
65#ifndef SO_EE_CODE_ZEROCOPY_COPIED
66#define SO_EE_CODE_ZEROCOPY_COPIED 1
67#endif
68
69#ifndef MSG_ZEROCOPY
70#define MSG_ZEROCOPY 0x4000000
71#endif
72
73static int cfg_cork;
74static bool cfg_cork_mixed;
75static int cfg_cpu = -1; /* default: pin to last cpu */
76static int cfg_family = PF_UNSPEC;
77static int cfg_ifindex = 1;
78static int cfg_payload_len;
79static int cfg_port = 8000;
80static bool cfg_rx;
81static int cfg_runtime_ms = 4200;
82static int cfg_verbose;
83static int cfg_waittime_ms = 500;
84static bool cfg_zerocopy;
85
86static socklen_t cfg_alen;
87static struct sockaddr_storage cfg_dst_addr;
88static struct sockaddr_storage cfg_src_addr;
89
90static char payload[IP_MAXPACKET];
91static long packets, bytes, completions, expected_completions;
92static int zerocopied = -1;
93static uint32_t next_completion;
94
95static unsigned long gettimeofday_ms(void)
96{
97 struct timeval tv;
98
99 gettimeofday(&tv, NULL);
100 return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
101}
102
103static uint16_t get_ip_csum(const uint16_t *start, int num_words)
104{
105 unsigned long sum = 0;
106 int i;
107
108 for (i = 0; i < num_words; i++)
109 sum += start[i];
110
111 while (sum >> 16)
112 sum = (sum & 0xFFFF) + (sum >> 16);
113
114 return ~sum;
115}
116
117static int do_setcpu(int cpu)
118{
119 cpu_set_t mask;
120
121 CPU_ZERO(&mask);
122 CPU_SET(cpu, &mask);
123 if (sched_setaffinity(0, sizeof(mask), &mask))
124 error(1, 0, "setaffinity %d", cpu);
125
126 if (cfg_verbose)
127 fprintf(stderr, "cpu: %u\n", cpu);
128
129 return 0;
130}
131
132static void do_setsockopt(int fd, int level, int optname, int val)
133{
134 if (setsockopt(fd, level, optname, &val, sizeof(val)))
135 error(1, errno, "setsockopt %d.%d: %d", level, optname, val);
136}
137
138static int do_poll(int fd, int events)
139{
140 struct pollfd pfd;
141 int ret;
142
143 pfd.events = events;
144 pfd.revents = 0;
145 pfd.fd = fd;
146
147 ret = poll(&pfd, 1, cfg_waittime_ms);
148 if (ret == -1)
149 error(1, errno, "poll");
150
151 return ret && (pfd.revents & events);
152}
153
154static int do_accept(int fd)
155{
156 int fda = fd;
157
158 fd = accept(fda, NULL, NULL);
159 if (fd == -1)
160 error(1, errno, "accept");
161 if (close(fda))
162 error(1, errno, "close listen sock");
163
164 return fd;
165}
166
167static bool do_sendmsg(int fd, struct msghdr *msg, bool do_zerocopy)
168{
169 int ret, len, i, flags;
170
171 len = 0;
172 for (i = 0; i < msg->msg_iovlen; i++)
173 len += msg->msg_iov[i].iov_len;
174
175 flags = MSG_DONTWAIT;
176 if (do_zerocopy)
177 flags |= MSG_ZEROCOPY;
178
179 ret = sendmsg(fd, msg, flags);
180 if (ret == -1 && errno == EAGAIN)
181 return false;
182 if (ret == -1)
183 error(1, errno, "send");
184 if (cfg_verbose && ret != len)
185 fprintf(stderr, "send: ret=%u != %u\n", ret, len);
186
187 if (len) {
188 packets++;
189 bytes += ret;
190 if (do_zerocopy && ret)
191 expected_completions++;
192 }
193
194 return true;
195}
196
197static void do_sendmsg_corked(int fd, struct msghdr *msg)
198{
199 bool do_zerocopy = cfg_zerocopy;
200 int i, payload_len, extra_len;
201
202 /* split up the packet. for non-multiple, make first buffer longer */
203 payload_len = cfg_payload_len / cfg_cork;
204 extra_len = cfg_payload_len - (cfg_cork * payload_len);
205
206 do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 1);
207
208 for (i = 0; i < cfg_cork; i++) {
209
210 /* in mixed-frags mode, alternate zerocopy and copy frags
211 * start with non-zerocopy, to ensure attach later works
212 */
213 if (cfg_cork_mixed)
214 do_zerocopy = (i & 1);
215
216 msg->msg_iov[0].iov_len = payload_len + extra_len;
217 extra_len = 0;
218
219 do_sendmsg(fd, msg, do_zerocopy);
220 }
221
222 do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 0);
223}
224
225static int setup_iph(struct iphdr *iph, uint16_t payload_len)
226{
227 struct sockaddr_in *daddr = (void *) &cfg_dst_addr;
228 struct sockaddr_in *saddr = (void *) &cfg_src_addr;
229
230 memset(iph, 0, sizeof(*iph));
231
232 iph->version = 4;
233 iph->tos = 0;
234 iph->ihl = 5;
235 iph->ttl = 2;
236 iph->saddr = saddr->sin_addr.s_addr;
237 iph->daddr = daddr->sin_addr.s_addr;
238 iph->protocol = IPPROTO_EGP;
239 iph->tot_len = htons(sizeof(*iph) + payload_len);
240 iph->check = get_ip_csum((void *) iph, iph->ihl << 1);
241
242 return sizeof(*iph);
243}
244
245static int setup_ip6h(struct ipv6hdr *ip6h, uint16_t payload_len)
246{
247 struct sockaddr_in6 *daddr = (void *) &cfg_dst_addr;
248 struct sockaddr_in6 *saddr = (void *) &cfg_src_addr;
249
250 memset(ip6h, 0, sizeof(*ip6h));
251
252 ip6h->version = 6;
253 ip6h->payload_len = htons(payload_len);
254 ip6h->nexthdr = IPPROTO_EGP;
255 ip6h->hop_limit = 2;
256 ip6h->saddr = saddr->sin6_addr;
257 ip6h->daddr = daddr->sin6_addr;
258
259 return sizeof(*ip6h);
260}
261
262static void setup_sockaddr(int domain, const char *str_addr, void *sockaddr)
263{
264 struct sockaddr_in6 *addr6 = (void *) sockaddr;
265 struct sockaddr_in *addr4 = (void *) sockaddr;
266
267 switch (domain) {
268 case PF_INET:
269 addr4->sin_family = AF_INET;
270 addr4->sin_port = htons(cfg_port);
271 if (inet_pton(AF_INET, str_addr, &(addr4->sin_addr)) != 1)
272 error(1, 0, "ipv4 parse error: %s", str_addr);
273 break;
274 case PF_INET6:
275 addr6->sin6_family = AF_INET6;
276 addr6->sin6_port = htons(cfg_port);
277 if (inet_pton(AF_INET6, str_addr, &(addr6->sin6_addr)) != 1)
278 error(1, 0, "ipv6 parse error: %s", str_addr);
279 break;
280 default:
281 error(1, 0, "illegal domain");
282 }
283}
284
285static int do_setup_tx(int domain, int type, int protocol)
286{
287 int fd;
288
289 fd = socket(domain, type, protocol);
290 if (fd == -1)
291 error(1, errno, "socket t");
292
293 do_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, 1 << 21);
294 if (cfg_zerocopy)
295 do_setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, 1);
296
297 if (domain != PF_PACKET)
298 if (connect(fd, (void *) &cfg_dst_addr, cfg_alen))
299 error(1, errno, "connect");
300
301 return fd;
302}
303
304static bool do_recv_completion(int fd)
305{
306 struct sock_extended_err *serr;
307 struct msghdr msg = {};
308 struct cmsghdr *cm;
309 uint32_t hi, lo, range;
310 int ret, zerocopy;
311 char control[100];
312
313 msg.msg_control = control;
314 msg.msg_controllen = sizeof(control);
315
316 ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
317 if (ret == -1 && errno == EAGAIN)
318 return false;
319 if (ret == -1)
320 error(1, errno, "recvmsg notification");
321 if (msg.msg_flags & MSG_CTRUNC)
322 error(1, errno, "recvmsg notification: truncated");
323
324 cm = CMSG_FIRSTHDR(&msg);
325 if (!cm)
326 error(1, 0, "cmsg: no cmsg");
327 if (!((cm->cmsg_level == SOL_IP && cm->cmsg_type == IP_RECVERR) ||
328 (cm->cmsg_level == SOL_IPV6 && cm->cmsg_type == IPV6_RECVERR) ||
329 (cm->cmsg_level == SOL_PACKET && cm->cmsg_type == PACKET_TX_TIMESTAMP)))
330 error(1, 0, "serr: wrong type: %d.%d",
331 cm->cmsg_level, cm->cmsg_type);
332
333 serr = (void *) CMSG_DATA(cm);
334 if (serr->ee_origin != SO_EE_ORIGIN_ZEROCOPY)
335 error(1, 0, "serr: wrong origin: %u", serr->ee_origin);
336 if (serr->ee_errno != 0)
337 error(1, 0, "serr: wrong error code: %u", serr->ee_errno);
338
339 hi = serr->ee_data;
340 lo = serr->ee_info;
341 range = hi - lo + 1;
342
343 /* Detect notification gaps. These should not happen often, if at all.
344 * Gaps can occur due to drops, reordering and retransmissions.
345 */
346 if (lo != next_completion)
347 fprintf(stderr, "gap: %u..%u does not append to %u\n",
348 lo, hi, next_completion);
349 next_completion = hi + 1;
350
351 zerocopy = !(serr->ee_code & SO_EE_CODE_ZEROCOPY_COPIED);
352 if (zerocopied == -1)
353 zerocopied = zerocopy;
354 else if (zerocopied != zerocopy) {
355 fprintf(stderr, "serr: inconsistent\n");
356 zerocopied = zerocopy;
357 }
358
359 if (cfg_verbose >= 2)
360 fprintf(stderr, "completed: %u (h=%u l=%u)\n",
361 range, hi, lo);
362
363 completions += range;
364 return true;
365}
366
367/* Read all outstanding messages on the errqueue */
368static void do_recv_completions(int fd)
369{
370 while (do_recv_completion(fd)) {}
371}
372
373/* Wait for all remaining completions on the errqueue */
374static void do_recv_remaining_completions(int fd)
375{
376 int64_t tstop = gettimeofday_ms() + cfg_waittime_ms;
377
378 while (completions < expected_completions &&
379 gettimeofday_ms() < tstop) {
380 if (do_poll(fd, POLLERR))
381 do_recv_completions(fd);
382 }
383
384 if (completions < expected_completions)
385 fprintf(stderr, "missing notifications: %lu < %lu\n",
386 completions, expected_completions);
387}
388
389static void do_tx(int domain, int type, int protocol)
390{
391 struct iovec iov[3] = { {0} };
392 struct sockaddr_ll laddr;
393 struct msghdr msg = {0};
394 struct ethhdr eth;
395 union {
396 struct ipv6hdr ip6h;
397 struct iphdr iph;
398 } nh;
399 uint64_t tstop;
400 int fd;
401
402 fd = do_setup_tx(domain, type, protocol);
403
404 if (domain == PF_PACKET) {
405 uint16_t proto = cfg_family == PF_INET ? ETH_P_IP : ETH_P_IPV6;
406
407 /* sock_raw passes ll header as data */
408 if (type == SOCK_RAW) {
409 memset(eth.h_dest, 0x06, ETH_ALEN);
410 memset(eth.h_source, 0x02, ETH_ALEN);
411 eth.h_proto = htons(proto);
412 iov[0].iov_base = &eth;
413 iov[0].iov_len = sizeof(eth);
414 msg.msg_iovlen++;
415 }
416
417 /* both sock_raw and sock_dgram expect name */
418 memset(&laddr, 0, sizeof(laddr));
419 laddr.sll_family = AF_PACKET;
420 laddr.sll_ifindex = cfg_ifindex;
421 laddr.sll_protocol = htons(proto);
422 laddr.sll_halen = ETH_ALEN;
423
424 memset(laddr.sll_addr, 0x06, ETH_ALEN);
425
426 msg.msg_name = &laddr;
427 msg.msg_namelen = sizeof(laddr);
428 }
429
430 /* packet and raw sockets with hdrincl must pass network header */
431 if (domain == PF_PACKET || protocol == IPPROTO_RAW) {
432 if (cfg_family == PF_INET)
433 iov[1].iov_len = setup_iph(&nh.iph, cfg_payload_len);
434 else
435 iov[1].iov_len = setup_ip6h(&nh.ip6h, cfg_payload_len);
436
437 iov[1].iov_base = (void *) &nh;
438 msg.msg_iovlen++;
439 }
440
441 iov[2].iov_base = payload;
442 iov[2].iov_len = cfg_payload_len;
443 msg.msg_iovlen++;
444 msg.msg_iov = &iov[3 - msg.msg_iovlen];
445
446 tstop = gettimeofday_ms() + cfg_runtime_ms;
447 do {
448 if (cfg_cork)
449 do_sendmsg_corked(fd, &msg);
450 else
451 do_sendmsg(fd, &msg, cfg_zerocopy);
452
453 while (!do_poll(fd, POLLOUT)) {
454 if (cfg_zerocopy)
455 do_recv_completions(fd);
456 }
457
458 } while (gettimeofday_ms() < tstop);
459
460 if (cfg_zerocopy)
461 do_recv_remaining_completions(fd);
462
463 if (close(fd))
464 error(1, errno, "close");
465
466 fprintf(stderr, "tx=%lu (%lu MB) txc=%lu zc=%c\n",
467 packets, bytes >> 20, completions,
468 zerocopied == 1 ? 'y' : 'n');
469}
470
471static int do_setup_rx(int domain, int type, int protocol)
472{
473 int fd;
474
475 /* If tx over PF_PACKET, rx over PF_INET(6)/SOCK_RAW,
476 * to recv the only copy of the packet, not a clone
477 */
478 if (domain == PF_PACKET)
479 error(1, 0, "Use PF_INET/SOCK_RAW to read");
480
481 if (type == SOCK_RAW && protocol == IPPROTO_RAW)
482 error(1, 0, "IPPROTO_RAW: not supported on Rx");
483
484 fd = socket(domain, type, protocol);
485 if (fd == -1)
486 error(1, errno, "socket r");
487
488 do_setsockopt(fd, SOL_SOCKET, SO_RCVBUF, 1 << 21);
489 do_setsockopt(fd, SOL_SOCKET, SO_RCVLOWAT, 1 << 16);
490 do_setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, 1);
491
492 if (bind(fd, (void *) &cfg_dst_addr, cfg_alen))
493 error(1, errno, "bind");
494
495 if (type == SOCK_STREAM) {
496 if (listen(fd, 1))
497 error(1, errno, "listen");
498 fd = do_accept(fd);
499 }
500
501 return fd;
502}
503
504/* Flush all outstanding bytes for the tcp receive queue */
505static void do_flush_tcp(int fd)
506{
507 int ret;
508
509 /* MSG_TRUNC flushes up to len bytes */
510 ret = recv(fd, NULL, 1 << 21, MSG_TRUNC | MSG_DONTWAIT);
511 if (ret == -1 && errno == EAGAIN)
512 return;
513 if (ret == -1)
514 error(1, errno, "flush");
515 if (!ret)
516 return;
517
518 packets++;
519 bytes += ret;
520}
521
522/* Flush all outstanding datagrams. Verify first few bytes of each. */
523static void do_flush_datagram(int fd, int type)
524{
525 int ret, off = 0;
526 char buf[64];
527
528 /* MSG_TRUNC will return full datagram length */
529 ret = recv(fd, buf, sizeof(buf), MSG_DONTWAIT | MSG_TRUNC);
530 if (ret == -1 && errno == EAGAIN)
531 return;
532
533 /* raw ipv4 return with header, raw ipv6 without */
534 if (cfg_family == PF_INET && type == SOCK_RAW) {
535 off += sizeof(struct iphdr);
536 ret -= sizeof(struct iphdr);
537 }
538
539 if (ret == -1)
540 error(1, errno, "recv");
541 if (ret != cfg_payload_len)
542 error(1, 0, "recv: ret=%u != %u", ret, cfg_payload_len);
543 if (ret > sizeof(buf) - off)
544 ret = sizeof(buf) - off;
545 if (memcmp(buf + off, payload, ret))
546 error(1, 0, "recv: data mismatch");
547
548 packets++;
549 bytes += cfg_payload_len;
550}
551
552static void do_rx(int domain, int type, int protocol)
553{
554 uint64_t tstop;
555 int fd;
556
557 fd = do_setup_rx(domain, type, protocol);
558
559 tstop = gettimeofday_ms() + cfg_runtime_ms;
560 do {
561 if (type == SOCK_STREAM)
562 do_flush_tcp(fd);
563 else
564 do_flush_datagram(fd, type);
565
566 do_poll(fd, POLLIN);
567
568 } while (gettimeofday_ms() < tstop);
569
570 if (close(fd))
571 error(1, errno, "close");
572
573 fprintf(stderr, "rx=%lu (%lu MB)\n", packets, bytes >> 20);
574}
575
576static void do_test(int domain, int type, int protocol)
577{
578 int i;
579
580 if (cfg_cork && (domain == PF_PACKET || type != SOCK_DGRAM))
581 error(1, 0, "can only cork udp sockets");
582
583 do_setcpu(cfg_cpu);
584
585 for (i = 0; i < IP_MAXPACKET; i++)
586 payload[i] = 'a' + (i % 26);
587
588 if (cfg_rx)
589 do_rx(domain, type, protocol);
590 else
591 do_tx(domain, type, protocol);
592}
593
594static void usage(const char *filepath)
595{
596 error(1, 0, "Usage: %s [options] <test>", filepath);
597}
598
599static void parse_opts(int argc, char **argv)
600{
601 const int max_payload_len = sizeof(payload) -
602 sizeof(struct ipv6hdr) -
603 sizeof(struct tcphdr) -
604 40 /* max tcp options */;
605 int c;
606
607 cfg_payload_len = max_payload_len;
608
609 while ((c = getopt(argc, argv, "46c:C:D:i:mp:rs:S:t:vz")) != -1) {
610 switch (c) {
611 case '4':
612 if (cfg_family != PF_UNSPEC)
613 error(1, 0, "Pass one of -4 or -6");
614 cfg_family = PF_INET;
615 cfg_alen = sizeof(struct sockaddr_in);
616 break;
617 case '6':
618 if (cfg_family != PF_UNSPEC)
619 error(1, 0, "Pass one of -4 or -6");
620 cfg_family = PF_INET6;
621 cfg_alen = sizeof(struct sockaddr_in6);
622 break;
623 case 'c':
624 cfg_cork = strtol(optarg, NULL, 0);
625 break;
626 case 'C':
627 cfg_cpu = strtol(optarg, NULL, 0);
628 break;
629 case 'D':
630 setup_sockaddr(cfg_family, optarg, &cfg_dst_addr);
631 break;
632 case 'i':
633 cfg_ifindex = if_nametoindex(optarg);
634 if (cfg_ifindex == 0)
635 error(1, errno, "invalid iface: %s", optarg);
636 break;
637 case 'm':
638 cfg_cork_mixed = true;
639 break;
640 case 'p':
641 cfg_port = htons(strtoul(optarg, NULL, 0));
642 break;
643 case 'r':
644 cfg_rx = true;
645 break;
646 case 's':
647 cfg_payload_len = strtoul(optarg, NULL, 0);
648 break;
649 case 'S':
650 setup_sockaddr(cfg_family, optarg, &cfg_src_addr);
651 break;
652 case 't':
653 cfg_runtime_ms = 200 + strtoul(optarg, NULL, 10) * 1000;
654 break;
655 case 'v':
656 cfg_verbose++;
657 break;
658 case 'z':
659 cfg_zerocopy = true;
660 break;
661 }
662 }
663
664 if (cfg_payload_len > max_payload_len)
665 error(1, 0, "-s: payload exceeds max (%d)", max_payload_len);
666 if (cfg_cork_mixed && (!cfg_zerocopy || !cfg_cork))
667 error(1, 0, "-m: cork_mixed requires corking and zerocopy");
668
669 if (optind != argc - 1)
670 usage(argv[0]);
671}
672
673int main(int argc, char **argv)
674{
675 const char *cfg_test;
676
677 parse_opts(argc, argv);
678
679 cfg_test = argv[argc - 1];
680
681 if (!strcmp(cfg_test, "packet"))
682 do_test(PF_PACKET, SOCK_RAW, 0);
683 else if (!strcmp(cfg_test, "packet_dgram"))
684 do_test(PF_PACKET, SOCK_DGRAM, 0);
685 else if (!strcmp(cfg_test, "raw"))
686 do_test(cfg_family, SOCK_RAW, IPPROTO_EGP);
687 else if (!strcmp(cfg_test, "raw_hdrincl"))
688 do_test(cfg_family, SOCK_RAW, IPPROTO_RAW);
689 else if (!strcmp(cfg_test, "tcp"))
690 do_test(cfg_family, SOCK_STREAM, 0);
691 else if (!strcmp(cfg_test, "udp"))
692 do_test(cfg_family, SOCK_DGRAM, 0);
693 else
694 error(1, 0, "unknown cfg_test %s", cfg_test);
695
696 return 0;
697}
diff --git a/tools/testing/selftests/net/msg_zerocopy.sh b/tools/testing/selftests/net/msg_zerocopy.sh
new file mode 100755
index 000000000000..d571d213418d
--- /dev/null
+++ b/tools/testing/selftests/net/msg_zerocopy.sh
@@ -0,0 +1,112 @@
1#!/bin/bash
2#
3# Send data between two processes across namespaces
4# Run twice: once without and once with zerocopy
5
6set -e
7
8readonly DEV="veth0"
9readonly DEV_MTU=65535
10readonly BIN="./msg_zerocopy"
11
12readonly RAND="$(mktemp -u XXXXXX)"
13readonly NSPREFIX="ns-${RAND}"
14readonly NS1="${NSPREFIX}1"
15readonly NS2="${NSPREFIX}2"
16
17readonly SADDR4='192.168.1.1'
18readonly DADDR4='192.168.1.2'
19readonly SADDR6='fd::1'
20readonly DADDR6='fd::2'
21
22readonly path_sysctl_mem="net.core.optmem_max"
23
24# Argument parsing
25if [[ "$#" -lt "2" ]]; then
26 echo "Usage: $0 [4|6] [tcp|udp|raw|raw_hdrincl|packet|packet_dgram] <args>"
27 exit 1
28fi
29
30readonly IP="$1"
31shift
32readonly TXMODE="$1"
33shift
34readonly EXTRA_ARGS="$@"
35
36# Argument parsing: configure addresses
37if [[ "${IP}" == "4" ]]; then
38 readonly SADDR="${SADDR4}"
39 readonly DADDR="${DADDR4}"
40elif [[ "${IP}" == "6" ]]; then
41 readonly SADDR="${SADDR6}"
42 readonly DADDR="${DADDR6}"
43else
44 echo "Invalid IP version ${IP}"
45 exit 1
46fi
47
48# Argument parsing: select receive mode
49#
50# This differs from send mode for
51# - packet: use raw recv, because packet receives skb clones
52# - raw_hdrinc: use raw recv, because hdrincl is a tx-only option
53case "${TXMODE}" in
54'packet' | 'packet_dgram' | 'raw_hdrincl')
55 RXMODE='raw'
56 ;;
57*)
58 RXMODE="${TXMODE}"
59 ;;
60esac
61
62# Start of state changes: install cleanup handler
63save_sysctl_mem="$(sysctl -n ${path_sysctl_mem})"
64
65cleanup() {
66 ip netns del "${NS2}"
67 ip netns del "${NS1}"
68 sysctl -w -q "${path_sysctl_mem}=${save_sysctl_mem}"
69}
70
71trap cleanup EXIT
72
73# Configure system settings
74sysctl -w -q "${path_sysctl_mem}=1000000"
75
76# Create virtual ethernet pair between network namespaces
77ip netns add "${NS1}"
78ip netns add "${NS2}"
79
80ip link add "${DEV}" mtu "${DEV_MTU}" netns "${NS1}" type veth \
81 peer name "${DEV}" mtu "${DEV_MTU}" netns "${NS2}"
82
83# Bring the devices up
84ip -netns "${NS1}" link set "${DEV}" up
85ip -netns "${NS2}" link set "${DEV}" up
86
87# Set fixed MAC addresses on the devices
88ip -netns "${NS1}" link set dev "${DEV}" address 02:02:02:02:02:02
89ip -netns "${NS2}" link set dev "${DEV}" address 06:06:06:06:06:06
90
91# Add fixed IP addresses to the devices
92ip -netns "${NS1}" addr add 192.168.1.1/24 dev "${DEV}"
93ip -netns "${NS2}" addr add 192.168.1.2/24 dev "${DEV}"
94ip -netns "${NS1}" addr add fd::1/64 dev "${DEV}" nodad
95ip -netns "${NS2}" addr add fd::2/64 dev "${DEV}" nodad
96
97# Optionally disable sg or csum offload to test edge cases
98# ip netns exec "${NS1}" ethtool -K "${DEV}" sg off
99
100do_test() {
101 local readonly ARGS="$1"
102
103 echo "ipv${IP} ${TXMODE} ${ARGS}"
104 ip netns exec "${NS2}" "${BIN}" "-${IP}" -i "${DEV}" -t 2 -C 2 -S "${SADDR}" -D "${DADDR}" ${ARGS} -r "${RXMODE}" &
105 sleep 0.2
106 ip netns exec "${NS1}" "${BIN}" "-${IP}" -i "${DEV}" -t 1 -C 3 -S "${SADDR}" -D "${DADDR}" ${ARGS} "${TXMODE}"
107 wait
108}
109
110do_test "${EXTRA_ARGS}"
111do_test "-z ${EXTRA_ARGS}"
112echo ok
diff --git a/tools/testing/selftests/net/netdevice.sh b/tools/testing/selftests/net/netdevice.sh
index 4e00568d70c2..903679e0ff31 100755
--- a/tools/testing/selftests/net/netdevice.sh
+++ b/tools/testing/selftests/net/netdevice.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# 3#
3# This test is for checking network interface 4# This test is for checking network interface
4# For the moment it tests only ethernet interface (but wifi could be easily added) 5# For the moment it tests only ethernet interface (but wifi could be easily added)
@@ -178,7 +179,7 @@ if [ "$(id -u)" -ne 0 ];then
178 exit 0 179 exit 0
179fi 180fi
180 181
181ip -Version 2>/dev/null >/dev/null 182ip link show 2>/dev/null >/dev/null
182if [ $? -ne 0 ];then 183if [ $? -ne 0 ];then
183 echo "SKIP: Could not run test without the ip tool" 184 echo "SKIP: Could not run test without the ip tool"
184 exit 0 185 exit 0
diff --git a/tools/testing/selftests/net/reuseaddr_conflict.c b/tools/testing/selftests/net/reuseaddr_conflict.c
new file mode 100644
index 000000000000..7c5b12664b03
--- /dev/null
+++ b/tools/testing/selftests/net/reuseaddr_conflict.c
@@ -0,0 +1,114 @@
1/*
2 * Test for the regression introduced by
3 *
4 * b9470c27607b ("inet: kill smallest_size and smallest_port")
5 *
6 * If we open an ipv4 socket on a port with reuseaddr we shouldn't reset the tb
7 * when we open the ipv6 conterpart, which is what was happening previously.
8 */
9#include <errno.h>
10#include <error.h>
11#include <arpa/inet.h>
12#include <netinet/in.h>
13#include <stdbool.h>
14#include <stdio.h>
15#include <sys/socket.h>
16#include <sys/types.h>
17#include <unistd.h>
18
19#define PORT 9999
20
21int open_port(int ipv6, int any)
22{
23 int fd = -1;
24 int reuseaddr = 1;
25 int v6only = 1;
26 int addrlen;
27 int ret = -1;
28 struct sockaddr *addr;
29 int family = ipv6 ? AF_INET6 : AF_INET;
30
31 struct sockaddr_in6 addr6 = {
32 .sin6_family = AF_INET6,
33 .sin6_port = htons(PORT),
34 .sin6_addr = in6addr_any
35 };
36 struct sockaddr_in addr4 = {
37 .sin_family = AF_INET,
38 .sin_port = htons(PORT),
39 .sin_addr.s_addr = any ? htonl(INADDR_ANY) : inet_addr("127.0.0.1"),
40 };
41
42
43 if (ipv6) {
44 addr = (struct sockaddr*)&addr6;
45 addrlen = sizeof(addr6);
46 } else {
47 addr = (struct sockaddr*)&addr4;
48 addrlen = sizeof(addr4);
49 }
50
51 if ((fd = socket(family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
52 perror("socket");
53 goto out;
54 }
55
56 if (ipv6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&v6only,
57 sizeof(v6only)) < 0) {
58 perror("setsockopt IPV6_V6ONLY");
59 goto out;
60 }
61
62 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
63 sizeof(reuseaddr)) < 0) {
64 perror("setsockopt SO_REUSEADDR");
65 goto out;
66 }
67
68 if (bind(fd, addr, addrlen) < 0) {
69 perror("bind");
70 goto out;
71 }
72
73 if (any)
74 return fd;
75
76 if (listen(fd, 1) < 0) {
77 perror("listen");
78 goto out;
79 }
80 return fd;
81out:
82 close(fd);
83 return ret;
84}
85
86int main(void)
87{
88 int listenfd;
89 int fd1, fd2;
90
91 fprintf(stderr, "Opening 127.0.0.1:%d\n", PORT);
92 listenfd = open_port(0, 0);
93 if (listenfd < 0)
94 error(1, errno, "Couldn't open listen socket");
95 fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT);
96 fd1 = open_port(0, 1);
97 if (fd1 >= 0)
98 error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket");
99 fprintf(stderr, "Opening in6addr_any:%d\n", PORT);
100 fd1 = open_port(1, 1);
101 if (fd1 < 0)
102 error(1, errno, "Couldn't open ipv6 reuseport");
103 fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT);
104 fd2 = open_port(0, 1);
105 if (fd2 >= 0)
106 error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket");
107 close(fd1);
108 fprintf(stderr, "Opening INADDR_ANY:%d after closing ipv6 socket\n", PORT);
109 fd1 = open_port(0, 1);
110 if (fd1 >= 0)
111 error(1, 0, "Was allowed to create an ipv4 reuseport on an already bound non-reuseport socket with no ipv6");
112 fprintf(stderr, "Success");
113 return 0;
114}
diff --git a/tools/testing/selftests/net/reuseport_bpf_cpu.c b/tools/testing/selftests/net/reuseport_bpf_cpu.c
index b23d6f54de7b..2d646174729f 100644
--- a/tools/testing/selftests/net/reuseport_bpf_cpu.c
+++ b/tools/testing/selftests/net/reuseport_bpf_cpu.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Test functionality of BPF filters with SO_REUSEPORT. This program creates 3 * Test functionality of BPF filters with SO_REUSEPORT. This program creates
3 * an SO_REUSEPORT receiver group containing one socket per CPU core. It then 4 * an SO_REUSEPORT receiver group containing one socket per CPU core. It then
diff --git a/tools/testing/selftests/net/reuseport_bpf_numa.c b/tools/testing/selftests/net/reuseport_bpf_numa.c
index 6f20bc9ff627..365c32e84189 100644
--- a/tools/testing/selftests/net/reuseport_bpf_numa.c
+++ b/tools/testing/selftests/net/reuseport_bpf_numa.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Test functionality of BPF filters with SO_REUSEPORT. Same test as 3 * Test functionality of BPF filters with SO_REUSEPORT. Same test as
3 * in reuseport_bpf_cpu, only as one socket per NUMA node. 4 * in reuseport_bpf_cpu, only as one socket per NUMA node.
diff --git a/tools/testing/selftests/net/reuseport_dualstack.c b/tools/testing/selftests/net/reuseport_dualstack.c
index 90958aaaafb9..fe3230c55986 100644
--- a/tools/testing/selftests/net/reuseport_dualstack.c
+++ b/tools/testing/selftests/net/reuseport_dualstack.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * It is possible to use SO_REUSEPORT to open multiple sockets bound to 3 * It is possible to use SO_REUSEPORT to open multiple sockets bound to
3 * equivalent local addresses using AF_INET and AF_INET6 at the same time. If 4 * equivalent local addresses using AF_INET and AF_INET6 at the same time. If
diff --git a/tools/testing/selftests/net/rtnetlink.sh b/tools/testing/selftests/net/rtnetlink.sh
new file mode 100755
index 000000000000..5215493166c9
--- /dev/null
+++ b/tools/testing/selftests/net/rtnetlink.sh
@@ -0,0 +1,543 @@
1#!/bin/sh
2#
3# This test is for checking rtnetlink callpaths, and get as much coverage as possible.
4#
5# set -e
6
7devdummy="test-dummy0"
8ret=0
9
10# set global exit status, but never reset nonzero one.
11check_err()
12{
13 if [ $ret -eq 0 ]; then
14 ret=$1
15 fi
16}
17
18# same but inverted -- used when command must fail for test to pass
19check_fail()
20{
21 if [ $1 -eq 0 ]; then
22 ret=1
23 fi
24}
25
26kci_add_dummy()
27{
28 ip link add name "$devdummy" type dummy
29 check_err $?
30 ip link set "$devdummy" up
31 check_err $?
32}
33
34kci_del_dummy()
35{
36 ip link del dev "$devdummy"
37 check_err $?
38}
39
40kci_test_netconf()
41{
42 dev="$1"
43 r=$ret
44
45 ip netconf show dev "$dev" > /dev/null
46 check_err $?
47
48 for f in 4 6; do
49 ip -$f netconf show dev "$dev" > /dev/null
50 check_err $?
51 done
52
53 if [ $ret -ne 0 ] ;then
54 echo "FAIL: ip netconf show $dev"
55 test $r -eq 0 && ret=0
56 return 1
57 fi
58}
59
60# add a bridge with vlans on top
61kci_test_bridge()
62{
63 devbr="test-br0"
64 vlandev="testbr-vlan1"
65
66 ret=0
67 ip link add name "$devbr" type bridge
68 check_err $?
69
70 ip link set dev "$devdummy" master "$devbr"
71 check_err $?
72
73 ip link set "$devbr" up
74 check_err $?
75
76 ip link add link "$devbr" name "$vlandev" type vlan id 1
77 check_err $?
78 ip addr add dev "$vlandev" 10.200.7.23/30
79 check_err $?
80 ip -6 addr add dev "$vlandev" dead:42::1234/64
81 check_err $?
82 ip -d link > /dev/null
83 check_err $?
84 ip r s t all > /dev/null
85 check_err $?
86
87 for name in "$devbr" "$vlandev" "$devdummy" ; do
88 kci_test_netconf "$name"
89 done
90
91 ip -6 addr del dev "$vlandev" dead:42::1234/64
92 check_err $?
93
94 ip link del dev "$vlandev"
95 check_err $?
96 ip link del dev "$devbr"
97 check_err $?
98
99 if [ $ret -ne 0 ];then
100 echo "FAIL: bridge setup"
101 return 1
102 fi
103 echo "PASS: bridge setup"
104
105}
106
107kci_test_gre()
108{
109 gredev=neta
110 rem=10.42.42.1
111 loc=10.0.0.1
112
113 ret=0
114 ip tunnel add $gredev mode gre remote $rem local $loc ttl 1
115 check_err $?
116 ip link set $gredev up
117 check_err $?
118 ip addr add 10.23.7.10 dev $gredev
119 check_err $?
120 ip route add 10.23.8.0/30 dev $gredev
121 check_err $?
122 ip addr add dev "$devdummy" 10.23.7.11/24
123 check_err $?
124 ip link > /dev/null
125 check_err $?
126 ip addr > /dev/null
127 check_err $?
128
129 kci_test_netconf "$gredev"
130
131 ip addr del dev "$devdummy" 10.23.7.11/24
132 check_err $?
133
134 ip link del $gredev
135 check_err $?
136
137 if [ $ret -ne 0 ];then
138 echo "FAIL: gre tunnel endpoint"
139 return 1
140 fi
141 echo "PASS: gre tunnel endpoint"
142}
143
144# tc uses rtnetlink too, for full tc testing
145# please see tools/testing/selftests/tc-testing.
146kci_test_tc()
147{
148 dev=lo
149 ret=0
150
151 tc qdisc add dev "$dev" root handle 1: htb
152 check_err $?
153 tc class add dev "$dev" parent 1: classid 1:10 htb rate 1mbit
154 check_err $?
155 tc filter add dev "$dev" parent 1:0 prio 5 handle ffe: protocol ip u32 divisor 256
156 check_err $?
157 tc filter add dev "$dev" parent 1:0 prio 5 handle ffd: protocol ip u32 divisor 256
158 check_err $?
159 tc filter add dev "$dev" parent 1:0 prio 5 handle ffc: protocol ip u32 divisor 256
160 check_err $?
161 tc filter add dev "$dev" protocol ip parent 1: prio 5 handle ffe:2:3 u32 ht ffe:2: match ip src 10.0.0.3 flowid 1:10
162 check_err $?
163 tc filter add dev "$dev" protocol ip parent 1: prio 5 handle ffe:2:2 u32 ht ffe:2: match ip src 10.0.0.2 flowid 1:10
164 check_err $?
165 tc filter show dev "$dev" parent 1:0 > /dev/null
166 check_err $?
167 tc filter del dev "$dev" protocol ip parent 1: prio 5 handle ffe:2:3 u32
168 check_err $?
169 tc filter show dev "$dev" parent 1:0 > /dev/null
170 check_err $?
171 tc qdisc del dev "$dev" root handle 1: htb
172 check_err $?
173
174 if [ $ret -ne 0 ];then
175 echo "FAIL: tc htb hierarchy"
176 return 1
177 fi
178 echo "PASS: tc htb hierarchy"
179
180}
181
182kci_test_polrouting()
183{
184 ret=0
185 ip rule add fwmark 1 lookup 100
186 check_err $?
187 ip route add local 0.0.0.0/0 dev lo table 100
188 check_err $?
189 ip r s t all > /dev/null
190 check_err $?
191 ip rule del fwmark 1 lookup 100
192 check_err $?
193 ip route del local 0.0.0.0/0 dev lo table 100
194 check_err $?
195
196 if [ $ret -ne 0 ];then
197 echo "FAIL: policy route test"
198 return 1
199 fi
200 echo "PASS: policy routing"
201}
202
203kci_test_route_get()
204{
205 ret=0
206
207 ip route get 127.0.0.1 > /dev/null
208 check_err $?
209 ip route get 127.0.0.1 dev "$devdummy" > /dev/null
210 check_err $?
211 ip route get ::1 > /dev/null
212 check_err $?
213 ip route get fe80::1 dev "$devdummy" > /dev/null
214 check_err $?
215 ip route get 127.0.0.1 from 127.0.0.1 oif lo tos 0x1 mark 0x1 > /dev/null
216 check_err $?
217 ip route get ::1 from ::1 iif lo oif lo tos 0x1 mark 0x1 > /dev/null
218 check_err $?
219 ip addr add dev "$devdummy" 10.23.7.11/24
220 check_err $?
221 ip route get 10.23.7.11 from 10.23.7.12 iif "$devdummy" > /dev/null
222 check_err $?
223 ip addr del dev "$devdummy" 10.23.7.11/24
224 check_err $?
225
226 if [ $ret -ne 0 ];then
227 echo "FAIL: route get"
228 return 1
229 fi
230
231 echo "PASS: route get"
232}
233
234kci_test_addrlabel()
235{
236 ret=0
237
238 ip addrlabel add prefix dead::/64 dev lo label 1
239 check_err $?
240
241 ip addrlabel list |grep -q "prefix dead::/64 dev lo label 1"
242 check_err $?
243
244 ip addrlabel del prefix dead::/64 dev lo label 1 2> /dev/null
245 check_err $?
246
247 ip addrlabel add prefix dead::/64 label 1 2> /dev/null
248 check_err $?
249
250 ip addrlabel del prefix dead::/64 label 1 2> /dev/null
251 check_err $?
252
253 # concurrent add/delete
254 for i in $(seq 1 1000); do
255 ip addrlabel add prefix 1c3::/64 label 12345 2>/dev/null
256 done &
257
258 for i in $(seq 1 1000); do
259 ip addrlabel del prefix 1c3::/64 label 12345 2>/dev/null
260 done
261
262 wait
263
264 ip addrlabel del prefix 1c3::/64 label 12345 2>/dev/null
265
266 if [ $ret -ne 0 ];then
267 echo "FAIL: ipv6 addrlabel"
268 return 1
269 fi
270
271 echo "PASS: ipv6 addrlabel"
272}
273
274kci_test_ifalias()
275{
276 ret=0
277 namewant=$(uuidgen)
278 syspathname="/sys/class/net/$devdummy/ifalias"
279
280 ip link set dev "$devdummy" alias "$namewant"
281 check_err $?
282
283 if [ $ret -ne 0 ]; then
284 echo "FAIL: cannot set interface alias of $devdummy to $namewant"
285 return 1
286 fi
287
288 ip link show "$devdummy" | grep -q "alias $namewant"
289 check_err $?
290
291 if [ -r "$syspathname" ] ; then
292 read namehave < "$syspathname"
293 if [ "$namewant" != "$namehave" ]; then
294 echo "FAIL: did set ifalias $namewant but got $namehave"
295 return 1
296 fi
297
298 namewant=$(uuidgen)
299 echo "$namewant" > "$syspathname"
300 ip link show "$devdummy" | grep -q "alias $namewant"
301 check_err $?
302
303 # sysfs interface allows to delete alias again
304 echo "" > "$syspathname"
305
306 ip link show "$devdummy" | grep -q "alias $namewant"
307 check_fail $?
308
309 for i in $(seq 1 100); do
310 uuidgen > "$syspathname" &
311 done
312
313 wait
314
315 # re-add the alias -- kernel should free mem when dummy dev is removed
316 ip link set dev "$devdummy" alias "$namewant"
317 check_err $?
318 fi
319
320 if [ $ret -ne 0 ]; then
321 echo "FAIL: set interface alias $devdummy to $namewant"
322 return 1
323 fi
324
325 echo "PASS: set ifalias $namewant for $devdummy"
326}
327
328kci_test_vrf()
329{
330 vrfname="test-vrf"
331 ret=0
332
333 ip link show type vrf 2>/dev/null
334 if [ $? -ne 0 ]; then
335 echo "SKIP: vrf: iproute2 too old"
336 return 0
337 fi
338
339 ip link add "$vrfname" type vrf table 10
340 check_err $?
341 if [ $ret -ne 0 ];then
342 echo "FAIL: can't add vrf interface, skipping test"
343 return 0
344 fi
345
346 ip -br link show type vrf | grep -q "$vrfname"
347 check_err $?
348 if [ $ret -ne 0 ];then
349 echo "FAIL: created vrf device not found"
350 return 1
351 fi
352
353 ip link set dev "$vrfname" up
354 check_err $?
355
356 ip link set dev "$devdummy" master "$vrfname"
357 check_err $?
358 ip link del dev "$vrfname"
359 check_err $?
360
361 if [ $ret -ne 0 ];then
362 echo "FAIL: vrf"
363 return 1
364 fi
365
366 echo "PASS: vrf"
367}
368
369kci_test_encap_vxlan()
370{
371 ret=0
372 vxlan="test-vxlan0"
373 vlan="test-vlan0"
374 testns="$1"
375
376 ip netns exec "$testns" ip link add "$vxlan" type vxlan id 42 group 239.1.1.1 \
377 dev "$devdummy" dstport 4789 2>/dev/null
378 if [ $? -ne 0 ]; then
379 echo "FAIL: can't add vxlan interface, skipping test"
380 return 0
381 fi
382 check_err $?
383
384 ip netns exec "$testns" ip addr add 10.2.11.49/24 dev "$vxlan"
385 check_err $?
386
387 ip netns exec "$testns" ip link set up dev "$vxlan"
388 check_err $?
389
390 ip netns exec "$testns" ip link add link "$vxlan" name "$vlan" type vlan id 1
391 check_err $?
392
393 ip netns exec "$testns" ip link del "$vxlan"
394 check_err $?
395
396 if [ $ret -ne 0 ]; then
397 echo "FAIL: vxlan"
398 return 1
399 fi
400 echo "PASS: vxlan"
401}
402
403kci_test_encap_fou()
404{
405 ret=0
406 name="test-fou"
407 testns="$1"
408
409 ip fou help 2>&1 |grep -q 'Usage: ip fou'
410 if [ $? -ne 0 ];then
411 echo "SKIP: fou: iproute2 too old"
412 return 1
413 fi
414
415 ip netns exec "$testns" ip fou add port 7777 ipproto 47 2>/dev/null
416 if [ $? -ne 0 ];then
417 echo "FAIL: can't add fou port 7777, skipping test"
418 return 1
419 fi
420
421 ip netns exec "$testns" ip fou add port 8888 ipproto 4
422 check_err $?
423
424 ip netns exec "$testns" ip fou del port 9999 2>/dev/null
425 check_fail $?
426
427 ip netns exec "$testns" ip fou del port 7777
428 check_err $?
429
430 if [ $ret -ne 0 ]; then
431 echo "FAIL: fou"
432 return 1
433 fi
434
435 echo "PASS: fou"
436}
437
438# test various encap methods, use netns to avoid unwanted interference
439kci_test_encap()
440{
441 testns="testns"
442 ret=0
443
444 ip netns add "$testns"
445 if [ $? -ne 0 ]; then
446 echo "SKIP encap tests: cannot add net namespace $testns"
447 return 1
448 fi
449
450 ip netns exec "$testns" ip link set lo up
451 check_err $?
452
453 ip netns exec "$testns" ip link add name "$devdummy" type dummy
454 check_err $?
455 ip netns exec "$testns" ip link set "$devdummy" up
456 check_err $?
457
458 kci_test_encap_vxlan "$testns"
459 kci_test_encap_fou "$testns"
460
461 ip netns del "$testns"
462}
463
464kci_test_macsec()
465{
466 msname="test_macsec0"
467 ret=0
468
469 ip macsec help 2>&1 | grep -q "^Usage: ip macsec"
470 if [ $? -ne 0 ]; then
471 echo "SKIP: macsec: iproute2 too old"
472 return 0
473 fi
474
475 ip link add link "$devdummy" "$msname" type macsec port 42 encrypt on
476 check_err $?
477 if [ $ret -ne 0 ];then
478 echo "FAIL: can't add macsec interface, skipping test"
479 return 1
480 fi
481
482 ip macsec add "$msname" tx sa 0 pn 1024 on key 01 12345678901234567890123456789012
483 check_err $?
484
485 ip macsec add "$msname" rx port 1234 address "1c:ed:de:ad:be:ef"
486 check_err $?
487
488 ip macsec add "$msname" rx port 1234 address "1c:ed:de:ad:be:ef" sa 0 pn 1 on key 00 0123456789abcdef0123456789abcdef
489 check_err $?
490
491 ip macsec show > /dev/null
492 check_err $?
493
494 ip link del dev "$msname"
495 check_err $?
496
497 if [ $ret -ne 0 ];then
498 echo "FAIL: macsec"
499 return 1
500 fi
501
502 echo "PASS: macsec"
503}
504
505kci_test_rtnl()
506{
507 kci_add_dummy
508 if [ $ret -ne 0 ];then
509 echo "FAIL: cannot add dummy interface"
510 return 1
511 fi
512
513 kci_test_polrouting
514 kci_test_route_get
515 kci_test_tc
516 kci_test_gre
517 kci_test_bridge
518 kci_test_addrlabel
519 kci_test_ifalias
520 kci_test_vrf
521 kci_test_encap
522 kci_test_macsec
523
524 kci_del_dummy
525}
526
527#check for needed privileges
528if [ "$(id -u)" -ne 0 ];then
529 echo "SKIP: Need root privileges"
530 exit 0
531fi
532
533for x in ip tc;do
534 $x -Version 2>/dev/null >/dev/null
535 if [ $? -ne 0 ];then
536 echo "SKIP: Could not run test without the $x tool"
537 exit 0
538 fi
539done
540
541kci_test_rtnl
542
543exit $ret
diff --git a/tools/testing/selftests/net/run_afpackettests b/tools/testing/selftests/net/run_afpackettests
index 5246e782d6e8..21fe149e3de1 100755
--- a/tools/testing/selftests/net/run_afpackettests
+++ b/tools/testing/selftests/net/run_afpackettests
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2 3
3if [ $(id -u) != 0 ]; then 4if [ $(id -u) != 0 ]; then
4 echo $msg must be run as root >&2 5 echo $msg must be run as root >&2
diff --git a/tools/testing/selftests/net/run_netsocktests b/tools/testing/selftests/net/run_netsocktests
index 16058bbea7a8..b093f39c298c 100755
--- a/tools/testing/selftests/net/run_netsocktests
+++ b/tools/testing/selftests/net/run_netsocktests
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2 3
3echo "--------------------" 4echo "--------------------"
4echo "running socket test" 5echo "running socket test"
diff --git a/tools/testing/selftests/net/socket.c b/tools/testing/selftests/net/socket.c
index 0f227f2f9be9..afca1ead677f 100644
--- a/tools/testing/selftests/net/socket.c
+++ b/tools/testing/selftests/net/socket.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <errno.h> 3#include <errno.h>
3#include <unistd.h> 4#include <unistd.h>
diff --git a/tools/testing/selftests/net/test_bpf.sh b/tools/testing/selftests/net/test_bpf.sh
index 8b29796d46aa..65677909c574 100755
--- a/tools/testing/selftests/net/test_bpf.sh
+++ b/tools/testing/selftests/net/test_bpf.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# Runs bpf test using test_bpf kernel module 3# Runs bpf test using test_bpf kernel module
3 4
4if /sbin/modprobe -q test_bpf ; then 5if /sbin/modprobe -q test_bpf ; then
diff --git a/tools/testing/selftests/networking/timestamping/.gitignore b/tools/testing/selftests/networking/timestamping/.gitignore
index 9e69e982fb38..d9355035e746 100644
--- a/tools/testing/selftests/networking/timestamping/.gitignore
+++ b/tools/testing/selftests/networking/timestamping/.gitignore
@@ -1,3 +1,4 @@
1timestamping 1timestamping
2rxtimestamp
2txtimestamp 3txtimestamp
3hwtstamp_config 4hwtstamp_config
diff --git a/tools/testing/selftests/networking/timestamping/Makefile b/tools/testing/selftests/networking/timestamping/Makefile
index ccbb9edbbbb9..a728040edbe1 100644
--- a/tools/testing/selftests/networking/timestamping/Makefile
+++ b/tools/testing/selftests/networking/timestamping/Makefile
@@ -1,4 +1,7 @@
1TEST_PROGS := hwtstamp_config timestamping txtimestamp 1# SPDX-License-Identifier: GPL-2.0
2CFLAGS += -I../../../../../usr/include
3
4TEST_PROGS := hwtstamp_config rxtimestamp timestamping txtimestamp
2 5
3all: $(TEST_PROGS) 6all: $(TEST_PROGS)
4 7
diff --git a/tools/testing/selftests/networking/timestamping/hwtstamp_config.c b/tools/testing/selftests/networking/timestamping/hwtstamp_config.c
index e8b685a7f15f..e1fdee841021 100644
--- a/tools/testing/selftests/networking/timestamping/hwtstamp_config.c
+++ b/tools/testing/selftests/networking/timestamping/hwtstamp_config.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* Test program for SIOC{G,S}HWTSTAMP 2/* Test program for SIOC{G,S}HWTSTAMP
2 * Copyright 2013 Solarflare Communications 3 * Copyright 2013 Solarflare Communications
3 * Author: Ben Hutchings 4 * Author: Ben Hutchings
diff --git a/tools/testing/selftests/networking/timestamping/rxtimestamp.c b/tools/testing/selftests/networking/timestamping/rxtimestamp.c
new file mode 100644
index 000000000000..dd4162fc0419
--- /dev/null
+++ b/tools/testing/selftests/networking/timestamping/rxtimestamp.c
@@ -0,0 +1,389 @@
1#include <errno.h>
2#include <error.h>
3#include <getopt.h>
4#include <stdbool.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include <sys/time.h>
10#include <sys/socket.h>
11#include <sys/select.h>
12#include <sys/ioctl.h>
13#include <arpa/inet.h>
14#include <net/if.h>
15
16#include <asm/types.h>
17#include <linux/net_tstamp.h>
18#include <linux/errqueue.h>
19
20#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
21
22struct options {
23 int so_timestamp;
24 int so_timestampns;
25 int so_timestamping;
26};
27
28struct tstamps {
29 bool tstamp;
30 bool tstampns;
31 bool swtstamp;
32 bool hwtstamp;
33};
34
35struct socket_type {
36 char *friendly_name;
37 int type;
38 int protocol;
39 bool enabled;
40};
41
42struct test_case {
43 struct options sockopt;
44 struct tstamps expected;
45 bool enabled;
46};
47
48struct sof_flag {
49 int mask;
50 char *name;
51};
52
53static struct sof_flag sof_flags[] = {
54#define SOF_FLAG(f) { f, #f }
55 SOF_FLAG(SOF_TIMESTAMPING_SOFTWARE),
56 SOF_FLAG(SOF_TIMESTAMPING_RX_SOFTWARE),
57 SOF_FLAG(SOF_TIMESTAMPING_RX_HARDWARE),
58};
59
60static struct socket_type socket_types[] = {
61 { "ip", SOCK_RAW, IPPROTO_EGP },
62 { "udp", SOCK_DGRAM, IPPROTO_UDP },
63 { "tcp", SOCK_STREAM, IPPROTO_TCP },
64};
65
66static struct test_case test_cases[] = {
67 { {}, {} },
68 {
69 { so_timestamp: 1 },
70 { tstamp: true }
71 },
72 {
73 { so_timestampns: 1 },
74 { tstampns: true }
75 },
76 {
77 { so_timestamp: 1, so_timestampns: 1 },
78 { tstampns: true }
79 },
80 {
81 { so_timestamping: SOF_TIMESTAMPING_RX_SOFTWARE },
82 {}
83 },
84 {
85 /* Loopback device does not support hw timestamps. */
86 { so_timestamping: SOF_TIMESTAMPING_RX_HARDWARE },
87 {}
88 },
89 {
90 { so_timestamping: SOF_TIMESTAMPING_SOFTWARE },
91 {}
92 },
93 {
94 { so_timestamping: SOF_TIMESTAMPING_RX_SOFTWARE
95 | SOF_TIMESTAMPING_RX_HARDWARE },
96 {}
97 },
98 {
99 { so_timestamping: SOF_TIMESTAMPING_SOFTWARE
100 | SOF_TIMESTAMPING_RX_SOFTWARE },
101 { swtstamp: true }
102 },
103 {
104 { so_timestamp: 1, so_timestamping: SOF_TIMESTAMPING_SOFTWARE
105 | SOF_TIMESTAMPING_RX_SOFTWARE },
106 { tstamp: true, swtstamp: true }
107 },
108};
109
110static struct option long_options[] = {
111 { "list_tests", no_argument, 0, 'l' },
112 { "test_num", required_argument, 0, 'n' },
113 { "op_size", required_argument, 0, 's' },
114 { "tcp", no_argument, 0, 't' },
115 { "udp", no_argument, 0, 'u' },
116 { "ip", no_argument, 0, 'i' },
117};
118
119static int next_port = 19999;
120static int op_size = 10 * 1024;
121
122void print_test_case(struct test_case *t)
123{
124 int f = 0;
125
126 printf("sockopts {");
127 if (t->sockopt.so_timestamp)
128 printf(" SO_TIMESTAMP ");
129 if (t->sockopt.so_timestampns)
130 printf(" SO_TIMESTAMPNS ");
131 if (t->sockopt.so_timestamping) {
132 printf(" SO_TIMESTAMPING: {");
133 for (f = 0; f < ARRAY_SIZE(sof_flags); f++)
134 if (t->sockopt.so_timestamping & sof_flags[f].mask)
135 printf(" %s |", sof_flags[f].name);
136 printf("}");
137 }
138 printf("} expected cmsgs: {");
139 if (t->expected.tstamp)
140 printf(" SCM_TIMESTAMP ");
141 if (t->expected.tstampns)
142 printf(" SCM_TIMESTAMPNS ");
143 if (t->expected.swtstamp || t->expected.hwtstamp) {
144 printf(" SCM_TIMESTAMPING {");
145 if (t->expected.swtstamp)
146 printf("0");
147 if (t->expected.swtstamp && t->expected.hwtstamp)
148 printf(",");
149 if (t->expected.hwtstamp)
150 printf("2");
151 printf("}");
152 }
153 printf("}\n");
154}
155
156void do_send(int src)
157{
158 int r;
159 char *buf = malloc(op_size);
160
161 memset(buf, 'z', op_size);
162 r = write(src, buf, op_size);
163 if (r < 0)
164 error(1, errno, "Failed to sendmsg");
165
166 free(buf);
167}
168
169bool do_recv(int rcv, int read_size, struct tstamps expected)
170{
171 const int CMSG_SIZE = 1024;
172
173 struct scm_timestamping *ts;
174 struct tstamps actual = {};
175 char cmsg_buf[CMSG_SIZE];
176 struct iovec recv_iov;
177 struct cmsghdr *cmsg;
178 bool failed = false;
179 struct msghdr hdr;
180 int flags = 0;
181 int r;
182
183 memset(&hdr, 0, sizeof(hdr));
184 hdr.msg_iov = &recv_iov;
185 hdr.msg_iovlen = 1;
186 recv_iov.iov_base = malloc(read_size);
187 recv_iov.iov_len = read_size;
188
189 hdr.msg_control = cmsg_buf;
190 hdr.msg_controllen = sizeof(cmsg_buf);
191
192 r = recvmsg(rcv, &hdr, flags);
193 if (r < 0)
194 error(1, errno, "Failed to recvmsg");
195 if (r != read_size)
196 error(1, 0, "Only received %d bytes of payload.", r);
197
198 if (hdr.msg_flags & (MSG_TRUNC | MSG_CTRUNC))
199 error(1, 0, "Message was truncated.");
200
201 for (cmsg = CMSG_FIRSTHDR(&hdr); cmsg != NULL;
202 cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
203 if (cmsg->cmsg_level != SOL_SOCKET)
204 error(1, 0, "Unexpected cmsg_level %d",
205 cmsg->cmsg_level);
206 switch (cmsg->cmsg_type) {
207 case SCM_TIMESTAMP:
208 actual.tstamp = true;
209 break;
210 case SCM_TIMESTAMPNS:
211 actual.tstampns = true;
212 break;
213 case SCM_TIMESTAMPING:
214 ts = (struct scm_timestamping *)CMSG_DATA(cmsg);
215 actual.swtstamp = !!ts->ts[0].tv_sec;
216 if (ts->ts[1].tv_sec != 0)
217 error(0, 0, "ts[1] should not be set.");
218 actual.hwtstamp = !!ts->ts[2].tv_sec;
219 break;
220 default:
221 error(1, 0, "Unexpected cmsg_type %d", cmsg->cmsg_type);
222 }
223 }
224
225#define VALIDATE(field) \
226 do { \
227 if (expected.field != actual.field) { \
228 if (expected.field) \
229 error(0, 0, "Expected " #field " to be set."); \
230 else \
231 error(0, 0, \
232 "Expected " #field " to not be set."); \
233 failed = true; \
234 } \
235 } while (0)
236
237 VALIDATE(tstamp);
238 VALIDATE(tstampns);
239 VALIDATE(swtstamp);
240 VALIDATE(hwtstamp);
241#undef VALIDATE
242
243 free(recv_iov.iov_base);
244
245 return failed;
246}
247
248void config_so_flags(int rcv, struct options o)
249{
250 int on = 1;
251
252 if (setsockopt(rcv, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
253 error(1, errno, "Failed to enable SO_REUSEADDR");
254
255 if (o.so_timestamp &&
256 setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMP,
257 &o.so_timestamp, sizeof(o.so_timestamp)) < 0)
258 error(1, errno, "Failed to enable SO_TIMESTAMP");
259
260 if (o.so_timestampns &&
261 setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMPNS,
262 &o.so_timestampns, sizeof(o.so_timestampns)) < 0)
263 error(1, errno, "Failed to enable SO_TIMESTAMPNS");
264
265 if (o.so_timestamping &&
266 setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMPING,
267 &o.so_timestamping, sizeof(o.so_timestamping)) < 0)
268 error(1, errno, "Failed to set SO_TIMESTAMPING");
269}
270
271bool run_test_case(struct socket_type s, struct test_case t)
272{
273 int port = (s.type == SOCK_RAW) ? 0 : next_port++;
274 int read_size = op_size;
275 struct sockaddr_in addr;
276 bool failed = false;
277 int src, dst, rcv;
278
279 src = socket(AF_INET, s.type, s.protocol);
280 if (src < 0)
281 error(1, errno, "Failed to open src socket");
282
283 dst = socket(AF_INET, s.type, s.protocol);
284 if (dst < 0)
285 error(1, errno, "Failed to open dst socket");
286
287 memset(&addr, 0, sizeof(addr));
288 addr.sin_family = AF_INET;
289 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
290 addr.sin_port = htons(port);
291
292 if (bind(dst, (struct sockaddr *)&addr, sizeof(addr)) < 0)
293 error(1, errno, "Failed to bind to port %d", port);
294
295 if (s.type == SOCK_STREAM && (listen(dst, 1) < 0))
296 error(1, errno, "Failed to listen");
297
298 if (connect(src, (struct sockaddr *)&addr, sizeof(addr)) < 0)
299 error(1, errno, "Failed to connect");
300
301 if (s.type == SOCK_STREAM) {
302 rcv = accept(dst, NULL, NULL);
303 if (rcv < 0)
304 error(1, errno, "Failed to accept");
305 close(dst);
306 } else {
307 rcv = dst;
308 }
309
310 config_so_flags(rcv, t.sockopt);
311 usleep(20000); /* setsockopt for SO_TIMESTAMPING is asynchronous */
312 do_send(src);
313
314 if (s.type == SOCK_RAW)
315 read_size += 20; /* for IP header */
316 failed = do_recv(rcv, read_size, t.expected);
317
318 close(rcv);
319 close(src);
320
321 return failed;
322}
323
324int main(int argc, char **argv)
325{
326 bool all_protocols = true;
327 bool all_tests = true;
328 int arg_index = 0;
329 int failures = 0;
330 int s, t;
331 char opt;
332
333 while ((opt = getopt_long(argc, argv, "", long_options,
334 &arg_index)) != -1) {
335 switch (opt) {
336 case 'l':
337 for (t = 0; t < ARRAY_SIZE(test_cases); t++) {
338 printf("%d\t", t);
339 print_test_case(&test_cases[t]);
340 }
341 return 0;
342 case 'n':
343 t = atoi(optarg);
344 if (t >= ARRAY_SIZE(test_cases))
345 error(1, 0, "Invalid test case: %d", t);
346 all_tests = false;
347 test_cases[t].enabled = true;
348 break;
349 case 's':
350 op_size = atoi(optarg);
351 break;
352 case 't':
353 all_protocols = false;
354 socket_types[2].enabled = true;
355 break;
356 case 'u':
357 all_protocols = false;
358 socket_types[1].enabled = true;
359 break;
360 case 'i':
361 all_protocols = false;
362 socket_types[0].enabled = true;
363 break;
364 default:
365 error(1, 0, "Failed to parse parameters.");
366 }
367 }
368
369 for (s = 0; s < ARRAY_SIZE(socket_types); s++) {
370 if (!all_protocols && !socket_types[s].enabled)
371 continue;
372
373 printf("Testing %s...\n", socket_types[s].friendly_name);
374 for (t = 0; t < ARRAY_SIZE(test_cases); t++) {
375 if (!all_tests && !test_cases[t].enabled)
376 continue;
377
378 printf("Starting testcase %d...\n", t);
379 if (run_test_case(socket_types[s], test_cases[t])) {
380 failures++;
381 printf("FAILURE in test case ");
382 print_test_case(&test_cases[t]);
383 }
384 }
385 }
386 if (!failures)
387 printf("PASSED.\n");
388 return failures;
389}
diff --git a/tools/testing/selftests/nsfs/config b/tools/testing/selftests/nsfs/config
new file mode 100644
index 000000000000..598d0a225fc9
--- /dev/null
+++ b/tools/testing/selftests/nsfs/config
@@ -0,0 +1,3 @@
1CONFIG_USER_NS=y
2CONFIG_UTS_NS=y
3CONFIG_PID_NS=y
diff --git a/tools/testing/selftests/nsfs/owner.c b/tools/testing/selftests/nsfs/owner.c
index 437205f8b714..96a976c74550 100644
--- a/tools/testing/selftests/nsfs/owner.c
+++ b/tools/testing/selftests/nsfs/owner.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2#include <sched.h> 3#include <sched.h>
3#include <unistd.h> 4#include <unistd.h>
diff --git a/tools/testing/selftests/nsfs/pidns.c b/tools/testing/selftests/nsfs/pidns.c
index ae3a0d68e966..1182d4e437a2 100644
--- a/tools/testing/selftests/nsfs/pidns.c
+++ b/tools/testing/selftests/nsfs/pidns.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2#include <sched.h> 3#include <sched.h>
3#include <unistd.h> 4#include <unistd.h>
diff --git a/tools/testing/selftests/ntb/ntb_test.sh b/tools/testing/selftests/ntb/ntb_test.sh
index 1c12b5855e4f..5fc7ad359e21 100755
--- a/tools/testing/selftests/ntb/ntb_test.sh
+++ b/tools/testing/selftests/ntb/ntb_test.sh
@@ -333,6 +333,10 @@ function ntb_tool_tests()
333 link_test $LOCAL_TOOL $REMOTE_TOOL 333 link_test $LOCAL_TOOL $REMOTE_TOOL
334 link_test $REMOTE_TOOL $LOCAL_TOOL 334 link_test $REMOTE_TOOL $LOCAL_TOOL
335 335
336 #Ensure the link is up on both sides before continuing
337 write_file Y $LOCAL_TOOL/link_event
338 write_file Y $REMOTE_TOOL/link_event
339
336 for PEER_TRANS in $(ls $LOCAL_TOOL/peer_trans*); do 340 for PEER_TRANS in $(ls $LOCAL_TOOL/peer_trans*); do
337 PT=$(basename $PEER_TRANS) 341 PT=$(basename $PEER_TRANS)
338 write_file $MW_SIZE $LOCAL_TOOL/$PT 342 write_file $MW_SIZE $LOCAL_TOOL/$PT
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index 72c3ac2323e1..f6b1338730db 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# Makefile for powerpc selftests 2# Makefile for powerpc selftests
2 3
3# ARCH can be overridden by the user for cross compiling 4# ARCH can be overridden by the user for cross compiling
diff --git a/tools/testing/selftests/powerpc/benchmarks/Makefile b/tools/testing/selftests/powerpc/benchmarks/Makefile
index fb96a89bd953..a35058e3766c 100644
--- a/tools/testing/selftests/powerpc/benchmarks/Makefile
+++ b/tools/testing/selftests/powerpc/benchmarks/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1TEST_GEN_PROGS := gettimeofday context_switch mmap_bench futex_bench null_syscall 2TEST_GEN_PROGS := gettimeofday context_switch mmap_bench futex_bench null_syscall
2 3
3CFLAGS += -O2 4CFLAGS += -O2
diff --git a/tools/testing/selftests/powerpc/benchmarks/context_switch.c b/tools/testing/selftests/powerpc/benchmarks/context_switch.c
index f4241339edd2..87f1f0252299 100644
--- a/tools/testing/selftests/powerpc/benchmarks/context_switch.c
+++ b/tools/testing/selftests/powerpc/benchmarks/context_switch.c
@@ -10,6 +10,7 @@
10 */ 10 */
11 11
12#define _GNU_SOURCE 12#define _GNU_SOURCE
13#include <errno.h>
13#include <sched.h> 14#include <sched.h>
14#include <string.h> 15#include <string.h>
15#include <stdio.h> 16#include <stdio.h>
@@ -75,6 +76,7 @@ static void touch(void)
75 76
76static void start_thread_on(void *(*fn)(void *), void *arg, unsigned long cpu) 77static void start_thread_on(void *(*fn)(void *), void *arg, unsigned long cpu)
77{ 78{
79 int rc;
78 pthread_t tid; 80 pthread_t tid;
79 cpu_set_t cpuset; 81 cpu_set_t cpuset;
80 pthread_attr_t attr; 82 pthread_attr_t attr;
@@ -82,14 +84,23 @@ static void start_thread_on(void *(*fn)(void *), void *arg, unsigned long cpu)
82 CPU_ZERO(&cpuset); 84 CPU_ZERO(&cpuset);
83 CPU_SET(cpu, &cpuset); 85 CPU_SET(cpu, &cpuset);
84 86
85 pthread_attr_init(&attr); 87 rc = pthread_attr_init(&attr);
88 if (rc) {
89 errno = rc;
90 perror("pthread_attr_init");
91 exit(1);
92 }
86 93
87 if (pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset)) { 94 rc = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
95 if (rc) {
96 errno = rc;
88 perror("pthread_attr_setaffinity_np"); 97 perror("pthread_attr_setaffinity_np");
89 exit(1); 98 exit(1);
90 } 99 }
91 100
92 if (pthread_create(&tid, &attr, fn, arg)) { 101 rc = pthread_create(&tid, &attr, fn, arg);
102 if (rc) {
103 errno = rc;
93 perror("pthread_create"); 104 perror("pthread_create");
94 exit(1); 105 exit(1);
95 } 106 }
diff --git a/tools/testing/selftests/powerpc/cache_shape/Makefile b/tools/testing/selftests/powerpc/cache_shape/Makefile
index b24485ab30e2..1be547434a49 100644
--- a/tools/testing/selftests/powerpc/cache_shape/Makefile
+++ b/tools/testing/selftests/powerpc/cache_shape/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1TEST_PROGS := cache_shape 2TEST_PROGS := cache_shape
2 3
3all: $(TEST_PROGS) 4all: $(TEST_PROGS)
diff --git a/tools/testing/selftests/powerpc/copyloops/Makefile b/tools/testing/selftests/powerpc/copyloops/Makefile
index 681ab19d0a84..ac4a52e19e59 100644
--- a/tools/testing/selftests/powerpc/copyloops/Makefile
+++ b/tools/testing/selftests/powerpc/copyloops/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# The loops are all 64-bit code 2# The loops are all 64-bit code
2CFLAGS += -m64 3CFLAGS += -m64
3CFLAGS += -I$(CURDIR) 4CFLAGS += -I$(CURDIR)
diff --git a/tools/testing/selftests/powerpc/copyloops/asm/export.h b/tools/testing/selftests/powerpc/copyloops/asm/export.h
index 2d14a9b4248c..0bab35f6777a 100644
--- a/tools/testing/selftests/powerpc/copyloops/asm/export.h
+++ b/tools/testing/selftests/powerpc/copyloops/asm/export.h
@@ -1 +1,2 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#define EXPORT_SYMBOL(x) 2#define EXPORT_SYMBOL(x)
diff --git a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
index 80d34a9ffff4..5ffe04d802c9 100644
--- a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
+++ b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include <ppc-asm.h> 2#include <ppc-asm.h>
2 3
3#define CONFIG_ALTIVEC 4#define CONFIG_ALTIVEC
diff --git a/tools/testing/selftests/powerpc/copyloops/validate.c b/tools/testing/selftests/powerpc/copyloops/validate.c
index 7fb436f82d16..0f6873618552 100644
--- a/tools/testing/selftests/powerpc/copyloops/validate.c
+++ b/tools/testing/selftests/powerpc/copyloops/validate.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <malloc.h> 2#include <malloc.h>
2#include <string.h> 3#include <string.h>
3#include <stdlib.h> 4#include <stdlib.h>
diff --git a/tools/testing/selftests/powerpc/dscr/Makefile b/tools/testing/selftests/powerpc/dscr/Makefile
index c5639deb8887..55d7db7a616b 100644
--- a/tools/testing/selftests/powerpc/dscr/Makefile
+++ b/tools/testing/selftests/powerpc/dscr/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1TEST_GEN_PROGS := dscr_default_test dscr_explicit_test dscr_user_test \ 2TEST_GEN_PROGS := dscr_default_test dscr_explicit_test dscr_user_test \
2 dscr_inherit_test dscr_inherit_exec_test dscr_sysfs_test \ 3 dscr_inherit_test dscr_inherit_exec_test dscr_sysfs_test \
3 dscr_sysfs_thread_test 4 dscr_sysfs_thread_test
diff --git a/tools/testing/selftests/powerpc/dscr/dscr.h b/tools/testing/selftests/powerpc/dscr/dscr.h
index 18ea223bd398..cdb840bc54f2 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr.h
+++ b/tools/testing/selftests/powerpc/dscr/dscr.h
@@ -39,7 +39,7 @@
39#define rmb() asm volatile("lwsync":::"memory") 39#define rmb() asm volatile("lwsync":::"memory")
40#define wmb() asm volatile("lwsync":::"memory") 40#define wmb() asm volatile("lwsync":::"memory")
41 41
42#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) 42#define READ_ONCE(x) (*(volatile typeof(x) *)&(x))
43 43
44/* Prilvilege state DSCR access */ 44/* Prilvilege state DSCR access */
45inline unsigned long get_dscr(void) 45inline unsigned long get_dscr(void)
diff --git a/tools/testing/selftests/powerpc/dscr/dscr_default_test.c b/tools/testing/selftests/powerpc/dscr/dscr_default_test.c
index df17c3bab0a7..9e1a37e93b63 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr_default_test.c
+++ b/tools/testing/selftests/powerpc/dscr/dscr_default_test.c
@@ -27,7 +27,7 @@ static void *do_test(void *in)
27 unsigned long d, cur_dscr, cur_dscr_usr; 27 unsigned long d, cur_dscr, cur_dscr_usr;
28 unsigned long s1, s2; 28 unsigned long s1, s2;
29 29
30 s1 = ACCESS_ONCE(sequence); 30 s1 = READ_ONCE(sequence);
31 if (s1 & 1) 31 if (s1 & 1)
32 continue; 32 continue;
33 rmb(); 33 rmb();
diff --git a/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c b/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c
index 17fb1b43c320..1899bd85121f 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c
+++ b/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c
@@ -53,6 +53,8 @@ static int check_all_cpu_dscr_defaults(unsigned long val)
53 } 53 }
54 54
55 while ((dp = readdir(sysfs))) { 55 while ((dp = readdir(sysfs))) {
56 int len;
57
56 if (!(dp->d_type & DT_DIR)) 58 if (!(dp->d_type & DT_DIR))
57 continue; 59 continue;
58 if (!strcmp(dp->d_name, "cpuidle")) 60 if (!strcmp(dp->d_name, "cpuidle"))
@@ -60,7 +62,9 @@ static int check_all_cpu_dscr_defaults(unsigned long val)
60 if (!strstr(dp->d_name, "cpu")) 62 if (!strstr(dp->d_name, "cpu"))
61 continue; 63 continue;
62 64
63 sprintf(file, "%s%s/dscr", CPU_PATH, dp->d_name); 65 len = snprintf(file, LEN_MAX, "%s%s/dscr", CPU_PATH, dp->d_name);
66 if (len >= LEN_MAX)
67 continue;
64 if (access(file, F_OK)) 68 if (access(file, F_OK))
65 continue; 69 continue;
66 70
diff --git a/tools/testing/selftests/powerpc/include/basic_asm.h b/tools/testing/selftests/powerpc/include/basic_asm.h
index 12eaddf72e66..886dc026fe7a 100644
--- a/tools/testing/selftests/powerpc/include/basic_asm.h
+++ b/tools/testing/selftests/powerpc/include/basic_asm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _SELFTESTS_POWERPC_BASIC_ASM_H 2#ifndef _SELFTESTS_POWERPC_BASIC_ASM_H
2#define _SELFTESTS_POWERPC_BASIC_ASM_H 3#define _SELFTESTS_POWERPC_BASIC_ASM_H
3 4
diff --git a/tools/testing/selftests/powerpc/include/instructions.h b/tools/testing/selftests/powerpc/include/instructions.h
index 0fb0bd3b28c9..f36061eb6f0f 100644
--- a/tools/testing/selftests/powerpc/include/instructions.h
+++ b/tools/testing/selftests/powerpc/include/instructions.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _SELFTESTS_POWERPC_INSTRUCTIONS_H 2#ifndef _SELFTESTS_POWERPC_INSTRUCTIONS_H
2#define _SELFTESTS_POWERPC_INSTRUCTIONS_H 3#define _SELFTESTS_POWERPC_INSTRUCTIONS_H
3 4
diff --git a/tools/testing/selftests/powerpc/math/Makefile b/tools/testing/selftests/powerpc/math/Makefile
index fa8bae920c91..0dd3a01fdab9 100644
--- a/tools/testing/selftests/powerpc/math/Makefile
+++ b/tools/testing/selftests/powerpc/math/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1TEST_GEN_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal vsx_preempt 2TEST_GEN_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal vsx_preempt
2 3
3include ../../lib.mk 4include ../../lib.mk
diff --git a/tools/testing/selftests/powerpc/mm/Makefile b/tools/testing/selftests/powerpc/mm/Makefile
index 1cffe54dccfb..bf315bcbe663 100644
--- a/tools/testing/selftests/powerpc/mm/Makefile
+++ b/tools/testing/selftests/powerpc/mm/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1noarg: 2noarg:
2 $(MAKE) -C ../ 3 $(MAKE) -C ../
3 4
diff --git a/tools/testing/selftests/powerpc/mm/hugetlb_vs_thp_test.c b/tools/testing/selftests/powerpc/mm/hugetlb_vs_thp_test.c
index 49003674de4f..9932359ce38f 100644
--- a/tools/testing/selftests/powerpc/mm/hugetlb_vs_thp_test.c
+++ b/tools/testing/selftests/powerpc/mm/hugetlb_vs_thp_test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <sys/mman.h> 3#include <sys/mman.h>
3#include <unistd.h> 4#include <unistd.h>
diff --git a/tools/testing/selftests/powerpc/pmu/Makefile b/tools/testing/selftests/powerpc/pmu/Makefile
index e4e55d1d3e0f..6e1629bf5b09 100644
--- a/tools/testing/selftests/powerpc/pmu/Makefile
+++ b/tools/testing/selftests/powerpc/pmu/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1noarg: 2noarg:
2 $(MAKE) -C ../ 3 $(MAKE) -C ../
3 4
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/Makefile b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
index 6001fb0a377a..c4e64bc2e265 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/Makefile
+++ b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1noarg: 2noarg:
2 $(MAKE) -C ../../ 3 $(MAKE) -C ../../
3 4
diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile
index fe6bc60dfc60..480305266504 100644
--- a/tools/testing/selftests/powerpc/ptrace/Makefile
+++ b/tools/testing/selftests/powerpc/ptrace/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ 2TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \
2 ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \ 3 ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \
3 ptrace-tm-spd-vsx ptrace-tm-spr 4 ptrace-tm-spd-vsx ptrace-tm-spr
@@ -6,7 +7,7 @@ include ../../lib.mk
6 7
7all: $(TEST_PROGS) 8all: $(TEST_PROGS)
8 9
9CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm 10CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm -fno-pie
10 11
11$(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h 12$(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h
12 13
diff --git a/tools/testing/selftests/powerpc/signal/Makefile b/tools/testing/selftests/powerpc/signal/Makefile
index f0eef27458e2..a7cbd5082e27 100644
--- a/tools/testing/selftests/powerpc/signal/Makefile
+++ b/tools/testing/selftests/powerpc/signal/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1TEST_PROGS := signal signal_tm 2TEST_PROGS := signal signal_tm
2 3
3all: $(TEST_PROGS) 4all: $(TEST_PROGS)
diff --git a/tools/testing/selftests/powerpc/stringloops/Makefile b/tools/testing/selftests/powerpc/stringloops/Makefile
index 557b9379f3bb..1125e489055e 100644
--- a/tools/testing/selftests/powerpc/stringloops/Makefile
+++ b/tools/testing/selftests/powerpc/stringloops/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# The loops are all 64-bit code 2# The loops are all 64-bit code
2CFLAGS += -m64 3CFLAGS += -m64
3CFLAGS += -I$(CURDIR) 4CFLAGS += -I$(CURDIR)
diff --git a/tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h b/tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h
index 11bece87e880..136242ec4b0e 100644
--- a/tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h
+++ b/tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include <ppc-asm.h> 2#include <ppc-asm.h>
2 3
3#ifndef r1 4#ifndef r1
diff --git a/tools/testing/selftests/powerpc/stringloops/memcmp.c b/tools/testing/selftests/powerpc/stringloops/memcmp.c
index 30b1222380ca..8250db25b379 100644
--- a/tools/testing/selftests/powerpc/stringloops/memcmp.c
+++ b/tools/testing/selftests/powerpc/stringloops/memcmp.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <malloc.h> 2#include <malloc.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <string.h> 4#include <string.h>
diff --git a/tools/testing/selftests/powerpc/switch_endian/Makefile b/tools/testing/selftests/powerpc/switch_endian/Makefile
index b92c2a132c4f..30b8ff8fb82e 100644
--- a/tools/testing/selftests/powerpc/switch_endian/Makefile
+++ b/tools/testing/selftests/powerpc/switch_endian/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1TEST_GEN_PROGS := switch_endian_test 2TEST_GEN_PROGS := switch_endian_test
2 3
3ASFLAGS += -O2 -Wall -g -nostdlib -m64 4ASFLAGS += -O2 -Wall -g -nostdlib -m64
diff --git a/tools/testing/selftests/powerpc/switch_endian/check.S b/tools/testing/selftests/powerpc/switch_endian/check.S
index e2484d2c24f4..927a5c675e83 100644
--- a/tools/testing/selftests/powerpc/switch_endian/check.S
+++ b/tools/testing/selftests/powerpc/switch_endian/check.S
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include "common.h" 2#include "common.h"
2 3
3/* 4/*
diff --git a/tools/testing/selftests/powerpc/switch_endian/common.h b/tools/testing/selftests/powerpc/switch_endian/common.h
index 69e399698c64..1434cbc2a6ad 100644
--- a/tools/testing/selftests/powerpc/switch_endian/common.h
+++ b/tools/testing/selftests/powerpc/switch_endian/common.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include <ppc-asm.h> 2#include <ppc-asm.h>
2#include <asm/unistd.h> 3#include <asm/unistd.h>
3 4
diff --git a/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S b/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
index ef7c971abb67..cc4930467235 100644
--- a/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
+++ b/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include "common.h" 2#include "common.h"
2 3
3 .data 4 .data
@@ -8,7 +9,7 @@ message:
8 .section ".toc" 9 .section ".toc"
9 .balign 8 10 .balign 8
10pattern: 11pattern:
11 .llong 0x5555AAAA5555AAAA 12 .8byte 0x5555AAAA5555AAAA
12 13
13 .text 14 .text
14FUNC_START(_start) 15FUNC_START(_start)
diff --git a/tools/testing/selftests/powerpc/syscalls/ipc.h b/tools/testing/selftests/powerpc/syscalls/ipc.h
index fbebc022edf6..26a20682c9a4 100644
--- a/tools/testing/selftests/powerpc/syscalls/ipc.h
+++ b/tools/testing/selftests/powerpc/syscalls/ipc.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifdef __NR_semop 2#ifdef __NR_semop
2DO_TEST(semop, __NR_semop) 3DO_TEST(semop, __NR_semop)
3#endif 4#endif
diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore
index 2f1f7b013293..241a4a4ee0e4 100644
--- a/tools/testing/selftests/powerpc/tm/.gitignore
+++ b/tools/testing/selftests/powerpc/tm/.gitignore
@@ -12,3 +12,4 @@ tm-signal-context-chk-gpr
12tm-signal-context-chk-vmx 12tm-signal-context-chk-vmx
13tm-signal-context-chk-vsx 13tm-signal-context-chk-vsx
14tm-vmx-unavail 14tm-vmx-unavail
15tm-unavailable
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 958c11c14acd..8ed6f8c57230 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,8 +1,9 @@
1# SPDX-License-Identifier: GPL-2.0
1SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu \ 2SIGNAL_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 tm-signal-context-chk-vmx tm-signal-context-chk-vsx
3 4
4TEST_GEN_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \ 5TEST_GEN_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \
5 tm-vmxcopy tm-fork tm-tar tm-tmspr tm-vmx-unavail \ 6 tm-vmxcopy tm-fork tm-tar tm-tmspr tm-vmx-unavail tm-unavailable \
6 $(SIGNAL_CONTEXT_CHK_TESTS) 7 $(SIGNAL_CONTEXT_CHK_TESTS)
7 8
8include ../../lib.mk 9include ../../lib.mk
@@ -15,6 +16,8 @@ $(OUTPUT)/tm-syscall: tm-syscall-asm.S
15$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include 16$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include
16$(OUTPUT)/tm-tmspr: CFLAGS += -pthread 17$(OUTPUT)/tm-tmspr: CFLAGS += -pthread
17$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64 18$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64
19$(OUTPUT)/tm-resched-dscr: ../pmu/lib.o
20$(OUTPUT)/tm-unavailable: CFLAGS += -O0 -pthread -m64 -Wno-error=uninitialized -mvsx
18 21
19SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS)) 22SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS))
20$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S 23$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
diff --git a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
index e79ccd6aada1..4cdb83964bb3 100644
--- a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* Test context switching to see if the DSCR SPR is correctly preserved 2/* Test context switching to see if the DSCR SPR is correctly preserved
2 * when within a transaction. 3 * when within a transaction.
3 * 4 *
@@ -30,6 +31,7 @@
30 31
31#include "utils.h" 32#include "utils.h"
32#include "tm.h" 33#include "tm.h"
34#include "../pmu/lib.h"
33 35
34#define SPRN_DSCR 0x03 36#define SPRN_DSCR 0x03
35 37
@@ -75,8 +77,6 @@ int test_body(void)
75 ); 77 );
76 assert(rv); /* make sure the transaction aborted */ 78 assert(rv); /* make sure the transaction aborted */
77 if ((texasr >> 56) != TM_CAUSE_RESCHED) { 79 if ((texasr >> 56) != TM_CAUSE_RESCHED) {
78 putchar('.');
79 fflush(stdout);
80 continue; 80 continue;
81 } 81 }
82 if (dscr2 != dscr1) { 82 if (dscr2 != dscr1) {
@@ -89,7 +89,12 @@ int test_body(void)
89 } 89 }
90} 90}
91 91
92int main(void) 92static int tm_resched_dscr(void)
93{ 93{
94 return test_harness(test_body, "tm_resched_dscr"); 94 return eat_cpu(test_body);
95}
96
97int main(int argc, const char *argv[])
98{
99 return test_harness(tm_resched_dscr, "tm_resched_dscr");
95} 100}
diff --git a/tools/testing/selftests/powerpc/tm/tm-syscall-asm.S b/tools/testing/selftests/powerpc/tm/tm-syscall-asm.S
index 431f61ae2368..bd1ca25febe4 100644
--- a/tools/testing/selftests/powerpc/tm/tm-syscall-asm.S
+++ b/tools/testing/selftests/powerpc/tm/tm-syscall-asm.S
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include <ppc-asm.h> 2#include <ppc-asm.h>
2#include <asm/unistd.h> 3#include <asm/unistd.h>
3 4
diff --git a/tools/testing/selftests/powerpc/tm/tm-unavailable.c b/tools/testing/selftests/powerpc/tm/tm-unavailable.c
new file mode 100644
index 000000000000..96c37f84ce54
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-unavailable.c
@@ -0,0 +1,371 @@
1/*
2 * Copyright 2017, Gustavo Romero, Breno Leitao, Cyril Bur, IBM Corp.
3 * Licensed under GPLv2.
4 *
5 * Force FP, VEC and VSX unavailable exception during transaction in all
6 * possible scenarios regarding the MSR.FP and MSR.VEC state, e.g. when FP
7 * is enable and VEC is disable, when FP is disable and VEC is enable, and
8 * so on. Then we check if the restored state is correctly set for the
9 * FP and VEC registers to the previous state we set just before we entered
10 * in TM, i.e. we check if it corrupts somehow the recheckpointed FP and
11 * VEC/Altivec registers on abortion due to an unavailable exception in TM.
12 * N.B. In this test we do not test all the FP/Altivec/VSX registers for
13 * corruption, but only for registers vs0 and vs32, which are respectively
14 * representatives of FP and VEC/Altivec reg sets.
15 */
16
17#define _GNU_SOURCE
18#include <stdio.h>
19#include <stdlib.h>
20#include <unistd.h>
21#include <inttypes.h>
22#include <stdbool.h>
23#include <pthread.h>
24#include <sched.h>
25
26#include "tm.h"
27
28#define DEBUG 0
29
30/* Unavailable exceptions to test in HTM */
31#define FP_UNA_EXCEPTION 0
32#define VEC_UNA_EXCEPTION 1
33#define VSX_UNA_EXCEPTION 2
34
35#define NUM_EXCEPTIONS 3
36
37struct Flags {
38 int touch_fp;
39 int touch_vec;
40 int result;
41 int exception;
42} flags;
43
44bool expecting_failure(void)
45{
46 if (flags.touch_fp && flags.exception == FP_UNA_EXCEPTION)
47 return false;
48
49 if (flags.touch_vec && flags.exception == VEC_UNA_EXCEPTION)
50 return false;
51
52 /*
53 * If both FP and VEC are touched it does not mean that touching VSX
54 * won't raise an exception. However since FP and VEC state are already
55 * correctly loaded, the transaction is not aborted (i.e.
56 * treclaimed/trecheckpointed) and MSR.VSX is just set as 1, so a TM
57 * failure is not expected also in this case.
58 */
59 if ((flags.touch_fp && flags.touch_vec) &&
60 flags.exception == VSX_UNA_EXCEPTION)
61 return false;
62
63 return true;
64}
65
66/* Check if failure occurred whilst in transaction. */
67bool is_failure(uint64_t condition_reg)
68{
69 /*
70 * When failure handling occurs, CR0 is set to 0b1010 (0xa). Otherwise
71 * transaction completes without failure and hence reaches out 'tend.'
72 * that sets CR0 to 0b0100 (0x4).
73 */
74 return ((condition_reg >> 28) & 0xa) == 0xa;
75}
76
77void *ping(void *input)
78{
79
80 /*
81 * Expected values for vs0 and vs32 after a TM failure. They must never
82 * change, otherwise they got corrupted.
83 */
84 uint64_t high_vs0 = 0x5555555555555555;
85 uint64_t low_vs0 = 0xffffffffffffffff;
86 uint64_t high_vs32 = 0x5555555555555555;
87 uint64_t low_vs32 = 0xffffffffffffffff;
88
89 /* Counter for busy wait */
90 uint64_t counter = 0x1ff000000;
91
92 /*
93 * Variable to keep a copy of CR register content taken just after we
94 * leave the transactional state.
95 */
96 uint64_t cr_ = 0;
97
98 /*
99 * Wait a bit so thread can get its name "ping". This is not important
100 * to reproduce the issue but it's nice to have for systemtap debugging.
101 */
102 if (DEBUG)
103 sleep(1);
104
105 printf("If MSR.FP=%d MSR.VEC=%d: ", flags.touch_fp, flags.touch_vec);
106
107 if (flags.exception != FP_UNA_EXCEPTION &&
108 flags.exception != VEC_UNA_EXCEPTION &&
109 flags.exception != VSX_UNA_EXCEPTION) {
110 printf("No valid exception specified to test.\n");
111 return NULL;
112 }
113
114 asm (
115 /* Prepare to merge low and high. */
116 " mtvsrd 33, %[high_vs0] ;"
117 " mtvsrd 34, %[low_vs0] ;"
118
119 /*
120 * Adjust VS0 expected value after an TM failure,
121 * i.e. vs0 = 0x5555555555555555555FFFFFFFFFFFFFFFF
122 */
123 " xxmrghd 0, 33, 34 ;"
124
125 /*
126 * Adjust VS32 expected value after an TM failure,
127 * i.e. vs32 = 0x5555555555555555555FFFFFFFFFFFFFFFF
128 */
129 " xxmrghd 32, 33, 34 ;"
130
131 /*
132 * Wait an amount of context switches so load_fp and load_vec
133 * overflow and MSR.FP, MSR.VEC, and MSR.VSX become zero (off).
134 */
135 " mtctr %[counter] ;"
136
137 /* Decrement CTR branch if CTR non zero. */
138 "1: bdnz 1b ;"
139
140 /*
141 * Check if we want to touch FP prior to the test in order
142 * to set MSR.FP = 1 before provoking an unavailable
143 * exception in TM.
144 */
145 " cmpldi %[touch_fp], 0 ;"
146 " beq no_fp ;"
147 " fadd 10, 10, 10 ;"
148 "no_fp: ;"
149
150 /*
151 * Check if we want to touch VEC prior to the test in order
152 * to set MSR.VEC = 1 before provoking an unavailable
153 * exception in TM.
154 */
155 " cmpldi %[touch_vec], 0 ;"
156 " beq no_vec ;"
157 " vaddcuw 10, 10, 10 ;"
158 "no_vec: ;"
159
160 /*
161 * Perhaps it would be a better idea to do the
162 * compares outside transactional context and simply
163 * duplicate code.
164 */
165 " tbegin. ;"
166 " beq trans_fail ;"
167
168 /* Do we do FP Unavailable? */
169 " cmpldi %[exception], %[ex_fp] ;"
170 " bne 1f ;"
171 " fadd 10, 10, 10 ;"
172 " b done ;"
173
174 /* Do we do VEC Unavailable? */
175 "1: cmpldi %[exception], %[ex_vec] ;"
176 " bne 2f ;"
177 " vaddcuw 10, 10, 10 ;"
178 " b done ;"
179
180 /*
181 * Not FP or VEC, therefore VSX. Ensure this
182 * instruction always generates a VSX Unavailable.
183 * ISA 3.0 is tricky here.
184 * (xxmrghd will on ISA 2.07 and ISA 3.0)
185 */
186 "2: xxmrghd 10, 10, 10 ;"
187
188 "done: tend. ;"
189
190 "trans_fail: ;"
191
192 /* Give values back to C. */
193 " mfvsrd %[high_vs0], 0 ;"
194 " xxsldwi 3, 0, 0, 2 ;"
195 " mfvsrd %[low_vs0], 3 ;"
196 " mfvsrd %[high_vs32], 32 ;"
197 " xxsldwi 3, 32, 32, 2 ;"
198 " mfvsrd %[low_vs32], 3 ;"
199
200 /* Give CR back to C so that it can check what happened. */
201 " mfcr %[cr_] ;"
202
203 : [high_vs0] "+r" (high_vs0),
204 [low_vs0] "+r" (low_vs0),
205 [high_vs32] "=r" (high_vs32),
206 [low_vs32] "=r" (low_vs32),
207 [cr_] "+r" (cr_)
208 : [touch_fp] "r" (flags.touch_fp),
209 [touch_vec] "r" (flags.touch_vec),
210 [exception] "r" (flags.exception),
211 [ex_fp] "i" (FP_UNA_EXCEPTION),
212 [ex_vec] "i" (VEC_UNA_EXCEPTION),
213 [ex_vsx] "i" (VSX_UNA_EXCEPTION),
214 [counter] "r" (counter)
215
216 : "cr0", "ctr", "v10", "vs0", "vs10", "vs3", "vs32", "vs33",
217 "vs34", "fr10"
218
219 );
220
221 /*
222 * Check if we were expecting a failure and it did not occur by checking
223 * CR0 state just after we leave the transaction. Either way we check if
224 * vs0 or vs32 got corrupted.
225 */
226 if (expecting_failure() && !is_failure(cr_)) {
227 printf("\n\tExpecting the transaction to fail, %s",
228 "but it didn't\n\t");
229 flags.result++;
230 }
231
232 /* Check if we were not expecting a failure and a it occurred. */
233 if (!expecting_failure() && is_failure(cr_)) {
234 printf("\n\tUnexpected transaction failure 0x%02lx\n\t",
235 failure_code());
236 return (void *) -1;
237 }
238
239 /*
240 * Check if TM failed due to the cause we were expecting. 0xda is a
241 * TM_CAUSE_FAC_UNAV cause, otherwise it's an unexpected cause.
242 */
243 if (is_failure(cr_) && !failure_is_unavailable()) {
244 printf("\n\tUnexpected failure cause 0x%02lx\n\t",
245 failure_code());
246 return (void *) -1;
247 }
248
249 /* 0x4 is a success and 0xa is a fail. See comment in is_failure(). */
250 if (DEBUG)
251 printf("CR0: 0x%1lx ", cr_ >> 28);
252
253 /* Check FP (vs0) for the expected value. */
254 if (high_vs0 != 0x5555555555555555 || low_vs0 != 0xFFFFFFFFFFFFFFFF) {
255 printf("FP corrupted!");
256 printf(" high = %#16" PRIx64 " low = %#16" PRIx64 " ",
257 high_vs0, low_vs0);
258 flags.result++;
259 } else
260 printf("FP ok ");
261
262 /* Check VEC (vs32) for the expected value. */
263 if (high_vs32 != 0x5555555555555555 || low_vs32 != 0xFFFFFFFFFFFFFFFF) {
264 printf("VEC corrupted!");
265 printf(" high = %#16" PRIx64 " low = %#16" PRIx64,
266 high_vs32, low_vs32);
267 flags.result++;
268 } else
269 printf("VEC ok");
270
271 putchar('\n');
272
273 return NULL;
274}
275
276/* Thread to force context switch */
277void *pong(void *not_used)
278{
279 /* Wait thread get its name "pong". */
280 if (DEBUG)
281 sleep(1);
282
283 /* Classed as an interactive-like thread. */
284 while (1)
285 sched_yield();
286}
287
288/* Function that creates a thread and launches the "ping" task. */
289void test_fp_vec(int fp, int vec, pthread_attr_t *attr)
290{
291 int retries = 2;
292 void *ret_value;
293 pthread_t t0;
294
295 flags.touch_fp = fp;
296 flags.touch_vec = vec;
297
298 /*
299 * Without luck it's possible that the transaction is aborted not due to
300 * the unavailable exception caught in the middle as we expect but also,
301 * for instance, due to a context switch or due to a KVM reschedule (if
302 * it's running on a VM). Thus we try a few times before giving up,
303 * checking if the failure cause is the one we expect.
304 */
305 do {
306 /* Bind 'ping' to CPU 0, as specified in 'attr'. */
307 pthread_create(&t0, attr, ping, (void *) &flags);
308 pthread_setname_np(t0, "ping");
309 pthread_join(t0, &ret_value);
310 retries--;
311 } while (ret_value != NULL && retries);
312
313 if (!retries) {
314 flags.result = 1;
315 if (DEBUG)
316 printf("All transactions failed unexpectedly\n");
317
318 }
319}
320
321int main(int argc, char **argv)
322{
323 int exception; /* FP = 0, VEC = 1, VSX = 2 */
324 pthread_t t1;
325 pthread_attr_t attr;
326 cpu_set_t cpuset;
327
328 /* Set only CPU 0 in the mask. Both threads will be bound to CPU 0. */
329 CPU_ZERO(&cpuset);
330 CPU_SET(0, &cpuset);
331
332 /* Init pthread attribute. */
333 pthread_attr_init(&attr);
334
335 /* Set CPU 0 mask into the pthread attribute. */
336 pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
337
338 pthread_create(&t1, &attr /* Bind 'pong' to CPU 0 */, pong, NULL);
339 pthread_setname_np(t1, "pong"); /* Name it for systemtap convenience */
340
341 flags.result = 0;
342
343 for (exception = 0; exception < NUM_EXCEPTIONS; exception++) {
344 printf("Checking if FP/VEC registers are sane after");
345
346 if (exception == FP_UNA_EXCEPTION)
347 printf(" a FP unavailable exception...\n");
348
349 else if (exception == VEC_UNA_EXCEPTION)
350 printf(" a VEC unavailable exception...\n");
351
352 else
353 printf(" a VSX unavailable exception...\n");
354
355 flags.exception = exception;
356
357 test_fp_vec(0, 0, &attr);
358 test_fp_vec(1, 0, &attr);
359 test_fp_vec(0, 1, &attr);
360 test_fp_vec(1, 1, &attr);
361
362 }
363
364 if (flags.result > 0) {
365 printf("result: failed!\n");
366 exit(1);
367 } else {
368 printf("result: success\n");
369 exit(0);
370 }
371}
diff --git a/tools/testing/selftests/powerpc/tm/tm.h b/tools/testing/selftests/powerpc/tm/tm.h
index 0ffff04433c5..df4204247d45 100644
--- a/tools/testing/selftests/powerpc/tm/tm.h
+++ b/tools/testing/selftests/powerpc/tm/tm.h
@@ -47,6 +47,11 @@ static inline bool failure_is_syscall(void)
47 return (failure_code() & TM_CAUSE_SYSCALL) == TM_CAUSE_SYSCALL; 47 return (failure_code() & TM_CAUSE_SYSCALL) == TM_CAUSE_SYSCALL;
48} 48}
49 49
50static inline bool failure_is_unavailable(void)
51{
52 return (failure_code() & TM_CAUSE_FAC_UNAV) == TM_CAUSE_FAC_UNAV;
53}
54
50static inline bool failure_is_nesting(void) 55static inline bool failure_is_nesting(void)
51{ 56{
52 return (__builtin_get_texasru() & 0x400000); 57 return (__builtin_get_texasru() & 0x400000);
diff --git a/tools/testing/selftests/powerpc/vphn/test-vphn.c b/tools/testing/selftests/powerpc/vphn/test-vphn.c
index 5742f6876b25..81d3069ffb84 100644
--- a/tools/testing/selftests/powerpc/vphn/test-vphn.c
+++ b/tools/testing/selftests/powerpc/vphn/test-vphn.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <stdio.h> 2#include <stdio.h>
2#include <byteswap.h> 3#include <byteswap.h>
3#include "utils.h" 4#include "utils.h"
diff --git a/tools/testing/selftests/prctl/Makefile b/tools/testing/selftests/prctl/Makefile
index 35aa1c8f2df2..c7923b205222 100644
--- a/tools/testing/selftests/prctl/Makefile
+++ b/tools/testing/selftests/prctl/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1ifndef CROSS_COMPILE 2ifndef CROSS_COMPILE
2uname_M := $(shell uname -m 2>/dev/null || echo not) 3uname_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/) 4ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
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
index f7499d1c0415..62a93cc61b7c 100644
--- a/tools/testing/selftests/prctl/disable-tsc-ctxt-sw-stress-test.c
+++ b/tools/testing/selftests/prctl/disable-tsc-ctxt-sw-stress-test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...) 3 * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
3 * 4 *
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
index a06f027e9d16..79950f9a26fd 100644
--- a/tools/testing/selftests/prctl/disable-tsc-on-off-stress-test.c
+++ b/tools/testing/selftests/prctl/disable-tsc-on-off-stress-test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...) 3 * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
3 * 4 *
diff --git a/tools/testing/selftests/prctl/disable-tsc-test.c b/tools/testing/selftests/prctl/disable-tsc-test.c
index 8d494f7bebdb..f84d4ee111d3 100644
--- a/tools/testing/selftests/prctl/disable-tsc-test.c
+++ b/tools/testing/selftests/prctl/disable-tsc-test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...) 3 * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
3 * 4 *
diff --git a/tools/testing/selftests/pstore/.gitignore b/tools/testing/selftests/pstore/.gitignore
new file mode 100644
index 000000000000..5a4a26e5464b
--- /dev/null
+++ b/tools/testing/selftests/pstore/.gitignore
@@ -0,0 +1,2 @@
1logs
2*uuid
diff --git a/tools/testing/selftests/pstore/Makefile b/tools/testing/selftests/pstore/Makefile
index c5f2440ba1f7..5ef57855a2be 100644
--- a/tools/testing/selftests/pstore/Makefile
+++ b/tools/testing/selftests/pstore/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# Makefile for pstore selftests. 2# Makefile for pstore selftests.
2# Expects pstore backend is registered. 3# Expects pstore backend is registered.
3 4
diff --git a/tools/testing/selftests/ptp/Makefile b/tools/testing/selftests/ptp/Makefile
index 83dd42b2129e..ef06de0898b7 100644
--- a/tools/testing/selftests/ptp/Makefile
+++ b/tools/testing/selftests/ptp/Makefile
@@ -1,3 +1,5 @@
1# SPDX-License-Identifier: GPL-2.0
2CFLAGS += -I../../../../usr/include/
1TEST_PROGS := testptp 3TEST_PROGS := testptp
2LDLIBS += -lrt 4LDLIBS += -lrt
3all: $(TEST_PROGS) 5all: $(TEST_PROGS)
diff --git a/tools/testing/selftests/ptrace/peeksiginfo.c b/tools/testing/selftests/ptrace/peeksiginfo.c
index c34cd8ac8aaa..54900657eb44 100644
--- a/tools/testing/selftests/ptrace/peeksiginfo.c
+++ b/tools/testing/selftests/ptrace/peeksiginfo.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2#include <stdio.h> 3#include <stdio.h>
3#include <signal.h> 4#include <signal.h>
diff --git a/tools/testing/selftests/rcutorture/bin/config_override.sh b/tools/testing/selftests/rcutorture/bin/config_override.sh
new file mode 100755
index 000000000000..ef7fcbac3d42
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/bin/config_override.sh
@@ -0,0 +1,61 @@
1#!/bin/bash
2#
3# config_override.sh base override
4#
5# Combines base and override, removing any Kconfig options from base
6# that conflict with any in override, concatenating what remains and
7# sending the result to standard output.
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 as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, you can access it online at
21# http://www.gnu.org/licenses/gpl-2.0.html.
22#
23# Copyright (C) IBM Corporation, 2017
24#
25# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
26
27base=$1
28if test -r $base
29then
30 :
31else
32 echo Base file $base unreadable!!!
33 exit 1
34fi
35
36override=$2
37if test -r $override
38then
39 :
40else
41 echo Override file $override unreadable!!!
42 exit 1
43fi
44
45T=${TMPDIR-/tmp}/config_override.sh.$$
46trap 'rm -rf $T' 0
47mkdir $T
48
49sed < $override -e 's/^/grep -v "/' -e 's/=.*$/="/' |
50 awk '
51 {
52 if (last)
53 print last " |";
54 last = $0;
55 }
56 END {
57 if (last)
58 print last;
59 }' > $T/script
60sh $T/script < $base
61cat $override
diff --git a/tools/testing/selftests/rcutorture/bin/configcheck.sh b/tools/testing/selftests/rcutorture/bin/configcheck.sh
index 70fca318a82b..197deece7c7c 100755
--- a/tools/testing/selftests/rcutorture/bin/configcheck.sh
+++ b/tools/testing/selftests/rcutorture/bin/configcheck.sh
@@ -19,7 +19,7 @@
19# 19#
20# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 20# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
21 21
22T=/tmp/abat-chk-config.sh.$$ 22T=${TMPDIR-/tmp}/abat-chk-config.sh.$$
23trap 'rm -rf $T' 0 23trap 'rm -rf $T' 0
24mkdir $T 24mkdir $T
25 25
diff --git a/tools/testing/selftests/rcutorture/bin/configinit.sh b/tools/testing/selftests/rcutorture/bin/configinit.sh
index 3f81a1095206..51f66a7ce876 100755
--- a/tools/testing/selftests/rcutorture/bin/configinit.sh
+++ b/tools/testing/selftests/rcutorture/bin/configinit.sh
@@ -32,7 +32,7 @@
32# 32#
33# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 33# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
34 34
35T=/tmp/configinit.sh.$$ 35T=${TMPDIR-/tmp}/configinit.sh.$$
36trap 'rm -rf $T' 0 36trap 'rm -rf $T' 0
37mkdir $T 37mkdir $T
38 38
diff --git a/tools/testing/selftests/rcutorture/bin/functions.sh b/tools/testing/selftests/rcutorture/bin/functions.sh
index 1426a9b97494..07a13779eece 100644
--- a/tools/testing/selftests/rcutorture/bin/functions.sh
+++ b/tools/testing/selftests/rcutorture/bin/functions.sh
@@ -66,9 +66,34 @@ configfrag_boot_params () {
66 66
67# configfrag_boot_cpus bootparam-string config-fragment-file config-cpus 67# configfrag_boot_cpus bootparam-string config-fragment-file config-cpus
68# 68#
69# Decreases number of CPUs based on any maxcpus= boot parameters specified. 69# Decreases number of CPUs based on any nr_cpus= boot parameters specified.
70configfrag_boot_cpus () { 70configfrag_boot_cpus () {
71 local bootargs="`configfrag_boot_params "$1" "$2"`" 71 local bootargs="`configfrag_boot_params "$1" "$2"`"
72 local nr_cpus
73 if echo "${bootargs}" | grep -q 'nr_cpus=[0-9]'
74 then
75 nr_cpus="`echo "${bootargs}" | sed -e 's/^.*nr_cpus=\([0-9]*\).*$/\1/'`"
76 if test "$3" -gt "$nr_cpus"
77 then
78 echo $nr_cpus
79 else
80 echo $3
81 fi
82 else
83 echo $3
84 fi
85}
86
87# configfrag_boot_maxcpus bootparam-string config-fragment-file config-cpus
88#
89# Decreases number of CPUs based on any maxcpus= boot parameters specified.
90# This allows tests where additional CPUs come online later during the
91# test run. However, the torture parameters will be set based on the
92# number of CPUs initially present, so the scripting should schedule
93# test runs based on the maxcpus= boot parameter controlling the initial
94# number of CPUs instead of on the ultimate number of CPUs.
95configfrag_boot_maxcpus () {
96 local bootargs="`configfrag_boot_params "$1" "$2"`"
72 local maxcpus 97 local maxcpus
73 if echo "${bootargs}" | grep -q 'maxcpus=[0-9]' 98 if echo "${bootargs}" | grep -q 'maxcpus=[0-9]'
74 then 99 then
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-build.sh b/tools/testing/selftests/rcutorture/bin/kvm-build.sh
index c29f2ec0bf9f..fb66d0173638 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-build.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-build.sh
@@ -2,7 +2,7 @@
2# 2#
3# Build a kvm-ready Linux kernel from the tree in the current directory. 3# Build a kvm-ready Linux kernel from the tree in the current directory.
4# 4#
5# Usage: kvm-build.sh config-template build-dir more-configs 5# Usage: kvm-build.sh config-template build-dir
6# 6#
7# This program is free software; you can redistribute it and/or modify 7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by 8# it under the terms of the GNU General Public License as published by
@@ -34,24 +34,17 @@ then
34 echo "kvm-build.sh :$builddir: Not a writable directory, cannot build into it" 34 echo "kvm-build.sh :$builddir: Not a writable directory, cannot build into it"
35 exit 1 35 exit 1
36fi 36fi
37moreconfigs=${3}
38if test -z "$moreconfigs" -o ! -r "$moreconfigs"
39then
40 echo "kvm-build.sh :$moreconfigs: Not a readable file"
41 exit 1
42fi
43 37
44T=/tmp/test-linux.sh.$$ 38T=${TMPDIR-/tmp}/test-linux.sh.$$
45trap 'rm -rf $T' 0 39trap 'rm -rf $T' 0
46mkdir $T 40mkdir $T
47 41
48grep -v 'CONFIG_[A-Z]*_TORTURE_TEST=' < ${config_template} > $T/config 42cp ${config_template} $T/config
49cat << ___EOF___ >> $T/config 43cat << ___EOF___ >> $T/config
50CONFIG_INITRAMFS_SOURCE="$TORTURE_INITRD" 44CONFIG_INITRAMFS_SOURCE="$TORTURE_INITRD"
51CONFIG_VIRTIO_PCI=y 45CONFIG_VIRTIO_PCI=y
52CONFIG_VIRTIO_CONSOLE=y 46CONFIG_VIRTIO_CONSOLE=y
53___EOF___ 47___EOF___
54cat $moreconfigs >> $T/config
55 48
56configinit.sh $T/config O=$builddir 49configinit.sh $T/config O=$builddir
57retval=$? 50retval=$?
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 93eede4e8fbe..ab14b97c942c 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
@@ -38,9 +38,9 @@
38# 38#
39# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 39# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
40 40
41T=/tmp/kvm-test-1-run.sh.$$ 41T=${TMPDIR-/tmp}/kvm-test-1-run.sh.$$
42trap 'rm -rf $T' 0 42trap 'rm -rf $T' 0
43touch $T 43mkdir $T
44 44
45. $KVM/bin/functions.sh 45. $KVM/bin/functions.sh
46. $CONFIGFRAG/ver_functions.sh 46. $CONFIGFRAG/ver_functions.sh
@@ -60,37 +60,33 @@ then
60 echo "kvm-test-1-run.sh :$resdir: Not a writable directory, cannot store results into it" 60 echo "kvm-test-1-run.sh :$resdir: Not a writable directory, cannot store results into it"
61 exit 1 61 exit 1
62fi 62fi
63cp $config_template $resdir/ConfigFragment
64echo ' ---' `date`: Starting build 63echo ' ---' `date`: Starting build
65echo ' ---' Kconfig fragment at: $config_template >> $resdir/log 64echo ' ---' Kconfig fragment at: $config_template >> $resdir/log
65touch $resdir/ConfigFragment.input $resdir/ConfigFragment
66if test -r "$config_dir/CFcommon" 66if test -r "$config_dir/CFcommon"
67then 67then
68 cat < $config_dir/CFcommon >> $T 68 echo " --- $config_dir/CFcommon" >> $resdir/ConfigFragment.input
69 cat < $config_dir/CFcommon >> $resdir/ConfigFragment.input
70 config_override.sh $config_dir/CFcommon $config_template > $T/Kc1
71 grep '#CHECK#' $config_dir/CFcommon >> $resdir/ConfigFragment
72else
73 cp $config_template $T/Kc1
69fi 74fi
70# Optimizations below this point 75echo " --- $config_template" >> $resdir/ConfigFragment.input
71# CONFIG_USB=n 76cat $config_template >> $resdir/ConfigFragment.input
72# CONFIG_SECURITY=n 77grep '#CHECK#' $config_template >> $resdir/ConfigFragment
73# CONFIG_NFS_FS=n 78if test -n "$TORTURE_KCONFIG_ARG"
74# CONFIG_SOUND=n 79then
75# CONFIG_INPUT_JOYSTICK=n 80 echo $TORTURE_KCONFIG_ARG | tr -s " " "\012" > $T/cmdline
76# CONFIG_INPUT_TABLET=n 81 echo " --- --kconfig argument" >> $resdir/ConfigFragment.input
77# CONFIG_INPUT_TOUCHSCREEN=n 82 cat $T/cmdline >> $resdir/ConfigFragment.input
78# CONFIG_INPUT_MISC=n 83 config_override.sh $T/Kc1 $T/cmdline > $T/Kc2
79# CONFIG_INPUT_MOUSE=n 84 # Note that "#CHECK#" is not permitted on commandline.
80# # CONFIG_NET=n # disables console access, so accept the slower build. 85else
81# CONFIG_SCSI=n 86 cp $T/Kc1 $T/Kc2
82# CONFIG_ATA=n 87fi
83# CONFIG_FAT_FS=n 88cat $T/Kc2 >> $resdir/ConfigFragment
84# CONFIG_MSDOS_FS=n 89
85# CONFIG_VFAT_FS=n
86# CONFIG_ISO9660_FS=n
87# CONFIG_QUOTA=n
88# CONFIG_HID=n
89# CONFIG_CRYPTO=n
90# CONFIG_PCCARD=n
91# CONFIG_PCMCIA=n
92# CONFIG_CARDBUS=n
93# CONFIG_YENTA=n
94base_resdir=`echo $resdir | sed -e 's/\.[0-9]\+$//'` 90base_resdir=`echo $resdir | sed -e 's/\.[0-9]\+$//'`
95if test "$base_resdir" != "$resdir" -a -f $base_resdir/bzImage -a -f $base_resdir/vmlinux 91if test "$base_resdir" != "$resdir" -a -f $base_resdir/bzImage -a -f $base_resdir/vmlinux
96then 92then
@@ -100,7 +96,9 @@ then
100 KERNEL=$base_resdir/${BOOT_IMAGE##*/} # use the last component of ${BOOT_IMAGE} 96 KERNEL=$base_resdir/${BOOT_IMAGE##*/} # use the last component of ${BOOT_IMAGE}
101 ln -s $base_resdir/Make*.out $resdir # for kvm-recheck.sh 97 ln -s $base_resdir/Make*.out $resdir # for kvm-recheck.sh
102 ln -s $base_resdir/.config $resdir # for kvm-recheck.sh 98 ln -s $base_resdir/.config $resdir # for kvm-recheck.sh
103elif kvm-build.sh $config_template $builddir $T 99 # Arch-independent indicator
100 touch $resdir/builtkernel
101elif kvm-build.sh $T/Kc2 $builddir
104then 102then
105 # Had to build a kernel for this test. 103 # Had to build a kernel for this test.
106 QEMU="`identify_qemu $builddir/vmlinux`" 104 QEMU="`identify_qemu $builddir/vmlinux`"
@@ -112,6 +110,8 @@ then
112 then 110 then
113 cp $builddir/$BOOT_IMAGE $resdir 111 cp $builddir/$BOOT_IMAGE $resdir
114 KERNEL=$resdir/${BOOT_IMAGE##*/} 112 KERNEL=$resdir/${BOOT_IMAGE##*/}
113 # Arch-independent indicator
114 touch $resdir/builtkernel
115 else 115 else
116 echo No identifiable boot image, not running KVM, see $resdir. 116 echo No identifiable boot image, not running KVM, see $resdir.
117 echo Do the torture scripts know about your architecture? 117 echo Do the torture scripts know about your architecture?
@@ -149,7 +149,7 @@ fi
149 149
150# Generate -smp qemu argument. 150# Generate -smp qemu argument.
151qemu_args="-enable-kvm -nographic $qemu_args" 151qemu_args="-enable-kvm -nographic $qemu_args"
152cpu_count=`configNR_CPUS.sh $config_template` 152cpu_count=`configNR_CPUS.sh $resdir/ConfigFragment`
153cpu_count=`configfrag_boot_cpus "$boot_args" "$config_template" "$cpu_count"` 153cpu_count=`configfrag_boot_cpus "$boot_args" "$config_template" "$cpu_count"`
154vcpus=`identify_qemu_vcpus` 154vcpus=`identify_qemu_vcpus`
155if test $cpu_count -gt $vcpus 155if test $cpu_count -gt $vcpus
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 50091de3a911..ccd49e958fd2 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -30,7 +30,7 @@
30scriptname=$0 30scriptname=$0
31args="$*" 31args="$*"
32 32
33T=/tmp/kvm.sh.$$ 33T=${TMPDIR-/tmp}/kvm.sh.$$
34trap 'rm -rf $T' 0 34trap 'rm -rf $T' 0
35mkdir $T 35mkdir $T
36 36
@@ -41,6 +41,7 @@ PATH=${KVM}/bin:$PATH; export PATH
41TORTURE_DEFCONFIG=defconfig 41TORTURE_DEFCONFIG=defconfig
42TORTURE_BOOT_IMAGE="" 42TORTURE_BOOT_IMAGE=""
43TORTURE_INITRD="$KVM/initrd"; export TORTURE_INITRD 43TORTURE_INITRD="$KVM/initrd"; export TORTURE_INITRD
44TORTURE_KCONFIG_ARG=""
44TORTURE_KMAKE_ARG="" 45TORTURE_KMAKE_ARG=""
45TORTURE_SHUTDOWN_GRACE=180 46TORTURE_SHUTDOWN_GRACE=180
46TORTURE_SUITE=rcu 47TORTURE_SUITE=rcu
@@ -65,6 +66,7 @@ usage () {
65 echo " --duration minutes" 66 echo " --duration minutes"
66 echo " --interactive" 67 echo " --interactive"
67 echo " --jitter N [ maxsleep (us) [ maxspin (us) ] ]" 68 echo " --jitter N [ maxsleep (us) [ maxspin (us) ] ]"
69 echo " --kconfig Kconfig-options"
68 echo " --kmake-arg kernel-make-arguments" 70 echo " --kmake-arg kernel-make-arguments"
69 echo " --mac nn:nn:nn:nn:nn:nn" 71 echo " --mac nn:nn:nn:nn:nn:nn"
70 echo " --no-initrd" 72 echo " --no-initrd"
@@ -129,6 +131,11 @@ do
129 jitter="$2" 131 jitter="$2"
130 shift 132 shift
131 ;; 133 ;;
134 --kconfig)
135 checkarg --kconfig "(Kconfig options)" $# "$2" '^CONFIG_[A-Z0-9_]\+=\([ynm]\|[0-9]\+\)\( CONFIG_[A-Z0-9_]\+=\([ynm]\|[0-9]\+\)\)*$' '^error$'
136 TORTURE_KCONFIG_ARG="$2"
137 shift
138 ;;
132 --kmake-arg) 139 --kmake-arg)
133 checkarg --kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$' 140 checkarg --kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$'
134 TORTURE_KMAKE_ARG="$2" 141 TORTURE_KMAKE_ARG="$2"
@@ -205,6 +212,7 @@ do
205 then 212 then
206 cpu_count=`configNR_CPUS.sh $CONFIGFRAG/$CF1` 213 cpu_count=`configNR_CPUS.sh $CONFIGFRAG/$CF1`
207 cpu_count=`configfrag_boot_cpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$CF1" "$cpu_count"` 214 cpu_count=`configfrag_boot_cpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$CF1" "$cpu_count"`
215 cpu_count=`configfrag_boot_maxcpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$CF1" "$cpu_count"`
208 for ((cur_rep=0;cur_rep<$config_reps;cur_rep++)) 216 for ((cur_rep=0;cur_rep<$config_reps;cur_rep++))
209 do 217 do
210 echo $CF1 $cpu_count >> $T/cfgcpu 218 echo $CF1 $cpu_count >> $T/cfgcpu
@@ -214,7 +222,7 @@ do
214 exit 1 222 exit 1
215 fi 223 fi
216done 224done
217sort -k2nr $T/cfgcpu > $T/cfgcpu.sort 225sort -k2nr $T/cfgcpu -T="$T" > $T/cfgcpu.sort
218 226
219# Use a greedy bin-packing algorithm, sorting the list accordingly. 227# Use a greedy bin-packing algorithm, sorting the list accordingly.
220awk < $T/cfgcpu.sort > $T/cfgcpu.pack -v ncpus=$cpus ' 228awk < $T/cfgcpu.sort > $T/cfgcpu.pack -v ncpus=$cpus '
@@ -275,6 +283,7 @@ TORTURE_BOOT_IMAGE="$TORTURE_BOOT_IMAGE"; export TORTURE_BOOT_IMAGE
275TORTURE_BUILDONLY="$TORTURE_BUILDONLY"; export TORTURE_BUILDONLY 283TORTURE_BUILDONLY="$TORTURE_BUILDONLY"; export TORTURE_BUILDONLY
276TORTURE_DEFCONFIG="$TORTURE_DEFCONFIG"; export TORTURE_DEFCONFIG 284TORTURE_DEFCONFIG="$TORTURE_DEFCONFIG"; export TORTURE_DEFCONFIG
277TORTURE_INITRD="$TORTURE_INITRD"; export TORTURE_INITRD 285TORTURE_INITRD="$TORTURE_INITRD"; export TORTURE_INITRD
286TORTURE_KCONFIG_ARG="$TORTURE_KCONFIG_ARG"; export TORTURE_KCONFIG_ARG
278TORTURE_KMAKE_ARG="$TORTURE_KMAKE_ARG"; export TORTURE_KMAKE_ARG 287TORTURE_KMAKE_ARG="$TORTURE_KMAKE_ARG"; export TORTURE_KMAKE_ARG
279TORTURE_QEMU_CMD="$TORTURE_QEMU_CMD"; export TORTURE_QEMU_CMD 288TORTURE_QEMU_CMD="$TORTURE_QEMU_CMD"; export TORTURE_QEMU_CMD
280TORTURE_QEMU_INTERACTIVE="$TORTURE_QEMU_INTERACTIVE"; export TORTURE_QEMU_INTERACTIVE 289TORTURE_QEMU_INTERACTIVE="$TORTURE_QEMU_INTERACTIVE"; export TORTURE_QEMU_INTERACTIVE
@@ -324,6 +333,7 @@ function dump(first, pastlast, batchnum)
324{ 333{
325 print "echo ----Start batch " batchnum ": `date`"; 334 print "echo ----Start batch " batchnum ": `date`";
326 print "echo ----Start batch " batchnum ": `date` >> " rd "/log"; 335 print "echo ----Start batch " batchnum ": `date` >> " rd "/log";
336 print "needqemurun="
327 jn=1 337 jn=1
328 for (j = first; j < pastlast; j++) { 338 for (j = first; j < pastlast; j++) {
329 builddir=KVM "/b" jn 339 builddir=KVM "/b" jn
@@ -359,10 +369,11 @@ function dump(first, pastlast, batchnum)
359 for (j = 1; j < jn; j++) { 369 for (j = 1; j < jn; j++) {
360 builddir=KVM "/b" j 370 builddir=KVM "/b" j
361 print "rm -f " builddir ".ready" 371 print "rm -f " builddir ".ready"
362 print "if test -z \"$TORTURE_BUILDONLY\"" 372 print "if test -f \"" rd cfr[j] "/builtkernel\""
363 print "then" 373 print "then"
364 print "\techo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date`"; 374 print "\techo ----", cfr[j], cpusr[j] ovf ": Kernel present. `date`";
365 print "\techo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date` >> " rd "/log"; 375 print "\techo ----", cfr[j], cpusr[j] ovf ": Kernel present. `date` >> " rd "/log";
376 print "\tneedqemurun=1"
366 print "fi" 377 print "fi"
367 } 378 }
368 njitter = 0; 379 njitter = 0;
@@ -377,13 +388,22 @@ function dump(first, pastlast, batchnum)
377 njitter = 0; 388 njitter = 0;
378 print "echo Build-only run, so suppressing jitter >> " rd "/log" 389 print "echo Build-only run, so suppressing jitter >> " rd "/log"
379 } 390 }
380 for (j = 0; j < njitter; j++) 391 if (TORTURE_BUILDONLY) {
381 print "jitter.sh " j " " dur " " ja[2] " " ja[3] "&" 392 print "needqemurun="
382 print "wait" 393 }
383 print "if test -z \"$TORTURE_BUILDONLY\"" 394 print "if test -n \"$needqemurun\""
384 print "then" 395 print "then"
396 print "\techo ---- Starting kernels. `date`";
397 print "\techo ---- Starting kernels. `date` >> " rd "/log";
398 for (j = 0; j < njitter; j++)
399 print "\tjitter.sh " j " " dur " " ja[2] " " ja[3] "&"
400 print "\twait"
385 print "\techo ---- All kernel runs complete. `date`"; 401 print "\techo ---- All kernel runs complete. `date`";
386 print "\techo ---- All kernel runs complete. `date` >> " rd "/log"; 402 print "\techo ---- All kernel runs complete. `date` >> " rd "/log";
403 print "else"
404 print "\twait"
405 print "\techo ---- No kernel runs. `date`";
406 print "\techo ---- No kernel runs. `date` >> " rd "/log";
387 print "fi" 407 print "fi"
388 for (j = 1; j < jn; j++) { 408 for (j = 1; j < jn; j++) {
389 builddir=KVM "/b" j 409 builddir=KVM "/b" j
diff --git a/tools/testing/selftests/rcutorture/bin/parse-build.sh b/tools/testing/selftests/rcutorture/bin/parse-build.sh
index a6b57622c2e5..24fe5f822b28 100755
--- a/tools/testing/selftests/rcutorture/bin/parse-build.sh
+++ b/tools/testing/selftests/rcutorture/bin/parse-build.sh
@@ -28,7 +28,7 @@
28 28
29F=$1 29F=$1
30title=$2 30title=$2
31T=/tmp/parse-build.sh.$$ 31T=${TMPDIR-/tmp}/parse-build.sh.$$
32trap 'rm -rf $T' 0 32trap 'rm -rf $T' 0
33mkdir $T 33mkdir $T
34 34
diff --git a/tools/testing/selftests/rcutorture/bin/parse-torture.sh b/tools/testing/selftests/rcutorture/bin/parse-torture.sh
index e3c5f0705696..f12c38909b00 100755
--- a/tools/testing/selftests/rcutorture/bin/parse-torture.sh
+++ b/tools/testing/selftests/rcutorture/bin/parse-torture.sh
@@ -27,7 +27,7 @@
27# 27#
28# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 28# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
29 29
30T=/tmp/parse-torture.sh.$$ 30T=${TMPDIR-/tmp}/parse-torture.sh.$$
31file="$1" 31file="$1"
32title="$2" 32title="$2"
33 33
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot
index 6804f9dcfc1b..be7728db42fd 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot
@@ -1 +1 @@
rcutorture.torture_type=rcu_busted rcutorture.torture_type=busted
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-C.boot b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-C.boot
deleted file mode 100644
index 84a7d51b7481..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-C.boot
+++ /dev/null
@@ -1 +0,0 @@
1rcutorture.torture_type=srcud
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-u b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-u
index 6bc24e99862f..c15ada821e45 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-u
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-u
@@ -4,6 +4,7 @@ CONFIG_PREEMPT_VOLUNTARY=n
4CONFIG_PREEMPT=n 4CONFIG_PREEMPT=n
5#CHECK#CONFIG_TINY_SRCU=y 5#CHECK#CONFIG_TINY_SRCU=y
6CONFIG_RCU_TRACE=n 6CONFIG_RCU_TRACE=n
7CONFIG_DEBUG_LOCK_ALLOC=n 7CONFIG_DEBUG_LOCK_ALLOC=y
8CONFIG_PROVE_LOCKING=y
8CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 9CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
9CONFIG_PREEMPT_COUNT=n 10CONFIG_PREEMPT_COUNT=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
index 1d14e1383016..9f3a4d28e508 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
@@ -1,4 +1,4 @@
1rcutorture.torture_type=rcu_bh maxcpus=8 1rcutorture.torture_type=rcu_bh maxcpus=8 nr_cpus=43
2rcutree.gp_preinit_delay=3 2rcutree.gp_preinit_delay=3
3rcutree.gp_init_delay=3 3rcutree.gp_init_delay=3
4rcutree.gp_cleanup_delay=3 4rcutree.gp_cleanup_delay=3
diff --git a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
index 9ad3f89c8dc7..af6fca03602f 100644
--- a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
+++ b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
@@ -69,11 +69,11 @@ CONFIG_RCU_TORTURE_TEST_RUNNABLE
69CONFIG_PREEMPT_RCU 69CONFIG_PREEMPT_RCU
70CONFIG_TREE_RCU 70CONFIG_TREE_RCU
71CONFIG_TINY_RCU 71CONFIG_TINY_RCU
72CONFIG_TASKS_RCU
72 73
73 These are controlled by CONFIG_PREEMPT and/or CONFIG_SMP. 74 These are controlled by CONFIG_PREEMPT and/or CONFIG_SMP.
74 75
75CONFIG_SRCU 76CONFIG_SRCU
76CONFIG_TASKS_RCU
77 77
78 Selected by CONFIG_RCU_TORTURE_TEST, so cannot disable. 78 Selected by CONFIG_RCU_TORTURE_TEST, so cannot disable.
79 79
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/Makefile b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/Makefile
index 16b01559fa55..4bed0b678f8b 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/Makefile
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1all: srcu.c store_buffering 2all: srcu.c store_buffering
2 3
3LINUX_SOURCE = ../../../../../.. 4LINUX_SOURCE = ../../../../../..
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h
index 4a3d538fef12..891ad13e95b2 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * This header has been modifies to remove definitions of types that 3 * This header has been modifies to remove definitions of types that
3 * are defined in standard userspace headers or are problematic for some 4 * are defined in standard userspace headers or are problematic for some
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk
index c9e8bc5082a7..e05182d3e47d 100755
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk
@@ -1,4 +1,5 @@
1#!/usr/bin/awk -f 1#!/usr/bin/awk -f
2# SPDX-License-Identifier: GPL-2.0
2 3
3# Modify SRCU for formal verification. The first argument should be srcu.h and 4# Modify SRCU for formal verification. The first argument should be srcu.h and
4# the second should be srcu.c. Outputs modified srcu.h and srcu.c into the 5# the second should be srcu.c. Outputs modified srcu.h and srcu.c into the
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/assume.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/assume.h
index a64955447995..570a49d9da7e 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/assume.h
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/assume.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef ASSUME_H 2#ifndef ASSUME_H
2#define ASSUME_H 3#define ASSUME_H
3 4
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/barriers.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/barriers.h
index 6687acc08e6d..3f95a768a03b 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/barriers.h
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/barriers.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef BARRIERS_H 2#ifndef BARRIERS_H
2#define BARRIERS_H 3#define BARRIERS_H
3 4
@@ -34,8 +35,7 @@
34#define rs_smp_mb() do {} while (0) 35#define rs_smp_mb() do {} while (0)
35#endif 36#endif
36 37
37#define ACCESS_ONCE(x) (*(volatile typeof(x) *) &(x)) 38#define READ_ONCE(x) (*(volatile typeof(x) *) &(x))
38#define READ_ONCE(x) ACCESS_ONCE(x) 39#define WRITE_ONCE(x) ((*(volatile typeof(x) *) &(x)) = (val))
39#define WRITE_ONCE(x, val) (ACCESS_ONCE(x) = (val))
40 40
41#endif 41#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/bug_on.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/bug_on.h
index 2a80e91f78e7..5e7912c6a521 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/bug_on.h
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/bug_on.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef BUG_ON_H 2#ifndef BUG_ON_H
2#define BUG_ON_H 3#define BUG_ON_H
3 4
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/combined_source.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/combined_source.c
index 29eb5d2697ed..e67ee5b3dd7c 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/combined_source.c
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/combined_source.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <config.h> 2#include <config.h>
2 3
3/* Include all source files. */ 4/* Include all source files. */
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/config.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/config.h
index a60038aeea7a..283d7103334f 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/config.h
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/config.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* "Cheater" definitions based on restricted Kconfig choices. */ 2/* "Cheater" definitions based on restricted Kconfig choices. */
2 3
3#undef CONFIG_TINY_RCU 4#undef CONFIG_TINY_RCU
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/include_srcu.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/include_srcu.c
index 5ec582a53018..e5202d4cff30 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/include_srcu.c
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/include_srcu.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <config.h> 2#include <config.h>
2 3
3#include <assert.h> 4#include <assert.h>
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/int_typedefs.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/int_typedefs.h
index 3aad63917858..0dd27aa517a7 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/int_typedefs.h
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/int_typedefs.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef INT_TYPEDEFS_H 2#ifndef INT_TYPEDEFS_H
2#define INT_TYPEDEFS_H 3#define INT_TYPEDEFS_H
3 4
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/locks.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/locks.h
index 356004665576..cf6938d679d7 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/locks.h
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/locks.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef LOCKS_H 2#ifndef LOCKS_H
2#define LOCKS_H 3#define LOCKS_H
3 4
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.c
index ca892e3b2351..9440cc39e3c6 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.c
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <config.h> 2#include <config.h>
2 3
3#include "misc.h" 4#include "misc.h"
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/percpu.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/percpu.h
index 3de5a49de49b..27e67a3f291f 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/percpu.h
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/percpu.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PERCPU_H 2#ifndef PERCPU_H
2#define PERCPU_H 3#define PERCPU_H
3 4
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.c
index 4f1b068e9b7a..b4083ae348fb 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.c
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <config.h> 2#include <config.h>
2 3
3#include "preempt.h" 4#include "preempt.h"
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h
index 2f95ee0e4dd5..f8b762cd214c 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef PREEMPT_H 2#ifndef PREEMPT_H
2#define PREEMPT_H 3#define PREEMPT_H
3 4
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/simple_sync_srcu.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/simple_sync_srcu.c
index ac9cbc62b411..97f592048e0b 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/simple_sync_srcu.c
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/simple_sync_srcu.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <config.h> 2#include <config.h>
2 3
3#include <assert.h> 4#include <assert.h>
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/workqueues.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/workqueues.h
index e58c8dfd3e90..28b960300971 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/workqueues.h
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/workqueues.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef WORKQUEUES_H 2#ifndef WORKQUEUES_H
2#define WORKQUEUES_H 3#define WORKQUEUES_H
3 4
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/Makefile b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/Makefile
index 3a3aee149225..ad21b925fbb4 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/Makefile
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1CBMC_FLAGS = -I../.. -I../../src -I../../include -I../../empty_includes -32 -pointer-check -mm pso 2CBMC_FLAGS = -I../.. -I../../src -I../../include -I../../empty_includes -32 -pointer-check -mm pso
2 3
3all: 4all:
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/test.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/test.c
index 470b1105a112..2ce2016f7871 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/test.c
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <src/combined_source.c> 2#include <src/combined_source.c>
2 3
3int x; 4int x;
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/test_script.sh b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/test_script.sh
index d1545972a0fa..2fe1f0339b4f 100755
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/test_script.sh
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/test_script.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2 3
3# This script expects a mode (either --should-pass or --should-fail) followed by 4# This script expects a mode (either --should-pass or --should-fail) followed by
4# an input file. The script uses the following environment variables. The test C 5# an input file. The script uses the following environment variables. The test C
diff --git a/tools/testing/selftests/seccomp/.gitignore b/tools/testing/selftests/seccomp/.gitignore
index 346d83ca8069..5af29d3a1b0a 100644
--- a/tools/testing/selftests/seccomp/.gitignore
+++ b/tools/testing/selftests/seccomp/.gitignore
@@ -1 +1,2 @@
1seccomp_bpf 1seccomp_bpf
2seccomp_benchmark
diff --git a/tools/testing/selftests/seccomp/Makefile b/tools/testing/selftests/seccomp/Makefile
index aeb0c805f3ca..fce7f4ce0692 100644
--- a/tools/testing/selftests/seccomp/Makefile
+++ b/tools/testing/selftests/seccomp/Makefile
@@ -1,8 +1,17 @@
1TEST_GEN_PROGS := seccomp_bpf 1# SPDX-License-Identifier: GPL-2.0
2CFLAGS += -Wl,-no-as-needed -Wall 2all:
3LDFLAGS += -lpthread
4 3
5include ../lib.mk 4include ../lib.mk
6 5
7$(TEST_GEN_PROGS): seccomp_bpf.c ../kselftest_harness.h 6.PHONY: all clean
8 $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ 7
8BINARIES := seccomp_bpf seccomp_benchmark
9CFLAGS += -Wl,-no-as-needed -Wall
10
11seccomp_bpf: seccomp_bpf.c ../kselftest_harness.h
12 $(CC) $(CFLAGS) $(LDFLAGS) -lpthread $< -o $@
13
14TEST_PROGS += $(BINARIES)
15EXTRA_CLEAN := $(BINARIES)
16
17all: $(BINARIES)
diff --git a/tools/testing/selftests/seccomp/seccomp_benchmark.c b/tools/testing/selftests/seccomp/seccomp_benchmark.c
new file mode 100644
index 000000000000..5838c8697ec3
--- /dev/null
+++ b/tools/testing/selftests/seccomp/seccomp_benchmark.c
@@ -0,0 +1,99 @@
1/*
2 * Strictly speaking, this is not a test. But it can report during test
3 * runs so relative performace can be measured.
4 */
5#define _GNU_SOURCE
6#include <assert.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <time.h>
10#include <unistd.h>
11#include <linux/filter.h>
12#include <linux/seccomp.h>
13#include <sys/prctl.h>
14#include <sys/syscall.h>
15#include <sys/types.h>
16
17#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
18
19unsigned long long timing(clockid_t clk_id, unsigned long long samples)
20{
21 pid_t pid, ret;
22 unsigned long long i;
23 struct timespec start, finish;
24
25 pid = getpid();
26 assert(clock_gettime(clk_id, &start) == 0);
27 for (i = 0; i < samples; i++) {
28 ret = syscall(__NR_getpid);
29 assert(pid == ret);
30 }
31 assert(clock_gettime(clk_id, &finish) == 0);
32
33 i = finish.tv_sec - start.tv_sec;
34 i *= 1000000000;
35 i += finish.tv_nsec - start.tv_nsec;
36
37 printf("%lu.%09lu - %lu.%09lu = %llu\n",
38 finish.tv_sec, finish.tv_nsec,
39 start.tv_sec, start.tv_nsec,
40 i);
41
42 return i;
43}
44
45unsigned long long calibrate(void)
46{
47 unsigned long long i;
48
49 printf("Calibrating reasonable sample size...\n");
50
51 for (i = 5; ; i++) {
52 unsigned long long samples = 1 << i;
53
54 /* Find something that takes more than 5 seconds to run. */
55 if (timing(CLOCK_REALTIME, samples) / 1000000000ULL > 5)
56 return samples;
57 }
58}
59
60int main(int argc, char *argv[])
61{
62 struct sock_filter filter[] = {
63 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
64 };
65 struct sock_fprog prog = {
66 .len = (unsigned short)ARRAY_SIZE(filter),
67 .filter = filter,
68 };
69 long ret;
70 unsigned long long samples;
71 unsigned long long native, filtered;
72
73 if (argc > 1)
74 samples = strtoull(argv[1], NULL, 0);
75 else
76 samples = calibrate();
77
78 printf("Benchmarking %llu samples...\n", samples);
79
80 native = timing(CLOCK_PROCESS_CPUTIME_ID, samples) / samples;
81 printf("getpid native: %llu ns\n", native);
82
83 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
84 assert(ret == 0);
85
86 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
87 assert(ret == 0);
88
89 filtered = timing(CLOCK_PROCESS_CPUTIME_ID, samples) / samples;
90 printf("getpid RET_ALLOW: %llu ns\n", filtered);
91
92 printf("Estimated seccomp overhead per syscall: %llu ns\n",
93 filtered - native);
94
95 if (filtered == native)
96 printf("Trying running again with more samples.\n");
97
98 return 0;
99}
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 73f5ea6778ce..24dbf634e2dd 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -6,10 +6,18 @@
6 */ 6 */
7 7
8#include <sys/types.h> 8#include <sys/types.h>
9#include <asm/siginfo.h> 9
10#define __have_siginfo_t 1 10/*
11#define __have_sigval_t 1 11 * glibc 2.26 and later have SIGSYS in siginfo_t. Before that,
12#define __have_sigevent_t 1 12 * we need to use the kernel's siginfo.h file and trick glibc
13 * into accepting it.
14 */
15#if !__GLIBC_PREREQ(2, 26)
16# include <asm/siginfo.h>
17# define __have_siginfo_t 1
18# define __have_sigval_t 1
19# define __have_sigevent_t 1
20#endif
13 21
14#include <errno.h> 22#include <errno.h>
15#include <linux/filter.h> 23#include <linux/filter.h>
@@ -68,17 +76,7 @@
68#define SECCOMP_MODE_FILTER 2 76#define SECCOMP_MODE_FILTER 2
69#endif 77#endif
70 78
71#ifndef SECCOMP_RET_KILL 79#ifndef SECCOMP_RET_ALLOW
72#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
73#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
74#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
75#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
76#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
77
78/* Masks for the return value sections. */
79#define SECCOMP_RET_ACTION 0x7fff0000U
80#define SECCOMP_RET_DATA 0x0000ffffU
81
82struct seccomp_data { 80struct seccomp_data {
83 int nr; 81 int nr;
84 __u32 arch; 82 __u32 arch;
@@ -87,6 +85,70 @@ struct seccomp_data {
87}; 85};
88#endif 86#endif
89 87
88#ifndef SECCOMP_RET_KILL_PROCESS
89#define SECCOMP_RET_KILL_PROCESS 0x80000000U /* kill the process */
90#define SECCOMP_RET_KILL_THREAD 0x00000000U /* kill the thread */
91#endif
92#ifndef SECCOMP_RET_KILL
93#define SECCOMP_RET_KILL SECCOMP_RET_KILL_THREAD
94#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
95#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
96#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
97#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
98#endif
99#ifndef SECCOMP_RET_LOG
100#define SECCOMP_RET_LOG 0x7ffc0000U /* allow after logging */
101#endif
102
103#ifndef __NR_seccomp
104# if defined(__i386__)
105# define __NR_seccomp 354
106# elif defined(__x86_64__)
107# define __NR_seccomp 317
108# elif defined(__arm__)
109# define __NR_seccomp 383
110# elif defined(__aarch64__)
111# define __NR_seccomp 277
112# elif defined(__hppa__)
113# define __NR_seccomp 338
114# elif defined(__powerpc__)
115# define __NR_seccomp 358
116# elif defined(__s390__)
117# define __NR_seccomp 348
118# else
119# warning "seccomp syscall number unknown for this architecture"
120# define __NR_seccomp 0xffff
121# endif
122#endif
123
124#ifndef SECCOMP_SET_MODE_STRICT
125#define SECCOMP_SET_MODE_STRICT 0
126#endif
127
128#ifndef SECCOMP_SET_MODE_FILTER
129#define SECCOMP_SET_MODE_FILTER 1
130#endif
131
132#ifndef SECCOMP_GET_ACTION_AVAIL
133#define SECCOMP_GET_ACTION_AVAIL 2
134#endif
135
136#ifndef SECCOMP_FILTER_FLAG_TSYNC
137#define SECCOMP_FILTER_FLAG_TSYNC 1
138#endif
139
140#ifndef SECCOMP_FILTER_FLAG_LOG
141#define SECCOMP_FILTER_FLAG_LOG 2
142#endif
143
144#ifndef seccomp
145int seccomp(unsigned int op, unsigned int flags, void *args)
146{
147 errno = 0;
148 return syscall(__NR_seccomp, op, flags, args);
149}
150#endif
151
90#if __BYTE_ORDER == __LITTLE_ENDIAN 152#if __BYTE_ORDER == __LITTLE_ENDIAN
91#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n])) 153#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]))
92#elif __BYTE_ORDER == __BIG_ENDIAN 154#elif __BYTE_ORDER == __BIG_ENDIAN
@@ -107,7 +169,7 @@ TEST(mode_strict_support)
107 ASSERT_EQ(0, ret) { 169 ASSERT_EQ(0, ret) {
108 TH_LOG("Kernel does not support CONFIG_SECCOMP"); 170 TH_LOG("Kernel does not support CONFIG_SECCOMP");
109 } 171 }
110 syscall(__NR_exit, 1); 172 syscall(__NR_exit, 0);
111} 173}
112 174
113TEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL) 175TEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL)
@@ -136,7 +198,7 @@ TEST(no_new_privs_support)
136 } 198 }
137} 199}
138 200
139/* Tests kernel support by checking for a copy_from_user() fault on * NULL. */ 201/* Tests kernel support by checking for a copy_from_user() fault on NULL. */
140TEST(mode_filter_support) 202TEST(mode_filter_support)
141{ 203{
142 long ret; 204 long ret;
@@ -342,6 +404,28 @@ TEST(empty_prog)
342 EXPECT_EQ(EINVAL, errno); 404 EXPECT_EQ(EINVAL, errno);
343} 405}
344 406
407TEST(log_all)
408{
409 struct sock_filter filter[] = {
410 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
411 };
412 struct sock_fprog prog = {
413 .len = (unsigned short)ARRAY_SIZE(filter),
414 .filter = filter,
415 };
416 long ret;
417 pid_t parent = getppid();
418
419 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
420 ASSERT_EQ(0, ret);
421
422 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
423 ASSERT_EQ(0, ret);
424
425 /* getppid() should succeed and be logged (no check for logging) */
426 EXPECT_EQ(parent, syscall(__NR_getppid));
427}
428
345TEST_SIGNAL(unknown_ret_is_kill_inside, SIGSYS) 429TEST_SIGNAL(unknown_ret_is_kill_inside, SIGSYS)
346{ 430{
347 struct sock_filter filter[] = { 431 struct sock_filter filter[] = {
@@ -520,6 +604,117 @@ TEST_SIGNAL(KILL_one_arg_six, SIGSYS)
520 close(fd); 604 close(fd);
521} 605}
522 606
607/* This is a thread task to die via seccomp filter violation. */
608void *kill_thread(void *data)
609{
610 bool die = (bool)data;
611
612 if (die) {
613 prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
614 return (void *)SIBLING_EXIT_FAILURE;
615 }
616
617 return (void *)SIBLING_EXIT_UNKILLED;
618}
619
620/* Prepare a thread that will kill itself or both of us. */
621void kill_thread_or_group(struct __test_metadata *_metadata, bool kill_process)
622{
623 pthread_t thread;
624 void *status;
625 /* Kill only when calling __NR_prctl. */
626 struct sock_filter filter_thread[] = {
627 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
628 offsetof(struct seccomp_data, nr)),
629 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
630 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_THREAD),
631 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
632 };
633 struct sock_fprog prog_thread = {
634 .len = (unsigned short)ARRAY_SIZE(filter_thread),
635 .filter = filter_thread,
636 };
637 struct sock_filter filter_process[] = {
638 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
639 offsetof(struct seccomp_data, nr)),
640 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
641 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_PROCESS),
642 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
643 };
644 struct sock_fprog prog_process = {
645 .len = (unsigned short)ARRAY_SIZE(filter_process),
646 .filter = filter_process,
647 };
648
649 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
650 TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
651 }
652
653 ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0,
654 kill_process ? &prog_process : &prog_thread));
655
656 /*
657 * Add the KILL_THREAD rule again to make sure that the KILL_PROCESS
658 * flag cannot be downgraded by a new filter.
659 */
660 ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog_thread));
661
662 /* Start a thread that will exit immediately. */
663 ASSERT_EQ(0, pthread_create(&thread, NULL, kill_thread, (void *)false));
664 ASSERT_EQ(0, pthread_join(thread, &status));
665 ASSERT_EQ(SIBLING_EXIT_UNKILLED, (unsigned long)status);
666
667 /* Start a thread that will die immediately. */
668 ASSERT_EQ(0, pthread_create(&thread, NULL, kill_thread, (void *)true));
669 ASSERT_EQ(0, pthread_join(thread, &status));
670 ASSERT_NE(SIBLING_EXIT_FAILURE, (unsigned long)status);
671
672 /*
673 * If we get here, only the spawned thread died. Let the parent know
674 * the whole process didn't die (i.e. this thread, the spawner,
675 * stayed running).
676 */
677 exit(42);
678}
679
680TEST(KILL_thread)
681{
682 int status;
683 pid_t child_pid;
684
685 child_pid = fork();
686 ASSERT_LE(0, child_pid);
687 if (child_pid == 0) {
688 kill_thread_or_group(_metadata, false);
689 _exit(38);
690 }
691
692 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
693
694 /* If only the thread was killed, we'll see exit 42. */
695 ASSERT_TRUE(WIFEXITED(status));
696 ASSERT_EQ(42, WEXITSTATUS(status));
697}
698
699TEST(KILL_process)
700{
701 int status;
702 pid_t child_pid;
703
704 child_pid = fork();
705 ASSERT_LE(0, child_pid);
706 if (child_pid == 0) {
707 kill_thread_or_group(_metadata, true);
708 _exit(38);
709 }
710
711 ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
712
713 /* If the entire process was killed, we'll see SIGSYS. */
714 ASSERT_TRUE(WIFSIGNALED(status));
715 ASSERT_EQ(SIGSYS, WTERMSIG(status));
716}
717
523/* TODO(wad) add 64-bit versus 32-bit arg tests. */ 718/* TODO(wad) add 64-bit versus 32-bit arg tests. */
524TEST(arg_out_of_range) 719TEST(arg_out_of_range)
525{ 720{
@@ -541,26 +736,30 @@ TEST(arg_out_of_range)
541 EXPECT_EQ(EINVAL, errno); 736 EXPECT_EQ(EINVAL, errno);
542} 737}
543 738
739#define ERRNO_FILTER(name, errno) \
740 struct sock_filter _read_filter_##name[] = { \
741 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, \
742 offsetof(struct seccomp_data, nr)), \
743 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1), \
744 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | errno), \
745 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), \
746 }; \
747 struct sock_fprog prog_##name = { \
748 .len = (unsigned short)ARRAY_SIZE(_read_filter_##name), \
749 .filter = _read_filter_##name, \
750 }
751
752/* Make sure basic errno values are correctly passed through a filter. */
544TEST(ERRNO_valid) 753TEST(ERRNO_valid)
545{ 754{
546 struct sock_filter filter[] = { 755 ERRNO_FILTER(valid, E2BIG);
547 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
548 offsetof(struct seccomp_data, nr)),
549 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
550 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | E2BIG),
551 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
552 };
553 struct sock_fprog prog = {
554 .len = (unsigned short)ARRAY_SIZE(filter),
555 .filter = filter,
556 };
557 long ret; 756 long ret;
558 pid_t parent = getppid(); 757 pid_t parent = getppid();
559 758
560 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 759 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
561 ASSERT_EQ(0, ret); 760 ASSERT_EQ(0, ret);
562 761
563 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); 762 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_valid);
564 ASSERT_EQ(0, ret); 763 ASSERT_EQ(0, ret);
565 764
566 EXPECT_EQ(parent, syscall(__NR_getppid)); 765 EXPECT_EQ(parent, syscall(__NR_getppid));
@@ -568,26 +767,17 @@ TEST(ERRNO_valid)
568 EXPECT_EQ(E2BIG, errno); 767 EXPECT_EQ(E2BIG, errno);
569} 768}
570 769
770/* Make sure an errno of zero is correctly handled by the arch code. */
571TEST(ERRNO_zero) 771TEST(ERRNO_zero)
572{ 772{
573 struct sock_filter filter[] = { 773 ERRNO_FILTER(zero, 0);
574 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
575 offsetof(struct seccomp_data, nr)),
576 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
577 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | 0),
578 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
579 };
580 struct sock_fprog prog = {
581 .len = (unsigned short)ARRAY_SIZE(filter),
582 .filter = filter,
583 };
584 long ret; 774 long ret;
585 pid_t parent = getppid(); 775 pid_t parent = getppid();
586 776
587 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 777 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
588 ASSERT_EQ(0, ret); 778 ASSERT_EQ(0, ret);
589 779
590 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); 780 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_zero);
591 ASSERT_EQ(0, ret); 781 ASSERT_EQ(0, ret);
592 782
593 EXPECT_EQ(parent, syscall(__NR_getppid)); 783 EXPECT_EQ(parent, syscall(__NR_getppid));
@@ -595,26 +785,21 @@ TEST(ERRNO_zero)
595 EXPECT_EQ(0, read(0, NULL, 0)); 785 EXPECT_EQ(0, read(0, NULL, 0));
596} 786}
597 787
788/*
789 * The SECCOMP_RET_DATA mask is 16 bits wide, but errno is smaller.
790 * This tests that the errno value gets capped correctly, fixed by
791 * 580c57f10768 ("seccomp: cap SECCOMP_RET_ERRNO data to MAX_ERRNO").
792 */
598TEST(ERRNO_capped) 793TEST(ERRNO_capped)
599{ 794{
600 struct sock_filter filter[] = { 795 ERRNO_FILTER(capped, 4096);
601 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
602 offsetof(struct seccomp_data, nr)),
603 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
604 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | 4096),
605 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
606 };
607 struct sock_fprog prog = {
608 .len = (unsigned short)ARRAY_SIZE(filter),
609 .filter = filter,
610 };
611 long ret; 796 long ret;
612 pid_t parent = getppid(); 797 pid_t parent = getppid();
613 798
614 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 799 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
615 ASSERT_EQ(0, ret); 800 ASSERT_EQ(0, ret);
616 801
617 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); 802 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_capped);
618 ASSERT_EQ(0, ret); 803 ASSERT_EQ(0, ret);
619 804
620 EXPECT_EQ(parent, syscall(__NR_getppid)); 805 EXPECT_EQ(parent, syscall(__NR_getppid));
@@ -622,6 +807,37 @@ TEST(ERRNO_capped)
622 EXPECT_EQ(4095, errno); 807 EXPECT_EQ(4095, errno);
623} 808}
624 809
810/*
811 * Filters are processed in reverse order: last applied is executed first.
812 * Since only the SECCOMP_RET_ACTION mask is tested for return values, the
813 * SECCOMP_RET_DATA mask results will follow the most recently applied
814 * matching filter return (and not the lowest or highest value).
815 */
816TEST(ERRNO_order)
817{
818 ERRNO_FILTER(first, 11);
819 ERRNO_FILTER(second, 13);
820 ERRNO_FILTER(third, 12);
821 long ret;
822 pid_t parent = getppid();
823
824 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
825 ASSERT_EQ(0, ret);
826
827 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_first);
828 ASSERT_EQ(0, ret);
829
830 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_second);
831 ASSERT_EQ(0, ret);
832
833 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_third);
834 ASSERT_EQ(0, ret);
835
836 EXPECT_EQ(parent, syscall(__NR_getppid));
837 EXPECT_EQ(-1, read(0, NULL, 0));
838 EXPECT_EQ(12, errno);
839}
840
625FIXTURE_DATA(TRAP) { 841FIXTURE_DATA(TRAP) {
626 struct sock_fprog prog; 842 struct sock_fprog prog;
627}; 843};
@@ -676,7 +892,7 @@ TEST_F_SIGNAL(TRAP, ign, SIGSYS)
676 syscall(__NR_getpid); 892 syscall(__NR_getpid);
677} 893}
678 894
679static struct siginfo TRAP_info; 895static siginfo_t TRAP_info;
680static volatile int TRAP_nr; 896static volatile int TRAP_nr;
681static void TRAP_action(int nr, siginfo_t *info, void *void_context) 897static void TRAP_action(int nr, siginfo_t *info, void *void_context)
682{ 898{
@@ -735,6 +951,7 @@ TEST_F(TRAP, handler)
735 951
736FIXTURE_DATA(precedence) { 952FIXTURE_DATA(precedence) {
737 struct sock_fprog allow; 953 struct sock_fprog allow;
954 struct sock_fprog log;
738 struct sock_fprog trace; 955 struct sock_fprog trace;
739 struct sock_fprog error; 956 struct sock_fprog error;
740 struct sock_fprog trap; 957 struct sock_fprog trap;
@@ -746,6 +963,13 @@ FIXTURE_SETUP(precedence)
746 struct sock_filter allow_insns[] = { 963 struct sock_filter allow_insns[] = {
747 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), 964 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
748 }; 965 };
966 struct sock_filter log_insns[] = {
967 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
968 offsetof(struct seccomp_data, nr)),
969 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
970 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
971 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
972 };
749 struct sock_filter trace_insns[] = { 973 struct sock_filter trace_insns[] = {
750 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 974 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
751 offsetof(struct seccomp_data, nr)), 975 offsetof(struct seccomp_data, nr)),
@@ -782,6 +1006,7 @@ FIXTURE_SETUP(precedence)
782 memcpy(self->_x.filter, &_x##_insns, sizeof(_x##_insns)); \ 1006 memcpy(self->_x.filter, &_x##_insns, sizeof(_x##_insns)); \
783 self->_x.len = (unsigned short)ARRAY_SIZE(_x##_insns) 1007 self->_x.len = (unsigned short)ARRAY_SIZE(_x##_insns)
784 FILTER_ALLOC(allow); 1008 FILTER_ALLOC(allow);
1009 FILTER_ALLOC(log);
785 FILTER_ALLOC(trace); 1010 FILTER_ALLOC(trace);
786 FILTER_ALLOC(error); 1011 FILTER_ALLOC(error);
787 FILTER_ALLOC(trap); 1012 FILTER_ALLOC(trap);
@@ -792,6 +1017,7 @@ FIXTURE_TEARDOWN(precedence)
792{ 1017{
793#define FILTER_FREE(_x) if (self->_x.filter) free(self->_x.filter) 1018#define FILTER_FREE(_x) if (self->_x.filter) free(self->_x.filter)
794 FILTER_FREE(allow); 1019 FILTER_FREE(allow);
1020 FILTER_FREE(log);
795 FILTER_FREE(trace); 1021 FILTER_FREE(trace);
796 FILTER_FREE(error); 1022 FILTER_FREE(error);
797 FILTER_FREE(trap); 1023 FILTER_FREE(trap);
@@ -809,6 +1035,8 @@ TEST_F(precedence, allow_ok)
809 1035
810 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow); 1036 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
811 ASSERT_EQ(0, ret); 1037 ASSERT_EQ(0, ret);
1038 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1039 ASSERT_EQ(0, ret);
812 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1040 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
813 ASSERT_EQ(0, ret); 1041 ASSERT_EQ(0, ret);
814 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1042 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -833,6 +1061,8 @@ TEST_F_SIGNAL(precedence, kill_is_highest, SIGSYS)
833 1061
834 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow); 1062 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
835 ASSERT_EQ(0, ret); 1063 ASSERT_EQ(0, ret);
1064 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1065 ASSERT_EQ(0, ret);
836 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1066 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
837 ASSERT_EQ(0, ret); 1067 ASSERT_EQ(0, ret);
838 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1068 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -864,6 +1094,8 @@ TEST_F_SIGNAL(precedence, kill_is_highest_in_any_order, SIGSYS)
864 ASSERT_EQ(0, ret); 1094 ASSERT_EQ(0, ret);
865 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1095 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
866 ASSERT_EQ(0, ret); 1096 ASSERT_EQ(0, ret);
1097 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1098 ASSERT_EQ(0, ret);
867 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1099 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
868 ASSERT_EQ(0, ret); 1100 ASSERT_EQ(0, ret);
869 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap); 1101 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
@@ -885,6 +1117,8 @@ TEST_F_SIGNAL(precedence, trap_is_second, SIGSYS)
885 1117
886 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow); 1118 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
887 ASSERT_EQ(0, ret); 1119 ASSERT_EQ(0, ret);
1120 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1121 ASSERT_EQ(0, ret);
888 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1122 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
889 ASSERT_EQ(0, ret); 1123 ASSERT_EQ(0, ret);
890 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1124 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -910,6 +1144,8 @@ TEST_F_SIGNAL(precedence, trap_is_second_in_any_order, SIGSYS)
910 ASSERT_EQ(0, ret); 1144 ASSERT_EQ(0, ret);
911 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap); 1145 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
912 ASSERT_EQ(0, ret); 1146 ASSERT_EQ(0, ret);
1147 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1148 ASSERT_EQ(0, ret);
913 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1149 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
914 ASSERT_EQ(0, ret); 1150 ASSERT_EQ(0, ret);
915 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1151 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -931,6 +1167,8 @@ TEST_F(precedence, errno_is_third)
931 1167
932 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow); 1168 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
933 ASSERT_EQ(0, ret); 1169 ASSERT_EQ(0, ret);
1170 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1171 ASSERT_EQ(0, ret);
934 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1172 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
935 ASSERT_EQ(0, ret); 1173 ASSERT_EQ(0, ret);
936 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1174 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -949,6 +1187,8 @@ TEST_F(precedence, errno_is_third_in_any_order)
949 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 1187 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
950 ASSERT_EQ(0, ret); 1188 ASSERT_EQ(0, ret);
951 1189
1190 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1191 ASSERT_EQ(0, ret);
952 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error); 1192 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
953 ASSERT_EQ(0, ret); 1193 ASSERT_EQ(0, ret);
954 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1194 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
@@ -971,6 +1211,8 @@ TEST_F(precedence, trace_is_fourth)
971 1211
972 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow); 1212 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
973 ASSERT_EQ(0, ret); 1213 ASSERT_EQ(0, ret);
1214 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1215 ASSERT_EQ(0, ret);
974 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace); 1216 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
975 ASSERT_EQ(0, ret); 1217 ASSERT_EQ(0, ret);
976 /* Should work just fine. */ 1218 /* Should work just fine. */
@@ -992,12 +1234,54 @@ TEST_F(precedence, trace_is_fourth_in_any_order)
992 ASSERT_EQ(0, ret); 1234 ASSERT_EQ(0, ret);
993 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow); 1235 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
994 ASSERT_EQ(0, ret); 1236 ASSERT_EQ(0, ret);
1237 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1238 ASSERT_EQ(0, ret);
995 /* Should work just fine. */ 1239 /* Should work just fine. */
996 EXPECT_EQ(parent, syscall(__NR_getppid)); 1240 EXPECT_EQ(parent, syscall(__NR_getppid));
997 /* No ptracer */ 1241 /* No ptracer */
998 EXPECT_EQ(-1, syscall(__NR_getpid)); 1242 EXPECT_EQ(-1, syscall(__NR_getpid));
999} 1243}
1000 1244
1245TEST_F(precedence, log_is_fifth)
1246{
1247 pid_t mypid, parent;
1248 long ret;
1249
1250 mypid = getpid();
1251 parent = getppid();
1252 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1253 ASSERT_EQ(0, ret);
1254
1255 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1256 ASSERT_EQ(0, ret);
1257 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1258 ASSERT_EQ(0, ret);
1259 /* Should work just fine. */
1260 EXPECT_EQ(parent, syscall(__NR_getppid));
1261 /* Should also work just fine */
1262 EXPECT_EQ(mypid, syscall(__NR_getpid));
1263}
1264
1265TEST_F(precedence, log_is_fifth_in_any_order)
1266{
1267 pid_t mypid, parent;
1268 long ret;
1269
1270 mypid = getpid();
1271 parent = getppid();
1272 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1273 ASSERT_EQ(0, ret);
1274
1275 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
1276 ASSERT_EQ(0, ret);
1277 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
1278 ASSERT_EQ(0, ret);
1279 /* Should work just fine. */
1280 EXPECT_EQ(parent, syscall(__NR_getppid));
1281 /* Should also work just fine */
1282 EXPECT_EQ(mypid, syscall(__NR_getpid));
1283}
1284
1001#ifndef PTRACE_O_TRACESECCOMP 1285#ifndef PTRACE_O_TRACESECCOMP
1002#define PTRACE_O_TRACESECCOMP 0x00000080 1286#define PTRACE_O_TRACESECCOMP 0x00000080
1003#endif 1287#endif
@@ -1262,6 +1546,13 @@ TEST_F(TRACE_poke, getpid_runs_normally)
1262# error "Do not know how to find your architecture's registers and syscalls" 1546# error "Do not know how to find your architecture's registers and syscalls"
1263#endif 1547#endif
1264 1548
1549/* When the syscall return can't be changed, stub out the tests for it. */
1550#ifdef SYSCALL_NUM_RET_SHARE_REG
1551# define EXPECT_SYSCALL_RETURN(val, action) EXPECT_EQ(-1, action)
1552#else
1553# define EXPECT_SYSCALL_RETURN(val, action) EXPECT_EQ(val, action)
1554#endif
1555
1265/* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for 1556/* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
1266 * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux). 1557 * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux).
1267 */ 1558 */
@@ -1357,7 +1648,7 @@ void change_syscall(struct __test_metadata *_metadata,
1357#ifdef SYSCALL_NUM_RET_SHARE_REG 1648#ifdef SYSCALL_NUM_RET_SHARE_REG
1358 TH_LOG("Can't modify syscall return on this architecture"); 1649 TH_LOG("Can't modify syscall return on this architecture");
1359#else 1650#else
1360 regs.SYSCALL_RET = 1; 1651 regs.SYSCALL_RET = EPERM;
1361#endif 1652#endif
1362 1653
1363#ifdef HAVE_GETREGS 1654#ifdef HAVE_GETREGS
@@ -1426,6 +1717,8 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
1426 1717
1427 if (nr == __NR_getpid) 1718 if (nr == __NR_getpid)
1428 change_syscall(_metadata, tracee, __NR_getppid); 1719 change_syscall(_metadata, tracee, __NR_getppid);
1720 if (nr == __NR_open)
1721 change_syscall(_metadata, tracee, -1);
1429} 1722}
1430 1723
1431FIXTURE_DATA(TRACE_syscall) { 1724FIXTURE_DATA(TRACE_syscall) {
@@ -1480,6 +1773,28 @@ FIXTURE_TEARDOWN(TRACE_syscall)
1480 free(self->prog.filter); 1773 free(self->prog.filter);
1481} 1774}
1482 1775
1776TEST_F(TRACE_syscall, ptrace_syscall_redirected)
1777{
1778 /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
1779 teardown_trace_fixture(_metadata, self->tracer);
1780 self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
1781 true);
1782
1783 /* Tracer will redirect getpid to getppid. */
1784 EXPECT_NE(self->mypid, syscall(__NR_getpid));
1785}
1786
1787TEST_F(TRACE_syscall, ptrace_syscall_dropped)
1788{
1789 /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
1790 teardown_trace_fixture(_metadata, self->tracer);
1791 self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
1792 true);
1793
1794 /* Tracer should skip the open syscall, resulting in EPERM. */
1795 EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_open));
1796}
1797
1483TEST_F(TRACE_syscall, syscall_allowed) 1798TEST_F(TRACE_syscall, syscall_allowed)
1484{ 1799{
1485 long ret; 1800 long ret;
@@ -1520,13 +1835,8 @@ TEST_F(TRACE_syscall, syscall_dropped)
1520 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0); 1835 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1521 ASSERT_EQ(0, ret); 1836 ASSERT_EQ(0, ret);
1522 1837
1523#ifdef SYSCALL_NUM_RET_SHARE_REG
1524 /* gettid has been skipped */
1525 EXPECT_EQ(-1, syscall(__NR_gettid));
1526#else
1527 /* gettid has been skipped and an altered return value stored. */ 1838 /* gettid has been skipped and an altered return value stored. */
1528 EXPECT_EQ(1, syscall(__NR_gettid)); 1839 EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_gettid));
1529#endif
1530 EXPECT_NE(self->mytid, syscall(__NR_gettid)); 1840 EXPECT_NE(self->mytid, syscall(__NR_gettid));
1531} 1841}
1532 1842
@@ -1557,6 +1867,7 @@ TEST_F(TRACE_syscall, skip_after_RET_TRACE)
1557 ASSERT_EQ(0, ret); 1867 ASSERT_EQ(0, ret);
1558 1868
1559 /* Tracer will redirect getpid to getppid, and we should see EPERM. */ 1869 /* Tracer will redirect getpid to getppid, and we should see EPERM. */
1870 errno = 0;
1560 EXPECT_EQ(-1, syscall(__NR_getpid)); 1871 EXPECT_EQ(-1, syscall(__NR_getpid));
1561 EXPECT_EQ(EPERM, errno); 1872 EXPECT_EQ(EPERM, errno);
1562} 1873}
@@ -1654,47 +1965,6 @@ TEST_F_SIGNAL(TRACE_syscall, kill_after_ptrace, SIGSYS)
1654 EXPECT_NE(self->mypid, syscall(__NR_getpid)); 1965 EXPECT_NE(self->mypid, syscall(__NR_getpid));
1655} 1966}
1656 1967
1657#ifndef __NR_seccomp
1658# if defined(__i386__)
1659# define __NR_seccomp 354
1660# elif defined(__x86_64__)
1661# define __NR_seccomp 317
1662# elif defined(__arm__)
1663# define __NR_seccomp 383
1664# elif defined(__aarch64__)
1665# define __NR_seccomp 277
1666# elif defined(__hppa__)
1667# define __NR_seccomp 338
1668# elif defined(__powerpc__)
1669# define __NR_seccomp 358
1670# elif defined(__s390__)
1671# define __NR_seccomp 348
1672# else
1673# warning "seccomp syscall number unknown for this architecture"
1674# define __NR_seccomp 0xffff
1675# endif
1676#endif
1677
1678#ifndef SECCOMP_SET_MODE_STRICT
1679#define SECCOMP_SET_MODE_STRICT 0
1680#endif
1681
1682#ifndef SECCOMP_SET_MODE_FILTER
1683#define SECCOMP_SET_MODE_FILTER 1
1684#endif
1685
1686#ifndef SECCOMP_FILTER_FLAG_TSYNC
1687#define SECCOMP_FILTER_FLAG_TSYNC 1
1688#endif
1689
1690#ifndef seccomp
1691int seccomp(unsigned int op, unsigned int flags, void *args)
1692{
1693 errno = 0;
1694 return syscall(__NR_seccomp, op, flags, args);
1695}
1696#endif
1697
1698TEST(seccomp_syscall) 1968TEST(seccomp_syscall)
1699{ 1969{
1700 struct sock_filter filter[] = { 1970 struct sock_filter filter[] = {
@@ -1783,6 +2053,67 @@ TEST(seccomp_syscall_mode_lock)
1783 } 2053 }
1784} 2054}
1785 2055
2056/*
2057 * Test detection of known and unknown filter flags. Userspace needs to be able
2058 * to check if a filter flag is supported by the current kernel and a good way
2059 * of doing that is by attempting to enter filter mode, with the flag bit in
2060 * question set, and a NULL pointer for the _args_ parameter. EFAULT indicates
2061 * that the flag is valid and EINVAL indicates that the flag is invalid.
2062 */
2063TEST(detect_seccomp_filter_flags)
2064{
2065 unsigned int flags[] = { SECCOMP_FILTER_FLAG_TSYNC,
2066 SECCOMP_FILTER_FLAG_LOG };
2067 unsigned int flag, all_flags;
2068 int i;
2069 long ret;
2070
2071 /* Test detection of known-good filter flags */
2072 for (i = 0, all_flags = 0; i < ARRAY_SIZE(flags); i++) {
2073 flag = flags[i];
2074 ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
2075 ASSERT_NE(ENOSYS, errno) {
2076 TH_LOG("Kernel does not support seccomp syscall!");
2077 }
2078 EXPECT_EQ(-1, ret);
2079 EXPECT_EQ(EFAULT, errno) {
2080 TH_LOG("Failed to detect that a known-good filter flag (0x%X) is supported!",
2081 flag);
2082 }
2083
2084 all_flags |= flag;
2085 }
2086
2087 /* Test detection of all known-good filter flags */
2088 ret = seccomp(SECCOMP_SET_MODE_FILTER, all_flags, NULL);
2089 EXPECT_EQ(-1, ret);
2090 EXPECT_EQ(EFAULT, errno) {
2091 TH_LOG("Failed to detect that all known-good filter flags (0x%X) are supported!",
2092 all_flags);
2093 }
2094
2095 /* Test detection of an unknown filter flag */
2096 flag = -1;
2097 ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
2098 EXPECT_EQ(-1, ret);
2099 EXPECT_EQ(EINVAL, errno) {
2100 TH_LOG("Failed to detect that an unknown filter flag (0x%X) is unsupported!",
2101 flag);
2102 }
2103
2104 /*
2105 * Test detection of an unknown filter flag that may simply need to be
2106 * added to this test
2107 */
2108 flag = flags[ARRAY_SIZE(flags) - 1] << 1;
2109 ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
2110 EXPECT_EQ(-1, ret);
2111 EXPECT_EQ(EINVAL, errno) {
2112 TH_LOG("Failed to detect that an unknown filter flag (0x%X) is unsupported! Does a new flag need to be added to this test?",
2113 flag);
2114 }
2115}
2116
1786TEST(TSYNC_first) 2117TEST(TSYNC_first)
1787{ 2118{
1788 struct sock_filter filter[] = { 2119 struct sock_filter filter[] = {
@@ -2421,6 +2752,99 @@ TEST(syscall_restart)
2421 _metadata->passed = 0; 2752 _metadata->passed = 0;
2422} 2753}
2423 2754
2755TEST_SIGNAL(filter_flag_log, SIGSYS)
2756{
2757 struct sock_filter allow_filter[] = {
2758 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2759 };
2760 struct sock_filter kill_filter[] = {
2761 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
2762 offsetof(struct seccomp_data, nr)),
2763 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
2764 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
2765 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2766 };
2767 struct sock_fprog allow_prog = {
2768 .len = (unsigned short)ARRAY_SIZE(allow_filter),
2769 .filter = allow_filter,
2770 };
2771 struct sock_fprog kill_prog = {
2772 .len = (unsigned short)ARRAY_SIZE(kill_filter),
2773 .filter = kill_filter,
2774 };
2775 long ret;
2776 pid_t parent = getppid();
2777
2778 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
2779 ASSERT_EQ(0, ret);
2780
2781 /* Verify that the FILTER_FLAG_LOG flag isn't accepted in strict mode */
2782 ret = seccomp(SECCOMP_SET_MODE_STRICT, SECCOMP_FILTER_FLAG_LOG,
2783 &allow_prog);
2784 ASSERT_NE(ENOSYS, errno) {
2785 TH_LOG("Kernel does not support seccomp syscall!");
2786 }
2787 EXPECT_NE(0, ret) {
2788 TH_LOG("Kernel accepted FILTER_FLAG_LOG flag in strict mode!");
2789 }
2790 EXPECT_EQ(EINVAL, errno) {
2791 TH_LOG("Kernel returned unexpected errno for FILTER_FLAG_LOG flag in strict mode!");
2792 }
2793
2794 /* Verify that a simple, permissive filter can be added with no flags */
2795 ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &allow_prog);
2796 EXPECT_EQ(0, ret);
2797
2798 /* See if the same filter can be added with the FILTER_FLAG_LOG flag */
2799 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
2800 &allow_prog);
2801 ASSERT_NE(EINVAL, errno) {
2802 TH_LOG("Kernel does not support the FILTER_FLAG_LOG flag!");
2803 }
2804 EXPECT_EQ(0, ret);
2805
2806 /* Ensure that the kill filter works with the FILTER_FLAG_LOG flag */
2807 ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
2808 &kill_prog);
2809 EXPECT_EQ(0, ret);
2810
2811 EXPECT_EQ(parent, syscall(__NR_getppid));
2812 /* getpid() should never return. */
2813 EXPECT_EQ(0, syscall(__NR_getpid));
2814}
2815
2816TEST(get_action_avail)
2817{
2818 __u32 actions[] = { SECCOMP_RET_KILL_THREAD, SECCOMP_RET_TRAP,
2819 SECCOMP_RET_ERRNO, SECCOMP_RET_TRACE,
2820 SECCOMP_RET_LOG, SECCOMP_RET_ALLOW };
2821 __u32 unknown_action = 0x10000000U;
2822 int i;
2823 long ret;
2824
2825 ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &actions[0]);
2826 ASSERT_NE(ENOSYS, errno) {
2827 TH_LOG("Kernel does not support seccomp syscall!");
2828 }
2829 ASSERT_NE(EINVAL, errno) {
2830 TH_LOG("Kernel does not support SECCOMP_GET_ACTION_AVAIL operation!");
2831 }
2832 EXPECT_EQ(ret, 0);
2833
2834 for (i = 0; i < ARRAY_SIZE(actions); i++) {
2835 ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &actions[i]);
2836 EXPECT_EQ(ret, 0) {
2837 TH_LOG("Expected action (0x%X) not available!",
2838 actions[i]);
2839 }
2840 }
2841
2842 /* Check that an unknown action is handled properly (EOPNOTSUPP) */
2843 ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &unknown_action);
2844 EXPECT_EQ(ret, -1);
2845 EXPECT_EQ(errno, EOPNOTSUPP);
2846}
2847
2424/* 2848/*
2425 * TODO: 2849 * TODO:
2426 * - add microbenchmarks 2850 * - add microbenchmarks
@@ -2429,6 +2853,8 @@ TEST(syscall_restart)
2429 * - endianness checking when appropriate 2853 * - endianness checking when appropriate
2430 * - 64-bit arg prodding 2854 * - 64-bit arg prodding
2431 * - arch value testing (x86 modes especially) 2855 * - arch value testing (x86 modes especially)
2856 * - verify that FILTER_FLAG_LOG filters generate log messages
2857 * - verify that RET_LOG generates log messages
2432 * - ... 2858 * - ...
2433 */ 2859 */
2434 2860
diff --git a/tools/testing/selftests/sigaltstack/sas.c b/tools/testing/selftests/sigaltstack/sas.c
index ccd07343d418..228c2ae47687 100644
--- a/tools/testing/selftests/sigaltstack/sas.c
+++ b/tools/testing/selftests/sigaltstack/sas.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Stas Sergeev <stsp@users.sourceforge.net> 3 * Stas Sergeev <stsp@users.sourceforge.net>
3 * 4 *
@@ -17,6 +18,8 @@
17#include <assert.h> 18#include <assert.h>
18#include <errno.h> 19#include <errno.h>
19 20
21#include "../kselftest.h"
22
20#ifndef SS_AUTODISARM 23#ifndef SS_AUTODISARM
21#define SS_AUTODISARM (1U << 31) 24#define SS_AUTODISARM (1U << 31)
22#endif 25#endif
@@ -37,12 +40,15 @@ void my_usr1(int sig, siginfo_t *si, void *u)
37 stack_t stk; 40 stack_t stk;
38 struct stk_data *p; 41 struct stk_data *p;
39 42
43#if __s390x__
44 register unsigned long sp asm("%15");
45#else
40 register unsigned long sp asm("sp"); 46 register unsigned long sp asm("sp");
47#endif
41 48
42 if (sp < (unsigned long)sstack || 49 if (sp < (unsigned long)sstack ||
43 sp >= (unsigned long)sstack + SIGSTKSZ) { 50 sp >= (unsigned long)sstack + SIGSTKSZ) {
44 printf("[FAIL]\tSP is not on sigaltstack\n"); 51 ksft_exit_fail_msg("SP is not on sigaltstack\n");
45 exit(EXIT_FAILURE);
46 } 52 }
47 /* put some data on stack. other sighandler will try to overwrite it */ 53 /* put some data on stack. other sighandler will try to overwrite it */
48 aa = alloca(1024); 54 aa = alloca(1024);
@@ -50,21 +56,22 @@ void my_usr1(int sig, siginfo_t *si, void *u)
50 p = (struct stk_data *)(aa + 512); 56 p = (struct stk_data *)(aa + 512);
51 strcpy(p->msg, msg); 57 strcpy(p->msg, msg);
52 p->flag = 1; 58 p->flag = 1;
53 printf("[RUN]\tsignal USR1\n"); 59 ksft_print_msg("[RUN]\tsignal USR1\n");
54 err = sigaltstack(NULL, &stk); 60 err = sigaltstack(NULL, &stk);
55 if (err) { 61 if (err) {
56 perror("[FAIL]\tsigaltstack()"); 62 ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
57 exit(EXIT_FAILURE); 63 exit(EXIT_FAILURE);
58 } 64 }
59 if (stk.ss_flags != SS_DISABLE) 65 if (stk.ss_flags != SS_DISABLE)
60 printf("[FAIL]\tss_flags=%x, should be SS_DISABLE\n", 66 ksft_test_result_fail("tss_flags=%x, should be SS_DISABLE\n",
61 stk.ss_flags); 67 stk.ss_flags);
62 else 68 else
63 printf("[OK]\tsigaltstack is disabled in sighandler\n"); 69 ksft_test_result_pass(
70 "sigaltstack is disabled in sighandler\n");
64 swapcontext(&sc, &uc); 71 swapcontext(&sc, &uc);
65 printf("%s\n", p->msg); 72 ksft_print_msg("%s\n", p->msg);
66 if (!p->flag) { 73 if (!p->flag) {
67 printf("[RUN]\tAborting\n"); 74 ksft_exit_skip("[RUN]\tAborting\n");
68 exit(EXIT_FAILURE); 75 exit(EXIT_FAILURE);
69 } 76 }
70} 77}
@@ -74,13 +81,13 @@ void my_usr2(int sig, siginfo_t *si, void *u)
74 char *aa; 81 char *aa;
75 struct stk_data *p; 82 struct stk_data *p;
76 83
77 printf("[RUN]\tsignal USR2\n"); 84 ksft_print_msg("[RUN]\tsignal USR2\n");
78 aa = alloca(1024); 85 aa = alloca(1024);
79 /* dont run valgrind on this */ 86 /* dont run valgrind on this */
80 /* try to find the data stored by previous sighandler */ 87 /* try to find the data stored by previous sighandler */
81 p = memmem(aa, 1024, msg, strlen(msg)); 88 p = memmem(aa, 1024, msg, strlen(msg));
82 if (p) { 89 if (p) {
83 printf("[FAIL]\tsigaltstack re-used\n"); 90 ksft_test_result_fail("sigaltstack re-used\n");
84 /* corrupt the data */ 91 /* corrupt the data */
85 strcpy(p->msg, msg2); 92 strcpy(p->msg, msg2);
86 /* tell other sighandler that his data is corrupted */ 93 /* tell other sighandler that his data is corrupted */
@@ -90,7 +97,7 @@ void my_usr2(int sig, siginfo_t *si, void *u)
90 97
91static void switch_fn(void) 98static void switch_fn(void)
92{ 99{
93 printf("[RUN]\tswitched to user ctx\n"); 100 ksft_print_msg("[RUN]\tswitched to user ctx\n");
94 raise(SIGUSR2); 101 raise(SIGUSR2);
95 setcontext(&sc); 102 setcontext(&sc);
96} 103}
@@ -101,6 +108,8 @@ int main(void)
101 stack_t stk; 108 stack_t stk;
102 int err; 109 int err;
103 110
111 ksft_print_header();
112
104 sigemptyset(&act.sa_mask); 113 sigemptyset(&act.sa_mask);
105 act.sa_flags = SA_ONSTACK | SA_SIGINFO; 114 act.sa_flags = SA_ONSTACK | SA_SIGINFO;
106 act.sa_sigaction = my_usr1; 115 act.sa_sigaction = my_usr1;
@@ -110,19 +119,20 @@ int main(void)
110 sstack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, 119 sstack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
111 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); 120 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
112 if (sstack == MAP_FAILED) { 121 if (sstack == MAP_FAILED) {
113 perror("mmap()"); 122 ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));
114 return EXIT_FAILURE; 123 return EXIT_FAILURE;
115 } 124 }
116 125
117 err = sigaltstack(NULL, &stk); 126 err = sigaltstack(NULL, &stk);
118 if (err) { 127 if (err) {
119 perror("[FAIL]\tsigaltstack()"); 128 ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
120 exit(EXIT_FAILURE); 129 exit(EXIT_FAILURE);
121 } 130 }
122 if (stk.ss_flags == SS_DISABLE) { 131 if (stk.ss_flags == SS_DISABLE) {
123 printf("[OK]\tInitial sigaltstack state was SS_DISABLE\n"); 132 ksft_test_result_pass(
133 "Initial sigaltstack state was SS_DISABLE\n");
124 } else { 134 } else {
125 printf("[FAIL]\tInitial sigaltstack state was %x; " 135 ksft_exit_fail_msg("Initial sigaltstack state was %x; "
126 "should have been SS_DISABLE\n", stk.ss_flags); 136 "should have been SS_DISABLE\n", stk.ss_flags);
127 return EXIT_FAILURE; 137 return EXIT_FAILURE;
128 } 138 }
@@ -133,7 +143,8 @@ int main(void)
133 err = sigaltstack(&stk, NULL); 143 err = sigaltstack(&stk, NULL);
134 if (err) { 144 if (err) {
135 if (errno == EINVAL) { 145 if (errno == EINVAL) {
136 printf("[NOTE]\tThe running kernel doesn't support SS_AUTODISARM\n"); 146 ksft_exit_skip(
147 "[NOTE]\tThe running kernel doesn't support SS_AUTODISARM\n");
137 /* 148 /*
138 * If test cases for the !SS_AUTODISARM variant were 149 * If test cases for the !SS_AUTODISARM variant were
139 * added, we could still run them. We don't have any 150 * added, we could still run them. We don't have any
@@ -142,7 +153,9 @@ int main(void)
142 */ 153 */
143 return 0; 154 return 0;
144 } else { 155 } else {
145 perror("[FAIL]\tsigaltstack(SS_ONSTACK | SS_AUTODISARM)"); 156 ksft_exit_fail_msg(
157 "sigaltstack(SS_ONSTACK | SS_AUTODISARM) %s\n",
158 strerror(errno));
146 return EXIT_FAILURE; 159 return EXIT_FAILURE;
147 } 160 }
148 } 161 }
@@ -150,7 +163,7 @@ int main(void)
150 ustack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, 163 ustack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
151 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); 164 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
152 if (ustack == MAP_FAILED) { 165 if (ustack == MAP_FAILED) {
153 perror("mmap()"); 166 ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));
154 return EXIT_FAILURE; 167 return EXIT_FAILURE;
155 } 168 }
156 getcontext(&uc); 169 getcontext(&uc);
@@ -162,16 +175,17 @@ int main(void)
162 175
163 err = sigaltstack(NULL, &stk); 176 err = sigaltstack(NULL, &stk);
164 if (err) { 177 if (err) {
165 perror("[FAIL]\tsigaltstack()"); 178 ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
166 exit(EXIT_FAILURE); 179 exit(EXIT_FAILURE);
167 } 180 }
168 if (stk.ss_flags != SS_AUTODISARM) { 181 if (stk.ss_flags != SS_AUTODISARM) {
169 printf("[FAIL]\tss_flags=%x, should be SS_AUTODISARM\n", 182 ksft_exit_fail_msg("ss_flags=%x, should be SS_AUTODISARM\n",
170 stk.ss_flags); 183 stk.ss_flags);
171 exit(EXIT_FAILURE); 184 exit(EXIT_FAILURE);
172 } 185 }
173 printf("[OK]\tsigaltstack is still SS_AUTODISARM after signal\n"); 186 ksft_test_result_pass(
187 "sigaltstack is still SS_AUTODISARM after signal\n");
174 188
175 printf("[OK]\tTest passed\n"); 189 ksft_exit_pass();
176 return 0; 190 return 0;
177} 191}
diff --git a/tools/testing/selftests/splice/.gitignore b/tools/testing/selftests/splice/.gitignore
new file mode 100644
index 000000000000..1e23fefd68e8
--- /dev/null
+++ b/tools/testing/selftests/splice/.gitignore
@@ -0,0 +1 @@
default_file_splice_read
diff --git a/tools/testing/selftests/splice/Makefile b/tools/testing/selftests/splice/Makefile
index 9fc78e5e5451..e519b159b60d 100644
--- a/tools/testing/selftests/splice/Makefile
+++ b/tools/testing/selftests/splice/Makefile
@@ -1,7 +1,5 @@
1# SPDX-License-Identifier: GPL-2.0
1TEST_PROGS := default_file_splice_read.sh 2TEST_PROGS := default_file_splice_read.sh
2EXTRA := default_file_splice_read 3TEST_GEN_PROGS_EXTENDED := default_file_splice_read
3all: $(TEST_PROGS) $(EXTRA)
4 4
5include ../lib.mk 5include ../lib.mk
6
7EXTRA_CLEAN := $(EXTRA)
diff --git a/tools/testing/selftests/splice/default_file_splice_read.c b/tools/testing/selftests/splice/default_file_splice_read.c
index 01dd6091554c..a3c6e5672e09 100644
--- a/tools/testing/selftests/splice/default_file_splice_read.c
+++ b/tools/testing/selftests/splice/default_file_splice_read.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2#include <fcntl.h> 3#include <fcntl.h>
3 4
diff --git a/tools/testing/selftests/splice/default_file_splice_read.sh b/tools/testing/selftests/splice/default_file_splice_read.sh
index 1ea2adeabc94..490db5a2e435 100755
--- a/tools/testing/selftests/splice/default_file_splice_read.sh
+++ b/tools/testing/selftests/splice/default_file_splice_read.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2n=`./default_file_splice_read </dev/null | wc -c` 3n=`./default_file_splice_read </dev/null | wc -c`
3 4
4test "$n" = 0 && exit 0 5test "$n" = 0 && exit 0
diff --git a/tools/testing/selftests/static_keys/test_static_keys.sh b/tools/testing/selftests/static_keys/test_static_keys.sh
index 1261e3fa1e3a..24cff498b31a 100755
--- a/tools/testing/selftests/static_keys/test_static_keys.sh
+++ b/tools/testing/selftests/static_keys/test_static_keys.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# Runs static keys kernel module tests 3# Runs static keys kernel module tests
3 4
4if /sbin/modprobe -q test_static_key_base; then 5if /sbin/modprobe -q test_static_key_base; then
diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile
index 4981c6b6d050..b3c8ba3cb668 100644
--- a/tools/testing/selftests/sync/Makefile
+++ b/tools/testing/selftests/sync/Makefile
@@ -1,13 +1,18 @@
1# SPDX-License-Identifier: GPL-2.0
1CFLAGS += -O2 -g -std=gnu89 -pthread -Wall -Wextra 2CFLAGS += -O2 -g -std=gnu89 -pthread -Wall -Wextra
2CFLAGS += -I../../../../usr/include/ 3CFLAGS += -I../../../../usr/include/
3LDFLAGS += -pthread 4LDFLAGS += -pthread
4 5
5TEST_PROGS = sync_test 6.PHONY: all clean
6
7all: $(TEST_PROGS)
8 7
9include ../lib.mk 8include ../lib.mk
10 9
10# lib.mk TEST_CUSTOM_PROGS var is for custom tests that need special
11# build rules. lib.mk will run and install them.
12
13TEST_CUSTOM_PROGS := $(OUTPUT)/sync_test
14all: $(TEST_CUSTOM_PROGS)
15
11OBJS = sync_test.o sync.o 16OBJS = sync_test.o sync.o
12 17
13TESTS += sync_alloc.o 18TESTS += sync_alloc.o
@@ -18,6 +23,16 @@ TESTS += sync_stress_parallelism.o
18TESTS += sync_stress_consumer.o 23TESTS += sync_stress_consumer.o
19TESTS += sync_stress_merge.o 24TESTS += sync_stress_merge.o
20 25
21sync_test: $(OBJS) $(TESTS) 26OBJS := $(patsubst %,$(OUTPUT)/%,$(OBJS))
27TESTS := $(patsubst %,$(OUTPUT)/%,$(TESTS))
28
29$(TEST_CUSTOM_PROGS): $(TESTS) $(OBJS)
30 $(CC) -o $(TEST_CUSTOM_PROGS) $(OBJS) $(TESTS) $(CFLAGS) $(LDFLAGS)
31
32$(OBJS): $(OUTPUT)/%.o: %.c
33 $(CC) -c $^ -o $@
34
35$(TESTS): $(OUTPUT)/%.o: %.c
36 $(CC) -c $^ -o $@
22 37
23EXTRA_CLEAN := sync_test $(OBJS) $(TESTS) 38EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(OBJS) $(TESTS)
diff --git a/tools/testing/selftests/sync/sync_test.c b/tools/testing/selftests/sync/sync_test.c
index 62fa666e501a..7f7938263c5c 100644
--- a/tools/testing/selftests/sync/sync_test.c
+++ b/tools/testing/selftests/sync/sync_test.c
@@ -31,62 +31,83 @@
31#include <sys/types.h> 31#include <sys/types.h>
32#include <sys/stat.h> 32#include <sys/stat.h>
33#include <sys/wait.h> 33#include <sys/wait.h>
34#include <errno.h>
35#include <string.h>
34 36
37#include "../kselftest.h"
35#include "synctest.h" 38#include "synctest.h"
36 39
37static int run_test(int (*test)(void), char *name) 40static int run_test(int (*test)(void), char *name)
38{ 41{
39 int result; 42 int result;
40 pid_t childpid; 43 pid_t childpid;
44 int ret;
41 45
42 fflush(stdout); 46 fflush(stdout);
43 childpid = fork(); 47 childpid = fork();
44 48
45 if (childpid) { 49 if (childpid) {
46 waitpid(childpid, &result, 0); 50 waitpid(childpid, &result, 0);
47 if (WIFEXITED(result)) 51 if (WIFEXITED(result)) {
48 return WEXITSTATUS(result); 52 ret = WEXITSTATUS(result);
53 if (!ret)
54 ksft_test_result_pass("[RUN]\t%s\n", name);
55 else
56 ksft_test_result_fail("[RUN]\t%s\n", name);
57 return ret;
58 }
49 return 1; 59 return 1;
50 } 60 }
51 61
52 printf("[RUN]\tExecuting %s\n", name);
53 exit(test()); 62 exit(test());
54} 63}
55 64
56static int sync_api_supported(void) 65static void sync_api_supported(void)
57{ 66{
58 struct stat sbuf; 67 struct stat sbuf;
68 int ret;
59 69
60 return 0 == stat("/sys/kernel/debug/sync/sw_sync", &sbuf); 70 ret = stat("/sys/kernel/debug/sync/sw_sync", &sbuf);
71 if (!ret)
72 return;
73
74 if (errno == ENOENT)
75 ksft_exit_skip("Sync framework not supported by kernel\n");
76
77 if (errno == EACCES)
78 ksft_exit_skip("Run Sync test as root.\n");
79
80 ksft_exit_fail_msg("stat failed on /sys/kernel/debug/sync/sw_sync: %s",
81 strerror(errno));
61} 82}
62 83
63int main(void) 84int main(void)
64{ 85{
65 int err = 0; 86 int err;
66 87
67 if (!sync_api_supported()) { 88 ksft_print_header();
68 printf("SKIP: Sync framework not supported by kernel\n"); 89
69 return 0; 90 sync_api_supported();
70 }
71 91
72 printf("[RUN]\tTesting sync framework\n"); 92 ksft_print_msg("[RUN]\tTesting sync framework\n");
73 93
74 err += RUN_TEST(test_alloc_timeline); 94 RUN_TEST(test_alloc_timeline);
75 err += RUN_TEST(test_alloc_fence); 95 RUN_TEST(test_alloc_fence);
76 err += RUN_TEST(test_alloc_fence_negative); 96 RUN_TEST(test_alloc_fence_negative);
77 97
78 err += RUN_TEST(test_fence_one_timeline_wait); 98 RUN_TEST(test_fence_one_timeline_wait);
79 err += RUN_TEST(test_fence_one_timeline_merge); 99 RUN_TEST(test_fence_one_timeline_merge);
80 err += RUN_TEST(test_fence_merge_same_fence); 100 RUN_TEST(test_fence_merge_same_fence);
81 err += RUN_TEST(test_fence_multi_timeline_wait); 101 RUN_TEST(test_fence_multi_timeline_wait);
82 err += RUN_TEST(test_stress_two_threads_shared_timeline); 102 RUN_TEST(test_stress_two_threads_shared_timeline);
83 err += RUN_TEST(test_consumer_stress_multi_producer_single_consumer); 103 RUN_TEST(test_consumer_stress_multi_producer_single_consumer);
84 err += RUN_TEST(test_merge_stress_random_merge); 104 RUN_TEST(test_merge_stress_random_merge);
85 105
106 err = ksft_get_fail_cnt();
86 if (err) 107 if (err)
87 printf("[FAIL]\tsync errors: %d\n", err); 108 ksft_exit_fail_msg("%d out of %d sync tests failed\n",
88 else 109 err, ksft_test_num());
89 printf("[OK]\tsync\n");
90 110
91 return !!err; 111 /* need this return to keep gcc happy */
112 return ksft_exit_pass();
92} 113}
diff --git a/tools/testing/selftests/sync/synctest.h b/tools/testing/selftests/sync/synctest.h
index e7d1d57dba7a..90a8e5369914 100644
--- a/tools/testing/selftests/sync/synctest.h
+++ b/tools/testing/selftests/sync/synctest.h
@@ -29,10 +29,11 @@
29#define SELFTESTS_SYNCTEST_H 29#define SELFTESTS_SYNCTEST_H
30 30
31#include <stdio.h> 31#include <stdio.h>
32#include "../kselftest.h"
32 33
33#define ASSERT(cond, msg) do { \ 34#define ASSERT(cond, msg) do { \
34 if (!(cond)) { \ 35 if (!(cond)) { \
35 printf("[ERROR]\t%s", (msg)); \ 36 ksft_print_msg("[ERROR]\t%s", (msg)); \
36 return 1; \ 37 return 1; \
37 } \ 38 } \
38} while (0) 39} while (0)
diff --git a/tools/testing/selftests/sysctl/sysctl.sh b/tools/testing/selftests/sysctl/sysctl.sh
index ec232c3cfcaa..ec232c3cfcaa 100644..100755
--- a/tools/testing/selftests/sysctl/sysctl.sh
+++ b/tools/testing/selftests/sysctl/sysctl.sh
diff --git a/tools/testing/selftests/tc-testing/.gitignore b/tools/testing/selftests/tc-testing/.gitignore
index c18dd8d83cee..7a60b85e148f 100644
--- a/tools/testing/selftests/tc-testing/.gitignore
+++ b/tools/testing/selftests/tc-testing/.gitignore
@@ -1 +1,2 @@
1__pycache__/ 1__pycache__/
2*.pyc
diff --git a/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt b/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt
index 4e09257bc443..00438331ba47 100644
--- a/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt
+++ b/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt
@@ -34,6 +34,12 @@ category: A list of single-word descriptions covering what the command
34setup: The list of commands required to ensure the command under test 34setup: The list of commands required to ensure the command under test
35 succeeds. For example: if testing a filter, the command to create 35 succeeds. For example: if testing a filter, the command to create
36 the qdisc would appear here. 36 the qdisc would appear here.
37 This list can be empty.
38 Each command can be a string to be executed, or a list consisting
39 of a string which is a command to be executed, followed by 1 or
40 more acceptable exit codes for this command.
41 If only a string is given for the command, then an exit code of 0
42 will be expected.
37cmdUnderTest: The tc command being tested itself. 43cmdUnderTest: The tc command being tested itself.
38expExitCode: The code returned by the command under test upon its termination. 44expExitCode: The code returned by the command under test upon its termination.
39 tdc will compare this value against the actual returned value. 45 tdc will compare this value against the actual returned value.
@@ -49,6 +55,12 @@ matchCount: How many times the regex in matchPattern should match. A value
49teardown: The list of commands to clean up after the test is completed. 55teardown: The list of commands to clean up after the test is completed.
50 The environment should be returned to the same state as when 56 The environment should be returned to the same state as when
51 this test was started: qdiscs deleted, actions flushed, etc. 57 this test was started: qdiscs deleted, actions flushed, etc.
58 This list can be empty.
59 Each command can be a string to be executed, or a list consisting
60 of a string which is a command to be executed, followed by 1 or
61 more acceptable exit codes for this command.
62 If only a string is given for the command, then an exit code of 0
63 will be expected.
52 64
53 65
54SETUP/TEARDOWN ERRORS 66SETUP/TEARDOWN ERRORS
diff --git a/tools/testing/selftests/tc-testing/creating-testcases/example.json b/tools/testing/selftests/tc-testing/creating-testcases/example.json
new file mode 100644
index 000000000000..5ec501200970
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/creating-testcases/example.json
@@ -0,0 +1,55 @@
1[
2 {
3 "id": "1f",
4 "name": "simple test to test framework",
5 "category": [
6 "example"
7 ],
8 "setup": [
9 "mkdir mytest"
10 ],
11 "cmdUnderTest": "touch mytest/blorfl",
12 "expExitCode": "0",
13 "verifyCmd": "ls mytest/* | grep '[b]lorfl'",
14 "matchPattern": "orfl",
15 "matchCount": "1",
16 "teardown": [
17 "rm -rf mytest"
18 ]
19 },
20 {
21 "id": "2f",
22 "name": "simple test, no need for verify",
23 "category": [
24 "example"
25 ],
26 "setup": [
27 "mkdir mytest",
28 "touch mytest/blorfl"
29 ],
30 "cmdUnderTest": "ls mytest/blorfl",
31 "expExitCode": "0",
32 "verifyCmd": "/bin/true",
33 "matchPattern": " ",
34 "matchCount": "0",
35 "teardown": [
36 "rm -rf mytest"
37 ]
38 },
39 {
40 "id": "3f",
41 "name": "simple test, no need for setup or teardown (or verify)",
42 "category": [
43 "example"
44 ],
45 "setup": [
46 ],
47 "cmdUnderTest": "ip l l lo",
48 "expExitCode": "0",
49 "verifyCmd": "/bin/true",
50 "matchPattern": " ",
51 "matchCount": "0",
52 "teardown": [
53 ]
54 }
55]
diff --git a/tools/testing/selftests/tc-testing/creating-testcases/template.json b/tools/testing/selftests/tc-testing/creating-testcases/template.json
index 87971744bdd4..8b99b86d65bd 100644
--- a/tools/testing/selftests/tc-testing/creating-testcases/template.json
+++ b/tools/testing/selftests/tc-testing/creating-testcases/template.json
@@ -26,7 +26,13 @@
26 "" 26 ""
27 ], 27 ],
28 "setup": [ 28 "setup": [
29 "" 29 "",
30 [
31 "",
32 0,
33 1,
34 255
35 ]
30 ], 36 ],
31 "cmdUnderTest": "", 37 "cmdUnderTest": "",
32 "expExitCode": "", 38 "expExitCode": "",
@@ -34,7 +40,12 @@
34 "matchPattern": "", 40 "matchPattern": "",
35 "matchCount": "", 41 "matchCount": "",
36 "teardown": [ 42 "teardown": [
37 "" 43 "",
44 [
45 "",
46 0,
47 255
48 ]
38 ] 49 ]
39 } 50 }
40] 51]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json b/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json
new file mode 100644
index 000000000000..e2187b6e0b7a
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/gact.json
@@ -0,0 +1,469 @@
1[
2 {
3 "id": "e89a",
4 "name": "Add valid pass action",
5 "category": [
6 "actions",
7 "gact"
8 ],
9 "setup": [
10 [
11 "$TC actions flush action gact",
12 0,
13 1,
14 255
15 ]
16 ],
17 "cmdUnderTest": "$TC actions add action pass index 8",
18 "expExitCode": "0",
19 "verifyCmd": "$TC actions list action gact",
20 "matchPattern": "action order [0-9]*: gact action pass.*index 8 ref",
21 "matchCount": "1",
22 "teardown": [
23 "$TC actions flush action gact"
24 ]
25 },
26 {
27 "id": "a02c",
28 "name": "Add valid pipe action",
29 "category": [
30 "actions",
31 "gact"
32 ],
33 "setup": [
34 [
35 "$TC actions flush action gact",
36 0,
37 1,
38 255
39 ]
40 ],
41 "cmdUnderTest": "$TC actions add action pipe index 6",
42 "expExitCode": "0",
43 "verifyCmd": "$TC actions list action gact",
44 "matchPattern": "action order [0-9]*: gact action pipe.*index 6 ref",
45 "matchCount": "1",
46 "teardown": [
47 "$TC actions flush action gact"
48 ]
49 },
50 {
51 "id": "feef",
52 "name": "Add valid reclassify action",
53 "category": [
54 "actions",
55 "gact"
56 ],
57 "setup": [
58 [
59 "$TC actions flush action gact",
60 0,
61 1,
62 255
63 ]
64 ],
65 "cmdUnderTest": "$TC actions add action reclassify index 5",
66 "expExitCode": "0",
67 "verifyCmd": "$TC actions list action gact",
68 "matchPattern": "action order [0-9]*: gact action reclassify.*index 5 ref",
69 "matchCount": "1",
70 "teardown": [
71 "$TC actions flush action gact"
72 ]
73 },
74 {
75 "id": "8a7a",
76 "name": "Add valid drop action",
77 "category": [
78 "actions",
79 "gact"
80 ],
81 "setup": [
82 [
83 "$TC actions flush action gact",
84 0,
85 1,
86 255
87 ]
88 ],
89 "cmdUnderTest": "$TC actions add action drop index 30",
90 "expExitCode": "0",
91 "verifyCmd": "$TC actions list action gact",
92 "matchPattern": "action order [0-9]*: gact action drop.*index 30 ref",
93 "matchCount": "1",
94 "teardown": [
95 "$TC actions flush action gact"
96 ]
97 },
98 {
99 "id": "9a52",
100 "name": "Add valid continue action",
101 "category": [
102 "actions",
103 "gact"
104 ],
105 "setup": [
106 [
107 "$TC actions flush action gact",
108 0,
109 1,
110 255
111 ]
112 ],
113 "cmdUnderTest": "$TC actions add action continue index 432",
114 "expExitCode": "0",
115 "verifyCmd": "$TC actions list action gact",
116 "matchPattern": "action order [0-9]*: gact action continue.*index 432 ref",
117 "matchCount": "1",
118 "teardown": [
119 "$TC actions flush action gact"
120 ]
121 },
122 {
123 "id": "d700",
124 "name": "Add invalid action",
125 "category": [
126 "actions",
127 "gact"
128 ],
129 "setup": [
130 [
131 "$TC actions flush action gact",
132 0,
133 1,
134 255
135 ]
136 ],
137 "cmdUnderTest": "$TC actions add action pump index 386",
138 "expExitCode": "255",
139 "verifyCmd": "$TC actions list action gact",
140 "matchPattern": "action order [0-9]*: gact action.*index 386 ref",
141 "matchCount": "0",
142 "teardown": [
143 "$TC actions flush action gact"
144 ]
145 },
146 {
147 "id": "9215",
148 "name": "Add action with duplicate index",
149 "category": [
150 "actions",
151 "gact"
152 ],
153 "setup": [
154 [
155 "$TC actions flush action gact",
156 0,
157 1,
158 255
159 ],
160 "$TC actions add action pipe index 15"
161 ],
162 "cmdUnderTest": "$TC actions add action drop index 15",
163 "expExitCode": "255",
164 "verifyCmd": "$TC actions list action gact",
165 "matchPattern": "action order [0-9]*: gact action drop.*index 15 ref",
166 "matchCount": "0",
167 "teardown": [
168 "$TC actions flush action gact"
169 ]
170 },
171 {
172 "id": "798e",
173 "name": "Add action with index exceeding 32-bit maximum",
174 "category": [
175 "actions",
176 "gact"
177 ],
178 "setup": [
179 [
180 "$TC actions flush action gact",
181 0,
182 1,
183 255
184 ]
185 ],
186 "cmdUnderTest": "$TC actions add action drop index 4294967296",
187 "expExitCode": "255",
188 "verifyCmd": "actions list action gact",
189 "matchPattern": "action order [0-9]*: gact action drop.*index 4294967296 ref",
190 "matchCount": "0",
191 "teardown": [
192 "$TC actions flush action gact"
193 ]
194 },
195 {
196 "id": "22be",
197 "name": "Add action with index at 32-bit maximum",
198 "category": [
199 "actions",
200 "gact"
201 ],
202 "setup": [
203 [
204 "$TC actions flush action gact",
205 0,
206 1,
207 255
208 ]
209 ],
210 "cmdUnderTest": "$TC actions add action drop index 4294967295",
211 "expExitCode": "0",
212 "verifyCmd": "$TC actions list action gact",
213 "matchPattern": "action order [0-9]*: gact action drop.*index 4294967295 ref",
214 "matchCount": "1",
215 "teardown": [
216 "$TC actions flush action gact"
217 ]
218 },
219 {
220 "id": "ac2a",
221 "name": "List actions",
222 "category": [
223 "actions",
224 "gact"
225 ],
226 "setup": [
227 [
228 "$TC actions flush action gact",
229 0,
230 1,
231 255
232 ],
233 "$TC actions add action reclassify index 101",
234 "$TC actions add action reclassify index 102",
235 "$TC actions add action reclassify index 103",
236 "$TC actions add action reclassify index 104",
237 "$TC actions add action reclassify index 105"
238 ],
239 "cmdUnderTest": "$TC actions list action gact",
240 "expExitCode": "0",
241 "verifyCmd": "$TC actions list action gact",
242 "matchPattern": "action order [0-9]*: gact action reclassify",
243 "matchCount": "5",
244 "teardown": [
245 "$TC actions flush action gact"
246 ]
247 },
248 {
249 "id": "3edf",
250 "name": "Flush gact actions",
251 "category": [
252 "actions",
253 "gact"
254 ],
255 "setup": [
256 "$TC actions add action reclassify index 101",
257 "$TC actions add action reclassify index 102",
258 "$TC actions add action reclassify index 103",
259 "$TC actions add action reclassify index 104",
260 "$TC actions add action reclassify index 105"
261 ],
262 "cmdUnderTest": "$TC actions flush action gact",
263 "expExitCode": "0",
264 "verifyCmd": "$TC actions list action gact",
265 "matchPattern": "action order [0-9]*: gact action reclassify",
266 "matchCount": "0",
267 "teardown": []
268 },
269 {
270 "id": "63ec",
271 "name": "Delete pass action",
272 "category": [
273 "actions",
274 "gact"
275 ],
276 "setup": [
277 [
278 "$TC actions flush action gact",
279 0,
280 1,
281 255
282 ],
283 "$TC actions add action pass index 1"
284 ],
285 "cmdUnderTest": "$TC actions del action gact index 1",
286 "expExitCode": "0",
287 "verifyCmd": "$TC actions list action gact",
288 "matchPattern": "action order [0-9]*: gact action pass.*index 1 ref",
289 "matchCount": "0",
290 "teardown": [
291 "$TC actions flush action gact"
292 ]
293 },
294 {
295 "id": "46be",
296 "name": "Delete pipe action",
297 "category": [
298 "actions",
299 "gact"
300 ],
301 "setup": [
302 [
303 "$TC actions flush action gact",
304 0,
305 1,
306 255
307 ],
308 "$TC actions add action pipe index 9"
309 ],
310 "cmdUnderTest": "$TC actions del action gact index 9",
311 "expExitCode": "0",
312 "verifyCmd": "$TC actions list action gact",
313 "matchPattern": "action order [0-9]*: gact action pipe.*index 9 ref",
314 "matchCount": "0",
315 "teardown": [
316 "$TC actions flush action gact"
317 ]
318 },
319 {
320 "id": "2e08",
321 "name": "Delete reclassify action",
322 "category": [
323 "actions",
324 "gact"
325 ],
326 "setup": [
327 [
328 "$TC actions flush action gact",
329 0,
330 1,
331 255
332 ],
333 "$TC actions add action reclassify index 65536"
334 ],
335 "cmdUnderTest": "$TC actions del action gact index 65536",
336 "expExitCode": "0",
337 "verifyCmd": "$TC actions list action gact",
338 "matchPattern": "action order [0-9]*: gact action reclassify.*index 65536 ref",
339 "matchCount": "0",
340 "teardown": [
341 "$TC actions flush action gact"
342 ]
343 },
344 {
345 "id": "99c4",
346 "name": "Delete drop action",
347 "category": [
348 "actions",
349 "gact"
350 ],
351 "setup": [
352 [
353 "$TC actions flush action gact",
354 0,
355 1,
356 255
357 ],
358 "$TC actions add action drop index 16"
359 ],
360 "cmdUnderTest": "$TC actions del action gact index 16",
361 "expExitCode": "0",
362 "verifyCmd": "$TC actions list action gact",
363 "matchPattern": "action order [0-9]*: gact action drop.*index 16 ref",
364 "matchCount": "0",
365 "teardown": [
366 "$TC actions flush action gact"
367 ]
368 },
369 {
370 "id": "fb6b",
371 "name": "Delete continue action",
372 "category": [
373 "actions",
374 "gact"
375 ],
376 "setup": [
377 [
378 "$TC actions flush action gact",
379 0,
380 1,
381 255
382 ],
383 "$TC actions add action continue index 32"
384 ],
385 "cmdUnderTest": "$TC actions del action gact index 32",
386 "expExitCode": "0",
387 "verifyCmd": "actions list action gact",
388 "matchPattern": "action order [0-9]*: gact action continue.*index 32 ref",
389 "matchCount": "0",
390 "teardown": [
391 "$TC actions flush action gact"
392 ]
393 },
394 {
395 "id": "0eb3",
396 "name": "Delete non-existent action",
397 "category": [
398 "actions",
399 "gact"
400 ],
401 "setup": [
402 [
403 "$TC actions flush action gact",
404 0,
405 1,
406 255
407 ]
408 ],
409 "cmdUnderTest": "$TC actions del action gact index 2",
410 "expExitCode": "255",
411 "verifyCmd": "$TC actions list action gact",
412 "matchPattern": "action order [0-9]*: gact action",
413 "matchCount": "0",
414 "teardown": [
415 "$TC actions flush action gact"
416 ]
417 },
418 {
419 "id": "f02c",
420 "name": "Replace gact action",
421 "category": [
422 "actions",
423 "gact"
424 ],
425 "setup": [
426 [
427 "$TC actions flush action gact",
428 0,
429 1,
430 255
431 ],
432 "$TC actions add action drop index 10",
433 "$TC actions add action drop index 12"
434 ],
435 "cmdUnderTest": "$TC actions replace action ok index 12",
436 "expExitCode": "0",
437 "verifyCmd": "$TC actions ls action gact",
438 "matchPattern": "action order [0-9]*: gact action pass",
439 "matchCount": "1",
440 "teardown": [
441 "$TC actions flush action gact"
442 ]
443 },
444 {
445 "id": "525f",
446 "name": "Get gact action by index",
447 "category": [
448 "actions",
449 "gact"
450 ],
451 "setup": [
452 [
453 "$TC actions flush action gact",
454 0,
455 1,
456 255
457 ],
458 "$TC actions add action drop index 3900800700"
459 ],
460 "cmdUnderTest": "$TC actions get action gact index 3900800700",
461 "expExitCode": "0",
462 "verifyCmd": "$TC actions get action gact index 3900800700",
463 "matchPattern": "index 3900800700",
464 "matchCount": "1",
465 "teardown": [
466 "$TC actions flush action gact"
467 ]
468 }
469]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/ife.json b/tools/testing/selftests/tc-testing/tc-tests/actions/ife.json
new file mode 100644
index 000000000000..9f34f0753969
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/ife.json
@@ -0,0 +1,52 @@
1[
2 {
3 "id": "a568",
4 "name": "Add action with ife type",
5 "category": [
6 "actions",
7 "ife"
8 ],
9 "setup": [
10 [
11 "$TC actions flush action ife",
12 0,
13 1,
14 255
15 ],
16 "$TC actions add action ife encode type 0xDEAD index 1"
17 ],
18 "cmdUnderTest": "$TC actions get action ife index 1",
19 "expExitCode": "0",
20 "verifyCmd": "$TC actions get action ife index 1",
21 "matchPattern": "type 0xDEAD",
22 "matchCount": "1",
23 "teardown": [
24 "$TC actions flush action ife"
25 ]
26 },
27 {
28 "id": "b983",
29 "name": "Add action without ife type",
30 "category": [
31 "actions",
32 "ife"
33 ],
34 "setup": [
35 [
36 "$TC actions flush action ife",
37 0,
38 1,
39 255
40 ],
41 "$TC actions add action ife encode index 1"
42 ],
43 "cmdUnderTest": "$TC actions get action ife index 1",
44 "expExitCode": "0",
45 "verifyCmd": "$TC actions get action ife index 1",
46 "matchPattern": "type 0xED3E",
47 "matchCount": "1",
48 "teardown": [
49 "$TC actions flush action ife"
50 ]
51 }
52]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json b/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json
new file mode 100644
index 000000000000..0fcccf18399b
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json
@@ -0,0 +1,223 @@
1[
2 {
3 "id": "5124",
4 "name": "Add mirred mirror to egress action",
5 "category": [
6 "actions",
7 "mirred"
8 ],
9 "setup": [
10 [
11 "$TC actions flush action mirred",
12 0,
13 1,
14 255
15 ]
16 ],
17 "cmdUnderTest": "$TC actions add action mirred egress mirror index 1 dev lo",
18 "expExitCode": "0",
19 "verifyCmd": "$TC actions list action mirred",
20 "matchPattern": "action order [0-9]*: mirred \\(Egress Mirror to device lo\\).*index 1 ref",
21 "matchCount": "1",
22 "teardown": [
23 "$TC actions flush action mirred"
24 ]
25 },
26 {
27 "id": "6fb4",
28 "name": "Add mirred redirect to egress action",
29 "category": [
30 "actions",
31 "mirred"
32 ],
33 "setup": [
34 [
35 "$TC actions flush action mirred",
36 0,
37 1,
38 255
39 ]
40 ],
41 "cmdUnderTest": "$TC actions add action mirred egress redirect index 2 dev lo action pipe",
42 "expExitCode": "0",
43 "verifyCmd": "$TC actions list action mirred",
44 "matchPattern": "action order [0-9]*: mirred \\(Egress Redirect to device lo\\).*index 2 ref",
45 "matchCount": "1",
46 "teardown": [
47 "$TC actions flush action mirred"
48 ]
49 },
50 {
51 "id": "ba38",
52 "name": "Get mirred actions",
53 "category": [
54 "actions",
55 "mirred"
56 ],
57 "setup": [
58 [
59 "$TC actions flush action mirred",
60 0,
61 1,
62 255
63 ],
64 "$TC actions add action mirred egress mirror index 1 dev lo",
65 "$TC actions add action mirred egress redirect index 2 dev lo"
66 ],
67 "cmdUnderTest": "$TC actions show action mirred",
68 "expExitCode": "0",
69 "verifyCmd": "$TC actions list action mirred",
70 "matchPattern": "[Mirror|Redirect] to device lo",
71 "matchCount": "2",
72 "teardown": [
73 "$TC actions flush action mirred"
74 ]
75 },
76 {
77 "id": "d7c0",
78 "name": "Add invalid mirred direction",
79 "category": [
80 "actions",
81 "mirred"
82 ],
83 "setup": [
84 [
85 "$TC actions flush action mirred",
86 0,
87 1,
88 255
89 ]
90 ],
91 "cmdUnderTest": "$TC actions add action mirred inbound mirror index 20 dev lo",
92 "expExitCode": "255",
93 "verifyCmd": "$TC actions list action mirred",
94 "matchPattern": "action order [0-9]*: mirred \\(.*to device lo\\).*index 20 ref",
95 "matchCount": "0",
96 "teardown": [
97 "$TC actions flush action mirred"
98 ]
99 },
100 {
101 "id": "e213",
102 "name": "Add invalid mirred action",
103 "category": [
104 "actions",
105 "mirred"
106 ],
107 "setup": [
108 [
109 "$TC actions flush action mirred",
110 0,
111 1,
112 255
113 ]
114 ],
115 "cmdUnderTest": "$TC actions add action mirred egress remirror index 20 dev lo",
116 "expExitCode": "255",
117 "verifyCmd": "$TC actions list action mirred",
118 "matchPattern": "action order [0-9]*: mirred \\(Egress.*to device lo\\).*index 20 ref",
119 "matchCount": "0",
120 "teardown": [
121 "$TC actions flush action mirred"
122 ]
123 },
124 {
125 "id": "2d89",
126 "name": "Add mirred action with invalid device",
127 "category": [
128 "actions",
129 "mirred"
130 ],
131 "setup": [
132 [
133 "$TC actions flush action mirred",
134 0,
135 1,
136 255
137 ]
138 ],
139 "cmdUnderTest": "$TC actions add action mirred egress mirror index 20 dev eltoh",
140 "expExitCode": "255",
141 "verifyCmd": "$TC actions list action mirred",
142 "matchPattern": "action order [0-9]*: mirred \\(.*to device eltoh\\).*index 20 ref",
143 "matchCount": "0",
144 "teardown": [
145 "$TC actions flush action mirred"
146 ]
147 },
148 {
149 "id": "300b",
150 "name": "Add mirred action with duplicate index",
151 "category": [
152 "actions",
153 "mirred"
154 ],
155 "setup": [
156 [
157 "$TC actions flush action mirred",
158 0,
159 1,
160 255
161 ],
162 "$TC actions add action mirred egress redirect index 15 dev lo"
163 ],
164 "cmdUnderTest": "$TC actions add action mirred egress mirror index 15 dev lo",
165 "expExitCode": "255",
166 "verifyCmd": "$TC actions list action mirred",
167 "matchPattern": "action order [0-9]*: mirred \\(.*to device lo\\).*index 15 ref",
168 "matchCount": "1",
169 "teardown": [
170 "$TC actions flush action mirred"
171 ]
172 },
173 {
174 "id": "a70e",
175 "name": "Delete mirred mirror action",
176 "category": [
177 "actions",
178 "mirred"
179 ],
180 "setup": [
181 [
182 "$TC actions flush action mirred",
183 0,
184 1,
185 255
186 ],
187 "$TC actions add action mirred egress mirror index 5 dev lo"
188 ],
189 "cmdUnderTest": "$TC actions del action mirred index 5",
190 "expExitCode": "0",
191 "verifyCmd": "$TC actions list action mirred",
192 "matchPattern": "action order [0-9]*: mirred \\(Egress Mirror to device lo\\).*index 5 ref",
193 "matchCount": "0",
194 "teardown": [
195 "$TC actions flush action mirred"
196 ]
197 },
198 {
199 "id": "3fb3",
200 "name": "Delete mirred redirect action",
201 "category": [
202 "actions",
203 "mirred"
204 ],
205 "setup": [
206 [
207 "$TC actions flush action mirred",
208 0,
209 1,
210 255
211 ],
212 "$TC actions add action mirred egress redirect index 5 dev lo"
213 ],
214 "cmdUnderTest": "$TC actions del action mirred index 5",
215 "expExitCode": "0",
216 "verifyCmd": "$TC actions list action mirred",
217 "matchPattern": "action order [0-9]*: mirred \\(Egress Redirect to device lo\\).*index 5 ref",
218 "matchCount": "0",
219 "teardown": [
220 "$TC actions flush action mirred"
221 ]
222 }
223]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/police.json b/tools/testing/selftests/tc-testing/tc-tests/actions/police.json
new file mode 100644
index 000000000000..0e602a3f9393
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/police.json
@@ -0,0 +1,527 @@
1[
2 {
3 "id": "49aa",
4 "name": "Add valid basic police action",
5 "category": [
6 "actions",
7 "police"
8 ],
9 "setup": [
10 [
11 "$TC actions flush action police",
12 0,
13 1,
14 255
15 ]
16 ],
17 "cmdUnderTest": "$TC actions add action police rate 1kbit burst 10k index 1",
18 "expExitCode": "0",
19 "verifyCmd": "$TC actions ls action police",
20 "matchPattern": "action order [0-9]*: police 0x1 rate 1Kbit burst 10Kb",
21 "matchCount": "1",
22 "teardown": [
23 "$TC actions flush action police"
24 ]
25 },
26 {
27 "id": "3abe",
28 "name": "Add police action with duplicate index",
29 "category": [
30 "actions",
31 "police"
32 ],
33 "setup": [
34 [
35 "$TC actions flush action police",
36 0,
37 1,
38 255
39 ],
40 "$TC actions add action police rate 4Mbit burst 120k index 9"
41 ],
42 "cmdUnderTest": "$TC actions add action police rate 8kbit burst 24k index 9",
43 "expExitCode": "255",
44 "verifyCmd": "$TC actions ls action police",
45 "matchPattern": "action order [0-9]*: police 0x9",
46 "matchCount": "1",
47 "teardown": [
48 "$TC actions flush action police"
49 ]
50 },
51 {
52 "id": "49fa",
53 "name": "Add valid police action with mtu",
54 "category": [
55 "actions",
56 "police"
57 ],
58 "setup": [
59 [
60 "$TC actions flush action police",
61 0,
62 1,
63 255
64 ]
65 ],
66 "cmdUnderTest": "$TC actions add action police rate 90kbit burst 10k mtu 1k index 98",
67 "expExitCode": "0",
68 "verifyCmd": "$TC actions get action police index 98",
69 "matchPattern": "action order [0-9]*: police 0x62 rate 90Kbit burst 10Kb mtu 1Kb",
70 "matchCount": "1",
71 "teardown": [
72 "$TC actions flush action police"
73 ]
74 },
75 {
76 "id": "7943",
77 "name": "Add valid police action with peakrate",
78 "category": [
79 "actions",
80 "police"
81 ],
82 "setup": [
83 [
84 "$TC actions flush action police",
85 0,
86 1,
87 255
88 ]
89 ],
90 "cmdUnderTest": "$TC actions add action police rate 90kbit burst 10k mtu 2kb peakrate 100kbit index 3",
91 "expExitCode": "0",
92 "verifyCmd": "$TC actions ls action police",
93 "matchPattern": "action order [0-9]*: police 0x3 rate 90Kbit burst 10Kb mtu 2Kb peakrate 100Kbit",
94 "matchCount": "1",
95 "teardown": [
96 "$TC actions flush action police"
97 ]
98 },
99 {
100 "id": "055e",
101 "name": "Add police action with peakrate and no mtu",
102 "category": [
103 "actions",
104 "police"
105 ],
106 "setup": [
107 [
108 "$TC actions flush action police",
109 0,
110 1,
111 255
112 ]
113 ],
114 "cmdUnderTest": "$TC actions add action police rate 5kbit burst 6kb peakrate 10kbit index 9",
115 "expExitCode": "255",
116 "verifyCmd": "$TC actions ls action police",
117 "matchPattern": "action order [0-9]*: police 0x9 rate 5Kb burst 10Kb",
118 "matchCount": "0",
119 "teardown": [
120 "$TC actions flush action police"
121 ]
122 },
123 {
124 "id": "f057",
125 "name": "Add police action with valid overhead",
126 "category": [
127 "actions",
128 "police"
129 ],
130 "setup": [
131 [
132 "$TC actions flush action police",
133 0,
134 1,
135 255
136 ]
137 ],
138 "cmdUnderTest": "$TC actions add action police rate 1mbit burst 100k overhead 64 index 64",
139 "expExitCode": "0",
140 "verifyCmd": "$TC actions get action police index 64",
141 "matchPattern": "action order [0-9]*: police 0x40 rate 1Mbit burst 100Kb mtu 2Kb action reclassify overhead 64b",
142 "matchCount": "1",
143 "teardown": [
144 "$TC actions flush action police"
145 ]
146 },
147 {
148 "id": "7ffb",
149 "name": "Add police action with ethernet linklayer type",
150 "category": [
151 "actions",
152 "police"
153 ],
154 "setup": [
155 [
156 "$TC actions flush action police",
157 0,
158 1,
159 255
160 ]
161 ],
162 "cmdUnderTest": "$TC actions add action police rate 2mbit burst 200k linklayer ethernet index 8",
163 "expExitCode": "0",
164 "verifyCmd": "$TC actions show action police",
165 "matchPattern": "action order [0-9]*: police 0x8 rate 2Mbit burst 200Kb mtu 2Kb action reclassify overhead 0b",
166 "matchCount": "1",
167 "teardown": [
168 "$TC actions flush action police"
169 ]
170 },
171 {
172 "id": "3dda",
173 "name": "Add police action with atm linklayer type",
174 "category": [
175 "actions",
176 "police"
177 ],
178 "setup": [
179 [
180 "$TC actions flush action police",
181 0,
182 1,
183 255
184 ]
185 ],
186 "cmdUnderTest": "$TC actions add action police rate 2mbit burst 200k linklayer atm index 8",
187 "expExitCode": "0",
188 "verifyCmd": "$TC actions show action police",
189 "matchPattern": "action order [0-9]*: police 0x8 rate 2Mbit burst 200Kb mtu 2Kb action reclassify overhead 0b linklayer atm",
190 "matchCount": "1",
191 "teardown": [
192 "$TC actions flush action police"
193 ]
194 },
195 {
196 "id": "551b",
197 "name": "Add police actions with conform-exceed control continue/drop",
198 "category": [
199 "actions",
200 "police"
201 ],
202 "setup": [
203 [
204 "$TC actions flush action police",
205 0,
206 1,
207 255
208 ]
209 ],
210 "cmdUnderTest": "$TC actions add action police rate 3mbit burst 250k conform-exceed continue/drop index 1",
211 "expExitCode": "0",
212 "verifyCmd": "$TC actions get action police index 1",
213 "matchPattern": "action order [0-9]*: police 0x1 rate 3Mbit burst 250Kb mtu 2Kb action continue/drop",
214 "matchCount": "1",
215 "teardown": [
216 "$TC actions flush action police"
217 ]
218 },
219 {
220 "id": "0c70",
221 "name": "Add police actions with conform-exceed control pass/reclassify",
222 "category": [
223 "actions",
224 "police"
225 ],
226 "setup": [
227 [
228 "$TC actions flush action police",
229 0,
230 1,
231 255
232 ]
233 ],
234 "cmdUnderTest": "$TC actions add action police rate 3mbit burst 250k conform-exceed pass/reclassify index 4",
235 "expExitCode": "0",
236 "verifyCmd": "$TC actions ls action police",
237 "matchPattern": "action order [0-9]*: police 0x4 rate 3Mbit burst 250Kb mtu 2Kb action pass/reclassify",
238 "matchCount": "1",
239 "teardown": [
240 "$TC actions flush action police"
241 ]
242 },
243 {
244 "id": "d946",
245 "name": "Add police actions with conform-exceed control pass/pipe",
246 "category": [
247 "actions",
248 "police"
249 ],
250 "setup": [
251 [
252 "$TC actions flush action police",
253 0,
254 1,
255 255
256 ]
257 ],
258 "cmdUnderTest": "$TC actions add action police rate 3mbit burst 250k conform-exceed pass/pipe index 5",
259 "expExitCode": "0",
260 "verifyCmd": "$TC actions ls action police",
261 "matchPattern": "action order [0-9]*: police 0x5 rate 3Mbit burst 250Kb mtu 2Kb action pass/pipe",
262 "matchCount": "1",
263 "teardown": [
264 "$TC actions flush action police"
265 ]
266 },
267 {
268 "id": "336e",
269 "name": "Delete police action",
270 "category": [
271 "actions",
272 "police"
273 ],
274 "setup": [
275 [
276 "$TC actions flush action police",
277 0,
278 1,
279 255
280 ],
281 "$TC actions add action police rate 5mbit burst 2m index 12"
282 ],
283 "cmdUnderTest": "$TC actions delete action police index 12",
284 "expExitCode": "0",
285 "verifyCmd": "$TC actions ls action police",
286 "matchPattern": "action order [0-9]*: police 0xc rate 5Mb burst 2Mb",
287 "matchCount": "0",
288 "teardown": [
289 "$TC actions flush action police"
290 ]
291 },
292 {
293 "id": "77fa",
294 "name": "Get single police action from many actions",
295 "category": [
296 "actions",
297 "police"
298 ],
299 "setup": [
300 [
301 "$TC actions flush action police",
302 0,
303 1,
304 255
305 ],
306 "$TC actions add action police rate 1mbit burst 100k index 1",
307 "$TC actions add action police rate 2mbit burst 200k index 2",
308 "$TC actions add action police rate 3mbit burst 300k index 3",
309 "$TC actions add action police rate 4mbit burst 400k index 4",
310 "$TC actions add action police rate 5mbit burst 500k index 5",
311 "$TC actions add action police rate 6mbit burst 600k index 6",
312 "$TC actions add action police rate 7mbit burst 700k index 7",
313 "$TC actions add action police rate 8mbit burst 800k index 8"
314 ],
315 "cmdUnderTest": "$TC actions get action police index 4",
316 "expExitCode": "0",
317 "verifyCmd": "$TC actions get action police index 4",
318 "matchPattern": "action order [0-9]*: police 0x4 rate 4Mbit burst 400Kb",
319 "matchCount": "1",
320 "teardown": [
321 "$TC actions flush action police"
322 ]
323 },
324 {
325 "id": "aa43",
326 "name": "Get single police action without specifying index",
327 "category": [
328 "actions",
329 "police"
330 ],
331 "setup": [
332 [
333 "$TC actions flush action police",
334 0,
335 1,
336 255
337 ],
338 "$TC actions add action police rate 1mbit burst 100k index 1"
339 ],
340 "cmdUnderTest": "$TC actions get action police",
341 "expExitCode": "255",
342 "verifyCmd": "$TC actions get action police",
343 "matchPattern": "action order [0-9]*: police",
344 "matchCount": "0",
345 "teardown": [
346 "$TC actions flush action police"
347 ]
348 },
349 {
350 "id": "858b",
351 "name": "List police actions",
352 "category": [
353 "actions",
354 "police"
355 ],
356 "setup": [
357 [
358 "$TC actions flush action police",
359 0,
360 1,
361 255
362 ],
363 "$TC actions add action police rate 1mbit burst 100k index 1",
364 "$TC actions add action police rate 2mbit burst 200k index 2",
365 "$TC actions add action police rate 3mbit burst 300k index 3",
366 "$TC actions add action police rate 4mbit burst 400k index 4",
367 "$TC actions add action police rate 5mbit burst 500k index 5",
368 "$TC actions add action police rate 6mbit burst 600k index 6",
369 "$TC actions add action police rate 7mbit burst 700k index 7",
370 "$TC actions add action police rate 8mbit burst 800k index 8"
371 ],
372 "cmdUnderTest": "$TC actions list action police",
373 "expExitCode": "0",
374 "verifyCmd": "$TC actions ls action police",
375 "matchPattern": "action order [0-9]*: police 0x[1-8] rate [1-8]Mbit burst [1-8]00Kb",
376 "matchCount": "8",
377 "teardown": [
378 "$TC actions flush action police"
379 ]
380 },
381 {
382 "id": "1c3a",
383 "name": "Flush police actions",
384 "category": [
385 "actions",
386 "police"
387 ],
388 "setup": [
389 "$TC actions add action police rate 1mbit burst 100k index 1",
390 "$TC actions add action police rate 2mbit burst 200k index 2",
391 "$TC actions add action police rate 3mbit burst 300k index 3",
392 "$TC actions add action police rate 4mbit burst 400k index 4",
393 "$TC actions add action police rate 5mbit burst 500k index 5",
394 "$TC actions add action police rate 6mbit burst 600k index 6",
395 "$TC actions add action police rate 7mbit burst 700k index 7",
396 "$TC actions add action police rate 8mbit burst 800k index 8"
397 ],
398 "cmdUnderTest": "$TC actions flush action police",
399 "expExitCode": "0",
400 "verifyCmd": "$TC actions ls action police",
401 "matchPattern": "action order [0-9]*: police",
402 "matchCount": "0",
403 "teardown": [
404 ""
405 ]
406 },
407 {
408 "id": "7326",
409 "name": "Add police action with control continue",
410 "category": [
411 "actions",
412 "police"
413 ],
414 "setup": [
415 [
416 "$TC actions flush action police",
417 0,
418 1,
419 255
420 ]
421 ],
422 "cmdUnderTest": "$TC actions add action police rate 7mbit burst 1m continue index 1",
423 "expExitCode": "0",
424 "verifyCmd": "$TC actions get action police index 1",
425 "matchPattern": "action order [0-9]*: police 0x1 rate 7Mbit burst 1024Kb mtu 2Kb action continue",
426 "matchCount": "1",
427 "teardown": [
428 "$TC actions flush action police"
429 ]
430 },
431 {
432 "id": "34fa",
433 "name": "Add police action with control drop",
434 "category": [
435 "actions",
436 "police"
437 ],
438 "setup": [
439 [
440 "$TC actions flush action police",
441 0,
442 1,
443 255
444 ]
445 ],
446 "cmdUnderTest": "$TC actions add action police rate 7mbit burst 1m drop index 1",
447 "expExitCode": "0",
448 "verifyCmd": "$TC actions ls action police",
449 "matchPattern": "action order [0-9]*: police 0x1 rate 7Mbit burst 1024Kb mtu 2Kb action drop",
450 "matchCount": "1",
451 "teardown": [
452 "$TC actions flush action police"
453 ]
454 },
455 {
456 "id": "8dd5",
457 "name": "Add police action with control ok",
458 "category": [
459 "actions",
460 "police"
461 ],
462 "setup": [
463 [
464 "$TC actions flush action police",
465 0,
466 1,
467 255
468 ]
469 ],
470 "cmdUnderTest": "$TC actions add action police rate 7mbit burst 1m ok index 1",
471 "expExitCode": "0",
472 "verifyCmd": "$TC actions ls action police",
473 "matchPattern": "action order [0-9]*: police 0x1 rate 7Mbit burst 1024Kb mtu 2Kb action pass",
474 "matchCount": "1",
475 "teardown": [
476 "$TC actions flush action police"
477 ]
478 },
479 {
480 "id": "b9d1",
481 "name": "Add police action with control reclassify",
482 "category": [
483 "actions",
484 "police"
485 ],
486 "setup": [
487 [
488 "$TC actions flush action police",
489 0,
490 1,
491 255
492 ]
493 ],
494 "cmdUnderTest": "$TC actions add action police rate 7mbit burst 1m reclassify index 1",
495 "expExitCode": "0",
496 "verifyCmd": "$TC actions get action police index 1",
497 "matchPattern": "action order [0-9]*: police 0x1 rate 7Mbit burst 1024Kb mtu 2Kb action reclassify",
498 "matchCount": "1",
499 "teardown": [
500 "$TC actions flush action police"
501 ]
502 },
503 {
504 "id": "c534",
505 "name": "Add police action with control pipe",
506 "category": [
507 "actions",
508 "police"
509 ],
510 "setup": [
511 [
512 "$TC actions flush action police",
513 0,
514 1,
515 255
516 ]
517 ],
518 "cmdUnderTest": "$TC actions add action police rate 7mbit burst 1m pipe index 1",
519 "expExitCode": "0",
520 "verifyCmd": "$TC actions ls action police",
521 "matchPattern": "action order [0-9]*: police 0x1 rate 7Mbit burst 1024Kb mtu 2Kb action pipe",
522 "matchCount": "1",
523 "teardown": [
524 "$TC actions flush action police"
525 ]
526 }
527]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/simple.json b/tools/testing/selftests/tc-testing/tc-tests/actions/simple.json
new file mode 100644
index 000000000000..e89a7aa4012d
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/simple.json
@@ -0,0 +1,130 @@
1[
2 {
3 "id": "b078",
4 "name": "Add simple action",
5 "category": [
6 "actions",
7 "simple"
8 ],
9 "setup": [
10 [
11 "$TC actions flush action simple",
12 0,
13 1,
14 255
15 ]
16 ],
17 "cmdUnderTest": "$TC actions add action simple sdata \"A triumph\" index 60",
18 "expExitCode": "0",
19 "verifyCmd": "$TC actions list action simple",
20 "matchPattern": "action order [0-9]*: Simple <A triumph>.*index 60 ref",
21 "matchCount": "1",
22 "teardown": [
23 "$TC actions flush action simple"
24 ]
25 },
26 {
27 "id": "6d4c",
28 "name": "Add simple action with duplicate index",
29 "category": [
30 "actions",
31 "simple"
32 ],
33 "setup": [
34 [
35 "$TC actions flush action simple",
36 0,
37 1,
38 255
39 ],
40 "$TC actions add action simple sdata \"Aruba\" index 4"
41 ],
42 "cmdUnderTest": "$TC actions add action simple sdata \"Jamaica\" index 4",
43 "expExitCode": "255",
44 "verifyCmd": "$TC actions list action simple",
45 "matchPattern": "action order [0-9]*: Simple <Jamaica>.*ref",
46 "matchCount": "0",
47 "teardown": [
48 "$TC actions flush action simple"
49 ]
50 },
51 {
52 "id": "2542",
53 "name": "List simple actions",
54 "category": [
55 "actions",
56 "simple"
57 ],
58 "setup": [
59 [
60 "$TC actions flush action simple",
61 0,
62 1,
63 255
64 ],
65 "$TC actions add action simple sdata \"Rock\"",
66 "$TC actions add action simple sdata \"Paper\"",
67 "$TC actions add action simple sdata \"Scissors\" index 98"
68 ],
69 "cmdUnderTest": "$TC actions list action simple",
70 "expExitCode": "0",
71 "verifyCmd": "$TC actions list action simple",
72 "matchPattern": "action order [0-9]*: Simple <[A-Z][a-z]*>",
73 "matchCount": "3",
74 "teardown": [
75 "$TC actions flush action simple"
76 ]
77 },
78 {
79 "id": "ea67",
80 "name": "Delete simple action",
81 "category": [
82 "actions",
83 "simple"
84 ],
85 "setup": [
86 [
87 "$TC actions flush action simple",
88 0,
89 1,
90 255
91 ],
92 "$TC actions add action simple sdata \"Blinkenlights\" index 1"
93 ],
94 "cmdUnderTest": "$TC actions delete action simple index 1",
95 "expExitCode": "0",
96 "verifyCmd": "$TC actions list action simple",
97 "matchPattern": "action order [0-9]*: Simple <Blinkenlights>.*index 1 ref",
98 "matchCount": "0",
99 "teardown": [
100 "$TC actions flush action simple"
101 ]
102 },
103 {
104 "id": "8ff1",
105 "name": "Flush simple actions",
106 "category": [
107 "actions",
108 "simple"
109 ],
110 "setup": [
111 [
112 "$TC actions flush action simple",
113 0,
114 1,
115 255
116 ],
117 "$TC actions add action simple sdata \"Kirk\"",
118 "$TC actions add action simple sdata \"Spock\" index 50",
119 "$TC actions add action simple sdata \"McCoy\" index 9"
120 ],
121 "cmdUnderTest": "$TC actions flush action simple",
122 "expExitCode": "0",
123 "verifyCmd": "$TC actions list action simple",
124 "matchPattern": "action order [0-9]*: Simple <[A-Z][a-z]*>",
125 "matchCount": "0",
126 "teardown": [
127 ""
128 ]
129 }
130]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json b/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json
new file mode 100644
index 000000000000..99635ea4722e
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json
@@ -0,0 +1,320 @@
1[
2 {
3 "id": "6236",
4 "name": "Add skbedit action with valid mark",
5 "category": [
6 "actions",
7 "skbedit"
8 ],
9 "setup": [
10 [
11 "$TC actions flush action skbedit",
12 0,
13 1,
14 255
15 ]
16 ],
17 "cmdUnderTest": "$TC actions add action skbedit mark 1",
18 "expExitCode": "0",
19 "verifyCmd": "$TC actions list action skbedit",
20 "matchPattern": "action order [0-9]*: skbedit mark 1",
21 "matchCount": "1",
22 "teardown": [
23 "$TC actions flush action skbedit"
24 ]
25 },
26 {
27 "id": "407b",
28 "name": "Add skbedit action with invalid mark",
29 "category": [
30 "actions",
31 "skbedit"
32 ],
33 "setup": [
34 [
35 "$TC actions flush action skbedit",
36 0,
37 1,
38 255
39 ]
40 ],
41 "cmdUnderTest": "$TC actions add action skbedit mark 666777888999",
42 "expExitCode": "255",
43 "verifyCmd": "$TC actions list action skbedit",
44 "matchPattern": "action order [0-9]*: skbedit mark",
45 "matchCount": "0",
46 "teardown": [
47 "$TC actions flush action skbedit"
48 ]
49 },
50 {
51 "id": "081d",
52 "name": "Add skbedit action with priority",
53 "category": [
54 "actions",
55 "skbedit"
56 ],
57 "setup": [
58 [
59 "$TC actions flush action skbedit",
60 0,
61 1,
62 255
63 ]
64 ],
65 "cmdUnderTest": "$TC actions add action skbedit prio 99",
66 "expExitCode": "0",
67 "verifyCmd": "$TC actions list action skbedit",
68 "matchPattern": "action order [0-9]*: skbedit priority :99",
69 "matchCount": "1",
70 "teardown": [
71 "$TC actions flush action skbedit"
72 ]
73 },
74 {
75 "id": "cc37",
76 "name": "Add skbedit action with invalid priority",
77 "category": [
78 "actions",
79 "skbedit"
80 ],
81 "setup": [
82 [
83 "$TC actions flush action skbedit",
84 0,
85 1,
86 255
87 ]
88 ],
89 "cmdUnderTest": "$TC actions add action skbedit prio foo",
90 "expExitCode": "255",
91 "verifyCmd": "$TC actions list action skbedit",
92 "matchPattern": "action order [0-9]*: skbedit priority",
93 "matchCount": "0",
94 "teardown": [
95 "$TC actions flush action skbedit"
96 ]
97 },
98 {
99 "id": "3c95",
100 "name": "Add skbedit action with queue_mapping",
101 "category": [
102 "actions",
103 "skbedit"
104 ],
105 "setup": [
106 [
107 "$TC actions flush action skbedit",
108 0,
109 1,
110 255
111 ]
112 ],
113 "cmdUnderTest": "$TC actions add action skbedit queue_mapping 909",
114 "expExitCode": "0",
115 "verifyCmd": "$TC actions list action skbedit",
116 "matchPattern": "action order [0-9]*: skbedit queue_mapping 909",
117 "matchCount": "1",
118 "teardown": [
119 "$TC actions flush action skbedit"
120 ]
121 },
122 {
123 "id": "985c",
124 "name": "Add skbedit action with invalid queue_mapping",
125 "category": [
126 "actions",
127 "skbedit"
128 ],
129 "setup": [
130 [
131 "$TC actions flush action skbedit",
132 0,
133 1,
134 255
135 ]
136 ],
137 "cmdUnderTest": "$TC actions add action skbedit queue_mapping 67000",
138 "expExitCode": "255",
139 "verifyCmd": "$TC actions list action skbedit",
140 "matchPattern": "action order [0-9]*: skbedit queue_mapping",
141 "matchCount": "0",
142 "teardown": [
143 "$TC actions flush action skbedit"
144 ]
145 },
146 {
147 "id": "224f",
148 "name": "Add skbedit action with ptype host",
149 "category": [
150 "actions",
151 "skbedit"
152 ],
153 "setup": [
154 [
155 "$TC actions flush action skbedit",
156 0,
157 1,
158 255
159 ]
160 ],
161 "cmdUnderTest": "$TC actions add action skbedit ptype host",
162 "expExitCode": "0",
163 "verifyCmd": "$TC actions list action skbedit",
164 "matchPattern": "action order [0-9]*: skbedit ptype host",
165 "matchCount": "1",
166 "teardown": [
167 "$TC actions flush action skbedit"
168 ]
169 },
170 {
171 "id": "d1a3",
172 "name": "Add skbedit action with ptype otherhost",
173 "category": [
174 "actions",
175 "skbedit"
176 ],
177 "setup": [
178 [
179 "$TC actions flush action skbedit",
180 0,
181 1,
182 255
183 ]
184 ],
185 "cmdUnderTest": "$TC actions add action skbedit ptype otherhost",
186 "expExitCode": "0",
187 "verifyCmd": "$TC actions list action skbedit",
188 "matchPattern": "action order [0-9]*: skbedit ptype otherhost",
189 "matchCount": "1",
190 "teardown": [
191 "$TC actions flush action skbedit"
192 ]
193 },
194 {
195 "id": "b9c6",
196 "name": "Add skbedit action with invalid ptype",
197 "category": [
198 "actions",
199 "skbedit"
200 ],
201 "setup": [
202 [
203 "$TC actions flush action skbedit",
204 0,
205 1,
206 255
207 ]
208 ],
209 "cmdUnderTest": "$TC actions add action skbedit ptype openair",
210 "expExitCode": "255",
211 "verifyCmd": "$TC actions list action skbedit",
212 "matchPattern": "action order [0-9]*: skbedit ptype openair",
213 "matchCount": "0",
214 "teardown": [
215 "$TC actions flush action skbedit"
216 ]
217 },
218 {
219 "id": "5172",
220 "name": "List skbedit actions",
221 "category": [
222 "actions",
223 "skbedit"
224 ],
225 "setup": [
226 [
227 "$TC actions flush action skbedit",
228 0,
229 1,
230 255
231 ],
232 "$TC actions add action skbedit ptype otherhost",
233 "$TC actions add action skbedit ptype broadcast",
234 "$TC actions add action skbedit mark 59",
235 "$TC actions add action skbedit mark 409"
236 ],
237 "cmdUnderTest": "$TC actions list action skbedit",
238 "expExitCode": "0",
239 "verifyCmd": "$TC actions list action skbedit",
240 "matchPattern": "action order [0-9]*: skbedit",
241 "matchCount": "4",
242 "teardown": [
243 "$TC actions flush action skbedit"
244 ]
245 },
246 {
247 "id": "a6d6",
248 "name": "Add skbedit action with index",
249 "category": [
250 "actions",
251 "skbedit"
252 ],
253 "setup": [
254 [
255 "$TC actions flush action skbedit",
256 0,
257 1,
258 255
259 ]
260 ],
261 "cmdUnderTest": "$TC actions add action skbedit mark 808 index 4040404040",
262 "expExitCode": "0",
263 "verifyCmd": "$TC actions list action skbedit",
264 "matchPattern": "index 4040404040",
265 "matchCount": "1",
266 "teardown": [
267 "$TC actions flush action skbedit"
268 ]
269 },
270 {
271 "id": "38f3",
272 "name": "Delete skbedit action",
273 "category": [
274 "actions",
275 "skbedit"
276 ],
277 "setup": [
278 [
279 "$TC actions flush action skbedit",
280 0,
281 1,
282 255
283 ],
284 "$TC actions add action skbedit mark 42 index 9009"
285 ],
286 "cmdUnderTest": "$TC actions del action skbedit index 9009",
287 "expExitCode": "0",
288 "verifyCmd": "$TC actions list action skbedit",
289 "matchPattern": "action order [0-9]*: skbedit mark 42",
290 "matchCount": "0",
291 "teardown": [
292 "$TC actions flush action skbedit"
293 ]
294 },
295 {
296 "id": "ce97",
297 "name": "Flush skbedit actions",
298 "category": [
299 "actions",
300 "skbedit"
301 ],
302 "setup": [
303 "$TC actions add action skbedit mark 500",
304 "$TC actions add action skbedit mark 501",
305 "$TC actions add action skbedit mark 502",
306 "$TC actions add action skbedit mark 503",
307 "$TC actions add action skbedit mark 504",
308 "$TC actions add action skbedit mark 505",
309 "$TC actions add action skbedit mark 506"
310 ],
311 "cmdUnderTest": "$TC actions flush action skbedit",
312 "expExitCode": "0",
313 "verifyCmd": "$TC actions list action skbedit",
314 "matchPattern": "action order [0-9]*: skbedit",
315 "matchCount": "0",
316 "teardown": [
317 "$TC actions flush action skbedit"
318 ]
319 }
320]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json b/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json
new file mode 100644
index 000000000000..e34075059c26
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json
@@ -0,0 +1,372 @@
1[
2 {
3 "id": "7d50",
4 "name": "Add skbmod action to set destination mac",
5 "category": [
6 "actions",
7 "skbmod"
8 ],
9 "setup": [
10 [
11 "$TC actions flush action skbmod",
12 0,
13 1,
14 255
15 ]
16 ],
17 "cmdUnderTest": "$TC actions add action skbmod set dmac 11:22:33:44:55:66 index 5",
18 "expExitCode": "0",
19 "verifyCmd": "$TC actions ls action skbmod",
20 "matchPattern": "action order [0-9]*: skbmod pipe set dmac 11:22:33:44:55:66\\s+index 5",
21 "matchCount": "1",
22 "teardown": [
23 "$TC actions flush action skbmod"
24 ]
25 },
26 {
27 "id": "9b29",
28 "name": "Add skbmod action to set source mac",
29 "category": [
30 "actions",
31 "skbmod"
32 ],
33 "setup": [
34 [
35 "$TC actions flush action skbmod",
36 0,
37 1,
38 255
39 ]
40 ],
41 "cmdUnderTest": "$TC actions add action skbmod set smac 77:88:99:AA:BB:CC index 7",
42 "expExitCode": "0",
43 "verifyCmd": "$TC actions get action skbmod index 7",
44 "matchPattern": "action order [0-9]*: skbmod pipe set smac 77:88:99:aa:bb:cc\\s+index 7",
45 "matchCount": "1",
46 "teardown": [
47 "$TC actions flush action skbmod"
48 ]
49 },
50 {
51 "id": "1724",
52 "name": "Add skbmod action with invalid mac",
53 "category": [
54 "actions",
55 "skbmod"
56 ],
57 "setup": [
58 [
59 "$TC actions flush action skbmod",
60 0,
61 1,
62 255
63 ]
64 ],
65 "cmdUnderTest": "$TC actions add action skbmod set smac 00:44:55:44:55",
66 "expExitCode": "255",
67 "verifyCmd": "$TC actions ls action skbmod",
68 "matchPattern": "action order [0-9]*: skbmod pipe set smac 00:44:55:44:55",
69 "matchCount": "0",
70 "teardown": [
71 "$TC actions flush action skbmod"
72 ]
73 },
74 {
75 "id": "3cf1",
76 "name": "Add skbmod action with valid etype",
77 "category": [
78 "actions",
79 "skbmod"
80 ],
81 "setup": [
82 [
83 "$TC actions flush action skbmod",
84 0,
85 1,
86 255
87 ]
88 ],
89 "cmdUnderTest": "$TC actions add action skbmod set etype 0xfefe",
90 "expExitCode": "0",
91 "verifyCmd": "$TC actions ls action skbmod",
92 "matchPattern": "action order [0-9]*: skbmod pipe set etype 0xFEFE",
93 "matchCount": "1",
94 "teardown": [
95 "$TC actions flush action skbmod"
96 ]
97 },
98 {
99 "id": "a749",
100 "name": "Add skbmod action with invalid etype",
101 "category": [
102 "actions",
103 "skbmod"
104 ],
105 "setup": [
106 [
107 "$TC actions flush action skbmod",
108 0,
109 1,
110 255
111 ]
112 ],
113 "cmdUnderTest": "$TC actions add action skbmod set etype 0xfefef",
114 "expExitCode": "255",
115 "verifyCmd": "$TC actions ls action skbmod",
116 "matchPattern": "action order [0-9]*: skbmod pipe set etype 0xFEFEF",
117 "matchCount": "0",
118 "teardown": [
119 "$TC actions flush action skbmod"
120 ]
121 },
122 {
123 "id": "bfe6",
124 "name": "Add skbmod action to swap mac",
125 "category": [
126 "actions",
127 "skbmod"
128 ],
129 "setup": [
130 [
131 "$TC actions flush action skbmod",
132 0,
133 1,
134 255
135 ]
136 ],
137 "cmdUnderTest": "$TC actions add action skbmod swap mac",
138 "expExitCode": "0",
139 "verifyCmd": "$TC actions get action skbmod index 1",
140 "matchPattern": "action order [0-9]*: skbmod pipe swap mac",
141 "matchCount": "1",
142 "teardown": [
143 "$TC actions flush action skbmod"
144 ]
145 },
146 {
147 "id": "839b",
148 "name": "Add skbmod action with control pipe",
149 "category": [
150 "actions",
151 "skbmod"
152 ],
153 "setup": [
154 [
155 "$TC actions flush action skbmod",
156 0,
157 1,
158 255
159 ]
160 ],
161 "cmdUnderTest": "$TC actions add action skbmod swap mac pipe",
162 "expExitCode": "0",
163 "verifyCmd": "$TC actions ls action skbmod",
164 "matchPattern": "action order [0-9]*: skbmod pipe swap mac",
165 "matchCount": "1",
166 "teardown": [
167 "$TC actions flush action skbmod"
168 ]
169 },
170 {
171 "id": "c167",
172 "name": "Add skbmod action with control reclassify",
173 "category": [
174 "actions",
175 "skbmod"
176 ],
177 "setup": [
178 [
179 "$TC actions flush action skbmod",
180 0,
181 1,
182 255
183 ]
184 ],
185 "cmdUnderTest": "$TC actions add action skbmod set etype 0xbeef reclassify",
186 "expExitCode": "0",
187 "verifyCmd": "$TC actions ls action skbmod",
188 "matchPattern": "action order [0-9]*: skbmod reclassify set etype 0xBEEF",
189 "matchCount": "1",
190 "teardown": [
191 "$TC actions flush action skbmod"
192 ]
193 },
194 {
195 "id": "0c2f",
196 "name": "Add skbmod action with control drop",
197 "category": [
198 "actions",
199 "skbmod"
200 ],
201 "setup": [
202 [
203 "$TC actions flush action skbmod",
204 0,
205 1,
206 255
207 ]
208 ],
209 "cmdUnderTest": "$TC actions add action skbmod set etype 0x0001 drop",
210 "expExitCode": "0",
211 "verifyCmd": "$TC actions get action skbmod index 1",
212 "matchPattern": "action order [0-9]*: skbmod drop set etype 0x1",
213 "matchCount": "1",
214 "teardown": [
215 "$TC actions flush action skbmod"
216 ]
217 },
218 {
219 "id": "d113",
220 "name": "Add skbmod action with control continue",
221 "category": [
222 "actions",
223 "skbmod"
224 ],
225 "setup": [
226 [
227 "$TC actions flush action skbmod",
228 0,
229 1,
230 255
231 ]
232 ],
233 "cmdUnderTest": "$TC actions add action skbmod set etype 0x1 continue",
234 "expExitCode": "0",
235 "verifyCmd": "$TC actions ls action skbmod",
236 "matchPattern": "action order [0-9]*: skbmod continue set etype 0x1",
237 "matchCount": "1",
238 "teardown": [
239 "$TC actions flush action skbmod"
240 ]
241 },
242 {
243 "id": "7242",
244 "name": "Add skbmod action with control pass",
245 "category": [
246 "actions",
247 "skbmod"
248 ],
249 "setup": [
250 [
251 "$TC actions flush action skbmod",
252 0,
253 1,
254 255
255 ]
256 ],
257 "cmdUnderTest": "$TC actions add action skbmod set smac 00:00:00:00:00:01 pass",
258 "expExitCode": "0",
259 "verifyCmd": "$TC actions ls action skbmod",
260 "matchPattern": "action order [0-9]*: skbmod pass set smac 00:00:00:00:00:01",
261 "matchCount": "1",
262 "teardown": [
263 "$TC actions flush action skbmod"
264 ]
265 },
266 {
267 "id": "58cb",
268 "name": "List skbmod actions",
269 "category": [
270 "actions",
271 "skbmod"
272 ],
273 "setup": [
274 [
275 "$TC actions flush action skbmod",
276 0,
277 1,
278 255
279 ],
280 "$TC actions add action skbmod set etype 0x0001",
281 "$TC actions add action skbmod set etype 0x0011",
282 "$TC actions add action skbmod set etype 0x0021",
283 "$TC actions add action skbmod set etype 0x0031",
284 "$TC actions add action skbmod set etype 0x0041"
285 ],
286 "cmdUnderTest": "$TC actions ls action skbmod",
287 "expExitCode": "0",
288 "verifyCmd": "$TC actions ls action skbmod",
289 "matchPattern": "action order [0-9]*: skbmod",
290 "matchCount": "5",
291 "teardown": [
292 "$TC actions flush action skbmod"
293 ]
294 },
295 {
296 "id": "9aa8",
297 "name": "Get a single skbmod action from a list",
298 "category": [
299 "actions",
300 "skbmod"
301 ],
302 "setup": [
303 [
304 "$TC actions flush action skbmod",
305 0,
306 1,
307 255
308 ],
309 "$TC actions add action skbmod set etype 0x0001",
310 "$TC actions add action skbmod set etype 0x0011",
311 "$TC actions add action skbmod set etype 0x0021",
312 "$TC actions add action skbmod set etype 0x0031",
313 "$TC actions add action skbmod set etype 0x0041"
314 ],
315 "cmdUnderTest": "$TC actions ls action skbmod",
316 "expExitCode": "0",
317 "verifyCmd": "$TC actions get action skbmod index 4",
318 "matchPattern": "action order [0-9]*: skbmod pipe set etype 0x0031",
319 "matchCount": "1",
320 "teardown": [
321 "$TC actions flush action skbmod"
322 ]
323 },
324 {
325 "id": "e93a",
326 "name": "Delete an skbmod action",
327 "category": [
328 "actions",
329 "skbmod"
330 ],
331 "setup": [
332 [
333 "$TC actions flush action skbmod",
334 0,
335 1,
336 255
337 ],
338 "$TC actions add action skbmod set etype 0x1111 index 909"
339 ],
340 "cmdUnderTest": "$TC actions del action skbmod index 909",
341 "expExitCode": "0",
342 "verifyCmd": "$TC actions ls action skbmod",
343 "matchPattern": "action order [0-9]*: skbmod pipe set etype 0x1111\\s+index 909",
344 "matchCount": "0",
345 "teardown": [
346 "$TC actions flush action skbmod"
347 ]
348 },
349 {
350 "id": "40c2",
351 "name": "Flush skbmod actions",
352 "category": [
353 "actions",
354 "skbmod"
355 ],
356 "setup": [
357 "$TC actions add action skbmod set etype 0x0001",
358 "$TC actions add action skbmod set etype 0x0011",
359 "$TC actions add action skbmod set etype 0x0021",
360 "$TC actions add action skbmod set etype 0x0031",
361 "$TC actions add action skbmod set etype 0x0041"
362 ],
363 "cmdUnderTest": "$TC actions flush action skbmod",
364 "expExitCode": "0",
365 "verifyCmd": "$TC actions ls action skbmod",
366 "matchPattern": "action order [0-9]*: skbmod",
367 "matchCount": "0",
368 "teardown": [
369 "$TC actions flush action skbmod"
370 ]
371 }
372]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json b/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
deleted file mode 100644
index af519bc97a8e..000000000000
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
+++ /dev/null
@@ -1,1115 +0,0 @@
1[
2 {
3 "id": "e89a",
4 "name": "Add valid pass action",
5 "category": [
6 "actions",
7 "gact"
8 ],
9 "setup": [
10 [
11 "$TC actions flush action gact",
12 0,
13 1,
14 255
15 ]
16 ],
17 "cmdUnderTest": "$TC actions add action pass index 8",
18 "expExitCode": "0",
19 "verifyCmd": "$TC actions list action gact",
20 "matchPattern": "action order [0-9]*: gact action pass.*index 8 ref",
21 "matchCount": "1",
22 "teardown": [
23 "$TC actions flush action gact"
24 ]
25 },
26 {
27 "id": "a02c",
28 "name": "Add valid pipe action",
29 "category": [
30 "actions",
31 "gact"
32 ],
33 "setup": [
34 [
35 "$TC actions flush action gact",
36 0,
37 1,
38 255
39 ]
40 ],
41 "cmdUnderTest": "$TC actions add action pipe index 6",
42 "expExitCode": "0",
43 "verifyCmd": "$TC actions list action gact",
44 "matchPattern": "action order [0-9]*: gact action pipe.*index 6 ref",
45 "matchCount": "1",
46 "teardown": [
47 "$TC actions flush action gact"
48 ]
49 },
50 {
51 "id": "feef",
52 "name": "Add valid reclassify action",
53 "category": [
54 "actions",
55 "gact"
56 ],
57 "setup": [
58 [
59 "$TC actions flush action gact",
60 0,
61 1,
62 255
63 ]
64 ],
65 "cmdUnderTest": "$TC actions add action reclassify index 5",
66 "expExitCode": "0",
67 "verifyCmd": "$TC actions list action gact",
68 "matchPattern": "action order [0-9]*: gact action reclassify.*index 5 ref",
69 "matchCount": "1",
70 "teardown": [
71 "$TC actions flush action gact"
72 ]
73 },
74 {
75 "id": "8a7a",
76 "name": "Add valid drop action",
77 "category": [
78 "actions",
79 "gact"
80 ],
81 "setup": [
82 [
83 "$TC actions flush action gact",
84 0,
85 1,
86 255
87 ]
88 ],
89 "cmdUnderTest": "$TC actions add action drop index 30",
90 "expExitCode": "0",
91 "verifyCmd": "$TC actions list action gact",
92 "matchPattern": "action order [0-9]*: gact action drop.*index 30 ref",
93 "matchCount": "1",
94 "teardown": [
95 "$TC actions flush action gact"
96 ]
97 },
98 {
99 "id": "9a52",
100 "name": "Add valid continue action",
101 "category": [
102 "actions",
103 "gact"
104 ],
105 "setup": [
106 [
107 "$TC actions flush action gact",
108 0,
109 1,
110 255
111 ]
112 ],
113 "cmdUnderTest": "$TC actions add action continue index 432",
114 "expExitCode": "0",
115 "verifyCmd": "$TC actions list action gact",
116 "matchPattern": "action order [0-9]*: gact action continue.*index 432 ref",
117 "matchCount": "1",
118 "teardown": [
119 "$TC actions flush action gact"
120 ]
121 },
122 {
123 "id": "d700",
124 "name": "Add invalid action",
125 "category": [
126 "actions",
127 "gact"
128 ],
129 "setup": [
130 [
131 "$TC actions flush action gact",
132 0,
133 1,
134 255
135 ]
136 ],
137 "cmdUnderTest": "$TC actions add action pump index 386",
138 "expExitCode": "255",
139 "verifyCmd": "$TC actions list action gact",
140 "matchPattern": "action order [0-9]*: gact action.*index 386 ref",
141 "matchCount": "0",
142 "teardown": [
143 "$TC actions flush action gact"
144 ]
145 },
146 {
147 "id": "9215",
148 "name": "Add action with duplicate index",
149 "category": [
150 "actions",
151 "gact"
152 ],
153 "setup": [
154 [
155 "$TC actions flush action gact",
156 0,
157 1,
158 255
159 ],
160 "$TC actions add action pipe index 15"
161 ],
162 "cmdUnderTest": "$TC actions add action drop index 15",
163 "expExitCode": "255",
164 "verifyCmd": "$TC actions list action gact",
165 "matchPattern": "action order [0-9]*: gact action drop.*index 15 ref",
166 "matchCount": "0",
167 "teardown": [
168 "$TC actions flush action gact"
169 ]
170 },
171 {
172 "id": "798e",
173 "name": "Add action with index exceeding 32-bit maximum",
174 "category": [
175 "actions",
176 "gact"
177 ],
178 "setup": [
179 [
180 "$TC actions flush action gact",
181 0,
182 1,
183 255
184 ]
185 ],
186 "cmdUnderTest": "$TC actions add action drop index 4294967296",
187 "expExitCode": "255",
188 "verifyCmd": "actions list action gact",
189 "matchPattern": "action order [0-9]*: gact action drop.*index 4294967296 ref",
190 "matchCount": "0",
191 "teardown": [
192 "$TC actions flush action gact"
193 ]
194 },
195 {
196 "id": "22be",
197 "name": "Add action with index at 32-bit maximum",
198 "category": [
199 "actions",
200 "gact"
201 ],
202 "setup": [
203 [
204 "$TC actions flush action gact",
205 0,
206 1,
207 255
208 ]
209 ],
210 "cmdUnderTest": "$TC actions add action drop index 4294967295",
211 "expExitCode": "0",
212 "verifyCmd": "$TC actions list action gact",
213 "matchPattern": "action order [0-9]*: gact action drop.*index 4294967295 ref",
214 "matchCount": "1",
215 "teardown": [
216 "$TC actions flush action gact"
217 ]
218 },
219 {
220 "id": "ac2a",
221 "name": "List actions",
222 "category": [
223 "actions",
224 "gact"
225 ],
226 "setup": [
227 [
228 "$TC actions flush action gact",
229 0,
230 1,
231 255
232 ],
233 "$TC actions add action reclassify index 101",
234 "$TC actions add action reclassify index 102",
235 "$TC actions add action reclassify index 103",
236 "$TC actions add action reclassify index 104",
237 "$TC actions add action reclassify index 105"
238 ],
239 "cmdUnderTest": "$TC actions list action gact",
240 "expExitCode": "0",
241 "verifyCmd": "$TC actions list action gact",
242 "matchPattern": "action order [0-9]*: gact action reclassify",
243 "matchCount": "5",
244 "teardown": [
245 "$TC actions flush action gact"
246 ]
247 },
248 {
249 "id": "63ec",
250 "name": "Delete pass action",
251 "category": [
252 "actions",
253 "gact"
254 ],
255 "setup": [
256 [
257 "$TC actions flush action gact",
258 0,
259 1,
260 255
261 ],
262 "$TC actions add action pass index 1"
263 ],
264 "cmdUnderTest": "$TC actions del action gact index 1",
265 "expExitCode": "0",
266 "verifyCmd": "$TC actions list action gact",
267 "matchPattern": "action order [0-9]*: gact action pass.*index 1 ref",
268 "matchCount": "0",
269 "teardown": [
270 "$TC actions flush action gact"
271 ]
272 },
273 {
274 "id": "46be",
275 "name": "Delete pipe action",
276 "category": [
277 "actions",
278 "gact"
279 ],
280 "setup": [
281 [
282 "$TC actions flush action gact",
283 0,
284 1,
285 255
286 ],
287 "$TC actions add action pipe index 9"
288 ],
289 "cmdUnderTest": "$TC actions del action gact index 9",
290 "expExitCode": "0",
291 "verifyCmd": "$TC actions list action gact",
292 "matchPattern": "action order [0-9]*: gact action pipe.*index 9 ref",
293 "matchCount": "0",
294 "teardown": [
295 "$TC actions flush action gact"
296 ]
297 },
298 {
299 "id": "2e08",
300 "name": "Delete reclassify action",
301 "category": [
302 "actions",
303 "gact"
304 ],
305 "setup": [
306 [
307 "$TC actions flush action gact",
308 0,
309 1,
310 255
311 ],
312 "$TC actions add action reclassify index 65536"
313 ],
314 "cmdUnderTest": "$TC actions del action gact index 65536",
315 "expExitCode": "0",
316 "verifyCmd": "$TC actions list action gact",
317 "matchPattern": "action order [0-9]*: gact action reclassify.*index 65536 ref",
318 "matchCount": "0",
319 "teardown": [
320 "$TC actions flush action gact"
321 ]
322 },
323 {
324 "id": "99c4",
325 "name": "Delete drop action",
326 "category": [
327 "actions",
328 "gact"
329 ],
330 "setup": [
331 [
332 "$TC actions flush action gact",
333 0,
334 1,
335 255
336 ],
337 "$TC actions add action drop index 16"
338 ],
339 "cmdUnderTest": "$TC actions del action gact index 16",
340 "expExitCode": "0",
341 "verifyCmd": "$TC actions list action gact",
342 "matchPattern": "action order [0-9]*: gact action drop.*index 16 ref",
343 "matchCount": "0",
344 "teardown": [
345 "$TC actions flush action gact"
346 ]
347 },
348 {
349 "id": "fb6b",
350 "name": "Delete continue action",
351 "category": [
352 "actions",
353 "gact"
354 ],
355 "setup": [
356 [
357 "$TC actions flush action gact",
358 0,
359 1,
360 255
361 ],
362 "$TC actions add action continue index 32"
363 ],
364 "cmdUnderTest": "$TC actions del action gact index 32",
365 "expExitCode": "0",
366 "verifyCmd": "actions list action gact",
367 "matchPattern": "action order [0-9]*: gact action continue.*index 32 ref",
368 "matchCount": "0",
369 "teardown": [
370 "$TC actions flush action gact"
371 ]
372 },
373 {
374 "id": "0eb3",
375 "name": "Delete non-existent action",
376 "category": [
377 "actions",
378 "gact"
379 ],
380 "setup": [
381 [
382 "$TC actions flush action gact",
383 0,
384 1,
385 255
386 ]
387 ],
388 "cmdUnderTest": "$TC actions del action gact index 2",
389 "expExitCode": "255",
390 "verifyCmd": "$TC actions list action gact",
391 "matchPattern": "action order [0-9]*: gact action",
392 "matchCount": "0",
393 "teardown": [
394 "$TC actions flush action gact"
395 ]
396 },
397 {
398 "id": "5124",
399 "name": "Add mirred mirror to egress action",
400 "category": [
401 "actions",
402 "mirred"
403 ],
404 "setup": [
405 [
406 "$TC actions flush action mirred",
407 0,
408 1,
409 255
410 ]
411 ],
412 "cmdUnderTest": "$TC actions add action mirred egress mirror index 1 dev lo",
413 "expExitCode": "0",
414 "verifyCmd": "$TC actions list action mirred",
415 "matchPattern": "action order [0-9]*: mirred \\(Egress Mirror to device lo\\).*index 1 ref",
416 "matchCount": "1",
417 "teardown": [
418 "$TC actions flush action mirred"
419 ]
420 },
421 {
422 "id": "6fb4",
423 "name": "Add mirred redirect to egress action",
424 "category": [
425 "actions",
426 "mirred"
427 ],
428 "setup": [
429 [
430 "$TC actions flush action mirred",
431 0,
432 1,
433 255
434 ]
435 ],
436 "cmdUnderTest": "$TC actions add action mirred egress redirect index 2 dev lo action pipe",
437 "expExitCode": "0",
438 "verifyCmd": "$TC actions list action mirred",
439 "matchPattern": "action order [0-9]*: mirred \\(Egress Redirect to device lo\\).*index 2 ref",
440 "matchCount": "1",
441 "teardown": [
442 "$TC actions flush action mirred"
443 ]
444 },
445 {
446 "id": "ba38",
447 "name": "Get mirred actions",
448 "category": [
449 "actions",
450 "mirred"
451 ],
452 "setup": [
453 [
454 "$TC actions flush action mirred",
455 0,
456 1,
457 255
458 ],
459 "$TC actions add action mirred egress mirror index 1 dev lo",
460 "$TC actions add action mirred egress redirect index 2 dev lo"
461 ],
462 "cmdUnderTest": "$TC actions show action mirred",
463 "expExitCode": "0",
464 "verifyCmd": "$TC actions list action mirred",
465 "matchPattern": "[Mirror|Redirect] to device lo",
466 "matchCount": "2",
467 "teardown": [
468 "$TC actions flush action mirred"
469 ]
470 },
471 {
472 "id": "d7c0",
473 "name": "Add invalid mirred direction",
474 "category": [
475 "actions",
476 "mirred"
477 ],
478 "setup": [
479 [
480 "$TC actions flush action mirred",
481 0,
482 1,
483 255
484 ]
485 ],
486 "cmdUnderTest": "$TC actions add action mirred inbound mirror index 20 dev lo",
487 "expExitCode": "255",
488 "verifyCmd": "$TC actions list action mirred",
489 "matchPattern": "action order [0-9]*: mirred \\(.*to device lo\\).*index 20 ref",
490 "matchCount": "0",
491 "teardown": [
492 "$TC actions flush action mirred"
493 ]
494 },
495 {
496 "id": "e213",
497 "name": "Add invalid mirred action",
498 "category": [
499 "actions",
500 "mirred"
501 ],
502 "setup": [
503 [
504 "$TC actions flush action mirred",
505 0,
506 1,
507 255
508 ]
509 ],
510 "cmdUnderTest": "$TC actions add action mirred egress remirror index 20 dev lo",
511 "expExitCode": "255",
512 "verifyCmd": "$TC actions list action mirred",
513 "matchPattern": "action order [0-9]*: mirred \\(Egress.*to device lo\\).*index 20 ref",
514 "matchCount": "0",
515 "teardown": [
516 "$TC actions flush action mirred"
517 ]
518 },
519 {
520 "id": "2d89",
521 "name": "Add mirred action with invalid device",
522 "category": [
523 "actions",
524 "mirred"
525 ],
526 "setup": [
527 [
528 "$TC actions flush action mirred",
529 0,
530 1,
531 255
532 ]
533 ],
534 "cmdUnderTest": "$TC actions add action mirred egress mirror index 20 dev eltoh",
535 "expExitCode": "255",
536 "verifyCmd": "$TC actions list action mirred",
537 "matchPattern": "action order [0-9]*: mirred \\(.*to device eltoh\\).*index 20 ref",
538 "matchCount": "0",
539 "teardown": [
540 "$TC actions flush action mirred"
541 ]
542 },
543 {
544 "id": "300b",
545 "name": "Add mirred action with duplicate index",
546 "category": [
547 "actions",
548 "mirred"
549 ],
550 "setup": [
551 [
552 "$TC actions flush action mirred",
553 0,
554 1,
555 255
556 ],
557 "$TC actions add action mirred egress redirect index 15 dev lo"
558 ],
559 "cmdUnderTest": "$TC actions add action mirred egress mirror index 15 dev lo",
560 "expExitCode": "255",
561 "verifyCmd": "$TC actions list action mirred",
562 "matchPattern": "action order [0-9]*: mirred \\(.*to device lo\\).*index 15 ref",
563 "matchCount": "1",
564 "teardown": [
565 "$TC actions flush action mirred"
566 ]
567 },
568 {
569 "id": "a70e",
570 "name": "Delete mirred mirror action",
571 "category": [
572 "actions",
573 "mirred"
574 ],
575 "setup": [
576 [
577 "$TC actions flush action mirred",
578 0,
579 1,
580 255
581 ],
582 "$TC actions add action mirred egress mirror index 5 dev lo"
583 ],
584 "cmdUnderTest": "$TC actions del action mirred index 5",
585 "expExitCode": "0",
586 "verifyCmd": "$TC actions list action mirred",
587 "matchPattern": "action order [0-9]*: mirred \\(Egress Mirror to device lo\\).*index 5 ref",
588 "matchCount": "0",
589 "teardown": [
590 "$TC actions flush action mirred"
591 ]
592 },
593 {
594 "id": "3fb3",
595 "name": "Delete mirred redirect action",
596 "category": [
597 "actions",
598 "mirred"
599 ],
600 "setup": [
601 [
602 "$TC actions flush action mirred",
603 0,
604 1,
605 255
606 ],
607 "$TC actions add action mirred egress redirect index 5 dev lo"
608 ],
609 "cmdUnderTest": "$TC actions del action mirred index 5",
610 "expExitCode": "0",
611 "verifyCmd": "$TC actions list action mirred",
612 "matchPattern": "action order [0-9]*: mirred \\(Egress Redirect to device lo\\).*index 5 ref",
613 "matchCount": "0",
614 "teardown": [
615 "$TC actions flush action mirred"
616 ]
617 },
618 {
619 "id": "b078",
620 "name": "Add simple action",
621 "category": [
622 "actions",
623 "simple"
624 ],
625 "setup": [
626 [
627 "$TC actions flush action simple",
628 0,
629 1,
630 255
631 ]
632 ],
633 "cmdUnderTest": "$TC actions add action simple sdata \"A triumph\" index 60",
634 "expExitCode": "0",
635 "verifyCmd": "$TC actions list action simple",
636 "matchPattern": "action order [0-9]*: Simple <A triumph>.*index 60 ref",
637 "matchCount": "1",
638 "teardown": [
639 "$TC actions flush action simple"
640 ]
641 },
642 {
643 "id": "6d4c",
644 "name": "Add simple action with duplicate index",
645 "category": [
646 "actions",
647 "simple"
648 ],
649 "setup": [
650 [
651 "$TC actions flush action simple",
652 0,
653 1,
654 255
655 ],
656 "$TC actions add action simple sdata \"Aruba\" index 4"
657 ],
658 "cmdUnderTest": "$TC actions add action simple sdata \"Jamaica\" index 4",
659 "expExitCode": "255",
660 "verifyCmd": "$TC actions list action simple",
661 "matchPattern": "action order [0-9]*: Simple <Jamaica>.*ref",
662 "matchCount": "0",
663 "teardown": [
664 "$TC actions flush action simple"
665 ]
666 },
667 {
668 "id": "2542",
669 "name": "List simple actions",
670 "category": [
671 "actions",
672 "simple"
673 ],
674 "setup": [
675 [
676 "$TC actions flush action simple",
677 0,
678 1,
679 255
680 ],
681 "$TC actions add action simple sdata \"Rock\"",
682 "$TC actions add action simple sdata \"Paper\"",
683 "$TC actions add action simple sdata \"Scissors\" index 98"
684 ],
685 "cmdUnderTest": "$TC actions list action simple",
686 "expExitCode": "0",
687 "verifyCmd": "$TC actions list action simple",
688 "matchPattern": "action order [0-9]*: Simple <[A-Z][a-z]*>",
689 "matchCount": "3",
690 "teardown": [
691 "$TC actions flush action simple"
692 ]
693 },
694 {
695 "id": "ea67",
696 "name": "Delete simple action",
697 "category": [
698 "actions",
699 "simple"
700 ],
701 "setup": [
702 [
703 "$TC actions flush action simple",
704 0,
705 1,
706 255
707 ],
708 "$TC actions add action simple sdata \"Blinkenlights\" index 1"
709 ],
710 "cmdUnderTest": "$TC actions delete action simple index 1",
711 "expExitCode": "0",
712 "verifyCmd": "$TC actions list action simple",
713 "matchPattern": "action order [0-9]*: Simple <Blinkenlights>.*index 1 ref",
714 "matchCount": "0",
715 "teardown": [
716 "$TC actions flush action simple"
717 ]
718 },
719 {
720 "id": "8ff1",
721 "name": "Flush simple actions",
722 "category": [
723 "actions",
724 "simple"
725 ],
726 "setup": [
727 [
728 "$TC actions flush action simple",
729 0,
730 1,
731 255
732 ],
733 "$TC actions add action simple sdata \"Kirk\"",
734 "$TC actions add action simple sdata \"Spock\" index 50",
735 "$TC actions add action simple sdata \"McCoy\" index 9"
736 ],
737 "cmdUnderTest": "$TC actions flush action simple",
738 "expExitCode": "0",
739 "verifyCmd": "$TC actions list action simple",
740 "matchPattern": "action order [0-9]*: Simple <[A-Z][a-z]*>",
741 "matchCount": "0",
742 "teardown": [
743 ""
744 ]
745 },
746 {
747 "id": "6236",
748 "name": "Add skbedit action with valid mark",
749 "category": [
750 "actions",
751 "skbedit"
752 ],
753 "setup": [
754 [
755 "$TC actions flush action skbedit",
756 0,
757 1,
758 255
759 ]
760 ],
761 "cmdUnderTest": "$TC actions add action skbedit mark 1",
762 "expExitCode": "0",
763 "verifyCmd": "$TC actions list action skbedit",
764 "matchPattern": "action order [0-9]*: skbedit mark 1",
765 "matchCount": "1",
766 "teardown": [
767 "$TC actions flush action skbedit"
768 ]
769 },
770 {
771 "id": "407b",
772 "name": "Add skbedit action with invalid mark",
773 "category": [
774 "actions",
775 "skbedit"
776 ],
777 "setup": [
778 [
779 "$TC actions flush action skbedit",
780 0,
781 1,
782 255
783 ]
784 ],
785 "cmdUnderTest": "$TC actions add action skbedit mark 666777888999",
786 "expExitCode": "255",
787 "verifyCmd": "$TC actions list action skbedit",
788 "matchPattern": "action order [0-9]*: skbedit mark",
789 "matchCount": "0",
790 "teardown": [
791 "$TC actions flush action skbedit"
792 ]
793 },
794 {
795 "id": "081d",
796 "name": "Add skbedit action with priority",
797 "category": [
798 "actions",
799 "skbedit"
800 ],
801 "setup": [
802 [
803 "$TC actions flush action skbedit",
804 0,
805 1,
806 255
807 ]
808 ],
809 "cmdUnderTest": "$TC actions add action skbedit prio 99",
810 "expExitCode": "0",
811 "verifyCmd": "$TC actions list action skbedit",
812 "matchPattern": "action order [0-9]*: skbedit priority :99",
813 "matchCount": "1",
814 "teardown": [
815 "$TC actions flush action skbedit"
816 ]
817 },
818 {
819 "id": "cc37",
820 "name": "Add skbedit action with invalid priority",
821 "category": [
822 "actions",
823 "skbedit"
824 ],
825 "setup": [
826 [
827 "$TC actions flush action skbedit",
828 0,
829 1,
830 255
831 ]
832 ],
833 "cmdUnderTest": "$TC actions add action skbedit prio foo",
834 "expExitCode": "255",
835 "verifyCmd": "$TC actions list action skbedit",
836 "matchPattern": "action order [0-9]*: skbedit priority",
837 "matchCount": "0",
838 "teardown": [
839 "$TC actions flush action skbedit"
840 ]
841 },
842 {
843 "id": "3c95",
844 "name": "Add skbedit action with queue_mapping",
845 "category": [
846 "actions",
847 "skbedit"
848 ],
849 "setup": [
850 [
851 "$TC actions flush action skbedit",
852 0,
853 1,
854 255
855 ]
856 ],
857 "cmdUnderTest": "$TC actions add action skbedit queue_mapping 909",
858 "expExitCode": "0",
859 "verifyCmd": "$TC actions list action skbedit",
860 "matchPattern": "action order [0-9]*: skbedit queue_mapping 909",
861 "matchCount": "1",
862 "teardown": [
863 "$TC actions flush action skbedit"
864 ]
865 },
866 {
867 "id": "985c",
868 "name": "Add skbedit action with invalid queue_mapping",
869 "category": [
870 "actions",
871 "skbedit"
872 ],
873 "setup": [
874 [
875 "$TC actions flush action skbedit",
876 0,
877 1,
878 255
879 ]
880 ],
881 "cmdUnderTest": "$TC actions add action skbedit queue_mapping 67000",
882 "expExitCode": "255",
883 "verifyCmd": "$TC actions list action skbedit",
884 "matchPattern": "action order [0-9]*: skbedit queue_mapping",
885 "matchCount": "0",
886 "teardown": [
887 "$TC actions flush action skbedit"
888 ]
889 },
890 {
891 "id": "224f",
892 "name": "Add skbedit action with ptype host",
893 "category": [
894 "actions",
895 "skbedit"
896 ],
897 "setup": [
898 [
899 "$TC actions flush action skbedit",
900 0,
901 1,
902 255
903 ]
904 ],
905 "cmdUnderTest": "$TC actions add action skbedit ptype host",
906 "expExitCode": "0",
907 "verifyCmd": "$TC actions list action skbedit",
908 "matchPattern": "action order [0-9]*: skbedit ptype host",
909 "matchCount": "1",
910 "teardown": [
911 "$TC actions flush action skbedit"
912 ]
913 },
914 {
915 "id": "d1a3",
916 "name": "Add skbedit action with ptype otherhost",
917 "category": [
918 "actions",
919 "skbedit"
920 ],
921 "setup": [
922 [
923 "$TC actions flush action skbedit",
924 0,
925 1,
926 255
927 ]
928 ],
929 "cmdUnderTest": "$TC actions add action skbedit ptype otherhost",
930 "expExitCode": "0",
931 "verifyCmd": "$TC actions list action skbedit",
932 "matchPattern": "action order [0-9]*: skbedit ptype otherhost",
933 "matchCount": "1",
934 "teardown": [
935 "$TC actions flush action skbedit"
936 ]
937 },
938 {
939 "id": "b9c6",
940 "name": "Add skbedit action with invalid ptype",
941 "category": [
942 "actions",
943 "skbedit"
944 ],
945 "setup": [
946 [
947 "$TC actions flush action skbedit",
948 0,
949 1,
950 255
951 ]
952 ],
953 "cmdUnderTest": "$TC actions add action skbedit ptype openair",
954 "expExitCode": "255",
955 "verifyCmd": "$TC actions list action skbedit",
956 "matchPattern": "action order [0-9]*: skbedit ptype openair",
957 "matchCount": "0",
958 "teardown": [
959 "$TC actions flush action skbedit"
960 ]
961 },
962 {
963 "id": "5172",
964 "name": "List skbedit actions",
965 "category": [
966 "actions",
967 "skbedit"
968 ],
969 "setup": [
970 [
971 "$TC actions flush action skbedit",
972 0,
973 1,
974 255
975 ],
976 "$TC actions add action skbedit ptype otherhost",
977 "$TC actions add action skbedit ptype broadcast",
978 "$TC actions add action skbedit mark 59",
979 "$TC actions add action skbedit mark 409"
980 ],
981 "cmdUnderTest": "$TC actions list action skbedit",
982 "expExitCode": "0",
983 "verifyCmd": "$TC actions list action skbedit",
984 "matchPattern": "action order [0-9]*: skbedit",
985 "matchCount": "4",
986 "teardown": [
987 "$TC actions flush action skbedit"
988 ]
989 },
990 {
991 "id": "a6d6",
992 "name": "Add skbedit action with index",
993 "category": [
994 "actions",
995 "skbedit"
996 ],
997 "setup": [
998 [
999 "$TC actions flush action skbedit",
1000 0,
1001 1,
1002 255
1003 ]
1004 ],
1005 "cmdUnderTest": "$TC actions add action skbedit mark 808 index 4040404040",
1006 "expExitCode": "0",
1007 "verifyCmd": "$TC actions list action skbedit",
1008 "matchPattern": "index 4040404040",
1009 "matchCount": "1",
1010 "teardown": [
1011 "$TC actions flush action skbedit"
1012 ]
1013 },
1014 {
1015 "id": "38f3",
1016 "name": "Delete skbedit action",
1017 "category": [
1018 "actions",
1019 "skbedit"
1020 ],
1021 "setup": [
1022 [
1023 "$TC actions flush action skbedit",
1024 0,
1025 1,
1026 255
1027 ],
1028 "$TC actions add action skbedit mark 42 index 9009"
1029 ],
1030 "cmdUnderTest": "$TC actions del action skbedit index 9009",
1031 "expExitCode": "0",
1032 "verifyCmd": "$TC actions list action skbedit",
1033 "matchPattern": "action order [0-9]*: skbedit mark 42",
1034 "matchCount": "0",
1035 "teardown": [
1036 "$TC actions flush action skbedit"
1037 ]
1038 },
1039 {
1040 "id": "ce97",
1041 "name": "Flush skbedit actions",
1042 "category": [
1043 "actions",
1044 "skbedit"
1045 ],
1046 "setup": [
1047 "$TC actions add action skbedit mark 500",
1048 "$TC actions add action skbedit mark 501",
1049 "$TC actions add action skbedit mark 502",
1050 "$TC actions add action skbedit mark 503",
1051 "$TC actions add action skbedit mark 504",
1052 "$TC actions add action skbedit mark 505",
1053 "$TC actions add action skbedit mark 506"
1054 ],
1055 "cmdUnderTest": "$TC actions flush action skbedit",
1056 "expExitCode": "0",
1057 "verifyCmd": "$TC actions list action skbedit",
1058 "matchPattern": "action order [0-9]*: skbedit",
1059 "matchCount": "0",
1060 "teardown": [
1061 "$TC actions flush action skbedit"
1062 ]
1063 },
1064 {
1065 "id": "f02c",
1066 "name": "Replace gact action",
1067 "category": [
1068 "actions",
1069 "gact"
1070 ],
1071 "setup": [
1072 [
1073 "$TC actions flush action gact",
1074 0,
1075 1,
1076 255
1077 ],
1078 "$TC actions add action drop index 10",
1079 "$TC actions add action drop index 12"
1080 ],
1081 "cmdUnderTest": "$TC actions replace action ok index 12",
1082 "expExitCode": "0",
1083 "verifyCmd": "$TC actions ls action gact",
1084 "matchPattern": "action order [0-9]*: gact action pass",
1085 "matchCount": "1",
1086 "teardown": [
1087 "$TC actions flush action gact"
1088 ]
1089 },
1090 {
1091 "id": "525f",
1092 "name": "Get gact action by index",
1093 "category": [
1094 "actions",
1095 "gact"
1096 ],
1097 "setup": [
1098 [
1099 "$TC actions flush action gact",
1100 0,
1101 1,
1102 255
1103 ],
1104 "$TC actions add action drop index 3900800700"
1105 ],
1106 "cmdUnderTest": "$TC actions get action gact index 3900800700",
1107 "expExitCode": "0",
1108 "verifyCmd": "$TC actions get action gact index 3900800700",
1109 "matchPattern": "index 3900800700",
1110 "matchCount": "1",
1111 "teardown": [
1112 "$TC actions flush action gact"
1113 ]
1114 }
1115] \ No newline at end of file
diff --git a/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json b/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
index c727b96a59b0..5fa02d86b35f 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
@@ -17,5 +17,26 @@
17 "teardown": [ 17 "teardown": [
18 "$TC qdisc del dev $DEV1 ingress" 18 "$TC qdisc del dev $DEV1 ingress"
19 ] 19 ]
20 },
21 {
22 "id": "d052",
23 "name": "Add 1M filters with the same action",
24 "category": [
25 "filter",
26 "flower"
27 ],
28 "setup": [
29 "$TC qdisc add dev $DEV2 ingress",
30 "./tdc_batch.py $DEV2 $BATCH_FILE --share_action -n 1000000"
31 ],
32 "cmdUnderTest": "$TC -b $BATCH_FILE",
33 "expExitCode": "0",
34 "verifyCmd": "$TC actions list action gact",
35 "matchPattern": "action order 0: gact action drop.*index 1 ref 1000000 bind 1000000",
36 "matchCount": "1",
37 "teardown": [
38 "$TC qdisc del dev $DEV2 ingress",
39 "/bin/rm $BATCH_FILE"
40 ]
20 } 41 }
21] \ No newline at end of file 42]
diff --git a/tools/testing/selftests/tc-testing/tdc.py b/tools/testing/selftests/tc-testing/tdc.py
index cd61b7844c0d..fc373fdf2bdc 100755
--- a/tools/testing/selftests/tc-testing/tdc.py
+++ b/tools/testing/selftests/tc-testing/tdc.py
@@ -1,4 +1,5 @@
1#!/usr/bin/env python3 1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0
2 3
3""" 4"""
4tdc.py - Linux tc (Traffic Control) unit test driver 5tdc.py - Linux tc (Traffic Control) unit test driver
@@ -49,7 +50,7 @@ def exec_cmd(command, nsonly=True):
49 stderr=subprocess.PIPE) 50 stderr=subprocess.PIPE)
50 (rawout, serr) = proc.communicate() 51 (rawout, serr) = proc.communicate()
51 52
52 if proc.returncode != 0: 53 if proc.returncode != 0 and len(serr) > 0:
53 foutput = serr.decode("utf-8") 54 foutput = serr.decode("utf-8")
54 else: 55 else:
55 foutput = rawout.decode("utf-8") 56 foutput = rawout.decode("utf-8")
@@ -88,7 +89,7 @@ def prepare_env(cmdlist):
88 exit(1) 89 exit(1)
89 90
90 91
91def test_runner(filtered_tests): 92def test_runner(filtered_tests, args):
92 """ 93 """
93 Driver function for the unit tests. 94 Driver function for the unit tests.
94 95
@@ -105,6 +106,8 @@ def test_runner(filtered_tests):
105 for tidx in testlist: 106 for tidx in testlist:
106 result = True 107 result = True
107 tresult = "" 108 tresult = ""
109 if "flower" in tidx["category"] and args.device == None:
110 continue
108 print("Test " + tidx["id"] + ": " + tidx["name"]) 111 print("Test " + tidx["id"] + ": " + tidx["name"])
109 prepare_env(tidx["setup"]) 112 prepare_env(tidx["setup"])
110 (p, procout) = exec_cmd(tidx["cmdUnderTest"]) 113 (p, procout) = exec_cmd(tidx["cmdUnderTest"])
@@ -150,7 +153,11 @@ def ns_create():
150 exec_cmd(cmd, False) 153 exec_cmd(cmd, False)
151 cmd = 'ip link set $DEV0 up' 154 cmd = 'ip link set $DEV0 up'
152 exec_cmd(cmd, False) 155 exec_cmd(cmd, False)
153 cmd = 'ip -s $NS link set $DEV1 up' 156 cmd = 'ip -n $NS link set $DEV1 up'
157 exec_cmd(cmd, False)
158 cmd = 'ip link set $DEV2 netns $NS'
159 exec_cmd(cmd, False)
160 cmd = 'ip -n $NS link set $DEV2 up'
154 exec_cmd(cmd, False) 161 exec_cmd(cmd, False)
155 162
156 163
@@ -173,15 +180,20 @@ def has_blank_ids(idlist):
173 180
174def load_from_file(filename): 181def load_from_file(filename):
175 """ 182 """
176 Open the JSON file containing the test cases and return them as an 183 Open the JSON file containing the test cases and return them
177 ordered dictionary object. 184 as list of ordered dictionary objects.
178 """ 185 """
179 with open(filename) as test_data: 186 try:
180 testlist = json.load(test_data, object_pairs_hook=OrderedDict) 187 with open(filename) as test_data:
181 idlist = get_id_list(testlist) 188 testlist = json.load(test_data, object_pairs_hook=OrderedDict)
182 if (has_blank_ids(idlist)): 189 except json.JSONDecodeError as jde:
183 for k in testlist: 190 print('IGNORING test case file {}\n\tBECAUSE: {}'.format(filename, jde))
184 k['filename'] = filename 191 testlist = list()
192 else:
193 idlist = get_id_list(testlist)
194 if (has_blank_ids(idlist)):
195 for k in testlist:
196 k['filename'] = filename
185 return testlist 197 return testlist
186 198
187 199
@@ -203,7 +215,7 @@ def set_args(parser):
203 help='Run tests only from the specified category, or if no category is specified, list known categories.') 215 help='Run tests only from the specified category, or if no category is specified, list known categories.')
204 parser.add_argument('-f', '--file', type=str, 216 parser.add_argument('-f', '--file', type=str,
205 help='Run tests from the specified file') 217 help='Run tests from the specified file')
206 parser.add_argument('-l', '--list', type=str, nargs='?', const="", metavar='CATEGORY', 218 parser.add_argument('-l', '--list', type=str, nargs='?', const="++", metavar='CATEGORY',
207 help='List all test cases, or those only within the specified category') 219 help='List all test cases, or those only within the specified category')
208 parser.add_argument('-s', '--show', type=str, nargs=1, metavar='ID', dest='showID', 220 parser.add_argument('-s', '--show', type=str, nargs=1, metavar='ID', dest='showID',
209 help='Display the test case with specified id') 221 help='Display the test case with specified id')
@@ -211,7 +223,8 @@ def set_args(parser):
211 help='Execute the single test case with specified ID') 223 help='Execute the single test case with specified ID')
212 parser.add_argument('-i', '--id', action='store_true', dest='gen_id', 224 parser.add_argument('-i', '--id', action='store_true', dest='gen_id',
213 help='Generate ID numbers for new test cases') 225 help='Generate ID numbers for new test cases')
214 return parser 226 parser.add_argument('-d', '--device',
227 help='Execute the test case in flower category')
215 return parser 228 return parser
216 229
217 230
@@ -225,6 +238,8 @@ def check_default_settings(args):
225 238
226 if args.path != None: 239 if args.path != None:
227 NAMES['TC'] = args.path 240 NAMES['TC'] = args.path
241 if args.device != None:
242 NAMES['DEV2'] = args.device
228 if not os.path.isfile(NAMES['TC']): 243 if not os.path.isfile(NAMES['TC']):
229 print("The specified tc path " + NAMES['TC'] + " does not exist.") 244 print("The specified tc path " + NAMES['TC'] + " does not exist.")
230 exit(1) 245 exit(1)
@@ -357,10 +372,10 @@ def set_operation_mode(args):
357 testcases = get_categorized_testlist(alltests, ucat) 372 testcases = get_categorized_testlist(alltests, ucat)
358 373
359 if args.list: 374 if args.list:
360 if (len(args.list) == 0): 375 if (args.list == "++"):
361 list_test_cases(alltests) 376 list_test_cases(alltests)
362 exit(0) 377 exit(0)
363 elif(len(args.list > 0)): 378 elif(len(args.list) > 0):
364 if (args.list not in ucat): 379 if (args.list not in ucat):
365 print("Unknown category " + args.list) 380 print("Unknown category " + args.list)
366 print("Available categories:") 381 print("Available categories:")
@@ -381,14 +396,17 @@ def set_operation_mode(args):
381 if (len(alltests) == 0): 396 if (len(alltests) == 0):
382 print("Cannot find a test case with ID matching " + target_id) 397 print("Cannot find a test case with ID matching " + target_id)
383 exit(1) 398 exit(1)
384 catresults = test_runner(alltests) 399 catresults = test_runner(alltests, args)
385 print("All test results: " + "\n\n" + catresults) 400 print("All test results: " + "\n\n" + catresults)
386 elif (len(target_category) > 0): 401 elif (len(target_category) > 0):
402 if (target_category == "flower") and args.device == None:
403 print("Please specify a NIC device (-d) to run category flower")
404 exit(1)
387 if (target_category not in ucat): 405 if (target_category not in ucat):
388 print("Specified category is not present in this file.") 406 print("Specified category is not present in this file.")
389 exit(1) 407 exit(1)
390 else: 408 else:
391 catresults = test_runner(testcases[target_category]) 409 catresults = test_runner(testcases[target_category], args)
392 print("Category " + target_category + "\n\n" + catresults) 410 print("Category " + target_category + "\n\n" + catresults)
393 411
394 ns_destroy() 412 ns_destroy()
diff --git a/tools/testing/selftests/tc-testing/tdc_batch.py b/tools/testing/selftests/tc-testing/tdc_batch.py
new file mode 100755
index 000000000000..707c6bfef689
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tdc_batch.py
@@ -0,0 +1,62 @@
1#!/usr/bin/python3
2
3"""
4tdc_batch.py - a script to generate TC batch file
5
6Copyright (C) 2017 Chris Mi <chrism@mellanox.com>
7"""
8
9import argparse
10
11parser = argparse.ArgumentParser(description='TC batch file generator')
12parser.add_argument("device", help="device name")
13parser.add_argument("file", help="batch file name")
14parser.add_argument("-n", "--number", type=int,
15 help="how many lines in batch file")
16parser.add_argument("-o", "--skip_sw",
17 help="skip_sw (offload), by default skip_hw",
18 action="store_true")
19parser.add_argument("-s", "--share_action",
20 help="all filters share the same action",
21 action="store_true")
22parser.add_argument("-p", "--prio",
23 help="all filters have different prio",
24 action="store_true")
25args = parser.parse_args()
26
27device = args.device
28file = open(args.file, 'w')
29
30number = 1
31if args.number:
32 number = args.number
33
34skip = "skip_hw"
35if args.skip_sw:
36 skip = "skip_sw"
37
38share_action = ""
39if args.share_action:
40 share_action = "index 1"
41
42prio = "prio 1"
43if args.prio:
44 prio = ""
45 if number > 0x4000:
46 number = 0x4000
47
48index = 0
49for i in range(0x100):
50 for j in range(0x100):
51 for k in range(0x100):
52 mac = ("%02x:%02x:%02x" % (i, j, k))
53 src_mac = "e4:11:00:" + mac
54 dst_mac = "e4:12:00:" + mac
55 cmd = ("filter add dev %s %s protocol ip parent ffff: flower %s "
56 "src_mac %s dst_mac %s action drop %s" %
57 (device, prio, skip, src_mac, dst_mac, share_action))
58 file.write("%s\n" % cmd)
59 index += 1
60 if index >= number:
61 file.close()
62 exit(0)
diff --git a/tools/testing/selftests/tc-testing/tdc_config.py b/tools/testing/selftests/tc-testing/tdc_config.py
index 01087375a7c3..a023d0d62b25 100644
--- a/tools/testing/selftests/tc-testing/tdc_config.py
+++ b/tools/testing/selftests/tc-testing/tdc_config.py
@@ -1,4 +1,5 @@
1""" 1"""
2# SPDX-License-Identifier: GPL-2.0
2tdc_config.py - tdc user-specified values 3tdc_config.py - tdc user-specified values
3 4
4Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com> 5Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com>
@@ -12,6 +13,22 @@ NAMES = {
12 # Name of veth devices to be created for the namespace 13 # Name of veth devices to be created for the namespace
13 'DEV0': 'v0p0', 14 'DEV0': 'v0p0',
14 'DEV1': 'v0p1', 15 'DEV1': 'v0p1',
16 'DEV2': '',
17 'BATCH_FILE': './batch.txt',
15 # Name of the namespace to use 18 # Name of the namespace to use
16 'NS': 'tcut' 19 'NS': 'tcut'
17 } 20 }
21
22
23ENVIR = { }
24
25# put customizations in tdc_config_local.py
26try:
27 from tdc_config_local import *
28except ImportError as ie:
29 pass
30
31try:
32 NAMES.update(EXTRA_NAMES)
33except NameError as ne:
34 pass
diff --git a/tools/testing/selftests/tc-testing/tdc_config_local_template.py b/tools/testing/selftests/tc-testing/tdc_config_local_template.py
new file mode 100644
index 000000000000..d48fc732a399
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tdc_config_local_template.py
@@ -0,0 +1,23 @@
1"""
2tdc_config_local.py - tdc plugin-writer-specified values
3
4Copyright (C) 2017 bjb@mojatatu.com
5"""
6
7import os
8
9ENVIR = os.environ.copy()
10
11ENV_LD_LIBRARY_PATH = os.getenv('LD_LIBRARY_PATH', '')
12ENV_OTHER_LIB = os.getenv('OTHER_LIB', '')
13
14
15# example adding value to NAMES, without editing tdc_config.py
16EXTRA_NAMES = dict()
17EXTRA_NAMES['SOME_BIN'] = os.path.join(os.getenv('OTHER_BIN', ''), 'some_bin')
18
19
20# example adding values to ENVIR, without editing tdc_config.py
21ENVIR['VALGRIND_LIB'] = '/usr/lib/valgrind'
22ENVIR['VALGRIND_BIN'] = '/usr/bin/valgrind'
23ENVIR['VGDB_BIN'] = '/usr/bin/vgdb'
diff --git a/tools/testing/selftests/tc-testing/tdc_helper.py b/tools/testing/selftests/tc-testing/tdc_helper.py
index c3254f861fb2..db381120a566 100644
--- a/tools/testing/selftests/tc-testing/tdc_helper.py
+++ b/tools/testing/selftests/tc-testing/tdc_helper.py
@@ -1,4 +1,5 @@
1""" 1"""
2# SPDX-License-Identifier: GPL-2.0
2tdc_helper.py - tdc helper functions 3tdc_helper.py - tdc helper functions
3 4
4Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com> 5Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com>
@@ -15,7 +16,7 @@ def get_categorized_testlist(alltests, ucat):
15 16
16 17
17def get_unique_item(lst): 18def get_unique_item(lst):
18 """ For a list, return a set of the unique items in the list. """ 19 """ For a list, return a list of the unique items in the list. """
19 return list(set(lst)) 20 return list(set(lst))
20 21
21 22
@@ -57,7 +58,7 @@ def print_sll(items):
57def print_test_case(tcase): 58def print_test_case(tcase):
58 """ Pretty-printing of a given test case. """ 59 """ Pretty-printing of a given test case. """
59 for k in tcase.keys(): 60 for k in tcase.keys():
60 if (type(tcase[k]) == list): 61 if (isinstance(tcase[k], list)):
61 print(k + ":") 62 print(k + ":")
62 print_list(tcase[k]) 63 print_list(tcase[k])
63 else: 64 else:
diff --git a/tools/testing/selftests/timers/.gitignore b/tools/testing/selftests/timers/.gitignore
index cc986621f512..2c8ac8416299 100644
--- a/tools/testing/selftests/timers/.gitignore
+++ b/tools/testing/selftests/timers/.gitignore
@@ -18,3 +18,5 @@ threadtest
18valid-adjtimex 18valid-adjtimex
19adjtick 19adjtick
20set-tz 20set-tz
21freq-step
22rtctest_setdate
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile
index a9b86133b9b3..3496680981f2 100644
--- a/tools/testing/selftests/timers/Makefile
+++ b/tools/testing/selftests/timers/Makefile
@@ -1,5 +1,5 @@
1BUILD_FLAGS = -DKTEST 1# SPDX-License-Identifier: GPL-2.0
2CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS) 2CFLAGS += -O3 -Wl,-no-as-needed -Wall
3LDFLAGS += -lrt -lpthread -lm 3LDFLAGS += -lrt -lpthread -lm
4 4
5# these are all "safe" tests that don't modify 5# these are all "safe" tests that don't modify
@@ -7,9 +7,11 @@ LDFLAGS += -lrt -lpthread -lm
7TEST_GEN_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \ 7TEST_GEN_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
8 inconsistency-check raw_skew threadtest rtctest 8 inconsistency-check raw_skew threadtest rtctest
9 9
10TEST_GEN_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \ 10DESTRUCTIVE_TESTS = alarmtimer-suspend valid-adjtimex adjtick change_skew \
11 skew_consistency clocksource-switch freq-step leap-a-day \ 11 skew_consistency clocksource-switch freq-step leap-a-day \
12 leapcrash set-tai set-2038 set-tz rtctest_setdate 12 leapcrash set-tai set-2038 set-tz
13
14TEST_GEN_PROGS_EXTENDED = $(DESTRUCTIVE_TESTS) rtctest_setdate
13 15
14 16
15include ../lib.mk 17include ../lib.mk
@@ -18,16 +20,4 @@ include ../lib.mk
18# and may modify the system time or trigger 20# and may modify the system time or trigger
19# other behavior like suspend 21# other behavior like suspend
20run_destructive_tests: run_tests 22run_destructive_tests: run_tests
21 ./alarmtimer-suspend 23 $(call RUN_TESTS, $(DESTRUCTIVE_TESTS))
22 ./valid-adjtimex
23 ./adjtick
24 ./change_skew
25 ./skew_consistency
26 ./clocksource-switch
27 ./freq-step
28 ./leap-a-day -s -i 10
29 ./leapcrash
30 ./set-tz
31 ./set-tai
32 ./set-2038
33
diff --git a/tools/testing/selftests/timers/adjtick.c b/tools/testing/selftests/timers/adjtick.c
index 9887fd538fec..0caca3a06bd2 100644
--- a/tools/testing/selftests/timers/adjtick.c
+++ b/tools/testing/selftests/timers/adjtick.c
@@ -23,18 +23,7 @@
23#include <sys/timex.h> 23#include <sys/timex.h>
24#include <time.h> 24#include <time.h>
25 25
26#ifdef KTEST
27#include "../kselftest.h" 26#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 27
39#define CLOCK_MONOTONIC_RAW 4 28#define CLOCK_MONOTONIC_RAW 4
40 29
diff --git a/tools/testing/selftests/timers/alarmtimer-suspend.c b/tools/testing/selftests/timers/alarmtimer-suspend.c
index 2b361b830395..4da09dbf83ba 100644
--- a/tools/testing/selftests/timers/alarmtimer-suspend.c
+++ b/tools/testing/selftests/timers/alarmtimer-suspend.c
@@ -28,18 +28,7 @@
28#include <signal.h> 28#include <signal.h>
29#include <stdlib.h> 29#include <stdlib.h>
30#include <pthread.h> 30#include <pthread.h>
31#ifdef KTEST
32#include "../kselftest.h" 31#include "../kselftest.h"
33#else
34static inline int ksft_exit_pass(void)
35{
36 exit(0);
37}
38static inline int ksft_exit_fail(void)
39{
40 exit(1);
41}
42#endif
43 32
44#define CLOCK_REALTIME 0 33#define CLOCK_REALTIME 0
45#define CLOCK_MONOTONIC 1 34#define CLOCK_MONOTONIC 1
diff --git a/tools/testing/selftests/timers/change_skew.c b/tools/testing/selftests/timers/change_skew.c
index cb1968977c04..c4eab7124990 100644
--- a/tools/testing/selftests/timers/change_skew.c
+++ b/tools/testing/selftests/timers/change_skew.c
@@ -28,18 +28,7 @@
28#include <sys/time.h> 28#include <sys/time.h>
29#include <sys/timex.h> 29#include <sys/timex.h>
30#include <time.h> 30#include <time.h>
31#ifdef KTEST
32#include "../kselftest.h" 31#include "../kselftest.h"
33#else
34static inline int ksft_exit_pass(void)
35{
36 exit(0);
37}
38static inline int ksft_exit_fail(void)
39{
40 exit(1);
41}
42#endif
43 32
44#define NSEC_PER_SEC 1000000000LL 33#define NSEC_PER_SEC 1000000000LL
45 34
diff --git a/tools/testing/selftests/timers/clocksource-switch.c b/tools/testing/selftests/timers/clocksource-switch.c
index 5ff165373f8b..bfc974b4572d 100644
--- a/tools/testing/selftests/timers/clocksource-switch.c
+++ b/tools/testing/selftests/timers/clocksource-switch.c
@@ -34,18 +34,7 @@
34#include <fcntl.h> 34#include <fcntl.h>
35#include <string.h> 35#include <string.h>
36#include <sys/wait.h> 36#include <sys/wait.h>
37#ifdef KTEST
38#include "../kselftest.h" 37#include "../kselftest.h"
39#else
40static inline int ksft_exit_pass(void)
41{
42 exit(0);
43}
44static inline int ksft_exit_fail(void)
45{
46 exit(1);
47}
48#endif
49 38
50 39
51int get_clocksources(char list[][30]) 40int get_clocksources(char list[][30])
@@ -61,7 +50,7 @@ int get_clocksources(char list[][30])
61 50
62 close(fd); 51 close(fd);
63 52
64 for (i = 0; i < 30; i++) 53 for (i = 0; i < 10; i++)
65 list[i][0] = '\0'; 54 list[i][0] = '\0';
66 55
67 head = buf; 56 head = buf;
diff --git a/tools/testing/selftests/timers/freq-step.c b/tools/testing/selftests/timers/freq-step.c
index e8c61830825a..14a2b77fd012 100644
--- a/tools/testing/selftests/timers/freq-step.c
+++ b/tools/testing/selftests/timers/freq-step.c
@@ -33,6 +33,10 @@
33#define MAX_FREQ_ERROR 10e-6 33#define MAX_FREQ_ERROR 10e-6
34#define MAX_STDDEV 1000e-9 34#define MAX_STDDEV 1000e-9
35 35
36#ifndef ADJ_SETOFFSET
37 #define ADJ_SETOFFSET 0x0100
38#endif
39
36struct sample { 40struct sample {
37 double offset; 41 double offset;
38 double time; 42 double time;
@@ -229,10 +233,9 @@ static void init_test(void)
229 printf("CLOCK_MONOTONIC_RAW+CLOCK_MONOTONIC precision: %.0f ns\t\t", 233 printf("CLOCK_MONOTONIC_RAW+CLOCK_MONOTONIC precision: %.0f ns\t\t",
230 1e9 * precision); 234 1e9 * precision);
231 235
232 if (precision > MAX_PRECISION) { 236 if (precision > MAX_PRECISION)
233 printf("[SKIP]\n"); 237 ksft_exit_skip("precision: %.0f ns > MAX_PRECISION: %.0f ns\n",
234 ksft_exit_skip(); 238 1e9 * precision, 1e9 * MAX_PRECISION);
235 }
236 239
237 printf("[OK]\n"); 240 printf("[OK]\n");
238 srand(ts.tv_sec ^ ts.tv_nsec); 241 srand(ts.tv_sec ^ ts.tv_nsec);
@@ -262,7 +265,7 @@ int main(int argc, char **argv)
262 set_frequency(0.0); 265 set_frequency(0.0);
263 266
264 if (fails) 267 if (fails)
265 ksft_exit_fail(); 268 return ksft_exit_fail();
266 269
267 ksft_exit_pass(); 270 return ksft_exit_pass();
268} 271}
diff --git a/tools/testing/selftests/timers/inconsistency-check.c b/tools/testing/selftests/timers/inconsistency-check.c
index 74c60e8759a0..022d3ffe3fbf 100644
--- a/tools/testing/selftests/timers/inconsistency-check.c
+++ b/tools/testing/selftests/timers/inconsistency-check.c
@@ -28,18 +28,7 @@
28#include <sys/timex.h> 28#include <sys/timex.h>
29#include <string.h> 29#include <string.h>
30#include <signal.h> 30#include <signal.h>
31#ifdef KTEST
32#include "../kselftest.h" 31#include "../kselftest.h"
33#else
34static inline int ksft_exit_pass(void)
35{
36 exit(0);
37}
38static inline int ksft_exit_fail(void)
39{
40 exit(1);
41}
42#endif
43 32
44#define CALLS_PER_LOOP 64 33#define CALLS_PER_LOOP 64
45#define NSEC_PER_SEC 1000000000ULL 34#define NSEC_PER_SEC 1000000000ULL
diff --git a/tools/testing/selftests/timers/leap-a-day.c b/tools/testing/selftests/timers/leap-a-day.c
index fb46ad6ac92c..19e46ed5dfb5 100644
--- a/tools/testing/selftests/timers/leap-a-day.c
+++ b/tools/testing/selftests/timers/leap-a-day.c
@@ -48,18 +48,7 @@
48#include <string.h> 48#include <string.h>
49#include <signal.h> 49#include <signal.h>
50#include <unistd.h> 50#include <unistd.h>
51#ifdef KTEST
52#include "../kselftest.h" 51#include "../kselftest.h"
53#else
54static inline int ksft_exit_pass(void)
55{
56 exit(0);
57}
58static inline int ksft_exit_fail(void)
59{
60 exit(1);
61}
62#endif
63 52
64#define NSEC_PER_SEC 1000000000ULL 53#define NSEC_PER_SEC 1000000000ULL
65#define CLOCK_TAI 11 54#define CLOCK_TAI 11
@@ -190,18 +179,18 @@ int main(int argc, char **argv)
190 struct sigevent se; 179 struct sigevent se;
191 struct sigaction act; 180 struct sigaction act;
192 int signum = SIGRTMAX; 181 int signum = SIGRTMAX;
193 int settime = 0; 182 int settime = 1;
194 int tai_time = 0; 183 int tai_time = 0;
195 int insert = 1; 184 int insert = 1;
196 int iterations = -1; 185 int iterations = 10;
197 int opt; 186 int opt;
198 187
199 /* Process arguments */ 188 /* Process arguments */
200 while ((opt = getopt(argc, argv, "sti:")) != -1) { 189 while ((opt = getopt(argc, argv, "sti:")) != -1) {
201 switch (opt) { 190 switch (opt) {
202 case 's': 191 case 'w':
203 printf("Setting time to speed up testing\n"); 192 printf("Only setting leap-flag, not changing time. It could take up to a day for leap to trigger.\n");
204 settime = 1; 193 settime = 0;
205 break; 194 break;
206 case 'i': 195 case 'i':
207 iterations = atoi(optarg); 196 iterations = atoi(optarg);
@@ -210,9 +199,10 @@ int main(int argc, char **argv)
210 tai_time = 1; 199 tai_time = 1;
211 break; 200 break;
212 default: 201 default:
213 printf("Usage: %s [-s] [-i <iterations>]\n", argv[0]); 202 printf("Usage: %s [-w] [-i <iterations>]\n", argv[0]);
214 printf(" -s: Set time to right before leap second each iteration\n"); 203 printf(" -w: Set flag and wait for leap second each iteration");
215 printf(" -i: Number of iterations\n"); 204 printf(" (default sets time to right before leapsecond)\n");
205 printf(" -i: Number of iterations (-1 = infinite, default is 10)\n");
216 printf(" -t: Print TAI time\n"); 206 printf(" -t: Print TAI time\n");
217 exit(-1); 207 exit(-1);
218 } 208 }
diff --git a/tools/testing/selftests/timers/leapcrash.c b/tools/testing/selftests/timers/leapcrash.c
index a1071bdbdeb7..830c462f605d 100644
--- a/tools/testing/selftests/timers/leapcrash.c
+++ b/tools/testing/selftests/timers/leapcrash.c
@@ -22,20 +22,7 @@
22#include <sys/timex.h> 22#include <sys/timex.h>
23#include <string.h> 23#include <string.h>
24#include <signal.h> 24#include <signal.h>
25#ifdef KTEST
26#include "../kselftest.h" 25#include "../kselftest.h"
27#else
28static inline int ksft_exit_pass(void)
29{
30 exit(0);
31}
32static inline int ksft_exit_fail(void)
33{
34 exit(1);
35}
36#endif
37
38
39 26
40/* clear NTP time_status & time_state */ 27/* clear NTP time_status & time_state */
41int clear_time_state(void) 28int clear_time_state(void)
diff --git a/tools/testing/selftests/timers/mqueue-lat.c b/tools/testing/selftests/timers/mqueue-lat.c
index a2a3924d0b41..1867db5d6f5e 100644
--- a/tools/testing/selftests/timers/mqueue-lat.c
+++ b/tools/testing/selftests/timers/mqueue-lat.c
@@ -29,18 +29,7 @@
29#include <signal.h> 29#include <signal.h>
30#include <errno.h> 30#include <errno.h>
31#include <mqueue.h> 31#include <mqueue.h>
32#ifdef KTEST
33#include "../kselftest.h" 32#include "../kselftest.h"
34#else
35static inline int ksft_exit_pass(void)
36{
37 exit(0);
38}
39static inline int ksft_exit_fail(void)
40{
41 exit(1);
42}
43#endif
44 33
45#define NSEC_PER_SEC 1000000000ULL 34#define NSEC_PER_SEC 1000000000ULL
46 35
diff --git a/tools/testing/selftests/timers/nanosleep.c b/tools/testing/selftests/timers/nanosleep.c
index ff942ff7c9b3..8adb0bb51d4d 100644
--- a/tools/testing/selftests/timers/nanosleep.c
+++ b/tools/testing/selftests/timers/nanosleep.c
@@ -27,18 +27,7 @@
27#include <sys/timex.h> 27#include <sys/timex.h>
28#include <string.h> 28#include <string.h>
29#include <signal.h> 29#include <signal.h>
30#ifdef KTEST
31#include "../kselftest.h" 30#include "../kselftest.h"
32#else
33static inline int ksft_exit_pass(void)
34{
35 exit(0);
36}
37static inline int ksft_exit_fail(void)
38{
39 exit(1);
40}
41#endif
42 31
43#define NSEC_PER_SEC 1000000000ULL 32#define NSEC_PER_SEC 1000000000ULL
44 33
diff --git a/tools/testing/selftests/timers/nsleep-lat.c b/tools/testing/selftests/timers/nsleep-lat.c
index 2d7898fda0f1..c3c3dc10db17 100644
--- a/tools/testing/selftests/timers/nsleep-lat.c
+++ b/tools/testing/selftests/timers/nsleep-lat.c
@@ -24,18 +24,7 @@
24#include <sys/timex.h> 24#include <sys/timex.h>
25#include <string.h> 25#include <string.h>
26#include <signal.h> 26#include <signal.h>
27#ifdef KTEST
28#include "../kselftest.h" 27#include "../kselftest.h"
29#else
30static inline int ksft_exit_pass(void)
31{
32 exit(0);
33}
34static inline int ksft_exit_fail(void)
35{
36 exit(1);
37}
38#endif
39 28
40#define NSEC_PER_SEC 1000000000ULL 29#define NSEC_PER_SEC 1000000000ULL
41 30
diff --git a/tools/testing/selftests/timers/raw_skew.c b/tools/testing/selftests/timers/raw_skew.c
index 30906bfd9c1b..ca6cd146aafe 100644
--- a/tools/testing/selftests/timers/raw_skew.c
+++ b/tools/testing/selftests/timers/raw_skew.c
@@ -25,19 +25,7 @@
25#include <sys/time.h> 25#include <sys/time.h>
26#include <sys/timex.h> 26#include <sys/timex.h>
27#include <time.h> 27#include <time.h>
28#ifdef KTEST
29#include "../kselftest.h" 28#include "../kselftest.h"
30#else
31static inline int ksft_exit_pass(void)
32{
33 exit(0);
34}
35static inline int ksft_exit_fail(void)
36{
37 exit(1);
38}
39#endif
40
41 29
42#define CLOCK_MONOTONIC_RAW 4 30#define CLOCK_MONOTONIC_RAW 4
43#define NSEC_PER_SEC 1000000000LL 31#define NSEC_PER_SEC 1000000000LL
diff --git a/tools/testing/selftests/timers/rtctest.c b/tools/testing/selftests/timers/rtctest.c
index f61170f7b024..411eff625e66 100644
--- a/tools/testing/selftests/timers/rtctest.c
+++ b/tools/testing/selftests/timers/rtctest.c
@@ -221,6 +221,11 @@ test_READ:
221 /* Read the current alarm settings */ 221 /* Read the current alarm settings */
222 retval = ioctl(fd, RTC_ALM_READ, &rtc_tm); 222 retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
223 if (retval == -1) { 223 if (retval == -1) {
224 if (errno == EINVAL) {
225 fprintf(stderr,
226 "\n...EINVAL reading current alarm setting.\n");
227 goto test_PIE;
228 }
224 perror("RTC_ALM_READ ioctl"); 229 perror("RTC_ALM_READ ioctl");
225 exit(errno); 230 exit(errno);
226 } 231 }
@@ -231,7 +236,7 @@ test_READ:
231 /* Enable alarm interrupts */ 236 /* Enable alarm interrupts */
232 retval = ioctl(fd, RTC_AIE_ON, 0); 237 retval = ioctl(fd, RTC_AIE_ON, 0);
233 if (retval == -1) { 238 if (retval == -1) {
234 if (errno == EINVAL) { 239 if (errno == EINVAL || errno == EIO) {
235 fprintf(stderr, 240 fprintf(stderr,
236 "\n...Alarm IRQs not supported.\n"); 241 "\n...Alarm IRQs not supported.\n");
237 goto test_PIE; 242 goto test_PIE;
diff --git a/tools/testing/selftests/timers/set-2038.c b/tools/testing/selftests/timers/set-2038.c
index c8a7e14446b1..688cfd81b531 100644
--- a/tools/testing/selftests/timers/set-2038.c
+++ b/tools/testing/selftests/timers/set-2038.c
@@ -27,18 +27,7 @@
27#include <unistd.h> 27#include <unistd.h>
28#include <time.h> 28#include <time.h>
29#include <sys/time.h> 29#include <sys/time.h>
30#ifdef KTEST
31#include "../kselftest.h" 30#include "../kselftest.h"
32#else
33static inline int ksft_exit_pass(void)
34{
35 exit(0);
36}
37static inline int ksft_exit_fail(void)
38{
39 exit(1);
40}
41#endif
42 31
43#define NSEC_PER_SEC 1000000000LL 32#define NSEC_PER_SEC 1000000000LL
44 33
diff --git a/tools/testing/selftests/timers/set-tai.c b/tools/testing/selftests/timers/set-tai.c
index dc88dbc8831f..70fed27d8fd3 100644
--- a/tools/testing/selftests/timers/set-tai.c
+++ b/tools/testing/selftests/timers/set-tai.c
@@ -23,18 +23,7 @@
23#include <string.h> 23#include <string.h>
24#include <signal.h> 24#include <signal.h>
25#include <unistd.h> 25#include <unistd.h>
26#ifdef KTEST
27#include "../kselftest.h" 26#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 27
39int set_tai(int offset) 28int set_tai(int offset)
40{ 29{
diff --git a/tools/testing/selftests/timers/set-timer-lat.c b/tools/testing/selftests/timers/set-timer-lat.c
index 4fc98c5b0899..50da45437daa 100644
--- a/tools/testing/selftests/timers/set-timer-lat.c
+++ b/tools/testing/selftests/timers/set-timer-lat.c
@@ -20,6 +20,7 @@
20 */ 20 */
21 21
22 22
23#include <errno.h>
23#include <stdio.h> 24#include <stdio.h>
24#include <unistd.h> 25#include <unistd.h>
25#include <time.h> 26#include <time.h>
@@ -27,18 +28,7 @@
27#include <signal.h> 28#include <signal.h>
28#include <stdlib.h> 29#include <stdlib.h>
29#include <pthread.h> 30#include <pthread.h>
30#ifdef KTEST
31#include "../kselftest.h" 31#include "../kselftest.h"
32#else
33static inline int ksft_exit_pass(void)
34{
35 exit(0);
36}
37static inline int ksft_exit_fail(void)
38{
39 exit(1);
40}
41#endif
42 32
43#define CLOCK_REALTIME 0 33#define CLOCK_REALTIME 0
44#define CLOCK_MONOTONIC 1 34#define CLOCK_MONOTONIC 1
@@ -63,6 +53,7 @@ int alarmcount;
63int clock_id; 53int clock_id;
64struct timespec start_time; 54struct timespec start_time;
65long long max_latency_ns; 55long long max_latency_ns;
56int timer_fired_early;
66 57
67char *clockstring(int clockid) 58char *clockstring(int clockid)
68{ 59{
@@ -115,16 +106,23 @@ void sigalarm(int signo)
115 delta_ns -= NSEC_PER_SEC * TIMER_SECS * alarmcount; 106 delta_ns -= NSEC_PER_SEC * TIMER_SECS * alarmcount;
116 107
117 if (delta_ns < 0) 108 if (delta_ns < 0)
118 printf("%s timer fired early: FAIL\n", clockstring(clock_id)); 109 timer_fired_early = 1;
119 110
120 if (delta_ns > max_latency_ns) 111 if (delta_ns > max_latency_ns)
121 max_latency_ns = delta_ns; 112 max_latency_ns = delta_ns;
122} 113}
123 114
124int do_timer(int clock_id, int flags) 115void describe_timer(int flags, int interval)
116{
117 printf("%-22s %s %s ",
118 clockstring(clock_id),
119 flags ? "ABSTIME":"RELTIME",
120 interval ? "PERIODIC":"ONE-SHOT");
121}
122
123int setup_timer(int clock_id, int flags, int interval, timer_t *tm1)
125{ 124{
126 struct sigevent se; 125 struct sigevent se;
127 timer_t tm1;
128 struct itimerspec its1, its2; 126 struct itimerspec its1, its2;
129 int err; 127 int err;
130 128
@@ -136,15 +134,17 @@ int do_timer(int clock_id, int flags)
136 134
137 max_latency_ns = 0; 135 max_latency_ns = 0;
138 alarmcount = 0; 136 alarmcount = 0;
137 timer_fired_early = 0;
139 138
140 err = timer_create(clock_id, &se, &tm1); 139 err = timer_create(clock_id, &se, tm1);
141 if (err) { 140 if (err) {
142 if ((clock_id == CLOCK_REALTIME_ALARM) || 141 if ((clock_id == CLOCK_REALTIME_ALARM) ||
143 (clock_id == CLOCK_BOOTTIME_ALARM)) { 142 (clock_id == CLOCK_BOOTTIME_ALARM)) {
144 printf("%-22s %s missing CAP_WAKE_ALARM? : [UNSUPPORTED]\n", 143 printf("%-22s %s missing CAP_WAKE_ALARM? : [UNSUPPORTED]\n",
145 clockstring(clock_id), 144 clockstring(clock_id),
146 flags ? "ABSTIME":"RELTIME"); 145 flags ? "ABSTIME":"RELTIME");
147 return 0; 146 /* Indicate timer isn't set, so caller doesn't wait */
147 return 1;
148 } 148 }
149 printf("%s - timer_create() failed\n", clockstring(clock_id)); 149 printf("%s - timer_create() failed\n", clockstring(clock_id));
150 return -1; 150 return -1;
@@ -158,32 +158,97 @@ int do_timer(int clock_id, int flags)
158 its1.it_value.tv_sec = TIMER_SECS; 158 its1.it_value.tv_sec = TIMER_SECS;
159 its1.it_value.tv_nsec = 0; 159 its1.it_value.tv_nsec = 0;
160 } 160 }
161 its1.it_interval.tv_sec = TIMER_SECS; 161 its1.it_interval.tv_sec = interval;
162 its1.it_interval.tv_nsec = 0; 162 its1.it_interval.tv_nsec = 0;
163 163
164 err = timer_settime(tm1, flags, &its1, &its2); 164 err = timer_settime(*tm1, flags, &its1, &its2);
165 if (err) { 165 if (err) {
166 printf("%s - timer_settime() failed\n", clockstring(clock_id)); 166 printf("%s - timer_settime() failed\n", clockstring(clock_id));
167 return -1; 167 return -1;
168 } 168 }
169 169
170 while (alarmcount < 5) 170 return 0;
171 sleep(1); 171}
172 172
173 printf("%-22s %s max latency: %10lld ns : ", 173int check_timer_latency(int flags, int interval)
174 clockstring(clock_id), 174{
175 flags ? "ABSTIME":"RELTIME", 175 int err = 0;
176 max_latency_ns); 176
177 describe_timer(flags, interval);
178 printf("timer fired early: %7d : ", timer_fired_early);
179 if (!timer_fired_early) {
180 printf("[OK]\n");
181 } else {
182 printf("[FAILED]\n");
183 err = -1;
184 }
185
186 describe_timer(flags, interval);
187 printf("max latency: %10lld ns : ", max_latency_ns);
177 188
178 timer_delete(tm1);
179 if (max_latency_ns < UNRESONABLE_LATENCY) { 189 if (max_latency_ns < UNRESONABLE_LATENCY) {
180 printf("[OK]\n"); 190 printf("[OK]\n");
191 } else {
192 printf("[FAILED]\n");
193 err = -1;
194 }
195 return err;
196}
197
198int check_alarmcount(int flags, int interval)
199{
200 describe_timer(flags, interval);
201 printf("count: %19d : ", alarmcount);
202 if (alarmcount == 1) {
203 printf("[OK]\n");
181 return 0; 204 return 0;
182 } 205 }
183 printf("[FAILED]\n"); 206 printf("[FAILED]\n");
184 return -1; 207 return -1;
185} 208}
186 209
210int do_timer(int clock_id, int flags)
211{
212 timer_t tm1;
213 const int interval = TIMER_SECS;
214 int err;
215
216 err = setup_timer(clock_id, flags, interval, &tm1);
217 /* Unsupported case - return 0 to not fail the test */
218 if (err)
219 return err == 1 ? 0 : err;
220
221 while (alarmcount < 5)
222 sleep(1);
223
224 timer_delete(tm1);
225 return check_timer_latency(flags, interval);
226}
227
228int do_timer_oneshot(int clock_id, int flags)
229{
230 timer_t tm1;
231 const int interval = 0;
232 struct timeval timeout;
233 int err;
234
235 err = setup_timer(clock_id, flags, interval, &tm1);
236 /* Unsupported case - return 0 to not fail the test */
237 if (err)
238 return err == 1 ? 0 : err;
239
240 memset(&timeout, 0, sizeof(timeout));
241 timeout.tv_sec = 5;
242 do {
243 err = select(0, NULL, NULL, NULL, &timeout);
244 } while (err == -1 && errno == EINTR);
245
246 timer_delete(tm1);
247 err = check_timer_latency(flags, interval);
248 err |= check_alarmcount(flags, interval);
249 return err;
250}
251
187int main(void) 252int main(void)
188{ 253{
189 struct sigaction act; 254 struct sigaction act;
@@ -209,6 +274,8 @@ int main(void)
209 274
210 ret |= do_timer(clock_id, TIMER_ABSTIME); 275 ret |= do_timer(clock_id, TIMER_ABSTIME);
211 ret |= do_timer(clock_id, 0); 276 ret |= do_timer(clock_id, 0);
277 ret |= do_timer_oneshot(clock_id, TIMER_ABSTIME);
278 ret |= do_timer_oneshot(clock_id, 0);
212 } 279 }
213 if (ret) 280 if (ret)
214 return ksft_exit_fail(); 281 return ksft_exit_fail();
diff --git a/tools/testing/selftests/timers/set-tz.c b/tools/testing/selftests/timers/set-tz.c
index f4184928b16b..877fd5532fee 100644
--- a/tools/testing/selftests/timers/set-tz.c
+++ b/tools/testing/selftests/timers/set-tz.c
@@ -23,18 +23,7 @@
23#include <string.h> 23#include <string.h>
24#include <signal.h> 24#include <signal.h>
25#include <unistd.h> 25#include <unistd.h>
26#ifdef KTEST
27#include "../kselftest.h" 26#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 27
39int set_tz(int min, int dst) 28int set_tz(int min, int dst)
40{ 29{
diff --git a/tools/testing/selftests/timers/skew_consistency.c b/tools/testing/selftests/timers/skew_consistency.c
index 2a996e072259..022b711c78ee 100644
--- a/tools/testing/selftests/timers/skew_consistency.c
+++ b/tools/testing/selftests/timers/skew_consistency.c
@@ -35,18 +35,7 @@
35#include <stdlib.h> 35#include <stdlib.h>
36#include <string.h> 36#include <string.h>
37#include <sys/wait.h> 37#include <sys/wait.h>
38#ifdef KTEST
39#include "../kselftest.h" 38#include "../kselftest.h"
40#else
41static inline int ksft_exit_pass(void)
42{
43 exit(0);
44}
45static inline int ksft_exit_fail(void)
46{
47 exit(1);
48}
49#endif
50 39
51#define NSEC_PER_SEC 1000000000LL 40#define NSEC_PER_SEC 1000000000LL
52 41
diff --git a/tools/testing/selftests/timers/threadtest.c b/tools/testing/selftests/timers/threadtest.c
index e632e116f05e..759c9c06f1a0 100644
--- a/tools/testing/selftests/timers/threadtest.c
+++ b/tools/testing/selftests/timers/threadtest.c
@@ -21,19 +21,7 @@
21#include <stdlib.h> 21#include <stdlib.h>
22#include <sys/time.h> 22#include <sys/time.h>
23#include <pthread.h> 23#include <pthread.h>
24#ifdef KTEST
25#include "../kselftest.h" 24#include "../kselftest.h"
26#else
27static inline int ksft_exit_pass(void)
28{
29 exit(0);
30}
31static inline int ksft_exit_fail(void)
32{
33 exit(1);
34}
35#endif
36
37 25
38/* serializes shared list access */ 26/* serializes shared list access */
39pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER; 27pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;
diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c
index 60fe3c569bd9..d9d3ab93b31a 100644
--- a/tools/testing/selftests/timers/valid-adjtimex.c
+++ b/tools/testing/selftests/timers/valid-adjtimex.c
@@ -32,18 +32,7 @@
32#include <string.h> 32#include <string.h>
33#include <signal.h> 33#include <signal.h>
34#include <unistd.h> 34#include <unistd.h>
35#ifdef KTEST
36#include "../kselftest.h" 35#include "../kselftest.h"
37#else
38static inline int ksft_exit_pass(void)
39{
40 exit(0);
41}
42static inline int ksft_exit_fail(void)
43{
44 exit(1);
45}
46#endif
47 36
48#define NSEC_PER_SEC 1000000000LL 37#define NSEC_PER_SEC 1000000000LL
49#define USEC_PER_SEC 1000000LL 38#define USEC_PER_SEC 1000000LL
diff --git a/tools/testing/selftests/user/test_user_copy.sh b/tools/testing/selftests/user/test_user_copy.sh
index 350107f40c1d..d60506fc77f8 100755
--- a/tools/testing/selftests/user/test_user_copy.sh
+++ b/tools/testing/selftests/user/test_user_copy.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# Runs copy_to/from_user infrastructure using test_user_copy kernel module 3# Runs copy_to/from_user infrastructure using test_user_copy kernel module
3 4
4if /sbin/modprobe -q test_user_copy; then 5if /sbin/modprobe -q test_user_copy; then
diff --git a/tools/testing/selftests/vDSO/Makefile b/tools/testing/selftests/vDSO/Makefile
index 706b68b1c372..3d5a62ff7d31 100644
--- a/tools/testing/selftests/vDSO/Makefile
+++ b/tools/testing/selftests/vDSO/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1ifndef CROSS_COMPILE 2ifndef CROSS_COMPILE
2CFLAGS := -std=gnu99 3CFLAGS := -std=gnu99
3CFLAGS_vdso_standalone_test_x86 := -nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector 4CFLAGS_vdso_standalone_test_x86 := -nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector
diff --git a/tools/testing/selftests/vDSO/vdso_test.c b/tools/testing/selftests/vDSO/vdso_test.c
index 8daeb7d7032c..2df26bd0099c 100644
--- a/tools/testing/selftests/vDSO/vdso_test.c
+++ b/tools/testing/selftests/vDSO/vdso_test.c
@@ -19,6 +19,19 @@ extern void *vdso_sym(const char *version, const char *name);
19extern void vdso_init_from_sysinfo_ehdr(uintptr_t base); 19extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
20extern void vdso_init_from_auxv(void *auxv); 20extern void vdso_init_from_auxv(void *auxv);
21 21
22/*
23 * ARM64's vDSO exports its gettimeofday() implementation with a different
24 * name and version from other architectures, so we need to handle it as
25 * a special case.
26 */
27#if defined(__aarch64__)
28const char *version = "LINUX_2.6.39";
29const char *name = "__kernel_gettimeofday";
30#else
31const char *version = "LINUX_2.6";
32const char *name = "__vdso_gettimeofday";
33#endif
34
22int main(int argc, char **argv) 35int main(int argc, char **argv)
23{ 36{
24 unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR); 37 unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
@@ -31,10 +44,10 @@ int main(int argc, char **argv)
31 44
32 /* Find gettimeofday. */ 45 /* Find gettimeofday. */
33 typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz); 46 typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
34 gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday"); 47 gtod_t gtod = (gtod_t)vdso_sym(version, name);
35 48
36 if (!gtod) { 49 if (!gtod) {
37 printf("Could not find __vdso_gettimeofday\n"); 50 printf("Could not find %s\n", name);
38 return 1; 51 return 1;
39 } 52 }
40 53
@@ -45,7 +58,7 @@ int main(int argc, char **argv)
45 printf("The time is %lld.%06lld\n", 58 printf("The time is %lld.%06lld\n",
46 (long long)tv.tv_sec, (long long)tv.tv_usec); 59 (long long)tv.tv_sec, (long long)tv.tv_usec);
47 } else { 60 } else {
48 printf("__vdso_gettimeofday failed\n"); 61 printf("%s failed\n", name);
49 } 62 }
50 63
51 return 0; 64 return 0;
diff --git a/tools/testing/selftests/vm/.gitignore b/tools/testing/selftests/vm/.gitignore
index 142c565bb351..1ca2ee4d15b9 100644
--- a/tools/testing/selftests/vm/.gitignore
+++ b/tools/testing/selftests/vm/.gitignore
@@ -8,3 +8,5 @@ on-fault-limit
8transhuge-stress 8transhuge-stress
9userfaultfd 9userfaultfd
10mlock-intersect-test 10mlock-intersect-test
11mlock-random-test
12virtual_address_range
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index cbb29e41ef2b..7f45806bd863 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# Makefile for vm selftests 2# Makefile for vm selftests
2 3
3ifndef OUTPUT 4ifndef OUTPUT
@@ -17,6 +18,7 @@ TEST_GEN_FILES += transhuge-stress
17TEST_GEN_FILES += userfaultfd 18TEST_GEN_FILES += userfaultfd
18TEST_GEN_FILES += mlock-random-test 19TEST_GEN_FILES += mlock-random-test
19TEST_GEN_FILES += virtual_address_range 20TEST_GEN_FILES += virtual_address_range
21TEST_GEN_FILES += gup_benchmark
20 22
21TEST_PROGS := run_vmtests 23TEST_PROGS := run_vmtests
22 24
diff --git a/tools/testing/selftests/vm/compaction_test.c b/tools/testing/selftests/vm/compaction_test.c
index 6d1437f895b8..a65b016d4c13 100644
--- a/tools/testing/selftests/vm/compaction_test.c
+++ b/tools/testing/selftests/vm/compaction_test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * 3 *
3 * A test for the patch "Allow compaction of unevictable pages". 4 * A test for the patch "Allow compaction of unevictable pages".
diff --git a/tools/testing/selftests/vm/gup_benchmark.c b/tools/testing/selftests/vm/gup_benchmark.c
new file mode 100644
index 000000000000..36df55132036
--- /dev/null
+++ b/tools/testing/selftests/vm/gup_benchmark.c
@@ -0,0 +1,91 @@
1#include <fcntl.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <unistd.h>
5
6#include <sys/ioctl.h>
7#include <sys/mman.h>
8#include <sys/prctl.h>
9#include <sys/stat.h>
10#include <sys/types.h>
11
12#include <linux/types.h>
13
14#define MB (1UL << 20)
15#define PAGE_SIZE sysconf(_SC_PAGESIZE)
16
17#define GUP_FAST_BENCHMARK _IOWR('g', 1, struct gup_benchmark)
18
19struct gup_benchmark {
20 __u64 delta_usec;
21 __u64 addr;
22 __u64 size;
23 __u32 nr_pages_per_call;
24 __u32 flags;
25};
26
27int main(int argc, char **argv)
28{
29 struct gup_benchmark gup;
30 unsigned long size = 128 * MB;
31 int i, fd, opt, nr_pages = 1, thp = -1, repeats = 1, write = 0;
32 char *p;
33
34 while ((opt = getopt(argc, argv, "m:r:n:tT")) != -1) {
35 switch (opt) {
36 case 'm':
37 size = atoi(optarg) * MB;
38 break;
39 case 'r':
40 repeats = atoi(optarg);
41 break;
42 case 'n':
43 nr_pages = atoi(optarg);
44 break;
45 case 't':
46 thp = 1;
47 break;
48 case 'T':
49 thp = 0;
50 break;
51 case 'w':
52 write = 1;
53 default:
54 return -1;
55 }
56 }
57
58 gup.nr_pages_per_call = nr_pages;
59 gup.flags = write;
60
61 fd = open("/sys/kernel/debug/gup_benchmark", O_RDWR);
62 if (fd == -1)
63 perror("open"), exit(1);
64
65 p = mmap(NULL, size, PROT_READ | PROT_WRITE,
66 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
67 if (p == MAP_FAILED)
68 perror("mmap"), exit(1);
69 gup.addr = (unsigned long)p;
70
71 if (thp == 1)
72 madvise(p, size, MADV_HUGEPAGE);
73 else if (thp == 0)
74 madvise(p, size, MADV_NOHUGEPAGE);
75
76 for (; (unsigned long)p < gup.addr + size; p += PAGE_SIZE)
77 p[0] = 0;
78
79 for (i = 0; i < repeats; i++) {
80 gup.size = size;
81 if (ioctl(fd, GUP_FAST_BENCHMARK, &gup))
82 perror("ioctl"), exit(1);
83
84 printf("Time: %lld us", gup.delta_usec);
85 if (gup.size != size)
86 printf(", truncated (size: %lld)", gup.size);
87 printf("\n");
88 }
89
90 return 0;
91}
diff --git a/tools/testing/selftests/vm/hugepage-mmap.c b/tools/testing/selftests/vm/hugepage-mmap.c
index a10f310d2362..93f9e7b81331 100644
--- a/tools/testing/selftests/vm/hugepage-mmap.c
+++ b/tools/testing/selftests/vm/hugepage-mmap.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * hugepage-mmap: 3 * hugepage-mmap:
3 * 4 *
diff --git a/tools/testing/selftests/vm/hugepage-shm.c b/tools/testing/selftests/vm/hugepage-shm.c
index 0d0ef4fc0c04..e2527f32005b 100644
--- a/tools/testing/selftests/vm/hugepage-shm.c
+++ b/tools/testing/selftests/vm/hugepage-shm.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * hugepage-shm: 3 * hugepage-shm:
3 * 4 *
diff --git a/tools/testing/selftests/vm/map_hugetlb.c b/tools/testing/selftests/vm/map_hugetlb.c
index 77687ab59f77..9b777fa95f09 100644
--- a/tools/testing/selftests/vm/map_hugetlb.c
+++ b/tools/testing/selftests/vm/map_hugetlb.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Example of using hugepage memory in a user application using the mmap 3 * Example of using hugepage memory in a user application using the mmap
3 * system call with MAP_HUGETLB flag. Before running this program make 4 * system call with MAP_HUGETLB flag. Before running this program make
diff --git a/tools/testing/selftests/vm/mlock-random-test.c b/tools/testing/selftests/vm/mlock-random-test.c
index 83de4f58d262..ff4d72eb74b9 100644
--- a/tools/testing/selftests/vm/mlock-random-test.c
+++ b/tools/testing/selftests/vm/mlock-random-test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * It tests the mlock/mlock2() when they are invoked 3 * It tests the mlock/mlock2() when they are invoked
3 * on randomly memory region. 4 * on randomly memory region.
diff --git a/tools/testing/selftests/vm/mlock2-tests.c b/tools/testing/selftests/vm/mlock2-tests.c
index e5dbc87b4297..4997b9222cfa 100644
--- a/tools/testing/selftests/vm/mlock2-tests.c
+++ b/tools/testing/selftests/vm/mlock2-tests.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2#include <sys/mman.h> 3#include <sys/mman.h>
3#include <stdint.h> 4#include <stdint.h>
diff --git a/tools/testing/selftests/vm/mlock2.h b/tools/testing/selftests/vm/mlock2.h
index 7ee062929d3e..2a6e76c226bc 100644
--- a/tools/testing/selftests/vm/mlock2.h
+++ b/tools/testing/selftests/vm/mlock2.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include <syscall.h> 2#include <syscall.h>
2#include <errno.h> 3#include <errno.h>
3#include <stdio.h> 4#include <stdio.h>
diff --git a/tools/testing/selftests/vm/on-fault-limit.c b/tools/testing/selftests/vm/on-fault-limit.c
index 7f96a5c2e292..634d87dfb2a4 100644
--- a/tools/testing/selftests/vm/on-fault-limit.c
+++ b/tools/testing/selftests/vm/on-fault-limit.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/mman.h> 2#include <sys/mman.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <unistd.h> 4#include <unistd.h>
diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
index 07548a1fa901..cc826326de87 100755
--- a/tools/testing/selftests/vm/run_vmtests
+++ b/tools/testing/selftests/vm/run_vmtests
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2#please run as root 3#please run as root
3 4
4#we need 256M, below is the size in kB 5#we need 256M, below is the size in kB
diff --git a/tools/testing/selftests/vm/thuge-gen.c b/tools/testing/selftests/vm/thuge-gen.c
index 88a2ab535e01..361ef7192cc6 100644
--- a/tools/testing/selftests/vm/thuge-gen.c
+++ b/tools/testing/selftests/vm/thuge-gen.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* Test selecting other page sizes for mmap/shmget. 2/* Test selecting other page sizes for mmap/shmget.
2 3
3 Before running this huge pages for each huge page size must have been 4 Before running this huge pages for each huge page size must have been
diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c
index 1eae79ae5b4e..de2f9ec8a87f 100644
--- a/tools/testing/selftests/vm/userfaultfd.c
+++ b/tools/testing/selftests/vm/userfaultfd.c
@@ -66,6 +66,8 @@
66#include <sys/wait.h> 66#include <sys/wait.h>
67#include <pthread.h> 67#include <pthread.h>
68#include <linux/userfaultfd.h> 68#include <linux/userfaultfd.h>
69#include <setjmp.h>
70#include <stdbool.h>
69 71
70#ifdef __NR_userfaultfd 72#ifdef __NR_userfaultfd
71 73
@@ -82,11 +84,17 @@ static int bounces;
82#define TEST_SHMEM 3 84#define TEST_SHMEM 3
83static int test_type; 85static int test_type;
84 86
87/* exercise the test_uffdio_*_eexist every ALARM_INTERVAL_SECS */
88#define ALARM_INTERVAL_SECS 10
89static volatile bool test_uffdio_copy_eexist = true;
90static volatile bool test_uffdio_zeropage_eexist = true;
91
92static bool map_shared;
85static int huge_fd; 93static int huge_fd;
86static char *huge_fd_off0; 94static char *huge_fd_off0;
87static unsigned long long *count_verify; 95static unsigned long long *count_verify;
88static int uffd, uffd_flags, finished, *pipefd; 96static int uffd, uffd_flags, finished, *pipefd;
89static char *area_src, *area_dst; 97static char *area_src, *area_src_alias, *area_dst, *area_dst_alias;
90static char *zeropage; 98static char *zeropage;
91pthread_attr_t attr; 99pthread_attr_t attr;
92 100
@@ -125,6 +133,9 @@ static void anon_allocate_area(void **alloc_area)
125 } 133 }
126} 134}
127 135
136static void noop_alias_mapping(__u64 *start, size_t len, unsigned long offset)
137{
138}
128 139
129/* HugeTLB memory */ 140/* HugeTLB memory */
130static int hugetlb_release_pages(char *rel_area) 141static int hugetlb_release_pages(char *rel_area)
@@ -145,17 +156,51 @@ static int hugetlb_release_pages(char *rel_area)
145 156
146static void hugetlb_allocate_area(void **alloc_area) 157static void hugetlb_allocate_area(void **alloc_area)
147{ 158{
159 void *area_alias = NULL;
160 char **alloc_area_alias;
148 *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE, 161 *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
149 MAP_PRIVATE | MAP_HUGETLB, huge_fd, 162 (map_shared ? MAP_SHARED : MAP_PRIVATE) |
150 *alloc_area == area_src ? 0 : 163 MAP_HUGETLB,
151 nr_pages * page_size); 164 huge_fd, *alloc_area == area_src ? 0 :
165 nr_pages * page_size);
152 if (*alloc_area == MAP_FAILED) { 166 if (*alloc_area == MAP_FAILED) {
153 fprintf(stderr, "mmap of hugetlbfs file failed\n"); 167 fprintf(stderr, "mmap of hugetlbfs file failed\n");
154 *alloc_area = NULL; 168 *alloc_area = NULL;
155 } 169 }
156 170
157 if (*alloc_area == area_src) 171 if (map_shared) {
172 area_alias = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
173 MAP_SHARED | MAP_HUGETLB,
174 huge_fd, *alloc_area == area_src ? 0 :
175 nr_pages * page_size);
176 if (area_alias == MAP_FAILED) {
177 if (munmap(*alloc_area, nr_pages * page_size) < 0)
178 perror("hugetlb munmap"), exit(1);
179 *alloc_area = NULL;
180 return;
181 }
182 }
183 if (*alloc_area == area_src) {
158 huge_fd_off0 = *alloc_area; 184 huge_fd_off0 = *alloc_area;
185 alloc_area_alias = &area_src_alias;
186 } else {
187 alloc_area_alias = &area_dst_alias;
188 }
189 if (area_alias)
190 *alloc_area_alias = area_alias;
191}
192
193static void hugetlb_alias_mapping(__u64 *start, size_t len, unsigned long offset)
194{
195 if (!map_shared)
196 return;
197 /*
198 * We can't zap just the pagetable with hugetlbfs because
199 * MADV_DONTEED won't work. So exercise -EEXIST on a alias
200 * mapping where the pagetables are not established initially,
201 * this way we'll exercise the -EEXEC at the fs level.
202 */
203 *start = (unsigned long) area_dst_alias + offset;
159} 204}
160 205
161/* Shared memory */ 206/* Shared memory */
@@ -185,6 +230,7 @@ struct uffd_test_ops {
185 unsigned long expected_ioctls; 230 unsigned long expected_ioctls;
186 void (*allocate_area)(void **alloc_area); 231 void (*allocate_area)(void **alloc_area);
187 int (*release_pages)(char *rel_area); 232 int (*release_pages)(char *rel_area);
233 void (*alias_mapping)(__u64 *start, size_t len, unsigned long offset);
188}; 234};
189 235
190#define ANON_EXPECTED_IOCTLS ((1 << _UFFDIO_WAKE) | \ 236#define ANON_EXPECTED_IOCTLS ((1 << _UFFDIO_WAKE) | \
@@ -195,18 +241,21 @@ static struct uffd_test_ops anon_uffd_test_ops = {
195 .expected_ioctls = ANON_EXPECTED_IOCTLS, 241 .expected_ioctls = ANON_EXPECTED_IOCTLS,
196 .allocate_area = anon_allocate_area, 242 .allocate_area = anon_allocate_area,
197 .release_pages = anon_release_pages, 243 .release_pages = anon_release_pages,
244 .alias_mapping = noop_alias_mapping,
198}; 245};
199 246
200static struct uffd_test_ops shmem_uffd_test_ops = { 247static struct uffd_test_ops shmem_uffd_test_ops = {
201 .expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC, 248 .expected_ioctls = ANON_EXPECTED_IOCTLS,
202 .allocate_area = shmem_allocate_area, 249 .allocate_area = shmem_allocate_area,
203 .release_pages = shmem_release_pages, 250 .release_pages = shmem_release_pages,
251 .alias_mapping = noop_alias_mapping,
204}; 252};
205 253
206static struct uffd_test_ops hugetlb_uffd_test_ops = { 254static struct uffd_test_ops hugetlb_uffd_test_ops = {
207 .expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC, 255 .expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC,
208 .allocate_area = hugetlb_allocate_area, 256 .allocate_area = hugetlb_allocate_area,
209 .release_pages = hugetlb_release_pages, 257 .release_pages = hugetlb_release_pages,
258 .alias_mapping = hugetlb_alias_mapping,
210}; 259};
211 260
212static struct uffd_test_ops *uffd_test_ops; 261static struct uffd_test_ops *uffd_test_ops;
@@ -331,7 +380,24 @@ static void *locking_thread(void *arg)
331 return NULL; 380 return NULL;
332} 381}
333 382
334static int copy_page(int ufd, unsigned long offset) 383static void retry_copy_page(int ufd, struct uffdio_copy *uffdio_copy,
384 unsigned long offset)
385{
386 uffd_test_ops->alias_mapping(&uffdio_copy->dst,
387 uffdio_copy->len,
388 offset);
389 if (ioctl(ufd, UFFDIO_COPY, uffdio_copy)) {
390 /* real retval in ufdio_copy.copy */
391 if (uffdio_copy->copy != -EEXIST)
392 fprintf(stderr, "UFFDIO_COPY retry error %Ld\n",
393 uffdio_copy->copy), exit(1);
394 } else {
395 fprintf(stderr, "UFFDIO_COPY retry unexpected %Ld\n",
396 uffdio_copy->copy), exit(1);
397 }
398}
399
400static int __copy_page(int ufd, unsigned long offset, bool retry)
335{ 401{
336 struct uffdio_copy uffdio_copy; 402 struct uffdio_copy uffdio_copy;
337 403
@@ -351,11 +417,26 @@ static int copy_page(int ufd, unsigned long offset)
351 } else if (uffdio_copy.copy != page_size) { 417 } else if (uffdio_copy.copy != page_size) {
352 fprintf(stderr, "UFFDIO_COPY unexpected copy %Ld\n", 418 fprintf(stderr, "UFFDIO_COPY unexpected copy %Ld\n",
353 uffdio_copy.copy), exit(1); 419 uffdio_copy.copy), exit(1);
354 } else 420 } else {
421 if (test_uffdio_copy_eexist && retry) {
422 test_uffdio_copy_eexist = false;
423 retry_copy_page(ufd, &uffdio_copy, offset);
424 }
355 return 1; 425 return 1;
426 }
356 return 0; 427 return 0;
357} 428}
358 429
430static int copy_page_retry(int ufd, unsigned long offset)
431{
432 return __copy_page(ufd, offset, true);
433}
434
435static int copy_page(int ufd, unsigned long offset)
436{
437 return __copy_page(ufd, offset, false);
438}
439
359static void *uffd_poll_thread(void *arg) 440static void *uffd_poll_thread(void *arg)
360{ 441{
361 unsigned long cpu = (unsigned long) arg; 442 unsigned long cpu = (unsigned long) arg;
@@ -408,6 +489,7 @@ static void *uffd_poll_thread(void *arg)
408 userfaults++; 489 userfaults++;
409 break; 490 break;
410 case UFFD_EVENT_FORK: 491 case UFFD_EVENT_FORK:
492 close(uffd);
411 uffd = msg.arg.fork.ufd; 493 uffd = msg.arg.fork.ufd;
412 pollfd[0].fd = uffd; 494 pollfd[0].fd = uffd;
413 break; 495 break;
@@ -472,7 +554,7 @@ static void *background_thread(void *arg)
472 for (page_nr = cpu * nr_pages_per_cpu; 554 for (page_nr = cpu * nr_pages_per_cpu;
473 page_nr < (cpu+1) * nr_pages_per_cpu; 555 page_nr < (cpu+1) * nr_pages_per_cpu;
474 page_nr++) 556 page_nr++)
475 copy_page(uffd, page_nr * page_size); 557 copy_page_retry(uffd, page_nr * page_size);
476 558
477 return NULL; 559 return NULL;
478} 560}
@@ -572,6 +654,17 @@ static int userfaultfd_open(int features)
572 return 0; 654 return 0;
573} 655}
574 656
657sigjmp_buf jbuf, *sigbuf;
658
659static void sighndl(int sig, siginfo_t *siginfo, void *ptr)
660{
661 if (sig == SIGBUS) {
662 if (sigbuf)
663 siglongjmp(*sigbuf, 1);
664 abort();
665 }
666}
667
575/* 668/*
576 * For non-cooperative userfaultfd test we fork() a process that will 669 * For non-cooperative userfaultfd test we fork() a process that will
577 * generate pagefaults, will mremap the area monitored by the 670 * generate pagefaults, will mremap the area monitored by the
@@ -585,19 +678,59 @@ static int userfaultfd_open(int features)
585 * The release of the pages currently generates event for shmem and 678 * The release of the pages currently generates event for shmem and
586 * anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked 679 * anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked
587 * for hugetlb. 680 * for hugetlb.
681 * For signal test(UFFD_FEATURE_SIGBUS), signal_test = 1, we register
682 * monitored area, generate pagefaults and test that signal is delivered.
683 * Use UFFDIO_COPY to allocate missing page and retry. For signal_test = 2
684 * test robustness use case - we release monitored area, fork a process
685 * that will generate pagefaults and verify signal is generated.
686 * This also tests UFFD_FEATURE_EVENT_FORK event along with the signal
687 * feature. Using monitor thread, verify no userfault events are generated.
588 */ 688 */
589static int faulting_process(void) 689static int faulting_process(int signal_test)
590{ 690{
591 unsigned long nr; 691 unsigned long nr;
592 unsigned long long count; 692 unsigned long long count;
593 unsigned long split_nr_pages; 693 unsigned long split_nr_pages;
694 unsigned long lastnr;
695 struct sigaction act;
696 unsigned long signalled = 0;
594 697
595 if (test_type != TEST_HUGETLB) 698 if (test_type != TEST_HUGETLB)
596 split_nr_pages = (nr_pages + 1) / 2; 699 split_nr_pages = (nr_pages + 1) / 2;
597 else 700 else
598 split_nr_pages = nr_pages; 701 split_nr_pages = nr_pages;
599 702
703 if (signal_test) {
704 sigbuf = &jbuf;
705 memset(&act, 0, sizeof(act));
706 act.sa_sigaction = sighndl;
707 act.sa_flags = SA_SIGINFO;
708 if (sigaction(SIGBUS, &act, 0)) {
709 perror("sigaction");
710 return 1;
711 }
712 lastnr = (unsigned long)-1;
713 }
714
600 for (nr = 0; nr < split_nr_pages; nr++) { 715 for (nr = 0; nr < split_nr_pages; nr++) {
716 if (signal_test) {
717 if (sigsetjmp(*sigbuf, 1) != 0) {
718 if (nr == lastnr) {
719 fprintf(stderr, "Signal repeated\n");
720 return 1;
721 }
722
723 lastnr = nr;
724 if (signal_test == 1) {
725 if (copy_page(uffd, nr * page_size))
726 signalled++;
727 } else {
728 signalled++;
729 continue;
730 }
731 }
732 }
733
601 count = *area_count(area_dst, nr); 734 count = *area_count(area_dst, nr);
602 if (count != count_verify[nr]) { 735 if (count != count_verify[nr]) {
603 fprintf(stderr, 736 fprintf(stderr,
@@ -607,6 +740,9 @@ static int faulting_process(void)
607 } 740 }
608 } 741 }
609 742
743 if (signal_test)
744 return signalled != split_nr_pages;
745
610 if (test_type == TEST_HUGETLB) 746 if (test_type == TEST_HUGETLB)
611 return 0; 747 return 0;
612 748
@@ -636,7 +772,24 @@ static int faulting_process(void)
636 return 0; 772 return 0;
637} 773}
638 774
639static int uffdio_zeropage(int ufd, unsigned long offset) 775static void retry_uffdio_zeropage(int ufd,
776 struct uffdio_zeropage *uffdio_zeropage,
777 unsigned long offset)
778{
779 uffd_test_ops->alias_mapping(&uffdio_zeropage->range.start,
780 uffdio_zeropage->range.len,
781 offset);
782 if (ioctl(ufd, UFFDIO_ZEROPAGE, uffdio_zeropage)) {
783 if (uffdio_zeropage->zeropage != -EEXIST)
784 fprintf(stderr, "UFFDIO_ZEROPAGE retry error %Ld\n",
785 uffdio_zeropage->zeropage), exit(1);
786 } else {
787 fprintf(stderr, "UFFDIO_ZEROPAGE retry unexpected %Ld\n",
788 uffdio_zeropage->zeropage), exit(1);
789 }
790}
791
792static int __uffdio_zeropage(int ufd, unsigned long offset, bool retry)
640{ 793{
641 struct uffdio_zeropage uffdio_zeropage; 794 struct uffdio_zeropage uffdio_zeropage;
642 int ret; 795 int ret;
@@ -670,8 +823,14 @@ static int uffdio_zeropage(int ufd, unsigned long offset)
670 if (uffdio_zeropage.zeropage != page_size) { 823 if (uffdio_zeropage.zeropage != page_size) {
671 fprintf(stderr, "UFFDIO_ZEROPAGE unexpected %Ld\n", 824 fprintf(stderr, "UFFDIO_ZEROPAGE unexpected %Ld\n",
672 uffdio_zeropage.zeropage), exit(1); 825 uffdio_zeropage.zeropage), exit(1);
673 } else 826 } else {
827 if (test_uffdio_zeropage_eexist && retry) {
828 test_uffdio_zeropage_eexist = false;
829 retry_uffdio_zeropage(ufd, &uffdio_zeropage,
830 offset);
831 }
674 return 1; 832 return 1;
833 }
675 } else { 834 } else {
676 fprintf(stderr, 835 fprintf(stderr,
677 "UFFDIO_ZEROPAGE succeeded %Ld\n", 836 "UFFDIO_ZEROPAGE succeeded %Ld\n",
@@ -681,6 +840,11 @@ static int uffdio_zeropage(int ufd, unsigned long offset)
681 return 0; 840 return 0;
682} 841}
683 842
843static int uffdio_zeropage(int ufd, unsigned long offset)
844{
845 return __uffdio_zeropage(ufd, offset, false);
846}
847
684/* exercise UFFDIO_ZEROPAGE */ 848/* exercise UFFDIO_ZEROPAGE */
685static int userfaultfd_zeropage_test(void) 849static int userfaultfd_zeropage_test(void)
686{ 850{
@@ -761,7 +925,7 @@ static int userfaultfd_events_test(void)
761 perror("fork"), exit(1); 925 perror("fork"), exit(1);
762 926
763 if (!pid) 927 if (!pid)
764 return faulting_process(); 928 return faulting_process(0);
765 929
766 waitpid(pid, &err, 0); 930 waitpid(pid, &err, 0);
767 if (err) 931 if (err)
@@ -778,6 +942,72 @@ static int userfaultfd_events_test(void)
778 return userfaults != nr_pages; 942 return userfaults != nr_pages;
779} 943}
780 944
945static int userfaultfd_sig_test(void)
946{
947 struct uffdio_register uffdio_register;
948 unsigned long expected_ioctls;
949 unsigned long userfaults;
950 pthread_t uffd_mon;
951 int err, features;
952 pid_t pid;
953 char c;
954
955 printf("testing signal delivery: ");
956 fflush(stdout);
957
958 if (uffd_test_ops->release_pages(area_dst))
959 return 1;
960
961 features = UFFD_FEATURE_EVENT_FORK|UFFD_FEATURE_SIGBUS;
962 if (userfaultfd_open(features) < 0)
963 return 1;
964 fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
965
966 uffdio_register.range.start = (unsigned long) area_dst;
967 uffdio_register.range.len = nr_pages * page_size;
968 uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
969 if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
970 fprintf(stderr, "register failure\n"), exit(1);
971
972 expected_ioctls = uffd_test_ops->expected_ioctls;
973 if ((uffdio_register.ioctls & expected_ioctls) !=
974 expected_ioctls)
975 fprintf(stderr,
976 "unexpected missing ioctl for anon memory\n"),
977 exit(1);
978
979 if (faulting_process(1))
980 fprintf(stderr, "faulting process failed\n"), exit(1);
981
982 if (uffd_test_ops->release_pages(area_dst))
983 return 1;
984
985 if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, NULL))
986 perror("uffd_poll_thread create"), exit(1);
987
988 pid = fork();
989 if (pid < 0)
990 perror("fork"), exit(1);
991
992 if (!pid)
993 exit(faulting_process(2));
994
995 waitpid(pid, &err, 0);
996 if (err)
997 fprintf(stderr, "faulting process failed\n"), exit(1);
998
999 if (write(pipefd[1], &c, sizeof(c)) != sizeof(c))
1000 perror("pipe write"), exit(1);
1001 if (pthread_join(uffd_mon, (void **)&userfaults))
1002 return 1;
1003
1004 printf("done.\n");
1005 if (userfaults)
1006 fprintf(stderr, "Signal test failed, userfaults: %ld\n",
1007 userfaults);
1008 close(uffd);
1009 return userfaults != 0;
1010}
781static int userfaultfd_stress(void) 1011static int userfaultfd_stress(void)
782{ 1012{
783 void *area; 1013 void *area;
@@ -879,6 +1109,15 @@ static int userfaultfd_stress(void)
879 return 1; 1109 return 1;
880 } 1110 }
881 1111
1112 if (area_dst_alias) {
1113 uffdio_register.range.start = (unsigned long)
1114 area_dst_alias;
1115 if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) {
1116 fprintf(stderr, "register failure alias\n");
1117 return 1;
1118 }
1119 }
1120
882 /* 1121 /*
883 * The madvise done previously isn't enough: some 1122 * The madvise done previously isn't enough: some
884 * uffd_thread could have read userfaults (one of 1123 * uffd_thread could have read userfaults (one of
@@ -912,9 +1151,17 @@ static int userfaultfd_stress(void)
912 1151
913 /* unregister */ 1152 /* unregister */
914 if (ioctl(uffd, UFFDIO_UNREGISTER, &uffdio_register.range)) { 1153 if (ioctl(uffd, UFFDIO_UNREGISTER, &uffdio_register.range)) {
915 fprintf(stderr, "register failure\n"); 1154 fprintf(stderr, "unregister failure\n");
916 return 1; 1155 return 1;
917 } 1156 }
1157 if (area_dst_alias) {
1158 uffdio_register.range.start = (unsigned long) area_dst;
1159 if (ioctl(uffd, UFFDIO_UNREGISTER,
1160 &uffdio_register.range)) {
1161 fprintf(stderr, "unregister failure alias\n");
1162 return 1;
1163 }
1164 }
918 1165
919 /* verification */ 1166 /* verification */
920 if (bounces & BOUNCE_VERIFY) { 1167 if (bounces & BOUNCE_VERIFY) {
@@ -936,6 +1183,10 @@ static int userfaultfd_stress(void)
936 area_src = area_dst; 1183 area_src = area_dst;
937 area_dst = tmp_area; 1184 area_dst = tmp_area;
938 1185
1186 tmp_area = area_src_alias;
1187 area_src_alias = area_dst_alias;
1188 area_dst_alias = tmp_area;
1189
939 printf("userfaults:"); 1190 printf("userfaults:");
940 for (cpu = 0; cpu < nr_cpus; cpu++) 1191 for (cpu = 0; cpu < nr_cpus; cpu++)
941 printf(" %lu", userfaults[cpu]); 1192 printf(" %lu", userfaults[cpu]);
@@ -946,7 +1197,8 @@ static int userfaultfd_stress(void)
946 return err; 1197 return err;
947 1198
948 close(uffd); 1199 close(uffd);
949 return userfaultfd_zeropage_test() || userfaultfd_events_test(); 1200 return userfaultfd_zeropage_test() || userfaultfd_sig_test()
1201 || userfaultfd_events_test();
950} 1202}
951 1203
952/* 1204/*
@@ -981,7 +1233,12 @@ static void set_test_type(const char *type)
981 } else if (!strcmp(type, "hugetlb")) { 1233 } else if (!strcmp(type, "hugetlb")) {
982 test_type = TEST_HUGETLB; 1234 test_type = TEST_HUGETLB;
983 uffd_test_ops = &hugetlb_uffd_test_ops; 1235 uffd_test_ops = &hugetlb_uffd_test_ops;
1236 } else if (!strcmp(type, "hugetlb_shared")) {
1237 map_shared = true;
1238 test_type = TEST_HUGETLB;
1239 uffd_test_ops = &hugetlb_uffd_test_ops;
984 } else if (!strcmp(type, "shmem")) { 1240 } else if (!strcmp(type, "shmem")) {
1241 map_shared = true;
985 test_type = TEST_SHMEM; 1242 test_type = TEST_SHMEM;
986 uffd_test_ops = &shmem_uffd_test_ops; 1243 uffd_test_ops = &shmem_uffd_test_ops;
987 } else { 1244 } else {
@@ -1001,12 +1258,25 @@ static void set_test_type(const char *type)
1001 fprintf(stderr, "Impossible to run this test\n"), exit(2); 1258 fprintf(stderr, "Impossible to run this test\n"), exit(2);
1002} 1259}
1003 1260
1261static void sigalrm(int sig)
1262{
1263 if (sig != SIGALRM)
1264 abort();
1265 test_uffdio_copy_eexist = true;
1266 test_uffdio_zeropage_eexist = true;
1267 alarm(ALARM_INTERVAL_SECS);
1268}
1269
1004int main(int argc, char **argv) 1270int main(int argc, char **argv)
1005{ 1271{
1006 if (argc < 4) 1272 if (argc < 4)
1007 fprintf(stderr, "Usage: <test type> <MiB> <bounces> [hugetlbfs_file]\n"), 1273 fprintf(stderr, "Usage: <test type> <MiB> <bounces> [hugetlbfs_file]\n"),
1008 exit(1); 1274 exit(1);
1009 1275
1276 if (signal(SIGALRM, sigalrm) == SIG_ERR)
1277 fprintf(stderr, "failed to arm SIGALRM"), exit(1);
1278 alarm(ALARM_INTERVAL_SECS);
1279
1010 set_test_type(argv[1]); 1280 set_test_type(argv[1]);
1011 1281
1012 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 1282 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
diff --git a/tools/testing/selftests/watchdog/Makefile b/tools/testing/selftests/watchdog/Makefile
index f863c664e3d1..6b5598b55252 100644
--- a/tools/testing/selftests/watchdog/Makefile
+++ b/tools/testing/selftests/watchdog/Makefile
@@ -1,8 +1,4 @@
1TEST_PROGS := watchdog-test 1# SPDX-License-Identifier: GPL-2.0
2 2TEST_GEN_PROGS := watchdog-test
3all: $(TEST_PROGS)
4 3
5include ../lib.mk 4include ../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
index a74c9d739d07..6e290874b70e 100644
--- a/tools/testing/selftests/watchdog/watchdog-test.c
+++ b/tools/testing/selftests/watchdog/watchdog-test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Watchdog Driver Test Program 3 * Watchdog Driver Test Program
3 */ 4 */
@@ -9,12 +10,25 @@
9#include <unistd.h> 10#include <unistd.h>
10#include <fcntl.h> 11#include <fcntl.h>
11#include <signal.h> 12#include <signal.h>
13#include <getopt.h>
12#include <sys/ioctl.h> 14#include <sys/ioctl.h>
13#include <linux/types.h> 15#include <linux/types.h>
14#include <linux/watchdog.h> 16#include <linux/watchdog.h>
15 17
18#define DEFAULT_PING_RATE 1
19
16int fd; 20int fd;
17const char v = 'V'; 21const char v = 'V';
22static const char sopts[] = "bdehp:t:";
23static const struct option lopts[] = {
24 {"bootstatus", no_argument, NULL, 'b'},
25 {"disable", no_argument, NULL, 'd'},
26 {"enable", no_argument, NULL, 'e'},
27 {"help", no_argument, NULL, 'h'},
28 {"pingrate", required_argument, NULL, 'p'},
29 {"timeout", required_argument, NULL, 't'},
30 {NULL, no_argument, NULL, 0x0}
31};
18 32
19/* 33/*
20 * This function simply sends an IOCTL to the driver, which in turn ticks 34 * This function simply sends an IOCTL to the driver, which in turn ticks
@@ -23,12 +37,12 @@ const char v = 'V';
23 */ 37 */
24static void keep_alive(void) 38static void keep_alive(void)
25{ 39{
26 int dummy; 40 int dummy;
27 int ret; 41 int ret;
28 42
29 ret = ioctl(fd, WDIOC_KEEPALIVE, &dummy); 43 ret = ioctl(fd, WDIOC_KEEPALIVE, &dummy);
30 if (!ret) 44 if (!ret)
31 printf("."); 45 printf(".");
32} 46}
33 47
34/* 48/*
@@ -38,75 +52,110 @@ static void keep_alive(void)
38 52
39static void term(int sig) 53static void term(int sig)
40{ 54{
41 int ret = write(fd, &v, 1); 55 int ret = write(fd, &v, 1);
42 56
43 close(fd); 57 close(fd);
44 if (ret < 0) 58 if (ret < 0)
45 printf("\nStopping watchdog ticks failed (%d)...\n", errno); 59 printf("\nStopping watchdog ticks failed (%d)...\n", errno);
46 else 60 else
47 printf("\nStopping watchdog ticks...\n"); 61 printf("\nStopping watchdog ticks...\n");
48 exit(0); 62 exit(0);
63}
64
65static void usage(char *progname)
66{
67 printf("Usage: %s [options]\n", progname);
68 printf(" -b, --bootstatus Get last boot status (Watchdog/POR)\n");
69 printf(" -d, --disable Turn off the watchdog timer\n");
70 printf(" -e, --enable Turn on the watchdog timer\n");
71 printf(" -h, --help Print the help message\n");
72 printf(" -p, --pingrate=P Set ping rate to P seconds (default %d)\n", DEFAULT_PING_RATE);
73 printf(" -t, --timeout=T Set timeout to T seconds\n");
74 printf("\n");
75 printf("Parameters are parsed left-to-right in real-time.\n");
76 printf("Example: %s -d -t 10 -p 5 -e\n", progname);
49} 77}
50 78
51int main(int argc, char *argv[]) 79int main(int argc, char *argv[])
52{ 80{
53 int flags; 81 int flags;
54 unsigned int ping_rate = 1; 82 unsigned int ping_rate = DEFAULT_PING_RATE;
55 int ret; 83 int ret;
56 int i; 84 int c;
57 85 int oneshot = 0;
58 setbuf(stdout, NULL); 86
59 87 setbuf(stdout, NULL);
60 fd = open("/dev/watchdog", O_WRONLY); 88
61 89 fd = open("/dev/watchdog", O_WRONLY);
62 if (fd == -1) { 90
63 printf("Watchdog device not enabled.\n"); 91 if (fd == -1) {
64 exit(-1); 92 printf("Watchdog device not enabled.\n");
65 } 93 exit(-1);
66 94 }
67 for (i = 1; i < argc; i++) { 95
68 if (!strncasecmp(argv[i], "-d", 2)) { 96 while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
69 flags = WDIOS_DISABLECARD; 97 switch (c) {
70 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags); 98 case 'b':
71 if (!ret) 99 flags = 0;
72 printf("Watchdog card disabled.\n"); 100 oneshot = 1;
73 } else if (!strncasecmp(argv[i], "-e", 2)) { 101 ret = ioctl(fd, WDIOC_GETBOOTSTATUS, &flags);
74 flags = WDIOS_ENABLECARD; 102 if (!ret)
75 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags); 103 printf("Last boot is caused by: %s.\n", (flags != 0) ?
76 if (!ret) 104 "Watchdog" : "Power-On-Reset");
77 printf("Watchdog card enabled.\n"); 105 else
78 } else if (!strncasecmp(argv[i], "-t", 2) && argv[2]) { 106 printf("WDIOC_GETBOOTSTATUS errno '%s'\n", strerror(errno));
79 flags = atoi(argv[i + 1]); 107 break;
80 ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags); 108 case 'd':
81 if (!ret) 109 flags = WDIOS_DISABLECARD;
82 printf("Watchdog timeout set to %u seconds.\n", flags); 110 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
83 i++; 111 if (!ret)
84 } else if (!strncasecmp(argv[i], "-p", 2) && argv[2]) { 112 printf("Watchdog card disabled.\n");
85 ping_rate = strtoul(argv[i + 1], NULL, 0); 113 else
86 printf("Watchdog ping rate set to %u seconds.\n", ping_rate); 114 printf("WDIOS_DISABLECARD errno '%s'\n", strerror(errno));
87 i++; 115 break;
88 } else { 116 case 'e':
89 printf("-d to disable, -e to enable, -t <n> to set " 117 flags = WDIOS_ENABLECARD;
90 "the timeout,\n-p <n> to set the ping rate, and "); 118 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
91 printf("run by itself to tick the card.\n"); 119 if (!ret)
92 printf("Parameters are parsed left-to-right in real-time.\n"); 120 printf("Watchdog card enabled.\n");
93 printf("Example: %s -d -t 10 -p 5 -e\n", argv[0]); 121 else
94 goto end; 122 printf("WDIOS_ENABLECARD errno '%s'\n", strerror(errno));
95 } 123 break;
96 } 124 case 'p':
97 125 ping_rate = strtoul(optarg, NULL, 0);
98 printf("Watchdog Ticking Away!\n"); 126 if (!ping_rate)
99 127 ping_rate = DEFAULT_PING_RATE;
100 signal(SIGINT, term); 128 printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
101 129 break;
102 while(1) { 130 case 't':
103 keep_alive(); 131 flags = strtoul(optarg, NULL, 0);
104 sleep(ping_rate); 132 ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags);
105 } 133 if (!ret)
134 printf("Watchdog timeout set to %u seconds.\n", flags);
135 else
136 printf("WDIOC_SETTIMEOUT errno '%s'\n", strerror(errno));
137 break;
138 default:
139 usage(argv[0]);
140 goto end;
141 }
142 }
143
144 if (oneshot)
145 goto end;
146
147 printf("Watchdog Ticking Away!\n");
148
149 signal(SIGINT, term);
150
151 while (1) {
152 keep_alive();
153 sleep(ping_rate);
154 }
106end: 155end:
107 ret = write(fd, &v, 1); 156 ret = write(fd, &v, 1);
108 if (ret < 0) 157 if (ret < 0)
109 printf("Stopping watchdog ticks failed (%d)...\n", errno); 158 printf("Stopping watchdog ticks failed (%d)...\n", errno);
110 close(fd); 159 close(fd);
111 return 0; 160 return 0;
112} 161}
diff --git a/tools/testing/selftests/x86/5lvl.c b/tools/testing/selftests/x86/5lvl.c
new file mode 100644
index 000000000000..2eafdcd4c2b3
--- /dev/null
+++ b/tools/testing/selftests/x86/5lvl.c
@@ -0,0 +1,177 @@
1#include <stdio.h>
2#include <sys/mman.h>
3
4#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
5
6#define PAGE_SIZE 4096
7#define LOW_ADDR ((void *) (1UL << 30))
8#define HIGH_ADDR ((void *) (1UL << 50))
9
10struct testcase {
11 void *addr;
12 unsigned long size;
13 unsigned long flags;
14 const char *msg;
15 unsigned int low_addr_required:1;
16 unsigned int keep_mapped:1;
17};
18
19static struct testcase testcases[] = {
20 {
21 .addr = NULL,
22 .size = 2 * PAGE_SIZE,
23 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
24 .msg = "mmap(NULL)",
25 .low_addr_required = 1,
26 },
27 {
28 .addr = LOW_ADDR,
29 .size = 2 * PAGE_SIZE,
30 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
31 .msg = "mmap(LOW_ADDR)",
32 .low_addr_required = 1,
33 },
34 {
35 .addr = HIGH_ADDR,
36 .size = 2 * PAGE_SIZE,
37 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
38 .msg = "mmap(HIGH_ADDR)",
39 .keep_mapped = 1,
40 },
41 {
42 .addr = HIGH_ADDR,
43 .size = 2 * PAGE_SIZE,
44 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
45 .msg = "mmap(HIGH_ADDR) again",
46 .keep_mapped = 1,
47 },
48 {
49 .addr = HIGH_ADDR,
50 .size = 2 * PAGE_SIZE,
51 .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
52 .msg = "mmap(HIGH_ADDR, MAP_FIXED)",
53 },
54 {
55 .addr = (void*) -1,
56 .size = 2 * PAGE_SIZE,
57 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
58 .msg = "mmap(-1)",
59 .keep_mapped = 1,
60 },
61 {
62 .addr = (void*) -1,
63 .size = 2 * PAGE_SIZE,
64 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
65 .msg = "mmap(-1) again",
66 },
67 {
68 .addr = (void *)((1UL << 47) - PAGE_SIZE),
69 .size = 2 * PAGE_SIZE,
70 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
71 .msg = "mmap((1UL << 47), 2 * PAGE_SIZE)",
72 .low_addr_required = 1,
73 .keep_mapped = 1,
74 },
75 {
76 .addr = (void *)((1UL << 47) - PAGE_SIZE / 2),
77 .size = 2 * PAGE_SIZE,
78 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
79 .msg = "mmap((1UL << 47), 2 * PAGE_SIZE / 2)",
80 .low_addr_required = 1,
81 .keep_mapped = 1,
82 },
83 {
84 .addr = (void *)((1UL << 47) - PAGE_SIZE),
85 .size = 2 * PAGE_SIZE,
86 .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
87 .msg = "mmap((1UL << 47) - PAGE_SIZE, 2 * PAGE_SIZE, MAP_FIXED)",
88 },
89 {
90 .addr = NULL,
91 .size = 2UL << 20,
92 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
93 .msg = "mmap(NULL, MAP_HUGETLB)",
94 .low_addr_required = 1,
95 },
96 {
97 .addr = LOW_ADDR,
98 .size = 2UL << 20,
99 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
100 .msg = "mmap(LOW_ADDR, MAP_HUGETLB)",
101 .low_addr_required = 1,
102 },
103 {
104 .addr = HIGH_ADDR,
105 .size = 2UL << 20,
106 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
107 .msg = "mmap(HIGH_ADDR, MAP_HUGETLB)",
108 .keep_mapped = 1,
109 },
110 {
111 .addr = HIGH_ADDR,
112 .size = 2UL << 20,
113 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
114 .msg = "mmap(HIGH_ADDR, MAP_HUGETLB) again",
115 .keep_mapped = 1,
116 },
117 {
118 .addr = HIGH_ADDR,
119 .size = 2UL << 20,
120 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
121 .msg = "mmap(HIGH_ADDR, MAP_FIXED | MAP_HUGETLB)",
122 },
123 {
124 .addr = (void*) -1,
125 .size = 2UL << 20,
126 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
127 .msg = "mmap(-1, MAP_HUGETLB)",
128 .keep_mapped = 1,
129 },
130 {
131 .addr = (void*) -1,
132 .size = 2UL << 20,
133 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
134 .msg = "mmap(-1, MAP_HUGETLB) again",
135 },
136 {
137 .addr = (void *)((1UL << 47) - PAGE_SIZE),
138 .size = 4UL << 20,
139 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
140 .msg = "mmap((1UL << 47), 4UL << 20, MAP_HUGETLB)",
141 .low_addr_required = 1,
142 .keep_mapped = 1,
143 },
144 {
145 .addr = (void *)((1UL << 47) - (2UL << 20)),
146 .size = 4UL << 20,
147 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
148 .msg = "mmap((1UL << 47) - (2UL << 20), 4UL << 20, MAP_FIXED | MAP_HUGETLB)",
149 },
150};
151
152int main(int argc, char **argv)
153{
154 int i;
155 void *p;
156
157 for (i = 0; i < ARRAY_SIZE(testcases); i++) {
158 struct testcase *t = testcases + i;
159
160 p = mmap(t->addr, t->size, PROT_NONE, t->flags, -1, 0);
161
162 printf("%s: %p - ", t->msg, p);
163
164 if (p == MAP_FAILED) {
165 printf("FAILED\n");
166 continue;
167 }
168
169 if (t->low_addr_required && p >= (void *)(1UL << 47))
170 printf("FAILED\n");
171 else
172 printf("OK\n");
173 if (!t->keep_mapped)
174 munmap(p, t->size);
175 }
176 return 0;
177}
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index 97f187e2663f..939a337128db 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1all: 2all:
2 3
3include ../lib.mk 4include ../lib.mk
@@ -10,7 +11,7 @@ TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_sysc
10TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ 11TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \
11 test_FCMOV test_FCOMI test_FISTTP \ 12 test_FCMOV test_FCOMI test_FISTTP \
12 vdso_restorer 13 vdso_restorer
13TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip 14TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip 5lvl
14 15
15TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) 16TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
16TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY) 17TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY)
@@ -20,7 +21,7 @@ BINARIES_64 := $(TARGETS_C_64BIT_ALL:%=%_64)
20BINARIES_32 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_32)) 21BINARIES_32 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_32))
21BINARIES_64 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_64)) 22BINARIES_64 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_64))
22 23
23CFLAGS := -O2 -g -std=gnu99 -pthread -Wall 24CFLAGS := -O2 -g -std=gnu99 -pthread -Wall -no-pie
24 25
25UNAME_M := $(shell uname -m) 26UNAME_M := $(shell uname -m)
26CAN_BUILD_I386 := $(shell ./check_cc.sh $(CC) trivial_32bit_program.c -m32) 27CAN_BUILD_I386 := $(shell ./check_cc.sh $(CC) trivial_32bit_program.c -m32)
diff --git a/tools/testing/selftests/x86/entry_from_vm86.c b/tools/testing/selftests/x86/entry_from_vm86.c
index d075ea0e5ca1..361466a2eaef 100644
--- a/tools/testing/selftests/x86/entry_from_vm86.c
+++ b/tools/testing/selftests/x86/entry_from_vm86.c
@@ -95,6 +95,27 @@ asm (
95 "int3\n\t" 95 "int3\n\t"
96 "vmcode_int80:\n\t" 96 "vmcode_int80:\n\t"
97 "int $0x80\n\t" 97 "int $0x80\n\t"
98 "vmcode_umip:\n\t"
99 /* addressing via displacements */
100 "smsw (2052)\n\t"
101 "sidt (2054)\n\t"
102 "sgdt (2060)\n\t"
103 /* addressing via registers */
104 "mov $2066, %bx\n\t"
105 "smsw (%bx)\n\t"
106 "mov $2068, %bx\n\t"
107 "sidt (%bx)\n\t"
108 "mov $2074, %bx\n\t"
109 "sgdt (%bx)\n\t"
110 /* register operands, only for smsw */
111 "smsw %ax\n\t"
112 "mov %ax, (2080)\n\t"
113 "int3\n\t"
114 "vmcode_umip_str:\n\t"
115 "str %eax\n\t"
116 "vmcode_umip_sldt:\n\t"
117 "sldt %eax\n\t"
118 "int3\n\t"
98 ".size vmcode, . - vmcode\n\t" 119 ".size vmcode, . - vmcode\n\t"
99 "end_vmcode:\n\t" 120 "end_vmcode:\n\t"
100 ".code32\n\t" 121 ".code32\n\t"
@@ -103,7 +124,8 @@ asm (
103 124
104extern unsigned char vmcode[], end_vmcode[]; 125extern unsigned char vmcode[], end_vmcode[];
105extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[], 126extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[],
106 vmcode_sti[], vmcode_int3[], vmcode_int80[]; 127 vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[],
128 vmcode_umip_str[], vmcode_umip_sldt[];
107 129
108/* Returns false if the test was skipped. */ 130/* Returns false if the test was skipped. */
109static bool do_test(struct vm86plus_struct *v86, unsigned long eip, 131static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
@@ -160,6 +182,68 @@ static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
160 return true; 182 return true;
161} 183}
162 184
185void do_umip_tests(struct vm86plus_struct *vm86, unsigned char *test_mem)
186{
187 struct table_desc {
188 unsigned short limit;
189 unsigned long base;
190 } __attribute__((packed));
191
192 /* Initialize variables with arbitrary values */
193 struct table_desc gdt1 = { .base = 0x3c3c3c3c, .limit = 0x9999 };
194 struct table_desc gdt2 = { .base = 0x1a1a1a1a, .limit = 0xaeae };
195 struct table_desc idt1 = { .base = 0x7b7b7b7b, .limit = 0xf1f1 };
196 struct table_desc idt2 = { .base = 0x89898989, .limit = 0x1313 };
197 unsigned short msw1 = 0x1414, msw2 = 0x2525, msw3 = 3737;
198
199 /* UMIP -- exit with INT3 unless kernel emulation did not trap #GP */
200 do_test(vm86, vmcode_umip - vmcode, VM86_TRAP, 3, "UMIP tests");
201
202 /* Results from displacement-only addressing */
203 msw1 = *(unsigned short *)(test_mem + 2052);
204 memcpy(&idt1, test_mem + 2054, sizeof(idt1));
205 memcpy(&gdt1, test_mem + 2060, sizeof(gdt1));
206
207 /* Results from register-indirect addressing */
208 msw2 = *(unsigned short *)(test_mem + 2066);
209 memcpy(&idt2, test_mem + 2068, sizeof(idt2));
210 memcpy(&gdt2, test_mem + 2074, sizeof(gdt2));
211
212 /* Results when using register operands */
213 msw3 = *(unsigned short *)(test_mem + 2080);
214
215 printf("[INFO]\tResult from SMSW:[0x%04x]\n", msw1);
216 printf("[INFO]\tResult from SIDT: limit[0x%04x]base[0x%08lx]\n",
217 idt1.limit, idt1.base);
218 printf("[INFO]\tResult from SGDT: limit[0x%04x]base[0x%08lx]\n",
219 gdt1.limit, gdt1.base);
220
221 if (msw1 != msw2 || msw1 != msw3)
222 printf("[FAIL]\tAll the results of SMSW should be the same.\n");
223 else
224 printf("[PASS]\tAll the results from SMSW are identical.\n");
225
226 if (memcmp(&gdt1, &gdt2, sizeof(gdt1)))
227 printf("[FAIL]\tAll the results of SGDT should be the same.\n");
228 else
229 printf("[PASS]\tAll the results from SGDT are identical.\n");
230
231 if (memcmp(&idt1, &idt2, sizeof(idt1)))
232 printf("[FAIL]\tAll the results of SIDT should be the same.\n");
233 else
234 printf("[PASS]\tAll the results from SIDT are identical.\n");
235
236 sethandler(SIGILL, sighandler, 0);
237 do_test(vm86, vmcode_umip_str - vmcode, VM86_SIGNAL, 0,
238 "STR instruction");
239 clearhandler(SIGILL);
240
241 sethandler(SIGILL, sighandler, 0);
242 do_test(vm86, vmcode_umip_sldt - vmcode, VM86_SIGNAL, 0,
243 "SLDT instruction");
244 clearhandler(SIGILL);
245}
246
163int main(void) 247int main(void)
164{ 248{
165 struct vm86plus_struct v86; 249 struct vm86plus_struct v86;
@@ -218,6 +302,9 @@ int main(void)
218 v86.regs.eax = (unsigned int)-1; 302 v86.regs.eax = (unsigned int)-1;
219 do_test(&v86, vmcode_int80 - vmcode, VM86_INTx, 0x80, "int80"); 303 do_test(&v86, vmcode_int80 - vmcode, VM86_INTx, 0x80, "int80");
220 304
305 /* UMIP -- should exit with INTx 0x80 unless UMIP was not disabled */
306 do_umip_tests(&v86, addr);
307
221 /* Execute a null pointer */ 308 /* Execute a null pointer */
222 v86.regs.cs = 0; 309 v86.regs.cs = 0;
223 v86.regs.ss = 0; 310 v86.regs.ss = 0;
diff --git a/tools/testing/selftests/x86/fsgsbase.c b/tools/testing/selftests/x86/fsgsbase.c
index b4967d875236..f249e042b3b5 100644
--- a/tools/testing/selftests/x86/fsgsbase.c
+++ b/tools/testing/selftests/x86/fsgsbase.c
@@ -285,9 +285,12 @@ static void *threadproc(void *ctx)
285 } 285 }
286} 286}
287 287
288static void set_gs_and_switch_to(unsigned long local, unsigned long remote) 288static void set_gs_and_switch_to(unsigned long local,
289 unsigned short force_sel,
290 unsigned long remote)
289{ 291{
290 unsigned long base; 292 unsigned long base;
293 unsigned short sel_pre_sched, sel_post_sched;
291 294
292 bool hard_zero = false; 295 bool hard_zero = false;
293 if (local == HARD_ZERO) { 296 if (local == HARD_ZERO) {
@@ -297,6 +300,8 @@ static void set_gs_and_switch_to(unsigned long local, unsigned long remote)
297 300
298 printf("[RUN]\tARCH_SET_GS(0x%lx)%s, then schedule to 0x%lx\n", 301 printf("[RUN]\tARCH_SET_GS(0x%lx)%s, then schedule to 0x%lx\n",
299 local, hard_zero ? " and clear gs" : "", remote); 302 local, hard_zero ? " and clear gs" : "", remote);
303 if (force_sel)
304 printf("\tBefore schedule, set selector to 0x%hx\n", force_sel);
300 if (syscall(SYS_arch_prctl, ARCH_SET_GS, local) != 0) 305 if (syscall(SYS_arch_prctl, ARCH_SET_GS, local) != 0)
301 err(1, "ARCH_SET_GS"); 306 err(1, "ARCH_SET_GS");
302 if (hard_zero) 307 if (hard_zero)
@@ -307,18 +312,35 @@ static void set_gs_and_switch_to(unsigned long local, unsigned long remote)
307 printf("[FAIL]\tGSBASE wasn't set as expected\n"); 312 printf("[FAIL]\tGSBASE wasn't set as expected\n");
308 } 313 }
309 314
315 if (force_sel) {
316 asm volatile ("mov %0, %%gs" : : "rm" (force_sel));
317 sel_pre_sched = force_sel;
318 local = read_base(GS);
319
320 /*
321 * Signal delivery seems to mess up weird selectors. Put it
322 * back.
323 */
324 asm volatile ("mov %0, %%gs" : : "rm" (force_sel));
325 } else {
326 asm volatile ("mov %%gs, %0" : "=rm" (sel_pre_sched));
327 }
328
310 remote_base = remote; 329 remote_base = remote;
311 ftx = 1; 330 ftx = 1;
312 syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); 331 syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
313 while (ftx != 0) 332 while (ftx != 0)
314 syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0); 333 syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0);
315 334
335 asm volatile ("mov %%gs, %0" : "=rm" (sel_post_sched));
316 base = read_base(GS); 336 base = read_base(GS);
317 if (base == local) { 337 if (base == local && sel_pre_sched == sel_post_sched) {
318 printf("[OK]\tGSBASE remained 0x%lx\n", local); 338 printf("[OK]\tGS/BASE remained 0x%hx/0x%lx\n",
339 sel_pre_sched, local);
319 } else { 340 } else {
320 nerrs++; 341 nerrs++;
321 printf("[FAIL]\tGSBASE changed to 0x%lx\n", base); 342 printf("[FAIL]\tGS/BASE changed from 0x%hx/0x%lx to 0x%hx/0x%lx\n",
343 sel_pre_sched, local, sel_post_sched, base);
322 } 344 }
323} 345}
324 346
@@ -381,8 +403,15 @@ int main()
381 403
382 for (int local = 0; local < 4; local++) { 404 for (int local = 0; local < 4; local++) {
383 for (int remote = 0; remote < 4; remote++) { 405 for (int remote = 0; remote < 4; remote++) {
384 set_gs_and_switch_to(bases_with_hard_zero[local], 406 for (unsigned short s = 0; s < 5; s++) {
385 bases_with_hard_zero[remote]); 407 unsigned short sel = s;
408 if (s == 4)
409 asm ("mov %%ss, %0" : "=rm" (sel));
410 set_gs_and_switch_to(
411 bases_with_hard_zero[local],
412 sel,
413 bases_with_hard_zero[remote]);
414 }
386 } 415 }
387 } 416 }
388 417
diff --git a/tools/testing/selftests/x86/ioperm.c b/tools/testing/selftests/x86/ioperm.c
index b77313ba2ab1..01de41c1b725 100644
--- a/tools/testing/selftests/x86/ioperm.c
+++ b/tools/testing/selftests/x86/ioperm.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * ioperm.c - Test case for ioperm(2) 3 * ioperm.c - Test case for ioperm(2)
3 * Copyright (c) 2015 Andrew Lutomirski 4 * Copyright (c) 2015 Andrew Lutomirski
diff --git a/tools/testing/selftests/x86/iopl.c b/tools/testing/selftests/x86/iopl.c
index c496ca97bc18..6aa27f34644c 100644
--- a/tools/testing/selftests/x86/iopl.c
+++ b/tools/testing/selftests/x86/iopl.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * iopl.c - Test case for a Linux on Xen 64-bit bug 3 * iopl.c - Test case for a Linux on Xen 64-bit bug
3 * Copyright (c) 2015 Andrew Lutomirski 4 * Copyright (c) 2015 Andrew Lutomirski
diff --git a/tools/testing/selftests/x86/ldt_gdt.c b/tools/testing/selftests/x86/ldt_gdt.c
index b9a22f18566a..66e5ce5b91f0 100644
--- a/tools/testing/selftests/x86/ldt_gdt.c
+++ b/tools/testing/selftests/x86/ldt_gdt.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * ldt_gdt.c - Test cases for LDT and GDT access 3 * ldt_gdt.c - Test cases for LDT and GDT access
3 * Copyright (c) 2015 Andrew Lutomirski 4 * Copyright (c) 2015 Andrew Lutomirski
@@ -114,7 +115,15 @@ static void check_valid_segment(uint16_t index, int ldt,
114 return; 115 return;
115 } 116 }
116 117
117 if (ar != expected_ar) { 118 /* The SDM says "bits 19:16 are undefined". Thanks. */
119 ar &= ~0xF0000;
120
121 /*
122 * NB: Different Linux versions do different things with the
123 * accessed bit in set_thread_area().
124 */
125 if (ar != expected_ar &&
126 (ldt || ar != (expected_ar | AR_ACCESSED))) {
118 printf("[FAIL]\t%s entry %hu has AR 0x%08X but expected 0x%08X\n", 127 printf("[FAIL]\t%s entry %hu has AR 0x%08X but expected 0x%08X\n",
119 (ldt ? "LDT" : "GDT"), index, ar, expected_ar); 128 (ldt ? "LDT" : "GDT"), index, ar, expected_ar);
120 nerrs++; 129 nerrs++;
@@ -128,30 +137,51 @@ static void check_valid_segment(uint16_t index, int ldt,
128 } 137 }
129} 138}
130 139
131static bool install_valid_mode(const struct user_desc *desc, uint32_t ar, 140static bool install_valid_mode(const struct user_desc *d, uint32_t ar,
132 bool oldmode) 141 bool oldmode, bool ldt)
133{ 142{
134 int ret = syscall(SYS_modify_ldt, oldmode ? 1 : 0x11, 143 struct user_desc desc = *d;
135 desc, sizeof(*desc)); 144 int ret;
136 if (ret < -1) 145
137 errno = -ret; 146 if (!ldt) {
147#ifndef __i386__
148 /* No point testing set_thread_area in a 64-bit build */
149 return false;
150#endif
151 if (!gdt_entry_num)
152 return false;
153 desc.entry_number = gdt_entry_num;
154
155 ret = syscall(SYS_set_thread_area, &desc);
156 } else {
157 ret = syscall(SYS_modify_ldt, oldmode ? 1 : 0x11,
158 &desc, sizeof(desc));
159
160 if (ret < -1)
161 errno = -ret;
162
163 if (ret != 0 && errno == ENOSYS) {
164 printf("[OK]\tmodify_ldt returned -ENOSYS\n");
165 return false;
166 }
167 }
168
138 if (ret == 0) { 169 if (ret == 0) {
139 uint32_t limit = desc->limit; 170 uint32_t limit = desc.limit;
140 if (desc->limit_in_pages) 171 if (desc.limit_in_pages)
141 limit = (limit << 12) + 4095; 172 limit = (limit << 12) + 4095;
142 check_valid_segment(desc->entry_number, 1, ar, limit, true); 173 check_valid_segment(desc.entry_number, ldt, ar, limit, true);
143 return true; 174 return true;
144 } else if (errno == ENOSYS) {
145 printf("[OK]\tmodify_ldt returned -ENOSYS\n");
146 return false;
147 } else { 175 } else {
148 if (desc->seg_32bit) { 176 if (desc.seg_32bit) {
149 printf("[FAIL]\tUnexpected modify_ldt failure %d\n", 177 printf("[FAIL]\tUnexpected %s failure %d\n",
178 ldt ? "modify_ldt" : "set_thread_area",
150 errno); 179 errno);
151 nerrs++; 180 nerrs++;
152 return false; 181 return false;
153 } else { 182 } else {
154 printf("[OK]\tmodify_ldt rejected 16 bit segment\n"); 183 printf("[OK]\t%s rejected 16 bit segment\n",
184 ldt ? "modify_ldt" : "set_thread_area");
155 return false; 185 return false;
156 } 186 }
157 } 187 }
@@ -159,7 +189,15 @@ static bool install_valid_mode(const struct user_desc *desc, uint32_t ar,
159 189
160static bool install_valid(const struct user_desc *desc, uint32_t ar) 190static bool install_valid(const struct user_desc *desc, uint32_t ar)
161{ 191{
162 return install_valid_mode(desc, ar, false); 192 bool ret = install_valid_mode(desc, ar, false, true);
193
194 if (desc->contents <= 1 && desc->seg_32bit &&
195 !desc->seg_not_present) {
196 /* Should work in the GDT, too. */
197 install_valid_mode(desc, ar, false, false);
198 }
199
200 return ret;
163} 201}
164 202
165static void install_invalid(const struct user_desc *desc, bool oldmode) 203static void install_invalid(const struct user_desc *desc, bool oldmode)
@@ -366,9 +404,24 @@ static void do_simple_tests(void)
366 install_invalid(&desc, false); 404 install_invalid(&desc, false);
367 405
368 desc.seg_not_present = 0; 406 desc.seg_not_present = 0;
369 desc.read_exec_only = 0;
370 desc.seg_32bit = 1; 407 desc.seg_32bit = 1;
408 desc.read_exec_only = 0;
409 desc.limit = 0xfffff;
410
371 install_valid(&desc, AR_DPL3 | AR_TYPE_RWDATA | AR_S | AR_P | AR_DB); 411 install_valid(&desc, AR_DPL3 | AR_TYPE_RWDATA | AR_S | AR_P | AR_DB);
412
413 desc.limit_in_pages = 1;
414
415 install_valid(&desc, AR_DPL3 | AR_TYPE_RWDATA | AR_S | AR_P | AR_DB | AR_G);
416 desc.read_exec_only = 1;
417 install_valid(&desc, AR_DPL3 | AR_TYPE_RODATA | AR_S | AR_P | AR_DB | AR_G);
418 desc.contents = 1;
419 desc.read_exec_only = 0;
420 install_valid(&desc, AR_DPL3 | AR_TYPE_RWDATA_EXPDOWN | AR_S | AR_P | AR_DB | AR_G);
421 desc.read_exec_only = 1;
422 install_valid(&desc, AR_DPL3 | AR_TYPE_RODATA_EXPDOWN | AR_S | AR_P | AR_DB | AR_G);
423
424 desc.limit = 0;
372 install_invalid(&desc, true); 425 install_invalid(&desc, true);
373} 426}
374 427
diff --git a/tools/testing/selftests/x86/mpx-debug.h b/tools/testing/selftests/x86/mpx-debug.h
index 9230981f2e12..7546eba7f17a 100644
--- a/tools/testing/selftests/x86/mpx-debug.h
+++ b/tools/testing/selftests/x86/mpx-debug.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _MPX_DEBUG_H 2#ifndef _MPX_DEBUG_H
2#define _MPX_DEBUG_H 3#define _MPX_DEBUG_H
3 4
diff --git a/tools/testing/selftests/x86/mpx-dig.c b/tools/testing/selftests/x86/mpx-dig.c
index ce85356d7e2e..c13607ef5c11 100644
--- a/tools/testing/selftests/x86/mpx-dig.c
+++ b/tools/testing/selftests/x86/mpx-dig.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Written by Dave Hansen <dave.hansen@intel.com> 3 * Written by Dave Hansen <dave.hansen@intel.com>
3 */ 4 */
diff --git a/tools/testing/selftests/x86/mpx-hw.h b/tools/testing/selftests/x86/mpx-hw.h
index 093c190178a9..d1b61ab870f8 100644
--- a/tools/testing/selftests/x86/mpx-hw.h
+++ b/tools/testing/selftests/x86/mpx-hw.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _MPX_HW_H 2#ifndef _MPX_HW_H
2#define _MPX_HW_H 3#define _MPX_HW_H
3 4
@@ -51,14 +52,14 @@
51struct mpx_bd_entry { 52struct mpx_bd_entry {
52 union { 53 union {
53 char x[MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES]; 54 char x[MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES];
54 void *contents[1]; 55 void *contents[0];
55 }; 56 };
56} __attribute__((packed)); 57} __attribute__((packed));
57 58
58struct mpx_bt_entry { 59struct mpx_bt_entry {
59 union { 60 union {
60 char x[MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES]; 61 char x[MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES];
61 unsigned long contents[1]; 62 unsigned long contents[0];
62 }; 63 };
63} __attribute__((packed)); 64} __attribute__((packed));
64 65
diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c
index a8df159a8924..ec0f6b45ce8b 100644
--- a/tools/testing/selftests/x86/mpx-mini-test.c
+++ b/tools/testing/selftests/x86/mpx-mini-test.c
@@ -391,8 +391,7 @@ void handler(int signum, siginfo_t *si, void *vucontext)
391 br_count++; 391 br_count++;
392 dprintf1("#BR 0x%jx (total seen: %d)\n", status, br_count); 392 dprintf1("#BR 0x%jx (total seen: %d)\n", status, br_count);
393 393
394#define __SI_FAULT (3 << 16) 394#define SEGV_BNDERR 3 /* failed address bound checks */
395#define SEGV_BNDERR (__SI_FAULT|3) /* failed address bound checks */
396 395
397 dprintf2("Saw a #BR! status 0x%jx at %016lx br_reason: %jx\n", 396 dprintf2("Saw a #BR! status 0x%jx at %016lx br_reason: %jx\n",
398 status, ip, br_reason); 397 status, ip, br_reason);
diff --git a/tools/testing/selftests/x86/mpx-mm.h b/tools/testing/selftests/x86/mpx-mm.h
index af706a5398f7..6dbdd66b8242 100644
--- a/tools/testing/selftests/x86/mpx-mm.h
+++ b/tools/testing/selftests/x86/mpx-mm.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _MPX_MM_H 2#ifndef _MPX_MM_H
2#define _MPX_MM_H 3#define _MPX_MM_H
3 4
diff --git a/tools/testing/selftests/x86/pkey-helpers.h b/tools/testing/selftests/x86/pkey-helpers.h
index b20293956eec..b3cb7670e026 100644
--- a/tools/testing/selftests/x86/pkey-helpers.h
+++ b/tools/testing/selftests/x86/pkey-helpers.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _PKEYS_HELPER_H 2#ifndef _PKEYS_HELPER_H
2#define _PKEYS_HELPER_H 3#define _PKEYS_HELPER_H
3#define _GNU_SOURCE 4#define _GNU_SOURCE
@@ -29,6 +30,7 @@ static inline void sigsafe_printf(const char *format, ...)
29 if (!dprint_in_signal) { 30 if (!dprint_in_signal) {
30 vprintf(format, ap); 31 vprintf(format, ap);
31 } else { 32 } else {
33 int ret;
32 int len = vsnprintf(dprint_in_signal_buffer, 34 int len = vsnprintf(dprint_in_signal_buffer,
33 DPRINT_IN_SIGNAL_BUF_SIZE, 35 DPRINT_IN_SIGNAL_BUF_SIZE,
34 format, ap); 36 format, ap);
@@ -38,7 +40,9 @@ static inline void sigsafe_printf(const char *format, ...)
38 */ 40 */
39 if (len > DPRINT_IN_SIGNAL_BUF_SIZE) 41 if (len > DPRINT_IN_SIGNAL_BUF_SIZE)
40 len = DPRINT_IN_SIGNAL_BUF_SIZE; 42 len = DPRINT_IN_SIGNAL_BUF_SIZE;
41 write(1, dprint_in_signal_buffer, len); 43 ret = write(1, dprint_in_signal_buffer, len);
44 if (ret < 0)
45 abort();
42 } 46 }
43 va_end(ap); 47 va_end(ap);
44} 48}
diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c
index 3237bc010e1c..bc1b0735bb50 100644
--- a/tools/testing/selftests/x86/protection_keys.c
+++ b/tools/testing/selftests/x86/protection_keys.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Tests x86 Memory Protection Keys (see Documentation/x86/protection-keys.txt) 3 * Tests x86 Memory Protection Keys (see Documentation/x86/protection-keys.txt)
3 * 4 *
@@ -188,17 +189,29 @@ void lots_o_noops_around_write(int *write_to_me)
188#define u64 uint64_t 189#define u64 uint64_t
189 190
190#ifdef __i386__ 191#ifdef __i386__
191#define SYS_mprotect_key 380 192
192#define SYS_pkey_alloc 381 193#ifndef SYS_mprotect_key
193#define SYS_pkey_free 382 194# define SYS_mprotect_key 380
195#endif
196#ifndef SYS_pkey_alloc
197# define SYS_pkey_alloc 381
198# define SYS_pkey_free 382
199#endif
194#define REG_IP_IDX REG_EIP 200#define REG_IP_IDX REG_EIP
195#define si_pkey_offset 0x14 201#define si_pkey_offset 0x14
202
196#else 203#else
197#define SYS_mprotect_key 329 204
198#define SYS_pkey_alloc 330 205#ifndef SYS_mprotect_key
199#define SYS_pkey_free 331 206# define SYS_mprotect_key 329
207#endif
208#ifndef SYS_pkey_alloc
209# define SYS_pkey_alloc 330
210# define SYS_pkey_free 331
211#endif
200#define REG_IP_IDX REG_RIP 212#define REG_IP_IDX REG_RIP
201#define si_pkey_offset 0x20 213#define si_pkey_offset 0x20
214
202#endif 215#endif
203 216
204void dump_mem(void *dumpme, int len_bytes) 217void dump_mem(void *dumpme, int len_bytes)
@@ -212,19 +225,18 @@ void dump_mem(void *dumpme, int len_bytes)
212 } 225 }
213} 226}
214 227
215#define __SI_FAULT (3 << 16) 228#define SEGV_BNDERR 3 /* failed address bound checks */
216#define SEGV_BNDERR (__SI_FAULT|3) /* failed address bound checks */ 229#define SEGV_PKUERR 4
217#define SEGV_PKUERR (__SI_FAULT|4)
218 230
219static char *si_code_str(int si_code) 231static char *si_code_str(int si_code)
220{ 232{
221 if (si_code & SEGV_MAPERR) 233 if (si_code == SEGV_MAPERR)
222 return "SEGV_MAPERR"; 234 return "SEGV_MAPERR";
223 if (si_code & SEGV_ACCERR) 235 if (si_code == SEGV_ACCERR)
224 return "SEGV_ACCERR"; 236 return "SEGV_ACCERR";
225 if (si_code & SEGV_BNDERR) 237 if (si_code == SEGV_BNDERR)
226 return "SEGV_BNDERR"; 238 return "SEGV_BNDERR";
227 if (si_code & SEGV_PKUERR) 239 if (si_code == SEGV_PKUERR)
228 return "SEGV_PKUERR"; 240 return "SEGV_PKUERR";
229 return "UNKNOWN"; 241 return "UNKNOWN";
230} 242}
@@ -238,7 +250,7 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
238 unsigned long ip; 250 unsigned long ip;
239 char *fpregs; 251 char *fpregs;
240 u32 *pkru_ptr; 252 u32 *pkru_ptr;
241 u64 si_pkey; 253 u64 siginfo_pkey;
242 u32 *si_pkey_ptr; 254 u32 *si_pkey_ptr;
243 int pkru_offset; 255 int pkru_offset;
244 fpregset_t fpregset; 256 fpregset_t fpregset;
@@ -280,9 +292,9 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
280 si_pkey_ptr = (u32 *)(((u8 *)si) + si_pkey_offset); 292 si_pkey_ptr = (u32 *)(((u8 *)si) + si_pkey_offset);
281 dprintf1("si_pkey_ptr: %p\n", si_pkey_ptr); 293 dprintf1("si_pkey_ptr: %p\n", si_pkey_ptr);
282 dump_mem(si_pkey_ptr - 8, 24); 294 dump_mem(si_pkey_ptr - 8, 24);
283 si_pkey = *si_pkey_ptr; 295 siginfo_pkey = *si_pkey_ptr;
284 pkey_assert(si_pkey < NR_PKEYS); 296 pkey_assert(siginfo_pkey < NR_PKEYS);
285 last_si_pkey = si_pkey; 297 last_si_pkey = siginfo_pkey;
286 298
287 if ((si->si_code == SEGV_MAPERR) || 299 if ((si->si_code == SEGV_MAPERR) ||
288 (si->si_code == SEGV_ACCERR) || 300 (si->si_code == SEGV_ACCERR) ||
@@ -294,7 +306,7 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
294 dprintf1("signal pkru from xsave: %08x\n", *pkru_ptr); 306 dprintf1("signal pkru from xsave: %08x\n", *pkru_ptr);
295 /* need __rdpkru() version so we do not do shadow_pkru checking */ 307 /* need __rdpkru() version so we do not do shadow_pkru checking */
296 dprintf1("signal pkru from pkru: %08x\n", __rdpkru()); 308 dprintf1("signal pkru from pkru: %08x\n", __rdpkru());
297 dprintf1("si_pkey from siginfo: %jx\n", si_pkey); 309 dprintf1("pkey from siginfo: %jx\n", siginfo_pkey);
298 *(u64 *)pkru_ptr = 0x00000000; 310 *(u64 *)pkru_ptr = 0x00000000;
299 dprintf1("WARNING: set PRKU=0 to allow faulting instruction to continue\n"); 311 dprintf1("WARNING: set PRKU=0 to allow faulting instruction to continue\n");
300 pkru_faults++; 312 pkru_faults++;
diff --git a/tools/testing/selftests/x86/ptrace_syscall.c b/tools/testing/selftests/x86/ptrace_syscall.c
index eaea92439708..1ae1c5a7392e 100644
--- a/tools/testing/selftests/x86/ptrace_syscall.c
+++ b/tools/testing/selftests/x86/ptrace_syscall.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2 3
3#include <sys/ptrace.h> 4#include <sys/ptrace.h>
diff --git a/tools/testing/selftests/x86/raw_syscall_helper_32.S b/tools/testing/selftests/x86/raw_syscall_helper_32.S
index 534e71e35c6a..94410fa2b5ed 100644
--- a/tools/testing/selftests/x86/raw_syscall_helper_32.S
+++ b/tools/testing/selftests/x86/raw_syscall_helper_32.S
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1.global sys32_helper 2.global sys32_helper
2sys32_helper: 3sys32_helper:
3 /* Args: syscall_args_32*, function pointer */ 4 /* Args: syscall_args_32*, function pointer */
diff --git a/tools/testing/selftests/x86/test_FCMOV.c b/tools/testing/selftests/x86/test_FCMOV.c
index 4adcca0c80c4..6b5036fbb735 100644
--- a/tools/testing/selftests/x86/test_FCMOV.c
+++ b/tools/testing/selftests/x86/test_FCMOV.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#undef _GNU_SOURCE 2#undef _GNU_SOURCE
2#define _GNU_SOURCE 1 3#define _GNU_SOURCE 1
3#undef __USE_GNU 4#undef __USE_GNU
diff --git a/tools/testing/selftests/x86/test_FCOMI.c b/tools/testing/selftests/x86/test_FCOMI.c
index db4933e31af9..aec6692c6dcf 100644
--- a/tools/testing/selftests/x86/test_FCOMI.c
+++ b/tools/testing/selftests/x86/test_FCOMI.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#undef _GNU_SOURCE 2#undef _GNU_SOURCE
2#define _GNU_SOURCE 1 3#define _GNU_SOURCE 1
3#undef __USE_GNU 4#undef __USE_GNU
diff --git a/tools/testing/selftests/x86/test_FISTTP.c b/tools/testing/selftests/x86/test_FISTTP.c
index b8e61a047f6b..09789c0ce3e9 100644
--- a/tools/testing/selftests/x86/test_FISTTP.c
+++ b/tools/testing/selftests/x86/test_FISTTP.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#undef _GNU_SOURCE 2#undef _GNU_SOURCE
2#define _GNU_SOURCE 1 3#define _GNU_SOURCE 1
3#undef __USE_GNU 4#undef __USE_GNU
diff --git a/tools/testing/selftests/x86/test_vdso.c b/tools/testing/selftests/x86/test_vdso.c
index 65d7a2bf7e14..29973cde06d3 100644
--- a/tools/testing/selftests/x86/test_vdso.c
+++ b/tools/testing/selftests/x86/test_vdso.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * ldt_gdt.c - Test cases for LDT and GDT access 3 * ldt_gdt.c - Test cases for LDT and GDT access
3 * Copyright (c) 2011-2015 Andrew Lutomirski 4 * Copyright (c) 2011-2015 Andrew Lutomirski
diff --git a/tools/testing/selftests/zram/Makefile b/tools/testing/selftests/zram/Makefile
index c3a87e5f9d36..7f78eb1b59cb 100644
--- a/tools/testing/selftests/zram/Makefile
+++ b/tools/testing/selftests/zram/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1all: 2all:
2 3
3TEST_PROGS := zram.sh 4TEST_PROGS := zram.sh
diff --git a/tools/testing/selftests/zram/zram.sh b/tools/testing/selftests/zram/zram.sh
index 683a292e3290..754de7da426a 100755
--- a/tools/testing/selftests/zram/zram.sh
+++ b/tools/testing/selftests/zram/zram.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
2TCID="zram.sh" 3TCID="zram.sh"
3 4
4. ./zram_lib.sh 5. ./zram_lib.sh
diff --git a/tools/testing/vsock/.gitignore b/tools/testing/vsock/.gitignore
new file mode 100644
index 000000000000..dc5f11faf530
--- /dev/null
+++ b/tools/testing/vsock/.gitignore
@@ -0,0 +1,2 @@
1*.d
2vsock_diag_test
diff --git a/tools/testing/vsock/Makefile b/tools/testing/vsock/Makefile
new file mode 100644
index 000000000000..66ba0924194d
--- /dev/null
+++ b/tools/testing/vsock/Makefile
@@ -0,0 +1,9 @@
1all: test
2test: vsock_diag_test
3vsock_diag_test: vsock_diag_test.o timeout.o control.o
4
5CFLAGS += -g -O2 -Werror -Wall -I. -I../../include/uapi -I../../include -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -D_GNU_SOURCE
6.PHONY: all test clean
7clean:
8 ${RM} *.o *.d vsock_diag_test
9-include *.d
diff --git a/tools/testing/vsock/README b/tools/testing/vsock/README
new file mode 100644
index 000000000000..2cc6d7302db6
--- /dev/null
+++ b/tools/testing/vsock/README
@@ -0,0 +1,36 @@
1AF_VSOCK test suite
2-------------------
3These tests exercise net/vmw_vsock/ host<->guest sockets for VMware, KVM, and
4Hyper-V.
5
6The following tests are available:
7
8 * vsock_diag_test - vsock_diag.ko module for listing open sockets
9
10The following prerequisite steps are not automated and must be performed prior
11to running tests:
12
131. Build the kernel and these tests.
142. Install the kernel and tests on the host.
153. Install the kernel and tests inside the guest.
164. Boot the guest and ensure that the AF_VSOCK transport is enabled.
17
18Invoke test binaries in both directions as follows:
19
20 # host=server, guest=client
21 (host)# $TEST_BINARY --mode=server \
22 --control-port=1234 \
23 --peer-cid=3
24 (guest)# $TEST_BINARY --mode=client \
25 --control-host=$HOST_IP \
26 --control-port=1234 \
27 --peer-cid=2
28
29 # host=client, guest=server
30 (guest)# $TEST_BINARY --mode=server \
31 --control-port=1234 \
32 --peer-cid=2
33 (host)# $TEST_BINARY --mode=client \
34 --control-port=$GUEST_IP \
35 --control-port=1234 \
36 --peer-cid=3
diff --git a/tools/testing/vsock/control.c b/tools/testing/vsock/control.c
new file mode 100644
index 000000000000..90fd47f0e422
--- /dev/null
+++ b/tools/testing/vsock/control.c
@@ -0,0 +1,219 @@
1/* Control socket for client/server test execution
2 *
3 * Copyright (C) 2017 Red Hat, Inc.
4 *
5 * Author: Stefan Hajnoczi <stefanha@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13/* The client and server may need to coordinate to avoid race conditions like
14 * the client attempting to connect to a socket that the server is not
15 * listening on yet. The control socket offers a communications channel for
16 * such coordination tasks.
17 *
18 * If the client calls control_expectln("LISTENING"), then it will block until
19 * the server calls control_writeln("LISTENING"). This provides a simple
20 * mechanism for coordinating between the client and the server.
21 */
22
23#include <errno.h>
24#include <netdb.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29#include <sys/types.h>
30#include <sys/socket.h>
31
32#include "timeout.h"
33#include "control.h"
34
35static int control_fd = -1;
36
37/* Open the control socket, either in server or client mode */
38void control_init(const char *control_host,
39 const char *control_port,
40 bool server)
41{
42 struct addrinfo hints = {
43 .ai_socktype = SOCK_STREAM,
44 };
45 struct addrinfo *result = NULL;
46 struct addrinfo *ai;
47 int ret;
48
49 ret = getaddrinfo(control_host, control_port, &hints, &result);
50 if (ret != 0) {
51 fprintf(stderr, "%s\n", gai_strerror(ret));
52 exit(EXIT_FAILURE);
53 }
54
55 for (ai = result; ai; ai = ai->ai_next) {
56 int fd;
57 int val = 1;
58
59 fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
60 if (fd < 0)
61 continue;
62
63 if (!server) {
64 if (connect(fd, ai->ai_addr, ai->ai_addrlen) < 0)
65 goto next;
66 control_fd = fd;
67 printf("Control socket connected to %s:%s.\n",
68 control_host, control_port);
69 break;
70 }
71
72 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
73 &val, sizeof(val)) < 0) {
74 perror("setsockopt");
75 exit(EXIT_FAILURE);
76 }
77
78 if (bind(fd, ai->ai_addr, ai->ai_addrlen) < 0)
79 goto next;
80 if (listen(fd, 1) < 0)
81 goto next;
82
83 printf("Control socket listening on %s:%s\n",
84 control_host, control_port);
85 fflush(stdout);
86
87 control_fd = accept(fd, NULL, 0);
88 close(fd);
89
90 if (control_fd < 0) {
91 perror("accept");
92 exit(EXIT_FAILURE);
93 }
94 printf("Control socket connection accepted...\n");
95 break;
96
97next:
98 close(fd);
99 }
100
101 if (control_fd < 0) {
102 fprintf(stderr, "Control socket initialization failed. Invalid address %s:%s?\n",
103 control_host, control_port);
104 exit(EXIT_FAILURE);
105 }
106
107 freeaddrinfo(result);
108}
109
110/* Free resources */
111void control_cleanup(void)
112{
113 close(control_fd);
114 control_fd = -1;
115}
116
117/* Write a line to the control socket */
118void control_writeln(const char *str)
119{
120 ssize_t len = strlen(str);
121 ssize_t ret;
122
123 timeout_begin(TIMEOUT);
124
125 do {
126 ret = send(control_fd, str, len, MSG_MORE);
127 timeout_check("send");
128 } while (ret < 0 && errno == EINTR);
129
130 if (ret != len) {
131 perror("send");
132 exit(EXIT_FAILURE);
133 }
134
135 do {
136 ret = send(control_fd, "\n", 1, 0);
137 timeout_check("send");
138 } while (ret < 0 && errno == EINTR);
139
140 if (ret != 1) {
141 perror("send");
142 exit(EXIT_FAILURE);
143 }
144
145 timeout_end();
146}
147
148/* Return the next line from the control socket (without the trailing newline).
149 *
150 * The program terminates if a timeout occurs.
151 *
152 * The caller must free() the returned string.
153 */
154char *control_readln(void)
155{
156 char *buf = NULL;
157 size_t idx = 0;
158 size_t buflen = 0;
159
160 timeout_begin(TIMEOUT);
161
162 for (;;) {
163 ssize_t ret;
164
165 if (idx >= buflen) {
166 char *new_buf;
167
168 new_buf = realloc(buf, buflen + 80);
169 if (!new_buf) {
170 perror("realloc");
171 exit(EXIT_FAILURE);
172 }
173
174 buf = new_buf;
175 buflen += 80;
176 }
177
178 do {
179 ret = recv(control_fd, &buf[idx], 1, 0);
180 timeout_check("recv");
181 } while (ret < 0 && errno == EINTR);
182
183 if (ret == 0) {
184 fprintf(stderr, "unexpected EOF on control socket\n");
185 exit(EXIT_FAILURE);
186 }
187
188 if (ret != 1) {
189 perror("recv");
190 exit(EXIT_FAILURE);
191 }
192
193 if (buf[idx] == '\n') {
194 buf[idx] = '\0';
195 break;
196 }
197
198 idx++;
199 }
200
201 timeout_end();
202
203 return buf;
204}
205
206/* Wait until a given line is received or a timeout occurs */
207void control_expectln(const char *str)
208{
209 char *line;
210
211 line = control_readln();
212 if (strcmp(str, line) != 0) {
213 fprintf(stderr, "expected \"%s\" on control socket, got \"%s\"\n",
214 str, line);
215 exit(EXIT_FAILURE);
216 }
217
218 free(line);
219}
diff --git a/tools/testing/vsock/control.h b/tools/testing/vsock/control.h
new file mode 100644
index 000000000000..54a07efd267c
--- /dev/null
+++ b/tools/testing/vsock/control.h
@@ -0,0 +1,13 @@
1#ifndef CONTROL_H
2#define CONTROL_H
3
4#include <stdbool.h>
5
6void control_init(const char *control_host, const char *control_port,
7 bool server);
8void control_cleanup(void);
9void control_writeln(const char *str);
10char *control_readln(void);
11void control_expectln(const char *str);
12
13#endif /* CONTROL_H */
diff --git a/tools/testing/vsock/timeout.c b/tools/testing/vsock/timeout.c
new file mode 100644
index 000000000000..c49b3003b2db
--- /dev/null
+++ b/tools/testing/vsock/timeout.c
@@ -0,0 +1,64 @@
1/* Timeout API for single-threaded programs that use blocking
2 * syscalls (read/write/send/recv/connect/accept).
3 *
4 * Copyright (C) 2017 Red Hat, Inc.
5 *
6 * Author: Stefan Hajnoczi <stefanha@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; version 2
11 * of the License.
12 */
13
14/* Use the following pattern:
15 *
16 * timeout_begin(TIMEOUT);
17 * do {
18 * ret = accept(...);
19 * timeout_check("accept");
20 * } while (ret < 0 && ret == EINTR);
21 * timeout_end();
22 */
23
24#include <stdlib.h>
25#include <stdbool.h>
26#include <unistd.h>
27#include <stdio.h>
28#include "timeout.h"
29
30static volatile bool timeout;
31
32/* SIGALRM handler function. Do not use sleep(2), alarm(2), or
33 * setitimer(2) while using this API - they may interfere with each
34 * other.
35 */
36void sigalrm(int signo)
37{
38 timeout = true;
39}
40
41/* Start a timeout. Call timeout_check() to verify that the timeout hasn't
42 * expired. timeout_end() must be called to stop the timeout. Timeouts cannot
43 * be nested.
44 */
45void timeout_begin(unsigned int seconds)
46{
47 alarm(seconds);
48}
49
50/* Exit with an error message if the timeout has expired */
51void timeout_check(const char *operation)
52{
53 if (timeout) {
54 fprintf(stderr, "%s timed out\n", operation);
55 exit(EXIT_FAILURE);
56 }
57}
58
59/* Stop a timeout */
60void timeout_end(void)
61{
62 alarm(0);
63 timeout = false;
64}
diff --git a/tools/testing/vsock/timeout.h b/tools/testing/vsock/timeout.h
new file mode 100644
index 000000000000..77db9ce9860a
--- /dev/null
+++ b/tools/testing/vsock/timeout.h
@@ -0,0 +1,14 @@
1#ifndef TIMEOUT_H
2#define TIMEOUT_H
3
4enum {
5 /* Default timeout */
6 TIMEOUT = 10 /* seconds */
7};
8
9void sigalrm(int signo);
10void timeout_begin(unsigned int seconds);
11void timeout_check(const char *operation);
12void timeout_end(void);
13
14#endif /* TIMEOUT_H */
diff --git a/tools/testing/vsock/vsock_diag_test.c b/tools/testing/vsock/vsock_diag_test.c
new file mode 100644
index 000000000000..e896a4af52f4
--- /dev/null
+++ b/tools/testing/vsock/vsock_diag_test.c
@@ -0,0 +1,681 @@
1/*
2 * vsock_diag_test - vsock_diag.ko test suite
3 *
4 * Copyright (C) 2017 Red Hat, Inc.
5 *
6 * Author: Stefan Hajnoczi <stefanha@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; version 2
11 * of the License.
12 */
13
14#include <getopt.h>
15#include <stdio.h>
16#include <stdbool.h>
17#include <stdlib.h>
18#include <string.h>
19#include <errno.h>
20#include <unistd.h>
21#include <signal.h>
22#include <sys/socket.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25#include <linux/list.h>
26#include <linux/net.h>
27#include <linux/netlink.h>
28#include <linux/sock_diag.h>
29#include <netinet/tcp.h>
30
31#include "../../../include/uapi/linux/vm_sockets.h"
32#include "../../../include/uapi/linux/vm_sockets_diag.h"
33
34#include "timeout.h"
35#include "control.h"
36
37enum test_mode {
38 TEST_MODE_UNSET,
39 TEST_MODE_CLIENT,
40 TEST_MODE_SERVER
41};
42
43/* Per-socket status */
44struct vsock_stat {
45 struct list_head list;
46 struct vsock_diag_msg msg;
47};
48
49static const char *sock_type_str(int type)
50{
51 switch (type) {
52 case SOCK_DGRAM:
53 return "DGRAM";
54 case SOCK_STREAM:
55 return "STREAM";
56 default:
57 return "INVALID TYPE";
58 }
59}
60
61static const char *sock_state_str(int state)
62{
63 switch (state) {
64 case TCP_CLOSE:
65 return "UNCONNECTED";
66 case TCP_SYN_SENT:
67 return "CONNECTING";
68 case TCP_ESTABLISHED:
69 return "CONNECTED";
70 case TCP_CLOSING:
71 return "DISCONNECTING";
72 case TCP_LISTEN:
73 return "LISTEN";
74 default:
75 return "INVALID STATE";
76 }
77}
78
79static const char *sock_shutdown_str(int shutdown)
80{
81 switch (shutdown) {
82 case 1:
83 return "RCV_SHUTDOWN";
84 case 2:
85 return "SEND_SHUTDOWN";
86 case 3:
87 return "RCV_SHUTDOWN | SEND_SHUTDOWN";
88 default:
89 return "0";
90 }
91}
92
93static void print_vsock_addr(FILE *fp, unsigned int cid, unsigned int port)
94{
95 if (cid == VMADDR_CID_ANY)
96 fprintf(fp, "*:");
97 else
98 fprintf(fp, "%u:", cid);
99
100 if (port == VMADDR_PORT_ANY)
101 fprintf(fp, "*");
102 else
103 fprintf(fp, "%u", port);
104}
105
106static void print_vsock_stat(FILE *fp, struct vsock_stat *st)
107{
108 print_vsock_addr(fp, st->msg.vdiag_src_cid, st->msg.vdiag_src_port);
109 fprintf(fp, " ");
110 print_vsock_addr(fp, st->msg.vdiag_dst_cid, st->msg.vdiag_dst_port);
111 fprintf(fp, " %s %s %s %u\n",
112 sock_type_str(st->msg.vdiag_type),
113 sock_state_str(st->msg.vdiag_state),
114 sock_shutdown_str(st->msg.vdiag_shutdown),
115 st->msg.vdiag_ino);
116}
117
118static void print_vsock_stats(FILE *fp, struct list_head *head)
119{
120 struct vsock_stat *st;
121
122 list_for_each_entry(st, head, list)
123 print_vsock_stat(fp, st);
124}
125
126static struct vsock_stat *find_vsock_stat(struct list_head *head, int fd)
127{
128 struct vsock_stat *st;
129 struct stat stat;
130
131 if (fstat(fd, &stat) < 0) {
132 perror("fstat");
133 exit(EXIT_FAILURE);
134 }
135
136 list_for_each_entry(st, head, list)
137 if (st->msg.vdiag_ino == stat.st_ino)
138 return st;
139
140 fprintf(stderr, "cannot find fd %d\n", fd);
141 exit(EXIT_FAILURE);
142}
143
144static void check_no_sockets(struct list_head *head)
145{
146 if (!list_empty(head)) {
147 fprintf(stderr, "expected no sockets\n");
148 print_vsock_stats(stderr, head);
149 exit(1);
150 }
151}
152
153static void check_num_sockets(struct list_head *head, int expected)
154{
155 struct list_head *node;
156 int n = 0;
157
158 list_for_each(node, head)
159 n++;
160
161 if (n != expected) {
162 fprintf(stderr, "expected %d sockets, found %d\n",
163 expected, n);
164 print_vsock_stats(stderr, head);
165 exit(EXIT_FAILURE);
166 }
167}
168
169static void check_socket_state(struct vsock_stat *st, __u8 state)
170{
171 if (st->msg.vdiag_state != state) {
172 fprintf(stderr, "expected socket state %#x, got %#x\n",
173 state, st->msg.vdiag_state);
174 exit(EXIT_FAILURE);
175 }
176}
177
178static void send_req(int fd)
179{
180 struct sockaddr_nl nladdr = {
181 .nl_family = AF_NETLINK,
182 };
183 struct {
184 struct nlmsghdr nlh;
185 struct vsock_diag_req vreq;
186 } req = {
187 .nlh = {
188 .nlmsg_len = sizeof(req),
189 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
190 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
191 },
192 .vreq = {
193 .sdiag_family = AF_VSOCK,
194 .vdiag_states = ~(__u32)0,
195 },
196 };
197 struct iovec iov = {
198 .iov_base = &req,
199 .iov_len = sizeof(req),
200 };
201 struct msghdr msg = {
202 .msg_name = &nladdr,
203 .msg_namelen = sizeof(nladdr),
204 .msg_iov = &iov,
205 .msg_iovlen = 1,
206 };
207
208 for (;;) {
209 if (sendmsg(fd, &msg, 0) < 0) {
210 if (errno == EINTR)
211 continue;
212
213 perror("sendmsg");
214 exit(EXIT_FAILURE);
215 }
216
217 return;
218 }
219}
220
221static ssize_t recv_resp(int fd, void *buf, size_t len)
222{
223 struct sockaddr_nl nladdr = {
224 .nl_family = AF_NETLINK,
225 };
226 struct iovec iov = {
227 .iov_base = buf,
228 .iov_len = len,
229 };
230 struct msghdr msg = {
231 .msg_name = &nladdr,
232 .msg_namelen = sizeof(nladdr),
233 .msg_iov = &iov,
234 .msg_iovlen = 1,
235 };
236 ssize_t ret;
237
238 do {
239 ret = recvmsg(fd, &msg, 0);
240 } while (ret < 0 && errno == EINTR);
241
242 if (ret < 0) {
243 perror("recvmsg");
244 exit(EXIT_FAILURE);
245 }
246
247 return ret;
248}
249
250static void add_vsock_stat(struct list_head *sockets,
251 const struct vsock_diag_msg *resp)
252{
253 struct vsock_stat *st;
254
255 st = malloc(sizeof(*st));
256 if (!st) {
257 perror("malloc");
258 exit(EXIT_FAILURE);
259 }
260
261 st->msg = *resp;
262 list_add_tail(&st->list, sockets);
263}
264
265/*
266 * Read vsock stats into a list.
267 */
268static void read_vsock_stat(struct list_head *sockets)
269{
270 long buf[8192 / sizeof(long)];
271 int fd;
272
273 fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
274 if (fd < 0) {
275 perror("socket");
276 exit(EXIT_FAILURE);
277 }
278
279 send_req(fd);
280
281 for (;;) {
282 const struct nlmsghdr *h;
283 ssize_t ret;
284
285 ret = recv_resp(fd, buf, sizeof(buf));
286 if (ret == 0)
287 goto done;
288 if (ret < sizeof(*h)) {
289 fprintf(stderr, "short read of %zd bytes\n", ret);
290 exit(EXIT_FAILURE);
291 }
292
293 h = (struct nlmsghdr *)buf;
294
295 while (NLMSG_OK(h, ret)) {
296 if (h->nlmsg_type == NLMSG_DONE)
297 goto done;
298
299 if (h->nlmsg_type == NLMSG_ERROR) {
300 const struct nlmsgerr *err = NLMSG_DATA(h);
301
302 if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
303 fprintf(stderr, "NLMSG_ERROR\n");
304 else {
305 errno = -err->error;
306 perror("NLMSG_ERROR");
307 }
308
309 exit(EXIT_FAILURE);
310 }
311
312 if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY) {
313 fprintf(stderr, "unexpected nlmsg_type %#x\n",
314 h->nlmsg_type);
315 exit(EXIT_FAILURE);
316 }
317 if (h->nlmsg_len <
318 NLMSG_LENGTH(sizeof(struct vsock_diag_msg))) {
319 fprintf(stderr, "short vsock_diag_msg\n");
320 exit(EXIT_FAILURE);
321 }
322
323 add_vsock_stat(sockets, NLMSG_DATA(h));
324
325 h = NLMSG_NEXT(h, ret);
326 }
327 }
328
329done:
330 close(fd);
331}
332
333static void free_sock_stat(struct list_head *sockets)
334{
335 struct vsock_stat *st;
336 struct vsock_stat *next;
337
338 list_for_each_entry_safe(st, next, sockets, list)
339 free(st);
340}
341
342static void test_no_sockets(unsigned int peer_cid)
343{
344 LIST_HEAD(sockets);
345
346 read_vsock_stat(&sockets);
347
348 check_no_sockets(&sockets);
349
350 free_sock_stat(&sockets);
351}
352
353static void test_listen_socket_server(unsigned int peer_cid)
354{
355 union {
356 struct sockaddr sa;
357 struct sockaddr_vm svm;
358 } addr = {
359 .svm = {
360 .svm_family = AF_VSOCK,
361 .svm_port = 1234,
362 .svm_cid = VMADDR_CID_ANY,
363 },
364 };
365 LIST_HEAD(sockets);
366 struct vsock_stat *st;
367 int fd;
368
369 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
370
371 if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) {
372 perror("bind");
373 exit(EXIT_FAILURE);
374 }
375
376 if (listen(fd, 1) < 0) {
377 perror("listen");
378 exit(EXIT_FAILURE);
379 }
380
381 read_vsock_stat(&sockets);
382
383 check_num_sockets(&sockets, 1);
384 st = find_vsock_stat(&sockets, fd);
385 check_socket_state(st, TCP_LISTEN);
386
387 close(fd);
388 free_sock_stat(&sockets);
389}
390
391static void test_connect_client(unsigned int peer_cid)
392{
393 union {
394 struct sockaddr sa;
395 struct sockaddr_vm svm;
396 } addr = {
397 .svm = {
398 .svm_family = AF_VSOCK,
399 .svm_port = 1234,
400 .svm_cid = peer_cid,
401 },
402 };
403 int fd;
404 int ret;
405 LIST_HEAD(sockets);
406 struct vsock_stat *st;
407
408 control_expectln("LISTENING");
409
410 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
411
412 timeout_begin(TIMEOUT);
413 do {
414 ret = connect(fd, &addr.sa, sizeof(addr.svm));
415 timeout_check("connect");
416 } while (ret < 0 && errno == EINTR);
417 timeout_end();
418
419 if (ret < 0) {
420 perror("connect");
421 exit(EXIT_FAILURE);
422 }
423
424 read_vsock_stat(&sockets);
425
426 check_num_sockets(&sockets, 1);
427 st = find_vsock_stat(&sockets, fd);
428 check_socket_state(st, TCP_ESTABLISHED);
429
430 control_expectln("DONE");
431 control_writeln("DONE");
432
433 close(fd);
434 free_sock_stat(&sockets);
435}
436
437static void test_connect_server(unsigned int peer_cid)
438{
439 union {
440 struct sockaddr sa;
441 struct sockaddr_vm svm;
442 } addr = {
443 .svm = {
444 .svm_family = AF_VSOCK,
445 .svm_port = 1234,
446 .svm_cid = VMADDR_CID_ANY,
447 },
448 };
449 union {
450 struct sockaddr sa;
451 struct sockaddr_vm svm;
452 } clientaddr;
453 socklen_t clientaddr_len = sizeof(clientaddr.svm);
454 LIST_HEAD(sockets);
455 struct vsock_stat *st;
456 int fd;
457 int client_fd;
458
459 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
460
461 if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) {
462 perror("bind");
463 exit(EXIT_FAILURE);
464 }
465
466 if (listen(fd, 1) < 0) {
467 perror("listen");
468 exit(EXIT_FAILURE);
469 }
470
471 control_writeln("LISTENING");
472
473 timeout_begin(TIMEOUT);
474 do {
475 client_fd = accept(fd, &clientaddr.sa, &clientaddr_len);
476 timeout_check("accept");
477 } while (client_fd < 0 && errno == EINTR);
478 timeout_end();
479
480 if (client_fd < 0) {
481 perror("accept");
482 exit(EXIT_FAILURE);
483 }
484 if (clientaddr.sa.sa_family != AF_VSOCK) {
485 fprintf(stderr, "expected AF_VSOCK from accept(2), got %d\n",
486 clientaddr.sa.sa_family);
487 exit(EXIT_FAILURE);
488 }
489 if (clientaddr.svm.svm_cid != peer_cid) {
490 fprintf(stderr, "expected peer CID %u from accept(2), got %u\n",
491 peer_cid, clientaddr.svm.svm_cid);
492 exit(EXIT_FAILURE);
493 }
494
495 read_vsock_stat(&sockets);
496
497 check_num_sockets(&sockets, 2);
498 find_vsock_stat(&sockets, fd);
499 st = find_vsock_stat(&sockets, client_fd);
500 check_socket_state(st, TCP_ESTABLISHED);
501
502 control_writeln("DONE");
503 control_expectln("DONE");
504
505 close(client_fd);
506 close(fd);
507 free_sock_stat(&sockets);
508}
509
510static struct {
511 const char *name;
512 void (*run_client)(unsigned int peer_cid);
513 void (*run_server)(unsigned int peer_cid);
514} test_cases[] = {
515 {
516 .name = "No sockets",
517 .run_server = test_no_sockets,
518 },
519 {
520 .name = "Listen socket",
521 .run_server = test_listen_socket_server,
522 },
523 {
524 .name = "Connect",
525 .run_client = test_connect_client,
526 .run_server = test_connect_server,
527 },
528 {},
529};
530
531static void init_signals(void)
532{
533 struct sigaction act = {
534 .sa_handler = sigalrm,
535 };
536
537 sigaction(SIGALRM, &act, NULL);
538 signal(SIGPIPE, SIG_IGN);
539}
540
541static unsigned int parse_cid(const char *str)
542{
543 char *endptr = NULL;
544 unsigned long int n;
545
546 errno = 0;
547 n = strtoul(str, &endptr, 10);
548 if (errno || *endptr != '\0') {
549 fprintf(stderr, "malformed CID \"%s\"\n", str);
550 exit(EXIT_FAILURE);
551 }
552 return n;
553}
554
555static const char optstring[] = "";
556static const struct option longopts[] = {
557 {
558 .name = "control-host",
559 .has_arg = required_argument,
560 .val = 'H',
561 },
562 {
563 .name = "control-port",
564 .has_arg = required_argument,
565 .val = 'P',
566 },
567 {
568 .name = "mode",
569 .has_arg = required_argument,
570 .val = 'm',
571 },
572 {
573 .name = "peer-cid",
574 .has_arg = required_argument,
575 .val = 'p',
576 },
577 {
578 .name = "help",
579 .has_arg = no_argument,
580 .val = '?',
581 },
582 {},
583};
584
585static void usage(void)
586{
587 fprintf(stderr, "Usage: vsock_diag_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid>\n"
588 "\n"
589 " Server: vsock_diag_test --control-port=1234 --mode=server --peer-cid=3\n"
590 " Client: vsock_diag_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n"
591 "\n"
592 "Run vsock_diag.ko tests. Must be launched in both\n"
593 "guest and host. One side must use --mode=client and\n"
594 "the other side must use --mode=server.\n"
595 "\n"
596 "A TCP control socket connection is used to coordinate tests\n"
597 "between the client and the server. The server requires a\n"
598 "listen address and the client requires an address to\n"
599 "connect to.\n"
600 "\n"
601 "The CID of the other side must be given with --peer-cid=<cid>.\n");
602 exit(EXIT_FAILURE);
603}
604
605int main(int argc, char **argv)
606{
607 const char *control_host = NULL;
608 const char *control_port = NULL;
609 int mode = TEST_MODE_UNSET;
610 unsigned int peer_cid = VMADDR_CID_ANY;
611 int i;
612
613 init_signals();
614
615 for (;;) {
616 int opt = getopt_long(argc, argv, optstring, longopts, NULL);
617
618 if (opt == -1)
619 break;
620
621 switch (opt) {
622 case 'H':
623 control_host = optarg;
624 break;
625 case 'm':
626 if (strcmp(optarg, "client") == 0)
627 mode = TEST_MODE_CLIENT;
628 else if (strcmp(optarg, "server") == 0)
629 mode = TEST_MODE_SERVER;
630 else {
631 fprintf(stderr, "--mode must be \"client\" or \"server\"\n");
632 return EXIT_FAILURE;
633 }
634 break;
635 case 'p':
636 peer_cid = parse_cid(optarg);
637 break;
638 case 'P':
639 control_port = optarg;
640 break;
641 case '?':
642 default:
643 usage();
644 }
645 }
646
647 if (!control_port)
648 usage();
649 if (mode == TEST_MODE_UNSET)
650 usage();
651 if (peer_cid == VMADDR_CID_ANY)
652 usage();
653
654 if (!control_host) {
655 if (mode != TEST_MODE_SERVER)
656 usage();
657 control_host = "0.0.0.0";
658 }
659
660 control_init(control_host, control_port, mode == TEST_MODE_SERVER);
661
662 for (i = 0; test_cases[i].name; i++) {
663 void (*run)(unsigned int peer_cid);
664
665 printf("%s...", test_cases[i].name);
666 fflush(stdout);
667
668 if (mode == TEST_MODE_CLIENT)
669 run = test_cases[i].run_client;
670 else
671 run = test_cases[i].run_server;
672
673 if (run)
674 run(peer_cid);
675
676 printf("ok\n");
677 }
678
679 control_cleanup();
680 return EXIT_SUCCESS;
681}
diff --git a/tools/thermal/tmon/Makefile b/tools/thermal/tmon/Makefile
index 3a961e998281..735a510230c3 100644
--- a/tools/thermal/tmon/Makefile
+++ b/tools/thermal/tmon/Makefile
@@ -1,9 +1,16 @@
1# SPDX-License-Identifier: GPL-2.0
2# We need this for the "cc-option" macro.
3include ../../../scripts/Kbuild.include
4
1VERSION = 1.0 5VERSION = 1.0
2 6
3BINDIR=usr/bin 7BINDIR=usr/bin
4WARNFLAGS=-Wall -Wshadow -W -Wformat -Wimplicit-function-declaration -Wimplicit-int 8WARNFLAGS=-Wall -Wshadow -W -Wformat -Wimplicit-function-declaration -Wimplicit-int
5CFLAGS+= -O1 ${WARNFLAGS} -fstack-protector 9CFLAGS+= -O1 ${WARNFLAGS}
6CC=$(CROSS_COMPILE)gcc 10# Add "-fstack-protector" only if toolchain supports it.
11CFLAGS+= $(call cc-option,-fstack-protector)
12CC?= $(CROSS_COMPILE)gcc
13PKG_CONFIG?= pkg-config
7 14
8CFLAGS+=-D VERSION=\"$(VERSION)\" 15CFLAGS+=-D VERSION=\"$(VERSION)\"
9LDFLAGS+= 16LDFLAGS+=
@@ -18,12 +25,12 @@ STATIC := --static
18endif 25endif
19 26
20TMON_LIBS=-lm -lpthread 27TMON_LIBS=-lm -lpthread
21TMON_LIBS += $(shell pkg-config --libs $(STATIC) panelw ncursesw 2> /dev/null || \ 28TMON_LIBS += $(shell $(PKG_CONFIG) --libs $(STATIC) panelw ncursesw 2> /dev/null || \
22 pkg-config --libs $(STATIC) panel ncurses 2> /dev/null || \ 29 $(PKG_CONFIG) --libs $(STATIC) panel ncurses 2> /dev/null || \
23 echo -lpanel -lncurses) 30 echo -lpanel -lncurses)
24 31
25CFLAGS += $(shell pkg-config --cflags $(STATIC) panelw ncursesw 2> /dev/null || \ 32CFLAGS += $(shell $(PKG_CONFIG) --cflags $(STATIC) panelw ncursesw 2> /dev/null || \
26 pkg-config --cflags $(STATIC) panel ncurses 2> /dev/null) 33 $(PKG_CONFIG) --cflags $(STATIC) panel ncurses 2> /dev/null)
27 34
28OBJS = tmon.o tui.o sysfs.o pid.o 35OBJS = tmon.o tui.o sysfs.o pid.o
29OBJS += 36OBJS +=
diff --git a/tools/thermal/tmon/tmon.8 b/tools/thermal/tmon/tmon.8
index 02d5179803aa..2f122de5841b 100644
--- a/tools/thermal/tmon/tmon.8
+++ b/tools/thermal/tmon/tmon.8
@@ -1,4 +1,5 @@
1.TH TMON 8 1.TH TMON 8
2# SPDX-License-Identifier: GPL-2.0
2.SH NAME 3.SH NAME
3\fBtmon\fP - A monitoring and testing tool for Linux kernel thermal subsystem 4\fBtmon\fP - A monitoring and testing tool for Linux kernel thermal subsystem
4 5
diff --git a/tools/usb/Makefile b/tools/usb/Makefile
index acf2165c04e6..4e6506078494 100644
--- a/tools/usb/Makefile
+++ b/tools/usb/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# Makefile for USB tools 2# Makefile for USB tools
2 3
3CC = $(CROSS_COMPILE)gcc 4CC = $(CROSS_COMPILE)gcc
diff --git a/tools/usb/ffs-aio-example/multibuff/host_app/Makefile b/tools/usb/ffs-aio-example/multibuff/host_app/Makefile
index 8c4a6f0aa82d..df36e4c28f61 100644
--- a/tools/usb/ffs-aio-example/multibuff/host_app/Makefile
+++ b/tools/usb/ffs-aio-example/multibuff/host_app/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1CC = gcc 2CC = gcc
2LIBUSB_CFLAGS = $(shell pkg-config --cflags libusb-1.0) 3LIBUSB_CFLAGS = $(shell pkg-config --cflags libusb-1.0)
3LIBUSB_LIBS = $(shell pkg-config --libs libusb-1.0) 4LIBUSB_LIBS = $(shell pkg-config --libs libusb-1.0)
diff --git a/tools/usb/hcd-tests.sh b/tools/usb/hcd-tests.sh
index b30b3dc4c788..e8cad6a4f9c9 100644
--- a/tools/usb/hcd-tests.sh
+++ b/tools/usb/hcd-tests.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2# 3#
3# test types can be passed on the command line: 4# test types can be passed on the command line:
4# 5#
diff --git a/tools/usb/usbip/Makefile.am b/tools/usb/usbip/Makefile.am
index 66f8bf038c9f..5961e9c18812 100644
--- a/tools/usb/usbip/Makefile.am
+++ b/tools/usb/usbip/Makefile.am
@@ -1,6 +1,8 @@
1# SPDX-License-Identifier: GPL-2.0
1SUBDIRS := libsrc src 2SUBDIRS := libsrc src
2includedir = @includedir@/usbip 3includedir = @includedir@/usbip
3include_HEADERS := $(addprefix libsrc/, \ 4include_HEADERS := $(addprefix libsrc/, \
4 usbip_common.h vhci_driver.h usbip_host_driver.h) 5 usbip_common.h vhci_driver.h usbip_host_driver.h \
6 list.h sysfs_utils.h usbip_host_common.h)
5 7
6dist_man_MANS := $(addprefix doc/, usbip.8 usbipd.8) 8dist_man_MANS := $(addprefix doc/, usbip.8 usbipd.8)
diff --git a/tools/usb/usbip/cleanup.sh b/tools/usb/usbip/cleanup.sh
index 955c3ccb729a..8028c3a5c22b 100755
--- a/tools/usb/usbip/cleanup.sh
+++ b/tools/usb/usbip/cleanup.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2 3
3if [ -r Makefile ]; then 4if [ -r Makefile ]; then
4 make distclean 5 make distclean
diff --git a/tools/usb/usbip/libsrc/Makefile.am b/tools/usb/usbip/libsrc/Makefile.am
index 90daf95c0804..dabd2c91d311 100644
--- a/tools/usb/usbip/libsrc/Makefile.am
+++ b/tools/usb/usbip/libsrc/Makefile.am
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1libusbip_la_CPPFLAGS = -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"' 2libusbip_la_CPPFLAGS = -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
2libusbip_la_CFLAGS = @EXTRA_CFLAGS@ 3libusbip_la_CFLAGS = @EXTRA_CFLAGS@
3libusbip_la_LDFLAGS = -version-info @LIBUSBIP_VERSION@ 4libusbip_la_LDFLAGS = -version-info @LIBUSBIP_VERSION@
diff --git a/tools/usb/usbip/libsrc/list.h b/tools/usb/usbip/libsrc/list.h
index 5eaaa78e2c6a..a941671e4900 100644
--- a/tools/usb/usbip/libsrc/list.h
+++ b/tools/usb/usbip/libsrc/list.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LIST_H 2#ifndef _LIST_H
2#define _LIST_H 3#define _LIST_H
3 4
diff --git a/tools/usb/usbip/libsrc/sysfs_utils.c b/tools/usb/usbip/libsrc/sysfs_utils.c
index 36ac88ece0b8..14d5e67d398a 100644
--- a/tools/usb/usbip/libsrc/sysfs_utils.c
+++ b/tools/usb/usbip/libsrc/sysfs_utils.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#include <sys/types.h> 2#include <sys/types.h>
2#include <sys/stat.h> 3#include <sys/stat.h>
3#include <fcntl.h> 4#include <fcntl.h>
diff --git a/tools/usb/usbip/libsrc/sysfs_utils.h b/tools/usb/usbip/libsrc/sysfs_utils.h
index 32ac1d105d18..0cd5f17e7eb2 100644
--- a/tools/usb/usbip/libsrc/sysfs_utils.h
+++ b/tools/usb/usbip/libsrc/sysfs_utils.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1 2
2#ifndef __SYSFS_UTILS_H 3#ifndef __SYSFS_UTILS_H
3#define __SYSFS_UTILS_H 4#define __SYSFS_UTILS_H
diff --git a/tools/usb/usbip/libsrc/usbip_common.c b/tools/usb/usbip/libsrc/usbip_common.c
index 1517a232ab18..001bb8e8f668 100644
--- a/tools/usb/usbip/libsrc/usbip_common.c
+++ b/tools/usb/usbip/libsrc/usbip_common.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright (C) 2005-2007 Takahiro Hirofuchi 3 * Copyright (C) 2005-2007 Takahiro Hirofuchi
3 */ 4 */
diff --git a/tools/usb/usbip/libsrc/usbip_common.h b/tools/usb/usbip/libsrc/usbip_common.h
index 51ef5fe485dd..e45ec9d2fdbc 100644
--- a/tools/usb/usbip/libsrc/usbip_common.h
+++ b/tools/usb/usbip/libsrc/usbip_common.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Copyright (C) 2005-2007 Takahiro Hirofuchi 3 * Copyright (C) 2005-2007 Takahiro Hirofuchi
3 */ 4 */
diff --git a/tools/usb/usbip/libsrc/vhci_driver.c b/tools/usb/usbip/libsrc/vhci_driver.c
index 9bd2cd71645d..5727dfb15a83 100644
--- a/tools/usb/usbip/libsrc/vhci_driver.c
+++ b/tools/usb/usbip/libsrc/vhci_driver.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Copyright (C) 2005-2007 Takahiro Hirofuchi 3 * Copyright (C) 2005-2007 Takahiro Hirofuchi
3 */ 4 */
diff --git a/tools/usb/usbip/libsrc/vhci_driver.h b/tools/usb/usbip/libsrc/vhci_driver.h
index 4898d3bafb10..418b404d5121 100644
--- a/tools/usb/usbip/libsrc/vhci_driver.h
+++ b/tools/usb/usbip/libsrc/vhci_driver.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Copyright (C) 2005-2007 Takahiro Hirofuchi 3 * Copyright (C) 2005-2007 Takahiro Hirofuchi
3 */ 4 */
diff --git a/tools/usb/usbip/src/Makefile.am b/tools/usb/usbip/src/Makefile.am
index e81a4ebadeff..e26f39e0579d 100644
--- a/tools/usb/usbip/src/Makefile.am
+++ b/tools/usb/usbip/src/Makefile.am
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1AM_CPPFLAGS = -I$(top_srcdir)/libsrc -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"' 2AM_CPPFLAGS = -I$(top_srcdir)/libsrc -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
2AM_CFLAGS = @EXTRA_CFLAGS@ 3AM_CFLAGS = @EXTRA_CFLAGS@
3LDADD = $(top_builddir)/libsrc/libusbip.la 4LDADD = $(top_builddir)/libsrc/libusbip.la
diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c
index 6e89768ffe30..7f07b2d50f59 100644
--- a/tools/usb/usbip/src/usbip_attach.c
+++ b/tools/usb/usbip/src/usbip_attach.c
@@ -99,29 +99,34 @@ static int import_device(int sockfd, struct usbip_usb_device *udev)
99 rc = usbip_vhci_driver_open(); 99 rc = usbip_vhci_driver_open();
100 if (rc < 0) { 100 if (rc < 0) {
101 err("open vhci_driver"); 101 err("open vhci_driver");
102 return -1; 102 goto err_out;
103 } 103 }
104 104
105 port = usbip_vhci_get_free_port(speed); 105 do {
106 if (port < 0) { 106 port = usbip_vhci_get_free_port(speed);
107 err("no free port"); 107 if (port < 0) {
108 usbip_vhci_driver_close(); 108 err("no free port");
109 return -1; 109 goto err_driver_close;
110 } 110 }
111 111
112 dbg("got free port %d", port); 112 dbg("got free port %d", port);
113 113
114 rc = usbip_vhci_attach_device(port, sockfd, udev->busnum, 114 rc = usbip_vhci_attach_device(port, sockfd, udev->busnum,
115 udev->devnum, udev->speed); 115 udev->devnum, udev->speed);
116 if (rc < 0) { 116 if (rc < 0 && errno != EBUSY) {
117 err("import device"); 117 err("import device");
118 usbip_vhci_driver_close(); 118 goto err_driver_close;
119 return -1; 119 }
120 } 120 } while (rc < 0);
121 121
122 usbip_vhci_driver_close(); 122 usbip_vhci_driver_close();
123 123
124 return port; 124 return port;
125
126err_driver_close:
127 usbip_vhci_driver_close();
128err_out:
129 return -1;
125} 130}
126 131
127static int query_import_device(int sockfd, char *busid) 132static int query_import_device(int sockfd, char *busid)
diff --git a/tools/usb/usbip/src/usbip_network.h b/tools/usb/usbip/src/usbip_network.h
index c1e875cf1078..7032687621d3 100644
--- a/tools/usb/usbip/src/usbip_network.h
+++ b/tools/usb/usbip/src/usbip_network.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1/* 2/*
2 * Copyright (C) 2005-2007 Takahiro Hirofuchi 3 * Copyright (C) 2005-2007 Takahiro Hirofuchi
3 */ 4 */
diff --git a/tools/virtio/Makefile b/tools/virtio/Makefile
index 39c89a5ea990..8e2a908115c2 100644
--- a/tools/virtio/Makefile
+++ b/tools/virtio/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1all: test mod 2all: test mod
2test: virtio_test vringh_test 3test: virtio_test vringh_test
3virtio_test: virtio_ring.o virtio_test.o 4virtio_test: virtio_ring.o virtio_test.o
diff --git a/tools/virtio/asm/barrier.h b/tools/virtio/asm/barrier.h
index ba34f9e96efd..0ac3caf90877 100644
--- a/tools/virtio/asm/barrier.h
+++ b/tools/virtio/asm/barrier.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#if defined(__i386__) || defined(__x86_64__) 2#if defined(__i386__) || defined(__x86_64__)
2#define barrier() asm volatile("" ::: "memory") 3#define barrier() asm volatile("" ::: "memory")
3#define virt_mb() __sync_synchronize() 4#define virt_mb() __sync_synchronize()
diff --git a/tools/virtio/linux/bug.h b/tools/virtio/linux/bug.h
index fb94f0787c47..b14c2c3b6b85 100644
--- a/tools/virtio/linux/bug.h
+++ b/tools/virtio/linux/bug.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef BUG_H 2#ifndef BUG_H
2#define BUG_H 3#define BUG_H
3 4
diff --git a/tools/virtio/linux/compiler.h b/tools/virtio/linux/compiler.h
index c9ccfd42ec13..903dc9c4bd11 100644
--- a/tools/virtio/linux/compiler.h
+++ b/tools/virtio/linux/compiler.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef LINUX_COMPILER_H 2#ifndef LINUX_COMPILER_H
2#define LINUX_COMPILER_H 3#define LINUX_COMPILER_H
3 4
diff --git a/tools/virtio/linux/dma-mapping.h b/tools/virtio/linux/dma-mapping.h
index 18601f6689b9..1571e24e9494 100644
--- a/tools/virtio/linux/dma-mapping.h
+++ b/tools/virtio/linux/dma-mapping.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LINUX_DMA_MAPPING_H 2#ifndef _LINUX_DMA_MAPPING_H
2#define _LINUX_DMA_MAPPING_H 3#define _LINUX_DMA_MAPPING_H
3 4
diff --git a/tools/virtio/linux/err.h b/tools/virtio/linux/err.h
index e32eff8b2a14..0943c644a701 100644
--- a/tools/virtio/linux/err.h
+++ b/tools/virtio/linux/err.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef ERR_H 2#ifndef ERR_H
2#define ERR_H 3#define ERR_H
3#define MAX_ERRNO 4095 4#define MAX_ERRNO 4095
diff --git a/tools/virtio/linux/kernel.h b/tools/virtio/linux/kernel.h
index d9554fc3f340..395521a7a8d8 100644
--- a/tools/virtio/linux/kernel.h
+++ b/tools/virtio/linux/kernel.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef KERNEL_H 2#ifndef KERNEL_H
2#define KERNEL_H 3#define KERNEL_H
3#include <stdbool.h> 4#include <stdbool.h>
diff --git a/tools/virtio/linux/module.h b/tools/virtio/linux/module.h
index 28ce95a05997..9dfa96fea2b2 100644
--- a/tools/virtio/linux/module.h
+++ b/tools/virtio/linux/module.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include <linux/export.h> 2#include <linux/export.h>
2 3
3#define MODULE_LICENSE(__MODULE_LICENSE_value) \ 4#define MODULE_LICENSE(__MODULE_LICENSE_value) \
diff --git a/tools/virtio/linux/scatterlist.h b/tools/virtio/linux/scatterlist.h
index 68c9e2adc996..9a45f90e2d08 100644
--- a/tools/virtio/linux/scatterlist.h
+++ b/tools/virtio/linux/scatterlist.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef SCATTERLIST_H 2#ifndef SCATTERLIST_H
2#define SCATTERLIST_H 3#define SCATTERLIST_H
3#include <linux/kernel.h> 4#include <linux/kernel.h>
diff --git a/tools/virtio/linux/slab.h b/tools/virtio/linux/slab.h
index 7e1c1197d439..319dcaa07755 100644
--- a/tools/virtio/linux/slab.h
+++ b/tools/virtio/linux/slab.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef LINUX_SLAB_H 2#ifndef LINUX_SLAB_H
2#define GFP_KERNEL 0 3#define GFP_KERNEL 0
3#define GFP_ATOMIC 0 4#define GFP_ATOMIC 0
diff --git a/tools/virtio/linux/uaccess.h b/tools/virtio/linux/uaccess.h
index fa05d01b2c90..991dfb263998 100644
--- a/tools/virtio/linux/uaccess.h
+++ b/tools/virtio/linux/uaccess.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef UACCESS_H 2#ifndef UACCESS_H
2#define UACCESS_H 3#define UACCESS_H
3 4
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h
index d8f534025b7f..b751350d4ce8 100644
--- a/tools/virtio/linux/virtio.h
+++ b/tools/virtio/linux/virtio.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef LINUX_VIRTIO_H 2#ifndef LINUX_VIRTIO_H
2#define LINUX_VIRTIO_H 3#define LINUX_VIRTIO_H
3#include <linux/scatterlist.h> 4#include <linux/scatterlist.h>
diff --git a/tools/virtio/linux/virtio_byteorder.h b/tools/virtio/linux/virtio_byteorder.h
index 9de9e6ac1d10..5b50f7eebd9c 100644
--- a/tools/virtio/linux/virtio_byteorder.h
+++ b/tools/virtio/linux/virtio_byteorder.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef _LINUX_VIRTIO_BYTEORDER_STUB_H 2#ifndef _LINUX_VIRTIO_BYTEORDER_STUB_H
2#define _LINUX_VIRTIO_BYTEORDER_STUB_H 3#define _LINUX_VIRTIO_BYTEORDER_STUB_H
3 4
diff --git a/tools/virtio/linux/virtio_config.h b/tools/virtio/linux/virtio_config.h
index 9ba11815e0a1..dbf14c1e2188 100644
--- a/tools/virtio/linux/virtio_config.h
+++ b/tools/virtio/linux/virtio_config.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#include <linux/virtio_byteorder.h> 2#include <linux/virtio_byteorder.h>
2#include <linux/virtio.h> 3#include <linux/virtio.h>
3#include <uapi/linux/virtio_config.h> 4#include <uapi/linux/virtio_config.h>
diff --git a/tools/virtio/ringtest/Makefile b/tools/virtio/ringtest/Makefile
index c012edbdb13b..85c98c2810fb 100644
--- a/tools/virtio/ringtest/Makefile
+++ b/tools/virtio/ringtest/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1all: 2all:
2 3
3all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder ptr_ring noring 4all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder ptr_ring noring
diff --git a/tools/virtio/ringtest/main.h b/tools/virtio/ringtest/main.h
index 90b0133004e1..5706e075adf2 100644
--- a/tools/virtio/ringtest/main.h
+++ b/tools/virtio/ringtest/main.h
@@ -110,11 +110,15 @@ static inline void busy_wait(void)
110 barrier(); 110 barrier();
111} 111}
112 112
113#if defined(__x86_64__) || defined(__i386__)
114#define smp_mb() asm volatile("lock; addl $0,-128(%%rsp)" ::: "memory", "cc")
115#else
113/* 116/*
114 * Not using __ATOMIC_SEQ_CST since gcc docs say they are only synchronized 117 * Not using __ATOMIC_SEQ_CST since gcc docs say they are only synchronized
115 * with other __ATOMIC_SEQ_CST calls. 118 * with other __ATOMIC_SEQ_CST calls.
116 */ 119 */
117#define smp_mb() __sync_synchronize() 120#define smp_mb() __sync_synchronize()
121#endif
118 122
119/* 123/*
120 * This abuses the atomic builtins for thread fences, and 124 * This abuses the atomic builtins for thread fences, and
diff --git a/tools/virtio/ringtest/noring.c b/tools/virtio/ringtest/noring.c
index b8d1c1daac7c..ce2440d5ca93 100644
--- a/tools/virtio/ringtest/noring.c
+++ b/tools/virtio/ringtest/noring.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2#include "main.h" 3#include "main.h"
3#include <assert.h> 4#include <assert.h>
diff --git a/tools/virtio/ringtest/ptr_ring.c b/tools/virtio/ringtest/ptr_ring.c
index 7b22f1b20652..38bb171aceba 100644
--- a/tools/virtio/ringtest/ptr_ring.c
+++ b/tools/virtio/ringtest/ptr_ring.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2#include "main.h" 3#include "main.h"
3#include <stdlib.h> 4#include <stdlib.h>
diff --git a/tools/virtio/ringtest/run-on-all.sh b/tools/virtio/ringtest/run-on-all.sh
index 29b0d3920bfc..dcc3ea758f48 100755
--- a/tools/virtio/ringtest/run-on-all.sh
+++ b/tools/virtio/ringtest/run-on-all.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
2 3
3CPUS_ONLINE=$(lscpu --online -p=cpu|grep -v -e '#') 4CPUS_ONLINE=$(lscpu --online -p=cpu|grep -v -e '#')
4#use last CPU for host. Why not the first? 5#use last CPU for host. Why not the first?
diff --git a/tools/virtio/uapi/linux/virtio_ring.h b/tools/virtio/uapi/linux/virtio_ring.h
index 4d99c78234d3..cf50b2e5ff02 100644
--- a/tools/virtio/uapi/linux/virtio_ring.h
+++ b/tools/virtio/uapi/linux/virtio_ring.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef VIRTIO_RING_H 2#ifndef VIRTIO_RING_H
2#define VIRTIO_RING_H 3#define VIRTIO_RING_H
3#include "../../../../include/uapi/linux/virtio_ring.h" 4#include "../../../../include/uapi/linux/virtio_ring.h"
diff --git a/tools/virtio/virtio-trace/Makefile b/tools/virtio/virtio-trace/Makefile
index 0d2381633475..7843ebcda71d 100644
--- a/tools/virtio/virtio-trace/Makefile
+++ b/tools/virtio/virtio-trace/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1CC = gcc 2CC = gcc
2CFLAGS = -O2 -Wall -pthread 3CFLAGS = -O2 -Wall -pthread
3 4
diff --git a/tools/virtio/virtio-trace/trace-agent.h b/tools/virtio/virtio-trace/trace-agent.h
index 8de79bfeaa73..e67885969f0e 100644
--- a/tools/virtio/virtio-trace/trace-agent.h
+++ b/tools/virtio/virtio-trace/trace-agent.h
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 */
1#ifndef __TRACE_AGENT_H__ 2#ifndef __TRACE_AGENT_H__
2#define __TRACE_AGENT_H__ 3#define __TRACE_AGENT_H__
3#include <pthread.h> 4#include <pthread.h>
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c
index 0fecaec90d0d..b427def67e7e 100644
--- a/tools/virtio/virtio_test.c
+++ b/tools/virtio/virtio_test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1#define _GNU_SOURCE 2#define _GNU_SOURCE
2#include <getopt.h> 3#include <getopt.h>
3#include <string.h> 4#include <string.h>
diff --git a/tools/virtio/vringh_test.c b/tools/virtio/vringh_test.c
index 9476c616d064..293653463303 100644
--- a/tools/virtio/vringh_test.c
+++ b/tools/virtio/vringh_test.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* Simple test of virtio code, entirely in userpsace. */ 2/* Simple test of virtio code, entirely in userpsace. */
2#define _GNU_SOURCE 3#define _GNU_SOURCE
3#include <sched.h> 4#include <sched.h>
diff --git a/tools/vm/Makefile b/tools/vm/Makefile
index 006029456988..be320b905ea7 100644
--- a/tools/vm/Makefile
+++ b/tools/vm/Makefile
@@ -1,3 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
1# Makefile for vm tools 2# Makefile for vm tools
2# 3#
3TARGETS=page-types slabinfo page_owner_sort 4TARGETS=page-types slabinfo page_owner_sort
diff --git a/tools/vm/page_owner_sort.c b/tools/vm/page_owner_sort.c
index f1c055f3c243..18fc112b65cd 100644
--- a/tools/vm/page_owner_sort.c
+++ b/tools/vm/page_owner_sort.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * User-space helper to sort the output of /sys/kernel/debug/page_owner 3 * User-space helper to sort the output of /sys/kernel/debug/page_owner
3 * 4 *
diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c
index b9d34b37c017..f82c2eaa859d 100644
--- a/tools/vm/slabinfo.c
+++ b/tools/vm/slabinfo.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Slabinfo: Tool to get reports about slabs 3 * Slabinfo: Tool to get reports about slabs
3 * 4 *
@@ -83,6 +84,7 @@ int output_lines = -1;
83int sort_loss; 84int sort_loss;
84int extended_totals; 85int extended_totals;
85int show_bytes; 86int show_bytes;
87int unreclaim_only;
86 88
87/* Debug options */ 89/* Debug options */
88int sanity; 90int sanity;
@@ -132,6 +134,7 @@ static void usage(void)
132 "-L|--Loss Sort by loss\n" 134 "-L|--Loss Sort by loss\n"
133 "-X|--Xtotals Show extended summary information\n" 135 "-X|--Xtotals Show extended summary information\n"
134 "-B|--Bytes Show size in bytes\n" 136 "-B|--Bytes Show size in bytes\n"
137 "-U|--Unreclaim Show unreclaimable slabs only\n"
135 "\nValid debug options (FZPUT may be combined)\n" 138 "\nValid debug options (FZPUT may be combined)\n"
136 "a / A Switch on all debug options (=FZUP)\n" 139 "a / A Switch on all debug options (=FZUP)\n"
137 "- Switch off all debug options\n" 140 "- Switch off all debug options\n"
@@ -568,6 +571,9 @@ static void slabcache(struct slabinfo *s)
568 if (strcmp(s->name, "*") == 0) 571 if (strcmp(s->name, "*") == 0)
569 return; 572 return;
570 573
574 if (unreclaim_only && s->reclaim_account)
575 return;
576
571 if (actual_slabs == 1) { 577 if (actual_slabs == 1) {
572 report(s); 578 report(s);
573 return; 579 return;
@@ -1346,6 +1352,7 @@ struct option opts[] = {
1346 { "Loss", no_argument, NULL, 'L'}, 1352 { "Loss", no_argument, NULL, 'L'},
1347 { "Xtotals", no_argument, NULL, 'X'}, 1353 { "Xtotals", no_argument, NULL, 'X'},
1348 { "Bytes", no_argument, NULL, 'B'}, 1354 { "Bytes", no_argument, NULL, 'B'},
1355 { "Unreclaim", no_argument, NULL, 'U'},
1349 { NULL, 0, NULL, 0 } 1356 { NULL, 0, NULL, 0 }
1350}; 1357};
1351 1358
@@ -1357,7 +1364,7 @@ int main(int argc, char *argv[])
1357 1364
1358 page_size = getpagesize(); 1365 page_size = getpagesize();
1359 1366
1360 while ((c = getopt_long(argc, argv, "aAd::Defhil1noprstvzTSN:LXB", 1367 while ((c = getopt_long(argc, argv, "aAd::Defhil1noprstvzTSN:LXBU",
1361 opts, NULL)) != -1) 1368 opts, NULL)) != -1)
1362 switch (c) { 1369 switch (c) {
1363 case '1': 1370 case '1':
@@ -1438,6 +1445,9 @@ int main(int argc, char *argv[])
1438 case 'B': 1445 case 'B':
1439 show_bytes = 1; 1446 show_bytes = 1;
1440 break; 1447 break;
1448 case 'U':
1449 unreclaim_only = 1;
1450 break;
1441 default: 1451 default:
1442 fatal("%s: Invalid option '%c'\n", argv[0], optopt); 1452 fatal("%s: Invalid option '%c'\n", argv[0], optopt);
1443 1453
diff --git a/tools/wmi/Makefile b/tools/wmi/Makefile
new file mode 100644
index 000000000000..e664f1167388
--- /dev/null
+++ b/tools/wmi/Makefile
@@ -0,0 +1,18 @@
1PREFIX ?= /usr
2SBINDIR ?= sbin
3INSTALL ?= install
4CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
5CC = $(CROSS_COMPILE)gcc
6
7TARGET = dell-smbios-example
8
9all: $(TARGET)
10
11%: %.c
12 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
13
14clean:
15 $(RM) $(TARGET)
16
17install: dell-smbios-example
18 $(INSTALL) -D -m 755 $(TARGET) $(DESTDIR)$(PREFIX)/$(SBINDIR)/$(TARGET)
diff --git a/tools/wmi/dell-smbios-example.c b/tools/wmi/dell-smbios-example.c
new file mode 100644
index 000000000000..9d3bde081249
--- /dev/null
+++ b/tools/wmi/dell-smbios-example.c
@@ -0,0 +1,210 @@
1/*
2 * Sample application for SMBIOS communication over WMI interface
3 * Performs the following:
4 * - Simple cmd_class/cmd_select lookup for TPM information
5 * - Simple query of known tokens and their values
6 * - Simple activation of a token
7 *
8 * Copyright (C) 2017 Dell, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <errno.h>
16#include <fcntl.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <sys/ioctl.h>
20#include <unistd.h>
21
22/* if uapi header isn't installed, this might not yet exist */
23#ifndef __packed
24#define __packed __attribute__((packed))
25#endif
26#include <linux/wmi.h>
27
28/* It would be better to discover these using udev, but for a simple
29 * application they're hardcoded
30 */
31static const char *ioctl_devfs = "/dev/wmi/dell-smbios";
32static const char *token_sysfs =
33 "/sys/bus/platform/devices/dell-smbios.0/tokens";
34
35static void show_buffer(struct dell_wmi_smbios_buffer *buffer)
36{
37 printf("Call: %x/%x [%x,%x,%x,%x]\nResults: [%8x,%8x,%8x,%8x]\n",
38 buffer->std.cmd_class, buffer->std.cmd_select,
39 buffer->std.input[0], buffer->std.input[1],
40 buffer->std.input[2], buffer->std.input[3],
41 buffer->std.output[0], buffer->std.output[1],
42 buffer->std.output[2], buffer->std.output[3]);
43}
44
45static int run_wmi_smbios_cmd(struct dell_wmi_smbios_buffer *buffer)
46{
47 int fd;
48 int ret;
49
50 fd = open(ioctl_devfs, O_NONBLOCK);
51 ret = ioctl(fd, DELL_WMI_SMBIOS_CMD, buffer);
52 close(fd);
53 return ret;
54}
55
56static int find_token(__u16 token, __u16 *location, __u16 *value)
57{
58 char location_sysfs[60];
59 char value_sysfs[57];
60 char buf[4096];
61 FILE *f;
62 int ret;
63
64 ret = sprintf(value_sysfs, "%s/%04x_value", token_sysfs, token);
65 if (ret < 0) {
66 printf("sprintf value failed\n");
67 return 2;
68 }
69 f = fopen(value_sysfs, "rb");
70 if (!f) {
71 printf("failed to open %s\n", value_sysfs);
72 return 2;
73 }
74 fread(buf, 1, 4096, f);
75 fclose(f);
76 *value = (__u16) strtol(buf, NULL, 16);
77
78 ret = sprintf(location_sysfs, "%s/%04x_location", token_sysfs, token);
79 if (ret < 0) {
80 printf("sprintf location failed\n");
81 return 1;
82 }
83 f = fopen(location_sysfs, "rb");
84 if (!f) {
85 printf("failed to open %s\n", location_sysfs);
86 return 2;
87 }
88 fread(buf, 1, 4096, f);
89 fclose(f);
90 *location = (__u16) strtol(buf, NULL, 16);
91
92 if (*location)
93 return 0;
94 return 2;
95}
96
97static int token_is_active(__u16 *location, __u16 *cmpvalue,
98 struct dell_wmi_smbios_buffer *buffer)
99{
100 int ret;
101
102 buffer->std.cmd_class = CLASS_TOKEN_READ;
103 buffer->std.cmd_select = SELECT_TOKEN_STD;
104 buffer->std.input[0] = *location;
105 ret = run_wmi_smbios_cmd(buffer);
106 if (ret != 0 || buffer->std.output[0] != 0)
107 return ret;
108 ret = (buffer->std.output[1] == *cmpvalue);
109 return ret;
110}
111
112static int query_token(__u16 token, struct dell_wmi_smbios_buffer *buffer)
113{
114 __u16 location;
115 __u16 value;
116 int ret;
117
118 ret = find_token(token, &location, &value);
119 if (ret != 0) {
120 printf("unable to find token %04x\n", token);
121 return 1;
122 }
123 return token_is_active(&location, &value, buffer);
124}
125
126static int activate_token(struct dell_wmi_smbios_buffer *buffer,
127 __u16 token)
128{
129 __u16 location;
130 __u16 value;
131 int ret;
132
133 ret = find_token(token, &location, &value);
134 if (ret != 0) {
135 printf("unable to find token %04x\n", token);
136 return 1;
137 }
138 buffer->std.cmd_class = CLASS_TOKEN_WRITE;
139 buffer->std.cmd_select = SELECT_TOKEN_STD;
140 buffer->std.input[0] = location;
141 buffer->std.input[1] = 1;
142 ret = run_wmi_smbios_cmd(buffer);
143 return ret;
144}
145
146static int query_buffer_size(__u64 *buffer_size)
147{
148 FILE *f;
149
150 f = fopen(ioctl_devfs, "rb");
151 if (!f)
152 return -EINVAL;
153 fread(buffer_size, sizeof(__u64), 1, f);
154 fclose(f);
155 return EXIT_SUCCESS;
156}
157
158int main(void)
159{
160 struct dell_wmi_smbios_buffer *buffer;
161 int ret;
162 __u64 value = 0;
163
164 ret = query_buffer_size(&value);
165 if (ret == EXIT_FAILURE || !value) {
166 printf("Unable to read buffer size\n");
167 goto out;
168 }
169 printf("Detected required buffer size %lld\n", value);
170
171 buffer = malloc(value);
172 if (buffer == NULL) {
173 printf("failed to alloc memory for ioctl\n");
174 ret = -ENOMEM;
175 goto out;
176 }
177 buffer->length = value;
178
179 /* simple SMBIOS call for looking up TPM info */
180 buffer->std.cmd_class = CLASS_FLASH_INTERFACE;
181 buffer->std.cmd_select = SELECT_FLASH_INTERFACE;
182 buffer->std.input[0] = 2;
183 ret = run_wmi_smbios_cmd(buffer);
184 if (ret) {
185 printf("smbios ioctl failed: %d\n", ret);
186 ret = EXIT_FAILURE;
187 goto out;
188 }
189 show_buffer(buffer);
190
191 /* query some tokens */
192 ret = query_token(CAPSULE_EN_TOKEN, buffer);
193 printf("UEFI Capsule enabled token is: %d\n", ret);
194 ret = query_token(CAPSULE_DIS_TOKEN, buffer);
195 printf("UEFI Capsule disabled token is: %d\n", ret);
196
197 /* activate UEFI capsule token if disabled */
198 if (ret) {
199 printf("Enabling UEFI capsule token");
200 if (activate_token(buffer, CAPSULE_EN_TOKEN)) {
201 printf("activate failed\n");
202 ret = -1;
203 goto out;
204 }
205 }
206 ret = EXIT_SUCCESS;
207out:
208 free(buffer);
209 return ret;
210}