aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2017-09-19 09:12:47 -0400
committerMark Brown <broonie@kernel.org>2017-09-19 09:12:47 -0400
commite9331ee9b164d58b4dd0abc882ba7e23d2f404b3 (patch)
tree903d078e53a59ed65708193f2486ad0b9a8109d8 /tools
parente7251484f3bc3bd9203a2c39555ca7d53e988cf6 (diff)
parent2bd6bf03f4c1c59381d62c61d03f6cc3fe71f66e (diff)
Merge tag 'v4.14-rc1' into asoc-rockchip
Linux 4.14-rc1
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile15
-rw-r--r--tools/arch/arm/include/uapi/asm/kvm.h8
-rw-r--r--tools/arch/arm64/include/uapi/asm/kvm.h3
-rw-r--r--tools/arch/parisc/include/uapi/asm/mman.h2
-rw-r--r--tools/arch/powerpc/include/uapi/asm/kvm.h6
-rw-r--r--tools/arch/s390/include/uapi/asm/kvm.h12
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h3
-rw-r--r--tools/arch/x86/include/asm/unistd_32.h3
-rw-r--r--tools/arch/x86/include/asm/unistd_64.h3
-rw-r--r--tools/arch/x86/include/uapi/asm/unistd.h17
-rw-r--r--tools/build/Makefile.feature3
-rw-r--r--tools/build/feature/Makefile6
-rw-r--r--tools/build/feature/test-all.c5
-rw-r--r--tools/build/feature/test-bpf.c2
-rw-r--r--tools/build/feature/test-setns.c7
-rw-r--r--tools/build/tests/ex/Makefile2
-rwxr-xr-xtools/hv/bondvf.sh232
-rw-r--r--tools/hv/hv_fcopy_daemon.c32
-rw-r--r--tools/hv/hv_kvp_daemon.c2
-rw-r--r--tools/hv/hv_vss_daemon.c7
-rw-r--r--tools/iio/Build3
-rw-r--r--tools/iio/Makefile76
-rw-r--r--tools/include/linux/compiler-gcc.h9
-rw-r--r--tools/include/linux/coresight-pmu.h6
-rw-r--r--tools/include/linux/string.h12
-rw-r--r--tools/include/uapi/asm-generic/fcntl.h220
-rw-r--r--tools/include/uapi/asm-generic/ioctls.h118
-rw-r--r--tools/include/uapi/drm/drm.h933
-rw-r--r--tools/include/uapi/drm/i915_drm.h1474
-rw-r--r--tools/include/uapi/linux/bpf.h76
-rw-r--r--tools/include/uapi/linux/fcntl.h21
-rw-r--r--tools/include/uapi/linux/kvm.h1419
-rw-r--r--tools/include/uapi/linux/perf_event.h61
-rw-r--r--tools/include/uapi/linux/sched.h52
-rw-r--r--tools/include/uapi/linux/vhost.h209
-rw-r--r--tools/include/uapi/sound/asound.h1026
-rwxr-xr-xtools/kvm/kvm_stat/kvm_stat22
-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/Makefile16
-rw-r--r--tools/lib/bpf/Makefile12
-rw-r--r--tools/lib/bpf/bpf.c39
-rw-r--r--tools/lib/bpf/bpf.h8
-rw-r--r--tools/lib/bpf/libbpf.c32
-rw-r--r--tools/lib/bpf/libbpf.h2
-rw-r--r--tools/lib/string.c41
-rw-r--r--tools/lib/subcmd/Makefile2
-rw-r--r--tools/lib/subcmd/help.c2
-rw-r--r--tools/lib/subcmd/parse-options.c18
-rw-r--r--tools/objtool/Build3
-rw-r--r--tools/objtool/Documentation/stack-validation.txt56
-rw-r--r--tools/objtool/Makefile6
-rw-r--r--tools/objtool/arch.h5
-rw-r--r--tools/objtool/arch/x86/decode.c91
-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.c498
-rw-r--r--tools/objtool/check.h22
-rw-r--r--tools/objtool/elf.c212
-rw-r--r--tools/objtool/elf.h15
-rw-r--r--tools/objtool/objtool.c3
-rw-r--r--tools/objtool/orc.h30
-rw-r--r--tools/objtool/orc_dump.c212
-rw-r--r--tools/objtool/orc_gen.c214
-rw-r--r--tools/objtool/orc_types.h107
-rw-r--r--tools/pci/pcitest.c1
-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-mem.txt4
-rw-r--r--tools/perf/Documentation/perf-probe.txt14
-rw-r--r--tools/perf/Documentation/perf-record.txt6
-rw-r--r--tools/perf/Documentation/perf-report.txt1
-rw-r--r--tools/perf/Documentation/perf-script.txt2
-rw-r--r--tools/perf/Documentation/perf-stat.txt4
-rw-r--r--tools/perf/Documentation/perf-top.txt4
-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/MANIFEST8
-rw-r--r--tools/perf/Makefile.config25
-rw-r--r--tools/perf/Makefile.perf101
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c28
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c2
-rw-r--r--tools/perf/arch/s390/util/Build1
-rw-r--r--tools/perf/arch/s390/util/sym-handling.c29
-rw-r--r--tools/perf/arch/x86/Makefile2
-rw-r--r--tools/perf/arch/x86/annotate/instructions.c46
-rw-r--r--tools/perf/arch/x86/include/arch-tests.h11
-rw-r--r--tools/perf/arch/x86/tests/insn-x86.c2
-rw-r--r--tools/perf/arch/x86/tests/intel-cqm.c2
-rw-r--r--tools/perf/arch/x86/tests/perf-time-to-tsc.c2
-rw-r--r--tools/perf/arch/x86/tests/rdpmc.c2
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c3
-rw-r--r--tools/perf/builtin-annotate.c23
-rw-r--r--tools/perf/builtin-buildid-cache.c54
-rw-r--r--tools/perf/builtin-config.c5
-rw-r--r--tools/perf/builtin-data.c2
-rw-r--r--tools/perf/builtin-ftrace.c2
-rw-r--r--tools/perf/builtin-help.c6
-rw-r--r--tools/perf/builtin-inject.c1
-rw-r--r--tools/perf/builtin-kmem.c1
-rw-r--r--tools/perf/builtin-mem.c97
-rw-r--r--tools/perf/builtin-probe.c45
-rw-r--r--tools/perf/builtin-record.c11
-rw-r--r--tools/perf/builtin-report.c63
-rw-r--r--tools/perf/builtin-script.c26
-rw-r--r--tools/perf/builtin-stat.c34
-rw-r--r--tools/perf/builtin-top.c22
-rw-r--r--tools/perf/builtin-trace.c781
-rwxr-xr-xtools/perf/check-headers.sh20
-rw-r--r--tools/perf/perf-sys.h28
-rw-r--r--tools/perf/perf.c30
-rw-r--r--tools/perf/perf.h2
-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/mapfile.csv1
-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/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.c23
-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/export-to-postgresql.py5
-rw-r--r--tools/perf/scripts/python/export-to-sqlite.py451
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/attr.c14
-rw-r--r--tools/perf/tests/attr.py50
-rw-r--r--tools/perf/tests/attr/base-record6
-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-group1
-rw-r--r--tools/perf/tests/attr/test-record-group-sampling1
-rw-r--r--tools/perf/tests/attr/test-record-group11
-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-C04
-rw-r--r--tools/perf/tests/attr/test-stat-default2
-rw-r--r--tools/perf/tests/attr/test-stat-detailed-12
-rw-r--r--tools/perf/tests/attr/test-stat-detailed-23
-rw-r--r--tools/perf/tests/attr/test-stat-detailed-35
-rw-r--r--tools/perf/tests/backward-ring-buffer.c2
-rw-r--r--tools/perf/tests/bitmap.c2
-rw-r--r--tools/perf/tests/bp_signal.c2
-rw-r--r--tools/perf/tests/bp_signal_overflow.c2
-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.c188
-rw-r--r--tools/perf/tests/clang.c4
-rw-r--r--tools/perf/tests/code-reading.c7
-rw-r--r--tools/perf/tests/cpumap.c4
-rw-r--r--tools/perf/tests/dso-data.c6
-rw-r--r--tools/perf/tests/dwarf-unwind.c4
-rw-r--r--tools/perf/tests/event-times.c2
-rw-r--r--tools/perf/tests/event_update.c2
-rw-r--r--tools/perf/tests/evsel-roundtrip-name.c2
-rw-r--r--tools/perf/tests/evsel-tp-sched.c2
-rw-r--r--tools/perf/tests/expr.c7
-rw-r--r--tools/perf/tests/fdarray.c4
-rw-r--r--tools/perf/tests/hists_cumulate.c2
-rw-r--r--tools/perf/tests/hists_filter.c2
-rw-r--r--tools/perf/tests/hists_link.c2
-rw-r--r--tools/perf/tests/hists_output.c2
-rw-r--r--tools/perf/tests/is_printable_array.c2
-rw-r--r--tools/perf/tests/keep-tracking.c2
-rw-r--r--tools/perf/tests/kmod-path.c2
-rw-r--r--tools/perf/tests/llvm.c2
-rw-r--r--tools/perf/tests/mem.c56
-rw-r--r--tools/perf/tests/mmap-basic.c2
-rw-r--r--tools/perf/tests/mmap-thread-lookup.c2
-rw-r--r--tools/perf/tests/openat-syscall-all-cpus.c4
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c2
-rw-r--r--tools/perf/tests/openat-syscall.c4
-rw-r--r--tools/perf/tests/parse-events.c2
-rw-r--r--tools/perf/tests/parse-no-sample-id-all.c2
-rw-r--r--tools/perf/tests/perf-hooks.c2
-rw-r--r--tools/perf/tests/perf-record.c2
-rw-r--r--tools/perf/tests/pmu.c2
-rw-r--r--tools/perf/tests/python-use.c2
-rw-r--r--tools/perf/tests/sample-parsing.c8
-rw-r--r--tools/perf/tests/sdt.c12
-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.sh43
-rwxr-xr-xtools/perf/tests/shell/trace+probe_vfs_getname.sh35
-rw-r--r--tools/perf/tests/stat.c6
-rw-r--r--tools/perf/tests/sw-clock.c2
-rw-r--r--tools/perf/tests/switch-tracking.c2
-rw-r--r--tools/perf/tests/task-exit.c2
-rw-r--r--tools/perf/tests/tests.h114
-rw-r--r--tools/perf/tests/thread-map.c6
-rw-r--r--tools/perf/tests/thread-mg-share.c2
-rw-r--r--tools/perf/tests/topology.c2
-rw-r--r--tools/perf/tests/unit_number__scnprintf.c2
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c2
-rw-r--r--tools/perf/trace/beauty/Build6
-rw-r--r--tools/perf/trace/beauty/beauty.h74
-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/fcntl.c100
-rw-r--r--tools/perf/trace/beauty/ioctl.c162
-rwxr-xr-xtools/perf/trace/beauty/kvm_ioctl.sh11
-rw-r--r--tools/perf/trace/beauty/mmap.c3
-rw-r--r--tools/perf/trace/beauty/open_flags.c29
-rwxr-xr-xtools/perf/trace/beauty/perf_ioctl.sh10
-rw-r--r--tools/perf/trace/beauty/pid.c4
-rw-r--r--tools/perf/trace/beauty/pkey_alloc.c50
-rwxr-xr-xtools/perf/trace/beauty/pkey_alloc_access_rights.sh10
-rwxr-xr-xtools/perf/trace/beauty/sndrv_ctl_ioctl.sh8
-rwxr-xr-xtools/perf/trace/beauty/sndrv_pcm_ioctl.sh8
-rwxr-xr-xtools/perf/trace/beauty/vhost_virtio_ioctl.sh17
-rw-r--r--tools/perf/ui/browser.c34
-rw-r--r--tools/perf/ui/browser.h2
-rw-r--r--tools/perf/ui/browsers/annotate.c97
-rw-r--r--tools/perf/ui/browsers/hists.c11
-rw-r--r--tools/perf/ui/gtk/annotate.c6
-rw-r--r--tools/perf/ui/progress.c9
-rw-r--r--tools/perf/ui/stdio/hist.c16
-rw-r--r--tools/perf/util/Build6
-rw-r--r--tools/perf/util/annotate.c137
-rw-r--r--tools/perf/util/annotate.h22
-rw-r--r--tools/perf/util/bpf-loader.c2
-rw-r--r--tools/perf/util/bpf-prologue.c49
-rw-r--r--tools/perf/util/branch.c147
-rw-r--r--tools/perf/util/branch.h25
-rw-r--r--tools/perf/util/build-id.c129
-rw-r--r--tools/perf/util/build-id.h16
-rw-r--r--tools/perf/util/callchain.c272
-rw-r--r--tools/perf/util/callchain.h12
-rw-r--r--tools/perf/util/cgroup.c8
-rw-r--r--tools/perf/util/config.c13
-rw-r--r--tools/perf/util/counts.h1
-rw-r--r--tools/perf/util/data-convert-bt.c127
-rw-r--r--tools/perf/util/data.c13
-rw-r--r--tools/perf/util/dso.c21
-rw-r--r--tools/perf/util/dso.h3
-rw-r--r--tools/perf/util/event.c1
-rw-r--r--tools/perf/util/event.h12
-rw-r--r--tools/perf/util/evlist.c16
-rw-r--r--tools/perf/util/evlist.h14
-rw-r--r--tools/perf/util/evsel.c240
-rw-r--r--tools/perf/util/evsel.h13
-rw-r--r--tools/perf/util/expr.h2
-rw-r--r--tools/perf/util/expr.y76
-rw-r--r--tools/perf/util/header.c1018
-rw-r--r--tools/perf/util/header.h16
-rw-r--r--tools/perf/util/hist.c11
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/intel-pt-decoder/Build2
-rw-r--r--tools/perf/util/llvm-utils.c2
-rw-r--r--tools/perf/util/machine.c130
-rw-r--r--tools/perf/util/map.c23
-rw-r--r--tools/perf/util/map.h2
-rw-r--r--tools/perf/util/mem-events.c54
-rw-r--r--tools/perf/util/namespaces.c211
-rw-r--r--tools/perf/util/namespaces.h38
-rw-r--r--tools/perf/util/parse-branch-options.c1
-rw-r--r--tools/perf/util/parse-events.c116
-rw-r--r--tools/perf/util/parse-events.h19
-rw-r--r--tools/perf/util/parse-events.l23
-rw-r--r--tools/perf/util/parse-events.y94
-rw-r--r--tools/perf/util/probe-event.c88
-rw-r--r--tools/perf/util/probe-event.h10
-rw-r--r--tools/perf/util/probe-file.c19
-rw-r--r--tools/perf/util/probe-file.h4
-rw-r--r--tools/perf/util/python-ext-sources1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c246
-rw-r--r--tools/perf/util/session.c32
-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.c44
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/srcline.c6
-rw-r--r--tools/perf/util/stat-shadow.c6
-rw-r--r--tools/perf/util/stat.c4
-rw-r--r--tools/perf/util/stat.h5
-rw-r--r--tools/perf/util/symbol-elf.c39
-rw-r--r--tools/perf/util/symbol-minimal.c2
-rw-r--r--tools/perf/util/symbol.c113
-rw-r--r--tools/perf/util/symbol.h8
-rw-r--r--tools/perf/util/syscalltbl.c33
-rw-r--r--tools/perf/util/syscalltbl.h3
-rw-r--r--tools/perf/util/thread.c3
-rw-r--r--tools/perf/util/thread.h1
-rw-r--r--tools/perf/util/tool.h10
-rw-r--r--tools/perf/util/util.c40
-rw-r--r--tools/perf/util/util.h8
-rw-r--r--tools/perf/util/values.c17
-rw-r--r--tools/perf/util/xyarray.c2
-rw-r--r--tools/perf/util/xyarray.h12
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslinuxtbl.c105
-rw-r--r--tools/power/acpi/tools/acpidump/apfiles.c2
-rw-r--r--tools/power/acpi/tools/acpidump/apmain.c2
-rw-r--r--tools/power/cpupower/Makefile2
-rw-r--r--tools/power/cpupower/utils/cpupower.c15
-rw-r--r--tools/power/cpupower/utils/helpers/cpuid.c4
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h5
-rw-r--r--tools/power/cpupower/utils/helpers/misc.c2
-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
-rw-r--r--tools/power/pm-graph/Makefile19
-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/scripts/Makefile.include10
-rw-r--r--tools/spi/Build2
-rw-r--r--tools/spi/Makefile64
-rw-r--r--tools/testing/nvdimm/test/nfit.c4
-rw-r--r--tools/testing/selftests/bpf/Makefile4
-rw-r--r--tools/testing/selftests/bpf/bpf_helpers.h9
-rw-r--r--tools/testing/selftests/bpf/sockmap_parse_prog.c38
-rw-r--r--tools/testing/selftests/bpf/sockmap_verdict_prog.c68
-rw-r--r--tools/testing/selftests/bpf/test_align.c464
-rw-r--r--tools/testing/selftests/bpf/test_maps.c442
-rw-r--r--tools/testing/selftests/bpf/test_pkt_md_access.c11
-rw-r--r--tools/testing/selftests/bpf/test_progs.c79
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c1391
-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/breakpoint_test.c4
-rw-r--r--tools/testing/selftests/capabilities/test_execve.c193
-rw-r--r--tools/testing/selftests/capabilities/validate_cap.c24
-rwxr-xr-xtools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh14
-rwxr-xr-xtools/testing/selftests/firmware/fw_fallback.sh31
-rwxr-xr-xtools/testing/selftests/firmware/fw_filesystem.sh241
-rwxr-xr-xtools/testing/selftests/ftrace/ftracetest51
-rw-r--r--tools/testing/selftests/futex/Makefile2
-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/kcmp/kcmp_test.c60
-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.mk17
-rw-r--r--tools/testing/selftests/memfd/Makefile2
-rw-r--r--tools/testing/selftests/memfd/fuse_test.c2
-rw-r--r--tools/testing/selftests/memfd/memfd_test.c372
-rw-r--r--tools/testing/selftests/memfd/run_tests.sh69
-rw-r--r--tools/testing/selftests/net/.gitignore1
-rw-r--r--tools/testing/selftests/net/Makefile4
-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/rtnetlink.sh272
-rw-r--r--tools/testing/selftests/networking/timestamping/.gitignore1
-rw-r--r--tools/testing/selftests/networking/timestamping/Makefile4
-rw-r--r--tools/testing/selftests/networking/timestamping/rxtimestamp.c389
-rw-r--r--tools/testing/selftests/nsfs/config3
-rwxr-xr-xtools/testing/selftests/ntb/ntb_test.sh4
-rw-r--r--tools/testing/selftests/powerpc/ptrace/Makefile2
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S2
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-resched-dscr.c12
-rw-r--r--tools/testing/selftests/pstore/.gitignore2
-rw-r--r--tools/testing/selftests/ptp/Makefile1
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/config_override.sh61
-rw-r--r--tools/testing/selftests/rcutorture/bin/functions.sh27
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-build.sh11
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh58
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh34
-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/seccomp/seccomp_bpf.c2
-rw-r--r--tools/testing/selftests/sigaltstack/sas.c53
-rw-r--r--tools/testing/selftests/splice/.gitignore1
-rw-r--r--tools/testing/selftests/splice/Makefile5
-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/tc-tests/actions/tests.json50
-rw-r--r--tools/testing/selftests/timers/Makefile23
-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.c114
-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
-rw-r--r--tools/testing/selftests/vm/userfaultfd.c279
-rw-r--r--tools/testing/selftests/watchdog/watchdog-test.c190
-rw-r--r--tools/testing/selftests/x86/fsgsbase.c41
-rw-r--r--tools/testing/selftests/x86/mpx-mini-test.c3
-rw-r--r--tools/testing/selftests/x86/protection_keys.c13
-rw-r--r--tools/usb/usbip/src/usbip_attach.c35
452 files changed, 30678 insertions, 7492 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 221e1ce78b06..9dfede37c8ff 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -18,7 +18,6 @@ help:
18 @echo ' iio - IIO tools' 18 @echo ' iio - IIO tools'
19 @echo ' kvm_stat - top-like utility for displaying kvm statistics' 19 @echo ' kvm_stat - top-like utility for displaying kvm statistics'
20 @echo ' leds - LEDs tools' 20 @echo ' leds - LEDs tools'
21 @echo ' lguest - a minimal 32-bit x86 hypervisor'
22 @echo ' liblockdep - user-space wrapper for kernel locking-validator' 21 @echo ' liblockdep - user-space wrapper for kernel locking-validator'
23 @echo ' net - misc networking tools' 22 @echo ' net - misc networking tools'
24 @echo ' perf - Linux performance measurement and analysis tool' 23 @echo ' perf - Linux performance measurement and analysis tool'
@@ -90,10 +89,10 @@ freefall: FORCE
90kvm_stat: FORCE 89kvm_stat: FORCE
91 $(call descend,kvm/$@) 90 $(call descend,kvm/$@)
92 91
93all: acpi cgroup cpupower gpio hv firewire lguest liblockdep \ 92all: acpi cgroup cpupower gpio hv firewire liblockdep \
94 perf selftests turbostat usb \ 93 perf selftests spi turbostat usb \
95 virtio vm net x86_energy_perf_policy \ 94 virtio vm net x86_energy_perf_policy \
96 tmon freefall objtool kvm_stat 95 tmon freefall iio objtool kvm_stat
97 96
98acpi_install: 97acpi_install:
99 $(call descend,power/$(@:_install=),install) 98 $(call descend,power/$(@:_install=),install)
@@ -101,7 +100,7 @@ acpi_install:
101cpupower_install: 100cpupower_install:
102 $(call descend,power/$(@:_install=),install) 101 $(call descend,power/$(@:_install=),install)
103 102
104cgroup_install firewire_install gpio_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install objtool_install: 103cgroup_install firewire_install gpio_install hv_install iio_install perf_install spi_install usb_install virtio_install vm_install net_install objtool_install:
105 $(call descend,$(@:_install=),install) 104 $(call descend,$(@:_install=),install)
106 105
107liblockdep_install: 106liblockdep_install:
@@ -123,7 +122,7 @@ kvm_stat_install:
123 $(call descend,kvm/$(@:_install=),install) 122 $(call descend,kvm/$(@:_install=),install)
124 123
125install: acpi_install cgroup_install cpupower_install gpio_install \ 124install: acpi_install cgroup_install cpupower_install gpio_install \
126 hv_install firewire_install lguest_install liblockdep_install \ 125 hv_install firewire_install iio_install liblockdep_install \
127 perf_install selftests_install turbostat_install usb_install \ 126 perf_install selftests_install turbostat_install usb_install \
128 virtio_install vm_install net_install x86_energy_perf_policy_install \ 127 virtio_install vm_install net_install x86_energy_perf_policy_install \
129 tmon_install freefall_install objtool_install kvm_stat_install 128 tmon_install freefall_install objtool_install kvm_stat_install
@@ -134,7 +133,7 @@ acpi_clean:
134cpupower_clean: 133cpupower_clean:
135 $(call descend,power/cpupower,clean) 134 $(call descend,power/cpupower,clean)
136 135
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: 136cgroup_clean hv_clean firewire_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean gpio_clean objtool_clean leds_clean:
138 $(call descend,$(@:_clean=),clean) 137 $(call descend,$(@:_clean=),clean)
139 138
140liblockdep_clean: 139liblockdep_clean:
@@ -168,7 +167,7 @@ freefall_clean:
168build_clean: 167build_clean:
169 $(call descend,build,clean) 168 $(call descend,build,clean)
170 169
171clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_clean \ 170clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean \
172 perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \ 171 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 \ 172 vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
174 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \ 173 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \
diff --git a/tools/arch/arm/include/uapi/asm/kvm.h b/tools/arch/arm/include/uapi/asm/kvm.h
index 5e3c673fa3f4..5db2d4c6a55f 100644
--- a/tools/arch/arm/include/uapi/asm/kvm.h
+++ b/tools/arch/arm/include/uapi/asm/kvm.h
@@ -203,6 +203,14 @@ struct kvm_arch_memory_slot {
203#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff 203#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
204#define VGIC_LEVEL_INFO_LINE_LEVEL 0 204#define VGIC_LEVEL_INFO_LINE_LEVEL 0
205 205
206/* Device Control API on vcpu fd */
207#define KVM_ARM_VCPU_PMU_V3_CTRL 0
208#define KVM_ARM_VCPU_PMU_V3_IRQ 0
209#define KVM_ARM_VCPU_PMU_V3_INIT 1
210#define KVM_ARM_VCPU_TIMER_CTRL 1
211#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
212#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
213
206#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 214#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
207#define KVM_DEV_ARM_ITS_SAVE_TABLES 1 215#define KVM_DEV_ARM_ITS_SAVE_TABLES 1
208#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 216#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2
diff --git a/tools/arch/arm64/include/uapi/asm/kvm.h b/tools/arch/arm64/include/uapi/asm/kvm.h
index 70eea2ecc663..9f3ca24bbcc6 100644
--- a/tools/arch/arm64/include/uapi/asm/kvm.h
+++ b/tools/arch/arm64/include/uapi/asm/kvm.h
@@ -232,6 +232,9 @@ struct kvm_arch_memory_slot {
232#define KVM_ARM_VCPU_PMU_V3_CTRL 0 232#define KVM_ARM_VCPU_PMU_V3_CTRL 0
233#define KVM_ARM_VCPU_PMU_V3_IRQ 0 233#define KVM_ARM_VCPU_PMU_V3_IRQ 0
234#define KVM_ARM_VCPU_PMU_V3_INIT 1 234#define KVM_ARM_VCPU_PMU_V3_INIT 1
235#define KVM_ARM_VCPU_TIMER_CTRL 1
236#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
237#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
235 238
236/* KVM_IRQ_LINE irq field index values */ 239/* KVM_IRQ_LINE irq field index values */
237#define KVM_ARM_IRQ_TYPE_SHIFT 24 240#define KVM_ARM_IRQ_TYPE_SHIFT 24
diff --git a/tools/arch/parisc/include/uapi/asm/mman.h b/tools/arch/parisc/include/uapi/asm/mman.h
index 03d8d5b7ae7f..286c0bd74573 100644
--- a/tools/arch/parisc/include/uapi/asm/mman.h
+++ b/tools/arch/parisc/include/uapi/asm/mman.h
@@ -36,9 +36,7 @@
36#define PROT_READ 0x1 36#define PROT_READ 0x1
37#define PROT_SEM 0x8 37#define PROT_SEM 0x8
38#define PROT_WRITE 0x2 38#define PROT_WRITE 0x2
39/* MADV_HWPOISON is undefined on parisc, fix it for perf */
40#define MADV_HWPOISON 100 39#define MADV_HWPOISON 100
41/* MADV_SOFT_OFFLINE is undefined on parisc, fix it for perf */
42#define MADV_SOFT_OFFLINE 101 40#define MADV_SOFT_OFFLINE 101
43/* MAP_32BIT is undefined on parisc, fix it for perf */ 41/* MAP_32BIT is undefined on parisc, fix it for perf */
44#define MAP_32BIT 0 42#define MAP_32BIT 0
diff --git a/tools/arch/powerpc/include/uapi/asm/kvm.h b/tools/arch/powerpc/include/uapi/asm/kvm.h
index 07fbeb927834..8cf8f0c96906 100644
--- a/tools/arch/powerpc/include/uapi/asm/kvm.h
+++ b/tools/arch/powerpc/include/uapi/asm/kvm.h
@@ -60,6 +60,12 @@ struct kvm_regs {
60 60
61#define KVM_SREGS_E_FSL_PIDn (1 << 0) /* PID1/PID2 */ 61#define KVM_SREGS_E_FSL_PIDn (1 << 0) /* PID1/PID2 */
62 62
63/* flags for kvm_run.flags */
64#define KVM_RUN_PPC_NMI_DISP_MASK (3 << 0)
65#define KVM_RUN_PPC_NMI_DISP_FULLY_RECOV (1 << 0)
66#define KVM_RUN_PPC_NMI_DISP_LIMITED_RECOV (2 << 0)
67#define KVM_RUN_PPC_NMI_DISP_NOT_RECOV (3 << 0)
68
63/* 69/*
64 * Feature bits indicate which sections of the sregs struct are valid, 70 * 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 71 * both in KVM_GET_SREGS and KVM_SET_SREGS. On KVM_SET_SREGS, registers
diff --git a/tools/arch/s390/include/uapi/asm/kvm.h b/tools/arch/s390/include/uapi/asm/kvm.h
index 3dd2a1d308dd..69d09c39bbcd 100644
--- a/tools/arch/s390/include/uapi/asm/kvm.h
+++ b/tools/arch/s390/include/uapi/asm/kvm.h
@@ -28,6 +28,7 @@
28#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8 28#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8
29#define KVM_DEV_FLIC_AISM 9 29#define KVM_DEV_FLIC_AISM 9
30#define KVM_DEV_FLIC_AIRQ_INJECT 10 30#define KVM_DEV_FLIC_AIRQ_INJECT 10
31#define KVM_DEV_FLIC_AISM_ALL 11
31/* 32/*
32 * We can have up to 4*64k pending subchannels + 8 adapter interrupts, 33 * 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. 34 * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
@@ -53,6 +54,11 @@ struct kvm_s390_ais_req {
53 __u16 mode; 54 __u16 mode;
54}; 55};
55 56
57struct kvm_s390_ais_all {
58 __u8 simm;
59 __u8 nimm;
60};
61
56#define KVM_S390_IO_ADAPTER_MASK 1 62#define KVM_S390_IO_ADAPTER_MASK 1
57#define KVM_S390_IO_ADAPTER_MAP 2 63#define KVM_S390_IO_ADAPTER_MAP 2
58#define KVM_S390_IO_ADAPTER_UNMAP 3 64#define KVM_S390_IO_ADAPTER_UNMAP 3
@@ -70,6 +76,7 @@ struct kvm_s390_io_adapter_req {
70#define KVM_S390_VM_TOD 1 76#define KVM_S390_VM_TOD 1
71#define KVM_S390_VM_CRYPTO 2 77#define KVM_S390_VM_CRYPTO 2
72#define KVM_S390_VM_CPU_MODEL 3 78#define KVM_S390_VM_CPU_MODEL 3
79#define KVM_S390_VM_MIGRATION 4
73 80
74/* kvm attributes for mem_ctrl */ 81/* kvm attributes for mem_ctrl */
75#define KVM_S390_VM_MEM_ENABLE_CMMA 0 82#define KVM_S390_VM_MEM_ENABLE_CMMA 0
@@ -151,6 +158,11 @@ struct kvm_s390_vm_cpu_subfunc {
151#define KVM_S390_VM_CRYPTO_DISABLE_AES_KW 2 158#define KVM_S390_VM_CRYPTO_DISABLE_AES_KW 2
152#define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW 3 159#define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW 3
153 160
161/* kvm attributes for migration mode */
162#define KVM_S390_VM_MIGRATION_STOP 0
163#define KVM_S390_VM_MIGRATION_START 1
164#define KVM_S390_VM_MIGRATION_STATUS 2
165
154/* for KVM_GET_REGS and KVM_SET_REGS */ 166/* for KVM_GET_REGS and KVM_SET_REGS */
155struct kvm_regs { 167struct kvm_regs {
156 /* general purpose regs for s390 */ 168 /* general purpose regs for s390 */
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index 2701e5f8145b..8ea315a11fe0 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -177,7 +177,7 @@
177#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */ 177#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */
178#define X86_FEATURE_BPEXT (6*32+26) /* data breakpoint extension */ 178#define X86_FEATURE_BPEXT (6*32+26) /* data breakpoint extension */
179#define X86_FEATURE_PTSC ( 6*32+27) /* performance time-stamp counter */ 179#define X86_FEATURE_PTSC ( 6*32+27) /* performance time-stamp counter */
180#define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */ 180#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) */ 181#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */
182 182
183/* 183/*
@@ -286,6 +286,7 @@
286#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */ 286#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */
287#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */ 287#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */
288#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */ 288#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */
289#define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* Virtual VMSAVE VMLOAD */
289 290
290/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */ 291/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
291#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/ 292#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
diff --git a/tools/arch/x86/include/asm/unistd_32.h b/tools/arch/x86/include/asm/unistd_32.h
index 88b3f8c8920c..0e4312ffc945 100644
--- a/tools/arch/x86/include/asm/unistd_32.h
+++ b/tools/arch/x86/include/asm/unistd_32.h
@@ -10,3 +10,6 @@
10#ifndef __NR_getcpu 10#ifndef __NR_getcpu
11# define __NR_getcpu 318 11# define __NR_getcpu 318
12#endif 12#endif
13#ifndef __NR_setns
14# define __NR_setns 346
15#endif
diff --git a/tools/arch/x86/include/asm/unistd_64.h b/tools/arch/x86/include/asm/unistd_64.h
index fbdb70ee8837..dd56bb36132a 100644
--- a/tools/arch/x86/include/asm/unistd_64.h
+++ b/tools/arch/x86/include/asm/unistd_64.h
@@ -10,3 +10,6 @@
10#ifndef __NR_getcpu 10#ifndef __NR_getcpu
11# define __NR_getcpu 309 11# define __NR_getcpu 309
12#endif 12#endif
13#ifndef __NR_setns
14#define __NR_setns 308
15#endif
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..a26df0d75cd0
--- /dev/null
+++ b/tools/arch/x86/include/uapi/asm/unistd.h
@@ -0,0 +1,17 @@
1#ifndef _UAPI_ASM_X86_UNISTD_H
2#define _UAPI_ASM_X86_UNISTD_H
3
4/* x32 syscall flag bit */
5#define __X32_SYSCALL_BIT 0x40000000
6
7#ifndef __KERNEL__
8# ifdef __i386__
9# include <asm/unistd_32.h>
10# elif defined(__ILP32__)
11# include <asm/unistd_x32.h>
12# else
13# include <asm/unistd_64.h>
14# endif
15#endif
16
17#endif /* _UAPI_ASM_X86_UNISTD_H */
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..ee2546ddf028 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -49,7 +49,8 @@ FILES= \
49 test-sdt.bin \ 49 test-sdt.bin \
50 test-cxx.bin \ 50 test-cxx.bin \
51 test-jvmti.bin \ 51 test-jvmti.bin \
52 test-sched_getcpu.bin 52 test-sched_getcpu.bin \
53 test-setns.bin
53 54
54FILES := $(addprefix $(OUTPUT),$(FILES)) 55FILES := $(addprefix $(OUTPUT),$(FILES))
55 56
@@ -95,6 +96,9 @@ $(OUTPUT)test-glibc.bin:
95$(OUTPUT)test-sched_getcpu.bin: 96$(OUTPUT)test-sched_getcpu.bin:
96 $(BUILD) 97 $(BUILD)
97 98
99$(OUTPUT)test-setns.bin:
100 $(BUILD)
101
98DWARFLIBS := -ldw 102DWARFLIBS := -ldw
99ifeq ($(findstring -static,${LDFLAGS}),-static) 103ifeq ($(findstring -static,${LDFLAGS}),-static)
100DWARFLIBS += -lelf -lebl -lz -llzma -lbz2 104DWARFLIBS += -lelf -lebl -lz -llzma -lbz2
diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c
index cc6c7c01f4ca..b5cfc6445771 100644
--- a/tools/build/feature/test-all.c
+++ b/tools/build/feature/test-all.c
@@ -153,6 +153,10 @@
153# include "test-sdt.c" 153# include "test-sdt.c"
154#undef main 154#undef main
155 155
156#define main main_test_setns
157# include "test-setns.c"
158#undef main
159
156int main(int argc, char *argv[]) 160int main(int argc, char *argv[])
157{ 161{
158 main_test_libpython(); 162 main_test_libpython();
@@ -188,6 +192,7 @@ int main(int argc, char *argv[])
188 main_test_libcrypto(); 192 main_test_libcrypto();
189 main_test_sched_getcpu(); 193 main_test_sched_getcpu();
190 main_test_sdt(); 194 main_test_sdt();
195 main_test_setns();
191 196
192 return 0; 197 return 0;
193} 198}
diff --git a/tools/build/feature/test-bpf.c b/tools/build/feature/test-bpf.c
index 7598361ef1f1..da2172ff9662 100644
--- a/tools/build/feature/test-bpf.c
+++ b/tools/build/feature/test-bpf.c
@@ -11,6 +11,8 @@
11# define __NR_bpf 280 11# define __NR_bpf 280
12# elif defined(__sparc__) 12# elif defined(__sparc__)
13# define __NR_bpf 349 13# define __NR_bpf 349
14# elif defined(__s390__)
15# define __NR_bpf 351
14# else 16# else
15# error __NR_bpf not defined. libbpf does not support your arch. 17# error __NR_bpf not defined. libbpf does not support your arch.
16# endif 18# endif
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/tests/ex/Makefile b/tools/build/tests/ex/Makefile
index c50d5782ad5a..027d6c8a58a7 100644
--- a/tools/build/tests/ex/Makefile
+++ b/tools/build/tests/ex/Makefile
@@ -8,7 +8,7 @@ ex:
8include $(srctree)/tools/build/Makefile.include 8include $(srctree)/tools/build/Makefile.include
9 9
10ex: ex-in.o libex-in.o 10ex: ex-in.o libex-in.o
11 gcc -o $@ $^ 11 $(CC) -o $@ $^
12 12
13ex.%: fixdep FORCE 13ex.%: fixdep FORCE
14 make -f $(srctree)/tools/build/Makefile.build dir=. $@ 14 make -f $(srctree)/tools/build/Makefile.build dir=. $@
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_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_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/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..d4d956020adf 100644
--- a/tools/iio/Makefile
+++ b/tools/iio/Makefile
@@ -1,31 +1,67 @@
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
2CFLAGS += -Wall -g -D_GNU_SOURCE -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include 15LD = $(CROSS_COMPILE)ld
16CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
3 17
4BINDIR=usr/bin 18ALL_TARGETS := iio_event_monitor lsiio iio_generic_buffer
5INSTALL_PROGRAM=install -m 755 -p 19ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
6DEL_FILE=rm -f
7 20
8all: iio_event_monitor lsiio iio_generic_buffer 21all: $(ALL_PROGRAMS)
9 22
10iio_event_monitor: iio_event_monitor.o iio_utils.o 23export srctree OUTPUT CC LD CFLAGS
24include $(srctree)/tools/build/Makefile.include
11 25
12lsiio: lsiio.o iio_utils.o 26#
27# We need the following to be outside of kernel tree
28#
29$(OUTPUT)include/linux/iio: ../../include/uapi/linux/iio
30 mkdir -p $(OUTPUT)include/linux/iio 2>&1 || true
31 ln -sf $(CURDIR)/../../include/uapi/linux/iio/events.h $@
32 ln -sf $(CURDIR)/../../include/uapi/linux/iio/types.h $@
13 33
14iio_generic_buffer: iio_generic_buffer.o iio_utils.o 34prepare: $(OUTPUT)include/linux/iio
15 35
16%.o: %.c iio_utils.h 36LSIIO_IN := $(OUTPUT)lsiio-in.o
37$(LSIIO_IN): prepare FORCE
38 $(Q)$(MAKE) $(build)=lsiio
39$(OUTPUT)lsiio: $(LSIIO_IN)
40 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
17 41
18install: 42IIO_EVENT_MONITOR_IN := $(OUTPUT)iio_event_monitor-in.o
19 - mkdir -p $(INSTALL_ROOT)/$(BINDIR) 43$(IIO_EVENT_MONITOR_IN): prepare FORCE
20 - $(INSTALL_PROGRAM) "iio_event_monitor" "$(INSTALL_ROOT)/$(BINDIR)/iio_event_monitor" 44 $(Q)$(MAKE) $(build)=iio_event_monitor
21 - $(INSTALL_PROGRAM) "lsiio" "$(INSTALL_ROOT)/$(BINDIR)/lsiio" 45$(OUTPUT)iio_event_monitor: $(IIO_EVENT_MONITOR_IN)
22 - $(INSTALL_PROGRAM) "iio_generic_buffer" "$(INSTALL_ROOT)/$(BINDIR)/iio_generic_buffer" 46 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
23 47
24uninstall: 48IIO_GENERIC_BUFFER_IN := $(OUTPUT)iio_generic_buffer-in.o
25 $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/iio_event_monitor" 49$(IIO_GENERIC_BUFFER_IN): prepare FORCE
26 $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/lsiio" 50 $(Q)$(MAKE) $(build)=iio_generic_buffer
27 $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/iio_generic_buffer" 51$(OUTPUT)iio_generic_buffer: $(IIO_GENERIC_BUFFER_IN)
52 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
28 53
29.PHONY: clean
30clean: 54clean:
31 rm -f *.o iio_event_monitor lsiio iio_generic_buffer 55 rm -f $(ALL_PROGRAMS)
56 rm -rf $(OUTPUT)include/linux/iio
57 find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete
58
59install: $(ALL_PROGRAMS)
60 install -d -m 755 $(DESTDIR)$(bindir); \
61 for program in $(ALL_PROGRAMS); do \
62 install $$program $(DESTDIR)$(bindir); \
63 done
64
65FORCE:
66
67.PHONY: all install clean FORCE prepare
diff --git a/tools/include/linux/compiler-gcc.h b/tools/include/linux/compiler-gcc.h
index bd39b2090ad1..3723b9f8f964 100644
--- a/tools/include/linux/compiler-gcc.h
+++ b/tools/include/linux/compiler-gcc.h
@@ -21,11 +21,14 @@
21#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) 21#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
22 22
23#define noinline __attribute__((noinline)) 23#define noinline __attribute__((noinline))
24 24#ifndef __packed
25#define __packed __attribute__((packed)) 25#define __packed __attribute__((packed))
26 26#endif
27#ifndef __noreturn
27#define __noreturn __attribute__((noreturn)) 28#define __noreturn __attribute__((noreturn))
28 29#endif
30#ifndef __aligned
29#define __aligned(x) __attribute__((aligned(x))) 31#define __aligned(x) __attribute__((aligned(x)))
32#endif
30#define __printf(a, b) __attribute__((format(printf, a, b))) 33#define __printf(a, b) __attribute__((format(printf, a, b)))
31#define __scanf(a, b) __attribute__((format(scanf, a, b))) 34#define __scanf(a, b) __attribute__((format(scanf, a, b)))
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/string.h b/tools/include/linux/string.h
index d62b56cf8c12..a30fad536f52 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -1,8 +1,8 @@
1#ifndef _TOOLS_LINUX_STRING_H_ 1#ifndef _TOOLS_LINUX_STRING_H_
2#define _TOOLS_LINUX_STRING_H_ 2#define _TOOLS_LINUX_STRING_H_
3 3
4
5#include <linux/types.h> /* for size_t */ 4#include <linux/types.h> /* for size_t */
5#include <string.h>
6 6
7void *memdup(const void *src, size_t len); 7void *memdup(const void *src, size_t len);
8 8
@@ -18,6 +18,14 @@ extern size_t strlcpy(char *dest, const char *src, size_t size);
18 18
19char *str_error_r(int errnum, char *buf, size_t buflen); 19char *str_error_r(int errnum, char *buf, size_t buflen);
20 20
21int prefixcmp(const char *str, const char *prefix); 21/**
22 * strstarts - does @str start with @prefix?
23 * @str: string to examine
24 * @prefix: prefix to look for.
25 */
26static inline bool strstarts(const char *str, const char *prefix)
27{
28 return strncmp(str, prefix, strlen(prefix)) == 0;
29}
22 30
23#endif /* _LINUX_STRING_H_ */ 31#endif /* _LINUX_STRING_H_ */
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..14baf9f23a14
--- /dev/null
+++ b/tools/include/uapi/asm-generic/ioctls.h
@@ -0,0 +1,118 @@
1#ifndef __ASM_GENERIC_IOCTLS_H
2#define __ASM_GENERIC_IOCTLS_H
3
4#include <linux/ioctl.h>
5
6/*
7 * These are the most common definitions for tty ioctl numbers.
8 * Most of them do not use the recommended _IOC(), but there is
9 * probably some source code out there hardcoding the number,
10 * so we might as well use them for all new platforms.
11 *
12 * The architectures that use different values here typically
13 * try to be compatible with some Unix variants for the same
14 * architecture.
15 */
16
17/* 0x54 is just a magic number to make these relatively unique ('T') */
18
19#define TCGETS 0x5401
20#define TCSETS 0x5402
21#define TCSETSW 0x5403
22#define TCSETSF 0x5404
23#define TCGETA 0x5405
24#define TCSETA 0x5406
25#define TCSETAW 0x5407
26#define TCSETAF 0x5408
27#define TCSBRK 0x5409
28#define TCXONC 0x540A
29#define TCFLSH 0x540B
30#define TIOCEXCL 0x540C
31#define TIOCNXCL 0x540D
32#define TIOCSCTTY 0x540E
33#define TIOCGPGRP 0x540F
34#define TIOCSPGRP 0x5410
35#define TIOCOUTQ 0x5411
36#define TIOCSTI 0x5412
37#define TIOCGWINSZ 0x5413
38#define TIOCSWINSZ 0x5414
39#define TIOCMGET 0x5415
40#define TIOCMBIS 0x5416
41#define TIOCMBIC 0x5417
42#define TIOCMSET 0x5418
43#define TIOCGSOFTCAR 0x5419
44#define TIOCSSOFTCAR 0x541A
45#define FIONREAD 0x541B
46#define TIOCINQ FIONREAD
47#define TIOCLINUX 0x541C
48#define TIOCCONS 0x541D
49#define TIOCGSERIAL 0x541E
50#define TIOCSSERIAL 0x541F
51#define TIOCPKT 0x5420
52#define FIONBIO 0x5421
53#define TIOCNOTTY 0x5422
54#define TIOCSETD 0x5423
55#define TIOCGETD 0x5424
56#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
57#define TIOCSBRK 0x5427 /* BSD compatibility */
58#define TIOCCBRK 0x5428 /* BSD compatibility */
59#define TIOCGSID 0x5429 /* Return the session ID of FD */
60#define TCGETS2 _IOR('T', 0x2A, struct termios2)
61#define TCSETS2 _IOW('T', 0x2B, struct termios2)
62#define TCSETSW2 _IOW('T', 0x2C, struct termios2)
63#define TCSETSF2 _IOW('T', 0x2D, struct termios2)
64#define TIOCGRS485 0x542E
65#ifndef TIOCSRS485
66#define TIOCSRS485 0x542F
67#endif
68#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
69#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
70#define TIOCGDEV _IOR('T', 0x32, unsigned int) /* Get primary device node of /dev/console */
71#define TCGETX 0x5432 /* SYS5 TCGETX compatibility */
72#define TCSETX 0x5433
73#define TCSETXF 0x5434
74#define TCSETXW 0x5435
75#define TIOCSIG _IOW('T', 0x36, int) /* pty: generate signal */
76#define TIOCVHANGUP 0x5437
77#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */
78#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */
79#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */
80#define TIOCGPTPEER _IO('T', 0x41) /* Safely open the slave */
81
82#define FIONCLEX 0x5450
83#define FIOCLEX 0x5451
84#define FIOASYNC 0x5452
85#define TIOCSERCONFIG 0x5453
86#define TIOCSERGWILD 0x5454
87#define TIOCSERSWILD 0x5455
88#define TIOCGLCKTRMIOS 0x5456
89#define TIOCSLCKTRMIOS 0x5457
90#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
91#define TIOCSERGETLSR 0x5459 /* Get line status register */
92#define TIOCSERGETMULTI 0x545A /* Get multiport config */
93#define TIOCSERSETMULTI 0x545B /* Set multiport config */
94
95#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
96#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
97
98/*
99 * Some arches already define FIOQSIZE due to a historical
100 * conflict with a Hayes modem-specific ioctl value.
101 */
102#ifndef FIOQSIZE
103# define FIOQSIZE 0x5460
104#endif
105
106/* Used for packet mode */
107#define TIOCPKT_DATA 0
108#define TIOCPKT_FLUSHREAD 1
109#define TIOCPKT_FLUSHWRITE 2
110#define TIOCPKT_STOP 4
111#define TIOCPKT_START 8
112#define TIOCPKT_NOSTOP 16
113#define TIOCPKT_DOSTOP 32
114#define TIOCPKT_IOCTL 64
115
116#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
117
118#endif /* __ASM_GENERIC_IOCTLS_H */
diff --git a/tools/include/uapi/drm/drm.h b/tools/include/uapi/drm/drm.h
new file mode 100644
index 000000000000..101593ab10ac
--- /dev/null
+++ b/tools/include/uapi/drm/drm.h
@@ -0,0 +1,933 @@
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 __u32 flags;
704};
705
706struct drm_syncobj_destroy {
707 __u32 handle;
708 __u32 pad;
709};
710
711#define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE (1 << 0)
712#define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE (1 << 0)
713struct drm_syncobj_handle {
714 __u32 handle;
715 __u32 flags;
716
717 __s32 fd;
718 __u32 pad;
719};
720
721#if defined(__cplusplus)
722}
723#endif
724
725#include "drm_mode.h"
726
727#if defined(__cplusplus)
728extern "C" {
729#endif
730
731#define DRM_IOCTL_BASE 'd'
732#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
733#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
734#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type)
735#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type)
736
737#define DRM_IOCTL_VERSION DRM_IOWR(0x00, struct drm_version)
738#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, struct drm_unique)
739#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, struct drm_auth)
740#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, struct drm_irq_busid)
741#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, struct drm_map)
742#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client)
743#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats)
744#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version)
745#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl)
746#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close)
747#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink)
748#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open)
749#define DRM_IOCTL_GET_CAP DRM_IOWR(0x0c, struct drm_get_cap)
750#define DRM_IOCTL_SET_CLIENT_CAP DRM_IOW( 0x0d, struct drm_set_client_cap)
751
752#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique)
753#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth)
754#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, struct drm_block)
755#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, struct drm_block)
756#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, struct drm_control)
757#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, struct drm_map)
758#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, struct drm_buf_desc)
759#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, struct drm_buf_desc)
760#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, struct drm_buf_info)
761#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, struct drm_buf_map)
762#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, struct drm_buf_free)
763
764#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, struct drm_map)
765
766#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map)
767#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map)
768
769#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e)
770#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f)
771
772#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx)
773#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx)
774#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx)
775#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, struct drm_ctx)
776#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, struct drm_ctx)
777#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, struct drm_ctx)
778#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, struct drm_ctx_res)
779#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, struct drm_draw)
780#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, struct drm_draw)
781#define DRM_IOCTL_DMA DRM_IOWR(0x29, struct drm_dma)
782#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, struct drm_lock)
783#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock)
784#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock)
785
786#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle)
787#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle)
788
789#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)
790#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31)
791#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, struct drm_agp_mode)
792#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, struct drm_agp_info)
793#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, struct drm_agp_buffer)
794#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, struct drm_agp_buffer)
795#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, struct drm_agp_binding)
796#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, struct drm_agp_binding)
797
798#define DRM_IOCTL_SG_ALLOC DRM_IOWR(0x38, struct drm_scatter_gather)
799#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, struct drm_scatter_gather)
800
801#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank)
802
803#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw)
804
805#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res)
806#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc)
807#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc)
808#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor)
809#define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut)
810#define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut)
811#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder)
812#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector)
813#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd) /* deprecated (never worked) */
814#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) /* deprecated (never worked) */
815
816#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property)
817#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property)
818#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob)
819#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
820#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
821#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int)
822#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)
823#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd)
824
825#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb)
826#define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB3, struct drm_mode_map_dumb)
827#define DRM_IOCTL_MODE_DESTROY_DUMB DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
828#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
829#define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane)
830#define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane)
831#define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
832#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
833#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property)
834#define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2)
835#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic)
836#define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct drm_mode_create_blob)
837#define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct drm_mode_destroy_blob)
838
839#define DRM_IOCTL_SYNCOBJ_CREATE DRM_IOWR(0xBF, struct drm_syncobj_create)
840#define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy)
841#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle)
842#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle)
843
844/**
845 * Device specific ioctls should only be in their respective headers
846 * The device specific ioctl range is from 0x40 to 0x9f.
847 * Generic IOCTLS restart at 0xA0.
848 *
849 * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
850 * drmCommandReadWrite().
851 */
852#define DRM_COMMAND_BASE 0x40
853#define DRM_COMMAND_END 0xA0
854
855/**
856 * Header for events written back to userspace on the drm fd. The
857 * type defines the type of event, the length specifies the total
858 * length of the event (including the header), and user_data is
859 * typically a 64 bit value passed with the ioctl that triggered the
860 * event. A read on the drm fd will always only return complete
861 * events, that is, if for example the read buffer is 100 bytes, and
862 * there are two 64 byte events pending, only one will be returned.
863 *
864 * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and
865 * up are chipset specific.
866 */
867struct drm_event {
868 __u32 type;
869 __u32 length;
870};
871
872#define DRM_EVENT_VBLANK 0x01
873#define DRM_EVENT_FLIP_COMPLETE 0x02
874
875struct drm_event_vblank {
876 struct drm_event base;
877 __u64 user_data;
878 __u32 tv_sec;
879 __u32 tv_usec;
880 __u32 sequence;
881 __u32 crtc_id; /* 0 on older kernels that do not support this */
882};
883
884/* typedef area */
885#ifndef __KERNEL__
886typedef struct drm_clip_rect drm_clip_rect_t;
887typedef struct drm_drawable_info drm_drawable_info_t;
888typedef struct drm_tex_region drm_tex_region_t;
889typedef struct drm_hw_lock drm_hw_lock_t;
890typedef struct drm_version drm_version_t;
891typedef struct drm_unique drm_unique_t;
892typedef struct drm_list drm_list_t;
893typedef struct drm_block drm_block_t;
894typedef struct drm_control drm_control_t;
895typedef enum drm_map_type drm_map_type_t;
896typedef enum drm_map_flags drm_map_flags_t;
897typedef struct drm_ctx_priv_map drm_ctx_priv_map_t;
898typedef struct drm_map drm_map_t;
899typedef struct drm_client drm_client_t;
900typedef enum drm_stat_type drm_stat_type_t;
901typedef struct drm_stats drm_stats_t;
902typedef enum drm_lock_flags drm_lock_flags_t;
903typedef struct drm_lock drm_lock_t;
904typedef enum drm_dma_flags drm_dma_flags_t;
905typedef struct drm_buf_desc drm_buf_desc_t;
906typedef struct drm_buf_info drm_buf_info_t;
907typedef struct drm_buf_free drm_buf_free_t;
908typedef struct drm_buf_pub drm_buf_pub_t;
909typedef struct drm_buf_map drm_buf_map_t;
910typedef struct drm_dma drm_dma_t;
911typedef union drm_wait_vblank drm_wait_vblank_t;
912typedef struct drm_agp_mode drm_agp_mode_t;
913typedef enum drm_ctx_flags drm_ctx_flags_t;
914typedef struct drm_ctx drm_ctx_t;
915typedef struct drm_ctx_res drm_ctx_res_t;
916typedef struct drm_draw drm_draw_t;
917typedef struct drm_update_draw drm_update_draw_t;
918typedef struct drm_auth drm_auth_t;
919typedef struct drm_irq_busid drm_irq_busid_t;
920typedef enum drm_vblank_seq_type drm_vblank_seq_type_t;
921
922typedef struct drm_agp_buffer drm_agp_buffer_t;
923typedef struct drm_agp_binding drm_agp_binding_t;
924typedef struct drm_agp_info drm_agp_info_t;
925typedef struct drm_scatter_gather drm_scatter_gather_t;
926typedef struct drm_set_version drm_set_version_t;
927#endif
928
929#if defined(__cplusplus)
930}
931#endif
932
933#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..7ccbd6a2bbe0
--- /dev/null
+++ b/tools/include/uapi/drm/i915_drm.h
@@ -0,0 +1,1474 @@
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
264#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
265#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
266#define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
267#define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
268#define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
269#define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
270#define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t)
271#define DRM_IOCTL_I915_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SETPARAM, drm_i915_setparam_t)
272#define DRM_IOCTL_I915_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_ALLOC, drm_i915_mem_alloc_t)
273#define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t)
274#define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t)
275#define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t)
276#define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
277#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
278#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
279#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
280#define DRM_IOCTL_I915_HWS_ADDR DRM_IOW(DRM_COMMAND_BASE + DRM_I915_HWS_ADDR, struct drm_i915_gem_init)
281#define DRM_IOCTL_I915_GEM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init)
282#define DRM_IOCTL_I915_GEM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer)
283#define DRM_IOCTL_I915_GEM_EXECBUFFER2 DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2)
284#define DRM_IOCTL_I915_GEM_EXECBUFFER2_WR DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2_WR, struct drm_i915_gem_execbuffer2)
285#define DRM_IOCTL_I915_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
286#define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
287#define DRM_IOCTL_I915_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
288#define DRM_IOCTL_I915_GEM_SET_CACHING DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_SET_CACHING, struct drm_i915_gem_caching)
289#define DRM_IOCTL_I915_GEM_GET_CACHING DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_GET_CACHING, struct drm_i915_gem_caching)
290#define DRM_IOCTL_I915_GEM_THROTTLE DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE)
291#define DRM_IOCTL_I915_GEM_ENTERVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT)
292#define DRM_IOCTL_I915_GEM_LEAVEVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT)
293#define DRM_IOCTL_I915_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create)
294#define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread)
295#define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite)
296#define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap)
297#define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt)
298#define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain)
299#define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish)
300#define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
301#define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling)
302#define DRM_IOCTL_I915_GEM_GET_APERTURE DRM_IOR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
303#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)
304#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
305#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image)
306#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
307#define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
308#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
309#define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait)
310#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
311#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
312#define DRM_IOCTL_I915_REG_READ DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
313#define DRM_IOCTL_I915_GET_RESET_STATS DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats)
314#define DRM_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_USERPTR, struct drm_i915_gem_userptr)
315#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
316#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
317#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
318
319/* Allow drivers to submit batchbuffers directly to hardware, relying
320 * on the security mechanisms provided by hardware.
321 */
322typedef struct drm_i915_batchbuffer {
323 int start; /* agp offset */
324 int used; /* nr bytes in use */
325 int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
326 int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
327 int num_cliprects; /* mulitpass with multiple cliprects? */
328 struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
329} drm_i915_batchbuffer_t;
330
331/* As above, but pass a pointer to userspace buffer which can be
332 * validated by the kernel prior to sending to hardware.
333 */
334typedef struct _drm_i915_cmdbuffer {
335 char __user *buf; /* pointer to userspace command buffer */
336 int sz; /* nr bytes in buf */
337 int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
338 int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
339 int num_cliprects; /* mulitpass with multiple cliprects? */
340 struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
341} drm_i915_cmdbuffer_t;
342
343/* Userspace can request & wait on irq's:
344 */
345typedef struct drm_i915_irq_emit {
346 int __user *irq_seq;
347} drm_i915_irq_emit_t;
348
349typedef struct drm_i915_irq_wait {
350 int irq_seq;
351} drm_i915_irq_wait_t;
352
353/* Ioctl to query kernel params:
354 */
355#define I915_PARAM_IRQ_ACTIVE 1
356#define I915_PARAM_ALLOW_BATCHBUFFER 2
357#define I915_PARAM_LAST_DISPATCH 3
358#define I915_PARAM_CHIPSET_ID 4
359#define I915_PARAM_HAS_GEM 5
360#define I915_PARAM_NUM_FENCES_AVAIL 6
361#define I915_PARAM_HAS_OVERLAY 7
362#define I915_PARAM_HAS_PAGEFLIPPING 8
363#define I915_PARAM_HAS_EXECBUF2 9
364#define I915_PARAM_HAS_BSD 10
365#define I915_PARAM_HAS_BLT 11
366#define I915_PARAM_HAS_RELAXED_FENCING 12
367#define I915_PARAM_HAS_COHERENT_RINGS 13
368#define I915_PARAM_HAS_EXEC_CONSTANTS 14
369#define I915_PARAM_HAS_RELAXED_DELTA 15
370#define I915_PARAM_HAS_GEN7_SOL_RESET 16
371#define I915_PARAM_HAS_LLC 17
372#define I915_PARAM_HAS_ALIASING_PPGTT 18
373#define I915_PARAM_HAS_WAIT_TIMEOUT 19
374#define I915_PARAM_HAS_SEMAPHORES 20
375#define I915_PARAM_HAS_PRIME_VMAP_FLUSH 21
376#define I915_PARAM_HAS_VEBOX 22
377#define I915_PARAM_HAS_SECURE_BATCHES 23
378#define I915_PARAM_HAS_PINNED_BATCHES 24
379#define I915_PARAM_HAS_EXEC_NO_RELOC 25
380#define I915_PARAM_HAS_EXEC_HANDLE_LUT 26
381#define I915_PARAM_HAS_WT 27
382#define I915_PARAM_CMD_PARSER_VERSION 28
383#define I915_PARAM_HAS_COHERENT_PHYS_GTT 29
384#define I915_PARAM_MMAP_VERSION 30
385#define I915_PARAM_HAS_BSD2 31
386#define I915_PARAM_REVISION 32
387#define I915_PARAM_SUBSLICE_TOTAL 33
388#define I915_PARAM_EU_TOTAL 34
389#define I915_PARAM_HAS_GPU_RESET 35
390#define I915_PARAM_HAS_RESOURCE_STREAMER 36
391#define I915_PARAM_HAS_EXEC_SOFTPIN 37
392#define I915_PARAM_HAS_POOLED_EU 38
393#define I915_PARAM_MIN_EU_IN_POOL 39
394#define I915_PARAM_MMAP_GTT_VERSION 40
395
396/* Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution
397 * priorities and the driver will attempt to execute batches in priority order.
398 */
399#define I915_PARAM_HAS_SCHEDULER 41
400#define I915_PARAM_HUC_STATUS 42
401
402/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to opt-out of
403 * synchronisation with implicit fencing on individual objects.
404 * See EXEC_OBJECT_ASYNC.
405 */
406#define I915_PARAM_HAS_EXEC_ASYNC 43
407
408/* Query whether DRM_I915_GEM_EXECBUFFER2 supports explicit fence support -
409 * both being able to pass in a sync_file fd to wait upon before executing,
410 * and being able to return a new sync_file fd that is signaled when the
411 * current request is complete. See I915_EXEC_FENCE_IN and I915_EXEC_FENCE_OUT.
412 */
413#define I915_PARAM_HAS_EXEC_FENCE 44
414
415/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to capture
416 * user specified bufffers for post-mortem debugging of GPU hangs. See
417 * EXEC_OBJECT_CAPTURE.
418 */
419#define I915_PARAM_HAS_EXEC_CAPTURE 45
420
421#define I915_PARAM_SLICE_MASK 46
422
423/* Assuming it's uniform for each slice, this queries the mask of subslices
424 * per-slice for this system.
425 */
426#define I915_PARAM_SUBSLICE_MASK 47
427
428/*
429 * Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying the batch buffer
430 * as the first execobject as opposed to the last. See I915_EXEC_BATCH_FIRST.
431 */
432#define I915_PARAM_HAS_EXEC_BATCH_FIRST 48
433
434typedef struct drm_i915_getparam {
435 __s32 param;
436 /*
437 * WARNING: Using pointers instead of fixed-size u64 means we need to write
438 * compat32 code. Don't repeat this mistake.
439 */
440 int __user *value;
441} drm_i915_getparam_t;
442
443/* Ioctl to set kernel params:
444 */
445#define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1
446#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2
447#define I915_SETPARAM_ALLOW_BATCHBUFFER 3
448#define I915_SETPARAM_NUM_USED_FENCES 4
449
450typedef struct drm_i915_setparam {
451 int param;
452 int value;
453} drm_i915_setparam_t;
454
455/* A memory manager for regions of shared memory:
456 */
457#define I915_MEM_REGION_AGP 1
458
459typedef struct drm_i915_mem_alloc {
460 int region;
461 int alignment;
462 int size;
463 int __user *region_offset; /* offset from start of fb or agp */
464} drm_i915_mem_alloc_t;
465
466typedef struct drm_i915_mem_free {
467 int region;
468 int region_offset;
469} drm_i915_mem_free_t;
470
471typedef struct drm_i915_mem_init_heap {
472 int region;
473 int size;
474 int start;
475} drm_i915_mem_init_heap_t;
476
477/* Allow memory manager to be torn down and re-initialized (eg on
478 * rotate):
479 */
480typedef struct drm_i915_mem_destroy_heap {
481 int region;
482} drm_i915_mem_destroy_heap_t;
483
484/* Allow X server to configure which pipes to monitor for vblank signals
485 */
486#define DRM_I915_VBLANK_PIPE_A 1
487#define DRM_I915_VBLANK_PIPE_B 2
488
489typedef struct drm_i915_vblank_pipe {
490 int pipe;
491} drm_i915_vblank_pipe_t;
492
493/* Schedule buffer swap at given vertical blank:
494 */
495typedef struct drm_i915_vblank_swap {
496 drm_drawable_t drawable;
497 enum drm_vblank_seq_type seqtype;
498 unsigned int sequence;
499} drm_i915_vblank_swap_t;
500
501typedef struct drm_i915_hws_addr {
502 __u64 addr;
503} drm_i915_hws_addr_t;
504
505struct drm_i915_gem_init {
506 /**
507 * Beginning offset in the GTT to be managed by the DRM memory
508 * manager.
509 */
510 __u64 gtt_start;
511 /**
512 * Ending offset in the GTT to be managed by the DRM memory
513 * manager.
514 */
515 __u64 gtt_end;
516};
517
518struct drm_i915_gem_create {
519 /**
520 * Requested size for the object.
521 *
522 * The (page-aligned) allocated size for the object will be returned.
523 */
524 __u64 size;
525 /**
526 * Returned handle for the object.
527 *
528 * Object handles are nonzero.
529 */
530 __u32 handle;
531 __u32 pad;
532};
533
534struct drm_i915_gem_pread {
535 /** Handle for the object being read. */
536 __u32 handle;
537 __u32 pad;
538 /** Offset into the object to read from */
539 __u64 offset;
540 /** Length of data to read */
541 __u64 size;
542 /**
543 * Pointer to write the data into.
544 *
545 * This is a fixed-size type for 32/64 compatibility.
546 */
547 __u64 data_ptr;
548};
549
550struct drm_i915_gem_pwrite {
551 /** Handle for the object being written to. */
552 __u32 handle;
553 __u32 pad;
554 /** Offset into the object to write to */
555 __u64 offset;
556 /** Length of data to write */
557 __u64 size;
558 /**
559 * Pointer to read the data from.
560 *
561 * This is a fixed-size type for 32/64 compatibility.
562 */
563 __u64 data_ptr;
564};
565
566struct drm_i915_gem_mmap {
567 /** Handle for the object being mapped. */
568 __u32 handle;
569 __u32 pad;
570 /** Offset in the object to map. */
571 __u64 offset;
572 /**
573 * Length of data to map.
574 *
575 * The value will be page-aligned.
576 */
577 __u64 size;
578 /**
579 * Returned pointer the data was mapped at.
580 *
581 * This is a fixed-size type for 32/64 compatibility.
582 */
583 __u64 addr_ptr;
584
585 /**
586 * Flags for extended behaviour.
587 *
588 * Added in version 2.
589 */
590 __u64 flags;
591#define I915_MMAP_WC 0x1
592};
593
594struct drm_i915_gem_mmap_gtt {
595 /** Handle for the object being mapped. */
596 __u32 handle;
597 __u32 pad;
598 /**
599 * Fake offset to use for subsequent mmap call
600 *
601 * This is a fixed-size type for 32/64 compatibility.
602 */
603 __u64 offset;
604};
605
606struct drm_i915_gem_set_domain {
607 /** Handle for the object */
608 __u32 handle;
609
610 /** New read domains */
611 __u32 read_domains;
612
613 /** New write domain */
614 __u32 write_domain;
615};
616
617struct drm_i915_gem_sw_finish {
618 /** Handle for the object */
619 __u32 handle;
620};
621
622struct drm_i915_gem_relocation_entry {
623 /**
624 * Handle of the buffer being pointed to by this relocation entry.
625 *
626 * It's appealing to make this be an index into the mm_validate_entry
627 * list to refer to the buffer, but this allows the driver to create
628 * a relocation list for state buffers and not re-write it per
629 * exec using the buffer.
630 */
631 __u32 target_handle;
632
633 /**
634 * Value to be added to the offset of the target buffer to make up
635 * the relocation entry.
636 */
637 __u32 delta;
638
639 /** Offset in the buffer the relocation entry will be written into */
640 __u64 offset;
641
642 /**
643 * Offset value of the target buffer that the relocation entry was last
644 * written as.
645 *
646 * If the buffer has the same offset as last time, we can skip syncing
647 * and writing the relocation. This value is written back out by
648 * the execbuffer ioctl when the relocation is written.
649 */
650 __u64 presumed_offset;
651
652 /**
653 * Target memory domains read by this operation.
654 */
655 __u32 read_domains;
656
657 /**
658 * Target memory domains written by this operation.
659 *
660 * Note that only one domain may be written by the whole
661 * execbuffer operation, so that where there are conflicts,
662 * the application will get -EINVAL back.
663 */
664 __u32 write_domain;
665};
666
667/** @{
668 * Intel memory domains
669 *
670 * Most of these just align with the various caches in
671 * the system and are used to flush and invalidate as
672 * objects end up cached in different domains.
673 */
674/** CPU cache */
675#define I915_GEM_DOMAIN_CPU 0x00000001
676/** Render cache, used by 2D and 3D drawing */
677#define I915_GEM_DOMAIN_RENDER 0x00000002
678/** Sampler cache, used by texture engine */
679#define I915_GEM_DOMAIN_SAMPLER 0x00000004
680/** Command queue, used to load batch buffers */
681#define I915_GEM_DOMAIN_COMMAND 0x00000008
682/** Instruction cache, used by shader programs */
683#define I915_GEM_DOMAIN_INSTRUCTION 0x00000010
684/** Vertex address cache */
685#define I915_GEM_DOMAIN_VERTEX 0x00000020
686/** GTT domain - aperture and scanout */
687#define I915_GEM_DOMAIN_GTT 0x00000040
688/** WC domain - uncached access */
689#define I915_GEM_DOMAIN_WC 0x00000080
690/** @} */
691
692struct drm_i915_gem_exec_object {
693 /**
694 * User's handle for a buffer to be bound into the GTT for this
695 * operation.
696 */
697 __u32 handle;
698
699 /** Number of relocations to be performed on this buffer */
700 __u32 relocation_count;
701 /**
702 * Pointer to array of struct drm_i915_gem_relocation_entry containing
703 * the relocations to be performed in this buffer.
704 */
705 __u64 relocs_ptr;
706
707 /** Required alignment in graphics aperture */
708 __u64 alignment;
709
710 /**
711 * Returned value of the updated offset of the object, for future
712 * presumed_offset writes.
713 */
714 __u64 offset;
715};
716
717struct drm_i915_gem_execbuffer {
718 /**
719 * List of buffers to be validated with their relocations to be
720 * performend on them.
721 *
722 * This is a pointer to an array of struct drm_i915_gem_validate_entry.
723 *
724 * These buffers must be listed in an order such that all relocations
725 * a buffer is performing refer to buffers that have already appeared
726 * in the validate list.
727 */
728 __u64 buffers_ptr;
729 __u32 buffer_count;
730
731 /** Offset in the batchbuffer to start execution from. */
732 __u32 batch_start_offset;
733 /** Bytes used in batchbuffer from batch_start_offset */
734 __u32 batch_len;
735 __u32 DR1;
736 __u32 DR4;
737 __u32 num_cliprects;
738 /** This is a struct drm_clip_rect *cliprects */
739 __u64 cliprects_ptr;
740};
741
742struct drm_i915_gem_exec_object2 {
743 /**
744 * User's handle for a buffer to be bound into the GTT for this
745 * operation.
746 */
747 __u32 handle;
748
749 /** Number of relocations to be performed on this buffer */
750 __u32 relocation_count;
751 /**
752 * Pointer to array of struct drm_i915_gem_relocation_entry containing
753 * the relocations to be performed in this buffer.
754 */
755 __u64 relocs_ptr;
756
757 /** Required alignment in graphics aperture */
758 __u64 alignment;
759
760 /**
761 * When the EXEC_OBJECT_PINNED flag is specified this is populated by
762 * the user with the GTT offset at which this object will be pinned.
763 * When the I915_EXEC_NO_RELOC flag is specified this must contain the
764 * presumed_offset of the object.
765 * During execbuffer2 the kernel populates it with the value of the
766 * current GTT offset of the object, for future presumed_offset writes.
767 */
768 __u64 offset;
769
770#define EXEC_OBJECT_NEEDS_FENCE (1<<0)
771#define EXEC_OBJECT_NEEDS_GTT (1<<1)
772#define EXEC_OBJECT_WRITE (1<<2)
773#define EXEC_OBJECT_SUPPORTS_48B_ADDRESS (1<<3)
774#define EXEC_OBJECT_PINNED (1<<4)
775#define EXEC_OBJECT_PAD_TO_SIZE (1<<5)
776/* The kernel implicitly tracks GPU activity on all GEM objects, and
777 * synchronises operations with outstanding rendering. This includes
778 * rendering on other devices if exported via dma-buf. However, sometimes
779 * this tracking is too coarse and the user knows better. For example,
780 * if the object is split into non-overlapping ranges shared between different
781 * clients or engines (i.e. suballocating objects), the implicit tracking
782 * by kernel assumes that each operation affects the whole object rather
783 * than an individual range, causing needless synchronisation between clients.
784 * The kernel will also forgo any CPU cache flushes prior to rendering from
785 * the object as the client is expected to be also handling such domain
786 * tracking.
787 *
788 * The kernel maintains the implicit tracking in order to manage resources
789 * used by the GPU - this flag only disables the synchronisation prior to
790 * rendering with this object in this execbuf.
791 *
792 * Opting out of implicit synhronisation requires the user to do its own
793 * explicit tracking to avoid rendering corruption. See, for example,
794 * I915_PARAM_HAS_EXEC_FENCE to order execbufs and execute them asynchronously.
795 */
796#define EXEC_OBJECT_ASYNC (1<<6)
797/* Request that the contents of this execobject be copied into the error
798 * state upon a GPU hang involving this batch for post-mortem debugging.
799 * These buffers are recorded in no particular order as "user" in
800 * /sys/class/drm/cardN/error. Query I915_PARAM_HAS_EXEC_CAPTURE to see
801 * if the kernel supports this flag.
802 */
803#define EXEC_OBJECT_CAPTURE (1<<7)
804/* All remaining bits are MBZ and RESERVED FOR FUTURE USE */
805#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_CAPTURE<<1)
806 __u64 flags;
807
808 union {
809 __u64 rsvd1;
810 __u64 pad_to_size;
811 };
812 __u64 rsvd2;
813};
814
815struct drm_i915_gem_execbuffer2 {
816 /**
817 * List of gem_exec_object2 structs
818 */
819 __u64 buffers_ptr;
820 __u32 buffer_count;
821
822 /** Offset in the batchbuffer to start execution from. */
823 __u32 batch_start_offset;
824 /** Bytes used in batchbuffer from batch_start_offset */
825 __u32 batch_len;
826 __u32 DR1;
827 __u32 DR4;
828 __u32 num_cliprects;
829 /** This is a struct drm_clip_rect *cliprects */
830 __u64 cliprects_ptr;
831#define I915_EXEC_RING_MASK (7<<0)
832#define I915_EXEC_DEFAULT (0<<0)
833#define I915_EXEC_RENDER (1<<0)
834#define I915_EXEC_BSD (2<<0)
835#define I915_EXEC_BLT (3<<0)
836#define I915_EXEC_VEBOX (4<<0)
837
838/* Used for switching the constants addressing mode on gen4+ RENDER ring.
839 * Gen6+ only supports relative addressing to dynamic state (default) and
840 * absolute addressing.
841 *
842 * These flags are ignored for the BSD and BLT rings.
843 */
844#define I915_EXEC_CONSTANTS_MASK (3<<6)
845#define I915_EXEC_CONSTANTS_REL_GENERAL (0<<6) /* default */
846#define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6)
847#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */
848 __u64 flags;
849 __u64 rsvd1; /* now used for context info */
850 __u64 rsvd2;
851};
852
853/** Resets the SO write offset registers for transform feedback on gen7. */
854#define I915_EXEC_GEN7_SOL_RESET (1<<8)
855
856/** Request a privileged ("secure") batch buffer. Note only available for
857 * DRM_ROOT_ONLY | DRM_MASTER processes.
858 */
859#define I915_EXEC_SECURE (1<<9)
860
861/** Inform the kernel that the batch is and will always be pinned. This
862 * negates the requirement for a workaround to be performed to avoid
863 * an incoherent CS (such as can be found on 830/845). If this flag is
864 * not passed, the kernel will endeavour to make sure the batch is
865 * coherent with the CS before execution. If this flag is passed,
866 * userspace assumes the responsibility for ensuring the same.
867 */
868#define I915_EXEC_IS_PINNED (1<<10)
869
870/** Provide a hint to the kernel that the command stream and auxiliary
871 * state buffers already holds the correct presumed addresses and so the
872 * relocation process may be skipped if no buffers need to be moved in
873 * preparation for the execbuffer.
874 */
875#define I915_EXEC_NO_RELOC (1<<11)
876
877/** Use the reloc.handle as an index into the exec object array rather
878 * than as the per-file handle.
879 */
880#define I915_EXEC_HANDLE_LUT (1<<12)
881
882/** Used for switching BSD rings on the platforms with two BSD rings */
883#define I915_EXEC_BSD_SHIFT (13)
884#define I915_EXEC_BSD_MASK (3 << I915_EXEC_BSD_SHIFT)
885/* default ping-pong mode */
886#define I915_EXEC_BSD_DEFAULT (0 << I915_EXEC_BSD_SHIFT)
887#define I915_EXEC_BSD_RING1 (1 << I915_EXEC_BSD_SHIFT)
888#define I915_EXEC_BSD_RING2 (2 << I915_EXEC_BSD_SHIFT)
889
890/** Tell the kernel that the batchbuffer is processed by
891 * the resource streamer.
892 */
893#define I915_EXEC_RESOURCE_STREAMER (1<<15)
894
895/* Setting I915_EXEC_FENCE_IN implies that lower_32_bits(rsvd2) represent
896 * a sync_file fd to wait upon (in a nonblocking manner) prior to executing
897 * the batch.
898 *
899 * Returns -EINVAL if the sync_file fd cannot be found.
900 */
901#define I915_EXEC_FENCE_IN (1<<16)
902
903/* Setting I915_EXEC_FENCE_OUT causes the ioctl to return a sync_file fd
904 * in the upper_32_bits(rsvd2) upon success. Ownership of the fd is given
905 * to the caller, and it should be close() after use. (The fd is a regular
906 * file descriptor and will be cleaned up on process termination. It holds
907 * a reference to the request, but nothing else.)
908 *
909 * The sync_file fd can be combined with other sync_file and passed either
910 * to execbuf using I915_EXEC_FENCE_IN, to atomic KMS ioctls (so that a flip
911 * will only occur after this request completes), or to other devices.
912 *
913 * Using I915_EXEC_FENCE_OUT requires use of
914 * DRM_IOCTL_I915_GEM_EXECBUFFER2_WR ioctl so that the result is written
915 * back to userspace. Failure to do so will cause the out-fence to always
916 * be reported as zero, and the real fence fd to be leaked.
917 */
918#define I915_EXEC_FENCE_OUT (1<<17)
919
920/*
921 * Traditionally the execbuf ioctl has only considered the final element in
922 * the execobject[] to be the executable batch. Often though, the client
923 * will known the batch object prior to construction and being able to place
924 * it into the execobject[] array first can simplify the relocation tracking.
925 * Setting I915_EXEC_BATCH_FIRST tells execbuf to use element 0 of the
926 * execobject[] as the * batch instead (the default is to use the last
927 * element).
928 */
929#define I915_EXEC_BATCH_FIRST (1<<18)
930#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_BATCH_FIRST<<1))
931
932#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
933#define i915_execbuffer2_set_context_id(eb2, context) \
934 (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK
935#define i915_execbuffer2_get_context_id(eb2) \
936 ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK)
937
938struct drm_i915_gem_pin {
939 /** Handle of the buffer to be pinned. */
940 __u32 handle;
941 __u32 pad;
942
943 /** alignment required within the aperture */
944 __u64 alignment;
945
946 /** Returned GTT offset of the buffer. */
947 __u64 offset;
948};
949
950struct drm_i915_gem_unpin {
951 /** Handle of the buffer to be unpinned. */
952 __u32 handle;
953 __u32 pad;
954};
955
956struct drm_i915_gem_busy {
957 /** Handle of the buffer to check for busy */
958 __u32 handle;
959
960 /** Return busy status
961 *
962 * A return of 0 implies that the object is idle (after
963 * having flushed any pending activity), and a non-zero return that
964 * the object is still in-flight on the GPU. (The GPU has not yet
965 * signaled completion for all pending requests that reference the
966 * object.) An object is guaranteed to become idle eventually (so
967 * long as no new GPU commands are executed upon it). Due to the
968 * asynchronous nature of the hardware, an object reported
969 * as busy may become idle before the ioctl is completed.
970 *
971 * Furthermore, if the object is busy, which engine is busy is only
972 * provided as a guide. There are race conditions which prevent the
973 * report of which engines are busy from being always accurate.
974 * However, the converse is not true. If the object is idle, the
975 * result of the ioctl, that all engines are idle, is accurate.
976 *
977 * The returned dword is split into two fields to indicate both
978 * the engines on which the object is being read, and the
979 * engine on which it is currently being written (if any).
980 *
981 * The low word (bits 0:15) indicate if the object is being written
982 * to by any engine (there can only be one, as the GEM implicit
983 * synchronisation rules force writes to be serialised). Only the
984 * engine for the last write is reported.
985 *
986 * The high word (bits 16:31) are a bitmask of which engines are
987 * currently reading from the object. Multiple engines may be
988 * reading from the object simultaneously.
989 *
990 * The value of each engine is the same as specified in the
991 * EXECBUFFER2 ioctl, i.e. I915_EXEC_RENDER, I915_EXEC_BSD etc.
992 * Note I915_EXEC_DEFAULT is a symbolic value and is mapped to
993 * the I915_EXEC_RENDER engine for execution, and so it is never
994 * reported as active itself. Some hardware may have parallel
995 * execution engines, e.g. multiple media engines, which are
996 * mapped to the same identifier in the EXECBUFFER2 ioctl and
997 * so are not separately reported for busyness.
998 *
999 * Caveat emptor:
1000 * Only the boolean result of this query is reliable; that is whether
1001 * the object is idle or busy. The report of which engines are busy
1002 * should be only used as a heuristic.
1003 */
1004 __u32 busy;
1005};
1006
1007/**
1008 * I915_CACHING_NONE
1009 *
1010 * GPU access is not coherent with cpu caches. Default for machines without an
1011 * LLC.
1012 */
1013#define I915_CACHING_NONE 0
1014/**
1015 * I915_CACHING_CACHED
1016 *
1017 * GPU access is coherent with cpu caches and furthermore the data is cached in
1018 * last-level caches shared between cpu cores and the gpu GT. Default on
1019 * machines with HAS_LLC.
1020 */
1021#define I915_CACHING_CACHED 1
1022/**
1023 * I915_CACHING_DISPLAY
1024 *
1025 * Special GPU caching mode which is coherent with the scanout engines.
1026 * Transparently falls back to I915_CACHING_NONE on platforms where no special
1027 * cache mode (like write-through or gfdt flushing) is available. The kernel
1028 * automatically sets this mode when using a buffer as a scanout target.
1029 * Userspace can manually set this mode to avoid a costly stall and clflush in
1030 * the hotpath of drawing the first frame.
1031 */
1032#define I915_CACHING_DISPLAY 2
1033
1034struct drm_i915_gem_caching {
1035 /**
1036 * Handle of the buffer to set/get the caching level of. */
1037 __u32 handle;
1038
1039 /**
1040 * Cacheing level to apply or return value
1041 *
1042 * bits0-15 are for generic caching control (i.e. the above defined
1043 * values). bits16-31 are reserved for platform-specific variations
1044 * (e.g. l3$ caching on gen7). */
1045 __u32 caching;
1046};
1047
1048#define I915_TILING_NONE 0
1049#define I915_TILING_X 1
1050#define I915_TILING_Y 2
1051#define I915_TILING_LAST I915_TILING_Y
1052
1053#define I915_BIT_6_SWIZZLE_NONE 0
1054#define I915_BIT_6_SWIZZLE_9 1
1055#define I915_BIT_6_SWIZZLE_9_10 2
1056#define I915_BIT_6_SWIZZLE_9_11 3
1057#define I915_BIT_6_SWIZZLE_9_10_11 4
1058/* Not seen by userland */
1059#define I915_BIT_6_SWIZZLE_UNKNOWN 5
1060/* Seen by userland. */
1061#define I915_BIT_6_SWIZZLE_9_17 6
1062#define I915_BIT_6_SWIZZLE_9_10_17 7
1063
1064struct drm_i915_gem_set_tiling {
1065 /** Handle of the buffer to have its tiling state updated */
1066 __u32 handle;
1067
1068 /**
1069 * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
1070 * I915_TILING_Y).
1071 *
1072 * This value is to be set on request, and will be updated by the
1073 * kernel on successful return with the actual chosen tiling layout.
1074 *
1075 * The tiling mode may be demoted to I915_TILING_NONE when the system
1076 * has bit 6 swizzling that can't be managed correctly by GEM.
1077 *
1078 * Buffer contents become undefined when changing tiling_mode.
1079 */
1080 __u32 tiling_mode;
1081
1082 /**
1083 * Stride in bytes for the object when in I915_TILING_X or
1084 * I915_TILING_Y.
1085 */
1086 __u32 stride;
1087
1088 /**
1089 * Returned address bit 6 swizzling required for CPU access through
1090 * mmap mapping.
1091 */
1092 __u32 swizzle_mode;
1093};
1094
1095struct drm_i915_gem_get_tiling {
1096 /** Handle of the buffer to get tiling state for. */
1097 __u32 handle;
1098
1099 /**
1100 * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
1101 * I915_TILING_Y).
1102 */
1103 __u32 tiling_mode;
1104
1105 /**
1106 * Returned address bit 6 swizzling required for CPU access through
1107 * mmap mapping.
1108 */
1109 __u32 swizzle_mode;
1110
1111 /**
1112 * Returned address bit 6 swizzling required for CPU access through
1113 * mmap mapping whilst bound.
1114 */
1115 __u32 phys_swizzle_mode;
1116};
1117
1118struct drm_i915_gem_get_aperture {
1119 /** Total size of the aperture used by i915_gem_execbuffer, in bytes */
1120 __u64 aper_size;
1121
1122 /**
1123 * Available space in the aperture used by i915_gem_execbuffer, in
1124 * bytes
1125 */
1126 __u64 aper_available_size;
1127};
1128
1129struct drm_i915_get_pipe_from_crtc_id {
1130 /** ID of CRTC being requested **/
1131 __u32 crtc_id;
1132
1133 /** pipe of requested CRTC **/
1134 __u32 pipe;
1135};
1136
1137#define I915_MADV_WILLNEED 0
1138#define I915_MADV_DONTNEED 1
1139#define __I915_MADV_PURGED 2 /* internal state */
1140
1141struct drm_i915_gem_madvise {
1142 /** Handle of the buffer to change the backing store advice */
1143 __u32 handle;
1144
1145 /* Advice: either the buffer will be needed again in the near future,
1146 * or wont be and could be discarded under memory pressure.
1147 */
1148 __u32 madv;
1149
1150 /** Whether the backing store still exists. */
1151 __u32 retained;
1152};
1153
1154/* flags */
1155#define I915_OVERLAY_TYPE_MASK 0xff
1156#define I915_OVERLAY_YUV_PLANAR 0x01
1157#define I915_OVERLAY_YUV_PACKED 0x02
1158#define I915_OVERLAY_RGB 0x03
1159
1160#define I915_OVERLAY_DEPTH_MASK 0xff00
1161#define I915_OVERLAY_RGB24 0x1000
1162#define I915_OVERLAY_RGB16 0x2000
1163#define I915_OVERLAY_RGB15 0x3000
1164#define I915_OVERLAY_YUV422 0x0100
1165#define I915_OVERLAY_YUV411 0x0200
1166#define I915_OVERLAY_YUV420 0x0300
1167#define I915_OVERLAY_YUV410 0x0400
1168
1169#define I915_OVERLAY_SWAP_MASK 0xff0000
1170#define I915_OVERLAY_NO_SWAP 0x000000
1171#define I915_OVERLAY_UV_SWAP 0x010000
1172#define I915_OVERLAY_Y_SWAP 0x020000
1173#define I915_OVERLAY_Y_AND_UV_SWAP 0x030000
1174
1175#define I915_OVERLAY_FLAGS_MASK 0xff000000
1176#define I915_OVERLAY_ENABLE 0x01000000
1177
1178struct drm_intel_overlay_put_image {
1179 /* various flags and src format description */
1180 __u32 flags;
1181 /* source picture description */
1182 __u32 bo_handle;
1183 /* stride values and offsets are in bytes, buffer relative */
1184 __u16 stride_Y; /* stride for packed formats */
1185 __u16 stride_UV;
1186 __u32 offset_Y; /* offset for packet formats */
1187 __u32 offset_U;
1188 __u32 offset_V;
1189 /* in pixels */
1190 __u16 src_width;
1191 __u16 src_height;
1192 /* to compensate the scaling factors for partially covered surfaces */
1193 __u16 src_scan_width;
1194 __u16 src_scan_height;
1195 /* output crtc description */
1196 __u32 crtc_id;
1197 __u16 dst_x;
1198 __u16 dst_y;
1199 __u16 dst_width;
1200 __u16 dst_height;
1201};
1202
1203/* flags */
1204#define I915_OVERLAY_UPDATE_ATTRS (1<<0)
1205#define I915_OVERLAY_UPDATE_GAMMA (1<<1)
1206#define I915_OVERLAY_DISABLE_DEST_COLORKEY (1<<2)
1207struct drm_intel_overlay_attrs {
1208 __u32 flags;
1209 __u32 color_key;
1210 __s32 brightness;
1211 __u32 contrast;
1212 __u32 saturation;
1213 __u32 gamma0;
1214 __u32 gamma1;
1215 __u32 gamma2;
1216 __u32 gamma3;
1217 __u32 gamma4;
1218 __u32 gamma5;
1219};
1220
1221/*
1222 * Intel sprite handling
1223 *
1224 * Color keying works with a min/mask/max tuple. Both source and destination
1225 * color keying is allowed.
1226 *
1227 * Source keying:
1228 * Sprite pixels within the min & max values, masked against the color channels
1229 * specified in the mask field, will be transparent. All other pixels will
1230 * be displayed on top of the primary plane. For RGB surfaces, only the min
1231 * and mask fields will be used; ranged compares are not allowed.
1232 *
1233 * Destination keying:
1234 * Primary plane pixels that match the min value, masked against the color
1235 * channels specified in the mask field, will be replaced by corresponding
1236 * pixels from the sprite plane.
1237 *
1238 * Note that source & destination keying are exclusive; only one can be
1239 * active on a given plane.
1240 */
1241
1242#define I915_SET_COLORKEY_NONE (1<<0) /* disable color key matching */
1243#define I915_SET_COLORKEY_DESTINATION (1<<1)
1244#define I915_SET_COLORKEY_SOURCE (1<<2)
1245struct drm_intel_sprite_colorkey {
1246 __u32 plane_id;
1247 __u32 min_value;
1248 __u32 channel_mask;
1249 __u32 max_value;
1250 __u32 flags;
1251};
1252
1253struct drm_i915_gem_wait {
1254 /** Handle of BO we shall wait on */
1255 __u32 bo_handle;
1256 __u32 flags;
1257 /** Number of nanoseconds to wait, Returns time remaining. */
1258 __s64 timeout_ns;
1259};
1260
1261struct drm_i915_gem_context_create {
1262 /* output: id of new context*/
1263 __u32 ctx_id;
1264 __u32 pad;
1265};
1266
1267struct drm_i915_gem_context_destroy {
1268 __u32 ctx_id;
1269 __u32 pad;
1270};
1271
1272struct drm_i915_reg_read {
1273 /*
1274 * Register offset.
1275 * For 64bit wide registers where the upper 32bits don't immediately
1276 * follow the lower 32bits, the offset of the lower 32bits must
1277 * be specified
1278 */
1279 __u64 offset;
1280 __u64 val; /* Return value */
1281};
1282/* Known registers:
1283 *
1284 * Render engine timestamp - 0x2358 + 64bit - gen7+
1285 * - Note this register returns an invalid value if using the default
1286 * single instruction 8byte read, in order to workaround that use
1287 * offset (0x2538 | 1) instead.
1288 *
1289 */
1290
1291struct drm_i915_reset_stats {
1292 __u32 ctx_id;
1293 __u32 flags;
1294
1295 /* All resets since boot/module reload, for all contexts */
1296 __u32 reset_count;
1297
1298 /* Number of batches lost when active in GPU, for this context */
1299 __u32 batch_active;
1300
1301 /* Number of batches lost pending for execution, for this context */
1302 __u32 batch_pending;
1303
1304 __u32 pad;
1305};
1306
1307struct drm_i915_gem_userptr {
1308 __u64 user_ptr;
1309 __u64 user_size;
1310 __u32 flags;
1311#define I915_USERPTR_READ_ONLY 0x1
1312#define I915_USERPTR_UNSYNCHRONIZED 0x80000000
1313 /**
1314 * Returned handle for the object.
1315 *
1316 * Object handles are nonzero.
1317 */
1318 __u32 handle;
1319};
1320
1321struct drm_i915_gem_context_param {
1322 __u32 ctx_id;
1323 __u32 size;
1324 __u64 param;
1325#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1
1326#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2
1327#define I915_CONTEXT_PARAM_GTT_SIZE 0x3
1328#define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE 0x4
1329#define I915_CONTEXT_PARAM_BANNABLE 0x5
1330 __u64 value;
1331};
1332
1333enum drm_i915_oa_format {
1334 I915_OA_FORMAT_A13 = 1, /* HSW only */
1335 I915_OA_FORMAT_A29, /* HSW only */
1336 I915_OA_FORMAT_A13_B8_C8, /* HSW only */
1337 I915_OA_FORMAT_B4_C8, /* HSW only */
1338 I915_OA_FORMAT_A45_B8_C8, /* HSW only */
1339 I915_OA_FORMAT_B4_C8_A16, /* HSW only */
1340 I915_OA_FORMAT_C4_B8, /* HSW+ */
1341
1342 /* Gen8+ */
1343 I915_OA_FORMAT_A12,
1344 I915_OA_FORMAT_A12_B8_C8,
1345 I915_OA_FORMAT_A32u40_A4u32_B8_C8,
1346
1347 I915_OA_FORMAT_MAX /* non-ABI */
1348};
1349
1350enum drm_i915_perf_property_id {
1351 /**
1352 * Open the stream for a specific context handle (as used with
1353 * execbuffer2). A stream opened for a specific context this way
1354 * won't typically require root privileges.
1355 */
1356 DRM_I915_PERF_PROP_CTX_HANDLE = 1,
1357
1358 /**
1359 * A value of 1 requests the inclusion of raw OA unit reports as
1360 * part of stream samples.
1361 */
1362 DRM_I915_PERF_PROP_SAMPLE_OA,
1363
1364 /**
1365 * The value specifies which set of OA unit metrics should be
1366 * be configured, defining the contents of any OA unit reports.
1367 */
1368 DRM_I915_PERF_PROP_OA_METRICS_SET,
1369
1370 /**
1371 * The value specifies the size and layout of OA unit reports.
1372 */
1373 DRM_I915_PERF_PROP_OA_FORMAT,
1374
1375 /**
1376 * Specifying this property implicitly requests periodic OA unit
1377 * sampling and (at least on Haswell) the sampling frequency is derived
1378 * from this exponent as follows:
1379 *
1380 * 80ns * 2^(period_exponent + 1)
1381 */
1382 DRM_I915_PERF_PROP_OA_EXPONENT,
1383
1384 DRM_I915_PERF_PROP_MAX /* non-ABI */
1385};
1386
1387struct drm_i915_perf_open_param {
1388 __u32 flags;
1389#define I915_PERF_FLAG_FD_CLOEXEC (1<<0)
1390#define I915_PERF_FLAG_FD_NONBLOCK (1<<1)
1391#define I915_PERF_FLAG_DISABLED (1<<2)
1392
1393 /** The number of u64 (id, value) pairs */
1394 __u32 num_properties;
1395
1396 /**
1397 * Pointer to array of u64 (id, value) pairs configuring the stream
1398 * to open.
1399 */
1400 __u64 properties_ptr;
1401};
1402
1403/**
1404 * Enable data capture for a stream that was either opened in a disabled state
1405 * via I915_PERF_FLAG_DISABLED or was later disabled via
1406 * I915_PERF_IOCTL_DISABLE.
1407 *
1408 * It is intended to be cheaper to disable and enable a stream than it may be
1409 * to close and re-open a stream with the same configuration.
1410 *
1411 * It's undefined whether any pending data for the stream will be lost.
1412 */
1413#define I915_PERF_IOCTL_ENABLE _IO('i', 0x0)
1414
1415/**
1416 * Disable data capture for a stream.
1417 *
1418 * It is an error to try and read a stream that is disabled.
1419 */
1420#define I915_PERF_IOCTL_DISABLE _IO('i', 0x1)
1421
1422/**
1423 * Common to all i915 perf records
1424 */
1425struct drm_i915_perf_record_header {
1426 __u32 type;
1427 __u16 pad;
1428 __u16 size;
1429};
1430
1431enum drm_i915_perf_record_type {
1432
1433 /**
1434 * Samples are the work horse record type whose contents are extensible
1435 * and defined when opening an i915 perf stream based on the given
1436 * properties.
1437 *
1438 * Boolean properties following the naming convention
1439 * DRM_I915_PERF_SAMPLE_xyz_PROP request the inclusion of 'xyz' data in
1440 * every sample.
1441 *
1442 * The order of these sample properties given by userspace has no
1443 * affect on the ordering of data within a sample. The order is
1444 * documented here.
1445 *
1446 * struct {
1447 * struct drm_i915_perf_record_header header;
1448 *
1449 * { u32 oa_report[]; } && DRM_I915_PERF_PROP_SAMPLE_OA
1450 * };
1451 */
1452 DRM_I915_PERF_RECORD_SAMPLE = 1,
1453
1454 /*
1455 * Indicates that one or more OA reports were not written by the
1456 * hardware. This can happen for example if an MI_REPORT_PERF_COUNT
1457 * command collides with periodic sampling - which would be more likely
1458 * at higher sampling frequencies.
1459 */
1460 DRM_I915_PERF_RECORD_OA_REPORT_LOST = 2,
1461
1462 /**
1463 * An error occurred that resulted in all pending OA reports being lost.
1464 */
1465 DRM_I915_PERF_RECORD_OA_BUFFER_LOST = 3,
1466
1467 DRM_I915_PERF_RECORD_MAX /* non-ABI */
1468};
1469
1470#if defined(__cplusplus)
1471}
1472#endif
1473
1474#endif /* _UAPI_I915_DRM_H_ */
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index ce2988be4f0e..461811e57140 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -30,9 +30,14 @@
30#define BPF_FROM_LE BPF_TO_LE 30#define BPF_FROM_LE BPF_TO_LE
31#define BPF_FROM_BE BPF_TO_BE 31#define BPF_FROM_BE BPF_TO_BE
32 32
33/* jmp encodings */
33#define BPF_JNE 0x50 /* jump != */ 34#define BPF_JNE 0x50 /* jump != */
35#define BPF_JLT 0xa0 /* LT is unsigned, '<' */
36#define BPF_JLE 0xb0 /* LE is unsigned, '<=' */
34#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */ 37#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */
35#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */ 38#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */
39#define BPF_JSLT 0xc0 /* SLT is signed, '<' */
40#define BPF_JSLE 0xd0 /* SLE is signed, '<=' */
36#define BPF_CALL 0x80 /* function call */ 41#define BPF_CALL 0x80 /* function call */
37#define BPF_EXIT 0x90 /* function return */ 42#define BPF_EXIT 0x90 /* function return */
38 43
@@ -104,6 +109,8 @@ enum bpf_map_type {
104 BPF_MAP_TYPE_LPM_TRIE, 109 BPF_MAP_TYPE_LPM_TRIE,
105 BPF_MAP_TYPE_ARRAY_OF_MAPS, 110 BPF_MAP_TYPE_ARRAY_OF_MAPS,
106 BPF_MAP_TYPE_HASH_OF_MAPS, 111 BPF_MAP_TYPE_HASH_OF_MAPS,
112 BPF_MAP_TYPE_DEVMAP,
113 BPF_MAP_TYPE_SOCKMAP,
107}; 114};
108 115
109enum bpf_prog_type { 116enum bpf_prog_type {
@@ -121,6 +128,7 @@ enum bpf_prog_type {
121 BPF_PROG_TYPE_LWT_OUT, 128 BPF_PROG_TYPE_LWT_OUT,
122 BPF_PROG_TYPE_LWT_XMIT, 129 BPF_PROG_TYPE_LWT_XMIT,
123 BPF_PROG_TYPE_SOCK_OPS, 130 BPF_PROG_TYPE_SOCK_OPS,
131 BPF_PROG_TYPE_SK_SKB,
124}; 132};
125 133
126enum bpf_attach_type { 134enum bpf_attach_type {
@@ -128,11 +136,19 @@ enum bpf_attach_type {
128 BPF_CGROUP_INET_EGRESS, 136 BPF_CGROUP_INET_EGRESS,
129 BPF_CGROUP_INET_SOCK_CREATE, 137 BPF_CGROUP_INET_SOCK_CREATE,
130 BPF_CGROUP_SOCK_OPS, 138 BPF_CGROUP_SOCK_OPS,
139 BPF_SK_SKB_STREAM_PARSER,
140 BPF_SK_SKB_STREAM_VERDICT,
131 __MAX_BPF_ATTACH_TYPE 141 __MAX_BPF_ATTACH_TYPE
132}; 142};
133 143
134#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE 144#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
135 145
146enum bpf_sockmap_flags {
147 BPF_SOCKMAP_UNSPEC,
148 BPF_SOCKMAP_STRPARSER,
149 __MAX_BPF_SOCKMAP_FLAG
150};
151
136/* If BPF_F_ALLOW_OVERRIDE flag is used in BPF_PROG_ATTACH command 152/* If BPF_F_ALLOW_OVERRIDE flag is used in BPF_PROG_ATTACH command
137 * to the given target_fd cgroup the descendent cgroup will be able to 153 * to the given target_fd cgroup the descendent cgroup will be able to
138 * override effective bpf program that was inherited from this cgroup 154 * override effective bpf program that was inherited from this cgroup
@@ -153,6 +169,7 @@ enum bpf_attach_type {
153#define BPF_NOEXIST 1 /* create new element if it didn't exist */ 169#define BPF_NOEXIST 1 /* create new element if it didn't exist */
154#define BPF_EXIST 2 /* update existing element */ 170#define BPF_EXIST 2 /* update existing element */
155 171
172/* flags for BPF_MAP_CREATE command */
156#define BPF_F_NO_PREALLOC (1U << 0) 173#define BPF_F_NO_PREALLOC (1U << 0)
157/* Instead of having one common LRU list in the 174/* Instead of having one common LRU list in the
158 * BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list 175 * BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list
@@ -161,6 +178,8 @@ enum bpf_attach_type {
161 * across different LRU lists. 178 * across different LRU lists.
162 */ 179 */
163#define BPF_F_NO_COMMON_LRU (1U << 1) 180#define BPF_F_NO_COMMON_LRU (1U << 1)
181/* Specify numa node during map creation */
182#define BPF_F_NUMA_NODE (1U << 2)
164 183
165union bpf_attr { 184union bpf_attr {
166 struct { /* anonymous struct used by BPF_MAP_CREATE command */ 185 struct { /* anonymous struct used by BPF_MAP_CREATE command */
@@ -168,8 +187,13 @@ union bpf_attr {
168 __u32 key_size; /* size of key in bytes */ 187 __u32 key_size; /* size of key in bytes */
169 __u32 value_size; /* size of value in bytes */ 188 __u32 value_size; /* size of value in bytes */
170 __u32 max_entries; /* max number of entries in a map */ 189 __u32 max_entries; /* max number of entries in a map */
171 __u32 map_flags; /* prealloc or not */ 190 __u32 map_flags; /* BPF_MAP_CREATE related
191 * flags defined above.
192 */
172 __u32 inner_map_fd; /* fd pointing to the inner map */ 193 __u32 inner_map_fd; /* fd pointing to the inner map */
194 __u32 numa_node; /* numa node (effective only if
195 * BPF_F_NUMA_NODE is set).
196 */
173 }; 197 };
174 198
175 struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */ 199 struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */
@@ -539,6 +563,20 @@ union bpf_attr {
539 * @mode: operation mode (enum bpf_adj_room_mode) 563 * @mode: operation mode (enum bpf_adj_room_mode)
540 * @flags: reserved for future use 564 * @flags: reserved for future use
541 * Return: 0 on success or negative error code 565 * Return: 0 on success or negative error code
566 *
567 * int bpf_sk_redirect_map(map, key, flags)
568 * Redirect skb to a sock in map using key as a lookup key for the
569 * sock in map.
570 * @map: pointer to sockmap
571 * @key: key to lookup sock in map
572 * @flags: reserved for future use
573 * Return: SK_REDIRECT
574 *
575 * int bpf_sock_map_update(skops, map, key, flags)
576 * @skops: pointer to bpf_sock_ops
577 * @map: pointer to sockmap to update
578 * @key: key to insert/update sock in map
579 * @flags: same flags as map update elem
542 */ 580 */
543#define __BPF_FUNC_MAPPER(FN) \ 581#define __BPF_FUNC_MAPPER(FN) \
544 FN(unspec), \ 582 FN(unspec), \
@@ -591,7 +629,10 @@ union bpf_attr {
591 FN(get_socket_uid), \ 629 FN(get_socket_uid), \
592 FN(set_hash), \ 630 FN(set_hash), \
593 FN(setsockopt), \ 631 FN(setsockopt), \
594 FN(skb_adjust_room), 632 FN(skb_adjust_room), \
633 FN(redirect_map), \
634 FN(sk_redirect_map), \
635 FN(sock_map_update),
595 636
596/* integer value in 'imm' field of BPF_CALL instruction selects which helper 637/* integer value in 'imm' field of BPF_CALL instruction selects which helper
597 * function eBPF program intends to call 638 * function eBPF program intends to call
@@ -643,7 +684,7 @@ enum bpf_func_id {
643 684
644/* Mode for BPF_FUNC_skb_adjust_room helper. */ 685/* Mode for BPF_FUNC_skb_adjust_room helper. */
645enum bpf_adj_room_mode { 686enum bpf_adj_room_mode {
646 BPF_ADJ_ROOM_NET_OPTS, 687 BPF_ADJ_ROOM_NET,
647}; 688};
648 689
649/* user accessible mirror of in-kernel sk_buff. 690/* user accessible mirror of in-kernel sk_buff.
@@ -668,6 +709,15 @@ struct __sk_buff {
668 __u32 data; 709 __u32 data;
669 __u32 data_end; 710 __u32 data_end;
670 __u32 napi_id; 711 __u32 napi_id;
712
713 /* accessed by BPF_PROG_TYPE_sk_skb types */
714 __u32 family;
715 __u32 remote_ip4; /* Stored in network byte order */
716 __u32 local_ip4; /* Stored in network byte order */
717 __u32 remote_ip6[4]; /* Stored in network byte order */
718 __u32 local_ip6[4]; /* Stored in network byte order */
719 __u32 remote_port; /* Stored in network byte order */
720 __u32 local_port; /* stored in host byte order */
671}; 721};
672 722
673struct bpf_tunnel_key { 723struct bpf_tunnel_key {
@@ -727,6 +777,12 @@ struct xdp_md {
727 __u32 data_end; 777 __u32 data_end;
728}; 778};
729 779
780enum sk_action {
781 SK_ABORTED = 0,
782 SK_DROP,
783 SK_REDIRECT,
784};
785
730#define BPF_TAG_SIZE 8 786#define BPF_TAG_SIZE 8
731 787
732struct bpf_prog_info { 788struct bpf_prog_info {
@@ -750,6 +806,8 @@ struct bpf_map_info {
750 806
751/* User bpf_sock_ops struct to access socket values and specify request ops 807/* User bpf_sock_ops struct to access socket values and specify request ops
752 * and their replies. 808 * and their replies.
809 * Some of this fields are in network (bigendian) byte order and may need
810 * 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 811 * New fields can only be added at the end of this structure
754 */ 812 */
755struct bpf_sock_ops { 813struct bpf_sock_ops {
@@ -759,12 +817,12 @@ struct bpf_sock_ops {
759 __u32 replylong[4]; 817 __u32 replylong[4];
760 }; 818 };
761 __u32 family; 819 __u32 family;
762 __u32 remote_ip4; 820 __u32 remote_ip4; /* Stored in network byte order */
763 __u32 local_ip4; 821 __u32 local_ip4; /* Stored in network byte order */
764 __u32 remote_ip6[4]; 822 __u32 remote_ip6[4]; /* Stored in network byte order */
765 __u32 local_ip6[4]; 823 __u32 local_ip6[4]; /* Stored in network byte order */
766 __u32 remote_port; 824 __u32 remote_port; /* Stored in network byte order */
767 __u32 local_port; 825 __u32 local_port; /* stored in host byte order */
768}; 826};
769 827
770/* List of known BPF sock_ops operators. 828/* List of known BPF sock_ops operators.
diff --git a/tools/include/uapi/linux/fcntl.h b/tools/include/uapi/linux/fcntl.h
index 813afd6eee71..ec69d55bcec7 100644
--- a/tools/include/uapi/linux/fcntl.h
+++ b/tools/include/uapi/linux/fcntl.h
@@ -43,6 +43,27 @@
43/* (1U << 31) is reserved for signed error codes */ 43/* (1U << 31) is reserved for signed error codes */
44 44
45/* 45/*
46 * Set/Get write life time hints. {GET,SET}_RW_HINT operate on the
47 * underlying inode, while {GET,SET}_FILE_RW_HINT operate only on
48 * the specific file.
49 */
50#define F_GET_RW_HINT (F_LINUX_SPECIFIC_BASE + 11)
51#define F_SET_RW_HINT (F_LINUX_SPECIFIC_BASE + 12)
52#define F_GET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 13)
53#define F_SET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 14)
54
55/*
56 * Valid hint values for F_{GET,SET}_RW_HINT. 0 is "not set", or can be
57 * used to clear any hints previously set.
58 */
59#define RWF_WRITE_LIFE_NOT_SET 0
60#define RWH_WRITE_LIFE_NONE 1
61#define RWH_WRITE_LIFE_SHORT 2
62#define RWH_WRITE_LIFE_MEDIUM 3
63#define RWH_WRITE_LIFE_LONG 4
64#define RWH_WRITE_LIFE_EXTREME 5
65
66/*
46 * Types of directory notifications that may be requested. 67 * Types of directory notifications that may be requested.
47 */ 68 */
48#define DN_ACCESS 0x00000001 /* File accessed */ 69#define DN_ACCESS 0x00000001 /* File accessed */
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
new file mode 100644
index 000000000000..6cd63c18708a
--- /dev/null
+++ b/tools/include/uapi/linux/kvm.h
@@ -0,0 +1,1419 @@
1#ifndef __LINUX_KVM_H
2#define __LINUX_KVM_H
3
4/*
5 * Userspace interface for /dev/kvm - kernel based virtual machine
6 *
7 * Note: you must update KVM_API_VERSION if you change this interface.
8 */
9
10#include <linux/types.h>
11#include <linux/compiler.h>
12#include <linux/ioctl.h>
13#include <asm/kvm.h>
14
15#define KVM_API_VERSION 12
16
17/* *** Deprecated interfaces *** */
18
19#define KVM_TRC_SHIFT 16
20
21#define KVM_TRC_ENTRYEXIT (1 << KVM_TRC_SHIFT)
22#define KVM_TRC_HANDLER (1 << (KVM_TRC_SHIFT + 1))
23
24#define KVM_TRC_VMENTRY (KVM_TRC_ENTRYEXIT + 0x01)
25#define KVM_TRC_VMEXIT (KVM_TRC_ENTRYEXIT + 0x02)
26#define KVM_TRC_PAGE_FAULT (KVM_TRC_HANDLER + 0x01)
27
28#define KVM_TRC_HEAD_SIZE 12
29#define KVM_TRC_CYCLE_SIZE 8
30#define KVM_TRC_EXTRA_MAX 7
31
32#define KVM_TRC_INJ_VIRQ (KVM_TRC_HANDLER + 0x02)
33#define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03)
34#define KVM_TRC_PEND_INTR (KVM_TRC_HANDLER + 0x04)
35#define KVM_TRC_IO_READ (KVM_TRC_HANDLER + 0x05)
36#define KVM_TRC_IO_WRITE (KVM_TRC_HANDLER + 0x06)
37#define KVM_TRC_CR_READ (KVM_TRC_HANDLER + 0x07)
38#define KVM_TRC_CR_WRITE (KVM_TRC_HANDLER + 0x08)
39#define KVM_TRC_DR_READ (KVM_TRC_HANDLER + 0x09)
40#define KVM_TRC_DR_WRITE (KVM_TRC_HANDLER + 0x0A)
41#define KVM_TRC_MSR_READ (KVM_TRC_HANDLER + 0x0B)
42#define KVM_TRC_MSR_WRITE (KVM_TRC_HANDLER + 0x0C)
43#define KVM_TRC_CPUID (KVM_TRC_HANDLER + 0x0D)
44#define KVM_TRC_INTR (KVM_TRC_HANDLER + 0x0E)
45#define KVM_TRC_NMI (KVM_TRC_HANDLER + 0x0F)
46#define KVM_TRC_VMMCALL (KVM_TRC_HANDLER + 0x10)
47#define KVM_TRC_HLT (KVM_TRC_HANDLER + 0x11)
48#define KVM_TRC_CLTS (KVM_TRC_HANDLER + 0x12)
49#define KVM_TRC_LMSW (KVM_TRC_HANDLER + 0x13)
50#define KVM_TRC_APIC_ACCESS (KVM_TRC_HANDLER + 0x14)
51#define KVM_TRC_TDP_FAULT (KVM_TRC_HANDLER + 0x15)
52#define KVM_TRC_GTLB_WRITE (KVM_TRC_HANDLER + 0x16)
53#define KVM_TRC_STLB_WRITE (KVM_TRC_HANDLER + 0x17)
54#define KVM_TRC_STLB_INVAL (KVM_TRC_HANDLER + 0x18)
55#define KVM_TRC_PPC_INSTR (KVM_TRC_HANDLER + 0x19)
56
57struct kvm_user_trace_setup {
58 __u32 buf_size;
59 __u32 buf_nr;
60};
61
62#define __KVM_DEPRECATED_MAIN_W_0x06 \
63 _IOW(KVMIO, 0x06, struct kvm_user_trace_setup)
64#define __KVM_DEPRECATED_MAIN_0x07 _IO(KVMIO, 0x07)
65#define __KVM_DEPRECATED_MAIN_0x08 _IO(KVMIO, 0x08)
66
67#define __KVM_DEPRECATED_VM_R_0x70 _IOR(KVMIO, 0x70, struct kvm_assigned_irq)
68
69struct kvm_breakpoint {
70 __u32 enabled;
71 __u32 padding;
72 __u64 address;
73};
74
75struct kvm_debug_guest {
76 __u32 enabled;
77 __u32 pad;
78 struct kvm_breakpoint breakpoints[4];
79 __u32 singlestep;
80};
81
82#define __KVM_DEPRECATED_VCPU_W_0x87 _IOW(KVMIO, 0x87, struct kvm_debug_guest)
83
84/* *** End of deprecated interfaces *** */
85
86
87/* for KVM_CREATE_MEMORY_REGION */
88struct kvm_memory_region {
89 __u32 slot;
90 __u32 flags;
91 __u64 guest_phys_addr;
92 __u64 memory_size; /* bytes */
93};
94
95/* for KVM_SET_USER_MEMORY_REGION */
96struct kvm_userspace_memory_region {
97 __u32 slot;
98 __u32 flags;
99 __u64 guest_phys_addr;
100 __u64 memory_size; /* bytes */
101 __u64 userspace_addr; /* start of the userspace allocated memory */
102};
103
104/*
105 * The bit 0 ~ bit 15 of kvm_memory_region::flags are visible for userspace,
106 * other bits are reserved for kvm internal use which are defined in
107 * include/linux/kvm_host.h.
108 */
109#define KVM_MEM_LOG_DIRTY_PAGES (1UL << 0)
110#define KVM_MEM_READONLY (1UL << 1)
111
112/* for KVM_IRQ_LINE */
113struct kvm_irq_level {
114 /*
115 * ACPI gsi notion of irq.
116 * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
117 * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
118 * For ARM: See Documentation/virtual/kvm/api.txt
119 */
120 union {
121 __u32 irq;
122 __s32 status;
123 };
124 __u32 level;
125};
126
127
128struct kvm_irqchip {
129 __u32 chip_id;
130 __u32 pad;
131 union {
132 char dummy[512]; /* reserving space */
133#ifdef __KVM_HAVE_PIT
134 struct kvm_pic_state pic;
135#endif
136#ifdef __KVM_HAVE_IOAPIC
137 struct kvm_ioapic_state ioapic;
138#endif
139 } chip;
140};
141
142/* for KVM_CREATE_PIT2 */
143struct kvm_pit_config {
144 __u32 flags;
145 __u32 pad[15];
146};
147
148#define KVM_PIT_SPEAKER_DUMMY 1
149
150struct kvm_s390_skeys {
151 __u64 start_gfn;
152 __u64 count;
153 __u64 skeydata_addr;
154 __u32 flags;
155 __u32 reserved[9];
156};
157
158#define KVM_S390_CMMA_PEEK (1 << 0)
159
160/**
161 * kvm_s390_cmma_log - Used for CMMA migration.
162 *
163 * Used both for input and output.
164 *
165 * @start_gfn: Guest page number to start from.
166 * @count: Size of the result buffer.
167 * @flags: Control operation mode via KVM_S390_CMMA_* flags
168 * @remaining: Used with KVM_S390_GET_CMMA_BITS. Indicates how many dirty
169 * pages are still remaining.
170 * @mask: Used with KVM_S390_SET_CMMA_BITS. Bitmap of bits to actually set
171 * in the PGSTE.
172 * @values: Pointer to the values buffer.
173 *
174 * Used in KVM_S390_{G,S}ET_CMMA_BITS ioctls.
175 */
176struct kvm_s390_cmma_log {
177 __u64 start_gfn;
178 __u32 count;
179 __u32 flags;
180 union {
181 __u64 remaining;
182 __u64 mask;
183 };
184 __u64 values;
185};
186
187struct kvm_hyperv_exit {
188#define KVM_EXIT_HYPERV_SYNIC 1
189#define KVM_EXIT_HYPERV_HCALL 2
190 __u32 type;
191 union {
192 struct {
193 __u32 msr;
194 __u64 control;
195 __u64 evt_page;
196 __u64 msg_page;
197 } synic;
198 struct {
199 __u64 input;
200 __u64 result;
201 __u64 params[2];
202 } hcall;
203 } u;
204};
205
206#define KVM_S390_GET_SKEYS_NONE 1
207#define KVM_S390_SKEYS_MAX 1048576
208
209#define KVM_EXIT_UNKNOWN 0
210#define KVM_EXIT_EXCEPTION 1
211#define KVM_EXIT_IO 2
212#define KVM_EXIT_HYPERCALL 3
213#define KVM_EXIT_DEBUG 4
214#define KVM_EXIT_HLT 5
215#define KVM_EXIT_MMIO 6
216#define KVM_EXIT_IRQ_WINDOW_OPEN 7
217#define KVM_EXIT_SHUTDOWN 8
218#define KVM_EXIT_FAIL_ENTRY 9
219#define KVM_EXIT_INTR 10
220#define KVM_EXIT_SET_TPR 11
221#define KVM_EXIT_TPR_ACCESS 12
222#define KVM_EXIT_S390_SIEIC 13
223#define KVM_EXIT_S390_RESET 14
224#define KVM_EXIT_DCR 15 /* deprecated */
225#define KVM_EXIT_NMI 16
226#define KVM_EXIT_INTERNAL_ERROR 17
227#define KVM_EXIT_OSI 18
228#define KVM_EXIT_PAPR_HCALL 19
229#define KVM_EXIT_S390_UCONTROL 20
230#define KVM_EXIT_WATCHDOG 21
231#define KVM_EXIT_S390_TSCH 22
232#define KVM_EXIT_EPR 23
233#define KVM_EXIT_SYSTEM_EVENT 24
234#define KVM_EXIT_S390_STSI 25
235#define KVM_EXIT_IOAPIC_EOI 26
236#define KVM_EXIT_HYPERV 27
237
238/* For KVM_EXIT_INTERNAL_ERROR */
239/* Emulate instruction failed. */
240#define KVM_INTERNAL_ERROR_EMULATION 1
241/* Encounter unexpected simultaneous exceptions. */
242#define KVM_INTERNAL_ERROR_SIMUL_EX 2
243/* Encounter unexpected vm-exit due to delivery event. */
244#define KVM_INTERNAL_ERROR_DELIVERY_EV 3
245
246/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
247struct kvm_run {
248 /* in */
249 __u8 request_interrupt_window;
250 __u8 immediate_exit;
251 __u8 padding1[6];
252
253 /* out */
254 __u32 exit_reason;
255 __u8 ready_for_interrupt_injection;
256 __u8 if_flag;
257 __u16 flags;
258
259 /* in (pre_kvm_run), out (post_kvm_run) */
260 __u64 cr8;
261 __u64 apic_base;
262
263#ifdef __KVM_S390
264 /* the processor status word for s390 */
265 __u64 psw_mask; /* psw upper half */
266 __u64 psw_addr; /* psw lower half */
267#endif
268 union {
269 /* KVM_EXIT_UNKNOWN */
270 struct {
271 __u64 hardware_exit_reason;
272 } hw;
273 /* KVM_EXIT_FAIL_ENTRY */
274 struct {
275 __u64 hardware_entry_failure_reason;
276 } fail_entry;
277 /* KVM_EXIT_EXCEPTION */
278 struct {
279 __u32 exception;
280 __u32 error_code;
281 } ex;
282 /* KVM_EXIT_IO */
283 struct {
284#define KVM_EXIT_IO_IN 0
285#define KVM_EXIT_IO_OUT 1
286 __u8 direction;
287 __u8 size; /* bytes */
288 __u16 port;
289 __u32 count;
290 __u64 data_offset; /* relative to kvm_run start */
291 } io;
292 /* KVM_EXIT_DEBUG */
293 struct {
294 struct kvm_debug_exit_arch arch;
295 } debug;
296 /* KVM_EXIT_MMIO */
297 struct {
298 __u64 phys_addr;
299 __u8 data[8];
300 __u32 len;
301 __u8 is_write;
302 } mmio;
303 /* KVM_EXIT_HYPERCALL */
304 struct {
305 __u64 nr;
306 __u64 args[6];
307 __u64 ret;
308 __u32 longmode;
309 __u32 pad;
310 } hypercall;
311 /* KVM_EXIT_TPR_ACCESS */
312 struct {
313 __u64 rip;
314 __u32 is_write;
315 __u32 pad;
316 } tpr_access;
317 /* KVM_EXIT_S390_SIEIC */
318 struct {
319 __u8 icptcode;
320 __u16 ipa;
321 __u32 ipb;
322 } s390_sieic;
323 /* KVM_EXIT_S390_RESET */
324#define KVM_S390_RESET_POR 1
325#define KVM_S390_RESET_CLEAR 2
326#define KVM_S390_RESET_SUBSYSTEM 4
327#define KVM_S390_RESET_CPU_INIT 8
328#define KVM_S390_RESET_IPL 16
329 __u64 s390_reset_flags;
330 /* KVM_EXIT_S390_UCONTROL */
331 struct {
332 __u64 trans_exc_code;
333 __u32 pgm_code;
334 } s390_ucontrol;
335 /* KVM_EXIT_DCR (deprecated) */
336 struct {
337 __u32 dcrn;
338 __u32 data;
339 __u8 is_write;
340 } dcr;
341 /* KVM_EXIT_INTERNAL_ERROR */
342 struct {
343 __u32 suberror;
344 /* Available with KVM_CAP_INTERNAL_ERROR_DATA: */
345 __u32 ndata;
346 __u64 data[16];
347 } internal;
348 /* KVM_EXIT_OSI */
349 struct {
350 __u64 gprs[32];
351 } osi;
352 /* KVM_EXIT_PAPR_HCALL */
353 struct {
354 __u64 nr;
355 __u64 ret;
356 __u64 args[9];
357 } papr_hcall;
358 /* KVM_EXIT_S390_TSCH */
359 struct {
360 __u16 subchannel_id;
361 __u16 subchannel_nr;
362 __u32 io_int_parm;
363 __u32 io_int_word;
364 __u32 ipb;
365 __u8 dequeued;
366 } s390_tsch;
367 /* KVM_EXIT_EPR */
368 struct {
369 __u32 epr;
370 } epr;
371 /* KVM_EXIT_SYSTEM_EVENT */
372 struct {
373#define KVM_SYSTEM_EVENT_SHUTDOWN 1
374#define KVM_SYSTEM_EVENT_RESET 2
375#define KVM_SYSTEM_EVENT_CRASH 3
376 __u32 type;
377 __u64 flags;
378 } system_event;
379 /* KVM_EXIT_S390_STSI */
380 struct {
381 __u64 addr;
382 __u8 ar;
383 __u8 reserved;
384 __u8 fc;
385 __u8 sel1;
386 __u16 sel2;
387 } s390_stsi;
388 /* KVM_EXIT_IOAPIC_EOI */
389 struct {
390 __u8 vector;
391 } eoi;
392 /* KVM_EXIT_HYPERV */
393 struct kvm_hyperv_exit hyperv;
394 /* Fix the size of the union. */
395 char padding[256];
396 };
397
398 /*
399 * shared registers between kvm and userspace.
400 * kvm_valid_regs specifies the register classes set by the host
401 * kvm_dirty_regs specified the register classes dirtied by userspace
402 * struct kvm_sync_regs is architecture specific, as well as the
403 * bits for kvm_valid_regs and kvm_dirty_regs
404 */
405 __u64 kvm_valid_regs;
406 __u64 kvm_dirty_regs;
407 union {
408 struct kvm_sync_regs regs;
409 char padding[2048];
410 } s;
411};
412
413/* for KVM_REGISTER_COALESCED_MMIO / KVM_UNREGISTER_COALESCED_MMIO */
414
415struct kvm_coalesced_mmio_zone {
416 __u64 addr;
417 __u32 size;
418 __u32 pad;
419};
420
421struct kvm_coalesced_mmio {
422 __u64 phys_addr;
423 __u32 len;
424 __u32 pad;
425 __u8 data[8];
426};
427
428struct kvm_coalesced_mmio_ring {
429 __u32 first, last;
430 struct kvm_coalesced_mmio coalesced_mmio[0];
431};
432
433#define KVM_COALESCED_MMIO_MAX \
434 ((PAGE_SIZE - sizeof(struct kvm_coalesced_mmio_ring)) / \
435 sizeof(struct kvm_coalesced_mmio))
436
437/* for KVM_TRANSLATE */
438struct kvm_translation {
439 /* in */
440 __u64 linear_address;
441
442 /* out */
443 __u64 physical_address;
444 __u8 valid;
445 __u8 writeable;
446 __u8 usermode;
447 __u8 pad[5];
448};
449
450/* for KVM_S390_MEM_OP */
451struct kvm_s390_mem_op {
452 /* in */
453 __u64 gaddr; /* the guest address */
454 __u64 flags; /* flags */
455 __u32 size; /* amount of bytes */
456 __u32 op; /* type of operation */
457 __u64 buf; /* buffer in userspace */
458 __u8 ar; /* the access register number */
459 __u8 reserved[31]; /* should be set to 0 */
460};
461/* types for kvm_s390_mem_op->op */
462#define KVM_S390_MEMOP_LOGICAL_READ 0
463#define KVM_S390_MEMOP_LOGICAL_WRITE 1
464/* flags for kvm_s390_mem_op->flags */
465#define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0)
466#define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1)
467
468/* for KVM_INTERRUPT */
469struct kvm_interrupt {
470 /* in */
471 __u32 irq;
472};
473
474/* for KVM_GET_DIRTY_LOG */
475struct kvm_dirty_log {
476 __u32 slot;
477 __u32 padding1;
478 union {
479 void __user *dirty_bitmap; /* one bit per page */
480 __u64 padding2;
481 };
482};
483
484/* for KVM_SET_SIGNAL_MASK */
485struct kvm_signal_mask {
486 __u32 len;
487 __u8 sigset[0];
488};
489
490/* for KVM_TPR_ACCESS_REPORTING */
491struct kvm_tpr_access_ctl {
492 __u32 enabled;
493 __u32 flags;
494 __u32 reserved[8];
495};
496
497/* for KVM_SET_VAPIC_ADDR */
498struct kvm_vapic_addr {
499 __u64 vapic_addr;
500};
501
502/* for KVM_SET_MP_STATE */
503
504/* not all states are valid on all architectures */
505#define KVM_MP_STATE_RUNNABLE 0
506#define KVM_MP_STATE_UNINITIALIZED 1
507#define KVM_MP_STATE_INIT_RECEIVED 2
508#define KVM_MP_STATE_HALTED 3
509#define KVM_MP_STATE_SIPI_RECEIVED 4
510#define KVM_MP_STATE_STOPPED 5
511#define KVM_MP_STATE_CHECK_STOP 6
512#define KVM_MP_STATE_OPERATING 7
513#define KVM_MP_STATE_LOAD 8
514
515struct kvm_mp_state {
516 __u32 mp_state;
517};
518
519struct kvm_s390_psw {
520 __u64 mask;
521 __u64 addr;
522};
523
524/* valid values for type in kvm_s390_interrupt */
525#define KVM_S390_SIGP_STOP 0xfffe0000u
526#define KVM_S390_PROGRAM_INT 0xfffe0001u
527#define KVM_S390_SIGP_SET_PREFIX 0xfffe0002u
528#define KVM_S390_RESTART 0xfffe0003u
529#define KVM_S390_INT_PFAULT_INIT 0xfffe0004u
530#define KVM_S390_INT_PFAULT_DONE 0xfffe0005u
531#define KVM_S390_MCHK 0xfffe1000u
532#define KVM_S390_INT_CLOCK_COMP 0xffff1004u
533#define KVM_S390_INT_CPU_TIMER 0xffff1005u
534#define KVM_S390_INT_VIRTIO 0xffff2603u
535#define KVM_S390_INT_SERVICE 0xffff2401u
536#define KVM_S390_INT_EMERGENCY 0xffff1201u
537#define KVM_S390_INT_EXTERNAL_CALL 0xffff1202u
538/* Anything below 0xfffe0000u is taken by INT_IO */
539#define KVM_S390_INT_IO(ai,cssid,ssid,schid) \
540 (((schid)) | \
541 ((ssid) << 16) | \
542 ((cssid) << 18) | \
543 ((ai) << 26))
544#define KVM_S390_INT_IO_MIN 0x00000000u
545#define KVM_S390_INT_IO_MAX 0xfffdffffu
546#define KVM_S390_INT_IO_AI_MASK 0x04000000u
547
548
549struct kvm_s390_interrupt {
550 __u32 type;
551 __u32 parm;
552 __u64 parm64;
553};
554
555struct kvm_s390_io_info {
556 __u16 subchannel_id;
557 __u16 subchannel_nr;
558 __u32 io_int_parm;
559 __u32 io_int_word;
560};
561
562struct kvm_s390_ext_info {
563 __u32 ext_params;
564 __u32 pad;
565 __u64 ext_params2;
566};
567
568struct kvm_s390_pgm_info {
569 __u64 trans_exc_code;
570 __u64 mon_code;
571 __u64 per_address;
572 __u32 data_exc_code;
573 __u16 code;
574 __u16 mon_class_nr;
575 __u8 per_code;
576 __u8 per_atmid;
577 __u8 exc_access_id;
578 __u8 per_access_id;
579 __u8 op_access_id;
580#define KVM_S390_PGM_FLAGS_ILC_VALID 0x01
581#define KVM_S390_PGM_FLAGS_ILC_0 0x02
582#define KVM_S390_PGM_FLAGS_ILC_1 0x04
583#define KVM_S390_PGM_FLAGS_ILC_MASK 0x06
584#define KVM_S390_PGM_FLAGS_NO_REWIND 0x08
585 __u8 flags;
586 __u8 pad[2];
587};
588
589struct kvm_s390_prefix_info {
590 __u32 address;
591};
592
593struct kvm_s390_extcall_info {
594 __u16 code;
595};
596
597struct kvm_s390_emerg_info {
598 __u16 code;
599};
600
601#define KVM_S390_STOP_FLAG_STORE_STATUS 0x01
602struct kvm_s390_stop_info {
603 __u32 flags;
604};
605
606struct kvm_s390_mchk_info {
607 __u64 cr14;
608 __u64 mcic;
609 __u64 failing_storage_address;
610 __u32 ext_damage_code;
611 __u32 pad;
612 __u8 fixed_logout[16];
613};
614
615struct kvm_s390_irq {
616 __u64 type;
617 union {
618 struct kvm_s390_io_info io;
619 struct kvm_s390_ext_info ext;
620 struct kvm_s390_pgm_info pgm;
621 struct kvm_s390_emerg_info emerg;
622 struct kvm_s390_extcall_info extcall;
623 struct kvm_s390_prefix_info prefix;
624 struct kvm_s390_stop_info stop;
625 struct kvm_s390_mchk_info mchk;
626 char reserved[64];
627 } u;
628};
629
630struct kvm_s390_irq_state {
631 __u64 buf;
632 __u32 flags;
633 __u32 len;
634 __u32 reserved[4];
635};
636
637/* for KVM_SET_GUEST_DEBUG */
638
639#define KVM_GUESTDBG_ENABLE 0x00000001
640#define KVM_GUESTDBG_SINGLESTEP 0x00000002
641
642struct kvm_guest_debug {
643 __u32 control;
644 __u32 pad;
645 struct kvm_guest_debug_arch arch;
646};
647
648enum {
649 kvm_ioeventfd_flag_nr_datamatch,
650 kvm_ioeventfd_flag_nr_pio,
651 kvm_ioeventfd_flag_nr_deassign,
652 kvm_ioeventfd_flag_nr_virtio_ccw_notify,
653 kvm_ioeventfd_flag_nr_fast_mmio,
654 kvm_ioeventfd_flag_nr_max,
655};
656
657#define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
658#define KVM_IOEVENTFD_FLAG_PIO (1 << kvm_ioeventfd_flag_nr_pio)
659#define KVM_IOEVENTFD_FLAG_DEASSIGN (1 << kvm_ioeventfd_flag_nr_deassign)
660#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \
661 (1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify)
662
663#define KVM_IOEVENTFD_VALID_FLAG_MASK ((1 << kvm_ioeventfd_flag_nr_max) - 1)
664
665struct kvm_ioeventfd {
666 __u64 datamatch;
667 __u64 addr; /* legal pio/mmio address */
668 __u32 len; /* 1, 2, 4, or 8 bytes; or 0 to ignore length */
669 __s32 fd;
670 __u32 flags;
671 __u8 pad[36];
672};
673
674/* for KVM_ENABLE_CAP */
675struct kvm_enable_cap {
676 /* in */
677 __u32 cap;
678 __u32 flags;
679 __u64 args[4];
680 __u8 pad[64];
681};
682
683/* for KVM_PPC_GET_PVINFO */
684
685#define KVM_PPC_PVINFO_FLAGS_EV_IDLE (1<<0)
686
687struct kvm_ppc_pvinfo {
688 /* out */
689 __u32 flags;
690 __u32 hcall[4];
691 __u8 pad[108];
692};
693
694/* for KVM_PPC_GET_SMMU_INFO */
695#define KVM_PPC_PAGE_SIZES_MAX_SZ 8
696
697struct kvm_ppc_one_page_size {
698 __u32 page_shift; /* Page shift (or 0) */
699 __u32 pte_enc; /* Encoding in the HPTE (>>12) */
700};
701
702struct kvm_ppc_one_seg_page_size {
703 __u32 page_shift; /* Base page shift of segment (or 0) */
704 __u32 slb_enc; /* SLB encoding for BookS */
705 struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ];
706};
707
708#define KVM_PPC_PAGE_SIZES_REAL 0x00000001
709#define KVM_PPC_1T_SEGMENTS 0x00000002
710
711struct kvm_ppc_smmu_info {
712 __u64 flags;
713 __u32 slb_size;
714 __u32 pad;
715 struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
716};
717
718/* for KVM_PPC_RESIZE_HPT_{PREPARE,COMMIT} */
719struct kvm_ppc_resize_hpt {
720 __u64 flags;
721 __u32 shift;
722 __u32 pad;
723};
724
725#define KVMIO 0xAE
726
727/* machine type bits, to be used as argument to KVM_CREATE_VM */
728#define KVM_VM_S390_UCONTROL 1
729
730/* on ppc, 0 indicate default, 1 should force HV and 2 PR */
731#define KVM_VM_PPC_HV 1
732#define KVM_VM_PPC_PR 2
733
734/* on MIPS, 0 forces trap & emulate, 1 forces VZ ASE */
735#define KVM_VM_MIPS_TE 0
736#define KVM_VM_MIPS_VZ 1
737
738#define KVM_S390_SIE_PAGE_OFFSET 1
739
740/*
741 * ioctls for /dev/kvm fds:
742 */
743#define KVM_GET_API_VERSION _IO(KVMIO, 0x00)
744#define KVM_CREATE_VM _IO(KVMIO, 0x01) /* returns a VM fd */
745#define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 0x02, struct kvm_msr_list)
746
747#define KVM_S390_ENABLE_SIE _IO(KVMIO, 0x06)
748/*
749 * Check if a kvm extension is available. Argument is extension number,
750 * return is 1 (yes) or 0 (no, sorry).
751 */
752#define KVM_CHECK_EXTENSION _IO(KVMIO, 0x03)
753/*
754 * Get size for mmap(vcpu_fd)
755 */
756#define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04) /* in bytes */
757#define KVM_GET_SUPPORTED_CPUID _IOWR(KVMIO, 0x05, struct kvm_cpuid2)
758#define KVM_TRACE_ENABLE __KVM_DEPRECATED_MAIN_W_0x06
759#define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07
760#define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08
761#define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2)
762
763/*
764 * Extension capability list.
765 */
766#define KVM_CAP_IRQCHIP 0
767#define KVM_CAP_HLT 1
768#define KVM_CAP_MMU_SHADOW_CACHE_CONTROL 2
769#define KVM_CAP_USER_MEMORY 3
770#define KVM_CAP_SET_TSS_ADDR 4
771#define KVM_CAP_VAPIC 6
772#define KVM_CAP_EXT_CPUID 7
773#define KVM_CAP_CLOCKSOURCE 8
774#define KVM_CAP_NR_VCPUS 9 /* returns recommended max vcpus per vm */
775#define KVM_CAP_NR_MEMSLOTS 10 /* returns max memory slots per vm */
776#define KVM_CAP_PIT 11
777#define KVM_CAP_NOP_IO_DELAY 12
778#define KVM_CAP_PV_MMU 13
779#define KVM_CAP_MP_STATE 14
780#define KVM_CAP_COALESCED_MMIO 15
781#define KVM_CAP_SYNC_MMU 16 /* Changes to host mmap are reflected in guest */
782#define KVM_CAP_IOMMU 18
783/* Bug in KVM_SET_USER_MEMORY_REGION fixed: */
784#define KVM_CAP_DESTROY_MEMORY_REGION_WORKS 21
785#define KVM_CAP_USER_NMI 22
786#ifdef __KVM_HAVE_GUEST_DEBUG
787#define KVM_CAP_SET_GUEST_DEBUG 23
788#endif
789#ifdef __KVM_HAVE_PIT
790#define KVM_CAP_REINJECT_CONTROL 24
791#endif
792#define KVM_CAP_IRQ_ROUTING 25
793#define KVM_CAP_IRQ_INJECT_STATUS 26
794#define KVM_CAP_ASSIGN_DEV_IRQ 29
795/* Another bug in KVM_SET_USER_MEMORY_REGION fixed: */
796#define KVM_CAP_JOIN_MEMORY_REGIONS_WORKS 30
797#ifdef __KVM_HAVE_MCE
798#define KVM_CAP_MCE 31
799#endif
800#define KVM_CAP_IRQFD 32
801#ifdef __KVM_HAVE_PIT
802#define KVM_CAP_PIT2 33
803#endif
804#define KVM_CAP_SET_BOOT_CPU_ID 34
805#ifdef __KVM_HAVE_PIT_STATE2
806#define KVM_CAP_PIT_STATE2 35
807#endif
808#define KVM_CAP_IOEVENTFD 36
809#define KVM_CAP_SET_IDENTITY_MAP_ADDR 37
810#ifdef __KVM_HAVE_XEN_HVM
811#define KVM_CAP_XEN_HVM 38
812#endif
813#define KVM_CAP_ADJUST_CLOCK 39
814#define KVM_CAP_INTERNAL_ERROR_DATA 40
815#ifdef __KVM_HAVE_VCPU_EVENTS
816#define KVM_CAP_VCPU_EVENTS 41
817#endif
818#define KVM_CAP_S390_PSW 42
819#define KVM_CAP_PPC_SEGSTATE 43
820#define KVM_CAP_HYPERV 44
821#define KVM_CAP_HYPERV_VAPIC 45
822#define KVM_CAP_HYPERV_SPIN 46
823#define KVM_CAP_PCI_SEGMENT 47
824#define KVM_CAP_PPC_PAIRED_SINGLES 48
825#define KVM_CAP_INTR_SHADOW 49
826#ifdef __KVM_HAVE_DEBUGREGS
827#define KVM_CAP_DEBUGREGS 50
828#endif
829#define KVM_CAP_X86_ROBUST_SINGLESTEP 51
830#define KVM_CAP_PPC_OSI 52
831#define KVM_CAP_PPC_UNSET_IRQ 53
832#define KVM_CAP_ENABLE_CAP 54
833#ifdef __KVM_HAVE_XSAVE
834#define KVM_CAP_XSAVE 55
835#endif
836#ifdef __KVM_HAVE_XCRS
837#define KVM_CAP_XCRS 56
838#endif
839#define KVM_CAP_PPC_GET_PVINFO 57
840#define KVM_CAP_PPC_IRQ_LEVEL 58
841#define KVM_CAP_ASYNC_PF 59
842#define KVM_CAP_TSC_CONTROL 60
843#define KVM_CAP_GET_TSC_KHZ 61
844#define KVM_CAP_PPC_BOOKE_SREGS 62
845#define KVM_CAP_SPAPR_TCE 63
846#define KVM_CAP_PPC_SMT 64
847#define KVM_CAP_PPC_RMA 65
848#define KVM_CAP_MAX_VCPUS 66 /* returns max vcpus per vm */
849#define KVM_CAP_PPC_HIOR 67
850#define KVM_CAP_PPC_PAPR 68
851#define KVM_CAP_SW_TLB 69
852#define KVM_CAP_ONE_REG 70
853#define KVM_CAP_S390_GMAP 71
854#define KVM_CAP_TSC_DEADLINE_TIMER 72
855#define KVM_CAP_S390_UCONTROL 73
856#define KVM_CAP_SYNC_REGS 74
857#define KVM_CAP_PCI_2_3 75
858#define KVM_CAP_KVMCLOCK_CTRL 76
859#define KVM_CAP_SIGNAL_MSI 77
860#define KVM_CAP_PPC_GET_SMMU_INFO 78
861#define KVM_CAP_S390_COW 79
862#define KVM_CAP_PPC_ALLOC_HTAB 80
863#define KVM_CAP_READONLY_MEM 81
864#define KVM_CAP_IRQFD_RESAMPLE 82
865#define KVM_CAP_PPC_BOOKE_WATCHDOG 83
866#define KVM_CAP_PPC_HTAB_FD 84
867#define KVM_CAP_S390_CSS_SUPPORT 85
868#define KVM_CAP_PPC_EPR 86
869#define KVM_CAP_ARM_PSCI 87
870#define KVM_CAP_ARM_SET_DEVICE_ADDR 88
871#define KVM_CAP_DEVICE_CTRL 89
872#define KVM_CAP_IRQ_MPIC 90
873#define KVM_CAP_PPC_RTAS 91
874#define KVM_CAP_IRQ_XICS 92
875#define KVM_CAP_ARM_EL1_32BIT 93
876#define KVM_CAP_SPAPR_MULTITCE 94
877#define KVM_CAP_EXT_EMUL_CPUID 95
878#define KVM_CAP_HYPERV_TIME 96
879#define KVM_CAP_IOAPIC_POLARITY_IGNORED 97
880#define KVM_CAP_ENABLE_CAP_VM 98
881#define KVM_CAP_S390_IRQCHIP 99
882#define KVM_CAP_IOEVENTFD_NO_LENGTH 100
883#define KVM_CAP_VM_ATTRIBUTES 101
884#define KVM_CAP_ARM_PSCI_0_2 102
885#define KVM_CAP_PPC_FIXUP_HCALL 103
886#define KVM_CAP_PPC_ENABLE_HCALL 104
887#define KVM_CAP_CHECK_EXTENSION_VM 105
888#define KVM_CAP_S390_USER_SIGP 106
889#define KVM_CAP_S390_VECTOR_REGISTERS 107
890#define KVM_CAP_S390_MEM_OP 108
891#define KVM_CAP_S390_USER_STSI 109
892#define KVM_CAP_S390_SKEYS 110
893#define KVM_CAP_MIPS_FPU 111
894#define KVM_CAP_MIPS_MSA 112
895#define KVM_CAP_S390_INJECT_IRQ 113
896#define KVM_CAP_S390_IRQ_STATE 114
897#define KVM_CAP_PPC_HWRNG 115
898#define KVM_CAP_DISABLE_QUIRKS 116
899#define KVM_CAP_X86_SMM 117
900#define KVM_CAP_MULTI_ADDRESS_SPACE 118
901#define KVM_CAP_GUEST_DEBUG_HW_BPS 119
902#define KVM_CAP_GUEST_DEBUG_HW_WPS 120
903#define KVM_CAP_SPLIT_IRQCHIP 121
904#define KVM_CAP_IOEVENTFD_ANY_LENGTH 122
905#define KVM_CAP_HYPERV_SYNIC 123
906#define KVM_CAP_S390_RI 124
907#define KVM_CAP_SPAPR_TCE_64 125
908#define KVM_CAP_ARM_PMU_V3 126
909#define KVM_CAP_VCPU_ATTRIBUTES 127
910#define KVM_CAP_MAX_VCPU_ID 128
911#define KVM_CAP_X2APIC_API 129
912#define KVM_CAP_S390_USER_INSTR0 130
913#define KVM_CAP_MSI_DEVID 131
914#define KVM_CAP_PPC_HTM 132
915#define KVM_CAP_SPAPR_RESIZE_HPT 133
916#define KVM_CAP_PPC_MMU_RADIX 134
917#define KVM_CAP_PPC_MMU_HASH_V3 135
918#define KVM_CAP_IMMEDIATE_EXIT 136
919#define KVM_CAP_MIPS_VZ 137
920#define KVM_CAP_MIPS_TE 138
921#define KVM_CAP_MIPS_64BIT 139
922#define KVM_CAP_S390_GS 140
923#define KVM_CAP_S390_AIS 141
924#define KVM_CAP_SPAPR_TCE_VFIO 142
925#define KVM_CAP_X86_GUEST_MWAIT 143
926#define KVM_CAP_ARM_USER_IRQ 144
927#define KVM_CAP_S390_CMMA_MIGRATION 145
928#define KVM_CAP_PPC_FWNMI 146
929#define KVM_CAP_PPC_SMT_POSSIBLE 147
930#define KVM_CAP_HYPERV_SYNIC2 148
931#define KVM_CAP_HYPERV_VP_INDEX 149
932
933#ifdef KVM_CAP_IRQ_ROUTING
934
935struct kvm_irq_routing_irqchip {
936 __u32 irqchip;
937 __u32 pin;
938};
939
940struct kvm_irq_routing_msi {
941 __u32 address_lo;
942 __u32 address_hi;
943 __u32 data;
944 union {
945 __u32 pad;
946 __u32 devid;
947 };
948};
949
950struct kvm_irq_routing_s390_adapter {
951 __u64 ind_addr;
952 __u64 summary_addr;
953 __u64 ind_offset;
954 __u32 summary_offset;
955 __u32 adapter_id;
956};
957
958struct kvm_irq_routing_hv_sint {
959 __u32 vcpu;
960 __u32 sint;
961};
962
963/* gsi routing entry types */
964#define KVM_IRQ_ROUTING_IRQCHIP 1
965#define KVM_IRQ_ROUTING_MSI 2
966#define KVM_IRQ_ROUTING_S390_ADAPTER 3
967#define KVM_IRQ_ROUTING_HV_SINT 4
968
969struct kvm_irq_routing_entry {
970 __u32 gsi;
971 __u32 type;
972 __u32 flags;
973 __u32 pad;
974 union {
975 struct kvm_irq_routing_irqchip irqchip;
976 struct kvm_irq_routing_msi msi;
977 struct kvm_irq_routing_s390_adapter adapter;
978 struct kvm_irq_routing_hv_sint hv_sint;
979 __u32 pad[8];
980 } u;
981};
982
983struct kvm_irq_routing {
984 __u32 nr;
985 __u32 flags;
986 struct kvm_irq_routing_entry entries[0];
987};
988
989#endif
990
991#ifdef KVM_CAP_MCE
992/* x86 MCE */
993struct kvm_x86_mce {
994 __u64 status;
995 __u64 addr;
996 __u64 misc;
997 __u64 mcg_status;
998 __u8 bank;
999 __u8 pad1[7];
1000 __u64 pad2[3];
1001};
1002#endif
1003
1004#ifdef KVM_CAP_XEN_HVM
1005struct kvm_xen_hvm_config {
1006 __u32 flags;
1007 __u32 msr;
1008 __u64 blob_addr_32;
1009 __u64 blob_addr_64;
1010 __u8 blob_size_32;
1011 __u8 blob_size_64;
1012 __u8 pad2[30];
1013};
1014#endif
1015
1016#define KVM_IRQFD_FLAG_DEASSIGN (1 << 0)
1017/*
1018 * Available with KVM_CAP_IRQFD_RESAMPLE
1019 *
1020 * KVM_IRQFD_FLAG_RESAMPLE indicates resamplefd is valid and specifies
1021 * the irqfd to operate in resampling mode for level triggered interrupt
1022 * emulation. See Documentation/virtual/kvm/api.txt.
1023 */
1024#define KVM_IRQFD_FLAG_RESAMPLE (1 << 1)
1025
1026struct kvm_irqfd {
1027 __u32 fd;
1028 __u32 gsi;
1029 __u32 flags;
1030 __u32 resamplefd;
1031 __u8 pad[16];
1032};
1033
1034/* For KVM_CAP_ADJUST_CLOCK */
1035
1036/* Do not use 1, KVM_CHECK_EXTENSION returned it before we had flags. */
1037#define KVM_CLOCK_TSC_STABLE 2
1038
1039struct kvm_clock_data {
1040 __u64 clock;
1041 __u32 flags;
1042 __u32 pad[9];
1043};
1044
1045/* For KVM_CAP_SW_TLB */
1046
1047#define KVM_MMU_FSL_BOOKE_NOHV 0
1048#define KVM_MMU_FSL_BOOKE_HV 1
1049
1050struct kvm_config_tlb {
1051 __u64 params;
1052 __u64 array;
1053 __u32 mmu_type;
1054 __u32 array_len;
1055};
1056
1057struct kvm_dirty_tlb {
1058 __u64 bitmap;
1059 __u32 num_dirty;
1060};
1061
1062/* Available with KVM_CAP_ONE_REG */
1063
1064#define KVM_REG_ARCH_MASK 0xff00000000000000ULL
1065#define KVM_REG_GENERIC 0x0000000000000000ULL
1066
1067/*
1068 * Architecture specific registers are to be defined in arch headers and
1069 * ORed with the arch identifier.
1070 */
1071#define KVM_REG_PPC 0x1000000000000000ULL
1072#define KVM_REG_X86 0x2000000000000000ULL
1073#define KVM_REG_IA64 0x3000000000000000ULL
1074#define KVM_REG_ARM 0x4000000000000000ULL
1075#define KVM_REG_S390 0x5000000000000000ULL
1076#define KVM_REG_ARM64 0x6000000000000000ULL
1077#define KVM_REG_MIPS 0x7000000000000000ULL
1078
1079#define KVM_REG_SIZE_SHIFT 52
1080#define KVM_REG_SIZE_MASK 0x00f0000000000000ULL
1081#define KVM_REG_SIZE_U8 0x0000000000000000ULL
1082#define KVM_REG_SIZE_U16 0x0010000000000000ULL
1083#define KVM_REG_SIZE_U32 0x0020000000000000ULL
1084#define KVM_REG_SIZE_U64 0x0030000000000000ULL
1085#define KVM_REG_SIZE_U128 0x0040000000000000ULL
1086#define KVM_REG_SIZE_U256 0x0050000000000000ULL
1087#define KVM_REG_SIZE_U512 0x0060000000000000ULL
1088#define KVM_REG_SIZE_U1024 0x0070000000000000ULL
1089
1090struct kvm_reg_list {
1091 __u64 n; /* number of regs */
1092 __u64 reg[0];
1093};
1094
1095struct kvm_one_reg {
1096 __u64 id;
1097 __u64 addr;
1098};
1099
1100#define KVM_MSI_VALID_DEVID (1U << 0)
1101struct kvm_msi {
1102 __u32 address_lo;
1103 __u32 address_hi;
1104 __u32 data;
1105 __u32 flags;
1106 __u32 devid;
1107 __u8 pad[12];
1108};
1109
1110struct kvm_arm_device_addr {
1111 __u64 id;
1112 __u64 addr;
1113};
1114
1115/*
1116 * Device control API, available with KVM_CAP_DEVICE_CTRL
1117 */
1118#define KVM_CREATE_DEVICE_TEST 1
1119
1120struct kvm_create_device {
1121 __u32 type; /* in: KVM_DEV_TYPE_xxx */
1122 __u32 fd; /* out: device handle */
1123 __u32 flags; /* in: KVM_CREATE_DEVICE_xxx */
1124};
1125
1126struct kvm_device_attr {
1127 __u32 flags; /* no flags currently defined */
1128 __u32 group; /* device-defined */
1129 __u64 attr; /* group-defined */
1130 __u64 addr; /* userspace address of attr data */
1131};
1132
1133#define KVM_DEV_VFIO_GROUP 1
1134#define KVM_DEV_VFIO_GROUP_ADD 1
1135#define KVM_DEV_VFIO_GROUP_DEL 2
1136#define KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE 3
1137
1138enum kvm_device_type {
1139 KVM_DEV_TYPE_FSL_MPIC_20 = 1,
1140#define KVM_DEV_TYPE_FSL_MPIC_20 KVM_DEV_TYPE_FSL_MPIC_20
1141 KVM_DEV_TYPE_FSL_MPIC_42,
1142#define KVM_DEV_TYPE_FSL_MPIC_42 KVM_DEV_TYPE_FSL_MPIC_42
1143 KVM_DEV_TYPE_XICS,
1144#define KVM_DEV_TYPE_XICS KVM_DEV_TYPE_XICS
1145 KVM_DEV_TYPE_VFIO,
1146#define KVM_DEV_TYPE_VFIO KVM_DEV_TYPE_VFIO
1147 KVM_DEV_TYPE_ARM_VGIC_V2,
1148#define KVM_DEV_TYPE_ARM_VGIC_V2 KVM_DEV_TYPE_ARM_VGIC_V2
1149 KVM_DEV_TYPE_FLIC,
1150#define KVM_DEV_TYPE_FLIC KVM_DEV_TYPE_FLIC
1151 KVM_DEV_TYPE_ARM_VGIC_V3,
1152#define KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_V3
1153 KVM_DEV_TYPE_ARM_VGIC_ITS,
1154#define KVM_DEV_TYPE_ARM_VGIC_ITS KVM_DEV_TYPE_ARM_VGIC_ITS
1155 KVM_DEV_TYPE_MAX,
1156};
1157
1158struct kvm_vfio_spapr_tce {
1159 __s32 groupfd;
1160 __s32 tablefd;
1161};
1162
1163/*
1164 * ioctls for VM fds
1165 */
1166#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 0x40, struct kvm_memory_region)
1167/*
1168 * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns
1169 * a vcpu fd.
1170 */
1171#define KVM_CREATE_VCPU _IO(KVMIO, 0x41)
1172#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log)
1173/* KVM_SET_MEMORY_ALIAS is obsolete: */
1174#define KVM_SET_MEMORY_ALIAS _IOW(KVMIO, 0x43, struct kvm_memory_alias)
1175#define KVM_SET_NR_MMU_PAGES _IO(KVMIO, 0x44)
1176#define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45)
1177#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46, \
1178 struct kvm_userspace_memory_region)
1179#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)
1180#define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64)
1181
1182/* enable ucontrol for s390 */
1183struct kvm_s390_ucas_mapping {
1184 __u64 user_addr;
1185 __u64 vcpu_addr;
1186 __u64 length;
1187};
1188#define KVM_S390_UCAS_MAP _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping)
1189#define KVM_S390_UCAS_UNMAP _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping)
1190#define KVM_S390_VCPU_FAULT _IOW(KVMIO, 0x52, unsigned long)
1191
1192/* Device model IOC */
1193#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)
1194#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
1195#define KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip)
1196#define KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip)
1197#define KVM_CREATE_PIT _IO(KVMIO, 0x64)
1198#define KVM_GET_PIT _IOWR(KVMIO, 0x65, struct kvm_pit_state)
1199#define KVM_SET_PIT _IOR(KVMIO, 0x66, struct kvm_pit_state)
1200#define KVM_IRQ_LINE_STATUS _IOWR(KVMIO, 0x67, struct kvm_irq_level)
1201#define KVM_REGISTER_COALESCED_MMIO \
1202 _IOW(KVMIO, 0x67, struct kvm_coalesced_mmio_zone)
1203#define KVM_UNREGISTER_COALESCED_MMIO \
1204 _IOW(KVMIO, 0x68, struct kvm_coalesced_mmio_zone)
1205#define KVM_ASSIGN_PCI_DEVICE _IOR(KVMIO, 0x69, \
1206 struct kvm_assigned_pci_dev)
1207#define KVM_SET_GSI_ROUTING _IOW(KVMIO, 0x6a, struct kvm_irq_routing)
1208/* deprecated, replaced by KVM_ASSIGN_DEV_IRQ */
1209#define KVM_ASSIGN_IRQ __KVM_DEPRECATED_VM_R_0x70
1210#define KVM_ASSIGN_DEV_IRQ _IOW(KVMIO, 0x70, struct kvm_assigned_irq)
1211#define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71)
1212#define KVM_DEASSIGN_PCI_DEVICE _IOW(KVMIO, 0x72, \
1213 struct kvm_assigned_pci_dev)
1214#define KVM_ASSIGN_SET_MSIX_NR _IOW(KVMIO, 0x73, \
1215 struct kvm_assigned_msix_nr)
1216#define KVM_ASSIGN_SET_MSIX_ENTRY _IOW(KVMIO, 0x74, \
1217 struct kvm_assigned_msix_entry)
1218#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq)
1219#define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd)
1220#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config)
1221#define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78)
1222#define KVM_IOEVENTFD _IOW(KVMIO, 0x79, struct kvm_ioeventfd)
1223#define KVM_XEN_HVM_CONFIG _IOW(KVMIO, 0x7a, struct kvm_xen_hvm_config)
1224#define KVM_SET_CLOCK _IOW(KVMIO, 0x7b, struct kvm_clock_data)
1225#define KVM_GET_CLOCK _IOR(KVMIO, 0x7c, struct kvm_clock_data)
1226/* Available with KVM_CAP_PIT_STATE2 */
1227#define KVM_GET_PIT2 _IOR(KVMIO, 0x9f, struct kvm_pit_state2)
1228#define KVM_SET_PIT2 _IOW(KVMIO, 0xa0, struct kvm_pit_state2)
1229/* Available with KVM_CAP_PPC_GET_PVINFO */
1230#define KVM_PPC_GET_PVINFO _IOW(KVMIO, 0xa1, struct kvm_ppc_pvinfo)
1231/* Available with KVM_CAP_TSC_CONTROL */
1232#define KVM_SET_TSC_KHZ _IO(KVMIO, 0xa2)
1233#define KVM_GET_TSC_KHZ _IO(KVMIO, 0xa3)
1234/* Available with KVM_CAP_PCI_2_3 */
1235#define KVM_ASSIGN_SET_INTX_MASK _IOW(KVMIO, 0xa4, \
1236 struct kvm_assigned_pci_dev)
1237/* Available with KVM_CAP_SIGNAL_MSI */
1238#define KVM_SIGNAL_MSI _IOW(KVMIO, 0xa5, struct kvm_msi)
1239/* Available with KVM_CAP_PPC_GET_SMMU_INFO */
1240#define KVM_PPC_GET_SMMU_INFO _IOR(KVMIO, 0xa6, struct kvm_ppc_smmu_info)
1241/* Available with KVM_CAP_PPC_ALLOC_HTAB */
1242#define KVM_PPC_ALLOCATE_HTAB _IOWR(KVMIO, 0xa7, __u32)
1243#define KVM_CREATE_SPAPR_TCE _IOW(KVMIO, 0xa8, struct kvm_create_spapr_tce)
1244#define KVM_CREATE_SPAPR_TCE_64 _IOW(KVMIO, 0xa8, \
1245 struct kvm_create_spapr_tce_64)
1246/* Available with KVM_CAP_RMA */
1247#define KVM_ALLOCATE_RMA _IOR(KVMIO, 0xa9, struct kvm_allocate_rma)
1248/* Available with KVM_CAP_PPC_HTAB_FD */
1249#define KVM_PPC_GET_HTAB_FD _IOW(KVMIO, 0xaa, struct kvm_get_htab_fd)
1250/* Available with KVM_CAP_ARM_SET_DEVICE_ADDR */
1251#define KVM_ARM_SET_DEVICE_ADDR _IOW(KVMIO, 0xab, struct kvm_arm_device_addr)
1252/* Available with KVM_CAP_PPC_RTAS */
1253#define KVM_PPC_RTAS_DEFINE_TOKEN _IOW(KVMIO, 0xac, struct kvm_rtas_token_args)
1254/* Available with KVM_CAP_SPAPR_RESIZE_HPT */
1255#define KVM_PPC_RESIZE_HPT_PREPARE _IOR(KVMIO, 0xad, struct kvm_ppc_resize_hpt)
1256#define KVM_PPC_RESIZE_HPT_COMMIT _IOR(KVMIO, 0xae, struct kvm_ppc_resize_hpt)
1257/* Available with KVM_CAP_PPC_RADIX_MMU or KVM_CAP_PPC_HASH_MMU_V3 */
1258#define KVM_PPC_CONFIGURE_V3_MMU _IOW(KVMIO, 0xaf, struct kvm_ppc_mmuv3_cfg)
1259/* Available with KVM_CAP_PPC_RADIX_MMU */
1260#define KVM_PPC_GET_RMMU_INFO _IOW(KVMIO, 0xb0, struct kvm_ppc_rmmu_info)
1261
1262/* ioctl for vm fd */
1263#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)
1264
1265/* ioctls for fds returned by KVM_CREATE_DEVICE */
1266#define KVM_SET_DEVICE_ATTR _IOW(KVMIO, 0xe1, struct kvm_device_attr)
1267#define KVM_GET_DEVICE_ATTR _IOW(KVMIO, 0xe2, struct kvm_device_attr)
1268#define KVM_HAS_DEVICE_ATTR _IOW(KVMIO, 0xe3, struct kvm_device_attr)
1269
1270/*
1271 * ioctls for vcpu fds
1272 */
1273#define KVM_RUN _IO(KVMIO, 0x80)
1274#define KVM_GET_REGS _IOR(KVMIO, 0x81, struct kvm_regs)
1275#define KVM_SET_REGS _IOW(KVMIO, 0x82, struct kvm_regs)
1276#define KVM_GET_SREGS _IOR(KVMIO, 0x83, struct kvm_sregs)
1277#define KVM_SET_SREGS _IOW(KVMIO, 0x84, struct kvm_sregs)
1278#define KVM_TRANSLATE _IOWR(KVMIO, 0x85, struct kvm_translation)
1279#define KVM_INTERRUPT _IOW(KVMIO, 0x86, struct kvm_interrupt)
1280/* KVM_DEBUG_GUEST is no longer supported, use KVM_SET_GUEST_DEBUG instead */
1281#define KVM_DEBUG_GUEST __KVM_DEPRECATED_VCPU_W_0x87
1282#define KVM_GET_MSRS _IOWR(KVMIO, 0x88, struct kvm_msrs)
1283#define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs)
1284#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid)
1285#define KVM_SET_SIGNAL_MASK _IOW(KVMIO, 0x8b, struct kvm_signal_mask)
1286#define KVM_GET_FPU _IOR(KVMIO, 0x8c, struct kvm_fpu)
1287#define KVM_SET_FPU _IOW(KVMIO, 0x8d, struct kvm_fpu)
1288#define KVM_GET_LAPIC _IOR(KVMIO, 0x8e, struct kvm_lapic_state)
1289#define KVM_SET_LAPIC _IOW(KVMIO, 0x8f, struct kvm_lapic_state)
1290#define KVM_SET_CPUID2 _IOW(KVMIO, 0x90, struct kvm_cpuid2)
1291#define KVM_GET_CPUID2 _IOWR(KVMIO, 0x91, struct kvm_cpuid2)
1292/* Available with KVM_CAP_VAPIC */
1293#define KVM_TPR_ACCESS_REPORTING _IOWR(KVMIO, 0x92, struct kvm_tpr_access_ctl)
1294/* Available with KVM_CAP_VAPIC */
1295#define KVM_SET_VAPIC_ADDR _IOW(KVMIO, 0x93, struct kvm_vapic_addr)
1296/* valid for virtual machine (for floating interrupt)_and_ vcpu */
1297#define KVM_S390_INTERRUPT _IOW(KVMIO, 0x94, struct kvm_s390_interrupt)
1298/* store status for s390 */
1299#define KVM_S390_STORE_STATUS_NOADDR (-1ul)
1300#define KVM_S390_STORE_STATUS_PREFIXED (-2ul)
1301#define KVM_S390_STORE_STATUS _IOW(KVMIO, 0x95, unsigned long)
1302/* initial ipl psw for s390 */
1303#define KVM_S390_SET_INITIAL_PSW _IOW(KVMIO, 0x96, struct kvm_s390_psw)
1304/* initial reset for s390 */
1305#define KVM_S390_INITIAL_RESET _IO(KVMIO, 0x97)
1306#define KVM_GET_MP_STATE _IOR(KVMIO, 0x98, struct kvm_mp_state)
1307#define KVM_SET_MP_STATE _IOW(KVMIO, 0x99, struct kvm_mp_state)
1308/* Available with KVM_CAP_USER_NMI */
1309#define KVM_NMI _IO(KVMIO, 0x9a)
1310/* Available with KVM_CAP_SET_GUEST_DEBUG */
1311#define KVM_SET_GUEST_DEBUG _IOW(KVMIO, 0x9b, struct kvm_guest_debug)
1312/* MCE for x86 */
1313#define KVM_X86_SETUP_MCE _IOW(KVMIO, 0x9c, __u64)
1314#define KVM_X86_GET_MCE_CAP_SUPPORTED _IOR(KVMIO, 0x9d, __u64)
1315#define KVM_X86_SET_MCE _IOW(KVMIO, 0x9e, struct kvm_x86_mce)
1316/* Available with KVM_CAP_VCPU_EVENTS */
1317#define KVM_GET_VCPU_EVENTS _IOR(KVMIO, 0x9f, struct kvm_vcpu_events)
1318#define KVM_SET_VCPU_EVENTS _IOW(KVMIO, 0xa0, struct kvm_vcpu_events)
1319/* Available with KVM_CAP_DEBUGREGS */
1320#define KVM_GET_DEBUGREGS _IOR(KVMIO, 0xa1, struct kvm_debugregs)
1321#define KVM_SET_DEBUGREGS _IOW(KVMIO, 0xa2, struct kvm_debugregs)
1322/*
1323 * vcpu version available with KVM_ENABLE_CAP
1324 * vm version available with KVM_CAP_ENABLE_CAP_VM
1325 */
1326#define KVM_ENABLE_CAP _IOW(KVMIO, 0xa3, struct kvm_enable_cap)
1327/* Available with KVM_CAP_XSAVE */
1328#define KVM_GET_XSAVE _IOR(KVMIO, 0xa4, struct kvm_xsave)
1329#define KVM_SET_XSAVE _IOW(KVMIO, 0xa5, struct kvm_xsave)
1330/* Available with KVM_CAP_XCRS */
1331#define KVM_GET_XCRS _IOR(KVMIO, 0xa6, struct kvm_xcrs)
1332#define KVM_SET_XCRS _IOW(KVMIO, 0xa7, struct kvm_xcrs)
1333/* Available with KVM_CAP_SW_TLB */
1334#define KVM_DIRTY_TLB _IOW(KVMIO, 0xaa, struct kvm_dirty_tlb)
1335/* Available with KVM_CAP_ONE_REG */
1336#define KVM_GET_ONE_REG _IOW(KVMIO, 0xab, struct kvm_one_reg)
1337#define KVM_SET_ONE_REG _IOW(KVMIO, 0xac, struct kvm_one_reg)
1338/* VM is being stopped by host */
1339#define KVM_KVMCLOCK_CTRL _IO(KVMIO, 0xad)
1340#define KVM_ARM_VCPU_INIT _IOW(KVMIO, 0xae, struct kvm_vcpu_init)
1341#define KVM_ARM_PREFERRED_TARGET _IOR(KVMIO, 0xaf, struct kvm_vcpu_init)
1342#define KVM_GET_REG_LIST _IOWR(KVMIO, 0xb0, struct kvm_reg_list)
1343/* Available with KVM_CAP_S390_MEM_OP */
1344#define KVM_S390_MEM_OP _IOW(KVMIO, 0xb1, struct kvm_s390_mem_op)
1345/* Available with KVM_CAP_S390_SKEYS */
1346#define KVM_S390_GET_SKEYS _IOW(KVMIO, 0xb2, struct kvm_s390_skeys)
1347#define KVM_S390_SET_SKEYS _IOW(KVMIO, 0xb3, struct kvm_s390_skeys)
1348/* Available with KVM_CAP_S390_INJECT_IRQ */
1349#define KVM_S390_IRQ _IOW(KVMIO, 0xb4, struct kvm_s390_irq)
1350/* Available with KVM_CAP_S390_IRQ_STATE */
1351#define KVM_S390_SET_IRQ_STATE _IOW(KVMIO, 0xb5, struct kvm_s390_irq_state)
1352#define KVM_S390_GET_IRQ_STATE _IOW(KVMIO, 0xb6, struct kvm_s390_irq_state)
1353/* Available with KVM_CAP_X86_SMM */
1354#define KVM_SMI _IO(KVMIO, 0xb7)
1355/* Available with KVM_CAP_S390_CMMA_MIGRATION */
1356#define KVM_S390_GET_CMMA_BITS _IOWR(KVMIO, 0xb8, struct kvm_s390_cmma_log)
1357#define KVM_S390_SET_CMMA_BITS _IOW(KVMIO, 0xb9, struct kvm_s390_cmma_log)
1358
1359#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
1360#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
1361#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
1362
1363struct kvm_assigned_pci_dev {
1364 __u32 assigned_dev_id;
1365 __u32 busnr;
1366 __u32 devfn;
1367 __u32 flags;
1368 __u32 segnr;
1369 union {
1370 __u32 reserved[11];
1371 };
1372};
1373
1374#define KVM_DEV_IRQ_HOST_INTX (1 << 0)
1375#define KVM_DEV_IRQ_HOST_MSI (1 << 1)
1376#define KVM_DEV_IRQ_HOST_MSIX (1 << 2)
1377
1378#define KVM_DEV_IRQ_GUEST_INTX (1 << 8)
1379#define KVM_DEV_IRQ_GUEST_MSI (1 << 9)
1380#define KVM_DEV_IRQ_GUEST_MSIX (1 << 10)
1381
1382#define KVM_DEV_IRQ_HOST_MASK 0x00ff
1383#define KVM_DEV_IRQ_GUEST_MASK 0xff00
1384
1385struct kvm_assigned_irq {
1386 __u32 assigned_dev_id;
1387 __u32 host_irq; /* ignored (legacy field) */
1388 __u32 guest_irq;
1389 __u32 flags;
1390 union {
1391 __u32 reserved[12];
1392 };
1393};
1394
1395struct kvm_assigned_msix_nr {
1396 __u32 assigned_dev_id;
1397 __u16 entry_nr;
1398 __u16 padding;
1399};
1400
1401#define KVM_MAX_MSIX_PER_DEV 256
1402struct kvm_assigned_msix_entry {
1403 __u32 assigned_dev_id;
1404 __u32 gsi;
1405 __u16 entry; /* The index of entry in the MSI-X table */
1406 __u16 padding[3];
1407};
1408
1409#define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0)
1410#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1)
1411
1412/* Available with KVM_CAP_ARM_USER_IRQ */
1413
1414/* Bits for run->s.regs.device_irq_level */
1415#define KVM_ARM_DEV_EL1_VTIMER (1 << 0)
1416#define KVM_ARM_DEV_EL1_PTIMER (1 << 1)
1417#define KVM_ARM_DEV_PMU (1 << 2)
1418
1419#endif /* __LINUX_KVM_H */
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index b1c0b187acfe..140ae638cfd6 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -139,8 +139,9 @@ enum perf_event_sample_format {
139 PERF_SAMPLE_IDENTIFIER = 1U << 16, 139 PERF_SAMPLE_IDENTIFIER = 1U << 16,
140 PERF_SAMPLE_TRANSACTION = 1U << 17, 140 PERF_SAMPLE_TRANSACTION = 1U << 17,
141 PERF_SAMPLE_REGS_INTR = 1U << 18, 141 PERF_SAMPLE_REGS_INTR = 1U << 18,
142 PERF_SAMPLE_PHYS_ADDR = 1U << 19,
142 143
143 PERF_SAMPLE_MAX = 1U << 19, /* non-ABI */ 144 PERF_SAMPLE_MAX = 1U << 20, /* non-ABI */
144}; 145};
145 146
146/* 147/*
@@ -174,6 +175,8 @@ enum perf_branch_sample_type_shift {
174 PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 14, /* no flags */ 175 PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 14, /* no flags */
175 PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 15, /* no cycles */ 176 PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 15, /* no cycles */
176 177
178 PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 16, /* save branch type */
179
177 PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */ 180 PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */
178}; 181};
179 182
@@ -198,9 +201,30 @@ enum perf_branch_sample_type {
198 PERF_SAMPLE_BRANCH_NO_FLAGS = 1U << PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT, 201 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, 202 PERF_SAMPLE_BRANCH_NO_CYCLES = 1U << PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT,
200 203
204 PERF_SAMPLE_BRANCH_TYPE_SAVE =
205 1U << PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT,
206
201 PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT, 207 PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT,
202}; 208};
203 209
210/*
211 * Common flow change classification
212 */
213enum {
214 PERF_BR_UNKNOWN = 0, /* unknown */
215 PERF_BR_COND = 1, /* conditional */
216 PERF_BR_UNCOND = 2, /* unconditional */
217 PERF_BR_IND = 3, /* indirect */
218 PERF_BR_CALL = 4, /* function call */
219 PERF_BR_IND_CALL = 5, /* indirect function call */
220 PERF_BR_RET = 6, /* function return */
221 PERF_BR_SYSCALL = 7, /* syscall */
222 PERF_BR_SYSRET = 8, /* syscall return */
223 PERF_BR_COND_CALL = 9, /* conditional function call */
224 PERF_BR_COND_RET = 10, /* conditional function return */
225 PERF_BR_MAX,
226};
227
204#define PERF_SAMPLE_BRANCH_PLM_ALL \ 228#define PERF_SAMPLE_BRANCH_PLM_ALL \
205 (PERF_SAMPLE_BRANCH_USER|\ 229 (PERF_SAMPLE_BRANCH_USER|\
206 PERF_SAMPLE_BRANCH_KERNEL|\ 230 PERF_SAMPLE_BRANCH_KERNEL|\
@@ -791,6 +815,7 @@ enum perf_event_type {
791 * { u64 transaction; } && PERF_SAMPLE_TRANSACTION 815 * { u64 transaction; } && PERF_SAMPLE_TRANSACTION
792 * { u64 abi; # enum perf_sample_regs_abi 816 * { u64 abi; # enum perf_sample_regs_abi
793 * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR 817 * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR
818 * { u64 phys_addr;} && PERF_SAMPLE_PHYS_ADDR
794 * }; 819 * };
795 */ 820 */
796 PERF_RECORD_SAMPLE = 9, 821 PERF_RECORD_SAMPLE = 9,
@@ -931,14 +956,20 @@ union perf_mem_data_src {
931 mem_snoop:5, /* snoop mode */ 956 mem_snoop:5, /* snoop mode */
932 mem_lock:2, /* lock instr */ 957 mem_lock:2, /* lock instr */
933 mem_dtlb:7, /* tlb access */ 958 mem_dtlb:7, /* tlb access */
934 mem_rsvd:31; 959 mem_lvl_num:4, /* memory hierarchy level number */
960 mem_remote:1, /* remote */
961 mem_snoopx:2, /* snoop mode, ext */
962 mem_rsvd:24;
935 }; 963 };
936}; 964};
937#elif defined(__BIG_ENDIAN_BITFIELD) 965#elif defined(__BIG_ENDIAN_BITFIELD)
938union perf_mem_data_src { 966union perf_mem_data_src {
939 __u64 val; 967 __u64 val;
940 struct { 968 struct {
941 __u64 mem_rsvd:31, 969 __u64 mem_rsvd:24,
970 mem_snoopx:2, /* snoop mode, ext */
971 mem_remote:1, /* remote */
972 mem_lvl_num:4, /* memory hierarchy level number */
942 mem_dtlb:7, /* tlb access */ 973 mem_dtlb:7, /* tlb access */
943 mem_lock:2, /* lock instr */ 974 mem_lock:2, /* lock instr */
944 mem_snoop:5, /* snoop mode */ 975 mem_snoop:5, /* snoop mode */
@@ -975,6 +1006,22 @@ union perf_mem_data_src {
975#define PERF_MEM_LVL_UNC 0x2000 /* Uncached memory */ 1006#define PERF_MEM_LVL_UNC 0x2000 /* Uncached memory */
976#define PERF_MEM_LVL_SHIFT 5 1007#define PERF_MEM_LVL_SHIFT 5
977 1008
1009#define PERF_MEM_REMOTE_REMOTE 0x01 /* Remote */
1010#define PERF_MEM_REMOTE_SHIFT 37
1011
1012#define PERF_MEM_LVLNUM_L1 0x01 /* L1 */
1013#define PERF_MEM_LVLNUM_L2 0x02 /* L2 */
1014#define PERF_MEM_LVLNUM_L3 0x03 /* L3 */
1015#define PERF_MEM_LVLNUM_L4 0x04 /* L4 */
1016/* 5-0xa available */
1017#define PERF_MEM_LVLNUM_ANY_CACHE 0x0b /* Any cache */
1018#define PERF_MEM_LVLNUM_LFB 0x0c /* LFB */
1019#define PERF_MEM_LVLNUM_RAM 0x0d /* RAM */
1020#define PERF_MEM_LVLNUM_PMEM 0x0e /* PMEM */
1021#define PERF_MEM_LVLNUM_NA 0x0f /* N/A */
1022
1023#define PERF_MEM_LVLNUM_SHIFT 33
1024
978/* snoop mode */ 1025/* snoop mode */
979#define PERF_MEM_SNOOP_NA 0x01 /* not available */ 1026#define PERF_MEM_SNOOP_NA 0x01 /* not available */
980#define PERF_MEM_SNOOP_NONE 0x02 /* no snoop */ 1027#define PERF_MEM_SNOOP_NONE 0x02 /* no snoop */
@@ -983,6 +1030,10 @@ union perf_mem_data_src {
983#define PERF_MEM_SNOOP_HITM 0x10 /* snoop hit modified */ 1030#define PERF_MEM_SNOOP_HITM 0x10 /* snoop hit modified */
984#define PERF_MEM_SNOOP_SHIFT 19 1031#define PERF_MEM_SNOOP_SHIFT 19
985 1032
1033#define PERF_MEM_SNOOPX_FWD 0x01 /* forward */
1034/* 1 free */
1035#define PERF_MEM_SNOOPX_SHIFT 37
1036
986/* locked instruction */ 1037/* locked instruction */
987#define PERF_MEM_LOCK_NA 0x01 /* not available */ 1038#define PERF_MEM_LOCK_NA 0x01 /* not available */
988#define PERF_MEM_LOCK_LOCKED 0x02 /* locked transaction */ 1039#define PERF_MEM_LOCK_LOCKED 0x02 /* locked transaction */
@@ -1015,6 +1066,7 @@ union perf_mem_data_src {
1015 * in_tx: running in a hardware transaction 1066 * in_tx: running in a hardware transaction
1016 * abort: aborting a hardware transaction 1067 * abort: aborting a hardware transaction
1017 * cycles: cycles from last branch (or 0 if not supported) 1068 * cycles: cycles from last branch (or 0 if not supported)
1069 * type: branch type
1018 */ 1070 */
1019struct perf_branch_entry { 1071struct perf_branch_entry {
1020 __u64 from; 1072 __u64 from;
@@ -1024,7 +1076,8 @@ struct perf_branch_entry {
1024 in_tx:1, /* in transaction */ 1076 in_tx:1, /* in transaction */
1025 abort:1, /* transaction abort */ 1077 abort:1, /* transaction abort */
1026 cycles:16, /* cycle count to last branch */ 1078 cycles:16, /* cycle count to last branch */
1027 reserved:44; 1079 type:4, /* branch type */
1080 reserved:40;
1028}; 1081};
1029 1082
1030#endif /* _UAPI_LINUX_PERF_EVENT_H */ 1083#endif /* _UAPI_LINUX_PERF_EVENT_H */
diff --git a/tools/include/uapi/linux/sched.h b/tools/include/uapi/linux/sched.h
new file mode 100644
index 000000000000..e2a6c7b3510b
--- /dev/null
+++ b/tools/include/uapi/linux/sched.h
@@ -0,0 +1,52 @@
1#ifndef _UAPI_LINUX_SCHED_H
2#define _UAPI_LINUX_SCHED_H
3
4/*
5 * cloning flags:
6 */
7#define CSIGNAL 0x000000ff /* signal mask to be sent at exit */
8#define CLONE_VM 0x00000100 /* set if VM shared between processes */
9#define CLONE_FS 0x00000200 /* set if fs info shared between processes */
10#define CLONE_FILES 0x00000400 /* set if open files shared between processes */
11#define CLONE_SIGHAND 0x00000800 /* set if signal handlers and blocked signals shared */
12#define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */
13#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
14#define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */
15#define CLONE_THREAD 0x00010000 /* Same thread group? */
16#define CLONE_NEWNS 0x00020000 /* New mount namespace group */
17#define CLONE_SYSVSEM 0x00040000 /* share system V SEM_UNDO semantics */
18#define CLONE_SETTLS 0x00080000 /* create a new TLS for the child */
19#define CLONE_PARENT_SETTID 0x00100000 /* set the TID in the parent */
20#define CLONE_CHILD_CLEARTID 0x00200000 /* clear the TID in the child */
21#define CLONE_DETACHED 0x00400000 /* Unused, ignored */
22#define CLONE_UNTRACED 0x00800000 /* set if the tracing process can't force CLONE_PTRACE on this clone */
23#define CLONE_CHILD_SETTID 0x01000000 /* set the TID in the child */
24#define CLONE_NEWCGROUP 0x02000000 /* New cgroup namespace */
25#define CLONE_NEWUTS 0x04000000 /* New utsname namespace */
26#define CLONE_NEWIPC 0x08000000 /* New ipc namespace */
27#define CLONE_NEWUSER 0x10000000 /* New user namespace */
28#define CLONE_NEWPID 0x20000000 /* New pid namespace */
29#define CLONE_NEWNET 0x40000000 /* New network namespace */
30#define CLONE_IO 0x80000000 /* Clone io context */
31
32/*
33 * Scheduling policies
34 */
35#define SCHED_NORMAL 0
36#define SCHED_FIFO 1
37#define SCHED_RR 2
38#define SCHED_BATCH 3
39/* SCHED_ISO: reserved but not implemented yet */
40#define SCHED_IDLE 5
41#define SCHED_DEADLINE 6
42
43/* Can be ORed in to make sure the process is reverted back to SCHED_NORMAL on fork */
44#define SCHED_RESET_ON_FORK 0x40000000
45
46/*
47 * For the sched_{set,get}attr() calls
48 */
49#define SCHED_FLAG_RESET_ON_FORK 0x01
50#define SCHED_FLAG_RECLAIM 0x02
51
52#endif /* _UAPI_LINUX_SCHED_H */
diff --git a/tools/include/uapi/linux/vhost.h b/tools/include/uapi/linux/vhost.h
new file mode 100644
index 000000000000..60180c0b5dc6
--- /dev/null
+++ b/tools/include/uapi/linux/vhost.h
@@ -0,0 +1,209 @@
1#ifndef _LINUX_VHOST_H
2#define _LINUX_VHOST_H
3/* Userspace interface for in-kernel virtio accelerators. */
4
5/* vhost is used to reduce the number of system calls involved in virtio.
6 *
7 * Existing virtio net code is used in the guest without modification.
8 *
9 * This header includes interface used by userspace hypervisor for
10 * device configuration.
11 */
12
13#include <linux/types.h>
14#include <linux/compiler.h>
15#include <linux/ioctl.h>
16#include <linux/virtio_config.h>
17#include <linux/virtio_ring.h>
18
19struct vhost_vring_state {
20 unsigned int index;
21 unsigned int num;
22};
23
24struct vhost_vring_file {
25 unsigned int index;
26 int fd; /* Pass -1 to unbind from file. */
27
28};
29
30struct vhost_vring_addr {
31 unsigned int index;
32 /* Option flags. */
33 unsigned int flags;
34 /* Flag values: */
35 /* Whether log address is valid. If set enables logging. */
36#define VHOST_VRING_F_LOG 0
37
38 /* Start of array of descriptors (virtually contiguous) */
39 __u64 desc_user_addr;
40 /* Used structure address. Must be 32 bit aligned */
41 __u64 used_user_addr;
42 /* Available structure address. Must be 16 bit aligned */
43 __u64 avail_user_addr;
44 /* Logging support. */
45 /* Log writes to used structure, at offset calculated from specified
46 * address. Address must be 32 bit aligned. */
47 __u64 log_guest_addr;
48};
49
50/* no alignment requirement */
51struct vhost_iotlb_msg {
52 __u64 iova;
53 __u64 size;
54 __u64 uaddr;
55#define VHOST_ACCESS_RO 0x1
56#define VHOST_ACCESS_WO 0x2
57#define VHOST_ACCESS_RW 0x3
58 __u8 perm;
59#define VHOST_IOTLB_MISS 1
60#define VHOST_IOTLB_UPDATE 2
61#define VHOST_IOTLB_INVALIDATE 3
62#define VHOST_IOTLB_ACCESS_FAIL 4
63 __u8 type;
64};
65
66#define VHOST_IOTLB_MSG 0x1
67
68struct vhost_msg {
69 int type;
70 union {
71 struct vhost_iotlb_msg iotlb;
72 __u8 padding[64];
73 };
74};
75
76struct vhost_memory_region {
77 __u64 guest_phys_addr;
78 __u64 memory_size; /* bytes */
79 __u64 userspace_addr;
80 __u64 flags_padding; /* No flags are currently specified. */
81};
82
83/* All region addresses and sizes must be 4K aligned. */
84#define VHOST_PAGE_SIZE 0x1000
85
86struct vhost_memory {
87 __u32 nregions;
88 __u32 padding;
89 struct vhost_memory_region regions[0];
90};
91
92/* ioctls */
93
94#define VHOST_VIRTIO 0xAF
95
96/* Features bitmask for forward compatibility. Transport bits are used for
97 * vhost specific features. */
98#define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64)
99#define VHOST_SET_FEATURES _IOW(VHOST_VIRTIO, 0x00, __u64)
100
101/* Set current process as the (exclusive) owner of this file descriptor. This
102 * must be called before any other vhost command. Further calls to
103 * VHOST_OWNER_SET fail until VHOST_OWNER_RESET is called. */
104#define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01)
105/* Give up ownership, and reset the device to default values.
106 * Allows subsequent call to VHOST_OWNER_SET to succeed. */
107#define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
108
109/* Set up/modify memory layout */
110#define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
111
112/* Write logging setup. */
113/* Memory writes can optionally be logged by setting bit at an offset
114 * (calculated from the physical address) from specified log base.
115 * The bit is set using an atomic 32 bit operation. */
116/* Set base address for logging. */
117#define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64)
118/* Specify an eventfd file descriptor to signal on log write. */
119#define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int)
120
121/* Ring setup. */
122/* Set number of descriptors in ring. This parameter can not
123 * be modified while ring is running (bound to a device). */
124#define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state)
125/* Set addresses for the ring. */
126#define VHOST_SET_VRING_ADDR _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr)
127/* Base value where queue looks for available descriptors */
128#define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
129/* Get accessor: reads index, writes value in num */
130#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
131
132/* Set the vring byte order in num. Valid values are VHOST_VRING_LITTLE_ENDIAN
133 * or VHOST_VRING_BIG_ENDIAN (other values return -EINVAL).
134 * The byte order cannot be changed while the device is active: trying to do so
135 * returns -EBUSY.
136 * This is a legacy only API that is simply ignored when VIRTIO_F_VERSION_1 is
137 * set.
138 * Not all kernel configurations support this ioctl, but all configurations that
139 * support SET also support GET.
140 */
141#define VHOST_VRING_LITTLE_ENDIAN 0
142#define VHOST_VRING_BIG_ENDIAN 1
143#define VHOST_SET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x13, struct vhost_vring_state)
144#define VHOST_GET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x14, struct vhost_vring_state)
145
146/* The following ioctls use eventfd file descriptors to signal and poll
147 * for events. */
148
149/* Set eventfd to poll for added buffers */
150#define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file)
151/* Set eventfd to signal when buffers have beed used */
152#define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file)
153/* Set eventfd to signal an error */
154#define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
155/* Set busy loop timeout (in us) */
156#define VHOST_SET_VRING_BUSYLOOP_TIMEOUT _IOW(VHOST_VIRTIO, 0x23, \
157 struct vhost_vring_state)
158/* Get busy loop timeout (in us) */
159#define VHOST_GET_VRING_BUSYLOOP_TIMEOUT _IOW(VHOST_VIRTIO, 0x24, \
160 struct vhost_vring_state)
161
162/* VHOST_NET specific defines */
163
164/* Attach virtio net ring to a raw socket, or tap device.
165 * The socket must be already bound to an ethernet device, this device will be
166 * used for transmit. Pass fd -1 to unbind from the socket and the transmit
167 * device. This can be used to stop the ring (e.g. for migration). */
168#define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
169
170/* Feature bits */
171/* Log all write descriptors. Can be changed while device is active. */
172#define VHOST_F_LOG_ALL 26
173/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
174#define VHOST_NET_F_VIRTIO_NET_HDR 27
175
176/* VHOST_SCSI specific definitions */
177
178/*
179 * Used by QEMU userspace to ensure a consistent vhost-scsi ABI.
180 *
181 * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate +
182 * RFC-v2 vhost-scsi userspace. Add GET_ABI_VERSION ioctl usage
183 * ABI Rev 1: January 2013. Ignore vhost_tpgt filed in struct vhost_scsi_target.
184 * All the targets under vhost_wwpn can be seen and used by guset.
185 */
186
187#define VHOST_SCSI_ABI_VERSION 1
188
189struct vhost_scsi_target {
190 int abi_version;
191 char vhost_wwpn[224]; /* TRANSPORT_IQN_LEN */
192 unsigned short vhost_tpgt;
193 unsigned short reserved;
194};
195
196#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
197#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
198/* Changing this breaks userspace. */
199#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int)
200/* Set and get the events missed flag */
201#define VHOST_SCSI_SET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x43, __u32)
202#define VHOST_SCSI_GET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x44, __u32)
203
204/* VHOST_VSOCK specific defines */
205
206#define VHOST_VSOCK_SET_GUEST_CID _IOW(VHOST_VIRTIO, 0x60, __u64)
207#define VHOST_VSOCK_SET_RUNNING _IOW(VHOST_VIRTIO, 0x61, int)
208
209#endif
diff --git a/tools/include/uapi/sound/asound.h b/tools/include/uapi/sound/asound.h
new file mode 100644
index 000000000000..87bf30b182df
--- /dev/null
+++ b/tools/include/uapi/sound/asound.h
@@ -0,0 +1,1026 @@
1/*
2 * Advanced Linux Sound Architecture - ALSA - Driver
3 * Copyright (c) 1994-2003 by Jaroslav Kysela <perex@perex.cz>,
4 * Abramo Bagnara <abramo@alsa-project.org>
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#ifndef _UAPI__SOUND_ASOUND_H
24#define _UAPI__SOUND_ASOUND_H
25
26#if defined(__KERNEL__) || defined(__linux__)
27#include <linux/types.h>
28#else
29#include <sys/ioctl.h>
30#endif
31
32#ifndef __KERNEL__
33#include <stdlib.h>
34#endif
35
36/*
37 * protocol version
38 */
39
40#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
41#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
42#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
43#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
44#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \
45 (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \
46 (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \
47 SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
48
49/****************************************************************************
50 * *
51 * Digital audio interface *
52 * *
53 ****************************************************************************/
54
55struct snd_aes_iec958 {
56 unsigned char status[24]; /* AES/IEC958 channel status bits */
57 unsigned char subcode[147]; /* AES/IEC958 subcode bits */
58 unsigned char pad; /* nothing */
59 unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */
60};
61
62/****************************************************************************
63 * *
64 * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort *
65 * *
66 ****************************************************************************/
67
68struct snd_cea_861_aud_if {
69 unsigned char db1_ct_cc; /* coding type and channel count */
70 unsigned char db2_sf_ss; /* sample frequency and size */
71 unsigned char db3; /* not used, all zeros */
72 unsigned char db4_ca; /* channel allocation code */
73 unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
74};
75
76/****************************************************************************
77 * *
78 * Section for driver hardware dependent interface - /dev/snd/hw? *
79 * *
80 ****************************************************************************/
81
82#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
83
84enum {
85 SNDRV_HWDEP_IFACE_OPL2 = 0,
86 SNDRV_HWDEP_IFACE_OPL3,
87 SNDRV_HWDEP_IFACE_OPL4,
88 SNDRV_HWDEP_IFACE_SB16CSP, /* Creative Signal Processor */
89 SNDRV_HWDEP_IFACE_EMU10K1, /* FX8010 processor in EMU10K1 chip */
90 SNDRV_HWDEP_IFACE_YSS225, /* Yamaha FX processor */
91 SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */
92 SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */
93 SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */
94 SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */
95 SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */
96 SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */
97 SNDRV_HWDEP_IFACE_BLUETOOTH, /* Bluetooth audio */
98 SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */
99 SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */
100 SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */
101 SNDRV_HWDEP_IFACE_HDA, /* HD-audio */
102 SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */
103 SNDRV_HWDEP_IFACE_FW_DICE, /* TC DICE FireWire device */
104 SNDRV_HWDEP_IFACE_FW_FIREWORKS, /* Echo Audio Fireworks based device */
105 SNDRV_HWDEP_IFACE_FW_BEBOB, /* BridgeCo BeBoB based device */
106 SNDRV_HWDEP_IFACE_FW_OXFW, /* Oxford OXFW970/971 based device */
107 SNDRV_HWDEP_IFACE_FW_DIGI00X, /* Digidesign Digi 002/003 family */
108 SNDRV_HWDEP_IFACE_FW_TASCAM, /* TASCAM FireWire series */
109 SNDRV_HWDEP_IFACE_LINE6, /* Line6 USB processors */
110 SNDRV_HWDEP_IFACE_FW_MOTU, /* MOTU FireWire series */
111 SNDRV_HWDEP_IFACE_FW_FIREFACE, /* RME Fireface series */
112
113 /* Don't forget to change the following: */
114 SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_FIREFACE
115};
116
117struct snd_hwdep_info {
118 unsigned int device; /* WR: device number */
119 int card; /* R: card number */
120 unsigned char id[64]; /* ID (user selectable) */
121 unsigned char name[80]; /* hwdep name */
122 int iface; /* hwdep interface */
123 unsigned char reserved[64]; /* reserved for future */
124};
125
126/* generic DSP loader */
127struct snd_hwdep_dsp_status {
128 unsigned int version; /* R: driver-specific version */
129 unsigned char id[32]; /* R: driver-specific ID string */
130 unsigned int num_dsps; /* R: number of DSP images to transfer */
131 unsigned int dsp_loaded; /* R: bit flags indicating the loaded DSPs */
132 unsigned int chip_ready; /* R: 1 = initialization finished */
133 unsigned char reserved[16]; /* reserved for future use */
134};
135
136struct snd_hwdep_dsp_image {
137 unsigned int index; /* W: DSP index */
138 unsigned char name[64]; /* W: ID (e.g. file name) */
139 unsigned char __user *image; /* W: binary image */
140 size_t length; /* W: size of image in bytes */
141 unsigned long driver_data; /* W: driver-specific data */
142};
143
144#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int)
145#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info)
146#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
147#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
148
149/*****************************************************************************
150 * *
151 * Digital Audio (PCM) interface - /dev/snd/pcm?? *
152 * *
153 *****************************************************************************/
154
155#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 14)
156
157typedef unsigned long snd_pcm_uframes_t;
158typedef signed long snd_pcm_sframes_t;
159
160enum {
161 SNDRV_PCM_CLASS_GENERIC = 0, /* standard mono or stereo device */
162 SNDRV_PCM_CLASS_MULTI, /* multichannel device */
163 SNDRV_PCM_CLASS_MODEM, /* software modem class */
164 SNDRV_PCM_CLASS_DIGITIZER, /* digitizer class */
165 /* Don't forget to change the following: */
166 SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
167};
168
169enum {
170 SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */
171 SNDRV_PCM_SUBCLASS_MULTI_MIX, /* multichannel subdevices are mixed together */
172 /* Don't forget to change the following: */
173 SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
174};
175
176enum {
177 SNDRV_PCM_STREAM_PLAYBACK = 0,
178 SNDRV_PCM_STREAM_CAPTURE,
179 SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
180};
181
182typedef int __bitwise snd_pcm_access_t;
183#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0) /* interleaved mmap */
184#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
185#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2) /* complex mmap */
186#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3) /* readi/writei */
187#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4) /* readn/writen */
188#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
189
190typedef int __bitwise snd_pcm_format_t;
191#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
192#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
193#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
194#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
195#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
196#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
197#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */
198#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */
199#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */
200#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */
201#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
202#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
203#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
204#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
205#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 */
206#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 */
207#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 */
208#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 */
209#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
210#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
211#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
212#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
213#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
214#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
215#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
216#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
217#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */
218#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */
219#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34) /* in three bytes */
220#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35) /* in three bytes */
221#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36) /* in three bytes */
222#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37) /* in three bytes */
223#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38) /* in three bytes */
224#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39) /* in three bytes */
225#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40) /* in three bytes */
226#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41) /* in three bytes */
227#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42) /* in three bytes */
228#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43) /* in three bytes */
229#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
230#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
231#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
232#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
233#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */
234#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */
235#define SNDRV_PCM_FORMAT_DSD_U32_LE ((__force snd_pcm_format_t) 50) /* DSD, 4-byte samples DSD (x32), little endian */
236#define SNDRV_PCM_FORMAT_DSD_U16_BE ((__force snd_pcm_format_t) 51) /* DSD, 2-byte samples DSD (x16), big endian */
237#define SNDRV_PCM_FORMAT_DSD_U32_BE ((__force snd_pcm_format_t) 52) /* DSD, 4-byte samples DSD (x32), big endian */
238#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U32_BE
239
240#ifdef SNDRV_LITTLE_ENDIAN
241#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
242#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE
243#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE
244#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE
245#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE
246#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE
247#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
248#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
249#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
250#endif
251#ifdef SNDRV_BIG_ENDIAN
252#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
253#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE
254#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE
255#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE
256#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE
257#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE
258#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
259#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
260#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
261#endif
262
263typedef int __bitwise snd_pcm_subformat_t;
264#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
265#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD
266
267#define SNDRV_PCM_INFO_MMAP 0x00000001 /* hardware supports mmap */
268#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */
269#define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */
270#define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */
271#define SNDRV_PCM_INFO_SYNC_APPLPTR 0x00000020 /* need the explicit sync of appl_ptr update */
272#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */
273#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */
274#define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */
275#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000 /* hardware transfer block of samples */
276#define SNDRV_PCM_INFO_OVERRANGE 0x00020000 /* hardware supports ADC (capture) overrange detection */
277#define SNDRV_PCM_INFO_RESUME 0x00040000 /* hardware supports stream resume after suspend */
278#define SNDRV_PCM_INFO_PAUSE 0x00080000 /* pause ioctl is supported */
279#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */
280#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
281#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */
282#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */
283#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* (Deprecated)has audio wall clock for audio/system time sync */
284#define SNDRV_PCM_INFO_HAS_LINK_ATIME 0x01000000 /* report hardware link audio time, reset on startup */
285#define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */
286#define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */
287#define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */
288
289#define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */
290#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */
291
292
293
294typedef int __bitwise snd_pcm_state_t;
295#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */
296#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */
297#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2) /* stream is ready to start */
298#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3) /* stream is running */
299#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4) /* stream reached an xrun */
300#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5) /* stream is draining */
301#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6) /* stream is paused */
302#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7) /* hardware is suspended */
303#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8) /* hardware is disconnected */
304#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
305
306enum {
307 SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
308 SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
309 SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
310};
311
312union snd_pcm_sync_id {
313 unsigned char id[16];
314 unsigned short id16[8];
315 unsigned int id32[4];
316};
317
318struct snd_pcm_info {
319 unsigned int device; /* RO/WR (control): device number */
320 unsigned int subdevice; /* RO/WR (control): subdevice number */
321 int stream; /* RO/WR (control): stream direction */
322 int card; /* R: card number */
323 unsigned char id[64]; /* ID (user selectable) */
324 unsigned char name[80]; /* name of this device */
325 unsigned char subname[32]; /* subdevice name */
326 int dev_class; /* SNDRV_PCM_CLASS_* */
327 int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */
328 unsigned int subdevices_count;
329 unsigned int subdevices_avail;
330 union snd_pcm_sync_id sync; /* hardware synchronization ID */
331 unsigned char reserved[64]; /* reserved for future... */
332};
333
334typedef int snd_pcm_hw_param_t;
335#define SNDRV_PCM_HW_PARAM_ACCESS 0 /* Access type */
336#define SNDRV_PCM_HW_PARAM_FORMAT 1 /* Format */
337#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2 /* Subformat */
338#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
339#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
340
341#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8 /* Bits per sample */
342#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9 /* Bits per frame */
343#define SNDRV_PCM_HW_PARAM_CHANNELS 10 /* Channels */
344#define SNDRV_PCM_HW_PARAM_RATE 11 /* Approx rate */
345#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12 /* Approx distance between
346 * interrupts in us
347 */
348#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13 /* Approx frames between
349 * interrupts
350 */
351#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14 /* Approx bytes between
352 * interrupts
353 */
354#define SNDRV_PCM_HW_PARAM_PERIODS 15 /* Approx interrupts per
355 * buffer
356 */
357#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16 /* Approx duration of buffer
358 * in us
359 */
360#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17 /* Size of buffer in frames */
361#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18 /* Size of buffer in bytes */
362#define SNDRV_PCM_HW_PARAM_TICK_TIME 19 /* Approx tick duration in us */
363#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
364#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
365
366#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */
367#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1) /* export buffer */
368#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) /* disable period wakeups */
369
370struct snd_interval {
371 unsigned int min, max;
372 unsigned int openmin:1,
373 openmax:1,
374 integer:1,
375 empty:1;
376};
377
378#define SNDRV_MASK_MAX 256
379
380struct snd_mask {
381 __u32 bits[(SNDRV_MASK_MAX+31)/32];
382};
383
384struct snd_pcm_hw_params {
385 unsigned int flags;
386 struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
387 SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
388 struct snd_mask mres[5]; /* reserved masks */
389 struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
390 SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
391 struct snd_interval ires[9]; /* reserved intervals */
392 unsigned int rmask; /* W: requested masks */
393 unsigned int cmask; /* R: changed masks */
394 unsigned int info; /* R: Info flags for returned setup */
395 unsigned int msbits; /* R: used most significant bits */
396 unsigned int rate_num; /* R: rate numerator */
397 unsigned int rate_den; /* R: rate denominator */
398 snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */
399 unsigned char reserved[64]; /* reserved for future */
400};
401
402enum {
403 SNDRV_PCM_TSTAMP_NONE = 0,
404 SNDRV_PCM_TSTAMP_ENABLE,
405 SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
406};
407
408struct snd_pcm_sw_params {
409 int tstamp_mode; /* timestamp mode */
410 unsigned int period_step;
411 unsigned int sleep_min; /* min ticks to sleep */
412 snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */
413 snd_pcm_uframes_t xfer_align; /* obsolete: xfer size need to be a multiple */
414 snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */
415 snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */
416 snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */
417 snd_pcm_uframes_t silence_size; /* silence block size */
418 snd_pcm_uframes_t boundary; /* pointers wrap point */
419 unsigned int proto; /* protocol version */
420 unsigned int tstamp_type; /* timestamp type (req. proto >= 2.0.12) */
421 unsigned char reserved[56]; /* reserved for future */
422};
423
424struct snd_pcm_channel_info {
425 unsigned int channel;
426 __kernel_off_t offset; /* mmap offset */
427 unsigned int first; /* offset to first sample in bits */
428 unsigned int step; /* samples distance in bits */
429};
430
431enum {
432 /*
433 * first definition for backwards compatibility only,
434 * maps to wallclock/link time for HDAudio playback and DEFAULT/DMA time for everything else
435 */
436 SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT = 0,
437
438 /* timestamp definitions */
439 SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT = 1, /* DMA time, reported as per hw_ptr */
440 SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK = 2, /* link time reported by sample or wallclock counter, reset on startup */
441 SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE = 3, /* link time reported by sample or wallclock counter, not reset on startup */
442 SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED = 4, /* link time estimated indirectly */
443 SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED = 5, /* link time synchronized with system time */
444 SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED
445};
446
447struct snd_pcm_status {
448 snd_pcm_state_t state; /* stream state */
449 struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
450 struct timespec tstamp; /* reference timestamp */
451 snd_pcm_uframes_t appl_ptr; /* appl ptr */
452 snd_pcm_uframes_t hw_ptr; /* hw ptr */
453 snd_pcm_sframes_t delay; /* current delay in frames */
454 snd_pcm_uframes_t avail; /* number of frames available */
455 snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */
456 snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
457 snd_pcm_state_t suspended_state; /* suspended stream state */
458 __u32 audio_tstamp_data; /* needed for 64-bit alignment, used for configs/report to/from userspace */
459 struct timespec audio_tstamp; /* sample counter, wall clock, PHC or on-demand sync'ed */
460 struct timespec driver_tstamp; /* useful in case reference system tstamp is reported with delay */
461 __u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */
462 unsigned char reserved[52-2*sizeof(struct timespec)]; /* must be filled with zero */
463};
464
465struct snd_pcm_mmap_status {
466 snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */
467 int pad1; /* Needed for 64 bit alignment */
468 snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
469 struct timespec tstamp; /* Timestamp */
470 snd_pcm_state_t suspended_state; /* RO: suspended stream state */
471 struct timespec audio_tstamp; /* from sample counter or wall clock */
472};
473
474struct snd_pcm_mmap_control {
475 snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */
476 snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */
477};
478
479#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0) /* execute hwsync */
480#define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */
481#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */
482
483struct snd_pcm_sync_ptr {
484 unsigned int flags;
485 union {
486 struct snd_pcm_mmap_status status;
487 unsigned char reserved[64];
488 } s;
489 union {
490 struct snd_pcm_mmap_control control;
491 unsigned char reserved[64];
492 } c;
493};
494
495struct snd_xferi {
496 snd_pcm_sframes_t result;
497 void __user *buf;
498 snd_pcm_uframes_t frames;
499};
500
501struct snd_xfern {
502 snd_pcm_sframes_t result;
503 void __user * __user *bufs;
504 snd_pcm_uframes_t frames;
505};
506
507enum {
508 SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
509 SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */
510 SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /* monotonic_raw (no NTP) */
511 SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW,
512};
513
514/* channel positions */
515enum {
516 SNDRV_CHMAP_UNKNOWN = 0,
517 SNDRV_CHMAP_NA, /* N/A, silent */
518 SNDRV_CHMAP_MONO, /* mono stream */
519 /* this follows the alsa-lib mixer channel value + 3 */
520 SNDRV_CHMAP_FL, /* front left */
521 SNDRV_CHMAP_FR, /* front right */
522 SNDRV_CHMAP_RL, /* rear left */
523 SNDRV_CHMAP_RR, /* rear right */
524 SNDRV_CHMAP_FC, /* front center */
525 SNDRV_CHMAP_LFE, /* LFE */
526 SNDRV_CHMAP_SL, /* side left */
527 SNDRV_CHMAP_SR, /* side right */
528 SNDRV_CHMAP_RC, /* rear center */
529 /* new definitions */
530 SNDRV_CHMAP_FLC, /* front left center */
531 SNDRV_CHMAP_FRC, /* front right center */
532 SNDRV_CHMAP_RLC, /* rear left center */
533 SNDRV_CHMAP_RRC, /* rear right center */
534 SNDRV_CHMAP_FLW, /* front left wide */
535 SNDRV_CHMAP_FRW, /* front right wide */
536 SNDRV_CHMAP_FLH, /* front left high */
537 SNDRV_CHMAP_FCH, /* front center high */
538 SNDRV_CHMAP_FRH, /* front right high */
539 SNDRV_CHMAP_TC, /* top center */
540 SNDRV_CHMAP_TFL, /* top front left */
541 SNDRV_CHMAP_TFR, /* top front right */
542 SNDRV_CHMAP_TFC, /* top front center */
543 SNDRV_CHMAP_TRL, /* top rear left */
544 SNDRV_CHMAP_TRR, /* top rear right */
545 SNDRV_CHMAP_TRC, /* top rear center */
546 /* new definitions for UAC2 */
547 SNDRV_CHMAP_TFLC, /* top front left center */
548 SNDRV_CHMAP_TFRC, /* top front right center */
549 SNDRV_CHMAP_TSL, /* top side left */
550 SNDRV_CHMAP_TSR, /* top side right */
551 SNDRV_CHMAP_LLFE, /* left LFE */
552 SNDRV_CHMAP_RLFE, /* right LFE */
553 SNDRV_CHMAP_BC, /* bottom center */
554 SNDRV_CHMAP_BLC, /* bottom left center */
555 SNDRV_CHMAP_BRC, /* bottom right center */
556 SNDRV_CHMAP_LAST = SNDRV_CHMAP_BRC,
557};
558
559#define SNDRV_CHMAP_POSITION_MASK 0xffff
560#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16)
561#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
562
563#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int)
564#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
565#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
566#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
567#define SNDRV_PCM_IOCTL_USER_PVERSION _IOW('A', 0x04, int)
568#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
569#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
570#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
571#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params)
572#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
573#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
574#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
575#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
576#define SNDRV_PCM_IOCTL_STATUS_EXT _IOWR('A', 0x24, struct snd_pcm_status)
577#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
578#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
579#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
580#define SNDRV_PCM_IOCTL_START _IO('A', 0x42)
581#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43)
582#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44)
583#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int)
584#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t)
585#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47)
586#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48)
587#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t)
588#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi)
589#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi)
590#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern)
591#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern)
592#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
593#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
594
595/*****************************************************************************
596 * *
597 * MIDI v1.0 interface *
598 * *
599 *****************************************************************************/
600
601/*
602 * Raw MIDI section - /dev/snd/midi??
603 */
604
605#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
606
607enum {
608 SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
609 SNDRV_RAWMIDI_STREAM_INPUT,
610 SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
611};
612
613#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001
614#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002
615#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004
616
617struct snd_rawmidi_info {
618 unsigned int device; /* RO/WR (control): device number */
619 unsigned int subdevice; /* RO/WR (control): subdevice number */
620 int stream; /* WR: stream */
621 int card; /* R: card number */
622 unsigned int flags; /* SNDRV_RAWMIDI_INFO_XXXX */
623 unsigned char id[64]; /* ID (user selectable) */
624 unsigned char name[80]; /* name of device */
625 unsigned char subname[32]; /* name of active or selected subdevice */
626 unsigned int subdevices_count;
627 unsigned int subdevices_avail;
628 unsigned char reserved[64]; /* reserved for future use */
629};
630
631struct snd_rawmidi_params {
632 int stream;
633 size_t buffer_size; /* queue size in bytes */
634 size_t avail_min; /* minimum avail bytes for wakeup */
635 unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
636 unsigned char reserved[16]; /* reserved for future use */
637};
638
639struct snd_rawmidi_status {
640 int stream;
641 struct timespec tstamp; /* Timestamp */
642 size_t avail; /* available bytes */
643 size_t xruns; /* count of overruns since last status (in bytes) */
644 unsigned char reserved[16]; /* reserved for future use */
645};
646
647#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
648#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info)
649#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params)
650#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status)
651#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int)
652#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int)
653
654/*
655 * Timer section - /dev/snd/timer
656 */
657
658#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
659
660enum {
661 SNDRV_TIMER_CLASS_NONE = -1,
662 SNDRV_TIMER_CLASS_SLAVE = 0,
663 SNDRV_TIMER_CLASS_GLOBAL,
664 SNDRV_TIMER_CLASS_CARD,
665 SNDRV_TIMER_CLASS_PCM,
666 SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
667};
668
669/* slave timer classes */
670enum {
671 SNDRV_TIMER_SCLASS_NONE = 0,
672 SNDRV_TIMER_SCLASS_APPLICATION,
673 SNDRV_TIMER_SCLASS_SEQUENCER, /* alias */
674 SNDRV_TIMER_SCLASS_OSS_SEQUENCER, /* alias */
675 SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
676};
677
678/* global timers (device member) */
679#define SNDRV_TIMER_GLOBAL_SYSTEM 0
680#define SNDRV_TIMER_GLOBAL_RTC 1 /* unused */
681#define SNDRV_TIMER_GLOBAL_HPET 2
682#define SNDRV_TIMER_GLOBAL_HRTIMER 3
683
684/* info flags */
685#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
686
687struct snd_timer_id {
688 int dev_class;
689 int dev_sclass;
690 int card;
691 int device;
692 int subdevice;
693};
694
695struct snd_timer_ginfo {
696 struct snd_timer_id tid; /* requested timer ID */
697 unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
698 int card; /* card number */
699 unsigned char id[64]; /* timer identification */
700 unsigned char name[80]; /* timer name */
701 unsigned long reserved0; /* reserved for future use */
702 unsigned long resolution; /* average period resolution in ns */
703 unsigned long resolution_min; /* minimal period resolution in ns */
704 unsigned long resolution_max; /* maximal period resolution in ns */
705 unsigned int clients; /* active timer clients */
706 unsigned char reserved[32];
707};
708
709struct snd_timer_gparams {
710 struct snd_timer_id tid; /* requested timer ID */
711 unsigned long period_num; /* requested precise period duration (in seconds) - numerator */
712 unsigned long period_den; /* requested precise period duration (in seconds) - denominator */
713 unsigned char reserved[32];
714};
715
716struct snd_timer_gstatus {
717 struct snd_timer_id tid; /* requested timer ID */
718 unsigned long resolution; /* current period resolution in ns */
719 unsigned long resolution_num; /* precise current period resolution (in seconds) - numerator */
720 unsigned long resolution_den; /* precise current period resolution (in seconds) - denominator */
721 unsigned char reserved[32];
722};
723
724struct snd_timer_select {
725 struct snd_timer_id id; /* bind to timer ID */
726 unsigned char reserved[32]; /* reserved */
727};
728
729struct snd_timer_info {
730 unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
731 int card; /* card number */
732 unsigned char id[64]; /* timer identificator */
733 unsigned char name[80]; /* timer name */
734 unsigned long reserved0; /* reserved for future use */
735 unsigned long resolution; /* average period resolution in ns */
736 unsigned char reserved[64]; /* reserved */
737};
738
739#define SNDRV_TIMER_PSFLG_AUTO (1<<0) /* auto start, otherwise one-shot */
740#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1) /* exclusive use, precise start/stop/pause/continue */
741#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */
742
743struct snd_timer_params {
744 unsigned int flags; /* flags - SNDRV_MIXER_PSFLG_* */
745 unsigned int ticks; /* requested resolution in ticks */
746 unsigned int queue_size; /* total size of queue (32-1024) */
747 unsigned int reserved0; /* reserved, was: failure locations */
748 unsigned int filter; /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */
749 unsigned char reserved[60]; /* reserved */
750};
751
752struct snd_timer_status {
753 struct timespec tstamp; /* Timestamp - last update */
754 unsigned int resolution; /* current period resolution in ns */
755 unsigned int lost; /* counter of master tick lost */
756 unsigned int overrun; /* count of read queue overruns */
757 unsigned int queue; /* used queue size */
758 unsigned char reserved[64]; /* reserved */
759};
760
761#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
762#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
763#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
764#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo)
765#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams)
766#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus)
767#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select)
768#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info)
769#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params)
770#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status)
771/* The following four ioctls are changed since 1.0.9 due to confliction */
772#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0)
773#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
774#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
775#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
776
777struct snd_timer_read {
778 unsigned int resolution;
779 unsigned int ticks;
780};
781
782enum {
783 SNDRV_TIMER_EVENT_RESOLUTION = 0, /* val = resolution in ns */
784 SNDRV_TIMER_EVENT_TICK, /* val = ticks */
785 SNDRV_TIMER_EVENT_START, /* val = resolution in ns */
786 SNDRV_TIMER_EVENT_STOP, /* val = 0 */
787 SNDRV_TIMER_EVENT_CONTINUE, /* val = resolution in ns */
788 SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */
789 SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */
790 SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */
791 SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */
792 /* master timer events for slave timer instances */
793 SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
794 SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
795 SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
796 SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
797 SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
798 SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
799};
800
801struct snd_timer_tread {
802 int event;
803 struct timespec tstamp;
804 unsigned int val;
805};
806
807/****************************************************************************
808 * *
809 * Section for driver control interface - /dev/snd/control? *
810 * *
811 ****************************************************************************/
812
813#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7)
814
815struct snd_ctl_card_info {
816 int card; /* card number */
817 int pad; /* reserved for future (was type) */
818 unsigned char id[16]; /* ID of card (user selectable) */
819 unsigned char driver[16]; /* Driver name */
820 unsigned char name[32]; /* Short name of soundcard */
821 unsigned char longname[80]; /* name + info text about soundcard */
822 unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */
823 unsigned char mixername[80]; /* visual mixer identification */
824 unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */
825};
826
827typedef int __bitwise snd_ctl_elem_type_t;
828#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */
829#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */
830#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2) /* integer type */
831#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3) /* enumerated type */
832#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4) /* byte array */
833#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
834#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
835#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
836
837typedef int __bitwise snd_ctl_elem_iface_t;
838#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0) /* global control */
839#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
840#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
841#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3) /* PCM device */
842#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
843#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5) /* timer device */
844#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
845#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
846
847#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
848#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
849#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
850#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */
851#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3) /* when was control changed */
852#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */
853#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */
854#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
855#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6) /* TLV command is possible */
856#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8) /* control does actually nothing, but may be updated */
857#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9) /* write lock */
858#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */
859#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */
860#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */
861/* bits 30 and 31 are obsoleted (for indirect access) */
862
863/* for further details see the ACPI and PCI power management specification */
864#define SNDRV_CTL_POWER_D0 0x0000 /* full On */
865#define SNDRV_CTL_POWER_D1 0x0100 /* partial On */
866#define SNDRV_CTL_POWER_D2 0x0200 /* partial On */
867#define SNDRV_CTL_POWER_D3 0x0300 /* Off */
868#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */
869#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */
870
871#define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44
872
873struct snd_ctl_elem_id {
874 unsigned int numid; /* numeric identifier, zero = invalid */
875 snd_ctl_elem_iface_t iface; /* interface identifier */
876 unsigned int device; /* device/client number */
877 unsigned int subdevice; /* subdevice (substream) number */
878 unsigned char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* ASCII name of item */
879 unsigned int index; /* index of item */
880};
881
882struct snd_ctl_elem_list {
883 unsigned int offset; /* W: first element ID to get */
884 unsigned int space; /* W: count of element IDs to get */
885 unsigned int used; /* R: count of element IDs set */
886 unsigned int count; /* R: count of all elements */
887 struct snd_ctl_elem_id __user *pids; /* R: IDs */
888 unsigned char reserved[50];
889};
890
891struct snd_ctl_elem_info {
892 struct snd_ctl_elem_id id; /* W: element ID */
893 snd_ctl_elem_type_t type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */
894 unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
895 unsigned int count; /* count of values */
896 __kernel_pid_t owner; /* owner's PID of this control */
897 union {
898 struct {
899 long min; /* R: minimum value */
900 long max; /* R: maximum value */
901 long step; /* R: step (0 variable) */
902 } integer;
903 struct {
904 long long min; /* R: minimum value */
905 long long max; /* R: maximum value */
906 long long step; /* R: step (0 variable) */
907 } integer64;
908 struct {
909 unsigned int items; /* R: number of items */
910 unsigned int item; /* W: item number */
911 char name[64]; /* R: value name */
912 __u64 names_ptr; /* W: names list (ELEM_ADD only) */
913 unsigned int names_length;
914 } enumerated;
915 unsigned char reserved[128];
916 } value;
917 union {
918 unsigned short d[4]; /* dimensions */
919 unsigned short *d_ptr; /* indirect - obsoleted */
920 } dimen;
921 unsigned char reserved[64-4*sizeof(unsigned short)];
922};
923
924struct snd_ctl_elem_value {
925 struct snd_ctl_elem_id id; /* W: element ID */
926 unsigned int indirect: 1; /* W: indirect access - obsoleted */
927 union {
928 union {
929 long value[128];
930 long *value_ptr; /* obsoleted */
931 } integer;
932 union {
933 long long value[64];
934 long long *value_ptr; /* obsoleted */
935 } integer64;
936 union {
937 unsigned int item[128];
938 unsigned int *item_ptr; /* obsoleted */
939 } enumerated;
940 union {
941 unsigned char data[512];
942 unsigned char *data_ptr; /* obsoleted */
943 } bytes;
944 struct snd_aes_iec958 iec958;
945 } value; /* RO */
946 struct timespec tstamp;
947 unsigned char reserved[128-sizeof(struct timespec)];
948};
949
950struct snd_ctl_tlv {
951 unsigned int numid; /* control element numeric identification */
952 unsigned int length; /* in bytes aligned to 4 */
953 unsigned int tlv[0]; /* first TLV */
954};
955
956#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
957#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
958#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
959#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
960#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
961#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value)
962#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id)
963#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id)
964#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
965#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info)
966#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info)
967#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id)
968#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv)
969#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv)
970#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv)
971#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
972#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info)
973#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int)
974#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info)
975#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
976#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
977#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info)
978#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
979#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int)
980#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int)
981
982/*
983 * Read interface.
984 */
985
986enum sndrv_ctl_event_type {
987 SNDRV_CTL_EVENT_ELEM = 0,
988 SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
989};
990
991#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0) /* element value was changed */
992#define SNDRV_CTL_EVENT_MASK_INFO (1<<1) /* element info was changed */
993#define SNDRV_CTL_EVENT_MASK_ADD (1<<2) /* element was added */
994#define SNDRV_CTL_EVENT_MASK_TLV (1<<3) /* element TLV tree was changed */
995#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U) /* element was removed */
996
997struct snd_ctl_event {
998 int type; /* event type - SNDRV_CTL_EVENT_* */
999 union {
1000 struct {
1001 unsigned int mask;
1002 struct snd_ctl_elem_id id;
1003 } elem;
1004 unsigned char data8[60];
1005 } data;
1006};
1007
1008/*
1009 * Control names
1010 */
1011
1012#define SNDRV_CTL_NAME_NONE ""
1013#define SNDRV_CTL_NAME_PLAYBACK "Playback "
1014#define SNDRV_CTL_NAME_CAPTURE "Capture "
1015
1016#define SNDRV_CTL_NAME_IEC958_NONE ""
1017#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch"
1018#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume"
1019#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default"
1020#define SNDRV_CTL_NAME_IEC958_MASK "Mask"
1021#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask"
1022#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask"
1023#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream"
1024#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
1025
1026#endif /* _UAPI__SOUND_ASOUND_H */
diff --git a/tools/kvm/kvm_stat/kvm_stat b/tools/kvm/kvm_stat/kvm_stat
index dd8f00cfb8b4..32283d88701a 100755
--- a/tools/kvm/kvm_stat/kvm_stat
+++ b/tools/kvm/kvm_stat/kvm_stat
@@ -474,7 +474,7 @@ class Provider(object):
474 @staticmethod 474 @staticmethod
475 def is_field_wanted(fields_filter, field): 475 def is_field_wanted(fields_filter, field):
476 """Indicate whether field is valid according to fields_filter.""" 476 """Indicate whether field is valid according to fields_filter."""
477 if not fields_filter: 477 if not fields_filter or fields_filter == "help":
478 return True 478 return True
479 return re.match(fields_filter, field) is not None 479 return re.match(fields_filter, field) is not None
480 480
@@ -1413,8 +1413,8 @@ performance.
1413 1413
1414Requirements: 1414Requirements:
1415- Access to: 1415- Access to:
1416 /sys/kernel/debug/kvm 1416 %s
1417 /sys/kernel/debug/trace/events/* 1417 %s/events/*
1418 /proc/pid/task 1418 /proc/pid/task
1419- /proc/sys/kernel/perf_event_paranoid < 1 if user has no 1419- /proc/sys/kernel/perf_event_paranoid < 1 if user has no
1420 CAP_SYS_ADMIN and perf events are used. 1420 CAP_SYS_ADMIN and perf events are used.
@@ -1434,7 +1434,7 @@ Interactive Commands:
1434 s set update interval 1434 s set update interval
1435 x toggle reporting of stats for individual child trace events 1435 x toggle reporting of stats for individual child trace events
1436Press any other key to refresh statistics immediately. 1436Press any other key to refresh statistics immediately.
1437""" 1437""" % (PATH_DEBUGFS_KVM, PATH_DEBUGFS_TRACING)
1438 1438
1439 class PlainHelpFormatter(optparse.IndentedHelpFormatter): 1439 class PlainHelpFormatter(optparse.IndentedHelpFormatter):
1440 def format_description(self, description): 1440 def format_description(self, description):
@@ -1496,7 +1496,8 @@ Press any other key to refresh statistics immediately.
1496 action='store', 1496 action='store',
1497 default=DEFAULT_REGEX, 1497 default=DEFAULT_REGEX,
1498 dest='fields', 1498 dest='fields',
1499 help='fields to display (regex)', 1499 help='''fields to display (regex)
1500 "-f help" for a list of available events''',
1500 ) 1501 )
1501 optparser.add_option('-p', '--pid', 1502 optparser.add_option('-p', '--pid',
1502 action='store', 1503 action='store',
@@ -1559,6 +1560,17 @@ def main():
1559 1560
1560 stats = Stats(options) 1561 stats = Stats(options)
1561 1562
1563 if options.fields == "help":
1564 event_list = "\n"
1565 s = stats.get()
1566 for key in s.keys():
1567 if key.find('(') != -1:
1568 key = key[0:key.find('(')]
1569 if event_list.find('\n' + key + '\n') == -1:
1570 event_list += key + '\n'
1571 sys.stdout.write(event_list)
1572 return ""
1573
1562 if options.log: 1574 if options.log:
1563 log(stats) 1575 log(stats)
1564 elif not options.once: 1576 elif not options.once:
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..1e83e3c07448 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -8,22 +8,28 @@ srctree := $(patsubst %/,%,$(dir $(srctree)))
8#$(info Determined 'srctree' to be $(srctree)) 8#$(info Determined 'srctree' to be $(srctree))
9endif 9endif
10 10
11CC = $(CROSS_COMPILE)gcc 11CC ?= $(CROSS_COMPILE)gcc
12AR = $(CROSS_COMPILE)ar 12AR ?= $(CROSS_COMPILE)ar
13LD = $(CROSS_COMPILE)ld 13LD ?= $(CROSS_COMPILE)ld
14 14
15MAKEFLAGS += --no-print-directory 15MAKEFLAGS += --no-print-directory
16 16
17LIBFILE = $(OUTPUT)libapi.a 17LIBFILE = $(OUTPUT)libapi.a
18 18
19CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 19CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
20CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC 20CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -fPIC
21 21
22ifeq ($(CC), clang) 22ifeq ($(DEBUG),0)
23ifeq ($(CC_NO_CLANG), 0)
23 CFLAGS += -O3 24 CFLAGS += -O3
24else 25else
25 CFLAGS += -O6 26 CFLAGS += -O6
26endif 27endif
28endif
29
30ifeq ($(DEBUG),0)
31 CFLAGS += -D_FORTIFY_SOURCE
32endif
27 33
28# Treat warnings as errors unless directed not to 34# Treat warnings as errors unless directed not to
29ifneq ($(WERROR),0) 35ifneq ($(WERROR),0)
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index 1f5300e56b44..d2441db34740 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -154,12 +154,12 @@ all: fixdep $(VERSION_FILES) all_cmd
154all_cmd: $(CMD_TARGETS) 154all_cmd: $(CMD_TARGETS)
155 155
156$(BPF_IN): force elfdep bpfdep 156$(BPF_IN): force elfdep bpfdep
157 @(test -f ../../../include/uapi/linux/bpf.h -a -f ../../../include/uapi/linux/bpf.h && ( \ 157 @(test -f ../../include/uapi/linux/bpf.h -a -f ../../../include/uapi/linux/bpf.h && ( \
158 (diff -B ../../include/uapi/linux/bpf.h ../../../include/uapi/linux/bpf.h >/dev/null) || \ 158 (diff -B ../../include/uapi/linux/bpf.h ../../../include/uapi/linux/bpf.h >/dev/null) || \
159 echo "Warning: tools/include/uapi/linux/bpf.h differs from kernel" >&2 )) || true 159 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 && ( \ 160 @(test -f ../../include/uapi/linux/bpf_common.h -a -f ../../../include/uapi/linux/bpf_common.h && ( \
161 (diff -B ../../include/uapi/linux/bpf_common.h ../../../include/uapi/linux/bpf_common.h >/dev/null) || \ 161 (diff -B ../../include/uapi/linux/bpf_common.h ../../../include/uapi/linux/bpf_common.h >/dev/null) || \
162 echo "Warning: tools/include/uapi/linux/bpf_common.h differs from kernel" >&2 )) || true 162 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 163 $(Q)$(MAKE) $(build)=libbpf
164 164
165$(OUTPUT)libbpf.so: $(BPF_IN) 165$(OUTPUT)libbpf.so: $(BPF_IN)
@@ -189,6 +189,10 @@ install_lib: all_cmd
189 $(call QUIET_INSTALL, $(LIB_FILE)) \ 189 $(call QUIET_INSTALL, $(LIB_FILE)) \
190 $(call do_install,$(LIB_FILE),$(libdir_SQ)) 190 $(call do_install,$(LIB_FILE),$(libdir_SQ))
191 191
192install_headers:
193 $(call QUIET_INSTALL, headers) \
194 $(call do_install,bpf.h,$(prefix)/include/bpf,644)
195
192install: install_lib 196install: install_lib
193 197
194### Cleaning rules 198### Cleaning rules
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 7e0405e1651d..1d6907d379c9 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -39,6 +39,8 @@
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
@@ -55,8 +57,9 @@ static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
55 return syscall(__NR_bpf, cmd, attr, size); 57 return syscall(__NR_bpf, cmd, attr, size);
56} 58}
57 59
58int bpf_create_map(enum bpf_map_type map_type, int key_size, 60int bpf_create_map_node(enum bpf_map_type map_type, int key_size,
59 int value_size, int max_entries, __u32 map_flags) 61 int value_size, int max_entries, __u32 map_flags,
62 int node)
60{ 63{
61 union bpf_attr attr; 64 union bpf_attr attr;
62 65
@@ -67,12 +70,24 @@ int bpf_create_map(enum bpf_map_type map_type, int key_size,
67 attr.value_size = value_size; 70 attr.value_size = value_size;
68 attr.max_entries = max_entries; 71 attr.max_entries = max_entries;
69 attr.map_flags = map_flags; 72 attr.map_flags = map_flags;
73 if (node >= 0) {
74 attr.map_flags |= BPF_F_NUMA_NODE;
75 attr.numa_node = node;
76 }
70 77
71 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 78 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
72} 79}
73 80
74int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size, 81int bpf_create_map(enum bpf_map_type map_type, int key_size,
75 int inner_map_fd, int max_entries, __u32 map_flags) 82 int value_size, int max_entries, __u32 map_flags)
83{
84 return bpf_create_map_node(map_type, key_size, value_size,
85 max_entries, map_flags, -1);
86}
87
88int bpf_create_map_in_map_node(enum bpf_map_type map_type, int key_size,
89 int inner_map_fd, int max_entries,
90 __u32 map_flags, int node)
76{ 91{
77 union bpf_attr attr; 92 union bpf_attr attr;
78 93
@@ -84,10 +99,21 @@ int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size,
84 attr.inner_map_fd = inner_map_fd; 99 attr.inner_map_fd = inner_map_fd;
85 attr.max_entries = max_entries; 100 attr.max_entries = max_entries;
86 attr.map_flags = map_flags; 101 attr.map_flags = map_flags;
102 if (node >= 0) {
103 attr.map_flags |= BPF_F_NUMA_NODE;
104 attr.numa_node = node;
105 }
87 106
88 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 107 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
89} 108}
90 109
110int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size,
111 int inner_map_fd, int max_entries, __u32 map_flags)
112{
113 return bpf_create_map_in_map_node(map_type, key_size, inner_map_fd,
114 max_entries, map_flags, -1);
115}
116
91int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, 117int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
92 size_t insns_cnt, const char *license, 118 size_t insns_cnt, const char *license,
93 __u32 kern_version, char *log_buf, size_t log_buf_sz) 119 __u32 kern_version, char *log_buf, size_t log_buf_sz)
@@ -120,7 +146,7 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
120int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, 146int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
121 size_t insns_cnt, int strict_alignment, 147 size_t insns_cnt, int strict_alignment,
122 const char *license, __u32 kern_version, 148 const char *license, __u32 kern_version,
123 char *log_buf, size_t log_buf_sz) 149 char *log_buf, size_t log_buf_sz, int log_level)
124{ 150{
125 union bpf_attr attr; 151 union bpf_attr attr;
126 152
@@ -131,7 +157,7 @@ int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
131 attr.license = ptr_to_u64(license); 157 attr.license = ptr_to_u64(license);
132 attr.log_buf = ptr_to_u64(log_buf); 158 attr.log_buf = ptr_to_u64(log_buf);
133 attr.log_size = log_buf_sz; 159 attr.log_size = log_buf_sz;
134 attr.log_level = 2; 160 attr.log_level = log_level;
135 log_buf[0] = 0; 161 log_buf[0] = 0;
136 attr.kern_version = kern_version; 162 attr.kern_version = kern_version;
137 attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0; 163 attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0;
@@ -314,7 +340,6 @@ int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len)
314 int err; 340 int err;
315 341
316 bzero(&attr, sizeof(attr)); 342 bzero(&attr, sizeof(attr));
317 bzero(info, *info_len);
318 attr.info.bpf_fd = prog_fd; 343 attr.info.bpf_fd = prog_fd;
319 attr.info.info_len = *info_len; 344 attr.info.info_len = *info_len;
320 attr.info.info = ptr_to_u64(info); 345 attr.info.info = ptr_to_u64(info);
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 16de44a14b48..b8ea5843c39e 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -24,8 +24,14 @@
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, int key_size,
28 int value_size, int max_entries, __u32 map_flags,
29 int node);
27int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, 30int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
28 int max_entries, __u32 map_flags); 31 int max_entries, __u32 map_flags);
32int bpf_create_map_in_map_node(enum bpf_map_type map_type, int key_size,
33 int inner_map_fd, int max_entries,
34 __u32 map_flags, int node);
29int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size, 35int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size,
30 int inner_map_fd, int max_entries, __u32 map_flags); 36 int inner_map_fd, int max_entries, __u32 map_flags);
31 37
@@ -38,7 +44,7 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
38int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, 44int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
39 size_t insns_cnt, int strict_alignment, 45 size_t insns_cnt, int strict_alignment,
40 const char *license, __u32 kern_version, 46 const char *license, __u32 kern_version,
41 char *log_buf, size_t log_buf_sz); 47 char *log_buf, size_t log_buf_sz, int log_level);
42 48
43int bpf_map_update_elem(int fd, const void *key, const void *value, 49int bpf_map_update_elem(int fd, const void *key, const void *value,
44 __u64 flags); 50 __u64 flags);
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 1a2c07eb7795..35f6dfcdc565 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -879,7 +879,8 @@ bpf_object__create_maps(struct bpf_object *obj)
879 size_t j; 879 size_t j;
880 int err = *pfd; 880 int err = *pfd;
881 881
882 pr_warning("failed to create map: %s\n", 882 pr_warning("failed to create map (name: '%s'): %s\n",
883 obj->maps[i].name,
883 strerror(errno)); 884 strerror(errno));
884 for (j = 0; j < i; j++) 885 for (j = 0; j < i; j++)
885 zclose(obj->maps[j].fd); 886 zclose(obj->maps[j].fd);
@@ -1744,3 +1745,32 @@ long libbpf_get_error(const void *ptr)
1744 return PTR_ERR(ptr); 1745 return PTR_ERR(ptr);
1745 return 0; 1746 return 0;
1746} 1747}
1748
1749int bpf_prog_load(const char *file, enum bpf_prog_type type,
1750 struct bpf_object **pobj, int *prog_fd)
1751{
1752 struct bpf_program *prog;
1753 struct bpf_object *obj;
1754 int err;
1755
1756 obj = bpf_object__open(file);
1757 if (IS_ERR(obj))
1758 return -ENOENT;
1759
1760 prog = bpf_program__next(NULL, obj);
1761 if (!prog) {
1762 bpf_object__close(obj);
1763 return -ENOENT;
1764 }
1765
1766 bpf_program__set_type(prog, type);
1767 err = bpf_object__load(obj);
1768 if (err) {
1769 bpf_object__close(obj);
1770 return -EINVAL;
1771 }
1772
1773 *pobj = obj;
1774 *prog_fd = bpf_program__fd(prog);
1775 return 0;
1776}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 32c7252f734e..7959086eb9c9 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -243,4 +243,6 @@ int bpf_map__pin(struct bpf_map *map, const char *path);
243 243
244long libbpf_get_error(const void *ptr); 244long libbpf_get_error(const void *ptr);
245 245
246int bpf_prog_load(const char *file, enum bpf_prog_type type,
247 struct bpf_object **pobj, int *prog_fd);
246#endif 248#endif
diff --git a/tools/lib/string.c b/tools/lib/string.c
index 8e678af1c6ee..a4246f14ded1 100644
--- a/tools/lib/string.c
+++ b/tools/lib/string.c
@@ -39,27 +39,45 @@ void *memdup(const void *src, size_t len)
39 * @s: input string 39 * @s: input string
40 * @res: result 40 * @res: result
41 * 41 *
42 * This routine returns 0 iff the first character is one of 'Yy1Nn0'. 42 * 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 43 * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value
44 * updated upon finding a match. 44 * pointed to by res is updated upon finding a match.
45 */ 45 */
46int strtobool(const char *s, bool *res) 46int strtobool(const char *s, bool *res)
47{ 47{
48 if (!s)
49 return -EINVAL;
50
48 switch (s[0]) { 51 switch (s[0]) {
49 case 'y': 52 case 'y':
50 case 'Y': 53 case 'Y':
51 case '1': 54 case '1':
52 *res = true; 55 *res = true;
53 break; 56 return 0;
54 case 'n': 57 case 'n':
55 case 'N': 58 case 'N':
56 case '0': 59 case '0':
57 *res = false; 60 *res = false;
58 break; 61 return 0;
62 case 'o':
63 case 'O':
64 switch (s[1]) {
65 case 'n':
66 case 'N':
67 *res = true;
68 return 0;
69 case 'f':
70 case 'F':
71 *res = false;
72 return 0;
73 default:
74 break;
75 }
59 default: 76 default:
60 return -EINVAL; 77 break;
61 } 78 }
62 return 0; 79
80 return -EINVAL;
63} 81}
64 82
65/** 83/**
@@ -87,12 +105,3 @@ size_t __weak strlcpy(char *dest, const char *src, size_t size)
87 } 105 }
88 return ret; 106 return ret;
89} 107}
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..7e9f03c97e4c 100644
--- a/tools/lib/subcmd/Makefile
+++ b/tools/lib/subcmd/Makefile
@@ -21,7 +21,7 @@ LIBFILE = $(OUTPUT)libsubcmd.a
21CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 21CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
22CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC 22CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
23 23
24ifeq ($(CC), clang) 24ifeq ($(CC_NO_CLANG), 0)
25 CFLAGS += -O3 25 CFLAGS += -O3
26else 26else
27 CFLAGS += -O6 27 CFLAGS += -O6
diff --git a/tools/lib/subcmd/help.c b/tools/lib/subcmd/help.c
index ba970a73d053..0310520f918e 100644
--- a/tools/lib/subcmd/help.c
+++ b/tools/lib/subcmd/help.c
@@ -171,7 +171,7 @@ static void list_commands_in_dir(struct cmdnames *cmds,
171 while ((de = readdir(dir)) != NULL) { 171 while ((de = readdir(dir)) != NULL) {
172 int entlen; 172 int entlen;
173 173
174 if (prefixcmp(de->d_name, prefix)) 174 if (!strstarts(de->d_name, prefix))
175 continue; 175 continue;
176 176
177 astrcat(&buf, de->d_name); 177 astrcat(&buf, de->d_name);
diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c
index 359bfa77f39c..2bd6fd0c1d40 100644
--- a/tools/lib/subcmd/parse-options.c
+++ b/tools/lib/subcmd/parse-options.c
@@ -368,7 +368,7 @@ retry:
368 return 0; 368 return 0;
369 } 369 }
370 if (!rest) { 370 if (!rest) {
371 if (!prefixcmp(options->long_name, "no-")) { 371 if (strstarts(options->long_name, "no-")) {
372 /* 372 /*
373 * The long name itself starts with "no-", so 373 * The long name itself starts with "no-", so
374 * accept the option without "no-" so that users 374 * accept the option without "no-" so that users
@@ -381,7 +381,7 @@ retry:
381 goto match; 381 goto match;
382 } 382 }
383 /* Abbreviated case */ 383 /* Abbreviated case */
384 if (!prefixcmp(options->long_name + 3, arg)) { 384 if (strstarts(options->long_name + 3, arg)) {
385 flags |= OPT_UNSET; 385 flags |= OPT_UNSET;
386 goto is_abbreviated; 386 goto is_abbreviated;
387 } 387 }
@@ -406,7 +406,7 @@ is_abbreviated:
406 continue; 406 continue;
407 } 407 }
408 /* negated and abbreviated very much? */ 408 /* negated and abbreviated very much? */
409 if (!prefixcmp("no-", arg)) { 409 if (strstarts("no-", arg)) {
410 flags |= OPT_UNSET; 410 flags |= OPT_UNSET;
411 goto is_abbreviated; 411 goto is_abbreviated;
412 } 412 }
@@ -416,7 +416,7 @@ is_abbreviated:
416 flags |= OPT_UNSET; 416 flags |= OPT_UNSET;
417 rest = skip_prefix(arg + 3, options->long_name); 417 rest = skip_prefix(arg + 3, options->long_name);
418 /* abbreviated and negated? */ 418 /* abbreviated and negated? */
419 if (!rest && !prefixcmp(options->long_name, arg + 3)) 419 if (!rest && strstarts(options->long_name, arg + 3))
420 goto is_abbreviated; 420 goto is_abbreviated;
421 if (!rest) 421 if (!rest)
422 continue; 422 continue;
@@ -456,7 +456,7 @@ static void check_typos(const char *arg, const struct option *options)
456 if (strlen(arg) < 3) 456 if (strlen(arg) < 3)
457 return; 457 return;
458 458
459 if (!prefixcmp(arg, "no-")) { 459 if (strstarts(arg, "no-")) {
460 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg); 460 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
461 exit(129); 461 exit(129);
462 } 462 }
@@ -464,7 +464,7 @@ static void check_typos(const char *arg, const struct option *options)
464 for (; options->type != OPTION_END; options++) { 464 for (; options->type != OPTION_END; options++) {
465 if (!options->long_name) 465 if (!options->long_name)
466 continue; 466 continue;
467 if (!prefixcmp(options->long_name, arg)) { 467 if (strstarts(options->long_name, arg)) {
468 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg); 468 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
469 exit(129); 469 exit(129);
470 } 470 }
@@ -933,10 +933,10 @@ opt:
933 if (opts->long_name == NULL) 933 if (opts->long_name == NULL)
934 continue; 934 continue;
935 935
936 if (!prefixcmp(opts->long_name, optstr)) 936 if (strstarts(opts->long_name, optstr))
937 print_option_help(opts, 0); 937 print_option_help(opts, 0);
938 if (!prefixcmp("no-", optstr) && 938 if (strstarts("no-", optstr) &&
939 !prefixcmp(opts->long_name, optstr + 3)) 939 strstarts(opts->long_name, optstr + 3))
940 print_option_help(opts, 0); 940 print_option_help(opts, 0);
941 } 941 }
942 942
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..6a1af43862df 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,7 +189,7 @@ 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
@@ -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..6976c73e60c4 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -25,7 +25,8 @@ OBJTOOL_IN := $(OBJTOOL)-in.o
25all: $(OBJTOOL) 25all: $(OBJTOOL)
26 26
27INCLUDES := -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi 27INCLUDES := -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi
28CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -Wno-switch-default -Wno-switch-enum -fomit-frame-pointer -O2 -g $(INCLUDES) 28WARNINGS := $(EXTRA_WARNINGS) -Wno-switch-default -Wno-switch-enum -Wno-packed
29CFLAGS += -Wall -Werror $(WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES)
29LDFLAGS += -lelf $(LIBSUBCMD) 30LDFLAGS += -lelf $(LIBSUBCMD)
30 31
31# Allow old libelf to be used: 32# Allow old libelf to be used:
@@ -52,6 +53,9 @@ $(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN)
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.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 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 || echo "warning: objtool: x86 instruction decoder differs from kernel" >&2 )) || true
56 @(test -d ../../kernel -a -d ../../tools -a -d ../objtool && (( \
57 diff ../../arch/x86/include/asm/orc_types.h orc_types.h >/dev/null) \
58 || echo "warning: objtool: orc_types.h differs from kernel" >&2 )) || true
55 $(QUIET_LINK)$(CC) $(OBJTOOL_IN) $(LDFLAGS) -o $@ 59 $(QUIET_LINK)$(CC) $(OBJTOOL_IN) $(LDFLAGS) -o $@
56 60
57 61
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/decode.c b/tools/objtool/arch/x86/decode.c
index a36c2eba64e7..0e8c8ec4fd4e 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -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
@@ -217,6 +218,18 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
217 op->dest.reg = CFI_BP; 218 op->dest.reg = CFI_BP;
218 break; 219 break;
219 } 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;
230 break;
231 }
232
220 /* fallthrough */ 233 /* fallthrough */
221 case 0x88: 234 case 0x88:
222 if (!rex_b && 235 if (!rex_b &&
@@ -269,56 +282,28 @@ 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 */ 287 /* lea disp(%rsp), reg */
275 *type = INSN_STACK;
276 op->src.type = OP_SRC_ADD;
277 op->src.reg = CFI_BP;
278 op->src.offset = insn.displacement.value;
279 op->dest.type = OP_DEST_REG;
280 op->dest.reg = CFI_SP;
281 break;
282 }
283
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; 288 *type = INSN_STACK;
294 op->src.type = OP_SRC_ADD; 289 op->src.type = OP_SRC_ADD;
295 op->src.reg = CFI_SP; 290 op->src.reg = CFI_SP;
296 op->src.offset = 8; 291 op->src.offset = insn.displacement.value;
297 op->dest.type = OP_DEST_REG; 292 op->dest.type = OP_DEST_REG;
298 op->dest.reg = CFI_R10; 293 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
299 break;
300 }
301 294
302 if (rex == 0x4c && modrm == 0x6c && sib == 0x24 && 295 } else if (rex == 0x48 && modrm == 0x65) {
303 insn.displacement.value == 16) {
304 296
305 /* 297 /* 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; 298 *type = INSN_STACK;
312 op->src.type = OP_SRC_ADD; 299 op->src.type = OP_SRC_ADD;
313 op->src.reg = CFI_SP; 300 op->src.reg = CFI_BP;
314 op->src.offset = 16; 301 op->src.offset = insn.displacement.value;
315 op->dest.type = OP_DEST_REG; 302 op->dest.type = OP_DEST_REG;
316 op->dest.reg = CFI_R13; 303 op->dest.reg = CFI_SP;
317 break;
318 }
319 304
320 if (rex == 0x49 && modrm == 0x62 && 305 } else if (rex == 0x49 && modrm == 0x62 &&
321 insn.displacement.value == -8) { 306 insn.displacement.value == -8) {
322 307
323 /* 308 /*
324 * lea -0x8(%r10), %rsp 309 * lea -0x8(%r10), %rsp
@@ -332,11 +317,9 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
332 op->src.offset = -8; 317 op->src.offset = -8;
333 op->dest.type = OP_DEST_REG; 318 op->dest.type = OP_DEST_REG;
334 op->dest.reg = CFI_SP; 319 op->dest.reg = CFI_SP;
335 break;
336 }
337 320
338 if (rex == 0x49 && modrm == 0x65 && 321 } else if (rex == 0x49 && modrm == 0x65 &&
339 insn.displacement.value == -16) { 322 insn.displacement.value == -16) {
340 323
341 /* 324 /*
342 * lea -0x10(%r13), %rsp 325 * lea -0x10(%r13), %rsp
@@ -350,7 +333,6 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
350 op->src.offset = -16; 333 op->src.offset = -16;
351 op->dest.type = OP_DEST_REG; 334 op->dest.type = OP_DEST_REG;
352 op->dest.reg = CFI_SP; 335 op->dest.reg = CFI_SP;
353 break;
354 } 336 }
355 337
356 break; 338 break;
@@ -382,20 +364,27 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
382 364
383 case 0x0f: 365 case 0x0f:
384 366
385 if (op2 >= 0x80 && op2 <= 0x8f) 367 if (op2 >= 0x80 && op2 <= 0x8f) {
368
386 *type = INSN_JUMP_CONDITIONAL; 369 *type = INSN_JUMP_CONDITIONAL;
387 else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 || 370
388 op2 == 0x35) 371 } else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 ||
372 op2 == 0x35) {
389 373
390 /* sysenter, sysret */ 374 /* sysenter, sysret */
391 *type = INSN_CONTEXT_SWITCH; 375 *type = INSN_CONTEXT_SWITCH;
392 376
393 else if (op2 == 0x0d || op2 == 0x1f) 377 } else if (op2 == 0x0b || op2 == 0xb9) {
378
379 /* ud2 */
380 *type = INSN_BUG;
381
382 } else if (op2 == 0x0d || op2 == 0x1f) {
394 383
395 /* nopl/nopw */ 384 /* nopl/nopw */
396 *type = INSN_NOP; 385 *type = INSN_NOP;
397 386
398 else if (op2 == 0xa0 || op2 == 0xa8) { 387 } else if (op2 == 0xa0 || op2 == 0xa8) {
399 388
400 /* push fs/gs */ 389 /* push fs/gs */
401 *type = INSN_STACK; 390 *type = INSN_STACK;
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..f744617c9946 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) {
@@ -310,7 +299,7 @@ static int decode_instructions(struct objtool_file *file)
310} 299}
311 300
312/* 301/*
313 * Find all uses of the unreachable() macro, which are code path dead ends. 302 * Mark "ud2" instructions and manually annotated dead ends.
314 */ 303 */
315static int add_dead_ends(struct objtool_file *file) 304static int add_dead_ends(struct objtool_file *file)
316{ 305{
@@ -319,9 +308,20 @@ static int add_dead_ends(struct objtool_file *file)
319 struct instruction *insn; 308 struct instruction *insn;
320 bool found; 309 bool found;
321 310
311 /*
312 * By default, "ud2" is a dead end unless otherwise annotated, because
313 * GCC 7 inserts it for certain divide-by-zero cases.
314 */
315 for_each_insn(file, insn)
316 if (insn->type == INSN_BUG)
317 insn->dead_end = true;
318
319 /*
320 * Check for manually annotated dead ends.
321 */
322 sec = find_section_by_name(file->elf, ".rela.discard.unreachable"); 322 sec = find_section_by_name(file->elf, ".rela.discard.unreachable");
323 if (!sec) 323 if (!sec)
324 return 0; 324 goto reachable;
325 325
326 list_for_each_entry(rela, &sec->rela_list, list) { 326 list_for_each_entry(rela, &sec->rela_list, list) {
327 if (rela->sym->type != STT_SECTION) { 327 if (rela->sym->type != STT_SECTION) {
@@ -354,6 +354,48 @@ static int add_dead_ends(struct objtool_file *file)
354 insn->dead_end = true; 354 insn->dead_end = true;
355 } 355 }
356 356
357reachable:
358 /*
359 * These manually annotated reachable checks are needed for GCC 4.4,
360 * where the Linux unreachable() macro isn't supported. In that case
361 * GCC doesn't know the "ud2" is fatal, so it generates code as if it's
362 * not a dead end.
363 */
364 sec = find_section_by_name(file->elf, ".rela.discard.reachable");
365 if (!sec)
366 return 0;
367
368 list_for_each_entry(rela, &sec->rela_list, list) {
369 if (rela->sym->type != STT_SECTION) {
370 WARN("unexpected relocation symbol type in %s", sec->name);
371 return -1;
372 }
373 insn = find_insn(file, rela->sym->sec, rela->addend);
374 if (insn)
375 insn = list_prev_entry(insn, list);
376 else if (rela->addend == rela->sym->sec->len) {
377 found = false;
378 list_for_each_entry_reverse(insn, &file->insn_list, list) {
379 if (insn->sec == rela->sym->sec) {
380 found = true;
381 break;
382 }
383 }
384
385 if (!found) {
386 WARN("can't find reachable insn at %s+0x%x",
387 rela->sym->sec->name, rela->addend);
388 return -1;
389 }
390 } else {
391 WARN("can't find reachable insn at %s+0x%x",
392 rela->sym->sec->name, rela->addend);
393 return -1;
394 }
395
396 insn->dead_end = false;
397 }
398
357 return 0; 399 return 0;
358} 400}
359 401
@@ -874,6 +916,99 @@ static int add_switch_table_alts(struct objtool_file *file)
874 return 0; 916 return 0;
875} 917}
876 918
919static int read_unwind_hints(struct objtool_file *file)
920{
921 struct section *sec, *relasec;
922 struct rela *rela;
923 struct unwind_hint *hint;
924 struct instruction *insn;
925 struct cfi_reg *cfa;
926 int i;
927
928 sec = find_section_by_name(file->elf, ".discard.unwind_hints");
929 if (!sec)
930 return 0;
931
932 relasec = sec->rela;
933 if (!relasec) {
934 WARN("missing .rela.discard.unwind_hints section");
935 return -1;
936 }
937
938 if (sec->len % sizeof(struct unwind_hint)) {
939 WARN("struct unwind_hint size mismatch");
940 return -1;
941 }
942
943 file->hints = true;
944
945 for (i = 0; i < sec->len / sizeof(struct unwind_hint); i++) {
946 hint = (struct unwind_hint *)sec->data->d_buf + i;
947
948 rela = find_rela_by_dest(sec, i * sizeof(*hint));
949 if (!rela) {
950 WARN("can't find rela for unwind_hints[%d]", i);
951 return -1;
952 }
953
954 insn = find_insn(file, rela->sym->sec, rela->addend);
955 if (!insn) {
956 WARN("can't find insn for unwind_hints[%d]", i);
957 return -1;
958 }
959
960 cfa = &insn->state.cfa;
961
962 if (hint->type == UNWIND_HINT_TYPE_SAVE) {
963 insn->save = true;
964 continue;
965
966 } else if (hint->type == UNWIND_HINT_TYPE_RESTORE) {
967 insn->restore = true;
968 insn->hint = true;
969 continue;
970 }
971
972 insn->hint = true;
973
974 switch (hint->sp_reg) {
975 case ORC_REG_UNDEFINED:
976 cfa->base = CFI_UNDEFINED;
977 break;
978 case ORC_REG_SP:
979 cfa->base = CFI_SP;
980 break;
981 case ORC_REG_BP:
982 cfa->base = CFI_BP;
983 break;
984 case ORC_REG_SP_INDIRECT:
985 cfa->base = CFI_SP_INDIRECT;
986 break;
987 case ORC_REG_R10:
988 cfa->base = CFI_R10;
989 break;
990 case ORC_REG_R13:
991 cfa->base = CFI_R13;
992 break;
993 case ORC_REG_DI:
994 cfa->base = CFI_DI;
995 break;
996 case ORC_REG_DX:
997 cfa->base = CFI_DX;
998 break;
999 default:
1000 WARN_FUNC("unsupported unwind_hint sp base reg %d",
1001 insn->sec, insn->offset, hint->sp_reg);
1002 return -1;
1003 }
1004
1005 cfa->offset = hint->sp_offset;
1006 insn->state.type = hint->type;
1007 }
1008
1009 return 0;
1010}
1011
877static int decode_sections(struct objtool_file *file) 1012static int decode_sections(struct objtool_file *file)
878{ 1013{
879 int ret; 1014 int ret;
@@ -904,6 +1039,10 @@ static int decode_sections(struct objtool_file *file)
904 if (ret) 1039 if (ret)
905 return ret; 1040 return ret;
906 1041
1042 ret = read_unwind_hints(file);
1043 if (ret)
1044 return ret;
1045
907 return 0; 1046 return 0;
908} 1047}
909 1048
@@ -947,11 +1086,34 @@ static bool has_valid_stack_frame(struct insn_state *state)
947 return false; 1086 return false;
948} 1087}
949 1088
1089static int update_insn_state_regs(struct instruction *insn, struct insn_state *state)
1090{
1091 struct cfi_reg *cfa = &state->cfa;
1092 struct stack_op *op = &insn->stack_op;
1093
1094 if (cfa->base != CFI_SP)
1095 return 0;
1096
1097 /* push */
1098 if (op->dest.type == OP_DEST_PUSH)
1099 cfa->offset += 8;
1100
1101 /* pop */
1102 if (op->src.type == OP_SRC_POP)
1103 cfa->offset -= 8;
1104
1105 /* add immediate to sp */
1106 if (op->dest.type == OP_DEST_REG && op->src.type == OP_SRC_ADD &&
1107 op->dest.reg == CFI_SP && op->src.reg == CFI_SP)
1108 cfa->offset -= op->src.offset;
1109
1110 return 0;
1111}
1112
950static void save_reg(struct insn_state *state, unsigned char reg, int base, 1113static void save_reg(struct insn_state *state, unsigned char reg, int base,
951 int offset) 1114 int offset)
952{ 1115{
953 if ((arch_callee_saved_reg(reg) || 1116 if (arch_callee_saved_reg(reg) &&
954 (state->drap && reg == state->drap_reg)) &&
955 state->regs[reg].base == CFI_UNDEFINED) { 1117 state->regs[reg].base == CFI_UNDEFINED) {
956 state->regs[reg].base = base; 1118 state->regs[reg].base = base;
957 state->regs[reg].offset = offset; 1119 state->regs[reg].offset = offset;
@@ -1032,30 +1194,56 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1032 return 0; 1194 return 0;
1033 } 1195 }
1034 1196
1197 if (state->type == ORC_TYPE_REGS || state->type == ORC_TYPE_REGS_IRET)
1198 return update_insn_state_regs(insn, state);
1199
1035 switch (op->dest.type) { 1200 switch (op->dest.type) {
1036 1201
1037 case OP_DEST_REG: 1202 case OP_DEST_REG:
1038 switch (op->src.type) { 1203 switch (op->src.type) {
1039 1204
1040 case OP_SRC_REG: 1205 case OP_SRC_REG:
1041 if (cfa->base == op->src.reg && cfa->base == CFI_SP && 1206 if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP) {
1042 op->dest.reg == CFI_BP && regs[CFI_BP].base == CFI_CFA && 1207
1043 regs[CFI_BP].offset == -cfa->offset) { 1208 if (cfa->base == CFI_SP &&
1044 1209 regs[CFI_BP].base == CFI_CFA &&
1045 /* mov %rsp, %rbp */ 1210 regs[CFI_BP].offset == -cfa->offset) {
1046 cfa->base = op->dest.reg; 1211
1047 state->bp_scratch = false; 1212 /* mov %rsp, %rbp */
1048 } else if (state->drap) { 1213 cfa->base = op->dest.reg;
1049 1214 state->bp_scratch = false;
1050 /* drap: mov %rsp, %rbp */ 1215 }
1051 regs[CFI_BP].base = CFI_BP; 1216
1052 regs[CFI_BP].offset = -state->stack_size; 1217 else if (state->drap) {
1053 state->bp_scratch = false; 1218
1054 } else if (!nofp) { 1219 /* drap: mov %rsp, %rbp */
1055 1220 regs[CFI_BP].base = CFI_BP;
1056 WARN_FUNC("unknown stack-related register move", 1221 regs[CFI_BP].offset = -state->stack_size;
1057 insn->sec, insn->offset); 1222 state->bp_scratch = false;
1058 return -1; 1223 }
1224 }
1225
1226 else if (op->dest.reg == cfa->base) {
1227
1228 /* mov %reg, %rsp */
1229 if (cfa->base == CFI_SP &&
1230 state->vals[op->src.reg].base == CFI_CFA) {
1231
1232 /*
1233 * This is needed for the rare case
1234 * where GCC does something dumb like:
1235 *
1236 * lea 0x8(%rsp), %rcx
1237 * ...
1238 * mov %rcx, %rsp
1239 */
1240 cfa->offset = -state->vals[op->src.reg].offset;
1241 state->stack_size = cfa->offset;
1242
1243 } else {
1244 cfa->base = CFI_UNDEFINED;
1245 cfa->offset = 0;
1246 }
1059 } 1247 }
1060 1248
1061 break; 1249 break;
@@ -1077,11 +1265,25 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1077 break; 1265 break;
1078 } 1266 }
1079 1267
1080 if (op->dest.reg != CFI_BP && op->src.reg == CFI_SP && 1268 if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
1081 cfa->base == CFI_SP) {
1082 1269
1083 /* drap: lea disp(%rsp), %drap */ 1270 /* drap: lea disp(%rsp), %drap */
1084 state->drap_reg = op->dest.reg; 1271 state->drap_reg = op->dest.reg;
1272
1273 /*
1274 * lea disp(%rsp), %reg
1275 *
1276 * This is needed for the rare case where GCC
1277 * does something dumb like:
1278 *
1279 * lea 0x8(%rsp), %rcx
1280 * ...
1281 * mov %rcx, %rsp
1282 */
1283 state->vals[op->dest.reg].base = CFI_CFA;
1284 state->vals[op->dest.reg].offset = \
1285 -state->stack_size + op->src.offset;
1286
1085 break; 1287 break;
1086 } 1288 }
1087 1289
@@ -1118,7 +1320,6 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1118 cfa->base = state->drap_reg; 1320 cfa->base = state->drap_reg;
1119 cfa->offset = state->stack_size = 0; 1321 cfa->offset = state->stack_size = 0;
1120 state->drap = true; 1322 state->drap = true;
1121
1122 } 1323 }
1123 1324
1124 /* 1325 /*
@@ -1136,17 +1337,19 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1136 cfa->base = CFI_SP; 1337 cfa->base = CFI_SP;
1137 } 1338 }
1138 1339
1139 if (regs[op->dest.reg].offset == -state->stack_size) { 1340 if (state->drap && cfa->base == CFI_BP_INDIRECT &&
1341 op->dest.type == OP_DEST_REG &&
1342 op->dest.reg == state->drap_reg &&
1343 state->drap_offset == -state->stack_size) {
1140 1344
1141 if (state->drap && cfa->base == CFI_BP_INDIRECT && 1345 /* drap: pop %drap */
1142 op->dest.type == OP_DEST_REG && 1346 cfa->base = state->drap_reg;
1143 op->dest.reg == state->drap_reg) { 1347 cfa->offset = 0;
1348 state->drap_offset = -1;
1144 1349
1145 /* drap: pop %drap */ 1350 } else if (regs[op->dest.reg].offset == -state->stack_size) {
1146 cfa->base = state->drap_reg;
1147 cfa->offset = 0;
1148 }
1149 1351
1352 /* pop %reg */
1150 restore_reg(state, op->dest.reg); 1353 restore_reg(state, op->dest.reg);
1151 } 1354 }
1152 1355
@@ -1158,14 +1361,18 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1158 1361
1159 case OP_SRC_REG_INDIRECT: 1362 case OP_SRC_REG_INDIRECT:
1160 if (state->drap && op->src.reg == CFI_BP && 1363 if (state->drap && op->src.reg == CFI_BP &&
1364 op->src.offset == state->drap_offset) {
1365
1366 /* drap: mov disp(%rbp), %drap */
1367 cfa->base = state->drap_reg;
1368 cfa->offset = 0;
1369 state->drap_offset = -1;
1370 }
1371
1372 if (state->drap && op->src.reg == CFI_BP &&
1161 op->src.offset == regs[op->dest.reg].offset) { 1373 op->src.offset == regs[op->dest.reg].offset) {
1162 1374
1163 /* drap: mov disp(%rbp), %reg */ 1375 /* 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); 1376 restore_reg(state, op->dest.reg);
1170 1377
1171 } else if (op->src.reg == cfa->base && 1378 } else if (op->src.reg == cfa->base &&
@@ -1201,8 +1408,8 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1201 cfa->base = CFI_BP_INDIRECT; 1408 cfa->base = CFI_BP_INDIRECT;
1202 cfa->offset = -state->stack_size; 1409 cfa->offset = -state->stack_size;
1203 1410
1204 /* save drap so we know when to undefine it */ 1411 /* save drap so we know when to restore it */
1205 save_reg(state, op->src.reg, CFI_CFA, -state->stack_size); 1412 state->drap_offset = -state->stack_size;
1206 1413
1207 } else if (op->src.reg == CFI_BP && cfa->base == state->drap_reg) { 1414 } else if (op->src.reg == CFI_BP && cfa->base == state->drap_reg) {
1208 1415
@@ -1222,7 +1429,7 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1222 } 1429 }
1223 1430
1224 /* detect when asm code uses rbp as a scratch register */ 1431 /* detect when asm code uses rbp as a scratch register */
1225 if (!nofp && insn->func && op->src.reg == CFI_BP && 1432 if (!no_fp && insn->func && op->src.reg == CFI_BP &&
1226 cfa->base != CFI_BP) 1433 cfa->base != CFI_BP)
1227 state->bp_scratch = true; 1434 state->bp_scratch = true;
1228 break; 1435 break;
@@ -1236,8 +1443,8 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1236 cfa->base = CFI_BP_INDIRECT; 1443 cfa->base = CFI_BP_INDIRECT;
1237 cfa->offset = op->dest.offset; 1444 cfa->offset = op->dest.offset;
1238 1445
1239 /* save drap so we know when to undefine it */ 1446 /* save drap offset so we know when to restore it */
1240 save_reg(state, op->src.reg, CFI_CFA, op->dest.offset); 1447 state->drap_offset = op->dest.offset;
1241 } 1448 }
1242 1449
1243 else if (regs[op->src.reg].base == CFI_UNDEFINED) { 1450 else if (regs[op->src.reg].base == CFI_UNDEFINED) {
@@ -1323,12 +1530,17 @@ static bool insn_state_match(struct instruction *insn, struct insn_state *state)
1323 break; 1530 break;
1324 } 1531 }
1325 1532
1533 } else if (state1->type != state2->type) {
1534 WARN_FUNC("stack state mismatch: type1=%d type2=%d",
1535 insn->sec, insn->offset, state1->type, state2->type);
1536
1326 } else if (state1->drap != state2->drap || 1537 } else if (state1->drap != state2->drap ||
1327 (state1->drap && state1->drap_reg != state2->drap_reg)) { 1538 (state1->drap && state1->drap_reg != state2->drap_reg) ||
1328 WARN_FUNC("stack state mismatch: drap1=%d(%d) drap2=%d(%d)", 1539 (state1->drap && state1->drap_offset != state2->drap_offset)) {
1540 WARN_FUNC("stack state mismatch: drap1=%d(%d,%d) drap2=%d(%d,%d)",
1329 insn->sec, insn->offset, 1541 insn->sec, insn->offset,
1330 state1->drap, state1->drap_reg, 1542 state1->drap, state1->drap_reg, state1->drap_offset,
1331 state2->drap, state2->drap_reg); 1543 state2->drap, state2->drap_reg, state2->drap_offset);
1332 1544
1333 } else 1545 } else
1334 return true; 1546 return true;
@@ -1346,7 +1558,7 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1346 struct insn_state state) 1558 struct insn_state state)
1347{ 1559{
1348 struct alternative *alt; 1560 struct alternative *alt;
1349 struct instruction *insn; 1561 struct instruction *insn, *next_insn;
1350 struct section *sec; 1562 struct section *sec;
1351 struct symbol *func = NULL; 1563 struct symbol *func = NULL;
1352 int ret; 1564 int ret;
@@ -1357,34 +1569,77 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1357 if (insn->alt_group && list_empty(&insn->alts)) { 1569 if (insn->alt_group && list_empty(&insn->alts)) {
1358 WARN_FUNC("don't know how to handle branch to middle of alternative instruction group", 1570 WARN_FUNC("don't know how to handle branch to middle of alternative instruction group",
1359 sec, insn->offset); 1571 sec, insn->offset);
1360 return -1; 1572 return 1;
1361 } 1573 }
1362 1574
1363 while (1) { 1575 while (1) {
1364 if (file->c_file && insn->func) { 1576 next_insn = next_insn_same_sec(file, insn);
1365 if (func && func != insn->func) { 1577
1366 WARN("%s() falls through to next function %s()", 1578
1367 func->name, insn->func->name); 1579 if (file->c_file && func && insn->func && func != insn->func) {
1368 return 1; 1580 WARN("%s() falls through to next function %s()",
1369 } 1581 func->name, insn->func->name);
1582 return 1;
1370 } 1583 }
1371 1584
1372 func = insn->func; 1585 if (insn->func)
1586 func = insn->func;
1373 1587
1374 if (func && insn->ignore) { 1588 if (func && insn->ignore) {
1375 WARN_FUNC("BUG: why am I validating an ignored function?", 1589 WARN_FUNC("BUG: why am I validating an ignored function?",
1376 sec, insn->offset); 1590 sec, insn->offset);
1377 return -1; 1591 return 1;
1378 } 1592 }
1379 1593
1380 if (insn->visited) { 1594 if (insn->visited) {
1381 if (!!insn_state_match(insn, &state)) 1595 if (!insn->hint && !insn_state_match(insn, &state))
1382 return 1; 1596 return 1;
1383 1597
1384 return 0; 1598 return 0;
1385 } 1599 }
1386 1600
1387 insn->state = state; 1601 if (insn->hint) {
1602 if (insn->restore) {
1603 struct instruction *save_insn, *i;
1604
1605 i = insn;
1606 save_insn = NULL;
1607 func_for_each_insn_continue_reverse(file, func, i) {
1608 if (i->save) {
1609 save_insn = i;
1610 break;
1611 }
1612 }
1613
1614 if (!save_insn) {
1615 WARN_FUNC("no corresponding CFI save for CFI restore",
1616 sec, insn->offset);
1617 return 1;
1618 }
1619
1620 if (!save_insn->visited) {
1621 /*
1622 * Oops, no state to copy yet.
1623 * Hopefully we can reach this
1624 * instruction from another branch
1625 * after the save insn has been
1626 * visited.
1627 */
1628 if (insn == first)
1629 return 0;
1630
1631 WARN_FUNC("objtool isn't smart enough to handle this CFI save/restore combo",
1632 sec, insn->offset);
1633 return 1;
1634 }
1635
1636 insn->state = save_insn->state;
1637 }
1638
1639 state = insn->state;
1640
1641 } else
1642 insn->state = state;
1388 1643
1389 insn->visited = true; 1644 insn->visited = true;
1390 1645
@@ -1423,7 +1678,7 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1423 1678
1424 /* fallthrough */ 1679 /* fallthrough */
1425 case INSN_CALL_DYNAMIC: 1680 case INSN_CALL_DYNAMIC:
1426 if (!nofp && func && !has_valid_stack_frame(&state)) { 1681 if (!no_fp && func && !has_valid_stack_frame(&state)) {
1427 WARN_FUNC("call without frame pointer save/setup", 1682 WARN_FUNC("call without frame pointer save/setup",
1428 sec, insn->offset); 1683 sec, insn->offset);
1429 return 1; 1684 return 1;
@@ -1461,9 +1716,17 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1461 1716
1462 return 0; 1717 return 0;
1463 1718
1719 case INSN_CONTEXT_SWITCH:
1720 if (func && (!next_insn || !next_insn->hint)) {
1721 WARN_FUNC("unsupported instruction in callable function",
1722 sec, insn->offset);
1723 return 1;
1724 }
1725 return 0;
1726
1464 case INSN_STACK: 1727 case INSN_STACK:
1465 if (update_insn_state(insn, &state)) 1728 if (update_insn_state(insn, &state))
1466 return -1; 1729 return 1;
1467 1730
1468 break; 1731 break;
1469 1732
@@ -1474,7 +1737,7 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1474 if (insn->dead_end) 1737 if (insn->dead_end)
1475 return 0; 1738 return 0;
1476 1739
1477 insn = next_insn_same_sec(file, insn); 1740 insn = next_insn;
1478 if (!insn) { 1741 if (!insn) {
1479 WARN("%s: unexpected end of section", sec->name); 1742 WARN("%s: unexpected end of section", sec->name);
1480 return 1; 1743 return 1;
@@ -1484,6 +1747,27 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1484 return 0; 1747 return 0;
1485} 1748}
1486 1749
1750static int validate_unwind_hints(struct objtool_file *file)
1751{
1752 struct instruction *insn;
1753 int ret, warnings = 0;
1754 struct insn_state state;
1755
1756 if (!file->hints)
1757 return 0;
1758
1759 clear_insn_state(&state);
1760
1761 for_each_insn(file, insn) {
1762 if (insn->hint && !insn->visited) {
1763 ret = validate_branch(file, insn, state);
1764 warnings += ret;
1765 }
1766 }
1767
1768 return warnings;
1769}
1770
1487static bool is_kasan_insn(struct instruction *insn) 1771static bool is_kasan_insn(struct instruction *insn)
1488{ 1772{
1489 return (insn->type == INSN_CALL && 1773 return (insn->type == INSN_CALL &&
@@ -1507,8 +1791,13 @@ static bool ignore_unreachable_insn(struct instruction *insn)
1507 /* 1791 /*
1508 * Ignore any unused exceptions. This can happen when a whitelisted 1792 * Ignore any unused exceptions. This can happen when a whitelisted
1509 * function has an exception table entry. 1793 * function has an exception table entry.
1794 *
1795 * Also ignore alternative replacement instructions. This can happen
1796 * when a whitelisted function uses one of the ALTERNATIVE macros.
1510 */ 1797 */
1511 if (!strcmp(insn->sec->name, ".fixup")) 1798 if (!strcmp(insn->sec->name, ".fixup") ||
1799 !strcmp(insn->sec->name, ".altinstr_replacement") ||
1800 !strcmp(insn->sec->name, ".altinstr_aux"))
1512 return true; 1801 return true;
1513 1802
1514 /* 1803 /*
@@ -1580,15 +1869,6 @@ static int validate_reachable_instructions(struct objtool_file *file)
1580 if (insn->visited || ignore_unreachable_insn(insn)) 1869 if (insn->visited || ignore_unreachable_insn(insn))
1581 continue; 1870 continue;
1582 1871
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); 1872 WARN_FUNC("unreachable instruction", insn->sec, insn->offset);
1593 return 1; 1873 return 1;
1594 } 1874 }
@@ -1613,15 +1893,15 @@ static void cleanup(struct objtool_file *file)
1613 elf_close(file->elf); 1893 elf_close(file->elf);
1614} 1894}
1615 1895
1616int check(const char *_objname, bool _nofp) 1896int check(const char *_objname, bool _no_fp, bool no_unreachable, bool orc)
1617{ 1897{
1618 struct objtool_file file; 1898 struct objtool_file file;
1619 int ret, warnings = 0; 1899 int ret, warnings = 0;
1620 1900
1621 objname = _objname; 1901 objname = _objname;
1622 nofp = _nofp; 1902 no_fp = _no_fp;
1623 1903
1624 file.elf = elf_open(objname); 1904 file.elf = elf_open(objname, orc ? O_RDWR : O_RDONLY);
1625 if (!file.elf) 1905 if (!file.elf)
1626 return 1; 1906 return 1;
1627 1907
@@ -1629,8 +1909,9 @@ int check(const char *_objname, bool _nofp)
1629 hash_init(file.insn_hash); 1909 hash_init(file.insn_hash);
1630 file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard"); 1910 file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard");
1631 file.rodata = find_section_by_name(file.elf, ".rodata"); 1911 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"); 1912 file.c_file = find_section_by_name(file.elf, ".comment");
1913 file.ignore_unreachables = no_unreachable;
1914 file.hints = false;
1634 1915
1635 arch_initial_func_cfi_state(&initial_func_cfi); 1916 arch_initial_func_cfi_state(&initial_func_cfi);
1636 1917
@@ -1647,6 +1928,11 @@ int check(const char *_objname, bool _nofp)
1647 goto out; 1928 goto out;
1648 warnings += ret; 1929 warnings += ret;
1649 1930
1931 ret = validate_unwind_hints(&file);
1932 if (ret < 0)
1933 goto out;
1934 warnings += ret;
1935
1650 if (!warnings) { 1936 if (!warnings) {
1651 ret = validate_reachable_instructions(&file); 1937 ret = validate_reachable_instructions(&file);
1652 if (ret < 0) 1938 if (ret < 0)
@@ -1654,6 +1940,20 @@ int check(const char *_objname, bool _nofp)
1654 warnings += ret; 1940 warnings += ret;
1655 } 1941 }
1656 1942
1943 if (orc) {
1944 ret = create_orc(&file);
1945 if (ret < 0)
1946 goto out;
1947
1948 ret = create_orc_sections(&file);
1949 if (ret < 0)
1950 goto out;
1951
1952 ret = elf_write(file.elf);
1953 if (ret < 0)
1954 goto out;
1955 }
1956
1657out: 1957out:
1658 cleanup(&file); 1958 cleanup(&file);
1659 1959
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..6e9f980a7d26 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;
@@ -349,9 +339,10 @@ static int read_relas(struct elf *elf)
349 return 0; 339 return 0;
350} 340}
351 341
352struct elf *elf_open(const char *name) 342struct elf *elf_open(const char *name, int flags)
353{ 343{
354 struct elf *elf; 344 struct elf *elf;
345 Elf_Cmd cmd;
355 346
356 elf_version(EV_CURRENT); 347 elf_version(EV_CURRENT);
357 348
@@ -364,13 +355,20 @@ struct elf *elf_open(const char *name)
364 355
365 INIT_LIST_HEAD(&elf->sections); 356 INIT_LIST_HEAD(&elf->sections);
366 357
367 elf->fd = open(name, O_RDONLY); 358 elf->fd = open(name, flags);
368 if (elf->fd == -1) { 359 if (elf->fd == -1) {
369 perror("open"); 360 perror("open");
370 goto err; 361 goto err;
371 } 362 }
372 363
373 elf->elf = elf_begin(elf->fd, ELF_C_READ_MMAP, NULL); 364 if ((flags & O_ACCMODE) == O_RDONLY)
365 cmd = ELF_C_READ_MMAP;
366 else if ((flags & O_ACCMODE) == O_RDWR)
367 cmd = ELF_C_RDWR;
368 else /* O_WRONLY */
369 cmd = ELF_C_WRITE;
370
371 elf->elf = elf_begin(elf->fd, cmd, NULL);
374 if (!elf->elf) { 372 if (!elf->elf) {
375 WARN_ELF("elf_begin"); 373 WARN_ELF("elf_begin");
376 goto err; 374 goto err;
@@ -397,6 +395,194 @@ err:
397 return NULL; 395 return NULL;
398} 396}
399 397
398struct section *elf_create_section(struct elf *elf, const char *name,
399 size_t entsize, int nr)
400{
401 struct section *sec, *shstrtab;
402 size_t size = entsize * nr;
403 struct Elf_Scn *s;
404 Elf_Data *data;
405
406 sec = malloc(sizeof(*sec));
407 if (!sec) {
408 perror("malloc");
409 return NULL;
410 }
411 memset(sec, 0, sizeof(*sec));
412
413 INIT_LIST_HEAD(&sec->symbol_list);
414 INIT_LIST_HEAD(&sec->rela_list);
415 hash_init(sec->rela_hash);
416 hash_init(sec->symbol_hash);
417
418 list_add_tail(&sec->list, &elf->sections);
419
420 s = elf_newscn(elf->elf);
421 if (!s) {
422 WARN_ELF("elf_newscn");
423 return NULL;
424 }
425
426 sec->name = strdup(name);
427 if (!sec->name) {
428 perror("strdup");
429 return NULL;
430 }
431
432 sec->idx = elf_ndxscn(s);
433 sec->len = size;
434 sec->changed = true;
435
436 sec->data = elf_newdata(s);
437 if (!sec->data) {
438 WARN_ELF("elf_newdata");
439 return NULL;
440 }
441
442 sec->data->d_size = size;
443 sec->data->d_align = 1;
444
445 if (size) {
446 sec->data->d_buf = malloc(size);
447 if (!sec->data->d_buf) {
448 perror("malloc");
449 return NULL;
450 }
451 memset(sec->data->d_buf, 0, size);
452 }
453
454 if (!gelf_getshdr(s, &sec->sh)) {
455 WARN_ELF("gelf_getshdr");
456 return NULL;
457 }
458
459 sec->sh.sh_size = size;
460 sec->sh.sh_entsize = entsize;
461 sec->sh.sh_type = SHT_PROGBITS;
462 sec->sh.sh_addralign = 1;
463 sec->sh.sh_flags = SHF_ALLOC;
464
465
466 /* Add section name to .shstrtab */
467 shstrtab = find_section_by_name(elf, ".shstrtab");
468 if (!shstrtab) {
469 WARN("can't find .shstrtab section");
470 return NULL;
471 }
472
473 s = elf_getscn(elf->elf, shstrtab->idx);
474 if (!s) {
475 WARN_ELF("elf_getscn");
476 return NULL;
477 }
478
479 data = elf_newdata(s);
480 if (!data) {
481 WARN_ELF("elf_newdata");
482 return NULL;
483 }
484
485 data->d_buf = sec->name;
486 data->d_size = strlen(name) + 1;
487 data->d_align = 1;
488
489 sec->sh.sh_name = shstrtab->len;
490
491 shstrtab->len += strlen(name) + 1;
492 shstrtab->changed = true;
493
494 return sec;
495}
496
497struct section *elf_create_rela_section(struct elf *elf, struct section *base)
498{
499 char *relaname;
500 struct section *sec;
501
502 relaname = malloc(strlen(base->name) + strlen(".rela") + 1);
503 if (!relaname) {
504 perror("malloc");
505 return NULL;
506 }
507 strcpy(relaname, ".rela");
508 strcat(relaname, base->name);
509
510 sec = elf_create_section(elf, relaname, sizeof(GElf_Rela), 0);
511 if (!sec)
512 return NULL;
513
514 base->rela = sec;
515 sec->base = base;
516
517 sec->sh.sh_type = SHT_RELA;
518 sec->sh.sh_addralign = 8;
519 sec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
520 sec->sh.sh_info = base->idx;
521 sec->sh.sh_flags = SHF_INFO_LINK;
522
523 return sec;
524}
525
526int elf_rebuild_rela_section(struct section *sec)
527{
528 struct rela *rela;
529 int nr, idx = 0, size;
530 GElf_Rela *relas;
531
532 nr = 0;
533 list_for_each_entry(rela, &sec->rela_list, list)
534 nr++;
535
536 size = nr * sizeof(*relas);
537 relas = malloc(size);
538 if (!relas) {
539 perror("malloc");
540 return -1;
541 }
542
543 sec->data->d_buf = relas;
544 sec->data->d_size = size;
545
546 sec->sh.sh_size = size;
547
548 idx = 0;
549 list_for_each_entry(rela, &sec->rela_list, list) {
550 relas[idx].r_offset = rela->offset;
551 relas[idx].r_addend = rela->addend;
552 relas[idx].r_info = GELF_R_INFO(rela->sym->idx, rela->type);
553 idx++;
554 }
555
556 return 0;
557}
558
559int elf_write(struct elf *elf)
560{
561 struct section *sec;
562 Elf_Scn *s;
563
564 list_for_each_entry(sec, &elf->sections, list) {
565 if (sec->changed) {
566 s = elf_getscn(elf->elf, sec->idx);
567 if (!s) {
568 WARN_ELF("elf_getscn");
569 return -1;
570 }
571 if (!gelf_update_shdr (s, &sec->sh)) {
572 WARN_ELF("gelf_update_shdr");
573 return -1;
574 }
575 }
576 }
577
578 if (elf_update(elf->elf, ELF_C_WRITE) < 0) {
579 WARN_ELF("elf_update");
580 return -1;
581 }
582
583 return 0;
584}
585
400void elf_close(struct elf *elf) 586void elf_close(struct elf *elf)
401{ 587{
402 struct section *sec, *tmpsec; 588 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..31e0f9143840 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;
diff --git a/tools/objtool/orc.h b/tools/objtool/orc.h
new file mode 100644
index 000000000000..a4139e386ef3
--- /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 "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/orc_types.h b/tools/objtool/orc_types.h
new file mode 100644
index 000000000000..9c9dc579bd7d
--- /dev/null
+++ b/tools/objtool/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/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/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-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..e397453e5a46 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -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.
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 9fa84617181e..383a98d992ed 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'.
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 5ee8796be96e..18dfcfa38454 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -117,7 +117,7 @@ OPTIONS
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, brstack, brstacksym, flags, bpf-output, brstackinsn, brstackoff,
120 callindent, insn, insnlen, synth. 120 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
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 698076313606..c37d61682dfb 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::
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index e71d63843f45..d864ea6fd367 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -237,6 +237,10 @@ 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
240INTERACTIVE PROMPTING KEYS 244INTERACTIVE PROMPTING KEYS
241-------------------------- 245--------------------------
242 246
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..62072822dc85 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -70,15 +70,23 @@ tools/include/linux/hash.h
70tools/include/linux/kernel.h 70tools/include/linux/kernel.h
71tools/include/linux/list.h 71tools/include/linux/list.h
72tools/include/linux/log2.h 72tools/include/linux/log2.h
73tools/include/uapi/asm-generic/fcntl.h
74tools/include/uapi/asm-generic/ioctls.h
73tools/include/uapi/asm-generic/mman-common.h 75tools/include/uapi/asm-generic/mman-common.h
74tools/include/uapi/asm-generic/mman.h 76tools/include/uapi/asm-generic/mman.h
77tools/include/uapi/drm/drm.h
78tools/include/uapi/drm/i915_drm.h
75tools/include/uapi/linux/bpf.h 79tools/include/uapi/linux/bpf.h
76tools/include/uapi/linux/bpf_common.h 80tools/include/uapi/linux/bpf_common.h
77tools/include/uapi/linux/fcntl.h 81tools/include/uapi/linux/fcntl.h
78tools/include/uapi/linux/hw_breakpoint.h 82tools/include/uapi/linux/hw_breakpoint.h
83tools/include/uapi/linux/kvm.h
79tools/include/uapi/linux/mman.h 84tools/include/uapi/linux/mman.h
80tools/include/uapi/linux/perf_event.h 85tools/include/uapi/linux/perf_event.h
86tools/include/uapi/linux/sched.h
81tools/include/uapi/linux/stat.h 87tools/include/uapi/linux/stat.h
88tools/include/uapi/linux/vhost.h
89tools/include/uapi/sound/asound.h
82tools/include/linux/poison.h 90tools/include/linux/poison.h
83tools/include/linux/rbtree.h 91tools/include/linux/rbtree.h
84tools/include/linux/rbtree_augmented.h 92tools/include/linux/rbtree_augmented.h
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index bdf0e87f9b29..63f534a0902f 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
@@ -103,8 +103,12 @@ ifdef LIBDW_DIR
103 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include 103 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
104 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib 104 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
105endif 105endif
106DWARFLIBS := -ldw
107ifeq ($(findstring -static,${LDFLAGS}),-static)
108 DWARFLIBS += -lelf -lebl -ldl -lz -llzma -lbz2
109endif
106FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS) 110FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
107FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw 111FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) $(DWARFLIBS)
108 112
109# for linking with debug library, run like: 113# for linking with debug library, run like:
110# make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/ 114# make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
@@ -144,7 +148,7 @@ ifndef DEBUG
144endif 148endif
145 149
146ifeq ($(DEBUG),0) 150ifeq ($(DEBUG),0)
147ifeq ($(CC), clang) 151ifeq ($(CC_NO_CLANG), 0)
148 CFLAGS += -O3 152 CFLAGS += -O3
149else 153else
150 CFLAGS += -O6 154 CFLAGS += -O6
@@ -180,7 +184,7 @@ ifdef PYTHON_CONFIG
180 PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) 184 PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
181 PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil 185 PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil
182 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) 186 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
183 ifeq ($(CC), clang) 187 ifeq ($(CC_NO_CLANG), 1)
184 PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS)) 188 PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS))
185 endif 189 endif
186 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 190 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
@@ -330,6 +334,11 @@ ifeq ($(feature-sched_getcpu), 1)
330 CFLAGS += -DHAVE_SCHED_GETCPU_SUPPORT 334 CFLAGS += -DHAVE_SCHED_GETCPU_SUPPORT
331endif 335endif
332 336
337ifeq ($(feature-setns), 1)
338 CFLAGS += -DHAVE_SETNS_SUPPORT
339 $(call detected,CONFIG_SETNS)
340endif
341
333ifndef NO_LIBELF 342ifndef NO_LIBELF
334 CFLAGS += -DHAVE_LIBELF_SUPPORT 343 CFLAGS += -DHAVE_LIBELF_SUPPORT
335 EXTLIBS += -lelf 344 EXTLIBS += -lelf
@@ -360,10 +369,6 @@ ifndef NO_LIBELF
360 else 369 else
361 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) 370 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
362 LDFLAGS += $(LIBDW_LDFLAGS) 371 LDFLAGS += $(LIBDW_LDFLAGS)
363 DWARFLIBS := -ldw
364 ifeq ($(findstring -static,${LDFLAGS}),-static)
365 DWARFLIBS += -lelf -lebl -lz -llzma -lbz2
366 endif
367 EXTLIBS += ${DWARFLIBS} 372 EXTLIBS += ${DWARFLIBS}
368 $(call detected,CONFIG_DWARF) 373 $(call detected,CONFIG_DWARF)
369 endif # PERF_HAVE_DWARF_REGS 374 endif # PERF_HAVE_DWARF_REGS
@@ -500,6 +505,10 @@ ifndef NO_LOCAL_LIBUNWIND
500 EXTLIBS += $(LIBUNWIND_LIBS) 505 EXTLIBS += $(LIBUNWIND_LIBS)
501 LDFLAGS += $(LIBUNWIND_LIBS) 506 LDFLAGS += $(LIBUNWIND_LIBS)
502endif 507endif
508ifeq ($(findstring -static,${LDFLAGS}),-static)
509 # gcc -static links libgcc_eh which contans piece of libunwind
510 LIBUNWIND_LDFLAGS += -Wl,--allow-multiple-definition
511endif
503 512
504ifndef NO_LIBUNWIND 513ifndef NO_LIBUNWIND
505 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT 514 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 5008f51a08a2..91ef44bfaf3e 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
@@ -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,60 @@ 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
423kvm_ioctl_array := $(beauty_ioctl_outdir)/kvm_ioctl_array.c
424kvm_hdr_dir := $(srctree)/tools/include/uapi/linux
425kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh
426
427$(kvm_ioctl_array): $(kvm_hdr_dir)/kvm.h $(kvm_ioctl_tbl)
428 $(Q)$(SHELL) '$(kvm_ioctl_tbl)' $(kvm_hdr_dir) > $@
429
430vhost_virtio_ioctl_array := $(beauty_ioctl_outdir)/vhost_virtio_ioctl_array.c
431vhost_virtio_hdr_dir := $(srctree)/tools/include/uapi/linux
432vhost_virtio_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
433
434$(vhost_virtio_ioctl_array): $(vhost_virtio_hdr_dir)/vhost.h $(vhost_virtio_ioctl_tbl)
435 $(Q)$(SHELL) '$(vhost_virtio_ioctl_tbl)' $(vhost_virtio_hdr_dir) > $@
436
437perf_ioctl_array := $(beauty_ioctl_outdir)/perf_ioctl_array.c
438perf_hdr_dir := $(srctree)/tools/include/uapi/linux
439perf_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/perf_ioctl.sh
440
441$(perf_ioctl_array): $(perf_hdr_dir)/perf_event.h $(perf_ioctl_tbl)
442 $(Q)$(SHELL) '$(perf_ioctl_tbl)' $(perf_hdr_dir) > $@
443
378all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) 444all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
379 445
380$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST) 446$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
@@ -469,7 +535,13 @@ endif
469__build-dir = $(subst $(OUTPUT),,$(dir $@)) 535__build-dir = $(subst $(OUTPUT),,$(dir $@))
470build-dir = $(if $(__build-dir),$(__build-dir),.) 536build-dir = $(if $(__build-dir),$(__build-dir),.)
471 537
472prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders 538prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioctl_array) \
539 $(pkey_alloc_access_rights_array) \
540 $(sndrv_pcm_ioctl_array) \
541 $(sndrv_ctl_ioctl_array) \
542 $(kvm_ioctl_array) \
543 $(vhost_virtio_ioctl_array) \
544 $(perf_ioctl_array)
473 545
474$(OUTPUT)%.o: %.c prepare FORCE 546$(OUTPUT)%.o: %.c prepare FORCE
475 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 547 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
@@ -512,7 +584,7 @@ $(LIBJVMTI_IN): FORCE
512 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=jvmti obj=jvmti 584 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=jvmti obj=jvmti
513 585
514$(OUTPUT)$(LIBJVMTI): $(LIBJVMTI_IN) 586$(OUTPUT)$(LIBJVMTI): $(LIBJVMTI_IN)
515 $(QUIET_LINK)$(CC) -shared -Wl,-soname -Wl,$(LIBJVMTI) -o $@ $< -lelf -lrt 587 $(QUIET_LINK)$(CC) -shared -Wl,-soname -Wl,$(LIBJVMTI) -o $@ $<
516endif 588endif
517 589
518$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h) 590$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
@@ -703,7 +775,11 @@ install-tests: all install-gtk
703 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ 775 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
704 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ 776 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
705 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ 777 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
706 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' 778 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
779 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell'; \
780 $(INSTALL) tests/shell/*.sh '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell'; \
781 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'; \
782 $(INSTALL) tests/shell/lib/*.sh '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'
707 783
708install-bin: install-tools install-tests install-traceevent-plugins 784install-bin: install-tools install-tests install-traceevent-plugins
709 785
@@ -734,7 +810,14 @@ 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* \ 810 $(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 \ 811 $(OUTPUT)util/intel-pt-decoder/inat-tables.c \
736 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \ 812 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
737 $(OUTPUT)pmu-events/pmu-events.c 813 $(OUTPUT)pmu-events/pmu-events.c \
814 $(OUTPUT)$(drm_ioctl_array) \
815 $(OUTPUT)$(pkey_alloc_access_rights_array) \
816 $(OUTPUT)$(sndrv_ctl_ioctl_array) \
817 $(OUTPUT)$(sndrv_pcm_ioctl_array) \
818 $(OUTPUT)$(kvm_ioctl_array) \
819 $(OUTPUT)$(vhost_virtio_ioctl_array) \
820 $(OUTPUT)$(perf_ioctl_array)
738 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 821 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
739 $(python-clean) 822 $(python-clean)
740 823
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/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/s390/util/Build b/tools/perf/arch/s390/util/Build
index 5bd7b9260cc0..bd518b623d7a 100644
--- a/tools/perf/arch/s390/util/Build
+++ b/tools/perf/arch/s390/util/Build
@@ -1,4 +1,5 @@
1libperf-y += header.o 1libperf-y += header.o
2libperf-y += sym-handling.o
2libperf-y += kvm-stat.o 3libperf-y += kvm-stat.o
3 4
4libperf-$(CONFIG_DWARF) += dwarf-regs.o 5libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/arch/s390/util/sym-handling.c b/tools/perf/arch/s390/util/sym-handling.c
new file mode 100644
index 000000000000..e103f6e46afe
--- /dev/null
+++ b/tools/perf/arch/s390/util/sym-handling.c
@@ -0,0 +1,29 @@
1/*
2 * Architecture specific ELF symbol handling and relocation mapping.
3 *
4 * Copyright 2017 IBM Corp.
5 * Author(s): Thomas Richter <tmricht@linux.vnet.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License (version 2 only)
9 * as published by the Free Software Foundation.
10 */
11
12#include "symbol.h"
13
14#ifdef HAVE_LIBELF_SUPPORT
15bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
16{
17 if (ehdr.e_type == ET_EXEC)
18 return false;
19 return ehdr.e_type == ET_REL || ehdr.e_type == ET_DYN;
20}
21
22void arch__adjust_sym_map_offset(GElf_Sym *sym,
23 GElf_Shdr *shdr __maybe_unused,
24 struct map *map)
25{
26 if (map->type == MAP__FUNCTION)
27 sym->st_value += map->start;
28}
29#endif
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 6c9211b18ec0..9a628a24c5c9 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -20,7 +20,7 @@ _dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
20$(header): $(sys)/syscall_64.tbl $(systbl) 20$(header): $(sys)/syscall_64.tbl $(systbl)
21 @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \ 21 @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
22 (diff -B arch/x86/entry/syscalls/syscall_64.tbl ../../arch/x86/entry/syscalls/syscall_64.tbl >/dev/null) \ 22 (diff -B arch/x86/entry/syscalls/syscall_64.tbl ../../arch/x86/entry/syscalls/syscall_64.tbl >/dev/null) \
23 || echo "Warning: x86_64's syscall_64.tbl differs from kernel" >&2 )) || true 23 || 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' > $@ 24 $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@
25 25
26clean:: 26clean::
diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c
index c1625f256df3..d84b72063a30 100644
--- a/tools/perf/arch/x86/annotate/instructions.c
+++ b/tools/perf/arch/x86/annotate/instructions.c
@@ -76,3 +76,49 @@ static struct ins x86__instructions[] = {
76 { .name = "xbeginq", .ops = &jump_ops, }, 76 { .name = "xbeginq", .ops = &jump_ops, },
77 { .name = "retq", .ops = &ret_ops, }, 77 { .name = "retq", .ops = &ret_ops, },
78}; 78};
79
80static bool x86__ins_is_fused(struct arch *arch, const char *ins1,
81 const char *ins2)
82{
83 if (arch->family != 6 || arch->model < 0x1e || strstr(ins2, "jmp"))
84 return false;
85
86 if (arch->model == 0x1e) {
87 /* Nehalem */
88 if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
89 strstr(ins1, "test")) {
90 return true;
91 }
92 } else {
93 /* Newer platform */
94 if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
95 strstr(ins1, "test") ||
96 strstr(ins1, "add") ||
97 strstr(ins1, "sub") ||
98 strstr(ins1, "and") ||
99 strstr(ins1, "inc") ||
100 strstr(ins1, "dec")) {
101 return true;
102 }
103 }
104
105 return false;
106}
107
108static int x86__cpuid_parse(struct arch *arch, char *cpuid)
109{
110 unsigned int family, model, stepping;
111 int ret;
112
113 /*
114 * cpuid = "GenuineIntel,family,model,stepping"
115 */
116 ret = sscanf(cpuid, "%*[^,],%u,%u,%u", &family, &model, &stepping);
117 if (ret == 3) {
118 arch->family = family;
119 arch->model = model;
120 return 0;
121 }
122
123 return -1;
124}
diff --git a/tools/perf/arch/x86/include/arch-tests.h b/tools/perf/arch/x86/include/arch-tests.h
index b48de2f5813c..4e0b806a7a0f 100644
--- a/tools/perf/arch/x86/include/arch-tests.h
+++ b/tools/perf/arch/x86/include/arch-tests.h
@@ -1,11 +1,14 @@
1#ifndef ARCH_TESTS_H 1#ifndef ARCH_TESTS_H
2#define ARCH_TESTS_H 2#define ARCH_TESTS_H
3 3
4#include <linux/compiler.h>
5struct test;
6
4/* Tests */ 7/* Tests */
5int test__rdpmc(int subtest); 8int test__rdpmc(struct test *test __maybe_unused, int subtest);
6int test__perf_time_to_tsc(int subtest); 9int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest);
7int test__insn_x86(int subtest); 10int test__insn_x86(struct test *test __maybe_unused, int subtest);
8int test__intel_cqm_count_nmi_context(int subtest); 11int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, 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/tests/insn-x86.c b/tools/perf/arch/x86/tests/insn-x86.c
index 08d9b2bc185c..b3860586a0c2 100644
--- a/tools/perf/arch/x86/tests/insn-x86.c
+++ b/tools/perf/arch/x86/tests/insn-x86.c
@@ -171,7 +171,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 171 * verbose (-v) option to see all the instructions and whether or not they
172 * decoded successfuly. 172 * decoded successfuly.
173 */ 173 */
174int test__insn_x86(int subtest __maybe_unused) 174int test__insn_x86(struct test *test __maybe_unused, int subtest __maybe_unused)
175{ 175{
176 int ret = 0; 176 int ret = 0;
177 177
diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c
index f9713a71d77e..57f86b6e7d6f 100644
--- a/tools/perf/arch/x86/tests/intel-cqm.c
+++ b/tools/perf/arch/x86/tests/intel-cqm.c
@@ -36,7 +36,7 @@ static pid_t spawn(void)
36 * the last read counter value to avoid triggering a WARN_ON_ONCE() in 36 * 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. 37 * smp_call_function_many() caused by sending IPIs from NMI context.
38 */ 38 */
39int test__intel_cqm_count_nmi_context(int subtest __maybe_unused) 39int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, int subtest __maybe_unused)
40{ 40{
41 struct perf_evlist *evlist = NULL; 41 struct perf_evlist *evlist = NULL;
42 struct perf_evsel *evsel = NULL; 42 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..5dd7efb192ce 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -37,7 +37,7 @@
37 * %0 is returned, otherwise %-1 is returned. If TSC conversion is not 37 * %0 is returned, otherwise %-1 is returned. If TSC conversion is not
38 * supported then then the test passes but " (not supported)" is printed. 38 * supported then then the test passes but " (not supported)" is printed.
39 */ 39 */
40int test__perf_time_to_tsc(int subtest __maybe_unused) 40int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe_unused)
41{ 41{
42 struct record_opts opts = { 42 struct record_opts opts = {
43 .mmap_pages = UINT_MAX, 43 .mmap_pages = UINT_MAX,
diff --git a/tools/perf/arch/x86/tests/rdpmc.c b/tools/perf/arch/x86/tests/rdpmc.c
index 500cf96db979..17fec30a0b31 100644
--- a/tools/perf/arch/x86/tests/rdpmc.c
+++ b/tools/perf/arch/x86/tests/rdpmc.c
@@ -154,7 +154,7 @@ out_close:
154 return 0; 154 return 0;
155} 155}
156 156
157int test__rdpmc(int subtest __maybe_unused) 157int test__rdpmc(struct test *test __maybe_unused, int subtest __maybe_unused)
158{ 158{
159 int status = 0; 159 int status = 0;
160 int wret = 0; 160 int wret = 0;
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/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 7a5dc7e5c577..c38373195c4a 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -177,14 +177,11 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
177 */ 177 */
178 process_branch_stack(sample->branch_stack, al, sample); 178 process_branch_stack(sample->branch_stack, al, sample);
179 179
180 sample->period = 1;
181 sample->weight = 1;
182
183 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); 180 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
184 if (he == NULL) 181 if (he == NULL)
185 return -ENOMEM; 182 return -ENOMEM;
186 183
187 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 184 ret = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr);
188 hists__inc_nr_samples(hists, true); 185 hists__inc_nr_samples(hists, true);
189 return ret; 186 return ret;
190} 187}
@@ -397,6 +394,8 @@ int cmd_annotate(int argc, const char **argv)
397 .namespaces = perf_event__process_namespaces, 394 .namespaces = perf_event__process_namespaces,
398 .attr = perf_event__process_attr, 395 .attr = perf_event__process_attr,
399 .build_id = perf_event__process_build_id, 396 .build_id = perf_event__process_build_id,
397 .tracing_data = perf_event__process_tracing_data,
398 .feature = perf_event__process_feature,
400 .ordered_events = true, 399 .ordered_events = true,
401 .ordering_requires_timestamps = true, 400 .ordering_requires_timestamps = true,
402 }, 401 },
@@ -404,7 +403,7 @@ int cmd_annotate(int argc, const char **argv)
404 struct perf_data_file file = { 403 struct perf_data_file file = {
405 .mode = PERF_DATA_MODE_READ, 404 .mode = PERF_DATA_MODE_READ,
406 }; 405 };
407 const struct option options[] = { 406 struct option options[] = {
408 OPT_STRING('i', "input", &input_name, "file", 407 OPT_STRING('i', "input", &input_name, "file",
409 "input file name"), 408 "input file name"),
410 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 409 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
@@ -446,13 +445,20 @@ int cmd_annotate(int argc, const char **argv)
446 "Show event group information together"), 445 "Show event group information together"),
447 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 446 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
448 "Show a column with the sum of periods"), 447 "Show a column with the sum of periods"),
448 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
449 "Show a column with the number of samples"),
449 OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode", 450 OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
450 "'always' (default), 'never' or 'auto' only applicable to --stdio mode", 451 "'always' (default), 'never' or 'auto' only applicable to --stdio mode",
451 stdio__config_color, "always"), 452 stdio__config_color, "always"),
452 OPT_END() 453 OPT_END()
453 }; 454 };
454 int ret = hists__init(); 455 int ret;
456
457 set_option_flag(options, 0, "show-total-period", PARSE_OPT_EXCLUSIVE);
458 set_option_flag(options, 0, "show-nr-samples", PARSE_OPT_EXCLUSIVE);
459
455 460
461 ret = hists__init();
456 if (ret < 0) 462 if (ret < 0)
457 return ret; 463 return ret;
458 464
@@ -468,6 +474,11 @@ int cmd_annotate(int argc, const char **argv)
468 annotate.sym_hist_filter = argv[0]; 474 annotate.sym_hist_filter = argv[0];
469 } 475 }
470 476
477 if (symbol_conf.show_nr_samples && annotate.use_gtk) {
478 pr_err("--show-nr-samples is not available in --gtk mode at this time\n");
479 return ret;
480 }
481
471 if (quiet) 482 if (quiet)
472 perf_quiet_option(); 483 perf_quiet_option();
473 484
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 9eba7f1add1f..e3eb6240ced0 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -14,6 +14,7 @@
14#include <unistd.h> 14#include <unistd.h>
15#include "builtin.h" 15#include "builtin.h"
16#include "perf.h" 16#include "perf.h"
17#include "namespaces.h"
17#include "util/cache.h" 18#include "util/cache.h"
18#include "util/debug.h" 19#include "util/debug.h"
19#include "util/header.h" 20#include "util/header.h"
@@ -165,33 +166,41 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
165 return 0; 166 return 0;
166} 167}
167 168
168static int build_id_cache__add_file(const char *filename) 169static int build_id_cache__add_file(const char *filename, struct nsinfo *nsi)
169{ 170{
170 char sbuild_id[SBUILD_ID_SIZE]; 171 char sbuild_id[SBUILD_ID_SIZE];
171 u8 build_id[BUILD_ID_SIZE]; 172 u8 build_id[BUILD_ID_SIZE];
172 int err; 173 int err;
174 struct nscookie nsc;
173 175
174 if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) { 176 nsinfo__mountns_enter(nsi, &nsc);
177 err = filename__read_build_id(filename, &build_id, sizeof(build_id));
178 nsinfo__mountns_exit(&nsc);
179 if (err < 0) {
175 pr_debug("Couldn't read a build-id in %s\n", filename); 180 pr_debug("Couldn't read a build-id in %s\n", filename);
176 return -1; 181 return -1;
177 } 182 }
178 183
179 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 184 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
180 err = build_id_cache__add_s(sbuild_id, filename, 185 err = build_id_cache__add_s(sbuild_id, filename, nsi,
181 false, false); 186 false, false);
182 pr_debug("Adding %s %s: %s\n", sbuild_id, filename, 187 pr_debug("Adding %s %s: %s\n", sbuild_id, filename,
183 err ? "FAIL" : "Ok"); 188 err ? "FAIL" : "Ok");
184 return err; 189 return err;
185} 190}
186 191
187static int build_id_cache__remove_file(const char *filename) 192static int build_id_cache__remove_file(const char *filename, struct nsinfo *nsi)
188{ 193{
189 u8 build_id[BUILD_ID_SIZE]; 194 u8 build_id[BUILD_ID_SIZE];
190 char sbuild_id[SBUILD_ID_SIZE]; 195 char sbuild_id[SBUILD_ID_SIZE];
196 struct nscookie nsc;
191 197
192 int err; 198 int err;
193 199
194 if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) { 200 nsinfo__mountns_enter(nsi, &nsc);
201 err = filename__read_build_id(filename, &build_id, sizeof(build_id));
202 nsinfo__mountns_exit(&nsc);
203 if (err < 0) {
195 pr_debug("Couldn't read a build-id in %s\n", filename); 204 pr_debug("Couldn't read a build-id in %s\n", filename);
196 return -1; 205 return -1;
197 } 206 }
@@ -204,13 +213,13 @@ static int build_id_cache__remove_file(const char *filename)
204 return err; 213 return err;
205} 214}
206 215
207static int build_id_cache__purge_path(const char *pathname) 216static int build_id_cache__purge_path(const char *pathname, struct nsinfo *nsi)
208{ 217{
209 struct strlist *list; 218 struct strlist *list;
210 struct str_node *pos; 219 struct str_node *pos;
211 int err; 220 int err;
212 221
213 err = build_id_cache__list_build_ids(pathname, &list); 222 err = build_id_cache__list_build_ids(pathname, nsi, &list);
214 if (err) 223 if (err)
215 goto out; 224 goto out;
216 225
@@ -234,7 +243,7 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
234 char filename[PATH_MAX]; 243 char filename[PATH_MAX];
235 u8 build_id[BUILD_ID_SIZE]; 244 u8 build_id[BUILD_ID_SIZE];
236 245
237 if (dso__build_id_filename(dso, filename, sizeof(filename)) && 246 if (dso__build_id_filename(dso, filename, sizeof(filename), false) &&
238 filename__read_build_id(filename, build_id, 247 filename__read_build_id(filename, build_id,
239 sizeof(build_id)) != sizeof(build_id)) { 248 sizeof(build_id)) != sizeof(build_id)) {
240 if (errno == ENOENT) 249 if (errno == ENOENT)
@@ -256,24 +265,30 @@ static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *f
256 return 0; 265 return 0;
257} 266}
258 267
259static int build_id_cache__update_file(const char *filename) 268static int build_id_cache__update_file(const char *filename, struct nsinfo *nsi)
260{ 269{
261 u8 build_id[BUILD_ID_SIZE]; 270 u8 build_id[BUILD_ID_SIZE];
262 char sbuild_id[SBUILD_ID_SIZE]; 271 char sbuild_id[SBUILD_ID_SIZE];
272 struct nscookie nsc;
263 273
264 int err = 0; 274 int err;
265 275
266 if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) { 276 nsinfo__mountns_enter(nsi, &nsc);
277 err = filename__read_build_id(filename, &build_id, sizeof(build_id));
278 nsinfo__mountns_exit(&nsc);
279 if (err < 0) {
267 pr_debug("Couldn't read a build-id in %s\n", filename); 280 pr_debug("Couldn't read a build-id in %s\n", filename);
268 return -1; 281 return -1;
269 } 282 }
283 err = 0;
270 284
271 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 285 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
272 if (build_id_cache__cached(sbuild_id)) 286 if (build_id_cache__cached(sbuild_id))
273 err = build_id_cache__remove_s(sbuild_id); 287 err = build_id_cache__remove_s(sbuild_id);
274 288
275 if (!err) 289 if (!err)
276 err = build_id_cache__add_s(sbuild_id, filename, false, false); 290 err = build_id_cache__add_s(sbuild_id, filename, nsi, false,
291 false);
277 292
278 pr_debug("Updating %s %s: %s\n", sbuild_id, filename, 293 pr_debug("Updating %s %s: %s\n", sbuild_id, filename,
279 err ? "FAIL" : "Ok"); 294 err ? "FAIL" : "Ok");
@@ -286,6 +301,7 @@ int cmd_buildid_cache(int argc, const char **argv)
286 struct strlist *list; 301 struct strlist *list;
287 struct str_node *pos; 302 struct str_node *pos;
288 int ret = 0; 303 int ret = 0;
304 int ns_id = -1;
289 bool force = false; 305 bool force = false;
290 char const *add_name_list_str = NULL, 306 char const *add_name_list_str = NULL,
291 *remove_name_list_str = NULL, 307 *remove_name_list_str = NULL,
@@ -299,6 +315,7 @@ int cmd_buildid_cache(int argc, const char **argv)
299 .mode = PERF_DATA_MODE_READ, 315 .mode = PERF_DATA_MODE_READ,
300 }; 316 };
301 struct perf_session *session = NULL; 317 struct perf_session *session = NULL;
318 struct nsinfo *nsi = NULL;
302 319
303 const struct option buildid_cache_options[] = { 320 const struct option buildid_cache_options[] = {
304 OPT_STRING('a', "add", &add_name_list_str, 321 OPT_STRING('a', "add", &add_name_list_str,
@@ -315,6 +332,7 @@ int cmd_buildid_cache(int argc, const char **argv)
315 OPT_STRING('u', "update", &update_name_list_str, "file list", 332 OPT_STRING('u', "update", &update_name_list_str, "file list",
316 "file(s) to update"), 333 "file(s) to update"),
317 OPT_INCR('v', "verbose", &verbose, "be more verbose"), 334 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
335 OPT_INTEGER(0, "target-ns", &ns_id, "target pid for namespace context"),
318 OPT_END() 336 OPT_END()
319 }; 337 };
320 const char * const buildid_cache_usage[] = { 338 const char * const buildid_cache_usage[] = {
@@ -330,6 +348,9 @@ int cmd_buildid_cache(int argc, const char **argv)
330 !missing_filename && !update_name_list_str)) 348 !missing_filename && !update_name_list_str))
331 usage_with_options(buildid_cache_usage, buildid_cache_options); 349 usage_with_options(buildid_cache_usage, buildid_cache_options);
332 350
351 if (ns_id > 0)
352 nsi = nsinfo__new(ns_id);
353
333 if (missing_filename) { 354 if (missing_filename) {
334 file.path = missing_filename; 355 file.path = missing_filename;
335 file.force = force; 356 file.force = force;
@@ -348,7 +369,7 @@ int cmd_buildid_cache(int argc, const char **argv)
348 list = strlist__new(add_name_list_str, NULL); 369 list = strlist__new(add_name_list_str, NULL);
349 if (list) { 370 if (list) {
350 strlist__for_each_entry(pos, list) 371 strlist__for_each_entry(pos, list)
351 if (build_id_cache__add_file(pos->s)) { 372 if (build_id_cache__add_file(pos->s, nsi)) {
352 if (errno == EEXIST) { 373 if (errno == EEXIST) {
353 pr_debug("%s already in the cache\n", 374 pr_debug("%s already in the cache\n",
354 pos->s); 375 pos->s);
@@ -366,7 +387,7 @@ int cmd_buildid_cache(int argc, const char **argv)
366 list = strlist__new(remove_name_list_str, NULL); 387 list = strlist__new(remove_name_list_str, NULL);
367 if (list) { 388 if (list) {
368 strlist__for_each_entry(pos, list) 389 strlist__for_each_entry(pos, list)
369 if (build_id_cache__remove_file(pos->s)) { 390 if (build_id_cache__remove_file(pos->s, nsi)) {
370 if (errno == ENOENT) { 391 if (errno == ENOENT) {
371 pr_debug("%s wasn't in the cache\n", 392 pr_debug("%s wasn't in the cache\n",
372 pos->s); 393 pos->s);
@@ -384,7 +405,7 @@ int cmd_buildid_cache(int argc, const char **argv)
384 list = strlist__new(purge_name_list_str, NULL); 405 list = strlist__new(purge_name_list_str, NULL);
385 if (list) { 406 if (list) {
386 strlist__for_each_entry(pos, list) 407 strlist__for_each_entry(pos, list)
387 if (build_id_cache__purge_path(pos->s)) { 408 if (build_id_cache__purge_path(pos->s, nsi)) {
388 if (errno == ENOENT) { 409 if (errno == ENOENT) {
389 pr_debug("%s wasn't in the cache\n", 410 pr_debug("%s wasn't in the cache\n",
390 pos->s); 411 pos->s);
@@ -405,7 +426,7 @@ int cmd_buildid_cache(int argc, const char **argv)
405 list = strlist__new(update_name_list_str, NULL); 426 list = strlist__new(update_name_list_str, NULL);
406 if (list) { 427 if (list) {
407 strlist__for_each_entry(pos, list) 428 strlist__for_each_entry(pos, list)
408 if (build_id_cache__update_file(pos->s)) { 429 if (build_id_cache__update_file(pos->s, nsi)) {
409 if (errno == ENOENT) { 430 if (errno == ENOENT) {
410 pr_debug("%s wasn't in the cache\n", 431 pr_debug("%s wasn't in the cache\n",
411 pos->s); 432 pos->s);
@@ -424,6 +445,7 @@ int cmd_buildid_cache(int argc, const char **argv)
424 445
425out: 446out:
426 perf_session__delete(session); 447 perf_session__delete(session);
448 nsinfo__zput(nsi);
427 449
428 return ret; 450 return ret;
429} 451}
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index ece45582a48d..a1d82e33282c 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -13,6 +13,7 @@
13#include "util/util.h" 13#include "util/util.h"
14#include "util/debug.h" 14#include "util/debug.h"
15#include "util/config.h" 15#include "util/config.h"
16#include <linux/string.h>
16 17
17static bool use_system_config, use_user_config; 18static bool use_system_config, use_user_config;
18 19
@@ -58,7 +59,7 @@ static int set_config(struct perf_config_set *set, const char *file_name,
58 fprintf(fp, "[%s]\n", section->name); 59 fprintf(fp, "[%s]\n", section->name);
59 60
60 perf_config_items__for_each_entry(&section->items, item) { 61 perf_config_items__for_each_entry(&section->items, item) {
61 if (!use_system_config && section->from_system_config) 62 if (!use_system_config && item->from_system_config)
62 continue; 63 continue;
63 if (item->value) 64 if (item->value)
64 fprintf(fp, "\t%s = %s\n", 65 fprintf(fp, "\t%s = %s\n",
@@ -79,7 +80,7 @@ static int show_spec_config(struct perf_config_set *set, const char *var)
79 return -1; 80 return -1;
80 81
81 perf_config_items__for_each_entry(&set->sections, section) { 82 perf_config_items__for_each_entry(&set->sections, section) {
82 if (prefixcmp(var, section->name) != 0) 83 if (!strstarts(var, section->name))
83 continue; 84 continue;
84 85
85 perf_config_items__for_each_entry(&section->items, item) { 86 perf_config_items__for_each_entry(&section->items, item) {
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
index 0adb5f82335a..46cd8490baf4 100644
--- a/tools/perf/builtin-data.c
+++ b/tools/perf/builtin-data.c
@@ -69,7 +69,7 @@ static int cmd_data_convert(int argc, const char **argv)
69 }; 69 };
70 70
71#ifndef HAVE_LIBBABELTRACE_SUPPORT 71#ifndef HAVE_LIBBABELTRACE_SUPPORT
72 pr_err("No conversion support compiled in.\n"); 72 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; 73 return -1;
74#endif 74#endif
75 75
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..dbe4e4153bcf 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -90,7 +90,7 @@ static int check_emacsclient_version(void)
90 */ 90 */
91 finish_command(&ec_process); 91 finish_command(&ec_process);
92 92
93 if (prefixcmp(buffer.buf, "emacsclient")) { 93 if (!strstarts(buffer.buf, "emacsclient")) {
94 fprintf(stderr, "Failed to parse emacsclient version.\n"); 94 fprintf(stderr, "Failed to parse emacsclient version.\n");
95 goto out; 95 goto out;
96 } 96 }
@@ -283,7 +283,7 @@ static int perf_help_config(const char *var, const char *value, void *cb)
283 add_man_viewer(value); 283 add_man_viewer(value);
284 return 0; 284 return 0;
285 } 285 }
286 if (!prefixcmp(var, "man.")) 286 if (!strstarts(var, "man."))
287 return add_man_viewer_info(var, value); 287 return add_man_viewer_info(var, value);
288 288
289 return 0; 289 return 0;
@@ -313,7 +313,7 @@ static const char *cmd_to_page(const char *perf_cmd)
313 313
314 if (!perf_cmd) 314 if (!perf_cmd)
315 return "perf"; 315 return "perf";
316 else if (!prefixcmp(perf_cmd, "perf")) 316 else if (!strstarts(perf_cmd, "perf"))
317 return perf_cmd; 317 return perf_cmd;
318 318
319 return asprintf(&s, "perf-%s", perf_cmd) < 0 ? NULL : s; 319 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..2b8032908fb2 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -770,6 +770,7 @@ int cmd_inject(int argc, const char **argv)
770 .finished_round = perf_event__repipe_oe_synth, 770 .finished_round = perf_event__repipe_oe_synth,
771 .build_id = perf_event__repipe_op2_synth, 771 .build_id = perf_event__repipe_op2_synth,
772 .id_index = perf_event__repipe_op2_synth, 772 .id_index = perf_event__repipe_op2_synth,
773 .feature = perf_event__repipe_op2_synth,
773 }, 774 },
774 .input_name = "-", 775 .input_name = "-",
775 .samples = LIST_HEAD_INIT(inject.samples), 776 .samples = LIST_HEAD_INIT(inject.samples),
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index a1497c516d85..24ee68ecdd42 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -627,7 +627,6 @@ static const struct {
627 { "GFP_HIGHUSER_MOVABLE", "HUM" }, 627 { "GFP_HIGHUSER_MOVABLE", "HUM" },
628 { "GFP_HIGHUSER", "HU" }, 628 { "GFP_HIGHUSER", "HU" },
629 { "GFP_USER", "U" }, 629 { "GFP_USER", "U" },
630 { "GFP_TEMPORARY", "TMP" },
631 { "GFP_KERNEL_ACCOUNT", "KAC" }, 630 { "GFP_KERNEL_ACCOUNT", "KAC" },
632 { "GFP_KERNEL", "K" }, 631 { "GFP_KERNEL", "K" },
633 { "GFP_NOFS", "NF" }, 632 { "GFP_NOFS", "NF" },
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index e001c0290793..0f15634ef82c 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -23,6 +23,7 @@ struct perf_mem {
23 bool hide_unresolved; 23 bool hide_unresolved;
24 bool dump_raw; 24 bool dump_raw;
25 bool force; 25 bool force;
26 bool phys_addr;
26 int operation; 27 int operation;
27 const char *cpu_list; 28 const char *cpu_list;
28 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 29 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -101,6 +102,9 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
101 102
102 rec_argv[i++] = "-d"; 103 rec_argv[i++] = "-d";
103 104
105 if (mem->phys_addr)
106 rec_argv[i++] = "--phys-data";
107
104 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { 108 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
105 if (!perf_mem_events[j].record) 109 if (!perf_mem_events[j].record)
106 continue; 110 continue;
@@ -161,30 +165,60 @@ dump_raw_samples(struct perf_tool *tool,
161 if (al.map != NULL) 165 if (al.map != NULL)
162 al.map->dso->hit = 1; 166 al.map->dso->hit = 1;
163 167
164 if (symbol_conf.field_sep) { 168 if (mem->phys_addr) {
165 fmt = "%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s%"PRIu64 169 if (symbol_conf.field_sep) {
166 "%s0x%"PRIx64"%s%s:%s\n"; 170 fmt = "%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s0x%016"PRIx64
171 "%s%"PRIu64"%s0x%"PRIx64"%s%s:%s\n";
172 } else {
173 fmt = "%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64
174 "%s0x%016"PRIx64"%s%5"PRIu64"%s0x%06"PRIx64
175 "%s%s:%s\n";
176 symbol_conf.field_sep = " ";
177 }
178
179 printf(fmt,
180 sample->pid,
181 symbol_conf.field_sep,
182 sample->tid,
183 symbol_conf.field_sep,
184 sample->ip,
185 symbol_conf.field_sep,
186 sample->addr,
187 symbol_conf.field_sep,
188 sample->phys_addr,
189 symbol_conf.field_sep,
190 sample->weight,
191 symbol_conf.field_sep,
192 sample->data_src,
193 symbol_conf.field_sep,
194 al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???",
195 al.sym ? al.sym->name : "???");
167 } else { 196 } else {
168 fmt = "%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64 197 if (symbol_conf.field_sep) {
169 "%s%5"PRIu64"%s0x%06"PRIx64"%s%s:%s\n"; 198 fmt = "%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s%"PRIu64
170 symbol_conf.field_sep = " "; 199 "%s0x%"PRIx64"%s%s:%s\n";
171 } 200 } else {
201 fmt = "%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64
202 "%s%5"PRIu64"%s0x%06"PRIx64"%s%s:%s\n";
203 symbol_conf.field_sep = " ";
204 }
172 205
173 printf(fmt, 206 printf(fmt,
174 sample->pid, 207 sample->pid,
175 symbol_conf.field_sep, 208 symbol_conf.field_sep,
176 sample->tid, 209 sample->tid,
177 symbol_conf.field_sep, 210 symbol_conf.field_sep,
178 sample->ip, 211 sample->ip,
179 symbol_conf.field_sep, 212 symbol_conf.field_sep,
180 sample->addr, 213 sample->addr,
181 symbol_conf.field_sep, 214 symbol_conf.field_sep,
182 sample->weight, 215 sample->weight,
183 symbol_conf.field_sep, 216 symbol_conf.field_sep,
184 sample->data_src, 217 sample->data_src,
185 symbol_conf.field_sep, 218 symbol_conf.field_sep,
186 al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???", 219 al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???",
187 al.sym ? al.sym->name : "???"); 220 al.sym ? al.sym->name : "???");
221 }
188out_put: 222out_put:
189 addr_location__put(&al); 223 addr_location__put(&al);
190 return 0; 224 return 0;
@@ -224,7 +258,10 @@ static int report_raw_events(struct perf_mem *mem)
224 if (ret < 0) 258 if (ret < 0)
225 goto out_delete; 259 goto out_delete;
226 260
227 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n"); 261 if (mem->phys_addr)
262 printf("# PID, TID, IP, ADDR, PHYS ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
263 else
264 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
228 265
229 ret = perf_session__process_events(session); 266 ret = perf_session__process_events(session);
230 267
@@ -254,9 +291,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 291 * there is no weight (cost) associated with stores, so don't print
255 * the column 292 * the column
256 */ 293 */
257 if (!(mem->operation & MEM_OPERATION_LOAD)) 294 if (!(mem->operation & MEM_OPERATION_LOAD)) {
258 rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr," 295 if (mem->phys_addr)
259 "dso_daddr,tlb,locked"; 296 rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr,"
297 "dso_daddr,tlb,locked,phys_daddr";
298 else
299 rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr,"
300 "dso_daddr,tlb,locked";
301 } else if (mem->phys_addr)
302 rep_argv[i++] = "--sort=local_weight,mem,sym,dso,symbol_daddr,"
303 "dso_daddr,snoop,tlb,locked,phys_daddr";
260 304
261 for (j = 1; j < argc; j++, i++) 305 for (j = 1; j < argc; j++, i++)
262 rep_argv[i] = argv[j]; 306 rep_argv[i] = argv[j];
@@ -373,6 +417,7 @@ int cmd_mem(int argc, const char **argv)
373 "separator for columns, no spaces will be added" 417 "separator for columns, no spaces will be added"
374 " between columns '.' is reserved."), 418 " between columns '.' is reserved."),
375 OPT_BOOLEAN('f', "force", &mem.force, "don't complain, do it"), 419 OPT_BOOLEAN('f', "force", &mem.force, "don't complain, do it"),
420 OPT_BOOLEAN('p', "phys-data", &mem.phys_addr, "Record/Report sample physical addresses"),
376 OPT_END() 421 OPT_END()
377 }; 422 };
378 const char *const mem_subcommands[] = { "record", "report", NULL }; 423 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..56f8142ff97f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -799,6 +799,13 @@ static int record__synthesize(struct record *rec, bool tail)
799 return 0; 799 return 0;
800 800
801 if (file->is_pipe) { 801 if (file->is_pipe) {
802 err = perf_event__synthesize_features(
803 tool, session, rec->evlist, process_synthesized_event);
804 if (err < 0) {
805 pr_err("Couldn't synthesize features.\n");
806 return err;
807 }
808
802 err = perf_event__synthesize_attrs(tool, session, 809 err = perf_event__synthesize_attrs(tool, session,
803 process_synthesized_event); 810 process_synthesized_event);
804 if (err < 0) { 811 if (err < 0) {
@@ -1597,6 +1604,8 @@ static struct option __record_options[] = {
1597 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1604 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1598 "per thread counts"), 1605 "per thread counts"),
1599 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 1606 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
1607 OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
1608 "Record the sample physical addresses"),
1600 OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), 1609 OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
1601 OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 1610 OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
1602 &record.opts.sample_time_set, 1611 &record.opts.sample_time_set,
@@ -1821,7 +1830,7 @@ int cmd_record(int argc, const char **argv)
1821 record.opts.tail_synthesize = true; 1830 record.opts.tail_synthesize = true;
1822 1831
1823 if (rec->evlist->nr_entries == 0 && 1832 if (rec->evlist->nr_entries == 0 &&
1824 perf_evlist__add_default(rec->evlist) < 0) { 1833 __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) {
1825 pr_err("Not enough memory for event selector list\n"); 1834 pr_err("Not enough memory for event selector list\n");
1826 goto out; 1835 goto out;
1827 } 1836 }
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 79a33eb1a10d..f9dff652dcbd 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -38,6 +38,7 @@
38#include "util/time-utils.h" 38#include "util/time-utils.h"
39#include "util/auxtrace.h" 39#include "util/auxtrace.h"
40#include "util/units.h" 40#include "util/units.h"
41#include "util/branch.h"
41 42
42#include <dlfcn.h> 43#include <dlfcn.h>
43#include <errno.h> 44#include <errno.h>
@@ -73,6 +74,7 @@ struct report {
73 u64 queue_size; 74 u64 queue_size;
74 int socket_filter; 75 int socket_filter;
75 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 76 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
77 struct branch_type_stat brtype_stat;
76}; 78};
77 79
78static int report__config(const char *var, const char *value, void *cb) 80static int report__config(const char *var, const char *value, void *cb)
@@ -113,43 +115,60 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
113 struct report *rep = arg; 115 struct report *rep = arg;
114 struct hist_entry *he = iter->he; 116 struct hist_entry *he = iter->he;
115 struct perf_evsel *evsel = iter->evsel; 117 struct perf_evsel *evsel = iter->evsel;
118 struct perf_sample *sample = iter->sample;
116 struct mem_info *mi; 119 struct mem_info *mi;
117 struct branch_info *bi; 120 struct branch_info *bi;
118 121
119 if (!ui__has_annotation()) 122 if (!ui__has_annotation())
120 return 0; 123 return 0;
121 124
122 hist__account_cycles(iter->sample->branch_stack, al, iter->sample, 125 hist__account_cycles(sample->branch_stack, al, sample,
123 rep->nonany_branch_mode); 126 rep->nonany_branch_mode);
124 127
125 if (sort__mode == SORT_MODE__BRANCH) { 128 if (sort__mode == SORT_MODE__BRANCH) {
126 bi = he->branch_info; 129 bi = he->branch_info;
127 err = addr_map_symbol__inc_samples(&bi->from, evsel->idx); 130 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel->idx);
128 if (err) 131 if (err)
129 goto out; 132 goto out;
130 133
131 err = addr_map_symbol__inc_samples(&bi->to, evsel->idx); 134 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel->idx);
132 135
133 } else if (rep->mem_mode) { 136 } else if (rep->mem_mode) {
134 mi = he->mem_info; 137 mi = he->mem_info;
135 err = addr_map_symbol__inc_samples(&mi->daddr, evsel->idx); 138 err = addr_map_symbol__inc_samples(&mi->daddr, sample, evsel->idx);
136 if (err) 139 if (err)
137 goto out; 140 goto out;
138 141
139 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 142 err = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr);
140 143
141 } else if (symbol_conf.cumulate_callchain) { 144 } else if (symbol_conf.cumulate_callchain) {
142 if (single) 145 if (single)
143 err = hist_entry__inc_addr_samples(he, evsel->idx, 146 err = hist_entry__inc_addr_samples(he, sample, evsel->idx,
144 al->addr); 147 al->addr);
145 } else { 148 } else {
146 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 149 err = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr);
147 } 150 }
148 151
149out: 152out:
150 return err; 153 return err;
151} 154}
152 155
156static int hist_iter__branch_callback(struct hist_entry_iter *iter,
157 struct addr_location *al __maybe_unused,
158 bool single __maybe_unused,
159 void *arg)
160{
161 struct hist_entry *he = iter->he;
162 struct report *rep = arg;
163 struct branch_info *bi;
164
165 bi = he->branch_info;
166 branch_type_count(&rep->brtype_stat, &bi->flags,
167 bi->from.addr, bi->to.addr);
168
169 return 0;
170}
171
153static int process_sample_event(struct perf_tool *tool, 172static int process_sample_event(struct perf_tool *tool,
154 union perf_event *event, 173 union perf_event *event,
155 struct perf_sample *sample, 174 struct perf_sample *sample,
@@ -188,6 +207,8 @@ static int process_sample_event(struct perf_tool *tool,
188 */ 207 */
189 if (!sample->branch_stack) 208 if (!sample->branch_stack)
190 goto out_put; 209 goto out_put;
210
211 iter.add_entry_cb = hist_iter__branch_callback;
191 iter.ops = &hist_iter_branch; 212 iter.ops = &hist_iter_branch;
192 } else if (rep->mem_mode) { 213 } else if (rep->mem_mode) {
193 iter.ops = &hist_iter_mem; 214 iter.ops = &hist_iter_mem;
@@ -220,7 +241,7 @@ static int process_read_event(struct perf_tool *tool,
220 const char *name = evsel ? perf_evsel__name(evsel) : "unknown"; 241 const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
221 int err = perf_read_values_add_value(&rep->show_threads_values, 242 int err = perf_read_values_add_value(&rep->show_threads_values,
222 event->read.pid, event->read.tid, 243 event->read.pid, event->read.tid,
223 event->read.id, 244 evsel->idx,
224 name, 245 name,
225 event->read.value); 246 event->read.value);
226 247
@@ -228,10 +249,6 @@ static int process_read_event(struct perf_tool *tool,
228 return err; 249 return err;
229 } 250 }
230 251
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; 252 return 0;
236} 253}
237 254
@@ -258,10 +275,11 @@ static int report__setup_sample_type(struct report *rep)
258 "'perf record' without -g?\n"); 275 "'perf record' without -g?\n");
259 return -EINVAL; 276 return -EINVAL;
260 } 277 }
261 if (symbol_conf.use_callchain) { 278 if (symbol_conf.use_callchain &&
262 ui__error("Selected -g or --branch-history but no " 279 !symbol_conf.show_branchflag_count) {
263 "callchain data. Did\n" 280 ui__error("Selected -g or --branch-history.\n"
264 "you call 'perf record' without -g?\n"); 281 "But no callchain or branch data.\n"
282 "Did you call 'perf record' without -g or -b?\n");
265 return -1; 283 return -1;
266 } 284 }
267 } else if (!callchain_param.enabled && 285 } else if (!callchain_param.enabled &&
@@ -396,7 +414,8 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
396 414
397 hists__fprintf_nr_sample_events(hists, rep, evname, stdout); 415 hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
398 hists__fprintf(hists, !quiet, 0, 0, rep->min_percent, stdout, 416 hists__fprintf(hists, !quiet, 0, 0, rep->min_percent, stdout,
399 symbol_conf.use_callchain); 417 symbol_conf.use_callchain ||
418 symbol_conf.show_branchflag_count);
400 fprintf(stdout, "\n\n"); 419 fprintf(stdout, "\n\n");
401 } 420 }
402 421
@@ -410,6 +429,9 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
410 perf_read_values_destroy(&rep->show_threads_values); 429 perf_read_values_destroy(&rep->show_threads_values);
411 } 430 }
412 431
432 if (sort__mode == SORT_MODE__BRANCH)
433 branch_type_stat_display(stdout, &rep->brtype_stat);
434
413 return 0; 435 return 0;
414} 436}
415 437
@@ -718,6 +740,7 @@ int cmd_report(int argc, const char **argv)
718 .id_index = perf_event__process_id_index, 740 .id_index = perf_event__process_id_index,
719 .auxtrace_info = perf_event__process_auxtrace_info, 741 .auxtrace_info = perf_event__process_auxtrace_info,
720 .auxtrace = perf_event__process_auxtrace, 742 .auxtrace = perf_event__process_auxtrace,
743 .feature = perf_event__process_feature,
721 .ordered_events = true, 744 .ordered_events = true,
722 .ordering_requires_timestamps = true, 745 .ordering_requires_timestamps = true,
723 }, 746 },
@@ -943,6 +966,8 @@ repeat:
943 if (has_br_stack && branch_call_mode) 966 if (has_br_stack && branch_call_mode)
944 symbol_conf.show_branchflag_count = true; 967 symbol_conf.show_branchflag_count = true;
945 968
969 memset(&report.brtype_stat, 0, sizeof(struct branch_type_stat));
970
946 /* 971 /*
947 * Branch mode is a tristate: 972 * Branch mode is a tristate:
948 * -1 means default, so decide based on the file having branch data. 973 * -1 means default, so decide based on the file having branch data.
@@ -988,6 +1013,10 @@ repeat:
988 /* Force tty output for header output and per-thread stat. */ 1013 /* Force tty output for header output and per-thread stat. */
989 if (report.header || report.header_only || report.show_threads) 1014 if (report.header || report.header_only || report.show_threads)
990 use_browser = 0; 1015 use_browser = 0;
1016 if (report.header || report.header_only)
1017 report.tool.show_feat_hdr = SHOW_FEAT_HEADER;
1018 if (report.show_full_info)
1019 report.tool.show_feat_hdr = SHOW_FEAT_HEADER_FULL_INFO;
991 1020
992 if (strcmp(input_name, "-") != 0) 1021 if (strcmp(input_name, "-") != 0)
993 setup_browser(true); 1022 setup_browser(true);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 83cdc0a61fd6..3d4c3b5e1868 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -87,6 +87,7 @@ enum perf_output_field {
87 PERF_OUTPUT_BRSTACKINSN = 1U << 23, 87 PERF_OUTPUT_BRSTACKINSN = 1U << 23,
88 PERF_OUTPUT_BRSTACKOFF = 1U << 24, 88 PERF_OUTPUT_BRSTACKOFF = 1U << 24,
89 PERF_OUTPUT_SYNTH = 1U << 25, 89 PERF_OUTPUT_SYNTH = 1U << 25,
90 PERF_OUTPUT_PHYS_ADDR = 1U << 26,
90}; 91};
91 92
92struct output_option { 93struct output_option {
@@ -119,6 +120,7 @@ struct output_option {
119 {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN}, 120 {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},
120 {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF}, 121 {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF},
121 {.str = "synth", .field = PERF_OUTPUT_SYNTH}, 122 {.str = "synth", .field = PERF_OUTPUT_SYNTH},
123 {.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR},
122}; 124};
123 125
124enum { 126enum {
@@ -175,7 +177,8 @@ static struct {
175 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 177 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
176 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | 178 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
177 PERF_OUTPUT_PERIOD | PERF_OUTPUT_ADDR | 179 PERF_OUTPUT_PERIOD | PERF_OUTPUT_ADDR |
178 PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT, 180 PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT |
181 PERF_OUTPUT_PHYS_ADDR,
179 182
180 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, 183 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
181 }, 184 },
@@ -382,6 +385,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
382 PERF_OUTPUT_IREGS)) 385 PERF_OUTPUT_IREGS))
383 return -EINVAL; 386 return -EINVAL;
384 387
388 if (PRINT_FIELD(PHYS_ADDR) &&
389 perf_evsel__check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR",
390 PERF_OUTPUT_PHYS_ADDR))
391 return -EINVAL;
392
385 return 0; 393 return 0;
386} 394}
387 395
@@ -1446,6 +1454,9 @@ static void process_event(struct perf_script *script,
1446 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT)) 1454 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
1447 print_sample_bpf_output(sample); 1455 print_sample_bpf_output(sample);
1448 print_insn(sample, attr, thread, machine); 1456 print_insn(sample, attr, thread, machine);
1457
1458 if (PRINT_FIELD(PHYS_ADDR))
1459 printf("%16" PRIx64, sample->phys_addr);
1449 printf("\n"); 1460 printf("\n");
1450} 1461}
1451 1462
@@ -2199,16 +2210,11 @@ static struct script_desc *script_desc__findnew(const char *name)
2199 2210
2200 s = script_desc__new(name); 2211 s = script_desc__new(name);
2201 if (!s) 2212 if (!s)
2202 goto out_delete_desc; 2213 return NULL;
2203 2214
2204 script_desc__add(s); 2215 script_desc__add(s);
2205 2216
2206 return s; 2217 return s;
2207
2208out_delete_desc:
2209 script_desc__delete(s);
2210
2211 return NULL;
2212} 2218}
2213 2219
2214static const char *ends_with(const char *str, const char *suffix) 2220static const char *ends_with(const char *str, const char *suffix)
@@ -2682,6 +2688,7 @@ int cmd_script(int argc, const char **argv)
2682 .attr = process_attr, 2688 .attr = process_attr,
2683 .event_update = perf_event__process_event_update, 2689 .event_update = perf_event__process_event_update,
2684 .tracing_data = perf_event__process_tracing_data, 2690 .tracing_data = perf_event__process_tracing_data,
2691 .feature = perf_event__process_feature,
2685 .build_id = perf_event__process_build_id, 2692 .build_id = perf_event__process_build_id,
2686 .id_index = perf_event__process_id_index, 2693 .id_index = perf_event__process_id_index,
2687 .auxtrace_info = perf_event__process_auxtrace_info, 2694 .auxtrace_info = perf_event__process_auxtrace_info,
@@ -2733,7 +2740,7 @@ int cmd_script(int argc, const char **argv)
2733 "Valid types: hw,sw,trace,raw,synth. " 2740 "Valid types: hw,sw,trace,raw,synth. "
2734 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 2741 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
2735 "addr,symoff,period,iregs,brstack,brstacksym,flags," 2742 "addr,symoff,period,iregs,brstack,brstacksym,flags,"
2736 "bpf-output,callindent,insn,insnlen,brstackinsn,synth", 2743 "bpf-output,callindent,insn,insnlen,brstackinsn,synth,phys_addr",
2737 parse_output_fields), 2744 parse_output_fields),
2738 OPT_BOOLEAN('a', "all-cpus", &system_wide, 2745 OPT_BOOLEAN('a', "all-cpus", &system_wide,
2739 "system-wide collection from all CPUs"), 2746 "system-wide collection from all CPUs"),
@@ -2972,10 +2979,13 @@ int cmd_script(int argc, const char **argv)
2972 return -1; 2979 return -1;
2973 2980
2974 if (header || header_only) { 2981 if (header || header_only) {
2982 script.tool.show_feat_hdr = SHOW_FEAT_HEADER;
2975 perf_session__fprintf_info(session, stdout, show_full_info); 2983 perf_session__fprintf_info(session, stdout, show_full_info);
2976 if (header_only) 2984 if (header_only)
2977 goto out_delete; 2985 goto out_delete;
2978 } 2986 }
2987 if (show_full_info)
2988 script.tool.show_feat_hdr = SHOW_FEAT_HEADER_FULL_INFO;
2979 2989
2980 if (symbol__init(&session->header.env) < 0) 2990 if (symbol__init(&session->header.env) < 0)
2981 goto out_delete; 2991 goto out_delete;
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 48ac53b199fc..69523ed55894 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -213,10 +213,20 @@ static void perf_stat__reset_stats(void)
213static int create_perf_stat_counter(struct perf_evsel *evsel) 213static int create_perf_stat_counter(struct perf_evsel *evsel)
214{ 214{
215 struct perf_event_attr *attr = &evsel->attr; 215 struct perf_event_attr *attr = &evsel->attr;
216 struct perf_evsel *leader = evsel->leader;
216 217
217 if (stat_config.scale) 218 if (stat_config.scale) {
218 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 219 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
219 PERF_FORMAT_TOTAL_TIME_RUNNING; 220 PERF_FORMAT_TOTAL_TIME_RUNNING;
221 }
222
223 /*
224 * The event is part of non trivial group, let's enable
225 * the group read (for leader) and ID retrieval for all
226 * members.
227 */
228 if (leader->nr_members > 1)
229 attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
220 230
221 attr->inherit = !no_inherit; 231 attr->inherit = !no_inherit;
222 232
@@ -333,13 +343,21 @@ static int read_counter(struct perf_evsel *counter)
333 struct perf_counts_values *count; 343 struct perf_counts_values *count;
334 344
335 count = perf_counts(counter->counts, cpu, thread); 345 count = perf_counts(counter->counts, cpu, thread);
336 if (perf_evsel__read(counter, cpu, thread, count)) { 346
347 /*
348 * The leader's group read loads data into its group members
349 * (via perf_evsel__read_counter) and sets threir count->loaded.
350 */
351 if (!count->loaded &&
352 perf_evsel__read_counter(counter, cpu, thread)) {
337 counter->counts->scaled = -1; 353 counter->counts->scaled = -1;
338 perf_counts(counter->counts, cpu, thread)->ena = 0; 354 perf_counts(counter->counts, cpu, thread)->ena = 0;
339 perf_counts(counter->counts, cpu, thread)->run = 0; 355 perf_counts(counter->counts, cpu, thread)->run = 0;
340 return -1; 356 return -1;
341 } 357 }
342 358
359 count->loaded = false;
360
343 if (STAT_RECORD) { 361 if (STAT_RECORD) {
344 if (perf_evsel__write_stat_event(counter, cpu, thread, count)) { 362 if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
345 pr_err("failed to write stat event\n"); 363 pr_err("failed to write stat event\n");
@@ -559,6 +577,11 @@ static int store_counter_ids(struct perf_evsel *counter)
559 return __store_counter_ids(counter, cpus, threads); 577 return __store_counter_ids(counter, cpus, threads);
560} 578}
561 579
580static bool perf_evsel__should_store_id(struct perf_evsel *counter)
581{
582 return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID;
583}
584
562static int __run_perf_stat(int argc, const char **argv) 585static int __run_perf_stat(int argc, const char **argv)
563{ 586{
564 int interval = stat_config.interval; 587 int interval = stat_config.interval;
@@ -631,7 +654,8 @@ try_again:
631 if (l > unit_width) 654 if (l > unit_width)
632 unit_width = l; 655 unit_width = l;
633 656
634 if (STAT_RECORD && store_counter_ids(counter)) 657 if (perf_evsel__should_store_id(counter) &&
658 store_counter_ids(counter))
635 return -1; 659 return -1;
636 } 660 }
637 661
@@ -683,7 +707,7 @@ try_again:
683 process_interval(); 707 process_interval();
684 } 708 }
685 } 709 }
686 wait(&status); 710 waitpid(child_pid, &status, 0);
687 711
688 if (workload_exec_errno) { 712 if (workload_exec_errno) {
689 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 713 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
@@ -1233,7 +1257,7 @@ static bool collect_data(struct perf_evsel *counter,
1233 if (counter->merged_stat) 1257 if (counter->merged_stat)
1234 return false; 1258 return false;
1235 cb(counter, data, true); 1259 cb(counter, data, true);
1236 if (!no_merge) 1260 if (!no_merge && counter->auto_merge_stats)
1237 collect_all_aliases(counter, cb, data); 1261 collect_all_aliases(counter, cb, data);
1238 return true; 1262 return true;
1239} 1263}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 6052376634c0..ee954bde7e3e 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));
@@ -1205,6 +1220,7 @@ int cmd_top(int argc, const char **argv)
1205 "Show raw trace event output (do not use print fmt or plugins)"), 1220 "Show raw trace event output (do not use print fmt or plugins)"),
1206 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy, 1221 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
1207 "Show entries in a hierarchy"), 1222 "Show entries in a hierarchy"),
1223 OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"),
1208 OPT_END() 1224 OPT_END()
1209 }; 1225 };
1210 const char * const top_usage[] = { 1226 const char * const top_usage[] = {
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 4b2a5d298197..771ddab94bb0 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,219 @@ 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 = "arch_prctl", .alias = "prctl", },
587 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), }, 582 { .name = "bpf",
583 .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, },
588 { .name = "brk", .hexret = true, 584 { .name = "brk", .hexret = true,
589 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, 585 .arg = { [0] = { .scnprintf = SCA_HEX, /* brk */ }, }, },
590 { .name = "chdir", .errmsg = true, }, 586 { .name = "clock_gettime",
591 { .name = "chmod", .errmsg = true, }, 587 .arg = { [0] = STRARRAY(clk_id, clockid), }, },
592 { .name = "chroot", .errmsg = true, }, 588 { .name = "clone", .errpid = true, .nr_args = 5,
593 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, 589 .arg = { [0] = { .name = "flags", .scnprintf = SCA_CLONE_FLAGS, },
594 { .name = "clone", .errpid = true, }, 590 [1] = { .name = "child_stack", .scnprintf = SCA_HEX, },
595 { .name = "close", .errmsg = true, 591 [2] = { .name = "parent_tidptr", .scnprintf = SCA_HEX, },
596 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, 592 [3] = { .name = "child_tidptr", .scnprintf = SCA_HEX, },
597 { .name = "connect", .errmsg = true, }, 593 [4] = { .name = "tls", .scnprintf = SCA_HEX, }, }, },
598 { .name = "creat", .errmsg = true, }, 594 { .name = "close",
599 { .name = "dup", .errmsg = true, }, 595 .arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, },
600 { .name = "dup2", .errmsg = true, }, 596 { .name = "epoll_ctl",
601 { .name = "dup3", .errmsg = true, }, 597 .arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, },
602 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), }, 598 { .name = "eventfd2",
603 { .name = "eventfd2", .errmsg = true, 599 .arg = { [1] = { .scnprintf = SCA_EFD_FLAGS, /* flags */ }, }, },
604 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, 600 { .name = "fchmodat",
605 { .name = "faccessat", .errmsg = true, }, 601 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
606 { .name = "fadvise64", .errmsg = true, }, 602 { .name = "fchownat",
607 { .name = "fallocate", .errmsg = true, }, 603 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
608 { .name = "fchdir", .errmsg = true, }, 604 { .name = "fcntl",
609 { .name = "fchmod", .errmsg = true, }, 605 .arg = { [1] = { .scnprintf = SCA_FCNTL_CMD, /* cmd */
610 { .name = "fchmodat", .errmsg = true, 606 .parm = &strarrays__fcntl_cmds_arrays,
611 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 607 .show_zero = true, },
612 { .name = "fchown", .errmsg = true, }, 608 [2] = { .scnprintf = SCA_FCNTL_ARG, /* arg */ }, }, },
613 { .name = "fchownat", .errmsg = true, 609 { .name = "flock",
614 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 610 .arg = { [1] = { .scnprintf = SCA_FLOCK, /* cmd */ }, }, },
615 { .name = "fcntl", .errmsg = true, 611 { .name = "fstat", .alias = "newfstat", },
616 .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ }, 612 { .name = "fstatat", .alias = "newfstatat", },
617 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, }, 613 { .name = "futex",
618 { .name = "fdatasync", .errmsg = true, }, 614 .arg = { [1] = { .scnprintf = SCA_FUTEX_OP, /* op */ }, }, },
619 { .name = "flock", .errmsg = true, 615 { .name = "futimesat",
620 .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, }, 616 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
621 { .name = "fsetxattr", .errmsg = true, }, 617 { .name = "getitimer",
622 { .name = "fstat", .errmsg = true, .alias = "newfstat", }, 618 .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, }, 619 { .name = "getpid", .errpid = true, },
635 { .name = "getpgid", .errpid = true, }, 620 { .name = "getpgid", .errpid = true, },
636 { .name = "getppid", .errpid = true, }, 621 { .name = "getppid", .errpid = true, },
637 { .name = "getrandom", .errmsg = true, 622 { .name = "getrandom",
638 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, }, 623 .arg = { [2] = { .scnprintf = SCA_GETRANDOM_FLAGS, /* flags */ }, }, },
639 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 624 { .name = "getrlimit",
640 { .name = "getxattr", .errmsg = true, }, 625 .arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
641 { .name = "inotify_add_watch", .errmsg = true, }, 626 { .name = "ioctl",
642 { .name = "ioctl", .errmsg = true, 627 .arg = {
643 .arg_scnprintf = {
644#if defined(__i386__) || defined(__x86_64__) 628#if defined(__i386__) || defined(__x86_64__)
645/* 629/*
646 * FIXME: Make this available to all arches. 630 * FIXME: Make this available to all arches.
647 */ 631 */
648 [1] = SCA_STRHEXARRAY, /* cmd */ 632 [1] = { .scnprintf = SCA_IOCTL_CMD, /* cmd */ },
649 [2] = SCA_HEX, /* arg */ }, 633 [2] = { .scnprintf = SCA_HEX, /* arg */ }, }, },
650 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
651#else 634#else
652 [2] = SCA_HEX, /* arg */ }, }, 635 [2] = { .scnprintf = SCA_HEX, /* arg */ }, }, },
653#endif 636#endif
654 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), }, 637 { .name = "keyctl",
655 { .name = "kill", .errmsg = true, 638 .arg = { [0] = STRARRAY(option, keyctl_options), }, },
656 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 639 { .name = "kill",
657 { .name = "lchown", .errmsg = true, }, 640 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
658 { .name = "lgetxattr", .errmsg = true, }, 641 { .name = "linkat",
659 { .name = "linkat", .errmsg = true, 642 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
660 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 643 { .name = "lseek",
661 { .name = "listxattr", .errmsg = true, }, 644 .arg = { [2] = STRARRAY(whence, whences), }, },
662 { .name = "llistxattr", .errmsg = true, }, 645 { .name = "lstat", .alias = "newlstat", },
663 { .name = "lremovexattr", .errmsg = true, }, 646 { .name = "madvise",
664 { .name = "lseek", .errmsg = true, 647 .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
665 .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ }, 648 [2] = { .scnprintf = SCA_MADV_BHV, /* behavior */ }, }, },
666 .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, 649 { .name = "mkdirat",
667 { .name = "lsetxattr", .errmsg = true, }, 650 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
668 { .name = "lstat", .errmsg = true, .alias = "newlstat", }, 651 { .name = "mknodat",
669 { .name = "lsxattr", .errmsg = true, }, 652 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
670 { .name = "madvise", .errmsg = true, 653 { .name = "mlock",
671 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 654 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
672 [2] = SCA_MADV_BHV, /* behavior */ }, }, 655 { .name = "mlockall",
673 { .name = "mkdir", .errmsg = true, }, 656 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
674 { .name = "mkdirat", .errmsg = true,
675 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
676 { .name = "mknod", .errmsg = true, },
677 { .name = "mknodat", .errmsg = true,
678 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
679 { .name = "mlock", .errmsg = true,
680 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
681 { .name = "mlockall", .errmsg = true,
682 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
683 { .name = "mmap", .hexret = true, 657 { .name = "mmap", .hexret = true,
684/* The standard mmap maps to old_mmap on s390x */ 658/* The standard mmap maps to old_mmap on s390x */
685#if defined(__s390x__) 659#if defined(__s390x__)
686 .alias = "old_mmap", 660 .alias = "old_mmap",
687#endif 661#endif
688 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 662 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
689 [2] = SCA_MMAP_PROT, /* prot */ 663 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
690 [3] = SCA_MMAP_FLAGS, /* flags */ }, }, 664 [3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, },
691 { .name = "mprotect", .errmsg = true, 665 { .name = "mprotect",
692 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 666 .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
693 [2] = SCA_MMAP_PROT, /* prot */ }, }, 667 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, },
694 { .name = "mq_unlink", .errmsg = true, 668 { .name = "mq_unlink",
695 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, }, 669 .arg = { [0] = { .scnprintf = SCA_FILENAME, /* u_name */ }, }, },
696 { .name = "mremap", .hexret = true, 670 { .name = "mremap", .hexret = true,
697 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 671 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
698 [3] = SCA_MREMAP_FLAGS, /* flags */ 672 [3] = { .scnprintf = SCA_MREMAP_FLAGS, /* flags */ },
699 [4] = SCA_HEX, /* new_addr */ }, }, 673 [4] = { .scnprintf = SCA_HEX, /* new_addr */ }, }, },
700 { .name = "munlock", .errmsg = true, 674 { .name = "munlock",
701 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 675 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
702 { .name = "munmap", .errmsg = true, 676 { .name = "munmap",
703 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 677 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
704 { .name = "name_to_handle_at", .errmsg = true, 678 { .name = "name_to_handle_at",
705 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 679 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
706 { .name = "newfstatat", .errmsg = true, 680 { .name = "newfstatat",
707 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 681 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
708 { .name = "open", .errmsg = true, 682 { .name = "open",
709 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, }, 683 .arg = { [1] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
710 { .name = "open_by_handle_at", .errmsg = true, 684 { .name = "open_by_handle_at",
711 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 685 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
712 [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 686 [2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
713 { .name = "openat", .errmsg = true, 687 { .name = "openat",
714 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 688 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
715 [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 689 [2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
716 { .name = "perf_event_open", .errmsg = true, 690 { .name = "perf_event_open",
717 .arg_scnprintf = { [2] = SCA_INT, /* cpu */ 691 .arg = { [2] = { .scnprintf = SCA_INT, /* cpu */ },
718 [3] = SCA_FD, /* group_fd */ 692 [3] = { .scnprintf = SCA_FD, /* group_fd */ },
719 [4] = SCA_PERF_FLAGS, /* flags */ }, }, 693 [4] = { .scnprintf = SCA_PERF_FLAGS, /* flags */ }, }, },
720 { .name = "pipe2", .errmsg = true, 694 { .name = "pipe2",
721 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, }, 695 .arg = { [1] = { .scnprintf = SCA_PIPE_FLAGS, /* flags */ }, }, },
722 { .name = "poll", .errmsg = true, .timeout = true, }, 696 { .name = "pkey_alloc",
723 { .name = "ppoll", .errmsg = true, .timeout = true, }, 697 .arg = { [1] = { .scnprintf = SCA_PKEY_ALLOC_ACCESS_RIGHTS, /* access_rights */ }, }, },
724 { .name = "pread", .errmsg = true, .alias = "pread64", }, 698 { .name = "pkey_free",
725 { .name = "preadv", .errmsg = true, .alias = "pread", }, 699 .arg = { [0] = { .scnprintf = SCA_INT, /* key */ }, }, },
726 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), }, 700 { .name = "pkey_mprotect",
727 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", }, 701 .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
728 { .name = "pwritev", .errmsg = true, }, 702 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
729 { .name = "read", .errmsg = true, }, 703 [3] = { .scnprintf = SCA_INT, /* pkey */ }, }, },
730 { .name = "readlink", .errmsg = true, }, 704 { .name = "poll", .timeout = true, },
731 { .name = "readlinkat", .errmsg = true, 705 { .name = "ppoll", .timeout = true, },
732 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 706 { .name = "pread", .alias = "pread64", },
733 { .name = "readv", .errmsg = true, }, 707 { .name = "preadv", .alias = "pread", },
734 { .name = "recvfrom", .errmsg = true, 708 { .name = "prlimit64",
735 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 709 .arg = { [1] = STRARRAY(resource, rlimit_resources), }, },
736 { .name = "recvmmsg", .errmsg = true, 710 { .name = "pwrite", .alias = "pwrite64", },
737 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 711 { .name = "readlinkat",
738 { .name = "recvmsg", .errmsg = true, 712 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
739 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, 713 { .name = "recvfrom",
740 { .name = "removexattr", .errmsg = true, }, 714 .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
741 { .name = "renameat", .errmsg = true, 715 { .name = "recvmmsg",
742 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 716 .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
743 { .name = "rmdir", .errmsg = true, }, 717 { .name = "recvmsg",
744 { .name = "rt_sigaction", .errmsg = true, 718 .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
745 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, 719 { .name = "renameat",
746 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), }, 720 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
747 { .name = "rt_sigqueueinfo", .errmsg = true, 721 { .name = "rt_sigaction",
748 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 722 .arg = { [0] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
749 { .name = "rt_tgsigqueueinfo", .errmsg = true, 723 { .name = "rt_sigprocmask",
750 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 724 .arg = { [0] = STRARRAY(how, sighow), }, },
751 { .name = "sched_getattr", .errmsg = true, }, 725 { .name = "rt_sigqueueinfo",
752 { .name = "sched_setattr", .errmsg = true, }, 726 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
753 { .name = "sched_setscheduler", .errmsg = true, 727 { .name = "rt_tgsigqueueinfo",
754 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, }, 728 .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
755 { .name = "seccomp", .errmsg = true, 729 { .name = "sched_setscheduler",
756 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */ 730 .arg = { [1] = { .scnprintf = SCA_SCHED_POLICY, /* policy */ }, }, },
757 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, }, 731 { .name = "seccomp",
758 { .name = "select", .errmsg = true, .timeout = true, }, 732 .arg = { [0] = { .scnprintf = SCA_SECCOMP_OP, /* op */ },
759 { .name = "sendmmsg", .errmsg = true, 733 [1] = { .scnprintf = SCA_SECCOMP_FLAGS, /* flags */ }, }, },
760 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 734 { .name = "select", .timeout = true, },
761 { .name = "sendmsg", .errmsg = true, 735 { .name = "sendmmsg",
762 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, 736 .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
763 { .name = "sendto", .errmsg = true, 737 { .name = "sendmsg",
764 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 738 .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
739 { .name = "sendto",
740 .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
765 { .name = "set_tid_address", .errpid = true, }, 741 { .name = "set_tid_address", .errpid = true, },
766 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, 742 { .name = "setitimer",
767 { .name = "setpgid", .errmsg = true, }, 743 .arg = { [0] = STRARRAY(which, itimers), }, },
768 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 744 { .name = "setrlimit",
769 { .name = "setxattr", .errmsg = true, }, 745 .arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
770 { .name = "shutdown", .errmsg = true, }, 746 { .name = "socket",
771 { .name = "socket", .errmsg = true, 747 .arg = { [0] = STRARRAY(family, socket_families),
772 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ 748 [1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, },
773 [1] = SCA_SK_TYPE, /* type */ }, 749 { .name = "socketpair",
774 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, 750 .arg = { [0] = STRARRAY(family, socket_families),
775 { .name = "socketpair", .errmsg = true, 751 [1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, },
776 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ 752 { .name = "stat", .alias = "newstat", },
777 [1] = SCA_SK_TYPE, /* type */ }, 753 { .name = "statx",
778 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, 754 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fdat */ },
779 { .name = "stat", .errmsg = true, .alias = "newstat", }, 755 [2] = { .scnprintf = SCA_STATX_FLAGS, /* flags */ } ,
780 { .name = "statfs", .errmsg = true, }, 756 [3] = { .scnprintf = SCA_STATX_MASK, /* mask */ }, }, },
781 { .name = "statx", .errmsg = true, 757 { .name = "swapoff",
782 .arg_scnprintf = { [0] = SCA_FDAT, /* flags */ 758 .arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, },
783 [2] = SCA_STATX_FLAGS, /* flags */ 759 { .name = "swapon",
784 [3] = SCA_STATX_MASK, /* mask */ }, }, 760 .arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, },
785 { .name = "swapoff", .errmsg = true, 761 { .name = "symlinkat",
786 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, 762 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
787 { .name = "swapon", .errmsg = true, 763 { .name = "tgkill",
788 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, 764 .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
789 { .name = "symlinkat", .errmsg = true, 765 { .name = "tkill",
790 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 766 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
791 { .name = "tgkill", .errmsg = true, 767 { .name = "uname", .alias = "newuname", },
792 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 768 { .name = "unlinkat",
793 { .name = "tkill", .errmsg = true, 769 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
794 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 770 { .name = "utimensat",
795 { .name = "truncate", .errmsg = true, }, 771 .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, 772 { .name = "wait4", .errpid = true,
805 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, }, 773 .arg = { [2] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, },
806 { .name = "waitid", .errpid = true, 774 { .name = "waitid", .errpid = true,
807 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, }, 775 .arg = { [3] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, },
808 { .name = "write", .errmsg = true, },
809 { .name = "writev", .errmsg = true, },
810}; 776};
811 777
812static int syscall_fmt__cmp(const void *name, const void *fmtp) 778static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -828,8 +794,7 @@ struct syscall {
828 const char *name; 794 const char *name;
829 bool is_exit; 795 bool is_exit;
830 struct syscall_fmt *fmt; 796 struct syscall_fmt *fmt;
831 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg); 797 struct syscall_arg_fmt *arg_fmt;
832 void **arg_parm;
833}; 798};
834 799
835/* 800/*
@@ -859,6 +824,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 824 * filename.ptr: The filename char pointer that will be vfs_getname'd
860 * filename.entry_str_pos: Where to insert the string translated from 825 * filename.entry_str_pos: Where to insert the string translated from
861 * filename.ptr by the vfs_getname tracepoint/kprobe. 826 * filename.ptr by the vfs_getname tracepoint/kprobe.
827 * ret_scnprintf: syscall args may set this to a different syscall return
828 * formatter, for instance, fcntl may return fds, file flags, etc.
862 */ 829 */
863struct thread_trace { 830struct thread_trace {
864 u64 entry_time; 831 u64 entry_time;
@@ -867,6 +834,7 @@ struct thread_trace {
867 unsigned long pfmaj, pfmin; 834 unsigned long pfmaj, pfmin;
868 char *entry_str; 835 char *entry_str;
869 double runtime_ms; 836 double runtime_ms;
837 size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
870 struct { 838 struct {
871 unsigned long ptr; 839 unsigned long ptr;
872 short int entry_str_pos; 840 short int entry_str_pos;
@@ -917,6 +885,15 @@ fail:
917 return NULL; 885 return NULL;
918} 886}
919 887
888
889void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
890 size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg))
891{
892 struct thread_trace *ttrace = thread__priv(arg->thread);
893
894 ttrace->ret_scnprintf = ret_scnprintf;
895}
896
920#define TRACE_PFMAJ (1 << 0) 897#define TRACE_PFMAJ (1 << 0)
921#define TRACE_PFMIN (1 << 1) 898#define TRACE_PFMIN (1 << 1)
922 899
@@ -996,8 +973,7 @@ static const char *thread__fd_path(struct thread *thread, int fd,
996 return ttrace->paths.table[fd]; 973 return ttrace->paths.table[fd];
997} 974}
998 975
999static size_t syscall_arg__scnprintf_fd(char *bf, size_t size, 976size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg)
1000 struct syscall_arg *arg)
1001{ 977{
1002 int fd = arg->val; 978 int fd = arg->val;
1003 size_t printed = scnprintf(bf, size, "%d", fd); 979 size_t printed = scnprintf(bf, size, "%d", fd);
@@ -1162,32 +1138,46 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1162 return err; 1138 return err;
1163} 1139}
1164 1140
1141static int syscall__alloc_arg_fmts(struct syscall *sc, int nr_args)
1142{
1143 int idx;
1144
1145 if (nr_args == 6 && sc->fmt && sc->fmt->nr_args != 0)
1146 nr_args = sc->fmt->nr_args;
1147
1148 sc->arg_fmt = calloc(nr_args, sizeof(*sc->arg_fmt));
1149 if (sc->arg_fmt == NULL)
1150 return -1;
1151
1152 for (idx = 0; idx < nr_args; ++idx) {
1153 if (sc->fmt)
1154 sc->arg_fmt[idx] = sc->fmt->arg[idx];
1155 }
1156
1157 sc->nr_args = nr_args;
1158 return 0;
1159}
1160
1165static int syscall__set_arg_fmts(struct syscall *sc) 1161static int syscall__set_arg_fmts(struct syscall *sc)
1166{ 1162{
1167 struct format_field *field; 1163 struct format_field *field;
1168 int idx = 0, len; 1164 int idx = 0, len;
1169 1165
1170 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *)); 1166 for (field = sc->args; field; field = field->next, ++idx) {
1171 if (sc->arg_scnprintf == NULL) 1167 if (sc->fmt && sc->fmt->arg[idx].scnprintf)
1172 return -1; 1168 continue;
1173
1174 if (sc->fmt)
1175 sc->arg_parm = sc->fmt->arg_parm;
1176 1169
1177 for (field = sc->args; field; field = field->next) { 1170 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 || 1171 (strcmp(field->name, "filename") == 0 ||
1182 strcmp(field->name, "path") == 0 || 1172 strcmp(field->name, "path") == 0 ||
1183 strcmp(field->name, "pathname") == 0)) 1173 strcmp(field->name, "pathname") == 0))
1184 sc->arg_scnprintf[idx] = SCA_FILENAME; 1174 sc->arg_fmt[idx].scnprintf = SCA_FILENAME;
1185 else if (field->flags & FIELD_IS_POINTER) 1175 else if (field->flags & FIELD_IS_POINTER)
1186 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex; 1176 sc->arg_fmt[idx].scnprintf = syscall_arg__scnprintf_hex;
1187 else if (strcmp(field->type, "pid_t") == 0) 1177 else if (strcmp(field->type, "pid_t") == 0)
1188 sc->arg_scnprintf[idx] = SCA_PID; 1178 sc->arg_fmt[idx].scnprintf = SCA_PID;
1189 else if (strcmp(field->type, "umode_t") == 0) 1179 else if (strcmp(field->type, "umode_t") == 0)
1190 sc->arg_scnprintf[idx] = SCA_MODE_T; 1180 sc->arg_fmt[idx].scnprintf = SCA_MODE_T;
1191 else if ((strcmp(field->type, "int") == 0 || 1181 else if ((strcmp(field->type, "int") == 0 ||
1192 strcmp(field->type, "unsigned int") == 0 || 1182 strcmp(field->type, "unsigned int") == 0 ||
1193 strcmp(field->type, "long") == 0) && 1183 strcmp(field->type, "long") == 0) &&
@@ -1200,9 +1190,8 @@ static int syscall__set_arg_fmts(struct syscall *sc)
1200 * 23 unsigned int 1190 * 23 unsigned int
1201 * 7 unsigned long 1191 * 7 unsigned long
1202 */ 1192 */
1203 sc->arg_scnprintf[idx] = SCA_FD; 1193 sc->arg_fmt[idx].scnprintf = SCA_FD;
1204 } 1194 }
1205 ++idx;
1206 } 1195 }
1207 1196
1208 return 0; 1197 return 0;
@@ -1247,11 +1236,13 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1247 sc->tp_format = trace_event__tp_format("syscalls", tp_name); 1236 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
1248 } 1237 }
1249 1238
1239 if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ? 6 : sc->tp_format->format.nr_fields))
1240 return -1;
1241
1250 if (IS_ERR(sc->tp_format)) 1242 if (IS_ERR(sc->tp_format))
1251 return -1; 1243 return -1;
1252 1244
1253 sc->args = sc->tp_format->format.fields; 1245 sc->args = sc->tp_format->format.fields;
1254 sc->nr_args = sc->tp_format->format.nr_fields;
1255 /* 1246 /*
1256 * We need to check and discard the first variable '__syscall_nr' 1247 * We need to check and discard the first variable '__syscall_nr'
1257 * or 'nr' that mean the syscall number. It is needless here. 1248 * or 'nr' that mean the syscall number. It is needless here.
@@ -1270,6 +1261,7 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1270static int trace__validate_ev_qualifier(struct trace *trace) 1261static int trace__validate_ev_qualifier(struct trace *trace)
1271{ 1262{
1272 int err = 0, i; 1263 int err = 0, i;
1264 size_t nr_allocated;
1273 struct str_node *pos; 1265 struct str_node *pos;
1274 1266
1275 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier); 1267 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
@@ -1283,13 +1275,18 @@ static int trace__validate_ev_qualifier(struct trace *trace)
1283 goto out; 1275 goto out;
1284 } 1276 }
1285 1277
1278 nr_allocated = trace->ev_qualifier_ids.nr;
1286 i = 0; 1279 i = 0;
1287 1280
1288 strlist__for_each_entry(pos, trace->ev_qualifier) { 1281 strlist__for_each_entry(pos, trace->ev_qualifier) {
1289 const char *sc = pos->s; 1282 const char *sc = pos->s;
1290 int id = syscalltbl__id(trace->sctbl, sc); 1283 int id = syscalltbl__id(trace->sctbl, sc), match_next = -1;
1291 1284
1292 if (id < 0) { 1285 if (id < 0) {
1286 id = syscalltbl__strglobmatch_first(trace->sctbl, sc, &match_next);
1287 if (id >= 0)
1288 goto matches;
1289
1293 if (err == 0) { 1290 if (err == 0) {
1294 fputs("Error:\tInvalid syscall ", trace->output); 1291 fputs("Error:\tInvalid syscall ", trace->output);
1295 err = -EINVAL; 1292 err = -EINVAL;
@@ -1299,13 +1296,37 @@ static int trace__validate_ev_qualifier(struct trace *trace)
1299 1296
1300 fputs(sc, trace->output); 1297 fputs(sc, trace->output);
1301 } 1298 }
1302 1299matches:
1303 trace->ev_qualifier_ids.entries[i++] = id; 1300 trace->ev_qualifier_ids.entries[i++] = id;
1301 if (match_next == -1)
1302 continue;
1303
1304 while (1) {
1305 id = syscalltbl__strglobmatch_next(trace->sctbl, sc, &match_next);
1306 if (id < 0)
1307 break;
1308 if (nr_allocated == trace->ev_qualifier_ids.nr) {
1309 void *entries;
1310
1311 nr_allocated += 8;
1312 entries = realloc(trace->ev_qualifier_ids.entries,
1313 nr_allocated * sizeof(trace->ev_qualifier_ids.entries[0]));
1314 if (entries == NULL) {
1315 err = -ENOMEM;
1316 fputs("\nError:\t Not enough memory for parsing\n", trace->output);
1317 goto out_free;
1318 }
1319 trace->ev_qualifier_ids.entries = entries;
1320 }
1321 trace->ev_qualifier_ids.nr++;
1322 trace->ev_qualifier_ids.entries[i++] = id;
1323 }
1304 } 1324 }
1305 1325
1306 if (err < 0) { 1326 if (err < 0) {
1307 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'" 1327 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1308 "\nHint:\tand: 'man syscalls'\n", trace->output); 1328 "\nHint:\tand: 'man syscalls'\n", trace->output);
1329out_free:
1309 zfree(&trace->ev_qualifier_ids.entries); 1330 zfree(&trace->ev_qualifier_ids.entries);
1310 trace->ev_qualifier_ids.nr = 0; 1331 trace->ev_qualifier_ids.nr = 0;
1311 } 1332 }
@@ -1321,33 +1342,68 @@ out:
1321 * variable to read it. Most notably this avoids extended load instructions 1342 * variable to read it. Most notably this avoids extended load instructions
1322 * on unaligned addresses 1343 * on unaligned addresses
1323 */ 1344 */
1345unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx)
1346{
1347 unsigned long val;
1348 unsigned char *p = arg->args + sizeof(unsigned long) * idx;
1349
1350 memcpy(&val, p, sizeof(val));
1351 return val;
1352}
1353
1354static size_t syscall__scnprintf_name(struct syscall *sc, char *bf, size_t size,
1355 struct syscall_arg *arg)
1356{
1357 if (sc->arg_fmt && sc->arg_fmt[arg->idx].name)
1358 return scnprintf(bf, size, "%s: ", sc->arg_fmt[arg->idx].name);
1359
1360 return scnprintf(bf, size, "arg%d: ", arg->idx);
1361}
1362
1363static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size,
1364 struct syscall_arg *arg, unsigned long val)
1365{
1366 if (sc->arg_fmt && sc->arg_fmt[arg->idx].scnprintf) {
1367 arg->val = val;
1368 if (sc->arg_fmt[arg->idx].parm)
1369 arg->parm = sc->arg_fmt[arg->idx].parm;
1370 return sc->arg_fmt[arg->idx].scnprintf(bf, size, arg);
1371 }
1372 return scnprintf(bf, size, "%ld", val);
1373}
1324 1374
1325static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, 1375static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1326 unsigned char *args, struct trace *trace, 1376 unsigned char *args, struct trace *trace,
1327 struct thread *thread) 1377 struct thread *thread)
1328{ 1378{
1329 size_t printed = 0; 1379 size_t printed = 0;
1330 unsigned char *p;
1331 unsigned long val; 1380 unsigned long val;
1381 u8 bit = 1;
1382 struct syscall_arg arg = {
1383 .args = args,
1384 .idx = 0,
1385 .mask = 0,
1386 .trace = trace,
1387 .thread = thread,
1388 };
1389 struct thread_trace *ttrace = thread__priv(thread);
1390
1391 /*
1392 * Things like fcntl will set this in its 'cmd' formatter to pick the
1393 * right formatter for the return value (an fd? file flags?), which is
1394 * not needed for syscalls that always return a given type, say an fd.
1395 */
1396 ttrace->ret_scnprintf = NULL;
1332 1397
1333 if (sc->args != NULL) { 1398 if (sc->args != NULL) {
1334 struct format_field *field; 1399 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 1400
1343 for (field = sc->args; field; 1401 for (field = sc->args; field;
1344 field = field->next, ++arg.idx, bit <<= 1) { 1402 field = field->next, ++arg.idx, bit <<= 1) {
1345 if (arg.mask & bit) 1403 if (arg.mask & bit)
1346 continue; 1404 continue;
1347 1405
1348 /* special care for unaligned accesses */ 1406 val = syscall_arg__val(&arg, arg.idx);
1349 p = args + sizeof(unsigned long) * arg.idx;
1350 memcpy(&val, p, sizeof(val));
1351 1407
1352 /* 1408 /*
1353 * Suppress this argument if its value is zero and 1409 * Suppress this argument if its value is zero and
@@ -1355,23 +1411,16 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1355 * strarray for it. 1411 * strarray for it.
1356 */ 1412 */
1357 if (val == 0 && 1413 if (val == 0 &&
1358 !(sc->arg_scnprintf && 1414 !(sc->arg_fmt &&
1359 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY && 1415 (sc->arg_fmt[arg.idx].show_zero ||
1360 sc->arg_parm[arg.idx])) 1416 sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAY ||
1417 sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAYS) &&
1418 sc->arg_fmt[arg.idx].parm))
1361 continue; 1419 continue;
1362 1420
1363 printed += scnprintf(bf + printed, size - printed, 1421 printed += scnprintf(bf + printed, size - printed,
1364 "%s%s: ", printed ? ", " : "", field->name); 1422 "%s%s: ", printed ? ", " : "", field->name);
1365 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) { 1423 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 } 1424 }
1376 } else if (IS_ERR(sc->tp_format)) { 1425 } else if (IS_ERR(sc->tp_format)) {
1377 /* 1426 /*
@@ -1379,16 +1428,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 1428 * 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. 1429 * print the raw args when we didn't manage to read it.
1381 */ 1430 */
1382 int i = 0; 1431 while (arg.idx < sc->nr_args) {
1383 1432 if (arg.mask & bit)
1384 while (i < 6) { 1433 goto next_arg;
1385 /* special care for unaligned accesses */ 1434 val = syscall_arg__val(&arg, arg.idx);
1386 p = args + sizeof(unsigned long) * i; 1435 if (printed)
1387 memcpy(&val, p, sizeof(val)); 1436 printed += scnprintf(bf + printed, size - printed, ", ");
1388 printed += scnprintf(bf + printed, size - printed, 1437 printed += syscall__scnprintf_name(sc, bf + printed, size - printed, &arg);
1389 "%sarg%d: %ld", 1438 printed += syscall__scnprintf_val(sc, bf + printed, size - printed, &arg, val);
1390 printed ? ", " : "", i, val); 1439next_arg:
1391 ++i; 1440 ++arg.idx;
1441 bit <<= 1;
1392 } 1442 }
1393 } 1443 }
1394 1444
@@ -1635,17 +1685,31 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1635 } 1685 }
1636 1686
1637 if (sc->fmt == NULL) { 1687 if (sc->fmt == NULL) {
1688 if (ret < 0)
1689 goto errno_print;
1638signed_print: 1690signed_print:
1639 fprintf(trace->output, ") = %ld", ret); 1691 fprintf(trace->output, ") = %ld", ret);
1640 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) { 1692 } else if (ret < 0) {
1693errno_print: {
1641 char bf[STRERR_BUFSIZE]; 1694 char bf[STRERR_BUFSIZE];
1642 const char *emsg = str_error_r(-ret, bf, sizeof(bf)), 1695 const char *emsg = str_error_r(-ret, bf, sizeof(bf)),
1643 *e = audit_errno_to_name(-ret); 1696 *e = audit_errno_to_name(-ret);
1644 1697
1645 fprintf(trace->output, ") = -1 %s %s", e, emsg); 1698 fprintf(trace->output, ") = -1 %s %s", e, emsg);
1699 }
1646 } else if (ret == 0 && sc->fmt->timeout) 1700 } else if (ret == 0 && sc->fmt->timeout)
1647 fprintf(trace->output, ") = 0 Timeout"); 1701 fprintf(trace->output, ") = 0 Timeout");
1648 else if (sc->fmt->hexret) 1702 else if (ttrace->ret_scnprintf) {
1703 char bf[1024];
1704 struct syscall_arg arg = {
1705 .val = ret,
1706 .thread = thread,
1707 .trace = trace,
1708 };
1709 ttrace->ret_scnprintf(bf, sizeof(bf), &arg);
1710 ttrace->ret_scnprintf = NULL;
1711 fprintf(trace->output, ") = %s", bf);
1712 } else if (sc->fmt->hexret)
1649 fprintf(trace->output, ") = %#lx", ret); 1713 fprintf(trace->output, ") = %#lx", ret);
1650 else if (sc->fmt->errpid) { 1714 else if (sc->fmt->errpid) {
1651 struct thread *child = machine__find_thread(trace->host, ret, ret); 1715 struct thread *child = machine__find_thread(trace->host, ret, ret);
@@ -2171,6 +2235,30 @@ out_enomem:
2171 goto out; 2235 goto out;
2172} 2236}
2173 2237
2238static int trace__set_filter_loop_pids(struct trace *trace)
2239{
2240 unsigned int nr = 1;
2241 pid_t pids[32] = {
2242 getpid(),
2243 };
2244 struct thread *thread = machine__find_thread(trace->host, pids[0], pids[0]);
2245
2246 while (thread && nr < ARRAY_SIZE(pids)) {
2247 struct thread *parent = machine__find_thread(trace->host, thread->ppid, thread->ppid);
2248
2249 if (parent == NULL)
2250 break;
2251
2252 if (!strcmp(thread__comm_str(parent), "sshd")) {
2253 pids[nr++] = parent->tid;
2254 break;
2255 }
2256 thread = parent;
2257 }
2258
2259 return perf_evlist__set_filter_pids(trace->evlist, nr, pids);
2260}
2261
2174static int trace__run(struct trace *trace, int argc, const char **argv) 2262static int trace__run(struct trace *trace, int argc, const char **argv)
2175{ 2263{
2176 struct perf_evlist *evlist = trace->evlist; 2264 struct perf_evlist *evlist = trace->evlist;
@@ -2294,7 +2382,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2294 if (trace->filter_pids.nr > 0) 2382 if (trace->filter_pids.nr > 0)
2295 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries); 2383 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) 2384 else if (thread_map__pid(evlist->threads, 0) == -1)
2297 err = perf_evlist__set_filter_pid(evlist, getpid()); 2385 err = trace__set_filter_loop_pids(trace);
2298 2386
2299 if (err < 0) 2387 if (err < 0)
2300 goto out_error_mem; 2388 goto out_error_mem;
@@ -2756,7 +2844,7 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
2756 struct trace *trace = (struct trace *)opt->value; 2844 struct trace *trace = (struct trace *)opt->value;
2757 const char *s = str; 2845 const char *s = str;
2758 char *sep = NULL, *lists[2] = { NULL, NULL, }; 2846 char *sep = NULL, *lists[2] = { NULL, NULL, };
2759 int len = strlen(str), err = -1, list; 2847 int len = strlen(str) + 1, err = -1, list, idx;
2760 char *strace_groups_dir = system_path(STRACE_GROUPS_DIR); 2848 char *strace_groups_dir = system_path(STRACE_GROUPS_DIR);
2761 char group_name[PATH_MAX]; 2849 char group_name[PATH_MAX];
2762 2850
@@ -2773,7 +2861,8 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
2773 *sep = '\0'; 2861 *sep = '\0';
2774 2862
2775 list = 0; 2863 list = 0;
2776 if (syscalltbl__id(trace->sctbl, s) >= 0) { 2864 if (syscalltbl__id(trace->sctbl, s) >= 0 ||
2865 syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) {
2777 list = 1; 2866 list = 1;
2778 } else { 2867 } else {
2779 path__join(group_name, sizeof(group_name), strace_groups_dir, s); 2868 path__join(group_name, sizeof(group_name), strace_groups_dir, s);
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 83fe2202382e..932fda54b8a6 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -1,9 +1,15 @@
1#!/bin/sh 1#!/bin/sh
2 2
3HEADERS=' 3HEADERS='
4include/uapi/drm/drm.h
5include/uapi/drm/i915_drm.h
4include/uapi/linux/fcntl.h 6include/uapi/linux/fcntl.h
7include/uapi/linux/kvm.h
5include/uapi/linux/perf_event.h 8include/uapi/linux/perf_event.h
9include/uapi/linux/sched.h
6include/uapi/linux/stat.h 10include/uapi/linux/stat.h
11include/uapi/linux/vhost.h
12include/uapi/sound/asound.h
7include/linux/hash.h 13include/linux/hash.h
8include/uapi/linux/hw_breakpoint.h 14include/uapi/linux/hw_breakpoint.h
9arch/x86/include/asm/disabled-features.h 15arch/x86/include/asm/disabled-features.h
@@ -16,6 +22,7 @@ arch/x86/include/uapi/asm/perf_regs.h
16arch/x86/include/uapi/asm/kvm.h 22arch/x86/include/uapi/asm/kvm.h
17arch/x86/include/uapi/asm/kvm_perf.h 23arch/x86/include/uapi/asm/kvm_perf.h
18arch/x86/include/uapi/asm/svm.h 24arch/x86/include/uapi/asm/svm.h
25arch/x86/include/uapi/asm/unistd.h
19arch/x86/include/uapi/asm/vmx.h 26arch/x86/include/uapi/asm/vmx.h
20arch/powerpc/include/uapi/asm/kvm.h 27arch/powerpc/include/uapi/asm/kvm.h
21arch/s390/include/uapi/asm/kvm.h 28arch/s390/include/uapi/asm/kvm.h
@@ -29,12 +36,13 @@ include/asm-generic/bitops/__fls.h
29include/asm-generic/bitops/fls.h 36include/asm-generic/bitops/fls.h
30include/asm-generic/bitops/fls64.h 37include/asm-generic/bitops/fls64.h
31include/linux/coresight-pmu.h 38include/linux/coresight-pmu.h
39include/uapi/asm-generic/ioctls.h
32include/uapi/asm-generic/mman-common.h 40include/uapi/asm-generic/mman-common.h
33' 41'
34 42
35check () { 43check () {
36 file=$1 44 file=$1
37 opts= 45 opts="--ignore-blank-lines --ignore-space-change"
38 46
39 shift 47 shift
40 while [ -n "$*" ]; do 48 while [ -n "$*" ]; do
@@ -45,7 +53,7 @@ check () {
45 cmd="diff $opts ../$file ../../$file > /dev/null" 53 cmd="diff $opts ../$file ../../$file > /dev/null"
46 54
47 test -f ../../$file && 55 test -f ../../$file &&
48 eval $cmd || echo "Warning: $file differs from kernel" >&2 56 eval $cmd || echo "Warning: Kernel ABI header at 'tools/$file' differs from latest version at '$file'" >&2
49} 57}
50 58
51 59
@@ -55,7 +63,7 @@ for i in $HEADERS; do
55done 63done
56 64
57# diff with extra ignore lines 65# diff with extra ignore lines
58check arch/x86/lib/memcpy_64.S -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" 66check 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>" 67check 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>" 68check 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>" 69check include/uapi/linux/mman.h -I "^#include <\(uapi/\)*asm/mman.h>"
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h
index e4b717e9eb6c..c11f0c76e90c 100644
--- a/tools/perf/perf-sys.h
+++ b/tools/perf/perf-sys.h
@@ -9,16 +9,6 @@
9#include <linux/perf_event.h> 9#include <linux/perf_event.h>
10#include <asm/barrier.h> 10#include <asm/barrier.h>
11 11
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__ 12#ifdef __powerpc__
23#define CPUINFO_PROC {"cpu"} 13#define CPUINFO_PROC {"cpu"}
24#endif 14#endif
@@ -43,19 +33,10 @@
43#define CPUINFO_PROC {"cpu model"} 33#define CPUINFO_PROC {"cpu model"}
44#endif 34#endif
45 35
46#ifdef __ia64__
47#define cpu_relax() asm volatile ("hint @pause" ::: "memory")
48#define CPUINFO_PROC {"model name"}
49#endif
50
51#ifdef __arm__ 36#ifdef __arm__
52#define CPUINFO_PROC {"model name", "Processor"} 37#define CPUINFO_PROC {"model name", "Processor"}
53#endif 38#endif
54 39
55#ifdef __aarch64__
56#define cpu_relax() asm volatile("yield" ::: "memory")
57#endif
58
59#ifdef __mips__ 40#ifdef __mips__
60#define CPUINFO_PROC {"cpu model"} 41#define CPUINFO_PROC {"cpu model"}
61#endif 42#endif
@@ -72,13 +53,8 @@
72#define CPUINFO_PROC {"core ID"} 53#define CPUINFO_PROC {"core ID"}
73#endif 54#endif
74 55
75#ifdef __tile__ 56#ifndef CPUINFO_PROC
76#define cpu_relax() asm volatile ("mfspr zero, PASS" ::: "memory") 57#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 58#endif
83 59
84static inline int 60static inline int
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 628a5e412cb1..2f19e03c5c40 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -89,7 +89,7 @@ struct pager_config {
89static int pager_command_config(const char *var, const char *value, void *data) 89static int pager_command_config(const char *var, const char *value, void *data)
90{ 90{
91 struct pager_config *c = data; 91 struct pager_config *c = data;
92 if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd)) 92 if (strstarts(var, "pager.") && !strcmp(var + 6, c->cmd))
93 c->val = perf_config_bool(var, value); 93 c->val = perf_config_bool(var, value);
94 return 0; 94 return 0;
95} 95}
@@ -108,9 +108,9 @@ static int check_pager_config(const char *cmd)
108static int browser_command_config(const char *var, const char *value, void *data) 108static int browser_command_config(const char *var, const char *value, void *data)
109{ 109{
110 struct pager_config *c = data; 110 struct pager_config *c = data;
111 if (!prefixcmp(var, "tui.") && !strcmp(var + 4, c->cmd)) 111 if (strstarts(var, "tui.") && !strcmp(var + 4, c->cmd))
112 c->val = perf_config_bool(var, value); 112 c->val = perf_config_bool(var, value);
113 if (!prefixcmp(var, "gtk.") && !strcmp(var + 4, c->cmd)) 113 if (strstarts(var, "gtk.") && !strcmp(var + 4, c->cmd))
114 c->val = perf_config_bool(var, value) ? 2 : 0; 114 c->val = perf_config_bool(var, value) ? 2 : 0;
115 return 0; 115 return 0;
116} 116}
@@ -192,7 +192,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
192 /* 192 /*
193 * Check remaining flags. 193 * Check remaining flags.
194 */ 194 */
195 if (!prefixcmp(cmd, CMD_EXEC_PATH)) { 195 if (strstarts(cmd, CMD_EXEC_PATH)) {
196 cmd += strlen(CMD_EXEC_PATH); 196 cmd += strlen(CMD_EXEC_PATH);
197 if (*cmd == '=') 197 if (*cmd == '=')
198 set_argv_exec_path(cmd + 1); 198 set_argv_exec_path(cmd + 1);
@@ -229,7 +229,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
229 *envchanged = 1; 229 *envchanged = 1;
230 (*argv)++; 230 (*argv)++;
231 (*argc)--; 231 (*argc)--;
232 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { 232 } else if (strstarts(cmd, CMD_DEBUGFS_DIR)) {
233 tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR)); 233 tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR));
234 fprintf(stderr, "dir: %s\n", tracing_path); 234 fprintf(stderr, "dir: %s\n", tracing_path);
235 if (envchanged) 235 if (envchanged)
@@ -467,17 +467,23 @@ int main(int argc, const char **argv)
467 * - cannot execute it externally (since it would just do 467 * - cannot execute it externally (since it would just do
468 * the same thing over again) 468 * the same thing over again)
469 * 469 *
470 * So we just directly call the internal command handler, and 470 * So we just directly call the internal command handler. If that one
471 * die if that one cannot handle it. 471 * fails to handle this, then maybe we just run a renamed perf binary
472 * that contains a dash in its name. To handle this scenario, we just
473 * fall through and ignore the "xxxx" part of the command string.
472 */ 474 */
473 if (!prefixcmp(cmd, "perf-")) { 475 if (strstarts(cmd, "perf-")) {
474 cmd += 5; 476 cmd += 5;
475 argv[0] = cmd; 477 argv[0] = cmd;
476 handle_internal_command(argc, argv); 478 handle_internal_command(argc, argv);
477 fprintf(stderr, "cannot handle %s internally", cmd); 479 /*
478 goto out; 480 * If the command is handled, the above function does not
481 * return undo changes and fall through in such a case.
482 */
483 cmd -= 5;
484 argv[0] = cmd;
479 } 485 }
480 if (!prefixcmp(cmd, "trace")) { 486 if (strstarts(cmd, "trace")) {
481#ifdef HAVE_LIBAUDIT_SUPPORT 487#ifdef HAVE_LIBAUDIT_SUPPORT
482 setup_path(); 488 setup_path();
483 argv[0] = "trace"; 489 argv[0] = "trace";
@@ -495,7 +501,7 @@ int main(int argc, const char **argv)
495 commit_pager_choice(); 501 commit_pager_choice();
496 502
497 if (argc > 0) { 503 if (argc > 0) {
498 if (!prefixcmp(argv[0], "--")) 504 if (strstarts(argv[0], "--"))
499 argv[0] += 2; 505 argv[0] += 2;
500 } else { 506 } else {
501 /* The user didn't specify a command; give them help */ 507 /* The user didn't specify a command; give them help */
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 806c216a1078..dc442ba21bf6 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -7,6 +7,7 @@
7#include <linux/perf_event.h> 7#include <linux/perf_event.h>
8 8
9extern bool test_attr__enabled; 9extern bool test_attr__enabled;
10void test_attr__ready(void);
10void test_attr__init(void); 11void test_attr__init(void);
11void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu, 12void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
12 int fd, int group_fd, unsigned long flags); 13 int fd, int group_fd, unsigned long flags);
@@ -42,6 +43,7 @@ struct record_opts {
42 bool no_samples; 43 bool no_samples;
43 bool raw_samples; 44 bool raw_samples;
44 bool sample_address; 45 bool sample_address;
46 bool sample_phys_addr;
45 bool sample_weight; 47 bool sample_weight;
46 bool sample_time; 48 bool sample_time;
47 bool sample_time_set; 49 bool sample_time_set;
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/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv
index d1a12e584c1b..4ea068366c3e 100644
--- a/tools/perf/pmu-events/arch/x86/mapfile.csv
+++ b/tools/perf/pmu-events/arch/x86/mapfile.csv
@@ -34,3 +34,4 @@ GenuineIntel-6-2C,v2,westmereep-dp,core
34GenuineIntel-6-2C,v2,westmereep-dp,core 34GenuineIntel-6-2C,v2,westmereep-dp,core
35GenuineIntel-6-25,v2,westmereep-sp,core 35GenuineIntel-6-25,v2,westmereep-sp,core
36GenuineIntel-6-2F,v2,westmereex,core 36GenuineIntel-6-2F,v2,westmereex,core
37GenuineIntel-6-55,v1,skylakex,core
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/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..d51dc9ca8861 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
@@ -822,10 +824,6 @@ static int process_one_file(const char *fpath, const struct stat *sb,
822 * PMU event tables (see struct pmu_events_map). 824 * PMU event tables (see struct pmu_events_map).
823 * 825 *
824 * Write out the PMU events tables and the mapping table to pmu-event.c. 826 * 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 */ 827 */
830int main(int argc, char *argv[]) 828int main(int argc, char *argv[])
831{ 829{
@@ -836,6 +834,7 @@ int main(int argc, char *argv[])
836 const char *arch; 834 const char *arch;
837 const char *output_file; 835 const char *output_file;
838 const char *start_dirname; 836 const char *start_dirname;
837 struct stat stbuf;
839 838
840 prog = basename(argv[0]); 839 prog = basename(argv[0]);
841 if (argc < 4) { 840 if (argc < 4) {
@@ -857,11 +856,17 @@ int main(int argc, char *argv[])
857 return 2; 856 return 2;
858 } 857 }
859 858
859 sprintf(ldirname, "%s/%s", start_dirname, arch);
860
861 /* If architecture does not have any event lists, bail out */
862 if (stat(ldirname, &stbuf) < 0) {
863 pr_info("%s: Arch %s has no PMU event lists\n", prog, arch);
864 goto empty_map;
865 }
866
860 /* Include pmu-events.h first */ 867 /* Include pmu-events.h first */
861 fprintf(eventsfp, "#include \"../../pmu-events/pmu-events.h\"\n"); 868 fprintf(eventsfp, "#include \"../../pmu-events/pmu-events.h\"\n");
862 869
863 sprintf(ldirname, "%s/%s", start_dirname, arch);
864
865 /* 870 /*
866 * The mapfile allows multiple CPUids to point to the same JSON file, 871 * 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 872 * so, not sure if there is a need for symlinks within the pmu-events
@@ -878,6 +883,9 @@ int main(int argc, char *argv[])
878 if (rc && verbose) { 883 if (rc && verbose) {
879 pr_info("%s: Error walking file tree %s\n", prog, ldirname); 884 pr_info("%s: Error walking file tree %s\n", prog, ldirname);
880 goto empty_map; 885 goto empty_map;
886 } else if (rc < 0) {
887 /* Make build fail */
888 return 1;
881 } else if (rc) { 889 } else if (rc) {
882 goto empty_map; 890 goto empty_map;
883 } 891 }
@@ -892,7 +900,8 @@ int main(int argc, char *argv[])
892 900
893 if (process_mapfile(eventsfp, mapfile)) { 901 if (process_mapfile(eventsfp, mapfile)) {
894 pr_info("%s: Error processing mapfile %s\n", prog, mapfile); 902 pr_info("%s: Error processing mapfile %s\n", prog, mapfile);
895 goto empty_map; 903 /* Make build fail */
904 return 1;
896 } 905 }
897 906
898 return 0; 907 return 0;
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/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/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..c9aafed7da15 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -36,6 +36,7 @@
36#define ENV "PERF_TEST_ATTR" 36#define ENV "PERF_TEST_ATTR"
37 37
38static char *dir; 38static char *dir;
39static bool ready;
39 40
40void test_attr__init(void) 41void test_attr__init(void)
41{ 42{
@@ -67,6 +68,9 @@ static int store_event(struct perf_event_attr *attr, pid_t pid, int cpu,
67 FILE *file; 68 FILE *file;
68 char path[PATH_MAX]; 69 char path[PATH_MAX];
69 70
71 if (!ready)
72 return 0;
73
70 snprintf(path, PATH_MAX, "%s/event-%d-%llu-%d", dir, 74 snprintf(path, PATH_MAX, "%s/event-%d-%llu-%d", dir,
71 attr->type, attr->config, fd); 75 attr->type, attr->config, fd);
72 76
@@ -136,7 +140,7 @@ void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
136{ 140{
137 int errno_saved = errno; 141 int errno_saved = errno;
138 142
139 if (store_event(attr, pid, cpu, fd, group_fd, flags)) { 143 if ((fd != -1) && store_event(attr, pid, cpu, fd, group_fd, flags)) {
140 pr_err("test attr FAILED"); 144 pr_err("test attr FAILED");
141 exit(128); 145 exit(128);
142 } 146 }
@@ -144,6 +148,12 @@ void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
144 errno = errno_saved; 148 errno = errno_saved;
145} 149}
146 150
151void test_attr__ready(void)
152{
153 if (unlikely(test_attr__enabled) && !ready)
154 ready = true;
155}
156
147static int run_dir(const char *d, const char *perf) 157static int run_dir(const char *d, const char *perf)
148{ 158{
149 char v[] = "-vvvvv"; 159 char v[] = "-vvvvv";
@@ -159,7 +169,7 @@ static int run_dir(const char *d, const char *perf)
159 return system(cmd); 169 return system(cmd);
160} 170}
161 171
162int test__attr(int subtest __maybe_unused) 172int test__attr(struct test *test __maybe_unused, int subtest __maybe_unused)
163{ 173{
164 struct stat st; 174 struct stat st;
165 char path_perf[PATH_MAX]; 175 char path_perf[PATH_MAX];
diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py
index cdf21a9d0c35..6bb50e82a3e3 100644
--- a/tools/perf/tests/attr.py
+++ b/tools/perf/tests/attr.py
@@ -9,6 +9,20 @@ import logging
9import shutil 9import shutil
10import ConfigParser 10import ConfigParser
11 11
12def data_equal(a, b):
13 # Allow multiple values in assignment separated by '|'
14 a_list = a.split('|')
15 b_list = b.split('|')
16
17 for a_item in a_list:
18 for b_item in b_list:
19 if (a_item == b_item):
20 return True
21 elif (a_item == '*') or (b_item == '*'):
22 return True
23
24 return False
25
12class Fail(Exception): 26class Fail(Exception):
13 def __init__(self, test, msg): 27 def __init__(self, test, msg):
14 self.msg = msg 28 self.msg = msg
@@ -82,34 +96,25 @@ class Event(dict):
82 self.add(base) 96 self.add(base)
83 self.add(data) 97 self.add(data)
84 98
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): 99 def equal(self, other):
100 for t in Event.terms: 100 for t in Event.terms:
101 log.debug(" [%s] %s %s" % (t, self[t], other[t])); 101 log.debug(" [%s] %s %s" % (t, self[t], other[t]));
102 if not self.has_key(t) or not other.has_key(t): 102 if not self.has_key(t) or not other.has_key(t):
103 return False 103 return False
104 if not self.compare_data(self[t], other[t]): 104 if not data_equal(self[t], other[t]):
105 return False 105 return False
106 return True 106 return True
107 107
108 def optional(self):
109 if self.has_key('optional') and self['optional'] == '1':
110 return True
111 return False
112
108 def diff(self, other): 113 def diff(self, other):
109 for t in Event.terms: 114 for t in Event.terms:
110 if not self.has_key(t) or not other.has_key(t): 115 if not self.has_key(t) or not other.has_key(t):
111 continue 116 continue
112 if not self.compare_data(self[t], other[t]): 117 if not data_equal(self[t], other[t]):
113 log.warning("expected %s=%s, got %s" % (t, self[t], other[t])) 118 log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
114 119
115# Test file description needs to have following sections: 120# Test file description needs to have following sections:
@@ -218,9 +223,9 @@ class Test(object):
218 self.perf, self.command, tempdir, self.args) 223 self.perf, self.command, tempdir, self.args)
219 ret = os.WEXITSTATUS(os.system(cmd)) 224 ret = os.WEXITSTATUS(os.system(cmd))
220 225
221 log.info(" '%s' ret %d " % (cmd, ret)) 226 log.info(" '%s' ret '%s', expected '%s'" % (cmd, str(ret), str(self.ret)))
222 227
223 if ret != int(self.ret): 228 if not data_equal(str(ret), str(self.ret)):
224 raise Unsup(self) 229 raise Unsup(self)
225 230
226 def compare(self, expect, result): 231 def compare(self, expect, result):
@@ -244,9 +249,12 @@ class Test(object):
244 log.debug(" match: [%s] matches %s" % (exp_name, str(exp_list))) 249 log.debug(" match: [%s] matches %s" % (exp_name, str(exp_list)))
245 250
246 # we did not any matching event - fail 251 # we did not any matching event - fail
247 if (not exp_list): 252 if not exp_list:
248 exp_event.diff(res_event) 253 if exp_event.optional():
249 raise Fail(self, 'match failure'); 254 log.debug(" %s does not match, but is optional" % exp_name)
255 else:
256 exp_event.diff(res_event)
257 raise Fail(self, 'match failure');
250 258
251 match[exp_name] = exp_list 259 match[exp_name] = exp_list
252 260
diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record
index 7e6d74946e04..31e0b1da830b 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
@@ -25,7 +25,7 @@ inherit_stat=0
25enable_on_exec=1 25enable_on_exec=1
26task=0 26task=0
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..6e7961f6f7a5 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
diff --git a/tools/perf/tests/attr/test-record-group-sampling b/tools/perf/tests/attr/test-record-group-sampling
index 658f5d60c873..ef59afd6d635 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
diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1
index c5548d054aff..87a222d014d8 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
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..67717fe6a65d 100644
--- a/tools/perf/tests/attr/test-stat-C0
+++ b/tools/perf/tests/attr/test-stat-C0
@@ -4,6 +4,6 @@ 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
diff --git a/tools/perf/tests/attr/test-stat-default b/tools/perf/tests/attr/test-stat-default
index 19270f54c96e..e911dbd4eb47 100644
--- a/tools/perf/tests/attr/test-stat-default
+++ b/tools/perf/tests/attr/test-stat-default
@@ -38,12 +38,14 @@ config=0
38fd=6 38fd=6
39type=0 39type=0
40config=7 40config=7
41optional=1
41 42
42# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 43# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
43[event7:base-stat] 44[event7:base-stat]
44fd=7 45fd=7
45type=0 46type=0
46config=8 47config=8
48optional=1
47 49
48# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 50# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
49[event8:base-stat] 51[event8:base-stat]
diff --git a/tools/perf/tests/attr/test-stat-detailed-1 b/tools/perf/tests/attr/test-stat-detailed-1
index 51426b87153b..b39270a08e74 100644
--- a/tools/perf/tests/attr/test-stat-detailed-1
+++ b/tools/perf/tests/attr/test-stat-detailed-1
@@ -39,12 +39,14 @@ config=0
39fd=6 39fd=6
40type=0 40type=0
41config=7 41config=7
42optional=1
42 43
43# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 44# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
44[event7:base-stat] 45[event7:base-stat]
45fd=7 46fd=7
46type=0 47type=0
47config=8 48config=8
49optional=1
48 50
49# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 51# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
50[event8:base-stat] 52[event8:base-stat]
diff --git a/tools/perf/tests/attr/test-stat-detailed-2 b/tools/perf/tests/attr/test-stat-detailed-2
index 8de5acc31c27..45f8e6ea34f8 100644
--- a/tools/perf/tests/attr/test-stat-detailed-2
+++ b/tools/perf/tests/attr/test-stat-detailed-2
@@ -39,12 +39,14 @@ config=0
39fd=6 39fd=6
40type=0 40type=0
41config=7 41config=7
42optional=1
42 43
43# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 44# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
44[event7:base-stat] 45[event7:base-stat]
45fd=7 46fd=7
46type=0 47type=0
47config=8 48config=8
49optional=1
48 50
49# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 51# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
50[event8:base-stat] 52[event8:base-stat]
@@ -108,6 +110,7 @@ config=65538
108fd=15 110fd=15
109type=3 111type=3
110config=1 112config=1
113optional=1
111 114
112# PERF_TYPE_HW_CACHE, 115# PERF_TYPE_HW_CACHE,
113# PERF_COUNT_HW_CACHE_L1I << 0 | 116# PERF_COUNT_HW_CACHE_L1I << 0 |
diff --git a/tools/perf/tests/attr/test-stat-detailed-3 b/tools/perf/tests/attr/test-stat-detailed-3
index 0a1f45bf7d79..30ae0fb7a3fd 100644
--- a/tools/perf/tests/attr/test-stat-detailed-3
+++ b/tools/perf/tests/attr/test-stat-detailed-3
@@ -39,12 +39,14 @@ config=0
39fd=6 39fd=6
40type=0 40type=0
41config=7 41config=7
42optional=1
42 43
43# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 44# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
44[event7:base-stat] 45[event7:base-stat]
45fd=7 46fd=7
46type=0 47type=0
47config=8 48config=8
49optional=1
48 50
49# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 51# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
50[event8:base-stat] 52[event8:base-stat]
@@ -108,6 +110,7 @@ config=65538
108fd=15 110fd=15
109type=3 111type=3
110config=1 112config=1
113optional=1
111 114
112# PERF_TYPE_HW_CACHE, 115# PERF_TYPE_HW_CACHE,
113# PERF_COUNT_HW_CACHE_L1I << 0 | 116# PERF_COUNT_HW_CACHE_L1I << 0 |
@@ -162,6 +165,7 @@ config=65540
162fd=21 165fd=21
163type=3 166type=3
164config=512 167config=512
168optional=1
165 169
166# PERF_TYPE_HW_CACHE, 170# PERF_TYPE_HW_CACHE,
167# PERF_COUNT_HW_CACHE_L1D << 0 | 171# PERF_COUNT_HW_CACHE_L1D << 0 |
@@ -171,3 +175,4 @@ config=512
171fd=22 175fd=22
172type=3 176type=3
173config=66048 177config=66048
178optional=1
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index 50f6d7afee58..d233ad336463 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -75,7 +75,7 @@ static int do_test(struct perf_evlist *evlist, int mmap_pages,
75} 75}
76 76
77 77
78int test__backward_ring_buffer(int subtest __maybe_unused) 78int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __maybe_unused)
79{ 79{
80 int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0; 80 int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0;
81 char pid[16], sbuf[STRERR_BUFSIZE]; 81 char pid[16], sbuf[STRERR_BUFSIZE];
diff --git a/tools/perf/tests/bitmap.c b/tools/perf/tests/bitmap.c
index 9abe6c13090f..0d7c06584905 100644
--- a/tools/perf/tests/bitmap.c
+++ b/tools/perf/tests/bitmap.c
@@ -40,7 +40,7 @@ static int test_bitmap(const char *str)
40 return ret; 40 return ret;
41} 41}
42 42
43int test__bitmap_print(int subtest __maybe_unused) 43int test__bitmap_print(struct test *test __maybe_unused, int subtest __maybe_unused)
44{ 44{
45 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1")); 45 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1"));
46 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,5")); 46 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..97937e1bc53a 100644
--- a/tools/perf/tests/bp_signal.c
+++ b/tools/perf/tests/bp_signal.c
@@ -164,7 +164,7 @@ static long long bp_count(int fd)
164 return count; 164 return count;
165} 165}
166 166
167int test__bp_signal(int subtest __maybe_unused) 167int test__bp_signal(struct test *test __maybe_unused, int subtest __maybe_unused)
168{ 168{
169 struct sigaction sa; 169 struct sigaction sa;
170 long long count1, count2, count3; 170 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..61ecd8021f49 100644
--- a/tools/perf/tests/bp_signal_overflow.c
+++ b/tools/perf/tests/bp_signal_overflow.c
@@ -57,7 +57,7 @@ static long long bp_count(int fd)
57#define EXECUTIONS 10000 57#define EXECUTIONS 10000
58#define THRESHOLD 100 58#define THRESHOLD 100
59 59
60int test__bp_signal_overflow(int subtest __maybe_unused) 60int test__bp_signal_overflow(struct test *test __maybe_unused, int subtest __maybe_unused)
61{ 61{
62 struct perf_event_attr pe; 62 struct perf_event_attr pe;
63 struct sigaction sa; 63 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..377bea009163 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -6,7 +6,10 @@
6#include <errno.h> 6#include <errno.h>
7#include <unistd.h> 7#include <unistd.h>
8#include <string.h> 8#include <string.h>
9#include <sys/types.h>
10#include <dirent.h>
9#include <sys/wait.h> 11#include <sys/wait.h>
12#include <sys/stat.h>
10#include "builtin.h" 13#include "builtin.h"
11#include "hist.h" 14#include "hist.h"
12#include "intlist.h" 15#include "intlist.h"
@@ -14,8 +17,10 @@
14#include "debug.h" 17#include "debug.h"
15#include "color.h" 18#include "color.h"
16#include <subcmd/parse-options.h> 19#include <subcmd/parse-options.h>
20#include "string2.h"
17#include "symbol.h" 21#include "symbol.h"
18#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <subcmd/exec-cmd.h>
19 24
20static bool dont_fork; 25static bool dont_fork;
21 26
@@ -43,6 +48,10 @@ static struct test generic_tests[] = {
43 .func = test__basic_mmap, 48 .func = test__basic_mmap,
44 }, 49 },
45 { 50 {
51 .desc = "Test data source output",
52 .func = test__mem,
53 },
54 {
46 .desc = "Parse event definition strings", 55 .desc = "Parse event definition strings",
47 .func = test__parse_events, 56 .func = test__parse_events,
48 }, 57 },
@@ -179,7 +188,7 @@ static struct test generic_tests[] = {
179 }, 188 },
180 { 189 {
181 .desc = "Session topology", 190 .desc = "Session topology",
182 .func = test_session_topology, 191 .func = test__session_topology,
183 }, 192 },
184 { 193 {
185 .desc = "BPF filter", 194 .desc = "BPF filter",
@@ -325,7 +334,7 @@ static int run_test(struct test *test, int subtest)
325 } 334 }
326 } 335 }
327 336
328 err = test->func(subtest); 337 err = test->func(test, subtest);
329 if (!dont_fork) 338 if (!dont_fork)
330 exit(err); 339 exit(err);
331 } 340 }
@@ -383,12 +392,143 @@ static int test_and_print(struct test *t, bool force_skip, int subtest)
383 return err; 392 return err;
384} 393}
385 394
395static const char *shell_test__description(char *description, size_t size,
396 const char *path, const char *name)
397{
398 FILE *fp;
399 char filename[PATH_MAX];
400
401 path__join(filename, sizeof(filename), path, name);
402 fp = fopen(filename, "r");
403 if (!fp)
404 return NULL;
405
406 description = fgets(description, size, fp);
407 fclose(fp);
408
409 return description ? trim(description + 1) : NULL;
410}
411
412#define for_each_shell_test(dir, ent) \
413 while ((ent = readdir(dir)) != NULL) \
414 if (ent->d_type == DT_REG && ent->d_name[0] != '.')
415
416static const char *shell_tests__dir(char *path, size_t size)
417{
418 const char *devel_dirs[] = { "./tools/perf/tests", "./tests", };
419 char *exec_path;
420 unsigned int i;
421
422 for (i = 0; i < ARRAY_SIZE(devel_dirs); ++i) {
423 struct stat st;
424 if (!lstat(devel_dirs[i], &st)) {
425 scnprintf(path, size, "%s/shell", devel_dirs[i]);
426 if (!lstat(devel_dirs[i], &st))
427 return path;
428 }
429 }
430
431 /* Then installed path. */
432 exec_path = get_argv_exec_path();
433 scnprintf(path, size, "%s/tests/shell", exec_path);
434 free(exec_path);
435 return path;
436}
437
438static int shell_tests__max_desc_width(void)
439{
440 DIR *dir;
441 struct dirent *ent;
442 char path_dir[PATH_MAX];
443 const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
444 int width = 0;
445
446 if (path == NULL)
447 return -1;
448
449 dir = opendir(path);
450 if (!dir)
451 return -1;
452
453 for_each_shell_test(dir, ent) {
454 char bf[256];
455 const char *desc = shell_test__description(bf, sizeof(bf), path, ent->d_name);
456
457 if (desc) {
458 int len = strlen(desc);
459
460 if (width < len)
461 width = len;
462 }
463 }
464
465 closedir(dir);
466 return width;
467}
468
469struct shell_test {
470 const char *dir;
471 const char *file;
472};
473
474static int shell_test__run(struct test *test, int subdir __maybe_unused)
475{
476 int err;
477 char script[PATH_MAX];
478 struct shell_test *st = test->priv;
479
480 path__join(script, sizeof(script), st->dir, st->file);
481
482 err = system(script);
483 if (!err)
484 return TEST_OK;
485
486 return WEXITSTATUS(err) == 2 ? TEST_SKIP : TEST_FAIL;
487}
488
489static int run_shell_tests(int argc, const char *argv[], int i, int width)
490{
491 DIR *dir;
492 struct dirent *ent;
493 char path_dir[PATH_MAX];
494 struct shell_test st = {
495 .dir = shell_tests__dir(path_dir, sizeof(path_dir)),
496 };
497
498 if (st.dir == NULL)
499 return -1;
500
501 dir = opendir(st.dir);
502 if (!dir)
503 return -1;
504
505 for_each_shell_test(dir, ent) {
506 int curr = i++;
507 char desc[256];
508 struct test test = {
509 .desc = shell_test__description(desc, sizeof(desc), st.dir, ent->d_name),
510 .func = shell_test__run,
511 .priv = &st,
512 };
513
514 if (!perf_test__matches(&test, curr, argc, argv))
515 continue;
516
517 st.file = ent->d_name;
518 pr_info("%2d: %-*s:", i, width, test.desc);
519 test_and_print(&test, false, -1);
520 }
521
522 closedir(dir);
523 return 0;
524}
525
386static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) 526static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
387{ 527{
388 struct test *t; 528 struct test *t;
389 unsigned int j; 529 unsigned int j;
390 int i = 0; 530 int i = 0;
391 int width = 0; 531 int width = shell_tests__max_desc_width();
392 532
393 for_each_test(j, t) { 533 for_each_test(j, t) {
394 int len = strlen(t->desc); 534 int len = strlen(t->desc);
@@ -455,6 +595,37 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
455 } 595 }
456 } 596 }
457 597
598 return run_shell_tests(argc, argv, i, width);
599}
600
601static int perf_test__list_shell(int argc, const char **argv, int i)
602{
603 DIR *dir;
604 struct dirent *ent;
605 char path_dir[PATH_MAX];
606 const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
607
608 if (path == NULL)
609 return -1;
610
611 dir = opendir(path);
612 if (!dir)
613 return -1;
614
615 for_each_shell_test(dir, ent) {
616 int curr = i++;
617 char bf[256];
618 struct test t = {
619 .desc = shell_test__description(bf, sizeof(bf), path, ent->d_name),
620 };
621
622 if (!perf_test__matches(&t, curr, argc, argv))
623 continue;
624
625 pr_info("%2d: %s\n", i, t.desc);
626 }
627
628 closedir(dir);
458 return 0; 629 return 0;
459} 630}
460 631
@@ -465,12 +636,17 @@ static int perf_test__list(int argc, const char **argv)
465 int i = 0; 636 int i = 0;
466 637
467 for_each_test(j, t) { 638 for_each_test(j, t) {
468 if (argc > 1 && !strstr(t->desc, argv[1])) 639 int curr = i++;
640
641 if (!perf_test__matches(t, curr, argc, argv) ||
642 (t->is_supported && !t->is_supported()))
469 continue; 643 continue;
470 644
471 pr_info("%2d: %s\n", ++i, t->desc); 645 pr_info("%2d: %s\n", i, t->desc);
472 } 646 }
473 647
648 perf_test__list_shell(argc, argv, i);
649
474 return 0; 650 return 0;
475} 651}
476 652
@@ -498,7 +674,7 @@ int cmd_test(int argc, const char **argv)
498 674
499 argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0); 675 argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0);
500 if (argc >= 1 && !strcmp(argv[0], "list")) 676 if (argc >= 1 && !strcmp(argv[0], "list"))
501 return perf_test__list(argc, argv); 677 return perf_test__list(argc - 1, argv + 1);
502 678
503 symbol_conf.priv_size = sizeof(int); 679 symbol_conf.priv_size = sizeof(int);
504 symbol_conf.sort_by_name = true; 680 symbol_conf.sort_by_name = true;
diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
index c5bb2203f5a9..c60ec916f0f2 100644
--- a/tools/perf/tests/clang.c
+++ b/tools/perf/tests/clang.c
@@ -33,12 +33,12 @@ const char *test__clang_subtest_get_desc(int i)
33} 33}
34 34
35#ifndef HAVE_LIBCLANGLLVM_SUPPORT 35#ifndef HAVE_LIBCLANGLLVM_SUPPORT
36int test__clang(int i __maybe_unused) 36int test__clang(struct test *test __maybe_unused, int i __maybe_unused)
37{ 37{
38 return TEST_SKIP; 38 return TEST_SKIP;
39} 39}
40#else 40#else
41int test__clang(int i) 41int test__clang(struct test *test __maybe_unused, int i)
42{ 42{
43 if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table)) 43 if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
44 return TEST_FAIL; 44 return TEST_FAIL;
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 94b7c7b02bde..466a462b26d1 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -237,6 +237,11 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
237 237
238 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al); 238 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al);
239 if (!al.map || !al.map->dso) { 239 if (!al.map || !al.map->dso) {
240 if (cpumode == PERF_RECORD_MISC_HYPERVISOR) {
241 pr_debug("Hypervisor address can not be resolved - skipping\n");
242 return 0;
243 }
244
240 pr_debug("thread__find_addr_map failed\n"); 245 pr_debug("thread__find_addr_map failed\n");
241 return -1; 246 return -1;
242 } 247 }
@@ -673,7 +678,7 @@ out_err:
673 return err; 678 return err;
674} 679}
675 680
676int test__code_reading(int subtest __maybe_unused) 681int test__code_reading(struct test *test __maybe_unused, int subtest __maybe_unused)
677{ 682{
678 int ret; 683 int ret;
679 684
diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c
index 4478773cdb97..199702252270 100644
--- a/tools/perf/tests/cpumap.c
+++ b/tools/perf/tests/cpumap.c
@@ -72,7 +72,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
72} 72}
73 73
74 74
75int test__cpu_map_synthesize(int subtest __maybe_unused) 75int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __maybe_unused)
76{ 76{
77 struct cpu_map *cpus; 77 struct cpu_map *cpus;
78 78
@@ -106,7 +106,7 @@ static int cpu_map_print(const char *str)
106 return !strcmp(buf, str); 106 return !strcmp(buf, str);
107} 107}
108 108
109int test__cpu_map_print(int subtest __maybe_unused) 109int test__cpu_map_print(struct test *test __maybe_unused, int subtest __maybe_unused)
110{ 110{
111 TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1")); 111 TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1"));
112 TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1,5")); 112 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..30aead42d136 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -112,7 +112,7 @@ static int dso__data_fd(struct dso *dso, struct machine *machine)
112 return fd; 112 return fd;
113} 113}
114 114
115int test__dso_data(int subtest __maybe_unused) 115int test__dso_data(struct test *test __maybe_unused, int subtest __maybe_unused)
116{ 116{
117 struct machine machine; 117 struct machine machine;
118 struct dso *dso; 118 struct dso *dso;
@@ -247,7 +247,7 @@ static int set_fd_limit(int n)
247 return setrlimit(RLIMIT_NOFILE, &rlim); 247 return setrlimit(RLIMIT_NOFILE, &rlim);
248} 248}
249 249
250int test__dso_data_cache(int subtest __maybe_unused) 250int test__dso_data_cache(struct test *test __maybe_unused, int subtest __maybe_unused)
251{ 251{
252 struct machine machine; 252 struct machine machine;
253 long nr_end, nr = open_files_cnt(); 253 long nr_end, nr = open_files_cnt();
@@ -307,7 +307,7 @@ int test__dso_data_cache(int subtest __maybe_unused)
307 return 0; 307 return 0;
308} 308}
309 309
310int test__dso_data_reopen(int subtest __maybe_unused) 310int test__dso_data_reopen(struct test *test __maybe_unused, int subtest __maybe_unused)
311{ 311{
312 struct machine machine; 312 struct machine machine;
313 long nr_end, nr = open_files_cnt(); 313 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..9ba1d216a89f 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -6,7 +6,7 @@
6#include "debug.h" 6#include "debug.h"
7#include "machine.h" 7#include "machine.h"
8#include "event.h" 8#include "event.h"
9#include "unwind.h" 9#include "../util/unwind.h"
10#include "perf_regs.h" 10#include "perf_regs.h"
11#include "map.h" 11#include "map.h"
12#include "thread.h" 12#include "thread.h"
@@ -154,7 +154,7 @@ static noinline int krava_1(struct thread *thread)
154 return krava_2(thread); 154 return krava_2(thread);
155} 155}
156 156
157int test__dwarf_unwind(int subtest __maybe_unused) 157int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unused)
158{ 158{
159 struct machine *machine; 159 struct machine *machine;
160 struct thread *thread; 160 struct thread *thread;
diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c
index 634f20c631d8..b82b981c3259 100644
--- a/tools/perf/tests/event-times.c
+++ b/tools/perf/tests/event-times.c
@@ -213,7 +213,7 @@ out_err:
213 * and checks that enabled and running times 213 * and checks that enabled and running times
214 * match. 214 * match.
215 */ 215 */
216int test__event_times(int subtest __maybe_unused) 216int test__event_times(struct test *test __maybe_unused, int subtest __maybe_unused)
217{ 217{
218 int err, ret = 0; 218 int err, ret = 0;
219 219
diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c
index 63ecf21750eb..9484da2ec6b4 100644
--- a/tools/perf/tests/event_update.c
+++ b/tools/perf/tests/event_update.c
@@ -76,7 +76,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
76 return 0; 76 return 0;
77} 77}
78 78
79int test__event_update(int subtest __maybe_unused) 79int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unused)
80{ 80{
81 struct perf_evlist *evlist; 81 struct perf_evlist *evlist;
82 struct perf_evsel *evsel; 82 struct perf_evsel *evsel;
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c
index d2bea6f780f8..d32759b6e38a 100644
--- a/tools/perf/tests/evsel-roundtrip-name.c
+++ b/tools/perf/tests/evsel-roundtrip-name.c
@@ -97,7 +97,7 @@ out_delete_evlist:
97#define perf_evsel__name_array_test(names) \ 97#define perf_evsel__name_array_test(names) \
98 __perf_evsel__name_array_test(names, ARRAY_SIZE(names)) 98 __perf_evsel__name_array_test(names, ARRAY_SIZE(names))
99 99
100int test__perf_evsel__roundtrip_name_test(int subtest __maybe_unused) 100int test__perf_evsel__roundtrip_name_test(struct test *test __maybe_unused, int subtest __maybe_unused)
101{ 101{
102 int err = 0, ret = 0; 102 int err = 0, ret = 0;
103 103
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
index 1984b3bbfe15..5fc906d26c5c 100644
--- a/tools/perf/tests/evsel-tp-sched.c
+++ b/tools/perf/tests/evsel-tp-sched.c
@@ -32,7 +32,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
32 return ret; 32 return ret;
33} 33}
34 34
35int test__perf_evsel__tp_sched_test(int subtest __maybe_unused) 35int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtest __maybe_unused)
36{ 36{
37 struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch"); 37 struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch");
38 int ret = 0; 38 int ret = 0;
diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
index 6c6a3749aaf6..cb251bf523e7 100644
--- a/tools/perf/tests/expr.c
+++ b/tools/perf/tests/expr.c
@@ -13,7 +13,7 @@ static int test(struct parse_ctx *ctx, const char *e, double val2)
13 return 0; 13 return 0;
14} 14}
15 15
16int test__expr(int subtest __maybe_unused) 16int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused)
17{ 17{
18 const char *p; 18 const char *p;
19 const char **other; 19 const char **other;
@@ -31,6 +31,11 @@ int test__expr(int subtest __maybe_unused)
31 ret |= test(&ctx, "(BAR/2)%2", 1); 31 ret |= test(&ctx, "(BAR/2)%2", 1);
32 ret |= test(&ctx, "1 - -4", 5); 32 ret |= test(&ctx, "1 - -4", 5);
33 ret |= test(&ctx, "(FOO-1)*2 + (BAR/2)%2 - -4", 5); 33 ret |= test(&ctx, "(FOO-1)*2 + (BAR/2)%2 - -4", 5);
34 ret |= test(&ctx, "1-1 | 1", 1);
35 ret |= test(&ctx, "1-1 & 1", 0);
36 ret |= test(&ctx, "min(1,2) + 1", 2);
37 ret |= test(&ctx, "max(1,2) + 1", 3);
38 ret |= test(&ctx, "1+1 if 3*4 else 0", 2);
34 39
35 if (ret) 40 if (ret)
36 return ret; 41 return ret;
diff --git a/tools/perf/tests/fdarray.c b/tools/perf/tests/fdarray.c
index bc5982f42dc3..7d3a9e2ff897 100644
--- a/tools/perf/tests/fdarray.c
+++ b/tools/perf/tests/fdarray.c
@@ -26,7 +26,7 @@ static int fdarray__fprintf_prefix(struct fdarray *fda, const char *prefix, FILE
26 return printed + fdarray__fprintf(fda, fp); 26 return printed + fdarray__fprintf(fda, fp);
27} 27}
28 28
29int test__fdarray__filter(int subtest __maybe_unused) 29int test__fdarray__filter(struct test *test __maybe_unused, int subtest __maybe_unused)
30{ 30{
31 int nr_fds, expected_fd[2], fd, err = TEST_FAIL; 31 int nr_fds, expected_fd[2], fd, err = TEST_FAIL;
32 struct fdarray *fda = fdarray__new(5, 5); 32 struct fdarray *fda = fdarray__new(5, 5);
@@ -104,7 +104,7 @@ out:
104 return err; 104 return err;
105} 105}
106 106
107int test__fdarray__add(int subtest __maybe_unused) 107int test__fdarray__add(struct test *test __maybe_unused, int subtest __maybe_unused)
108{ 108{
109 int err = TEST_FAIL; 109 int err = TEST_FAIL;
110 struct fdarray *fda = fdarray__new(2, 2); 110 struct fdarray *fda = fdarray__new(2, 2);
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index d549a9f2c41b..8d19c0200cb7 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -687,7 +687,7 @@ out:
687 return err; 687 return err;
688} 688}
689 689
690int test__hists_cumulate(int subtest __maybe_unused) 690int test__hists_cumulate(struct test *test __maybe_unused, int subtest __maybe_unused)
691{ 691{
692 int err = TEST_FAIL; 692 int err = TEST_FAIL;
693 struct machines machines; 693 struct machines machines;
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index df9c91f49af1..755ca551b810 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -101,7 +101,7 @@ out:
101 return TEST_FAIL; 101 return TEST_FAIL;
102} 102}
103 103
104int test__hists_filter(int subtest __maybe_unused) 104int test__hists_filter(struct test *test __maybe_unused, int subtest __maybe_unused)
105{ 105{
106 int err = TEST_FAIL; 106 int err = TEST_FAIL;
107 struct machines machines; 107 struct machines machines;
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index a26cbb79e988..073c9c2856bc 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -264,7 +264,7 @@ static int validate_link(struct hists *leader, struct hists *other)
264 return __validate_link(leader, 0) || __validate_link(other, 1); 264 return __validate_link(leader, 0) || __validate_link(other, 1);
265} 265}
266 266
267int test__hists_link(int subtest __maybe_unused) 267int test__hists_link(struct test *test __maybe_unused, int subtest __maybe_unused)
268{ 268{
269 int err = -1; 269 int err = -1;
270 struct hists *hists, *first_hists; 270 struct hists *hists, *first_hists;
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index 06e5080182d3..282d62eaebe2 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -573,7 +573,7 @@ out:
573 return err; 573 return err;
574} 574}
575 575
576int test__hists_output(int subtest __maybe_unused) 576int test__hists_output(struct test *test __maybe_unused, int subtest __maybe_unused)
577{ 577{
578 int err = TEST_FAIL; 578 int err = TEST_FAIL;
579 struct machines machines; 579 struct machines machines;
diff --git a/tools/perf/tests/is_printable_array.c b/tools/perf/tests/is_printable_array.c
index a5192f6a20d7..38f765767587 100644
--- a/tools/perf/tests/is_printable_array.c
+++ b/tools/perf/tests/is_printable_array.c
@@ -4,7 +4,7 @@
4#include "debug.h" 4#include "debug.h"
5#include "print_binary.h" 5#include "print_binary.h"
6 6
7int test__is_printable_array(int subtest __maybe_unused) 7int test__is_printable_array(struct test *test __maybe_unused, int subtest __maybe_unused)
8{ 8{
9 char buf1[] = { 'k', 'r', 4, 'v', 'a', 0 }; 9 char buf1[] = { 'k', 'r', 4, 'v', 'a', 0 };
10 char buf2[] = { 'k', 'r', 'a', 'v', 4, 0 }; 10 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..739428603b71 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -49,7 +49,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 49 * 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. 50 * test passes %0 is returned, otherwise %-1 is returned.
51 */ 51 */
52int test__keep_tracking(int subtest __maybe_unused) 52int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_unused)
53{ 53{
54 struct record_opts opts = { 54 struct record_opts opts = {
55 .mmap_pages = UINT_MAX, 55 .mmap_pages = UINT_MAX,
diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c
index 6cd9e5107f77..8b9d4ba06c0e 100644
--- a/tools/perf/tests/kmod-path.c
+++ b/tools/perf/tests/kmod-path.c
@@ -50,7 +50,7 @@ static int test_is_kernel_module(const char *path, int cpumode, bool expect)
50#define M(path, c, e) \ 50#define M(path, c, e) \
51 TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e)) 51 TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e))
52 52
53int test__kmod_path__parse(int subtest __maybe_unused) 53int test__kmod_path__parse(struct test *t __maybe_unused, int subtest __maybe_unused)
54{ 54{
55 /* path alloc_name alloc_ext kmod comp name ext */ 55 /* path alloc_name alloc_ext kmod comp name ext */
56 T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL); 56 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..5187b50dbafe 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -132,7 +132,7 @@ out:
132 return ret; 132 return ret;
133} 133}
134 134
135int test__llvm(int subtest) 135int test__llvm(struct test *test __maybe_unused, int subtest)
136{ 136{
137 int ret; 137 int ret;
138 void *obj_buf = NULL; 138 void *obj_buf = NULL;
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..bc8a70ee46d8 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -22,7 +22,7 @@
22 * Then it checks if the number of syscalls reported as perf events by 22 * Then it checks if the number of syscalls reported as perf events by
23 * the kernel corresponds to the number of syscalls made. 23 * the kernel corresponds to the number of syscalls made.
24 */ 24 */
25int test__basic_mmap(int subtest __maybe_unused) 25int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unused)
26{ 26{
27 int err = -1; 27 int err = -1;
28 union perf_event *event; 28 union perf_event *event;
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c
index 6ea4d8a5d26b..f94a4196e7c9 100644
--- a/tools/perf/tests/mmap-thread-lookup.c
+++ b/tools/perf/tests/mmap-thread-lookup.c
@@ -221,7 +221,7 @@ static int mmap_events(synth_cb synth)
221 * 221 *
222 * by using all thread objects. 222 * by using all thread objects.
223 */ 223 */
224int test__mmap_thread_lookup(int subtest __maybe_unused) 224int test__mmap_thread_lookup(struct test *test __maybe_unused, int subtest __maybe_unused)
225{ 225{
226 /* perf_event__synthesize_threads synthesize */ 226 /* perf_event__synthesize_threads synthesize */
227 TEST_ASSERT_VAL("failed with sythesizing all", 227 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..9cf1c35f2ad0 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -16,7 +16,7 @@
16#include "debug.h" 16#include "debug.h"
17#include "stat.h" 17#include "stat.h"
18 18
19int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused) 19int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int subtest __maybe_unused)
20{ 20{
21 int err = -1, fd, cpu; 21 int err = -1, fd, cpu;
22 struct cpu_map *cpus; 22 struct cpu_map *cpus;
@@ -115,7 +115,7 @@ int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused)
115 115
116 perf_evsel__free_counts(evsel); 116 perf_evsel__free_counts(evsel);
117out_close_fd: 117out_close_fd:
118 perf_evsel__close_fd(evsel, 1, threads->nr); 118 perf_evsel__close_fd(evsel);
119out_evsel_delete: 119out_evsel_delete:
120 perf_evsel__delete(evsel); 120 perf_evsel__delete(evsel);
121out_thread_map_delete: 121out_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..b6ee1c41f45d 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -14,7 +14,7 @@
14#define AT_FDCWD -100 14#define AT_FDCWD -100
15#endif 15#endif
16 16
17int test__syscall_openat_tp_fields(int subtest __maybe_unused) 17int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest __maybe_unused)
18{ 18{
19 struct record_opts opts = { 19 struct record_opts opts = {
20 .target = { 20 .target = {
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
index e44506e21ee7..9dc5c5d37553 100644
--- a/tools/perf/tests/openat-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -10,7 +10,7 @@
10#include "debug.h" 10#include "debug.h"
11#include "tests.h" 11#include "tests.h"
12 12
13int test__openat_syscall_event(int subtest __maybe_unused) 13int test__openat_syscall_event(struct test *test __maybe_unused, int subtest __maybe_unused)
14{ 14{
15 int err = -1, fd; 15 int err = -1, fd;
16 struct perf_evsel *evsel; 16 struct perf_evsel *evsel;
@@ -56,7 +56,7 @@ int test__openat_syscall_event(int subtest __maybe_unused)
56 56
57 err = 0; 57 err = 0;
58out_close_fd: 58out_close_fd:
59 perf_evsel__close_fd(evsel, 1, threads->nr); 59 perf_evsel__close_fd(evsel);
60out_evsel_delete: 60out_evsel_delete:
61 perf_evsel__delete(evsel); 61 perf_evsel__delete(evsel);
62out_thread_map_delete: 62out_thread_map_delete:
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 812a053d1941..0f0b025faa4b 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -1810,7 +1810,7 @@ static int test_pmu_events(void)
1810 return ret; 1810 return ret;
1811} 1811}
1812 1812
1813int test__parse_events(int subtest __maybe_unused) 1813int test__parse_events(struct test *test __maybe_unused, int subtest __maybe_unused)
1814{ 1814{
1815 int ret1, ret2 = 0; 1815 int ret1, ret2 = 0;
1816 1816
diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c
index c6207db09f12..91867dcc39f0 100644
--- a/tools/perf/tests/parse-no-sample-id-all.c
+++ b/tools/perf/tests/parse-no-sample-id-all.c
@@ -68,7 +68,7 @@ struct test_attr_event {
68 * 68 *
69 * Return: %0 on success, %-1 if the test fails. 69 * Return: %0 on success, %-1 if the test fails.
70 */ 70 */
71int test__parse_no_sample_id_all(int subtest __maybe_unused) 71int test__parse_no_sample_id_all(struct test *test __maybe_unused, int subtest __maybe_unused)
72{ 72{
73 int err; 73 int err;
74 74
diff --git a/tools/perf/tests/perf-hooks.c b/tools/perf/tests/perf-hooks.c
index 665ecc19671c..bf2517d6de70 100644
--- a/tools/perf/tests/perf-hooks.c
+++ b/tools/perf/tests/perf-hooks.c
@@ -27,7 +27,7 @@ static void the_hook(void *_hook_flags)
27 *p = 0; 27 *p = 0;
28} 28}
29 29
30int test__perf_hooks(int subtest __maybe_unused) 30int test__perf_hooks(struct test *test __maybe_unused, int subtest __maybe_unused)
31{ 31{
32 int hook_flags = 0; 32 int hook_flags = 0;
33 33
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index d37cd9588cc0..19b650064b70 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -37,7 +37,7 @@ realloc:
37 return cpu; 37 return cpu;
38} 38}
39 39
40int test__PERF_RECORD(int subtest __maybe_unused) 40int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unused)
41{ 41{
42 struct record_opts opts = { 42 struct record_opts opts = {
43 .target = { 43 .target = {
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index a6d7aef30030..9f7f589f9c54 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -135,7 +135,7 @@ static struct list_head *test_terms_list(void)
135 return &terms; 135 return &terms;
136} 136}
137 137
138int test__pmu(int subtest __maybe_unused) 138int test__pmu(struct test *test __maybe_unused, int subtest __maybe_unused)
139{ 139{
140 char *format = test_format_dir_get(); 140 char *format = test_format_dir_get();
141 LIST_HEAD(formats); 141 LIST_HEAD(formats);
diff --git a/tools/perf/tests/python-use.c b/tools/perf/tests/python-use.c
index fa79509da535..598a7e058ad4 100644
--- a/tools/perf/tests/python-use.c
+++ b/tools/perf/tests/python-use.c
@@ -9,7 +9,7 @@
9 9
10extern int verbose; 10extern int verbose;
11 11
12int test__python_use(int subtest __maybe_unused) 12int test__python_use(struct test *test __maybe_unused, int subtest __maybe_unused)
13{ 13{
14 char *cmd; 14 char *cmd;
15 int ret; 15 int ret;
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index bac5c3885b3b..c3858487159d 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -141,6 +141,9 @@ static bool samples_same(const struct perf_sample *s1,
141 } 141 }
142 } 142 }
143 143
144 if (type & PERF_SAMPLE_PHYS_ADDR)
145 COMP(phys_addr);
146
144 return true; 147 return true;
145} 148}
146 149
@@ -206,6 +209,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
206 .mask = sample_regs, 209 .mask = sample_regs,
207 .regs = regs, 210 .regs = regs,
208 }, 211 },
212 .phys_addr = 113,
209 }; 213 };
210 struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},}; 214 struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},};
211 struct perf_sample sample_out; 215 struct perf_sample sample_out;
@@ -292,7 +296,7 @@ out_free:
292 * checks sample format bits separately and together. If the test passes %0 is 296 * checks sample format bits separately and together. If the test passes %0 is
293 * returned, otherwise %-1 is returned. 297 * returned, otherwise %-1 is returned.
294 */ 298 */
295int test__sample_parsing(int subtest __maybe_unused) 299int test__sample_parsing(struct test *test __maybe_unused, int subtest __maybe_unused)
296{ 300{
297 const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15}; 301 const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15};
298 u64 sample_type; 302 u64 sample_type;
@@ -305,7 +309,7 @@ int test__sample_parsing(int subtest __maybe_unused)
305 * were added. Please actually update the test rather than just change 309 * were added. Please actually update the test rather than just change
306 * the condition below. 310 * the condition below.
307 */ 311 */
308 if (PERF_SAMPLE_MAX > PERF_SAMPLE_REGS_INTR << 1) { 312 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"); 313 pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n");
310 return -1; 314 return -1;
311 } 315 }
diff --git a/tools/perf/tests/sdt.c b/tools/perf/tests/sdt.c
index 06eda675ae2c..a9903d9b8bc2 100644
--- a/tools/perf/tests/sdt.c
+++ b/tools/perf/tests/sdt.c
@@ -33,7 +33,7 @@ static int build_id_cache__add_file(const char *filename)
33 } 33 }
34 34
35 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 35 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
36 err = build_id_cache__add_s(sbuild_id, filename, false, false); 36 err = build_id_cache__add_s(sbuild_id, filename, NULL, false, false);
37 if (err < 0) 37 if (err < 0)
38 pr_debug("Failed to add build id cache of %s\n", filename); 38 pr_debug("Failed to add build id cache of %s\n", filename);
39 return err; 39 return err;
@@ -54,7 +54,7 @@ static char *get_self_path(void)
54static int search_cached_probe(const char *target, 54static int search_cached_probe(const char *target,
55 const char *group, const char *event) 55 const char *group, const char *event)
56{ 56{
57 struct probe_cache *cache = probe_cache__new(target); 57 struct probe_cache *cache = probe_cache__new(target, NULL);
58 int ret = 0; 58 int ret = 0;
59 59
60 if (!cache) { 60 if (!cache) {
@@ -71,7 +71,7 @@ static int search_cached_probe(const char *target,
71 return ret; 71 return ret;
72} 72}
73 73
74int test__sdt_event(int subtests __maybe_unused) 74int test__sdt_event(struct test *test __maybe_unused, int subtests __maybe_unused)
75{ 75{
76 int ret = TEST_FAIL; 76 int ret = TEST_FAIL;
77 char __tempdir[] = "./test-buildid-XXXXXX"; 77 char __tempdir[] = "./test-buildid-XXXXXX";
@@ -83,6 +83,8 @@ int test__sdt_event(int subtests __maybe_unused)
83 } 83 }
84 /* Note that buildid_dir must be an absolute path */ 84 /* Note that buildid_dir must be an absolute path */
85 tempdir = realpath(__tempdir, NULL); 85 tempdir = realpath(__tempdir, NULL);
86 if (tempdir == NULL)
87 goto error_rmdir;
86 88
87 /* At first, scan itself */ 89 /* At first, scan itself */
88 set_buildid_dir(tempdir); 90 set_buildid_dir(tempdir);
@@ -100,14 +102,14 @@ int test__sdt_event(int subtests __maybe_unused)
100 102
101error_rmdir: 103error_rmdir:
102 /* Cleanup temporary buildid dir */ 104 /* Cleanup temporary buildid dir */
103 rm_rf(tempdir); 105 rm_rf(__tempdir);
104error: 106error:
105 free(tempdir); 107 free(tempdir);
106 free(myself); 108 free(myself);
107 return ret; 109 return ret;
108} 110}
109#else 111#else
110int test__sdt_event(int subtests __maybe_unused) 112int test__sdt_event(struct test *test __maybe_unused, int subtests __maybe_unused)
111{ 113{
112 pr_debug("Skip SDT event test because SDT support is not compiled\n"); 114 pr_debug("Skip SDT event test because SDT support is not compiled\n");
113 return TEST_SKIP; 115 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..462fc755092e
--- /dev/null
+++ b/tools/perf/tests/shell/trace+probe_libc_inet_pton.sh
@@ -0,0 +1,43 @@
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
13trace_libc_inet_pton_backtrace() {
14 idx=0
15 expected[0]="PING.*bytes"
16 expected[1]="64 bytes from ::1.*"
17 expected[2]=".*ping statistics.*"
18 expected[3]=".*packets transmitted.*"
19 expected[4]="rtt min.*"
20 expected[5]="[0-9]+\.[0-9]+[[:space:]]+probe_libc:inet_pton:\([[:xdigit:]]+\)"
21 expected[6]=".*inet_pton[[:space:]]\(/usr/lib.*/libc-[0-9]+\.[0-9]+\.so\)$"
22 expected[7]="getaddrinfo[[:space:]]\(/usr/lib.*/libc-[0-9]+\.[0-9]+\.so\)$"
23 expected[8]=".*\(.*/bin/ping.*\)$"
24
25 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
26 echo $line
27 echo "$line" | egrep -q "${expected[$idx]}"
28 if [ $? -ne 0 ] ; then
29 printf "FAIL: expected backtrace entry %d \"%s\" got \"%s\"\n" $idx "${expected[$idx]}" "$line"
30 exit 1
31 fi
32 let idx+=1
33 [ $idx -eq 9 ] && break
34 done
35}
36
37skip_if_no_perf_probe && \
38perf probe -q /lib64/libc-*.so inet_pton && \
39trace_libc_inet_pton_backtrace
40err=$?
41rm -f ${file}
42perf probe -q -d probe_libc:inet_pton
43exit $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..7f988a939036 100644
--- a/tools/perf/tests/stat.c
+++ b/tools/perf/tests/stat.c
@@ -45,7 +45,7 @@ static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
45 return 0; 45 return 0;
46} 46}
47 47
48int test__synthesize_stat_config(int subtest __maybe_unused) 48int test__synthesize_stat_config(struct test *test __maybe_unused, int subtest __maybe_unused)
49{ 49{
50 struct perf_stat_config stat_config = { 50 struct perf_stat_config stat_config = {
51 .aggr_mode = AGGR_CORE, 51 .aggr_mode = AGGR_CORE,
@@ -75,7 +75,7 @@ static int process_stat_event(struct perf_tool *tool __maybe_unused,
75 return 0; 75 return 0;
76} 76}
77 77
78int test__synthesize_stat(int subtest __maybe_unused) 78int test__synthesize_stat(struct test *test __maybe_unused, int subtest __maybe_unused)
79{ 79{
80 struct perf_counts_values count; 80 struct perf_counts_values count;
81 81
@@ -101,7 +101,7 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
101 return 0; 101 return 0;
102} 102}
103 103
104int test__synthesize_stat_round(int subtest __maybe_unused) 104int test__synthesize_stat_round(struct test *test __maybe_unused, int subtest __maybe_unused)
105{ 105{
106 TEST_ASSERT_VAL("failed to synthesize stat_config", 106 TEST_ASSERT_VAL("failed to synthesize stat_config",
107 !perf_event__synthesize_stat_round(NULL, 0xdeadbeef, PERF_STAT_ROUND_TYPE__INTERVAL, 107 !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..d88511f6072c 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -124,7 +124,7 @@ out_delete_evlist:
124 return err; 124 return err;
125} 125}
126 126
127int test__sw_clock_freq(int subtest __maybe_unused) 127int test__sw_clock_freq(struct test *test __maybe_unused, int subtest __maybe_unused)
128{ 128{
129 int ret; 129 int ret;
130 130
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index 65474fd80da7..2acd78555192 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -306,7 +306,7 @@ out_free_nodes:
306 * evsel->system_wide and evsel->tracking flags (respectively) with other events 306 * evsel->system_wide and evsel->tracking flags (respectively) with other events
307 * sometimes enabled or disabled. 307 * sometimes enabled or disabled.
308 */ 308 */
309int test__switch_tracking(int subtest __maybe_unused) 309int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_unused)
310{ 310{
311 const char *sched_switch = "sched:sched_switch"; 311 const char *sched_switch = "sched:sched_switch";
312 struct switch_tracking switch_tracking = { .tids = NULL, }; 312 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..f0881d0dd9c9 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -32,7 +32,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 32 * 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. 33 * in order to check the kernel returns correct number of event.
34 */ 34 */
35int test__task_exit(int subtest __maybe_unused) 35int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused)
36{ 36{
37 int err = -1; 37 int err = -1;
38 union perf_event *event; 38 union perf_event *event;
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 577363809c9b..921412a6a880 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -28,77 +28,79 @@ enum {
28 28
29struct test { 29struct test {
30 const char *desc; 30 const char *desc;
31 int (*func)(int subtest); 31 int (*func)(struct test *test, int subtest);
32 struct { 32 struct {
33 bool skip_if_fail; 33 bool skip_if_fail;
34 int (*get_nr)(void); 34 int (*get_nr)(void);
35 const char *(*get_desc)(int subtest); 35 const char *(*get_desc)(int subtest);
36 } subtest; 36 } subtest;
37 bool (*is_supported)(void); 37 bool (*is_supported)(void);
38 void *priv;
38}; 39};
39 40
40/* Tests */ 41/* Tests */
41int test__vmlinux_matches_kallsyms(int subtest); 42int test__vmlinux_matches_kallsyms(struct test *test, int subtest);
42int test__openat_syscall_event(int subtest); 43int test__openat_syscall_event(struct test *test, int subtest);
43int test__openat_syscall_event_on_all_cpus(int subtest); 44int test__openat_syscall_event_on_all_cpus(struct test *test, int subtest);
44int test__basic_mmap(int subtest); 45int test__basic_mmap(struct test *test, int subtest);
45int test__PERF_RECORD(int subtest); 46int test__PERF_RECORD(struct test *test, int subtest);
46int test__perf_evsel__roundtrip_name_test(int subtest); 47int test__perf_evsel__roundtrip_name_test(struct test *test, int subtest);
47int test__perf_evsel__tp_sched_test(int subtest); 48int test__perf_evsel__tp_sched_test(struct test *test, int subtest);
48int test__syscall_openat_tp_fields(int subtest); 49int test__syscall_openat_tp_fields(struct test *test, int subtest);
49int test__pmu(int subtest); 50int test__pmu(struct test *test, int subtest);
50int test__attr(int subtest); 51int test__attr(struct test *test, int subtest);
51int test__dso_data(int subtest); 52int test__dso_data(struct test *test, int subtest);
52int test__dso_data_cache(int subtest); 53int test__dso_data_cache(struct test *test, int subtest);
53int test__dso_data_reopen(int subtest); 54int test__dso_data_reopen(struct test *test, int subtest);
54int test__parse_events(int subtest); 55int test__parse_events(struct test *test, int subtest);
55int test__hists_link(int subtest); 56int test__hists_link(struct test *test, int subtest);
56int test__python_use(int subtest); 57int test__python_use(struct test *test, int subtest);
57int test__bp_signal(int subtest); 58int test__bp_signal(struct test *test, int subtest);
58int test__bp_signal_overflow(int subtest); 59int test__bp_signal_overflow(struct test *test, int subtest);
59int test__task_exit(int subtest); 60int test__task_exit(struct test *test, int subtest);
60int test__sw_clock_freq(int subtest); 61int test__mem(struct test *test, int subtest);
61int test__code_reading(int subtest); 62int test__sw_clock_freq(struct test *test, int subtest);
62int test__sample_parsing(int subtest); 63int test__code_reading(struct test *test, int subtest);
63int test__keep_tracking(int subtest); 64int test__sample_parsing(struct test *test, int subtest);
64int test__parse_no_sample_id_all(int subtest); 65int test__keep_tracking(struct test *test, int subtest);
65int test__dwarf_unwind(int subtest); 66int test__parse_no_sample_id_all(struct test *test, int subtest);
66int test__expr(int subtest); 67int test__dwarf_unwind(struct test *test, int subtest);
67int test__hists_filter(int subtest); 68int test__expr(struct test *test, int subtest);
68int test__mmap_thread_lookup(int subtest); 69int test__hists_filter(struct test *test, int subtest);
69int test__thread_mg_share(int subtest); 70int test__mmap_thread_lookup(struct test *test, int subtest);
70int test__hists_output(int subtest); 71int test__thread_mg_share(struct test *test, int subtest);
71int test__hists_cumulate(int subtest); 72int test__hists_output(struct test *test, int subtest);
72int test__switch_tracking(int subtest); 73int test__hists_cumulate(struct test *test, int subtest);
73int test__fdarray__filter(int subtest); 74int test__switch_tracking(struct test *test, int subtest);
74int test__fdarray__add(int subtest); 75int test__fdarray__filter(struct test *test, int subtest);
75int test__kmod_path__parse(int subtest); 76int test__fdarray__add(struct test *test, int subtest);
76int test__thread_map(int subtest); 77int test__kmod_path__parse(struct test *test, int subtest);
77int test__llvm(int subtest); 78int test__thread_map(struct test *test, int subtest);
79int test__llvm(struct test *test, int subtest);
78const char *test__llvm_subtest_get_desc(int subtest); 80const char *test__llvm_subtest_get_desc(int subtest);
79int test__llvm_subtest_get_nr(void); 81int test__llvm_subtest_get_nr(void);
80int test__bpf(int subtest); 82int test__bpf(struct test *test, int subtest);
81const char *test__bpf_subtest_get_desc(int subtest); 83const char *test__bpf_subtest_get_desc(int subtest);
82int test__bpf_subtest_get_nr(void); 84int test__bpf_subtest_get_nr(void);
83int test_session_topology(int subtest); 85int test__session_topology(struct test *test, int subtest);
84int test__thread_map_synthesize(int subtest); 86int test__thread_map_synthesize(struct test *test, int subtest);
85int test__thread_map_remove(int subtest); 87int test__thread_map_remove(struct test *test, int subtest);
86int test__cpu_map_synthesize(int subtest); 88int test__cpu_map_synthesize(struct test *test, int subtest);
87int test__synthesize_stat_config(int subtest); 89int test__synthesize_stat_config(struct test *test, int subtest);
88int test__synthesize_stat(int subtest); 90int test__synthesize_stat(struct test *test, int subtest);
89int test__synthesize_stat_round(int subtest); 91int test__synthesize_stat_round(struct test *test, int subtest);
90int test__event_update(int subtest); 92int test__event_update(struct test *test, int subtest);
91int test__event_times(int subtest); 93int test__event_times(struct test *test, int subtest);
92int test__backward_ring_buffer(int subtest); 94int test__backward_ring_buffer(struct test *test, int subtest);
93int test__cpu_map_print(int subtest); 95int test__cpu_map_print(struct test *test, int subtest);
94int test__sdt_event(int subtest); 96int test__sdt_event(struct test *test, int subtest);
95int test__is_printable_array(int subtest); 97int test__is_printable_array(struct test *test, int subtest);
96int test__bitmap_print(int subtest); 98int test__bitmap_print(struct test *test, int subtest);
97int test__perf_hooks(int subtest); 99int test__perf_hooks(struct test *test, int subtest);
98int test__clang(int subtest); 100int test__clang(struct test *test, int subtest);
99const char *test__clang_subtest_get_desc(int subtest); 101const char *test__clang_subtest_get_desc(int subtest);
100int test__clang_subtest_get_nr(void); 102int test__clang_subtest_get_nr(void);
101int test__unit_number__scnprint(int subtest); 103int test__unit_number__scnprint(struct test *test, int subtest);
102 104
103bool test__bp_signal_is_supported(void); 105bool test__bp_signal_is_supported(void);
104 106
diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index a63d6945807b..b3423c744f46 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -9,7 +9,7 @@
9#define NAME (const char *) "perf" 9#define NAME (const char *) "perf"
10#define NAMEUL (unsigned long) NAME 10#define NAMEUL (unsigned long) NAME
11 11
12int test__thread_map(int subtest __maybe_unused) 12int test__thread_map(struct test *test __maybe_unused, int subtest __maybe_unused)
13{ 13{
14 struct thread_map *map; 14 struct thread_map *map;
15 15
@@ -76,7 +76,7 @@ static int process_event(struct perf_tool *tool __maybe_unused,
76 return 0; 76 return 0;
77} 77}
78 78
79int test__thread_map_synthesize(int subtest __maybe_unused) 79int test__thread_map_synthesize(struct test *test __maybe_unused, int subtest __maybe_unused)
80{ 80{
81 struct thread_map *threads; 81 struct thread_map *threads;
82 82
@@ -95,7 +95,7 @@ int test__thread_map_synthesize(int subtest __maybe_unused)
95 return 0; 95 return 0;
96} 96}
97 97
98int test__thread_map_remove(int subtest __maybe_unused) 98int test__thread_map_remove(struct test *test __maybe_unused, int subtest __maybe_unused)
99{ 99{
100 struct thread_map *threads; 100 struct thread_map *threads;
101 char *str; 101 char *str;
diff --git a/tools/perf/tests/thread-mg-share.c b/tools/perf/tests/thread-mg-share.c
index 76686dd6f5ec..b9c7f58db6c4 100644
--- a/tools/perf/tests/thread-mg-share.c
+++ b/tools/perf/tests/thread-mg-share.c
@@ -4,7 +4,7 @@
4#include "map.h" 4#include "map.h"
5#include "debug.h" 5#include "debug.h"
6 6
7int test__thread_mg_share(int subtest __maybe_unused) 7int test__thread_mg_share(struct test *test __maybe_unused, int subtest __maybe_unused)
8{ 8{
9 struct machines machines; 9 struct machines machines;
10 struct machine *machine; 10 struct machine *machine;
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
index 803f893550d6..19b0561fd6f6 100644
--- a/tools/perf/tests/topology.c
+++ b/tools/perf/tests/topology.c
@@ -86,7 +86,7 @@ static int check_cpu_topology(char *path, struct cpu_map *map)
86 return 0; 86 return 0;
87} 87}
88 88
89int test_session_topology(int subtest __maybe_unused) 89int test__session_topology(struct test *test __maybe_unused, int subtest __maybe_unused)
90{ 90{
91 char path[PATH_MAX]; 91 char path[PATH_MAX];
92 struct cpu_map *map; 92 struct cpu_map *map;
diff --git a/tools/perf/tests/unit_number__scnprintf.c b/tools/perf/tests/unit_number__scnprintf.c
index 44589de084b8..15cd1cf8c129 100644
--- a/tools/perf/tests/unit_number__scnprintf.c
+++ b/tools/perf/tests/unit_number__scnprintf.c
@@ -5,7 +5,7 @@
5#include "units.h" 5#include "units.h"
6#include "debug.h" 6#include "debug.h"
7 7
8int test__unit_number__scnprint(int subtest __maybe_unused) 8int test__unit_number__scnprint(struct test *t __maybe_unused, int subtest __maybe_unused)
9{ 9{
10 struct { 10 struct {
11 u64 n; 11 u64 n;
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index 8456175fc234..86cb8868f67f 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -11,7 +11,7 @@
11 11
12#define UM(x) kallsyms_map->unmap_ip(kallsyms_map, (x)) 12#define UM(x) kallsyms_map->unmap_ip(kallsyms_map, (x))
13 13
14int test__vmlinux_matches_kallsyms(int subtest __maybe_unused) 14int test__vmlinux_matches_kallsyms(struct test *test __maybe_unused, int subtest __maybe_unused)
15{ 15{
16 int err = -1; 16 int err = -1;
17 struct rb_node *nd; 17 struct rb_node *nd;
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build
index be95ac6ce845..175d633c6b49 100644
--- a/tools/perf/trace/beauty/Build
+++ b/tools/perf/trace/beauty/Build
@@ -1 +1,7 @@
1libperf-y += clone.o
2libperf-y += fcntl.o
3ifeq ($(SRCARCH),$(filter $(SRCARCH),x86))
4libperf-y += ioctl.o
5endif
6libperf-y += pkey_alloc.o
1libperf-y += statx.o 7libperf-y += statx.o
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index cf50be3f17a4..4b58581a6053 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -1,13 +1,44 @@
1#ifndef _PERF_TRACE_BEAUTY_H 1#ifndef _PERF_TRACE_BEAUTY_H
2#define _PERF_TRACE_BEAUTY_H 2#define _PERF_TRACE_BEAUTY_H
3 3
4#include <linux/kernel.h>
4#include <linux/types.h> 5#include <linux/types.h>
5 6
7struct strarray {
8 int offset;
9 int nr_entries;
10 const char **entries;
11};
12
13#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
14 .nr_entries = ARRAY_SIZE(array), \
15 .entries = array, \
16}
17
18#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
19 .offset = off, \
20 .nr_entries = ARRAY_SIZE(array), \
21 .entries = array, \
22}
23
24size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val);
25
6struct trace; 26struct trace;
7struct thread; 27struct thread;
8 28
29/**
30 * @val: value of syscall argument being formatted
31 * @args: All the args, use syscall_args__val(arg, nth) to access one
32 * @thread: tid state (maps, pid, tid, etc)
33 * @trace: 'perf trace' internals: all threads, etc
34 * @parm: private area, may be an strarray, for instance
35 * @idx: syscall arg idx (is this the first?)
36 * @mask: a syscall arg may mask another arg, see syscall_arg__scnprintf_futex_op
37 */
38
9struct syscall_arg { 39struct syscall_arg {
10 unsigned long val; 40 unsigned long val;
41 unsigned char *args;
11 struct thread *thread; 42 struct thread *thread;
12 struct trace *trace; 43 struct trace *trace;
13 void *parm; 44 void *parm;
@@ -15,10 +46,53 @@ struct syscall_arg {
15 u8 mask; 46 u8 mask;
16}; 47};
17 48
49unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx);
50
51size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
52#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays
53
54size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg);
55#define SCA_FD syscall_arg__scnprintf_fd
56
57size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg);
58#define SCA_HEX syscall_arg__scnprintf_hex
59
60size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg);
61#define SCA_INT syscall_arg__scnprintf_int
62
63size_t syscall_arg__scnprintf_long(char *bf, size_t size, struct syscall_arg *arg);
64#define SCA_LONG syscall_arg__scnprintf_long
65
66size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg);
67#define SCA_PID syscall_arg__scnprintf_pid
68
69size_t syscall_arg__scnprintf_clone_flags(char *bf, size_t size, struct syscall_arg *arg);
70#define SCA_CLONE_FLAGS syscall_arg__scnprintf_clone_flags
71
72size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg);
73#define SCA_FCNTL_CMD syscall_arg__scnprintf_fcntl_cmd
74
75size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_arg *arg);
76#define SCA_FCNTL_ARG syscall_arg__scnprintf_fcntl_arg
77
78size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg);
79#define SCA_IOCTL_CMD syscall_arg__scnprintf_ioctl_cmd
80
81size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg);
82#define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights
83
84size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg);
85#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
86
18size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg); 87size_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 88#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags
20 89
21size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_arg *arg); 90size_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 91#define SCA_STATX_MASK syscall_arg__scnprintf_statx_mask
23 92
93size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size);
94
95void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
96 size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg));
97
24#endif /* _PERF_TRACE_BEAUTY_H */ 98#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/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/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/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/mmap.c b/tools/perf/trace/beauty/mmap.c
index af1cfde6b97b..754558f9009d 100644
--- a/tools/perf/trace/beauty/mmap.c
+++ b/tools/perf/trace/beauty/mmap.c
@@ -34,6 +34,9 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
34{ 34{
35 int printed = 0, flags = arg->val; 35 int printed = 0, flags = arg->val;
36 36
37 if (flags & MAP_ANONYMOUS)
38 arg->mask |= (1 << 4) | (1 << 5); /* Mask 4th ('fd') and 5th ('offset') args, ignored */
39
37#define P_MMAP_FLAG(n) \ 40#define P_MMAP_FLAG(n) \
38 if (flags & MAP_##n) { \ 41 if (flags & MAP_##n) { \
39 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ 42 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
index f55a4597fc38..e359e041dc0e 100644
--- a/tools/perf/trace/beauty/open_flags.c
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -14,13 +14,16 @@
14#define O_NOATIME 01000000 14#define O_NOATIME 01000000
15#endif 15#endif
16 16
17static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, 17#ifndef O_TMPFILE
18 struct syscall_arg *arg) 18#define O_TMPFILE 020000000
19{ 19#endif
20 int printed = 0, flags = arg->val;
21 20
22 if (!(flags & O_CREAT)) 21#undef O_LARGEFILE
23 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */ 22#define O_LARGEFILE 00100000
23
24size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size)
25{
26 int printed = 0;
24 27
25 if (flags == 0) 28 if (flags == 0)
26 return scnprintf(bf, size, "RDONLY"); 29 return scnprintf(bf, size, "RDONLY");
@@ -30,6 +33,7 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
30 flags &= ~O_##n; \ 33 flags &= ~O_##n; \
31 } 34 }
32 35
36 P_FLAG(RDWR);
33 P_FLAG(APPEND); 37 P_FLAG(APPEND);
34 P_FLAG(ASYNC); 38 P_FLAG(ASYNC);
35 P_FLAG(CLOEXEC); 39 P_FLAG(CLOEXEC);
@@ -38,6 +42,8 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
38 P_FLAG(DIRECTORY); 42 P_FLAG(DIRECTORY);
39 P_FLAG(EXCL); 43 P_FLAG(EXCL);
40 P_FLAG(LARGEFILE); 44 P_FLAG(LARGEFILE);
45 P_FLAG(NOFOLLOW);
46 P_FLAG(TMPFILE);
41 P_FLAG(NOATIME); 47 P_FLAG(NOATIME);
42 P_FLAG(NOCTTY); 48 P_FLAG(NOCTTY);
43#ifdef O_NONBLOCK 49#ifdef O_NONBLOCK
@@ -48,7 +54,6 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
48#ifdef O_PATH 54#ifdef O_PATH
49 P_FLAG(PATH); 55 P_FLAG(PATH);
50#endif 56#endif
51 P_FLAG(RDWR);
52#ifdef O_DSYNC 57#ifdef O_DSYNC
53 if ((flags & O_SYNC) == O_SYNC) 58 if ((flags & O_SYNC) == O_SYNC)
54 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC"); 59 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
@@ -68,4 +73,12 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
68 return printed; 73 return printed;
69} 74}
70 75
71#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags 76size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg)
77{
78 int flags = arg->val;
79
80 if (!(flags & O_CREAT))
81 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
82
83 return open__scnprintf_flags(flags, bf, size);
84}
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..b6d419e16dcf 100644
--- a/tools/perf/trace/beauty/pid.c
+++ b/tools/perf/trace/beauty/pid.c
@@ -1,4 +1,4 @@
1static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg) 1size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
2{ 2{
3 int pid = arg->val; 3 int pid = arg->val;
4 struct trace *trace = arg->trace; 4 struct trace *trace = arg->trace;
@@ -17,5 +17,3 @@ static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_a
17 17
18 return printed; 18 return printed;
19} 19}
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/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/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/ui/browser.c b/tools/perf/ui/browser.c
index a4d3762cd825..d0c2007c307b 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -8,6 +8,7 @@
8#include <linux/compiler.h> 8#include <linux/compiler.h>
9#include <linux/list.h> 9#include <linux/list.h>
10#include <linux/rbtree.h> 10#include <linux/rbtree.h>
11#include <linux/string.h>
11#include <stdlib.h> 12#include <stdlib.h>
12#include <sys/ttydefaults.h> 13#include <sys/ttydefaults.h>
13#include "browser.h" 14#include "browser.h"
@@ -563,7 +564,7 @@ static int ui_browser__color_config(const char *var, const char *value,
563 int i; 564 int i;
564 565
565 /* same dir for all commands */ 566 /* same dir for all commands */
566 if (prefixcmp(var, "colors.") != 0) 567 if (!strstarts(var, "colors.") != 0)
567 return 0; 568 return 0;
568 569
569 for (i = 0; ui_browser__colorsets[i].name != NULL; ++i) { 570 for (i = 0; ui_browser__colorsets[i].name != NULL; ++i) {
@@ -704,7 +705,7 @@ static void __ui_browser__line_arrow_down(struct ui_browser *browser,
704 ui_browser__gotorc(browser, row, column + 1); 705 ui_browser__gotorc(browser, row, column + 1);
705 SLsmg_draw_hline(2); 706 SLsmg_draw_hline(2);
706 707
707 if (row++ == 0) 708 if (++row == 0)
708 goto out; 709 goto out;
709 } else 710 } else
710 row = 0; 711 row = 0;
@@ -738,6 +739,35 @@ void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
738 __ui_browser__line_arrow_down(browser, column, start, end); 739 __ui_browser__line_arrow_down(browser, column, start, end);
739} 740}
740 741
742void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column,
743 unsigned int row, bool arrow_down)
744{
745 unsigned int end_row;
746
747 if (row >= browser->top_idx)
748 end_row = row - browser->top_idx;
749 else
750 return;
751
752 SLsmg_set_char_set(1);
753
754 if (arrow_down) {
755 ui_browser__gotorc(browser, end_row, column - 1);
756 SLsmg_write_char(SLSMG_ULCORN_CHAR);
757 ui_browser__gotorc(browser, end_row, column);
758 SLsmg_draw_hline(2);
759 ui_browser__gotorc(browser, end_row + 1, column - 1);
760 SLsmg_write_char(SLSMG_LTEE_CHAR);
761 } else {
762 ui_browser__gotorc(browser, end_row, column - 1);
763 SLsmg_write_char(SLSMG_LTEE_CHAR);
764 ui_browser__gotorc(browser, end_row, column);
765 SLsmg_draw_hline(2);
766 }
767
768 SLsmg_set_char_set(0);
769}
770
741void ui_browser__init(void) 771void ui_browser__init(void)
742{ 772{
743 int i = 0; 773 int i = 0;
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index be3b70eb5fca..a12eff75638b 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -43,6 +43,8 @@ void ui_browser__printf(struct ui_browser *browser, const char *fmt, ...);
43void ui_browser__write_graph(struct ui_browser *browser, int graph); 43void ui_browser__write_graph(struct ui_browser *browser, int graph);
44void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column, 44void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
45 u64 start, u64 end); 45 u64 start, u64 end);
46void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column,
47 unsigned int row, bool arrow_down);
46void __ui_browser__show_title(struct ui_browser *browser, const char *title); 48void __ui_browser__show_title(struct ui_browser *browser, const char *title);
47void ui_browser__show_title(struct ui_browser *browser, const char *title); 49void ui_browser__show_title(struct ui_browser *browser, const char *title);
48int ui_browser__show(struct ui_browser *browser, const char *title, 50int 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..786fecaf578e 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -9,14 +9,16 @@
9#include "../../util/symbol.h" 9#include "../../util/symbol.h"
10#include "../../util/evsel.h" 10#include "../../util/evsel.h"
11#include "../../util/config.h" 11#include "../../util/config.h"
12#include "../../util/evlist.h"
12#include <inttypes.h> 13#include <inttypes.h>
13#include <pthread.h> 14#include <pthread.h>
14#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/string.h>
15#include <sys/ttydefaults.h> 17#include <sys/ttydefaults.h>
16 18
17struct disasm_line_samples { 19struct disasm_line_samples {
18 double percent; 20 double percent;
19 u64 nr; 21 struct sym_hist_entry he;
20}; 22};
21 23
22#define IPC_WIDTH 6 24#define IPC_WIDTH 6
@@ -40,6 +42,7 @@ static struct annotate_browser_opt {
40 jump_arrows, 42 jump_arrows,
41 show_linenr, 43 show_linenr,
42 show_nr_jumps, 44 show_nr_jumps,
45 show_nr_samples,
43 show_total_period; 46 show_total_period;
44} annotate_browser__opts = { 47} annotate_browser__opts = {
45 .use_offset = true, 48 .use_offset = true,
@@ -108,11 +111,12 @@ static int annotate_browser__set_jumps_percent_color(struct annotate_browser *br
108 111
109static int annotate_browser__pcnt_width(struct annotate_browser *ab) 112static int annotate_browser__pcnt_width(struct annotate_browser *ab)
110{ 113{
111 int w = 7 * ab->nr_events; 114 return (annotate_browser__opts.show_total_period ? 12 : 7) * ab->nr_events;
115}
112 116
113 if (ab->have_cycles) 117static int annotate_browser__cycles_width(struct annotate_browser *ab)
114 w += IPC_WIDTH + CYCLES_WIDTH; 118{
115 return w; 119 return ab->have_cycles ? IPC_WIDTH + CYCLES_WIDTH : 0;
116} 120}
117 121
118static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 122static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
@@ -125,7 +129,8 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
125 (!current_entry || (browser->use_navkeypressed && 129 (!current_entry || (browser->use_navkeypressed &&
126 !browser->navkeypressed))); 130 !browser->navkeypressed)));
127 int width = browser->width, printed; 131 int width = browser->width, printed;
128 int i, pcnt_width = annotate_browser__pcnt_width(ab); 132 int i, pcnt_width = annotate_browser__pcnt_width(ab),
133 cycles_width = annotate_browser__cycles_width(ab);
129 double percent_max = 0.0; 134 double percent_max = 0.0;
130 char bf[256]; 135 char bf[256];
131 bool show_title = false; 136 bool show_title = false;
@@ -149,8 +154,11 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
149 bdl->samples[i].percent, 154 bdl->samples[i].percent,
150 current_entry); 155 current_entry);
151 if (annotate_browser__opts.show_total_period) { 156 if (annotate_browser__opts.show_total_period) {
157 ui_browser__printf(browser, "%11" PRIu64 " ",
158 bdl->samples[i].he.period);
159 } else if (annotate_browser__opts.show_nr_samples) {
152 ui_browser__printf(browser, "%6" PRIu64 " ", 160 ui_browser__printf(browser, "%6" PRIu64 " ",
153 bdl->samples[i].nr); 161 bdl->samples[i].he.nr_samples);
154 } else { 162 } else {
155 ui_browser__printf(browser, "%6.2f ", 163 ui_browser__printf(browser, "%6.2f ",
156 bdl->samples[i].percent); 164 bdl->samples[i].percent);
@@ -160,9 +168,12 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
160 ui_browser__set_percent_color(browser, 0, current_entry); 168 ui_browser__set_percent_color(browser, 0, current_entry);
161 169
162 if (!show_title) 170 if (!show_title)
163 ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); 171 ui_browser__write_nstring(browser, " ", pcnt_width);
164 else 172 else {
165 ui_browser__printf(browser, "%*s", 7, "Percent"); 173 ui_browser__printf(browser, "%*s", pcnt_width,
174 annotate_browser__opts.show_total_period ? "Period" :
175 annotate_browser__opts.show_nr_samples ? "Samples" : "Percent");
176 }
166 } 177 }
167 if (ab->have_cycles) { 178 if (ab->have_cycles) {
168 if (dl->ipc) 179 if (dl->ipc)
@@ -188,7 +199,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
188 width += 1; 199 width += 1;
189 200
190 if (!*dl->line) 201 if (!*dl->line)
191 ui_browser__write_nstring(browser, " ", width - pcnt_width); 202 ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width);
192 else if (dl->offset == -1) { 203 else if (dl->offset == -1) {
193 if (dl->line_nr && annotate_browser__opts.show_linenr) 204 if (dl->line_nr && annotate_browser__opts.show_linenr)
194 printed = scnprintf(bf, sizeof(bf), "%-*d ", 205 printed = scnprintf(bf, sizeof(bf), "%-*d ",
@@ -197,7 +208,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
197 printed = scnprintf(bf, sizeof(bf), "%*s ", 208 printed = scnprintf(bf, sizeof(bf), "%*s ",
198 ab->addr_width, " "); 209 ab->addr_width, " ");
199 ui_browser__write_nstring(browser, bf, printed); 210 ui_browser__write_nstring(browser, bf, printed);
200 ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width + 1); 211 ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width - cycles_width + 1);
201 } else { 212 } else {
202 u64 addr = dl->offset; 213 u64 addr = dl->offset;
203 int color = -1; 214 int color = -1;
@@ -254,7 +265,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
254 } 265 }
255 266
256 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 267 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset);
257 ui_browser__write_nstring(browser, bf, width - pcnt_width - 3 - printed); 268 ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed);
258 } 269 }
259 270
260 if (current_entry) 271 if (current_entry)
@@ -272,6 +283,25 @@ static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sy
272 return true; 283 return true;
273} 284}
274 285
286static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
287{
288 struct disasm_line *pos = list_prev_entry(cursor, node);
289 const char *name;
290
291 if (!pos)
292 return false;
293
294 if (ins__is_lock(&pos->ins))
295 name = pos->ops.locked.ins.name;
296 else
297 name = pos->ins.name;
298
299 if (!name || !cursor->ins.name)
300 return false;
301
302 return ins__is_fused(ab->arch, name, cursor->ins.name);
303}
304
275static void annotate_browser__draw_current_jump(struct ui_browser *browser) 305static void annotate_browser__draw_current_jump(struct ui_browser *browser)
276{ 306{
277 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 307 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
@@ -307,6 +337,13 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
307 ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 337 ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
308 __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, 338 __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width,
309 from, to); 339 from, to);
340
341 if (is_fused(ab, cursor)) {
342 ui_browser__mark_fused(browser,
343 pcnt_width + 3 + ab->addr_width,
344 from - 1,
345 to > from ? true : false);
346 }
310} 347}
311 348
312static unsigned int annotate_browser__refresh(struct ui_browser *browser) 349static unsigned int annotate_browser__refresh(struct ui_browser *browser)
@@ -422,14 +459,14 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
422 next = disasm__get_next_ip_line(&notes->src->source, pos); 459 next = disasm__get_next_ip_line(&notes->src->source, pos);
423 460
424 for (i = 0; i < browser->nr_events; i++) { 461 for (i = 0; i < browser->nr_events; i++) {
425 u64 nr_samples; 462 struct sym_hist_entry sample;
426 463
427 bpos->samples[i].percent = disasm__calc_percent(notes, 464 bpos->samples[i].percent = disasm__calc_percent(notes,
428 evsel->idx + i, 465 evsel->idx + i,
429 pos->offset, 466 pos->offset,
430 next ? next->offset : len, 467 next ? next->offset : len,
431 &path, &nr_samples); 468 &path, &sample);
432 bpos->samples[i].nr = nr_samples; 469 bpos->samples[i].he = sample;
433 470
434 if (max_percent < bpos->samples[i].percent) 471 if (max_percent < bpos->samples[i].percent)
435 max_percent = bpos->samples[i].percent; 472 max_percent = bpos->samples[i].percent;
@@ -792,13 +829,14 @@ static int annotate_browser__run(struct annotate_browser *browser,
792 "q/ESC/CTRL+C Exit\n\n" 829 "q/ESC/CTRL+C Exit\n\n"
793 "ENTER Go to target\n" 830 "ENTER Go to target\n"
794 "ESC Exit\n" 831 "ESC Exit\n"
795 "H Cycle thru hottest instructions\n" 832 "H Go to hottest instruction\n"
833 "TAB/shift+TAB Cycle thru hottest instructions\n"
796 "j Toggle showing jump to target arrows\n" 834 "j Toggle showing jump to target arrows\n"
797 "J Toggle showing number of jump sources on targets\n" 835 "J Toggle showing number of jump sources on targets\n"
798 "n Search next string\n" 836 "n Search next string\n"
799 "o Toggle disassembler output/simplified view\n" 837 "o Toggle disassembler output/simplified view\n"
800 "s Toggle source code view\n" 838 "s Toggle source code view\n"
801 "t Toggle total period view\n" 839 "t Circulate percent, total period, samples view\n"
802 "/ Search string\n" 840 "/ Search string\n"
803 "k Toggle line numbers\n" 841 "k Toggle line numbers\n"
804 "r Run available scripts\n" 842 "r Run available scripts\n"
@@ -875,8 +913,13 @@ show_sup_ins:
875 } 913 }
876 continue; 914 continue;
877 case 't': 915 case 't':
878 annotate_browser__opts.show_total_period = 916 if (annotate_browser__opts.show_total_period) {
879 !annotate_browser__opts.show_total_period; 917 annotate_browser__opts.show_total_period = false;
918 annotate_browser__opts.show_nr_samples = true;
919 } else if (annotate_browser__opts.show_nr_samples)
920 annotate_browser__opts.show_nr_samples = false;
921 else
922 annotate_browser__opts.show_total_period = true;
880 annotate_browser__update_addr_width(browser); 923 annotate_browser__update_addr_width(browser);
881 continue; 924 continue;
882 case K_LEFT: 925 case K_LEFT:
@@ -899,9 +942,11 @@ out:
899int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 942int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
900 struct hist_browser_timer *hbt) 943 struct hist_browser_timer *hbt)
901{ 944{
902 /* Set default value for show_total_period. */ 945 /* Set default value for show_total_period and show_nr_samples */
903 annotate_browser__opts.show_total_period = 946 annotate_browser__opts.show_total_period =
904 symbol_conf.show_total_period; 947 symbol_conf.show_total_period;
948 annotate_browser__opts.show_nr_samples =
949 symbol_conf.show_nr_samples;
905 950
906 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 951 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt);
907} 952}
@@ -1074,7 +1119,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1074 } 1119 }
1075 1120
1076 err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 1121 err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
1077 sizeof_bdl, &browser.arch); 1122 sizeof_bdl, &browser.arch,
1123 perf_evsel__env_cpuid(evsel));
1078 if (err) { 1124 if (err) {
1079 char msg[BUFSIZ]; 1125 char msg[BUFSIZ];
1080 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 1126 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
@@ -1151,6 +1197,7 @@ static struct annotate_config {
1151 ANNOTATE_CFG(jump_arrows), 1197 ANNOTATE_CFG(jump_arrows),
1152 ANNOTATE_CFG(show_linenr), 1198 ANNOTATE_CFG(show_linenr),
1153 ANNOTATE_CFG(show_nr_jumps), 1199 ANNOTATE_CFG(show_nr_jumps),
1200 ANNOTATE_CFG(show_nr_samples),
1154 ANNOTATE_CFG(show_total_period), 1201 ANNOTATE_CFG(show_total_period),
1155 ANNOTATE_CFG(use_offset), 1202 ANNOTATE_CFG(use_offset),
1156}; 1203};
@@ -1170,7 +1217,7 @@ static int annotate__config(const char *var, const char *value,
1170 struct annotate_config *cfg; 1217 struct annotate_config *cfg;
1171 const char *name; 1218 const char *name;
1172 1219
1173 if (prefixcmp(var, "annotate.") != 0) 1220 if (!strstarts(var, "annotate."))
1174 return 0; 1221 return 0;
1175 1222
1176 name = var + 9; 1223 name = var + 9;
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 69f4570bd4f9..13dfb0a0bdeb 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -166,9 +166,6 @@ static struct inline_node *inline_node__create(struct map *map, u64 ip)
166 if (dso == NULL) 166 if (dso == NULL)
167 return NULL; 167 return NULL;
168 168
169 if (dso->kernel != DSO_TYPE_USER)
170 return NULL;
171
172 node = dso__parse_addr_inlines(dso, 169 node = dso__parse_addr_inlines(dso,
173 map__rip_2objdump(map, ip)); 170 map__rip_2objdump(map, ip));
174 171
@@ -934,12 +931,8 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
934 browser->show_dso); 931 browser->show_dso);
935 932
936 if (symbol_conf.show_branchflag_count) { 933 if (symbol_conf.show_branchflag_count) {
937 if (need_percent) 934 callchain_list_counts__printf_value(chain, NULL,
938 callchain_list_counts__printf_value(node, chain, NULL, 935 buf, sizeof(buf));
939 buf, sizeof(buf));
940 else
941 callchain_list_counts__printf_value(NULL, chain, NULL,
942 buf, sizeof(buf));
943 936
944 if (asprintf(&alloc_str2, "%s%s", str, buf) < 0) 937 if (asprintf(&alloc_str2, "%s%s", str, buf) < 0)
945 str = "Not enough memory!"; 938 str = "Not enough memory!";
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index d903fd493416..02176193f427 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -34,10 +34,10 @@ static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym,
34 return 0; 34 return 0;
35 35
36 symhist = annotation__histogram(symbol__annotation(sym), evidx); 36 symhist = annotation__histogram(symbol__annotation(sym), evidx);
37 if (!symbol_conf.event_group && !symhist->addr[dl->offset]) 37 if (!symbol_conf.event_group && !symhist->addr[dl->offset].nr_samples)
38 return 0; 38 return 0;
39 39
40 percent = 100.0 * symhist->addr[dl->offset] / symhist->sum; 40 percent = 100.0 * symhist->addr[dl->offset].nr_samples / symhist->nr_samples;
41 41
42 markup = perf_gtk__get_percent_color(percent); 42 markup = perf_gtk__get_percent_color(percent);
43 if (markup) 43 if (markup)
@@ -169,7 +169,7 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
169 return -1; 169 return -1;
170 170
171 err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 171 err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
172 0, NULL); 172 0, NULL, NULL);
173 if (err) { 173 if (err) {
174 char msg[BUFSIZ]; 174 char msg[BUFSIZ];
175 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 175 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c
index a0f24c7115c5..ae91c8148edf 100644
--- a/tools/perf/ui/progress.c
+++ b/tools/perf/ui/progress.c
@@ -1,3 +1,4 @@
1#include <linux/kernel.h>
1#include "../cache.h" 2#include "../cache.h"
2#include "progress.h" 3#include "progress.h"
3 4
@@ -14,10 +15,14 @@ struct ui_progress_ops *ui_progress__ops = &null_progress__ops;
14 15
15void ui_progress__update(struct ui_progress *p, u64 adv) 16void ui_progress__update(struct ui_progress *p, u64 adv)
16{ 17{
18 u64 last = p->curr;
19
17 p->curr += adv; 20 p->curr += adv;
18 21
19 if (p->curr >= p->next) { 22 if (p->curr >= p->next) {
20 p->next += p->step; 23 u64 nr = DIV_ROUND_UP(p->curr - last, p->step);
24
25 p->next += nr * p->step;
21 ui_progress__ops->update(p); 26 ui_progress__ops->update(p);
22 } 27 }
23} 28}
@@ -25,7 +30,7 @@ void ui_progress__update(struct ui_progress *p, u64 adv)
25void ui_progress__init(struct ui_progress *p, u64 total, const char *title) 30void ui_progress__init(struct ui_progress *p, u64 total, const char *title)
26{ 31{
27 p->curr = 0; 32 p->curr = 0;
28 p->next = p->step = total / 16; 33 p->next = p->step = total / 16 ?: 1;
29 p->total = total; 34 p->total = total;
30 p->title = title; 35 p->title = title;
31 36
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 42e432bd2eb4..8bdb7a500181 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -1,4 +1,5 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <linux/string.h>
2 3
3#include "../../util/util.h" 4#include "../../util/util.h"
4#include "../../util/hist.h" 5#include "../../util/hist.h"
@@ -35,9 +36,6 @@ static size_t inline__fprintf(struct map *map, u64 ip, int left_margin,
35 if (dso == NULL) 36 if (dso == NULL)
36 return 0; 37 return 0;
37 38
38 if (dso->kernel != DSO_TYPE_USER)
39 return 0;
40
41 node = dso__parse_addr_inlines(dso, 39 node = dso__parse_addr_inlines(dso,
42 map__rip_2objdump(map, ip)); 40 map__rip_2objdump(map, ip));
43 if (node == NULL) 41 if (node == NULL)
@@ -126,12 +124,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
126 str = callchain_list__sym_name(chain, bf, sizeof(bf), false); 124 str = callchain_list__sym_name(chain, bf, sizeof(bf), false);
127 125
128 if (symbol_conf.show_branchflag_count) { 126 if (symbol_conf.show_branchflag_count) {
129 if (!period) 127 callchain_list_counts__printf_value(chain, NULL,
130 callchain_list_counts__printf_value(node, chain, NULL, 128 buf, sizeof(buf));
131 buf, sizeof(buf));
132 else
133 callchain_list_counts__printf_value(NULL, chain, NULL,
134 buf, sizeof(buf));
135 129
136 if (asprintf(&alloc_str, "%s%s", str, buf) < 0) 130 if (asprintf(&alloc_str, "%s%s", str, buf) < 0)
137 str = "Not enough memory!"; 131 str = "Not enough memory!";
@@ -295,7 +289,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
295 * displayed twice. 289 * displayed twice.
296 */ 290 */
297 if (!i++ && field_order == NULL && 291 if (!i++ && field_order == NULL &&
298 sort_order && !prefixcmp(sort_order, "sym")) 292 sort_order && strstarts(sort_order, "sym"))
299 continue; 293 continue;
300 294
301 if (!printed) { 295 if (!printed) {
@@ -315,7 +309,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
315 309
316 if (symbol_conf.show_branchflag_count) 310 if (symbol_conf.show_branchflag_count)
317 ret += callchain_list_counts__printf_value( 311 ret += callchain_list_counts__printf_value(
318 NULL, chain, fp, NULL, 0); 312 chain, fp, NULL, 0);
319 ret += fprintf(fp, "\n"); 313 ret += fprintf(fp, "\n");
320 314
321 if (++entries_printed == callchain_param.print_limit) 315 if (++entries_printed == callchain_param.print_limit)
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 79dea95a7f68..94518c1bf8b6 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -22,6 +22,7 @@ libperf-y += rbtree.o
22libperf-y += libstring.o 22libperf-y += libstring.o
23libperf-y += bitmap.o 23libperf-y += bitmap.o
24libperf-y += hweight.o 24libperf-y += hweight.o
25libperf-y += smt.o
25libperf-y += quote.o 26libperf-y += quote.o
26libperf-y += strbuf.o 27libperf-y += strbuf.o
27libperf-y += string.o 28libperf-y += string.o
@@ -93,6 +94,7 @@ libperf-y += drv_configs.o
93libperf-y += units.o 94libperf-y += units.o
94libperf-y += time-utils.o 95libperf-y += time-utils.o
95libperf-y += expr-bison.o 96libperf-y += expr-bison.o
97libperf-y += branch.o
96 98
97libperf-$(CONFIG_LIBBPF) += bpf-loader.o 99libperf-$(CONFIG_LIBBPF) += bpf-loader.o
98libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o 100libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
@@ -104,6 +106,10 @@ ifndef CONFIG_LIBELF
104libperf-y += symbol-minimal.o 106libperf-y += symbol-minimal.o
105endif 107endif
106 108
109ifndef CONFIG_SETNS
110libperf-y += setns.o
111endif
112
107libperf-$(CONFIG_DWARF) += probe-finder.o 113libperf-$(CONFIG_DWARF) += probe-finder.o
108libperf-$(CONFIG_DWARF) += dwarf-aux.o 114libperf-$(CONFIG_DWARF) += dwarf-aux.o
109libperf-$(CONFIG_DWARF) += dwarf-regs.o 115libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index be1caabb9290..4397a8b6e6cd 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -47,7 +47,12 @@ struct arch {
47 bool sorted_instructions; 47 bool sorted_instructions;
48 bool initialized; 48 bool initialized;
49 void *priv; 49 void *priv;
50 unsigned int model;
51 unsigned int family;
50 int (*init)(struct arch *arch); 52 int (*init)(struct arch *arch);
53 bool (*ins_is_fused)(struct arch *arch, const char *ins1,
54 const char *ins2);
55 int (*cpuid_parse)(struct arch *arch, char *cpuid);
51 struct { 56 struct {
52 char comment_char; 57 char comment_char;
53 char skip_functions_char; 58 char skip_functions_char;
@@ -129,6 +134,8 @@ static struct arch architectures[] = {
129 .name = "x86", 134 .name = "x86",
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,
138 .cpuid_parse = x86__cpuid_parse,
132 .objdump = { 139 .objdump = {
133 .comment_char = '#', 140 .comment_char = '#',
134 }, 141 },
@@ -171,6 +178,14 @@ int ins__scnprintf(struct ins *ins, char *bf, size_t size,
171 return ins__raw_scnprintf(ins, bf, size, ops); 178 return ins__raw_scnprintf(ins, bf, size, ops);
172} 179}
173 180
181bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
182{
183 if (!arch || !arch->ins_is_fused)
184 return false;
185
186 return arch->ins_is_fused(arch, ins1, ins2);
187}
188
174static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map) 189static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map)
175{ 190{
176 char *endptr, *tok, *name; 191 char *endptr, *tok, *name;
@@ -502,6 +517,11 @@ bool ins__is_ret(const struct ins *ins)
502 return ins->ops == &ret_ops; 517 return ins->ops == &ret_ops;
503} 518}
504 519
520bool ins__is_lock(const struct ins *ins)
521{
522 return ins->ops == &lock_ops;
523}
524
505static int ins__key_cmp(const void *name, const void *insp) 525static int ins__key_cmp(const void *name, const void *insp)
506{ 526{
507 const struct ins *ins = insp; 527 const struct ins *ins = insp;
@@ -590,10 +610,10 @@ int symbol__alloc_hist(struct symbol *sym)
590 size_t sizeof_sym_hist; 610 size_t sizeof_sym_hist;
591 611
592 /* Check for overflow when calculating sizeof_sym_hist */ 612 /* Check for overflow when calculating sizeof_sym_hist */
593 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(u64)) 613 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(struct sym_hist_entry))
594 return -1; 614 return -1;
595 615
596 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64)); 616 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(struct sym_hist_entry));
597 617
598 /* Check for overflow in zalloc argument */ 618 /* Check for overflow in zalloc argument */
599 if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src)) 619 if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src))
@@ -677,7 +697,8 @@ static int __symbol__account_cycles(struct annotation *notes,
677} 697}
678 698
679static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, 699static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
680 struct annotation *notes, int evidx, u64 addr) 700 struct annotation *notes, int evidx, u64 addr,
701 struct perf_sample *sample)
681{ 702{
682 unsigned offset; 703 unsigned offset;
683 struct sym_hist *h; 704 struct sym_hist *h;
@@ -693,12 +714,15 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
693 714
694 offset = addr - sym->start; 715 offset = addr - sym->start;
695 h = annotation__histogram(notes, evidx); 716 h = annotation__histogram(notes, evidx);
696 h->sum++; 717 h->nr_samples++;
697 h->addr[offset]++; 718 h->addr[offset].nr_samples++;
719 h->period += sample->period;
720 h->addr[offset].period += sample->period;
698 721
699 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64 722 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
700 ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name, 723 ", evidx=%d] => nr_samples: %" PRIu64 ", period: %" PRIu64 "\n",
701 addr, addr - sym->start, evidx, h->addr[offset]); 724 sym->start, sym->name, addr, addr - sym->start, evidx,
725 h->addr[offset].nr_samples, h->addr[offset].period);
702 return 0; 726 return 0;
703} 727}
704 728
@@ -718,7 +742,8 @@ static struct annotation *symbol__get_annotation(struct symbol *sym, bool cycles
718} 742}
719 743
720static int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 744static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
721 int evidx, u64 addr) 745 int evidx, u64 addr,
746 struct perf_sample *sample)
722{ 747{
723 struct annotation *notes; 748 struct annotation *notes;
724 749
@@ -727,7 +752,7 @@ static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
727 notes = symbol__get_annotation(sym, false); 752 notes = symbol__get_annotation(sym, false);
728 if (notes == NULL) 753 if (notes == NULL)
729 return -ENOMEM; 754 return -ENOMEM;
730 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr); 755 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr, sample);
731} 756}
732 757
733static int symbol__account_cycles(u64 addr, u64 start, 758static int symbol__account_cycles(u64 addr, u64 start,
@@ -791,14 +816,16 @@ int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
791 return err; 816 return err;
792} 817}
793 818
794int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx) 819int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
820 int evidx)
795{ 821{
796 return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr); 822 return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr, sample);
797} 823}
798 824
799int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip) 825int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
826 int evidx, u64 ip)
800{ 827{
801 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); 828 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip, sample);
802} 829}
803 830
804static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map) 831static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map)
@@ -908,11 +935,12 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa
908} 935}
909 936
910double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset, 937double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
911 s64 end, const char **path, u64 *nr_samples) 938 s64 end, const char **path, struct sym_hist_entry *sample)
912{ 939{
913 struct source_line *src_line = notes->src->lines; 940 struct source_line *src_line = notes->src->lines;
914 double percent = 0.0; 941 double percent = 0.0;
915 *nr_samples = 0; 942
943 sample->nr_samples = sample->period = 0;
916 944
917 if (src_line) { 945 if (src_line) {
918 size_t sizeof_src_line = sizeof(*src_line) + 946 size_t sizeof_src_line = sizeof(*src_line) +
@@ -926,19 +954,24 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
926 *path = src_line->path; 954 *path = src_line->path;
927 955
928 percent += src_line->samples[evidx].percent; 956 percent += src_line->samples[evidx].percent;
929 *nr_samples += src_line->samples[evidx].nr; 957 sample->nr_samples += src_line->samples[evidx].nr;
930 offset++; 958 offset++;
931 } 959 }
932 } else { 960 } else {
933 struct sym_hist *h = annotation__histogram(notes, evidx); 961 struct sym_hist *h = annotation__histogram(notes, evidx);
934 unsigned int hits = 0; 962 unsigned int hits = 0;
963 u64 period = 0;
935 964
936 while (offset < end) 965 while (offset < end) {
937 hits += h->addr[offset++]; 966 hits += h->addr[offset].nr_samples;
967 period += h->addr[offset].period;
968 ++offset;
969 }
938 970
939 if (h->sum) { 971 if (h->nr_samples) {
940 *nr_samples = hits; 972 sample->period = period;
941 percent = 100.0 * hits / h->sum; 973 sample->nr_samples = hits;
974 percent = 100.0 * hits / h->nr_samples;
942 } 975 }
943 } 976 }
944 977
@@ -1037,10 +1070,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1037 1070
1038 if (dl->offset != -1) { 1071 if (dl->offset != -1) {
1039 const char *path = NULL; 1072 const char *path = NULL;
1040 u64 nr_samples;
1041 double percent, max_percent = 0.0; 1073 double percent, max_percent = 0.0;
1042 double *ppercents = &percent; 1074 double *ppercents = &percent;
1043 u64 *psamples = &nr_samples; 1075 struct sym_hist_entry sample;
1076 struct sym_hist_entry *psamples = &sample;
1044 int i, nr_percent = 1; 1077 int i, nr_percent = 1;
1045 const char *color; 1078 const char *color;
1046 struct annotation *notes = symbol__annotation(sym); 1079 struct annotation *notes = symbol__annotation(sym);
@@ -1054,7 +1087,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1054 if (perf_evsel__is_group_event(evsel)) { 1087 if (perf_evsel__is_group_event(evsel)) {
1055 nr_percent = evsel->nr_members; 1088 nr_percent = evsel->nr_members;
1056 ppercents = calloc(nr_percent, sizeof(double)); 1089 ppercents = calloc(nr_percent, sizeof(double));
1057 psamples = calloc(nr_percent, sizeof(u64)); 1090 psamples = calloc(nr_percent, sizeof(struct sym_hist_entry));
1058 if (ppercents == NULL || psamples == NULL) { 1091 if (ppercents == NULL || psamples == NULL) {
1059 return -1; 1092 return -1;
1060 } 1093 }
@@ -1065,10 +1098,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1065 notes->src->lines ? i : evsel->idx + i, 1098 notes->src->lines ? i : evsel->idx + i,
1066 offset, 1099 offset,
1067 next ? next->offset : (s64) len, 1100 next ? next->offset : (s64) len,
1068 &path, &nr_samples); 1101 &path, &sample);
1069 1102
1070 ppercents[i] = percent; 1103 ppercents[i] = percent;
1071 psamples[i] = nr_samples; 1104 psamples[i] = sample;
1072 if (percent > max_percent) 1105 if (percent > max_percent)
1073 max_percent = percent; 1106 max_percent = percent;
1074 } 1107 }
@@ -1106,12 +1139,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1106 1139
1107 for (i = 0; i < nr_percent; i++) { 1140 for (i = 0; i < nr_percent; i++) {
1108 percent = ppercents[i]; 1141 percent = ppercents[i];
1109 nr_samples = psamples[i]; 1142 sample = psamples[i];
1110 color = get_percent_color(percent); 1143 color = get_percent_color(percent);
1111 1144
1112 if (symbol_conf.show_total_period) 1145 if (symbol_conf.show_total_period)
1146 color_fprintf(stdout, color, " %11" PRIu64,
1147 sample.period);
1148 else if (symbol_conf.show_nr_samples)
1113 color_fprintf(stdout, color, " %7" PRIu64, 1149 color_fprintf(stdout, color, " %7" PRIu64,
1114 nr_samples); 1150 sample.nr_samples);
1115 else 1151 else
1116 color_fprintf(stdout, color, " %7.2f", percent); 1152 color_fprintf(stdout, color, " %7.2f", percent);
1117 } 1153 }
@@ -1127,13 +1163,13 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1127 if (ppercents != &percent) 1163 if (ppercents != &percent)
1128 free(ppercents); 1164 free(ppercents);
1129 1165
1130 if (psamples != &nr_samples) 1166 if (psamples != &sample)
1131 free(psamples); 1167 free(psamples);
1132 1168
1133 } else if (max_lines && printed >= max_lines) 1169 } else if (max_lines && printed >= max_lines)
1134 return 1; 1170 return 1;
1135 else { 1171 else {
1136 int width = 8; 1172 int width = symbol_conf.show_total_period ? 12 : 8;
1137 1173
1138 if (queue) 1174 if (queue)
1139 return -1; 1175 return -1;
@@ -1327,7 +1363,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
1327 !dso__is_kcore(dso)) 1363 !dso__is_kcore(dso))
1328 return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX; 1364 return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
1329 1365
1330 build_id_filename = dso__build_id_filename(dso, NULL, 0); 1366 build_id_filename = dso__build_id_filename(dso, NULL, 0, false);
1331 if (build_id_filename) { 1367 if (build_id_filename) {
1332 __symbol__join_symfs(filename, filename_size, build_id_filename); 1368 __symbol__join_symfs(filename, filename_size, build_id_filename);
1333 free(build_id_filename); 1369 free(build_id_filename);
@@ -1381,7 +1417,7 @@ static const char *annotate__norm_arch(const char *arch_name)
1381 1417
1382int symbol__disassemble(struct symbol *sym, struct map *map, 1418int symbol__disassemble(struct symbol *sym, struct map *map,
1383 const char *arch_name, size_t privsize, 1419 const char *arch_name, size_t privsize,
1384 struct arch **parch) 1420 struct arch **parch, char *cpuid)
1385{ 1421{
1386 struct dso *dso = map->dso; 1422 struct dso *dso = map->dso;
1387 char command[PATH_MAX * 2]; 1423 char command[PATH_MAX * 2];
@@ -1418,6 +1454,9 @@ int symbol__disassemble(struct symbol *sym, struct map *map,
1418 } 1454 }
1419 } 1455 }
1420 1456
1457 if (arch->cpuid_parse && cpuid)
1458 arch->cpuid_parse(arch, cpuid);
1459
1421 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__, 1460 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
1422 symfs_filename, sym->name, map->unmap_ip(map, sym->start), 1461 symfs_filename, sym->name, map->unmap_ip(map, sym->start),
1423 map->unmap_ip(map, sym->end)); 1462 map->unmap_ip(map, sym->end));
@@ -1648,19 +1687,19 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1648 struct sym_hist *h = annotation__histogram(notes, evidx); 1687 struct sym_hist *h = annotation__histogram(notes, evidx);
1649 struct rb_root tmp_root = RB_ROOT; 1688 struct rb_root tmp_root = RB_ROOT;
1650 int nr_pcnt = 1; 1689 int nr_pcnt = 1;
1651 u64 h_sum = h->sum; 1690 u64 nr_samples = h->nr_samples;
1652 size_t sizeof_src_line = sizeof(struct source_line); 1691 size_t sizeof_src_line = sizeof(struct source_line);
1653 1692
1654 if (perf_evsel__is_group_event(evsel)) { 1693 if (perf_evsel__is_group_event(evsel)) {
1655 for (i = 1; i < evsel->nr_members; i++) { 1694 for (i = 1; i < evsel->nr_members; i++) {
1656 h = annotation__histogram(notes, evidx + i); 1695 h = annotation__histogram(notes, evidx + i);
1657 h_sum += h->sum; 1696 nr_samples += h->nr_samples;
1658 } 1697 }
1659 nr_pcnt = evsel->nr_members; 1698 nr_pcnt = evsel->nr_members;
1660 sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples); 1699 sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples);
1661 } 1700 }
1662 1701
1663 if (!h_sum) 1702 if (!nr_samples)
1664 return 0; 1703 return 0;
1665 1704
1666 src_line = notes->src->lines = calloc(len, sizeof_src_line); 1705 src_line = notes->src->lines = calloc(len, sizeof_src_line);
@@ -1670,7 +1709,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1670 start = map__rip_2objdump(map, sym->start); 1709 start = map__rip_2objdump(map, sym->start);
1671 1710
1672 for (i = 0; i < len; i++) { 1711 for (i = 0; i < len; i++) {
1673 u64 offset, nr_samples; 1712 u64 offset;
1674 double percent_max = 0.0; 1713 double percent_max = 0.0;
1675 1714
1676 src_line->nr_pcnt = nr_pcnt; 1715 src_line->nr_pcnt = nr_pcnt;
@@ -1679,9 +1718,9 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1679 double percent = 0.0; 1718 double percent = 0.0;
1680 1719
1681 h = annotation__histogram(notes, evidx + k); 1720 h = annotation__histogram(notes, evidx + k);
1682 nr_samples = h->addr[i]; 1721 nr_samples = h->addr[i].nr_samples;
1683 if (h->sum) 1722 if (h->nr_samples)
1684 percent = 100.0 * nr_samples / h->sum; 1723 percent = 100.0 * nr_samples / h->nr_samples;
1685 1724
1686 if (percent > percent_max) 1725 if (percent > percent_max)
1687 percent_max = percent; 1726 percent_max = percent;
@@ -1750,10 +1789,10 @@ static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
1750 u64 len = symbol__size(sym), offset; 1789 u64 len = symbol__size(sym), offset;
1751 1790
1752 for (offset = 0; offset < len; ++offset) 1791 for (offset = 0; offset < len; ++offset)
1753 if (h->addr[offset] != 0) 1792 if (h->addr[offset].nr_samples != 0)
1754 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2, 1793 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
1755 sym->start + offset, h->addr[offset]); 1794 sym->start + offset, h->addr[offset].nr_samples);
1756 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum); 1795 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->nr_samples", h->nr_samples);
1757} 1796}
1758 1797
1759int symbol__annotate_printf(struct symbol *sym, struct map *map, 1798int symbol__annotate_printf(struct symbol *sym, struct map *map,
@@ -1771,7 +1810,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1771 int printed = 2, queue_len = 0; 1810 int printed = 2, queue_len = 0;
1772 int more = 0; 1811 int more = 0;
1773 u64 len; 1812 u64 len;
1774 int width = 8; 1813 int width = symbol_conf.show_total_period ? 12 : 8;
1775 int graph_dotted_len; 1814 int graph_dotted_len;
1776 1815
1777 filename = strdup(dso->long_name); 1816 filename = strdup(dso->long_name);
@@ -1789,7 +1828,9 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1789 width *= evsel->nr_members; 1828 width *= evsel->nr_members;
1790 1829
1791 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n", 1830 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); 1831 width, width, symbol_conf.show_total_period ? "Period" :
1832 symbol_conf.show_nr_samples ? "Samples" : "Percent",
1833 d_filename, evsel_name, h->nr_samples);
1793 1834
1794 printf("%-*.*s----\n", 1835 printf("%-*.*s----\n",
1795 graph_dotted_len, graph_dotted_len, graph_dotted_line); 1836 graph_dotted_len, graph_dotted_len, graph_dotted_line);
@@ -1853,10 +1894,10 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
1853 struct sym_hist *h = annotation__histogram(notes, evidx); 1894 struct sym_hist *h = annotation__histogram(notes, evidx);
1854 int len = symbol__size(sym), offset; 1895 int len = symbol__size(sym), offset;
1855 1896
1856 h->sum = 0; 1897 h->nr_samples = 0;
1857 for (offset = 0; offset < len; ++offset) { 1898 for (offset = 0; offset < len; ++offset) {
1858 h->addr[offset] = h->addr[offset] * 7 / 8; 1899 h->addr[offset].nr_samples = h->addr[offset].nr_samples * 7 / 8;
1859 h->sum += h->addr[offset]; 1900 h->nr_samples += h->addr[offset].nr_samples;
1860 } 1901 }
1861} 1902}
1862 1903
@@ -1907,7 +1948,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1907 u64 len; 1948 u64 len;
1908 1949
1909 if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 1950 if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
1910 0, NULL) < 0) 1951 0, NULL, NULL) < 0)
1911 return -1; 1952 return -1;
1912 1953
1913 len = symbol__size(sym); 1954 len = symbol__size(sym);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 21055034aedd..9ce575c25fd9 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -52,7 +52,9 @@ struct ins_ops {
52bool ins__is_jump(const struct ins *ins); 52bool ins__is_jump(const struct ins *ins);
53bool ins__is_call(const struct ins *ins); 53bool ins__is_call(const struct ins *ins);
54bool ins__is_ret(const struct ins *ins); 54bool ins__is_ret(const struct ins *ins);
55bool ins__is_lock(const struct ins *ins);
55int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops); 56int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops);
57bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);
56 58
57struct annotation; 59struct annotation;
58 60
@@ -72,16 +74,22 @@ static inline bool disasm_line__has_offset(const struct disasm_line *dl)
72 return dl->ops.target.offset_avail; 74 return dl->ops.target.offset_avail;
73} 75}
74 76
77struct sym_hist_entry {
78 u64 nr_samples;
79 u64 period;
80};
81
75void disasm_line__free(struct disasm_line *dl); 82void disasm_line__free(struct disasm_line *dl);
76struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos); 83struct 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); 84int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
78size_t disasm__fprintf(struct list_head *head, FILE *fp); 85size_t disasm__fprintf(struct list_head *head, FILE *fp);
79double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset, 86double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
80 s64 end, const char **path, u64 *nr_samples); 87 s64 end, const char **path, struct sym_hist_entry *sample);
81 88
82struct sym_hist { 89struct sym_hist {
83 u64 sum; 90 u64 nr_samples;
84 u64 addr[0]; 91 u64 period;
92 struct sym_hist_entry addr[0];
85}; 93};
86 94
87struct cyc_hist { 95struct cyc_hist {
@@ -147,20 +155,22 @@ static inline struct annotation *symbol__annotation(struct symbol *sym)
147 return (void *)sym - symbol_conf.priv_size; 155 return (void *)sym - symbol_conf.priv_size;
148} 156}
149 157
150int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx); 158int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
159 int evidx);
151 160
152int addr_map_symbol__account_cycles(struct addr_map_symbol *ams, 161int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
153 struct addr_map_symbol *start, 162 struct addr_map_symbol *start,
154 unsigned cycles); 163 unsigned cycles);
155 164
156int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); 165int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
166 int evidx, u64 addr);
157 167
158int symbol__alloc_hist(struct symbol *sym); 168int symbol__alloc_hist(struct symbol *sym);
159void symbol__annotate_zero_histograms(struct symbol *sym); 169void symbol__annotate_zero_histograms(struct symbol *sym);
160 170
161int symbol__disassemble(struct symbol *sym, struct map *map, 171int symbol__disassemble(struct symbol *sym, struct map *map,
162 const char *arch_name, size_t privsize, 172 const char *arch_name, size_t privsize,
163 struct arch **parch); 173 struct arch **parch, char *cpuid);
164 174
165enum symbol_disassemble_errno { 175enum symbol_disassemble_errno {
166 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, 176 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 4bd2d1d882af..4a1264c66101 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -1246,7 +1246,7 @@ int bpf__config_obj(struct bpf_object *obj,
1246 if (!obj || !term || !term->config) 1246 if (!obj || !term || !term->config)
1247 return -EINVAL; 1247 return -EINVAL;
1248 1248
1249 if (!prefixcmp(term->config, "map:")) { 1249 if (strstarts(term->config, "map:")) {
1250 key_scan_pos = sizeof("map:") - 1; 1250 key_scan_pos = sizeof("map:") - 1;
1251 err = bpf__obj_config_map(obj, term, evlist, &key_scan_pos); 1251 err = bpf__obj_config_map(obj, term, evlist, &key_scan_pos);
1252 goto out; 1252 goto out;
diff --git a/tools/perf/util/bpf-prologue.c b/tools/perf/util/bpf-prologue.c
index 1356220a9f1b..827f9140f3b8 100644
--- a/tools/perf/util/bpf-prologue.c
+++ b/tools/perf/util/bpf-prologue.c
@@ -58,6 +58,46 @@ check_pos(struct bpf_insn_pos *pos)
58 return 0; 58 return 0;
59} 59}
60 60
61/*
62 * Convert type string (u8/u16/u32/u64/s8/s16/s32/s64 ..., see
63 * Documentation/trace/kprobetrace.txt) to size field of BPF_LDX_MEM
64 * instruction (BPF_{B,H,W,DW}).
65 */
66static int
67argtype_to_ldx_size(const char *type)
68{
69 int arg_size = type ? atoi(&type[1]) : 64;
70
71 switch (arg_size) {
72 case 8:
73 return BPF_B;
74 case 16:
75 return BPF_H;
76 case 32:
77 return BPF_W;
78 case 64:
79 default:
80 return BPF_DW;
81 }
82}
83
84static const char *
85insn_sz_to_str(int insn_sz)
86{
87 switch (insn_sz) {
88 case BPF_B:
89 return "BPF_B";
90 case BPF_H:
91 return "BPF_H";
92 case BPF_W:
93 return "BPF_W";
94 case BPF_DW:
95 return "BPF_DW";
96 default:
97 return "UNKNOWN";
98 }
99}
100
61/* Give it a shorter name */ 101/* Give it a shorter name */
62#define ins(i, p) append_insn((i), (p)) 102#define ins(i, p) append_insn((i), (p))
63 103
@@ -258,9 +298,14 @@ gen_prologue_slowpath(struct bpf_insn_pos *pos,
258 } 298 }
259 299
260 /* Final pass: read to registers */ 300 /* Final pass: read to registers */
261 for (i = 0; i < nargs; i++) 301 for (i = 0; i < nargs; i++) {
262 ins(BPF_LDX_MEM(BPF_DW, BPF_PROLOGUE_START_ARG_REG + i, 302 int insn_sz = (args[i].ref) ? argtype_to_ldx_size(args[i].type) : BPF_DW;
303
304 pr_debug("prologue: load arg %d, insn_sz is %s\n",
305 i, insn_sz_to_str(insn_sz));
306 ins(BPF_LDX_MEM(insn_sz, BPF_PROLOGUE_START_ARG_REG + i,
263 BPF_REG_FP, -BPF_REG_SIZE * (i + 1)), pos); 307 BPF_REG_FP, -BPF_REG_SIZE * (i + 1)), pos);
308 }
264 309
265 ins(BPF_JMP_IMM(BPF_JA, BPF_REG_0, 0, JMP_TO_SUCCESS_CODE), pos); 310 ins(BPF_JMP_IMM(BPF_JA, BPF_REG_0, 0, JMP_TO_SUCCESS_CODE), pos);
266 311
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..c1a06fcd7e70 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -243,12 +243,15 @@ static bool build_id_cache__valid_id(char *sbuild_id)
243 return result; 243 return result;
244} 244}
245 245
246static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso) 246static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso,
247 bool is_debug)
247{ 248{
248 return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf"); 249 return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : (is_debug ?
250 "debug" : "elf"));
249} 251}
250 252
251char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) 253char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size,
254 bool is_debug)
252{ 255{
253 bool is_kallsyms = dso__is_kallsyms((struct dso *)dso); 256 bool is_kallsyms = dso__is_kallsyms((struct dso *)dso);
254 bool is_vdso = dso__is_vdso((struct dso *)dso); 257 bool is_vdso = dso__is_vdso((struct dso *)dso);
@@ -270,7 +273,8 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
270 ret = asnprintf(&bf, size, "%s", linkname); 273 ret = asnprintf(&bf, size, "%s", linkname);
271 else 274 else
272 ret = asnprintf(&bf, size, "%s/%s", linkname, 275 ret = asnprintf(&bf, size, "%s/%s", linkname,
273 build_id_cache__basename(is_kallsyms, is_vdso)); 276 build_id_cache__basename(is_kallsyms, is_vdso,
277 is_debug));
274 if (ret < 0 || (!alloc && size < (unsigned int)ret)) 278 if (ret < 0 || (!alloc && size < (unsigned int)ret))
275 bf = NULL; 279 bf = NULL;
276 free(linkname); 280 free(linkname);
@@ -285,7 +289,7 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
285 else 289 else
286 290
287static int write_buildid(const char *name, size_t name_len, u8 *build_id, 291static int write_buildid(const char *name, size_t name_len, u8 *build_id,
288 pid_t pid, u16 misc, int fd) 292 pid_t pid, u16 misc, struct feat_fd *fd)
289{ 293{
290 int err; 294 int err;
291 struct build_id_event b; 295 struct build_id_event b;
@@ -300,14 +304,15 @@ static int write_buildid(const char *name, size_t name_len, u8 *build_id,
300 b.header.misc = misc; 304 b.header.misc = misc;
301 b.header.size = sizeof(b) + len; 305 b.header.size = sizeof(b) + len;
302 306
303 err = writen(fd, &b, sizeof(b)); 307 err = do_write(fd, &b, sizeof(b));
304 if (err < 0) 308 if (err < 0)
305 return err; 309 return err;
306 310
307 return write_padded(fd, name, name_len + 1, len); 311 return write_padded(fd, name, name_len + 1, len);
308} 312}
309 313
310static int machine__write_buildid_table(struct machine *machine, int fd) 314static int machine__write_buildid_table(struct machine *machine,
315 struct feat_fd *fd)
311{ 316{
312 int err = 0; 317 int err = 0;
313 char nm[PATH_MAX]; 318 char nm[PATH_MAX];
@@ -352,7 +357,8 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
352 return err; 357 return err;
353} 358}
354 359
355int perf_session__write_buildid_table(struct perf_session *session, int fd) 360int perf_session__write_buildid_table(struct perf_session *session,
361 struct feat_fd *fd)
356{ 362{
357 struct rb_node *nd; 363 struct rb_node *nd;
358 int err = machine__write_buildid_table(&session->machines.host, fd); 364 int err = machine__write_buildid_table(&session->machines.host, fd);
@@ -534,13 +540,14 @@ char *build_id_cache__complement(const char *incomplete_sbuild_id)
534} 540}
535 541
536char *build_id_cache__cachedir(const char *sbuild_id, const char *name, 542char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
537 bool is_kallsyms, bool is_vdso) 543 struct nsinfo *nsi, bool is_kallsyms,
544 bool is_vdso)
538{ 545{
539 char *realname = (char *)name, *filename; 546 char *realname = (char *)name, *filename;
540 bool slash = is_kallsyms || is_vdso; 547 bool slash = is_kallsyms || is_vdso;
541 548
542 if (!slash) { 549 if (!slash) {
543 realname = realpath(name, NULL); 550 realname = nsinfo__realpath(name, nsi);
544 if (!realname) 551 if (!realname)
545 return NULL; 552 return NULL;
546 } 553 }
@@ -556,13 +563,13 @@ char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
556 return filename; 563 return filename;
557} 564}
558 565
559int build_id_cache__list_build_ids(const char *pathname, 566int build_id_cache__list_build_ids(const char *pathname, struct nsinfo *nsi,
560 struct strlist **result) 567 struct strlist **result)
561{ 568{
562 char *dir_name; 569 char *dir_name;
563 int ret = 0; 570 int ret = 0;
564 571
565 dir_name = build_id_cache__cachedir(NULL, pathname, false, false); 572 dir_name = build_id_cache__cachedir(NULL, pathname, nsi, false, false);
566 if (!dir_name) 573 if (!dir_name)
567 return -ENOMEM; 574 return -ENOMEM;
568 575
@@ -576,16 +583,20 @@ int build_id_cache__list_build_ids(const char *pathname,
576 583
577#if defined(HAVE_LIBELF_SUPPORT) && defined(HAVE_GELF_GETNOTE_SUPPORT) 584#if defined(HAVE_LIBELF_SUPPORT) && defined(HAVE_GELF_GETNOTE_SUPPORT)
578static int build_id_cache__add_sdt_cache(const char *sbuild_id, 585static int build_id_cache__add_sdt_cache(const char *sbuild_id,
579 const char *realname) 586 const char *realname,
587 struct nsinfo *nsi)
580{ 588{
581 struct probe_cache *cache; 589 struct probe_cache *cache;
582 int ret; 590 int ret;
591 struct nscookie nsc;
583 592
584 cache = probe_cache__new(sbuild_id); 593 cache = probe_cache__new(sbuild_id, nsi);
585 if (!cache) 594 if (!cache)
586 return -1; 595 return -1;
587 596
597 nsinfo__mountns_enter(nsi, &nsc);
588 ret = probe_cache__scan_sdt(cache, realname); 598 ret = probe_cache__scan_sdt(cache, realname);
599 nsinfo__mountns_exit(&nsc);
589 if (ret >= 0) { 600 if (ret >= 0) {
590 pr_debug4("Found %d SDTs in %s\n", ret, realname); 601 pr_debug4("Found %d SDTs in %s\n", ret, realname);
591 if (probe_cache__commit(cache) < 0) 602 if (probe_cache__commit(cache) < 0)
@@ -595,25 +606,56 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id,
595 return ret; 606 return ret;
596} 607}
597#else 608#else
598#define build_id_cache__add_sdt_cache(sbuild_id, realname) (0) 609#define build_id_cache__add_sdt_cache(sbuild_id, realname, nsi) (0)
599#endif 610#endif
600 611
612static char *build_id_cache__find_debug(const char *sbuild_id,
613 struct nsinfo *nsi)
614{
615 char *realname = NULL;
616 char *debugfile;
617 struct nscookie nsc;
618 size_t len = 0;
619
620 debugfile = calloc(1, PATH_MAX);
621 if (!debugfile)
622 goto out;
623
624 len = __symbol__join_symfs(debugfile, PATH_MAX,
625 "/usr/lib/debug/.build-id/");
626 snprintf(debugfile + len, PATH_MAX - len, "%.2s/%s.debug", sbuild_id,
627 sbuild_id + 2);
628
629 nsinfo__mountns_enter(nsi, &nsc);
630 realname = realpath(debugfile, NULL);
631 if (realname && access(realname, R_OK))
632 zfree(&realname);
633 nsinfo__mountns_exit(&nsc);
634out:
635 free(debugfile);
636 return realname;
637}
638
601int build_id_cache__add_s(const char *sbuild_id, const char *name, 639int build_id_cache__add_s(const char *sbuild_id, const char *name,
602 bool is_kallsyms, bool is_vdso) 640 struct nsinfo *nsi, bool is_kallsyms, bool is_vdso)
603{ 641{
604 const size_t size = PATH_MAX; 642 const size_t size = PATH_MAX;
605 char *realname = NULL, *filename = NULL, *dir_name = NULL, 643 char *realname = NULL, *filename = NULL, *dir_name = NULL,
606 *linkname = zalloc(size), *tmp; 644 *linkname = zalloc(size), *tmp;
645 char *debugfile = NULL;
607 int err = -1; 646 int err = -1;
608 647
609 if (!is_kallsyms) { 648 if (!is_kallsyms) {
610 realname = realpath(name, NULL); 649 if (!is_vdso)
650 realname = nsinfo__realpath(name, nsi);
651 else
652 realname = realpath(name, NULL);
611 if (!realname) 653 if (!realname)
612 goto out_free; 654 goto out_free;
613 } 655 }
614 656
615 dir_name = build_id_cache__cachedir(sbuild_id, name, 657 dir_name = build_id_cache__cachedir(sbuild_id, name, nsi, is_kallsyms,
616 is_kallsyms, is_vdso); 658 is_vdso);
617 if (!dir_name) 659 if (!dir_name)
618 goto out_free; 660 goto out_free;
619 661
@@ -627,20 +669,52 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
627 669
628 /* Save the allocated buildid dirname */ 670 /* Save the allocated buildid dirname */
629 if (asprintf(&filename, "%s/%s", dir_name, 671 if (asprintf(&filename, "%s/%s", dir_name,
630 build_id_cache__basename(is_kallsyms, is_vdso)) < 0) { 672 build_id_cache__basename(is_kallsyms, is_vdso,
673 false)) < 0) {
631 filename = NULL; 674 filename = NULL;
632 goto out_free; 675 goto out_free;
633 } 676 }
634 677
635 if (access(filename, F_OK)) { 678 if (access(filename, F_OK)) {
636 if (is_kallsyms) { 679 if (is_kallsyms) {
637 if (copyfile("/proc/kallsyms", filename)) 680 if (copyfile("/proc/kallsyms", filename))
681 goto out_free;
682 } else if (nsi && nsi->need_setns) {
683 if (copyfile_ns(name, filename, nsi))
638 goto out_free; 684 goto out_free;
639 } else if (link(realname, filename) && errno != EEXIST && 685 } else if (link(realname, filename) && errno != EEXIST &&
640 copyfile(name, filename)) 686 copyfile(name, filename))
641 goto out_free; 687 goto out_free;
642 } 688 }
643 689
690 /* Some binaries are stripped, but have .debug files with their symbol
691 * table. Check to see if we can locate one of those, since the elf
692 * file itself may not be very useful to users of our tools without a
693 * symtab.
694 */
695 if (!is_kallsyms && !is_vdso &&
696 strncmp(".ko", name + strlen(name) - 3, 3)) {
697 debugfile = build_id_cache__find_debug(sbuild_id, nsi);
698 if (debugfile) {
699 zfree(&filename);
700 if (asprintf(&filename, "%s/%s", dir_name,
701 build_id_cache__basename(false, false, true)) < 0) {
702 filename = NULL;
703 goto out_free;
704 }
705 if (access(filename, F_OK)) {
706 if (nsi && nsi->need_setns) {
707 if (copyfile_ns(debugfile, filename,
708 nsi))
709 goto out_free;
710 } else if (link(debugfile, filename) &&
711 errno != EEXIST &&
712 copyfile(debugfile, filename))
713 goto out_free;
714 }
715 }
716 }
717
644 if (!build_id_cache__linkname(sbuild_id, linkname, size)) 718 if (!build_id_cache__linkname(sbuild_id, linkname, size))
645 goto out_free; 719 goto out_free;
646 tmp = strrchr(linkname, '/'); 720 tmp = strrchr(linkname, '/');
@@ -657,27 +731,30 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
657 err = 0; 731 err = 0;
658 732
659 /* Update SDT cache : error is just warned */ 733 /* Update SDT cache : error is just warned */
660 if (realname && build_id_cache__add_sdt_cache(sbuild_id, realname) < 0) 734 if (realname &&
735 build_id_cache__add_sdt_cache(sbuild_id, realname, nsi) < 0)
661 pr_debug4("Failed to update/scan SDT cache for %s\n", realname); 736 pr_debug4("Failed to update/scan SDT cache for %s\n", realname);
662 737
663out_free: 738out_free:
664 if (!is_kallsyms) 739 if (!is_kallsyms)
665 free(realname); 740 free(realname);
666 free(filename); 741 free(filename);
742 free(debugfile);
667 free(dir_name); 743 free(dir_name);
668 free(linkname); 744 free(linkname);
669 return err; 745 return err;
670} 746}
671 747
672static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, 748static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
673 const char *name, bool is_kallsyms, 749 const char *name, struct nsinfo *nsi,
674 bool is_vdso) 750 bool is_kallsyms, bool is_vdso)
675{ 751{
676 char sbuild_id[SBUILD_ID_SIZE]; 752 char sbuild_id[SBUILD_ID_SIZE];
677 753
678 build_id__sprintf(build_id, build_id_size, sbuild_id); 754 build_id__sprintf(build_id, build_id_size, sbuild_id);
679 755
680 return build_id_cache__add_s(sbuild_id, name, is_kallsyms, is_vdso); 756 return build_id_cache__add_s(sbuild_id, name, nsi, is_kallsyms,
757 is_vdso);
681} 758}
682 759
683bool build_id_cache__cached(const char *sbuild_id) 760bool build_id_cache__cached(const char *sbuild_id)
@@ -743,7 +820,7 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine)
743 name = nm; 820 name = nm;
744 } 821 }
745 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, 822 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
746 is_kallsyms, is_vdso); 823 dso->nsinfo, is_kallsyms, is_vdso);
747} 824}
748 825
749static int __dsos__cache_build_ids(struct list_head *head, 826static 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..c94b0dcbfd74 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -5,10 +5,12 @@
5#define SBUILD_ID_SIZE (BUILD_ID_SIZE * 2 + 1) 5#define SBUILD_ID_SIZE (BUILD_ID_SIZE * 2 + 1)
6 6
7#include "tool.h" 7#include "tool.h"
8#include "namespaces.h"
8#include <linux/types.h> 9#include <linux/types.h>
9 10
10extern struct perf_tool build_id__mark_dso_hit_ops; 11extern struct perf_tool build_id__mark_dso_hit_ops;
11struct dso; 12struct dso;
13struct feat_fd;
12 14
13int build_id__sprintf(const u8 *build_id, int len, char *bf); 15int build_id__sprintf(const u8 *build_id, int len, char *bf);
14int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id); 16int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id);
@@ -16,7 +18,8 @@ int filename__sprintf_build_id(const char *pathname, char *sbuild_id);
16char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf, 18char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
17 size_t size); 19 size_t size);
18 20
19char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); 21char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size,
22 bool is_debug);
20 23
21int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, 24int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
22 struct perf_sample *sample, struct perf_evsel *evsel, 25 struct perf_sample *sample, struct perf_evsel *evsel,
@@ -25,23 +28,26 @@ int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
25int dsos__hit_all(struct perf_session *session); 28int dsos__hit_all(struct perf_session *session);
26 29
27bool perf_session__read_build_ids(struct perf_session *session, bool with_hits); 30bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
28int perf_session__write_buildid_table(struct perf_session *session, int fd); 31int perf_session__write_buildid_table(struct perf_session *session,
32 struct feat_fd *fd);
29int perf_session__cache_build_ids(struct perf_session *session); 33int perf_session__cache_build_ids(struct perf_session *session);
30 34
31char *build_id_cache__origname(const char *sbuild_id); 35char *build_id_cache__origname(const char *sbuild_id);
32char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size); 36char *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, 37char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
34 bool is_kallsyms, bool is_vdso); 38 struct nsinfo *nsi, bool is_kallsyms,
39 bool is_vdso);
35 40
36struct strlist; 41struct strlist;
37 42
38struct strlist *build_id_cache__list_all(bool validonly); 43struct strlist *build_id_cache__list_all(bool validonly);
39char *build_id_cache__complement(const char *incomplete_sbuild_id); 44char *build_id_cache__complement(const char *incomplete_sbuild_id);
40int build_id_cache__list_build_ids(const char *pathname, 45int build_id_cache__list_build_ids(const char *pathname, struct nsinfo *nsi,
41 struct strlist **result); 46 struct strlist **result);
42bool build_id_cache__cached(const char *sbuild_id); 47bool build_id_cache__cached(const char *sbuild_id);
43int build_id_cache__add_s(const char *sbuild_id, 48int build_id_cache__add_s(const char *sbuild_id,
44 const char *name, bool is_kallsyms, bool is_vdso); 49 const char *name, struct nsinfo *nsi,
50 bool is_kallsyms, bool is_vdso);
45int build_id_cache__remove_s(const char *sbuild_id); 51int build_id_cache__remove_s(const char *sbuild_id);
46 52
47extern char buildid_dir[]; 53extern char buildid_dir[];
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index b4204b43ed58..510b513e0f01 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -23,6 +23,7 @@
23#include "sort.h" 23#include "sort.h"
24#include "machine.h" 24#include "machine.h"
25#include "callchain.h" 25#include "callchain.h"
26#include "branch.h"
26 27
27#define CALLCHAIN_PARAM_DEFAULT \ 28#define CALLCHAIN_PARAM_DEFAULT \
28 .mode = CHAIN_GRAPH_ABS, \ 29 .mode = CHAIN_GRAPH_ABS, \
@@ -303,7 +304,7 @@ int perf_callchain_config(const char *var, const char *value)
303{ 304{
304 char *endptr; 305 char *endptr;
305 306
306 if (prefixcmp(var, "call-graph.")) 307 if (!strstarts(var, "call-graph."))
307 return 0; 308 return 0;
308 var += sizeof("call-graph.") - 1; 309 var += sizeof("call-graph.") - 1;
309 310
@@ -562,15 +563,33 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
562 if (cursor_node->branch) { 563 if (cursor_node->branch) {
563 call->branch_count = 1; 564 call->branch_count = 1;
564 565
565 if (cursor_node->branch_flags.predicted) 566 if (cursor_node->branch_from) {
566 call->predicted_count = 1; 567 /*
567 568 * branch_from is set with value somewhere else
568 if (cursor_node->branch_flags.abort) 569 * to imply it's "to" of a branch.
569 call->abort_count = 1; 570 */
570 571 call->brtype_stat.branch_to = true;
571 call->cycles_count = cursor_node->branch_flags.cycles; 572
572 call->iter_count = cursor_node->nr_loop_iter; 573 if (cursor_node->branch_flags.predicted)
573 call->samples_count = cursor_node->samples; 574 call->predicted_count = 1;
575
576 if (cursor_node->branch_flags.abort)
577 call->abort_count = 1;
578
579 branch_type_count(&call->brtype_stat,
580 &cursor_node->branch_flags,
581 cursor_node->branch_from,
582 cursor_node->ip);
583 } else {
584 /*
585 * It's "from" of a branch
586 */
587 call->brtype_stat.branch_to = false;
588 call->cycles_count =
589 cursor_node->branch_flags.cycles;
590 call->iter_count = cursor_node->nr_loop_iter;
591 call->iter_cycles = cursor_node->iter_cycles;
592 }
574 } 593 }
575 594
576 list_add_tail(&call->list, &node->val); 595 list_add_tail(&call->list, &node->val);
@@ -679,15 +698,32 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
679 if (node->branch) { 698 if (node->branch) {
680 cnode->branch_count++; 699 cnode->branch_count++;
681 700
682 if (node->branch_flags.predicted) 701 if (node->branch_from) {
683 cnode->predicted_count++; 702 /*
684 703 * It's "to" of a branch
685 if (node->branch_flags.abort) 704 */
686 cnode->abort_count++; 705 cnode->brtype_stat.branch_to = true;
687 706
688 cnode->cycles_count += node->branch_flags.cycles; 707 if (node->branch_flags.predicted)
689 cnode->iter_count += node->nr_loop_iter; 708 cnode->predicted_count++;
690 cnode->samples_count += node->samples; 709
710 if (node->branch_flags.abort)
711 cnode->abort_count++;
712
713 branch_type_count(&cnode->brtype_stat,
714 &node->branch_flags,
715 node->branch_from,
716 node->ip);
717 } else {
718 /*
719 * It's "from" of a branch
720 */
721 cnode->brtype_stat.branch_to = false;
722 cnode->cycles_count +=
723 node->branch_flags.cycles;
724 cnode->iter_count += node->nr_loop_iter;
725 cnode->iter_cycles += node->iter_cycles;
726 }
691 } 727 }
692 728
693 return MATCH_EQ; 729 return MATCH_EQ;
@@ -922,7 +958,7 @@ merge_chain_branch(struct callchain_cursor *cursor,
922 list_for_each_entry_safe(list, next_list, &src->val, list) { 958 list_for_each_entry_safe(list, next_list, &src->val, list) {
923 callchain_cursor_append(cursor, list->ip, 959 callchain_cursor_append(cursor, list->ip,
924 list->ms.map, list->ms.sym, 960 list->ms.map, list->ms.sym,
925 false, NULL, 0, 0); 961 false, NULL, 0, 0, 0);
926 list_del(&list->list); 962 list_del(&list->list);
927 map__zput(list->ms.map); 963 map__zput(list->ms.map);
928 free(list); 964 free(list);
@@ -962,7 +998,7 @@ int callchain_merge(struct callchain_cursor *cursor,
962int callchain_cursor_append(struct callchain_cursor *cursor, 998int callchain_cursor_append(struct callchain_cursor *cursor,
963 u64 ip, struct map *map, struct symbol *sym, 999 u64 ip, struct map *map, struct symbol *sym,
964 bool branch, struct branch_flags *flags, 1000 bool branch, struct branch_flags *flags,
965 int nr_loop_iter, int samples) 1001 int nr_loop_iter, u64 iter_cycles, u64 branch_from)
966{ 1002{
967 struct callchain_cursor_node *node = *cursor->last; 1003 struct callchain_cursor_node *node = *cursor->last;
968 1004
@@ -980,12 +1016,13 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
980 node->sym = sym; 1016 node->sym = sym;
981 node->branch = branch; 1017 node->branch = branch;
982 node->nr_loop_iter = nr_loop_iter; 1018 node->nr_loop_iter = nr_loop_iter;
983 node->samples = samples; 1019 node->iter_cycles = iter_cycles;
984 1020
985 if (flags) 1021 if (flags)
986 memcpy(&node->branch_flags, flags, 1022 memcpy(&node->branch_flags, flags,
987 sizeof(struct branch_flags)); 1023 sizeof(struct branch_flags));
988 1024
1025 node->branch_from = branch_from;
989 cursor->nr++; 1026 cursor->nr++;
990 1027
991 cursor->last = &node->next; 1028 cursor->last = &node->next;
@@ -998,11 +1035,11 @@ int sample__resolve_callchain(struct perf_sample *sample,
998 struct perf_evsel *evsel, struct addr_location *al, 1035 struct perf_evsel *evsel, struct addr_location *al,
999 int max_stack) 1036 int max_stack)
1000{ 1037{
1001 if (sample->callchain == NULL) 1038 if (sample->callchain == NULL && !symbol_conf.show_branchflag_count)
1002 return 0; 1039 return 0;
1003 1040
1004 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain || 1041 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
1005 perf_hpp_list.parent) { 1042 perf_hpp_list.parent || symbol_conf.show_branchflag_count) {
1006 return thread__resolve_callchain(al->thread, cursor, evsel, sample, 1043 return thread__resolve_callchain(al->thread, cursor, evsel, sample,
1007 parent, al, max_stack); 1044 parent, al, max_stack);
1008 } 1045 }
@@ -1011,7 +1048,8 @@ int sample__resolve_callchain(struct perf_sample *sample,
1011 1048
1012int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample) 1049int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
1013{ 1050{
1014 if (!symbol_conf.use_callchain || sample->callchain == NULL) 1051 if ((!symbol_conf.use_callchain || sample->callchain == NULL) &&
1052 !symbol_conf.show_branchflag_count)
1015 return 0; 1053 return 0;
1016 return callchain_append(he->callchain, &callchain_cursor, sample->period); 1054 return callchain_append(he->callchain, &callchain_cursor, sample->period);
1017} 1055}
@@ -1214,95 +1252,124 @@ int callchain_branch_counts(struct callchain_root *root,
1214 cycles_count); 1252 cycles_count);
1215} 1253}
1216 1254
1217static int counts_str_build(char *bf, int bfsize, 1255static 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{ 1256{
1222 double predicted_percent = 0.0; 1257 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 1258
1229 if (branch_count == 0) 1259 printed = scnprintf(bf, bfsize, "%s%s:%" PRId64 "", (idx) ? " " : " (", str, value);
1230 return scnprintf(bf, bfsize, " (calltrace)");
1231 1260
1232 cycles = cycles_count / branch_count; 1261 return printed;
1262}
1233 1263
1234 if (iter_count && samples_count) { 1264static int count_float_printf(int idx, const char *str, float value,
1235 if (cycles > 0) 1265 char *bf, int bfsize, float threshold)
1236 scnprintf(iter_str, sizeof(iter_str), 1266{
1237 " iterations:%" PRId64 "", 1267 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 1268
1247 if (cycles > 0) { 1269 if (threshold != 0.0 && value < threshold)
1248 scnprintf(cycle_str, sizeof(cycle_str), 1270 return 0;
1249 "cycles:%" PRId64 "", cycles);
1250 cstr = cycle_str;
1251 } else
1252 cstr = (char *)null_str;
1253 1271
1254 predicted_percent = predicted_count * 100.0 / branch_count; 1272 printed = scnprintf(bf, bfsize, "%s%s:%.1f%%", (idx) ? " " : " (", str, value);
1255 1273
1256 if ((predicted_count == branch_count) && (abort_count == 0)) { 1274 return printed;
1257 if ((cycles > 0) || (istr != (char *)null_str)) 1275}
1258 return scnprintf(bf, bfsize, " (%s%s)", cstr, istr); 1276
1259 else 1277static int branch_to_str(char *bf, int bfsize,
1260 return scnprintf(bf, bfsize, "%s", (char *)null_str); 1278 u64 branch_count, u64 predicted_count,
1279 u64 abort_count,
1280 struct branch_type_stat *brtype_stat)
1281{
1282 int printed, i = 0;
1283
1284 printed = branch_type_str(brtype_stat, bf, bfsize);
1285 if (printed)
1286 i++;
1287
1288 if (predicted_count < branch_count) {
1289 printed += count_float_printf(i++, "predicted",
1290 predicted_count * 100.0 / branch_count,
1291 bf + printed, bfsize - printed, 0.0);
1261 } 1292 }
1262 1293
1263 if ((predicted_count < branch_count) && (abort_count == 0)) { 1294 if (abort_count) {
1264 if ((cycles > 0) || (istr != (char *)null_str)) 1295 printed += count_float_printf(i++, "abort",
1265 return scnprintf(bf, bfsize, 1296 abort_count * 100.0 / branch_count,
1266 " (predicted:%.1f%% %s%s)", 1297 bf + printed, bfsize - printed, 0.1);
1267 predicted_percent, cstr, istr);
1268 else {
1269 return scnprintf(bf, bfsize,
1270 " (predicted:%.1f%%)",
1271 predicted_percent);
1272 }
1273 } 1298 }
1274 1299
1275 if ((predicted_count == branch_count) && (abort_count > 0)) { 1300 if (i)
1276 if ((cycles > 0) || (istr != (char *)null_str)) 1301 printed += scnprintf(bf + printed, bfsize - printed, ")");
1277 return scnprintf(bf, bfsize, 1302
1278 " (abort:%" PRId64 " %s%s)", 1303 return printed;
1279 abort_count, cstr, istr); 1304}
1280 else 1305
1281 return scnprintf(bf, bfsize, 1306static int branch_from_str(char *bf, int bfsize,
1282 " (abort:%" PRId64 ")", 1307 u64 branch_count,
1283 abort_count); 1308 u64 cycles_count, u64 iter_count,
1309 u64 iter_cycles)
1310{
1311 int printed = 0, i = 0;
1312 u64 cycles;
1313
1314 cycles = cycles_count / branch_count;
1315 if (cycles) {
1316 printed += count_pri64_printf(i++, "cycles",
1317 cycles,
1318 bf + printed, bfsize - printed);
1284 } 1319 }
1285 1320
1286 if ((cycles > 0) || (istr != (char *)null_str)) 1321 if (iter_count) {
1287 return scnprintf(bf, bfsize, 1322 printed += count_pri64_printf(i++, "iter",
1288 " (predicted:%.1f%% abort:%" PRId64 " %s%s)", 1323 iter_count,
1289 predicted_percent, abort_count, cstr, istr); 1324 bf + printed, bfsize - printed);
1325
1326 printed += count_pri64_printf(i++, "avg_cycles",
1327 iter_cycles / iter_count,
1328 bf + printed, bfsize - printed);
1329 }
1290 1330
1291 return scnprintf(bf, bfsize, 1331 if (i)
1292 " (predicted:%.1f%% abort:%" PRId64 ")", 1332 printed += scnprintf(bf + printed, bfsize - printed, ")");
1293 predicted_percent, abort_count); 1333
1334 return printed;
1335}
1336
1337static int counts_str_build(char *bf, int bfsize,
1338 u64 branch_count, u64 predicted_count,
1339 u64 abort_count, u64 cycles_count,
1340 u64 iter_count, u64 iter_cycles,
1341 struct branch_type_stat *brtype_stat)
1342{
1343 int printed;
1344
1345 if (branch_count == 0)
1346 return scnprintf(bf, bfsize, " (calltrace)");
1347
1348 if (brtype_stat->branch_to) {
1349 printed = branch_to_str(bf, bfsize, branch_count,
1350 predicted_count, abort_count, brtype_stat);
1351 } else {
1352 printed = branch_from_str(bf, bfsize, branch_count,
1353 cycles_count, iter_count, iter_cycles);
1354 }
1355
1356 if (!printed)
1357 bf[0] = 0;
1358
1359 return printed;
1294} 1360}
1295 1361
1296static int callchain_counts_printf(FILE *fp, char *bf, int bfsize, 1362static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
1297 u64 branch_count, u64 predicted_count, 1363 u64 branch_count, u64 predicted_count,
1298 u64 abort_count, u64 cycles_count, 1364 u64 abort_count, u64 cycles_count,
1299 u64 iter_count, u64 samples_count) 1365 u64 iter_count, u64 iter_cycles,
1366 struct branch_type_stat *brtype_stat)
1300{ 1367{
1301 char str[128]; 1368 char str[256];
1302 1369
1303 counts_str_build(str, sizeof(str), branch_count, 1370 counts_str_build(str, sizeof(str), branch_count,
1304 predicted_count, abort_count, cycles_count, 1371 predicted_count, abort_count, cycles_count,
1305 iter_count, samples_count); 1372 iter_count, iter_cycles, brtype_stat);
1306 1373
1307 if (fp) 1374 if (fp)
1308 return fprintf(fp, "%s", str); 1375 return fprintf(fp, "%s", str);
@@ -1310,31 +1377,24 @@ static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
1310 return scnprintf(bf, bfsize, "%s", str); 1377 return scnprintf(bf, bfsize, "%s", str);
1311} 1378}
1312 1379
1313int callchain_list_counts__printf_value(struct callchain_node *node, 1380int callchain_list_counts__printf_value(struct callchain_list *clist,
1314 struct callchain_list *clist,
1315 FILE *fp, char *bf, int bfsize) 1381 FILE *fp, char *bf, int bfsize)
1316{ 1382{
1317 u64 branch_count, predicted_count; 1383 u64 branch_count, predicted_count;
1318 u64 abort_count, cycles_count; 1384 u64 abort_count, cycles_count;
1319 u64 iter_count = 0, samples_count = 0; 1385 u64 iter_count, iter_cycles;
1320 1386
1321 branch_count = clist->branch_count; 1387 branch_count = clist->branch_count;
1322 predicted_count = clist->predicted_count; 1388 predicted_count = clist->predicted_count;
1323 abort_count = clist->abort_count; 1389 abort_count = clist->abort_count;
1324 cycles_count = clist->cycles_count; 1390 cycles_count = clist->cycles_count;
1325 1391 iter_count = clist->iter_count;
1326 if (node) { 1392 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 1393
1335 return callchain_counts_printf(fp, bf, bfsize, branch_count, 1394 return callchain_counts_printf(fp, bf, bfsize, branch_count,
1336 predicted_count, abort_count, 1395 predicted_count, abort_count,
1337 cycles_count, iter_count, samples_count); 1396 cycles_count, iter_count, iter_cycles,
1397 &clist->brtype_stat);
1338} 1398}
1339 1399
1340static void free_callchain_node(struct callchain_node *node) 1400static void free_callchain_node(struct callchain_node *node)
@@ -1459,7 +1519,9 @@ int callchain_cursor__copy(struct callchain_cursor *dst,
1459 1519
1460 rc = callchain_cursor_append(dst, node->ip, node->map, node->sym, 1520 rc = callchain_cursor_append(dst, node->ip, node->map, node->sym,
1461 node->branch, &node->branch_flags, 1521 node->branch, &node->branch_flags,
1462 node->nr_loop_iter, node->samples); 1522 node->nr_loop_iter,
1523 node->iter_cycles,
1524 node->branch_from);
1463 if (rc) 1525 if (rc)
1464 break; 1526 break;
1465 1527
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index c56c23dbbf72..1ed6fc61d0a5 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -7,6 +7,7 @@
7#include "event.h" 7#include "event.h"
8#include "map.h" 8#include "map.h"
9#include "symbol.h" 9#include "symbol.h"
10#include "branch.h"
10 11
11#define HELP_PAD "\t\t\t\t" 12#define HELP_PAD "\t\t\t\t"
12 13
@@ -118,7 +119,8 @@ struct callchain_list {
118 u64 abort_count; 119 u64 abort_count;
119 u64 cycles_count; 120 u64 cycles_count;
120 u64 iter_count; 121 u64 iter_count;
121 u64 samples_count; 122 u64 iter_cycles;
123 struct branch_type_stat brtype_stat;
122 char *srcline; 124 char *srcline;
123 struct list_head list; 125 struct list_head list;
124}; 126};
@@ -135,8 +137,9 @@ struct callchain_cursor_node {
135 struct symbol *sym; 137 struct symbol *sym;
136 bool branch; 138 bool branch;
137 struct branch_flags branch_flags; 139 struct branch_flags branch_flags;
140 u64 branch_from;
138 int nr_loop_iter; 141 int nr_loop_iter;
139 int samples; 142 u64 iter_cycles;
140 struct callchain_cursor_node *next; 143 struct callchain_cursor_node *next;
141}; 144};
142 145
@@ -198,7 +201,7 @@ static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
198int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip, 201int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
199 struct map *map, struct symbol *sym, 202 struct map *map, struct symbol *sym,
200 bool branch, struct branch_flags *flags, 203 bool branch, struct branch_flags *flags,
201 int nr_loop_iter, int samples); 204 int nr_loop_iter, u64 iter_cycles, u64 branch_from);
202 205
203/* Close a cursor writing session. Initialize for the reader */ 206/* Close a cursor writing session. Initialize for the reader */
204static inline void callchain_cursor_commit(struct callchain_cursor *cursor) 207static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
@@ -279,8 +282,7 @@ char *callchain_node__scnprintf_value(struct callchain_node *node,
279int callchain_node__fprintf_value(struct callchain_node *node, 282int callchain_node__fprintf_value(struct callchain_node *node,
280 FILE *fp, u64 total); 283 FILE *fp, u64 total);
281 284
282int callchain_list_counts__printf_value(struct callchain_node *node, 285int callchain_list_counts__printf_value(struct callchain_list *clist,
283 struct callchain_list *clist,
284 FILE *fp, char *bf, int bfsize); 286 FILE *fp, char *bf, int bfsize);
285 287
286void free_callchain(struct callchain_root *root); 288void free_callchain(struct callchain_root *root);
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 03347748f3fa..0e77bc9e5f3c 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -98,8 +98,10 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
98 cgrp = counter->cgrp; 98 cgrp = counter->cgrp;
99 if (!cgrp) 99 if (!cgrp)
100 continue; 100 continue;
101 if (!strcmp(cgrp->name, str)) 101 if (!strcmp(cgrp->name, str)) {
102 refcount_inc(&cgrp->refcnt);
102 break; 103 break;
104 }
103 105
104 cgrp = NULL; 106 cgrp = NULL;
105 } 107 }
@@ -110,6 +112,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
110 return -1; 112 return -1;
111 113
112 cgrp->name = str; 114 cgrp->name = str;
115 refcount_set(&cgrp->refcnt, 1);
113 116
114 cgrp->fd = open_cgroup(str); 117 cgrp->fd = open_cgroup(str);
115 if (cgrp->fd == -1) { 118 if (cgrp->fd == -1) {
@@ -128,12 +131,11 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
128 goto found; 131 goto found;
129 n++; 132 n++;
130 } 133 }
131 if (refcount_read(&cgrp->refcnt) == 0) 134 if (refcount_dec_and_test(&cgrp->refcnt))
132 free(cgrp); 135 free(cgrp);
133 136
134 return -1; 137 return -1;
135found: 138found:
136 refcount_inc(&cgrp->refcnt);
137 counter->cgrp = cgrp; 139 counter->cgrp = cgrp;
138 return 0; 140 return 0;
139} 141}
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 31a7dea248d0..bc75596f9e79 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -19,6 +19,7 @@
19#include <sys/types.h> 19#include <sys/types.h>
20#include <sys/stat.h> 20#include <sys/stat.h>
21#include <unistd.h> 21#include <unistd.h>
22#include <linux/string.h>
22 23
23#include "sane_ctype.h" 24#include "sane_ctype.h"
24 25
@@ -433,22 +434,22 @@ static int perf_ui_config(const char *var, const char *value)
433int perf_default_config(const char *var, const char *value, 434int perf_default_config(const char *var, const char *value,
434 void *dummy __maybe_unused) 435 void *dummy __maybe_unused)
435{ 436{
436 if (!prefixcmp(var, "core.")) 437 if (strstarts(var, "core."))
437 return perf_default_core_config(var, value); 438 return perf_default_core_config(var, value);
438 439
439 if (!prefixcmp(var, "hist.")) 440 if (strstarts(var, "hist."))
440 return perf_hist_config(var, value); 441 return perf_hist_config(var, value);
441 442
442 if (!prefixcmp(var, "ui.")) 443 if (strstarts(var, "ui."))
443 return perf_ui_config(var, value); 444 return perf_ui_config(var, value);
444 445
445 if (!prefixcmp(var, "call-graph.")) 446 if (strstarts(var, "call-graph."))
446 return perf_callchain_config(var, value); 447 return perf_callchain_config(var, value);
447 448
448 if (!prefixcmp(var, "llvm.")) 449 if (strstarts(var, "llvm."))
449 return perf_llvm_config(var, value); 450 return perf_llvm_config(var, value);
450 451
451 if (!prefixcmp(var, "buildid.")) 452 if (strstarts(var, "buildid."))
452 return perf_buildid_config(var, value); 453 return perf_buildid_config(var, value);
453 454
454 /* Add other config variables here. */ 455 /* Add other config variables here. */
diff --git a/tools/perf/util/counts.h b/tools/perf/util/counts.h
index 34d8baaf558a..cb45a6aecf9d 100644
--- a/tools/perf/util/counts.h
+++ b/tools/perf/util/counts.h
@@ -12,6 +12,7 @@ struct perf_counts_values {
12 }; 12 };
13 u64 values[3]; 13 u64 values[3];
14 }; 14 };
15 bool loaded;
15}; 16};
16 17
17struct perf_counts { 18struct perf_counts {
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 3149b70799fd..2346cecb8ea2 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
@@ -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);
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index e84bbc8ec058..263f5a906ba5 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -10,6 +10,16 @@
10#include "util.h" 10#include "util.h"
11#include "debug.h" 11#include "debug.h"
12 12
13#ifndef O_CLOEXEC
14#ifdef __sparc__
15#define O_CLOEXEC 0x400000
16#elif defined(__alpha__) || defined(__hppa__)
17#define O_CLOEXEC 010000000
18#else
19#define O_CLOEXEC 02000000
20#endif
21#endif
22
13static bool check_pipe(struct perf_data_file *file) 23static bool check_pipe(struct perf_data_file *file)
14{ 24{
15 struct stat st; 25 struct stat st;
@@ -96,7 +106,8 @@ static int open_file_write(struct perf_data_file *file)
96 if (check_backup(file)) 106 if (check_backup(file))
97 return -1; 107 return -1;
98 108
99 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); 109 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC,
110 S_IRUSR|S_IWUSR);
100 111
101 if (fd < 0) 112 if (fd < 0)
102 pr_err("failed to open %s : %s\n", file->path, 113 pr_err("failed to open %s : %s\n", file->path,
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 4e7ab611377a..b9e087fb8247 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -32,6 +32,7 @@ char dso__symtab_origin(const struct dso *dso)
32 [DSO_BINARY_TYPE__JAVA_JIT] = 'j', 32 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
33 [DSO_BINARY_TYPE__DEBUGLINK] = 'l', 33 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
34 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B', 34 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
35 [DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO] = 'D',
35 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f', 36 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
36 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u', 37 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
37 [DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o', 38 [DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o',
@@ -97,7 +98,12 @@ int dso__read_binary_type_filename(const struct dso *dso,
97 break; 98 break;
98 } 99 }
99 case DSO_BINARY_TYPE__BUILD_ID_CACHE: 100 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
100 if (dso__build_id_filename(dso, filename, size) == NULL) 101 if (dso__build_id_filename(dso, filename, size, false) == NULL)
102 ret = -1;
103 break;
104
105 case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
106 if (dso__build_id_filename(dso, filename, size, true) == NULL)
101 ret = -1; 107 ret = -1;
102 break; 108 break;
103 109
@@ -504,7 +510,14 @@ static void check_data_close(void);
504 */ 510 */
505static int open_dso(struct dso *dso, struct machine *machine) 511static int open_dso(struct dso *dso, struct machine *machine)
506{ 512{
507 int fd = __open_dso(dso, machine); 513 int fd;
514 struct nscookie nsc;
515
516 if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
517 nsinfo__mountns_enter(dso->nsinfo, &nsc);
518 fd = __open_dso(dso, machine);
519 if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
520 nsinfo__mountns_exit(&nsc);
508 521
509 if (fd >= 0) { 522 if (fd >= 0) {
510 dso__list_add(dso); 523 dso__list_add(dso);
@@ -1236,6 +1249,7 @@ void dso__delete(struct dso *dso)
1236 dso_cache__free(dso); 1249 dso_cache__free(dso);
1237 dso__free_a2l(dso); 1250 dso__free_a2l(dso);
1238 zfree(&dso->symsrc_filename); 1251 zfree(&dso->symsrc_filename);
1252 nsinfo__zput(dso->nsinfo);
1239 pthread_mutex_destroy(&dso->lock); 1253 pthread_mutex_destroy(&dso->lock);
1240 free(dso); 1254 free(dso);
1241} 1255}
@@ -1301,6 +1315,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1301{ 1315{
1302 bool have_build_id = false; 1316 bool have_build_id = false;
1303 struct dso *pos; 1317 struct dso *pos;
1318 struct nscookie nsc;
1304 1319
1305 list_for_each_entry(pos, head, node) { 1320 list_for_each_entry(pos, head, node) {
1306 if (with_hits && !pos->hit && !dso__is_vdso(pos)) 1321 if (with_hits && !pos->hit && !dso__is_vdso(pos))
@@ -1309,11 +1324,13 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1309 have_build_id = true; 1324 have_build_id = true;
1310 continue; 1325 continue;
1311 } 1326 }
1327 nsinfo__mountns_enter(pos->nsinfo, &nsc);
1312 if (filename__read_build_id(pos->long_name, pos->build_id, 1328 if (filename__read_build_id(pos->long_name, pos->build_id,
1313 sizeof(pos->build_id)) > 0) { 1329 sizeof(pos->build_id)) > 0) {
1314 have_build_id = true; 1330 have_build_id = true;
1315 pos->has_build_id = true; 1331 pos->has_build_id = true;
1316 } 1332 }
1333 nsinfo__mountns_exit(&nsc);
1317 } 1334 }
1318 1335
1319 return have_build_id; 1336 return have_build_id;
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index bd061ba7b47c..f886141678eb 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -10,6 +10,7 @@
10#include <linux/types.h> 10#include <linux/types.h>
11#include <linux/bitops.h> 11#include <linux/bitops.h>
12#include "map.h" 12#include "map.h"
13#include "namespaces.h"
13#include "build-id.h" 14#include "build-id.h"
14 15
15enum dso_binary_type { 16enum dso_binary_type {
@@ -20,6 +21,7 @@ enum dso_binary_type {
20 DSO_BINARY_TYPE__JAVA_JIT, 21 DSO_BINARY_TYPE__JAVA_JIT,
21 DSO_BINARY_TYPE__DEBUGLINK, 22 DSO_BINARY_TYPE__DEBUGLINK,
22 DSO_BINARY_TYPE__BUILD_ID_CACHE, 23 DSO_BINARY_TYPE__BUILD_ID_CACHE,
24 DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
23 DSO_BINARY_TYPE__FEDORA_DEBUGINFO, 25 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
24 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO, 26 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
25 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 27 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
@@ -187,6 +189,7 @@ struct dso {
187 void *priv; 189 void *priv;
188 u64 db_id; 190 u64 db_id;
189 }; 191 };
192 struct nsinfo *nsinfo;
190 refcount_t refcnt; 193 refcount_t refcnt;
191 char name[0]; 194 char name[0];
192}; 195};
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index dc5c3bb69d73..1c905ba3641b 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -57,6 +57,7 @@ static const char *perf_event__names[] = {
57 [PERF_RECORD_STAT_ROUND] = "STAT_ROUND", 57 [PERF_RECORD_STAT_ROUND] = "STAT_ROUND",
58 [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", 58 [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE",
59 [PERF_RECORD_TIME_CONV] = "TIME_CONV", 59 [PERF_RECORD_TIME_CONV] = "TIME_CONV",
60 [PERF_RECORD_HEADER_FEATURE] = "FEATURE",
60}; 61};
61 62
62static const char *perf_ns__names[] = { 63static const char *perf_ns__names[] = {
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 9967c87af7a6..ee7bcc898d35 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -142,7 +142,8 @@ struct branch_flags {
142 u64 in_tx:1; 142 u64 in_tx:1;
143 u64 abort:1; 143 u64 abort:1;
144 u64 cycles:16; 144 u64 cycles:16;
145 u64 reserved:44; 145 u64 type:4;
146 u64 reserved:40;
146}; 147};
147 148
148struct branch_entry { 149struct branch_entry {
@@ -199,6 +200,7 @@ struct perf_sample {
199 u32 cpu; 200 u32 cpu;
200 u32 raw_size; 201 u32 raw_size;
201 u64 data_src; 202 u64 data_src;
203 u64 phys_addr;
202 u32 flags; 204 u32 flags;
203 u16 insn_len; 205 u16 insn_len;
204 u8 cpumode; 206 u8 cpumode;
@@ -244,6 +246,7 @@ enum perf_user_event_type { /* above any possible kernel type */
244 PERF_RECORD_STAT_ROUND = 77, 246 PERF_RECORD_STAT_ROUND = 77,
245 PERF_RECORD_EVENT_UPDATE = 78, 247 PERF_RECORD_EVENT_UPDATE = 78,
246 PERF_RECORD_TIME_CONV = 79, 248 PERF_RECORD_TIME_CONV = 79,
249 PERF_RECORD_HEADER_FEATURE = 80,
247 PERF_RECORD_HEADER_MAX 250 PERF_RECORD_HEADER_MAX
248}; 251};
249 252
@@ -609,6 +612,12 @@ struct time_conv_event {
609 u64 time_zero; 612 u64 time_zero;
610}; 613};
611 614
615struct feature_event {
616 struct perf_event_header header;
617 u64 feat_id;
618 char data[];
619};
620
612union perf_event { 621union perf_event {
613 struct perf_event_header header; 622 struct perf_event_header header;
614 struct mmap_event mmap; 623 struct mmap_event mmap;
@@ -639,6 +648,7 @@ union perf_event {
639 struct stat_event stat; 648 struct stat_event stat;
640 struct stat_round_event stat_round; 649 struct stat_round_event stat_round;
641 struct time_conv_event time_conv; 650 struct time_conv_event time_conv;
651 struct feature_event feat;
642}; 652};
643 653
644void perf_event__print_totals(void); 654void perf_event__print_totals(void);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 46c0faf6c502..6a0d7ffbeba0 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -242,9 +242,9 @@ void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr)
242 } 242 }
243} 243}
244 244
245int perf_evlist__add_default(struct perf_evlist *evlist) 245int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise)
246{ 246{
247 struct perf_evsel *evsel = perf_evsel__new_cycles(); 247 struct perf_evsel *evsel = perf_evsel__new_cycles(precise);
248 248
249 if (evsel == NULL) 249 if (evsel == NULL)
250 return -ENOMEM; 250 return -ENOMEM;
@@ -1419,8 +1419,6 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e
1419{ 1419{
1420 struct perf_evsel *evsel; 1420 struct perf_evsel *evsel;
1421 int err = 0; 1421 int err = 0;
1422 const int ncpus = cpu_map__nr(evlist->cpus),
1423 nthreads = thread_map__nr(evlist->threads);
1424 1422
1425 evlist__for_each_entry(evlist, evsel) { 1423 evlist__for_each_entry(evlist, evsel) {
1426 if (evsel->filter == NULL) 1424 if (evsel->filter == NULL)
@@ -1430,7 +1428,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. 1428 * filters only work for tracepoint event, which doesn't have cpu limit.
1431 * So evlist and evsel should always be same. 1429 * So evlist and evsel should always be same.
1432 */ 1430 */
1433 err = perf_evsel__apply_filter(evsel, ncpus, nthreads, evsel->filter); 1431 err = perf_evsel__apply_filter(evsel, evsel->filter);
1434 if (err) { 1432 if (err) {
1435 *err_evsel = evsel; 1433 *err_evsel = evsel;
1436 break; 1434 break;
@@ -1623,13 +1621,9 @@ void perf_evlist__set_selected(struct perf_evlist *evlist,
1623void perf_evlist__close(struct perf_evlist *evlist) 1621void perf_evlist__close(struct perf_evlist *evlist)
1624{ 1622{
1625 struct perf_evsel *evsel; 1623 struct perf_evsel *evsel;
1626 int ncpus = cpu_map__nr(evlist->cpus);
1627 int nthreads = thread_map__nr(evlist->threads);
1628 1624
1629 evlist__for_each_entry_reverse(evlist, evsel) { 1625 evlist__for_each_entry_reverse(evlist, evsel)
1630 int n = evsel->cpus ? evsel->cpus->nr : ncpus; 1626 perf_evsel__close(evsel);
1631 perf_evsel__close(evsel, n, nthreads);
1632 }
1633} 1627}
1634 1628
1635static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) 1629static 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..bf2c4936e35f 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -115,7 +115,14 @@ void perf_evlist__delete(struct perf_evlist *evlist);
115 115
116void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); 116void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
117void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel); 117void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel);
118int perf_evlist__add_default(struct perf_evlist *evlist); 118
119int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise);
120
121static inline int perf_evlist__add_default(struct perf_evlist *evlist)
122{
123 return __perf_evlist__add_default(evlist, true);
124}
125
119int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 126int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
120 struct perf_event_attr *attrs, size_t nr_attrs); 127 struct perf_event_attr *attrs, size_t nr_attrs);
121 128
@@ -258,6 +265,11 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist);
258void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 265void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
259 struct list_head *list); 266 struct list_head *list);
260 267
268static inline bool perf_evlist__empty(struct perf_evlist *evlist)
269{
270 return list_empty(&evlist->entries);
271}
272
261static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist) 273static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist)
262{ 274{
263 return list_entry(evlist->entries.next, struct perf_evsel, node); 275 return list_entry(evlist->entries.next, struct perf_evsel, node);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 87b431886670..4bb89373eb52 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,19 @@ 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) 274struct perf_evsel *perf_evsel__new_cycles(bool precise)
272{ 275{
273 struct perf_event_attr attr = { 276 struct perf_event_attr attr = {
274 .type = PERF_TYPE_HARDWARE, 277 .type = PERF_TYPE_HARDWARE,
275 .config = PERF_COUNT_HW_CPU_CYCLES, 278 .config = PERF_COUNT_HW_CPU_CYCLES,
276 .exclude_kernel = 1, 279 .exclude_kernel = geteuid() != 0,
277 }; 280 };
278 struct perf_evsel *evsel; 281 struct perf_evsel *evsel;
279 282
280 event_attr_init(&attr); 283 event_attr_init(&attr);
284
285 if (!precise)
286 goto new_event;
281 /* 287 /*
282 * Unnamed union member, not supported as struct member named 288 * Unnamed union member, not supported as struct member named
283 * initializer in older compilers such as gcc 4.4.7 289 * initializer in older compilers such as gcc 4.4.7
@@ -292,14 +298,16 @@ struct perf_evsel *perf_evsel__new_cycles(void)
292 * to kick in when we return and before perf_evsel__open() is called. 298 * to kick in when we return and before perf_evsel__open() is called.
293 */ 299 */
294 attr.sample_period = 0; 300 attr.sample_period = 0;
295 301new_event:
296 evsel = perf_evsel__new(&attr); 302 evsel = perf_evsel__new(&attr);
297 if (evsel == NULL) 303 if (evsel == NULL)
298 goto out; 304 goto out;
299 305
300 /* use asprintf() because free(evsel) assumes name is allocated */ 306 /* use asprintf() because free(evsel) assumes name is allocated */
301 if (asprintf(&evsel->name, "cycles%.*s", 307 if (asprintf(&evsel->name, "cycles%s%s%.*s",
302 attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0) 308 (attr.precise_ip || attr.exclude_kernel) ? ":" : "",
309 attr.exclude_kernel ? "u" : "",
310 attr.precise_ip ? attr.precise_ip + 1 : 0, "ppp") < 0)
303 goto error_free; 311 goto error_free;
304out: 312out:
305 return evsel; 313 return evsel;
@@ -894,8 +902,13 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
894 if (opts->no_samples) 902 if (opts->no_samples)
895 attr->sample_freq = 0; 903 attr->sample_freq = 0;
896 904
897 if (opts->inherit_stat) 905 if (opts->inherit_stat) {
906 evsel->attr.read_format |=
907 PERF_FORMAT_TOTAL_TIME_ENABLED |
908 PERF_FORMAT_TOTAL_TIME_RUNNING |
909 PERF_FORMAT_ID;
898 attr->inherit_stat = 1; 910 attr->inherit_stat = 1;
911 }
899 912
900 if (opts->sample_address) { 913 if (opts->sample_address) {
901 perf_evsel__set_sample_bit(evsel, ADDR); 914 perf_evsel__set_sample_bit(evsel, ADDR);
@@ -942,6 +955,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
942 if (opts->sample_address) 955 if (opts->sample_address)
943 perf_evsel__set_sample_bit(evsel, DATA_SRC); 956 perf_evsel__set_sample_bit(evsel, DATA_SRC);
944 957
958 if (opts->sample_phys_addr)
959 perf_evsel__set_sample_bit(evsel, PHYS_ADDR);
960
945 if (opts->no_buffering) { 961 if (opts->no_buffering) {
946 attr->watermark = 0; 962 attr->watermark = 0;
947 attr->wakeup_events = 1; 963 attr->wakeup_events = 1;
@@ -1043,16 +1059,13 @@ static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthread
1043 return evsel->fd != NULL ? 0 : -ENOMEM; 1059 return evsel->fd != NULL ? 0 : -ENOMEM;
1044} 1060}
1045 1061
1046static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ncpus, int nthreads, 1062static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
1047 int ioc, void *arg) 1063 int ioc, void *arg)
1048{ 1064{
1049 int cpu, thread; 1065 int cpu, thread;
1050 1066
1051 if (evsel->system_wide) 1067 for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
1052 nthreads = 1; 1068 for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
1053
1054 for (cpu = 0; cpu < ncpus; cpu++) {
1055 for (thread = 0; thread < nthreads; thread++) {
1056 int fd = FD(evsel, cpu, thread), 1069 int fd = FD(evsel, cpu, thread),
1057 err = ioctl(fd, ioc, arg); 1070 err = ioctl(fd, ioc, arg);
1058 1071
@@ -1064,10 +1077,9 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ncpus, int nthrea
1064 return 0; 1077 return 0;
1065} 1078}
1066 1079
1067int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads, 1080int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter)
1068 const char *filter)
1069{ 1081{
1070 return perf_evsel__run_ioctl(evsel, ncpus, nthreads, 1082 return perf_evsel__run_ioctl(evsel,
1071 PERF_EVENT_IOC_SET_FILTER, 1083 PERF_EVENT_IOC_SET_FILTER,
1072 (void *)filter); 1084 (void *)filter);
1073} 1085}
@@ -1114,20 +1126,14 @@ int perf_evsel__append_addr_filter(struct perf_evsel *evsel, const char *filter)
1114 1126
1115int perf_evsel__enable(struct perf_evsel *evsel) 1127int perf_evsel__enable(struct perf_evsel *evsel)
1116{ 1128{
1117 int nthreads = thread_map__nr(evsel->threads); 1129 return perf_evsel__run_ioctl(evsel,
1118 int ncpus = cpu_map__nr(evsel->cpus);
1119
1120 return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
1121 PERF_EVENT_IOC_ENABLE, 1130 PERF_EVENT_IOC_ENABLE,
1122 0); 1131 0);
1123} 1132}
1124 1133
1125int perf_evsel__disable(struct perf_evsel *evsel) 1134int perf_evsel__disable(struct perf_evsel *evsel)
1126{ 1135{
1127 int nthreads = thread_map__nr(evsel->threads); 1136 return perf_evsel__run_ioctl(evsel,
1128 int ncpus = cpu_map__nr(evsel->cpus);
1129
1130 return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
1131 PERF_EVENT_IOC_DISABLE, 1137 PERF_EVENT_IOC_DISABLE,
1132 0); 1138 0);
1133} 1139}
@@ -1177,15 +1183,12 @@ static void perf_evsel__free_config_terms(struct perf_evsel *evsel)
1177 } 1183 }
1178} 1184}
1179 1185
1180void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 1186void perf_evsel__close_fd(struct perf_evsel *evsel)
1181{ 1187{
1182 int cpu, thread; 1188 int cpu, thread;
1183 1189
1184 if (evsel->system_wide) 1190 for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++)
1185 nthreads = 1; 1191 for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
1186
1187 for (cpu = 0; cpu < ncpus; cpu++)
1188 for (thread = 0; thread < nthreads; ++thread) {
1189 close(FD(evsel, cpu, thread)); 1192 close(FD(evsel, cpu, thread));
1190 FD(evsel, cpu, thread) = -1; 1193 FD(evsel, cpu, thread) = -1;
1191 } 1194 }
@@ -1254,20 +1257,148 @@ void perf_counts_values__scale(struct perf_counts_values *count,
1254 *pscaled = scaled; 1257 *pscaled = scaled;
1255} 1258}
1256 1259
1260static int perf_evsel__read_size(struct perf_evsel *evsel)
1261{
1262 u64 read_format = evsel->attr.read_format;
1263 int entry = sizeof(u64); /* value */
1264 int size = 0;
1265 int nr = 1;
1266
1267 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1268 size += sizeof(u64);
1269
1270 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1271 size += sizeof(u64);
1272
1273 if (read_format & PERF_FORMAT_ID)
1274 entry += sizeof(u64);
1275
1276 if (read_format & PERF_FORMAT_GROUP) {
1277 nr = evsel->nr_members;
1278 size += sizeof(u64);
1279 }
1280
1281 size += entry * nr;
1282 return size;
1283}
1284
1257int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, 1285int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
1258 struct perf_counts_values *count) 1286 struct perf_counts_values *count)
1259{ 1287{
1288 size_t size = perf_evsel__read_size(evsel);
1289
1260 memset(count, 0, sizeof(*count)); 1290 memset(count, 0, sizeof(*count));
1261 1291
1262 if (FD(evsel, cpu, thread) < 0) 1292 if (FD(evsel, cpu, thread) < 0)
1263 return -EINVAL; 1293 return -EINVAL;
1264 1294
1265 if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) <= 0) 1295 if (readn(FD(evsel, cpu, thread), count->values, size) <= 0)
1266 return -errno; 1296 return -errno;
1267 1297
1268 return 0; 1298 return 0;
1269} 1299}
1270 1300
1301static int
1302perf_evsel__read_one(struct perf_evsel *evsel, int cpu, int thread)
1303{
1304 struct perf_counts_values *count = perf_counts(evsel->counts, cpu, thread);
1305
1306 return perf_evsel__read(evsel, cpu, thread, count);
1307}
1308
1309static void
1310perf_evsel__set_count(struct perf_evsel *counter, int cpu, int thread,
1311 u64 val, u64 ena, u64 run)
1312{
1313 struct perf_counts_values *count;
1314
1315 count = perf_counts(counter->counts, cpu, thread);
1316
1317 count->val = val;
1318 count->ena = ena;
1319 count->run = run;
1320 count->loaded = true;
1321}
1322
1323static int
1324perf_evsel__process_group_data(struct perf_evsel *leader,
1325 int cpu, int thread, u64 *data)
1326{
1327 u64 read_format = leader->attr.read_format;
1328 struct sample_read_value *v;
1329 u64 nr, ena = 0, run = 0, i;
1330
1331 nr = *data++;
1332
1333 if (nr != (u64) leader->nr_members)
1334 return -EINVAL;
1335
1336 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1337 ena = *data++;
1338
1339 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1340 run = *data++;
1341
1342 v = (struct sample_read_value *) data;
1343
1344 perf_evsel__set_count(leader, cpu, thread,
1345 v[0].value, ena, run);
1346
1347 for (i = 1; i < nr; i++) {
1348 struct perf_evsel *counter;
1349
1350 counter = perf_evlist__id2evsel(leader->evlist, v[i].id);
1351 if (!counter)
1352 return -EINVAL;
1353
1354 perf_evsel__set_count(counter, cpu, thread,
1355 v[i].value, ena, run);
1356 }
1357
1358 return 0;
1359}
1360
1361static int
1362perf_evsel__read_group(struct perf_evsel *leader, int cpu, int thread)
1363{
1364 struct perf_stat_evsel *ps = leader->priv;
1365 u64 read_format = leader->attr.read_format;
1366 int size = perf_evsel__read_size(leader);
1367 u64 *data = ps->group_data;
1368
1369 if (!(read_format & PERF_FORMAT_ID))
1370 return -EINVAL;
1371
1372 if (!perf_evsel__is_group_leader(leader))
1373 return -EINVAL;
1374
1375 if (!data) {
1376 data = zalloc(size);
1377 if (!data)
1378 return -ENOMEM;
1379
1380 ps->group_data = data;
1381 }
1382
1383 if (FD(leader, cpu, thread) < 0)
1384 return -EINVAL;
1385
1386 if (readn(FD(leader, cpu, thread), data, size) <= 0)
1387 return -errno;
1388
1389 return perf_evsel__process_group_data(leader, cpu, thread, data);
1390}
1391
1392int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread)
1393{
1394 u64 read_format = evsel->attr.read_format;
1395
1396 if (read_format & PERF_FORMAT_GROUP)
1397 return perf_evsel__read_group(evsel, cpu, thread);
1398 else
1399 return perf_evsel__read_one(evsel, cpu, thread);
1400}
1401
1271int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 1402int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
1272 int cpu, int thread, bool scale) 1403 int cpu, int thread, bool scale)
1273{ 1404{
@@ -1336,7 +1467,7 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
1336 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), 1467 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1337 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), 1468 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1338 bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC), 1469 bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC),
1339 bit_name(WEIGHT), 1470 bit_name(WEIGHT), bit_name(PHYS_ADDR),
1340 { .name = NULL, } 1471 { .name = NULL, }
1341 }; 1472 };
1342#undef bit_name 1473#undef bit_name
@@ -1543,6 +1674,8 @@ fallback_missing_features:
1543 if (perf_missing_features.lbr_flags) 1674 if (perf_missing_features.lbr_flags)
1544 evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | 1675 evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
1545 PERF_SAMPLE_BRANCH_NO_CYCLES); 1676 PERF_SAMPLE_BRANCH_NO_CYCLES);
1677 if (perf_missing_features.group_read && evsel->attr.inherit)
1678 evsel->attr.read_format &= ~(PERF_FORMAT_GROUP|PERF_FORMAT_ID);
1546retry_sample_id: 1679retry_sample_id:
1547 if (perf_missing_features.sample_id_all) 1680 if (perf_missing_features.sample_id_all)
1548 evsel->attr.sample_id_all = 0; 1681 evsel->attr.sample_id_all = 0;
@@ -1567,6 +1700,8 @@ retry_open:
1567 pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx", 1700 pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx",
1568 pid, cpus->map[cpu], group_fd, flags); 1701 pid, cpus->map[cpu], group_fd, flags);
1569 1702
1703 test_attr__ready();
1704
1570 fd = sys_perf_event_open(&evsel->attr, pid, cpus->map[cpu], 1705 fd = sys_perf_event_open(&evsel->attr, pid, cpus->map[cpu],
1571 group_fd, flags); 1706 group_fd, flags);
1572 1707
@@ -1662,31 +1797,45 @@ try_fallback:
1662 */ 1797 */
1663 if (!perf_missing_features.write_backward && evsel->attr.write_backward) { 1798 if (!perf_missing_features.write_backward && evsel->attr.write_backward) {
1664 perf_missing_features.write_backward = true; 1799 perf_missing_features.write_backward = true;
1800 pr_debug2("switching off write_backward\n");
1665 goto out_close; 1801 goto out_close;
1666 } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { 1802 } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) {
1667 perf_missing_features.clockid_wrong = true; 1803 perf_missing_features.clockid_wrong = true;
1804 pr_debug2("switching off clockid\n");
1668 goto fallback_missing_features; 1805 goto fallback_missing_features;
1669 } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) { 1806 } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) {
1670 perf_missing_features.clockid = true; 1807 perf_missing_features.clockid = true;
1808 pr_debug2("switching off use_clockid\n");
1671 goto fallback_missing_features; 1809 goto fallback_missing_features;
1672 } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) { 1810 } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
1673 perf_missing_features.cloexec = true; 1811 perf_missing_features.cloexec = true;
1812 pr_debug2("switching off cloexec flag\n");
1674 goto fallback_missing_features; 1813 goto fallback_missing_features;
1675 } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { 1814 } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
1676 perf_missing_features.mmap2 = true; 1815 perf_missing_features.mmap2 = true;
1816 pr_debug2("switching off mmap2\n");
1677 goto fallback_missing_features; 1817 goto fallback_missing_features;
1678 } else if (!perf_missing_features.exclude_guest && 1818 } else if (!perf_missing_features.exclude_guest &&
1679 (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { 1819 (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
1680 perf_missing_features.exclude_guest = true; 1820 perf_missing_features.exclude_guest = true;
1821 pr_debug2("switching off exclude_guest, exclude_host\n");
1681 goto fallback_missing_features; 1822 goto fallback_missing_features;
1682 } else if (!perf_missing_features.sample_id_all) { 1823 } else if (!perf_missing_features.sample_id_all) {
1683 perf_missing_features.sample_id_all = true; 1824 perf_missing_features.sample_id_all = true;
1825 pr_debug2("switching off sample_id_all\n");
1684 goto retry_sample_id; 1826 goto retry_sample_id;
1685 } else if (!perf_missing_features.lbr_flags && 1827 } else if (!perf_missing_features.lbr_flags &&
1686 (evsel->attr.branch_sample_type & 1828 (evsel->attr.branch_sample_type &
1687 (PERF_SAMPLE_BRANCH_NO_CYCLES | 1829 (PERF_SAMPLE_BRANCH_NO_CYCLES |
1688 PERF_SAMPLE_BRANCH_NO_FLAGS))) { 1830 PERF_SAMPLE_BRANCH_NO_FLAGS))) {
1689 perf_missing_features.lbr_flags = true; 1831 perf_missing_features.lbr_flags = true;
1832 pr_debug2("switching off branch sample type no (cycles/flags)\n");
1833 goto fallback_missing_features;
1834 } else if (!perf_missing_features.group_read &&
1835 evsel->attr.inherit &&
1836 (evsel->attr.read_format & PERF_FORMAT_GROUP)) {
1837 perf_missing_features.group_read = true;
1838 pr_debug2("switching off group read\n");
1690 goto fallback_missing_features; 1839 goto fallback_missing_features;
1691 } 1840 }
1692out_close: 1841out_close:
@@ -1700,12 +1849,12 @@ out_close:
1700 return err; 1849 return err;
1701} 1850}
1702 1851
1703void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads) 1852void perf_evsel__close(struct perf_evsel *evsel)
1704{ 1853{
1705 if (evsel->fd == NULL) 1854 if (evsel->fd == NULL)
1706 return; 1855 return;
1707 1856
1708 perf_evsel__close_fd(evsel, ncpus, nthreads); 1857 perf_evsel__close_fd(evsel);
1709 perf_evsel__free_fd(evsel); 1858 perf_evsel__free_fd(evsel);
1710} 1859}
1711 1860
@@ -2060,6 +2209,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
2060 } 2209 }
2061 } 2210 }
2062 2211
2212 data->phys_addr = 0;
2213 if (type & PERF_SAMPLE_PHYS_ADDR) {
2214 data->phys_addr = *array;
2215 array++;
2216 }
2217
2063 return 0; 2218 return 0;
2064} 2219}
2065 2220
@@ -2165,6 +2320,9 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
2165 } 2320 }
2166 } 2321 }
2167 2322
2323 if (type & PERF_SAMPLE_PHYS_ADDR)
2324 result += sizeof(u64);
2325
2168 return result; 2326 return result;
2169} 2327}
2170 2328
@@ -2354,6 +2512,11 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
2354 } 2512 }
2355 } 2513 }
2356 2514
2515 if (type & PERF_SAMPLE_PHYS_ADDR) {
2516 *array = sample->phys_addr;
2517 array++;
2518 }
2519
2357 return 0; 2520 return 0;
2358} 2521}
2359 2522
@@ -2533,7 +2696,9 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2533 "unprivileged users (without CAP_SYS_ADMIN).\n\n" 2696 "unprivileged users (without CAP_SYS_ADMIN).\n\n"
2534 "The current value is %d:\n\n" 2697 "The current value is %d:\n\n"
2535 " -1: Allow use of (almost) all events by all users\n" 2698 " -1: Allow use of (almost) all events by all users\n"
2536 ">= 0: Disallow raw tracepoint access by users without CAP_IOC_LOCK\n" 2699 " Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK\n"
2700 ">= 0: Disallow ftrace function tracepoint by users without CAP_SYS_ADMIN\n"
2701 " Disallow raw tracepoint access by users without CAP_SYS_ADMIN\n"
2537 ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n" 2702 ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n"
2538 ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN\n\n" 2703 ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN\n\n"
2539 "To make this setting permanent, edit /etc/sysctl.conf too, e.g.:\n\n" 2704 "To make this setting permanent, edit /etc/sysctl.conf too, e.g.:\n\n"
@@ -2608,3 +2773,10 @@ char *perf_evsel__env_arch(struct perf_evsel *evsel)
2608 return evsel->evlist->env->arch; 2773 return evsel->evlist->env->arch;
2609 return NULL; 2774 return NULL;
2610} 2775}
2776
2777char *perf_evsel__env_cpuid(struct perf_evsel *evsel)
2778{
2779 if (evsel && evsel->evlist && evsel->evlist->env)
2780 return evsel->evlist->env->cpuid;
2781 return NULL;
2782}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index d101695c482c..dd2c4b5112a5 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -131,6 +131,7 @@ struct perf_evsel {
131 bool cmdline_group_boundary; 131 bool cmdline_group_boundary;
132 struct list_head config_terms; 132 struct list_head config_terms;
133 int bpf_fd; 133 int bpf_fd;
134 bool auto_merge_stats;
134 bool merged_stat; 135 bool merged_stat;
135 const char * metric_expr; 136 const char * metric_expr;
136 const char * metric_name; 137 const char * metric_name;
@@ -185,7 +186,7 @@ static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *
185 return perf_evsel__newtp_idx(sys, name, 0); 186 return perf_evsel__newtp_idx(sys, name, 0);
186} 187}
187 188
188struct perf_evsel *perf_evsel__new_cycles(void); 189struct perf_evsel *perf_evsel__new_cycles(bool precise);
189 190
190struct event_format *event_format__new(const char *sys, const char *name); 191struct event_format *event_format__new(const char *sys, const char *name);
191 192
@@ -226,7 +227,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); 227int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
227 228
228int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 229int 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); 230void perf_evsel__close_fd(struct perf_evsel *evsel);
230 231
231void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, 232void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
232 enum perf_event_sample_format bit); 233 enum perf_event_sample_format bit);
@@ -246,8 +247,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); 247int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter);
247int perf_evsel__append_addr_filter(struct perf_evsel *evsel, 248int perf_evsel__append_addr_filter(struct perf_evsel *evsel,
248 const char *filter); 249 const char *filter);
249int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads, 250int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter);
250 const char *filter);
251int perf_evsel__enable(struct perf_evsel *evsel); 251int perf_evsel__enable(struct perf_evsel *evsel);
252int perf_evsel__disable(struct perf_evsel *evsel); 252int perf_evsel__disable(struct perf_evsel *evsel);
253 253
@@ -257,7 +257,7 @@ int perf_evsel__open_per_thread(struct perf_evsel *evsel,
257 struct thread_map *threads); 257 struct thread_map *threads);
258int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 258int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
259 struct thread_map *threads); 259 struct thread_map *threads);
260void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads); 260void perf_evsel__close(struct perf_evsel *evsel);
261 261
262struct perf_sample; 262struct perf_sample;
263 263
@@ -299,6 +299,8 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1,
299int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, 299int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
300 struct perf_counts_values *count); 300 struct perf_counts_values *count);
301 301
302int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread);
303
302int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 304int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
303 int cpu, int thread, bool scale); 305 int cpu, int thread, bool scale);
304 306
@@ -436,5 +438,6 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
436 attr__fprintf_f attr__fprintf, void *priv); 438 attr__fprintf_f attr__fprintf, void *priv);
437 439
438char *perf_evsel__env_arch(struct perf_evsel *evsel); 440char *perf_evsel__env_arch(struct perf_evsel *evsel);
441char *perf_evsel__env_cpuid(struct perf_evsel *evsel);
439 442
440#endif /* __PERF_EVSEL_H */ 443#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h
index 9c2760a1a96e..400ef9eab00a 100644
--- a/tools/perf/util/expr.h
+++ b/tools/perf/util/expr.h
@@ -1,7 +1,7 @@
1#ifndef PARSE_CTX_H 1#ifndef PARSE_CTX_H
2#define PARSE_CTX_H 1 2#define PARSE_CTX_H 1
3 3
4#define EXPR_MAX_OTHER 8 4#define EXPR_MAX_OTHER 15
5#define MAX_PARSE_ID EXPR_MAX_OTHER 5#define MAX_PARSE_ID EXPR_MAX_OTHER
6 6
7struct parse_id { 7struct 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/header.c b/tools/perf/util/header.c
index 76ed7d03e500..605bbd5404fb 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -12,6 +12,7 @@
12#include <linux/list.h> 12#include <linux/list.h>
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/bitops.h> 14#include <linux/bitops.h>
15#include <linux/stringify.h>
15#include <sys/stat.h> 16#include <sys/stat.h>
16#include <sys/types.h> 17#include <sys/types.h>
17#include <sys/utsname.h> 18#include <sys/utsname.h>
@@ -34,6 +35,7 @@
34#include "data.h" 35#include "data.h"
35#include <api/fs/fs.h> 36#include <api/fs/fs.h>
36#include "asm/bug.h" 37#include "asm/bug.h"
38#include "tool.h"
37 39
38#include "sane_ctype.h" 40#include "sane_ctype.h"
39 41
@@ -59,6 +61,15 @@ struct perf_file_attr {
59 struct perf_file_section ids; 61 struct perf_file_section ids;
60}; 62};
61 63
64struct feat_fd {
65 struct perf_header *ph;
66 int fd;
67 void *buf; /* Either buf != NULL or fd >= 0 */
68 ssize_t offset;
69 size_t size;
70 struct perf_evsel *events;
71};
72
62void perf_header__set_feat(struct perf_header *header, int feat) 73void perf_header__set_feat(struct perf_header *header, int feat)
63{ 74{
64 set_bit(feat, header->adds_features); 75 set_bit(feat, header->adds_features);
@@ -74,28 +85,60 @@ bool perf_header__has_feat(const struct perf_header *header, int feat)
74 return test_bit(feat, header->adds_features); 85 return test_bit(feat, header->adds_features);
75} 86}
76 87
77static int do_write(int fd, const void *buf, size_t size) 88static int __do_write_fd(struct feat_fd *ff, const void *buf, size_t size)
78{ 89{
79 while (size) { 90 ssize_t ret = writen(ff->fd, buf, size);
80 int ret = write(fd, buf, size);
81 91
82 if (ret < 0) 92 if (ret != (ssize_t)size)
83 return -errno; 93 return ret < 0 ? (int)ret : -1;
94 return 0;
95}
96
97static int __do_write_buf(struct feat_fd *ff, const void *buf, size_t size)
98{
99 /* struct perf_event_header::size is u16 */
100 const size_t max_size = 0xffff - sizeof(struct perf_event_header);
101 size_t new_size = ff->size;
102 void *addr;
84 103
85 size -= ret; 104 if (size + ff->offset > max_size)
86 buf += ret; 105 return -E2BIG;
106
107 while (size > (new_size - ff->offset))
108 new_size <<= 1;
109 new_size = min(max_size, new_size);
110
111 if (ff->size < new_size) {
112 addr = realloc(ff->buf, new_size);
113 if (!addr)
114 return -ENOMEM;
115 ff->buf = addr;
116 ff->size = new_size;
87 } 117 }
88 118
119 memcpy(ff->buf + ff->offset, buf, size);
120 ff->offset += size;
121
89 return 0; 122 return 0;
90} 123}
91 124
92int write_padded(int fd, const void *bf, size_t count, size_t count_aligned) 125/* Return: 0 if succeded, -ERR if failed. */
126int do_write(struct feat_fd *ff, const void *buf, size_t size)
127{
128 if (!ff->buf)
129 return __do_write_fd(ff, buf, size);
130 return __do_write_buf(ff, buf, size);
131}
132
133/* Return: 0 if succeded, -ERR if failed. */
134int write_padded(struct feat_fd *ff, const void *bf,
135 size_t count, size_t count_aligned)
93{ 136{
94 static const char zero_buf[NAME_ALIGN]; 137 static const char zero_buf[NAME_ALIGN];
95 int err = do_write(fd, bf, count); 138 int err = do_write(ff, bf, count);
96 139
97 if (!err) 140 if (!err)
98 err = do_write(fd, zero_buf, count_aligned - count); 141 err = do_write(ff, zero_buf, count_aligned - count);
99 142
100 return err; 143 return err;
101} 144}
@@ -103,7 +146,8 @@ int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
103#define string_size(str) \ 146#define string_size(str) \
104 (PERF_ALIGN((strlen(str) + 1), NAME_ALIGN) + sizeof(u32)) 147 (PERF_ALIGN((strlen(str) + 1), NAME_ALIGN) + sizeof(u32))
105 148
106static int do_write_string(int fd, const char *str) 149/* Return: 0 if succeded, -ERR if failed. */
150static int do_write_string(struct feat_fd *ff, const char *str)
107{ 151{
108 u32 len, olen; 152 u32 len, olen;
109 int ret; 153 int ret;
@@ -112,32 +156,80 @@ static int do_write_string(int fd, const char *str)
112 len = PERF_ALIGN(olen, NAME_ALIGN); 156 len = PERF_ALIGN(olen, NAME_ALIGN);
113 157
114 /* write len, incl. \0 */ 158 /* write len, incl. \0 */
115 ret = do_write(fd, &len, sizeof(len)); 159 ret = do_write(ff, &len, sizeof(len));
116 if (ret < 0) 160 if (ret < 0)
117 return ret; 161 return ret;
118 162
119 return write_padded(fd, str, olen, len); 163 return write_padded(ff, str, olen, len);
120} 164}
121 165
122static char *do_read_string(int fd, struct perf_header *ph) 166static int __do_read_fd(struct feat_fd *ff, void *addr, ssize_t size)
167{
168 ssize_t ret = readn(ff->fd, addr, size);
169
170 if (ret != size)
171 return ret < 0 ? (int)ret : -1;
172 return 0;
173}
174
175static int __do_read_buf(struct feat_fd *ff, void *addr, ssize_t size)
176{
177 if (size > (ssize_t)ff->size - ff->offset)
178 return -1;
179
180 memcpy(addr, ff->buf + ff->offset, size);
181 ff->offset += size;
182
183 return 0;
184
185}
186
187static int __do_read(struct feat_fd *ff, void *addr, ssize_t size)
188{
189 if (!ff->buf)
190 return __do_read_fd(ff, addr, size);
191 return __do_read_buf(ff, addr, size);
192}
193
194static int do_read_u32(struct feat_fd *ff, u32 *addr)
195{
196 int ret;
197
198 ret = __do_read(ff, addr, sizeof(*addr));
199 if (ret)
200 return ret;
201
202 if (ff->ph->needs_swap)
203 *addr = bswap_32(*addr);
204 return 0;
205}
206
207static int do_read_u64(struct feat_fd *ff, u64 *addr)
208{
209 int ret;
210
211 ret = __do_read(ff, addr, sizeof(*addr));
212 if (ret)
213 return ret;
214
215 if (ff->ph->needs_swap)
216 *addr = bswap_64(*addr);
217 return 0;
218}
219
220static char *do_read_string(struct feat_fd *ff)
123{ 221{
124 ssize_t sz, ret;
125 u32 len; 222 u32 len;
126 char *buf; 223 char *buf;
127 224
128 sz = readn(fd, &len, sizeof(len)); 225 if (do_read_u32(ff, &len))
129 if (sz < (ssize_t)sizeof(len))
130 return NULL; 226 return NULL;
131 227
132 if (ph->needs_swap)
133 len = bswap_32(len);
134
135 buf = malloc(len); 228 buf = malloc(len);
136 if (!buf) 229 if (!buf)
137 return NULL; 230 return NULL;
138 231
139 ret = readn(fd, buf, len); 232 if (!__do_read(ff, buf, len)) {
140 if (ret == (ssize_t)len) {
141 /* 233 /*
142 * strings are padded by zeroes 234 * strings are padded by zeroes
143 * thus the actual strlen of buf 235 * thus the actual strlen of buf
@@ -150,25 +242,30 @@ static char *do_read_string(int fd, struct perf_header *ph)
150 return NULL; 242 return NULL;
151} 243}
152 244
153static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, 245static int write_tracing_data(struct feat_fd *ff,
154 struct perf_evlist *evlist) 246 struct perf_evlist *evlist)
155{ 247{
156 return read_tracing_data(fd, &evlist->entries); 248 if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
157} 249 return -1;
158 250
251 return read_tracing_data(ff->fd, &evlist->entries);
252}
159 253
160static int write_build_id(int fd, struct perf_header *h, 254static int write_build_id(struct feat_fd *ff,
161 struct perf_evlist *evlist __maybe_unused) 255 struct perf_evlist *evlist __maybe_unused)
162{ 256{
163 struct perf_session *session; 257 struct perf_session *session;
164 int err; 258 int err;
165 259
166 session = container_of(h, struct perf_session, header); 260 session = container_of(ff->ph, struct perf_session, header);
167 261
168 if (!perf_session__read_build_ids(session, true)) 262 if (!perf_session__read_build_ids(session, true))
169 return -1; 263 return -1;
170 264
171 err = perf_session__write_buildid_table(session, fd); 265 if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
266 return -1;
267
268 err = perf_session__write_buildid_table(session, ff);
172 if (err < 0) { 269 if (err < 0) {
173 pr_debug("failed to write buildid table\n"); 270 pr_debug("failed to write buildid table\n");
174 return err; 271 return err;
@@ -178,7 +275,7 @@ static int write_build_id(int fd, struct perf_header *h,
178 return 0; 275 return 0;
179} 276}
180 277
181static int write_hostname(int fd, struct perf_header *h __maybe_unused, 278static int write_hostname(struct feat_fd *ff,
182 struct perf_evlist *evlist __maybe_unused) 279 struct perf_evlist *evlist __maybe_unused)
183{ 280{
184 struct utsname uts; 281 struct utsname uts;
@@ -188,10 +285,10 @@ static int write_hostname(int fd, struct perf_header *h __maybe_unused,
188 if (ret < 0) 285 if (ret < 0)
189 return -1; 286 return -1;
190 287
191 return do_write_string(fd, uts.nodename); 288 return do_write_string(ff, uts.nodename);
192} 289}
193 290
194static int write_osrelease(int fd, struct perf_header *h __maybe_unused, 291static int write_osrelease(struct feat_fd *ff,
195 struct perf_evlist *evlist __maybe_unused) 292 struct perf_evlist *evlist __maybe_unused)
196{ 293{
197 struct utsname uts; 294 struct utsname uts;
@@ -201,10 +298,10 @@ static int write_osrelease(int fd, struct perf_header *h __maybe_unused,
201 if (ret < 0) 298 if (ret < 0)
202 return -1; 299 return -1;
203 300
204 return do_write_string(fd, uts.release); 301 return do_write_string(ff, uts.release);
205} 302}
206 303
207static int write_arch(int fd, struct perf_header *h __maybe_unused, 304static int write_arch(struct feat_fd *ff,
208 struct perf_evlist *evlist __maybe_unused) 305 struct perf_evlist *evlist __maybe_unused)
209{ 306{
210 struct utsname uts; 307 struct utsname uts;
@@ -214,16 +311,16 @@ static int write_arch(int fd, struct perf_header *h __maybe_unused,
214 if (ret < 0) 311 if (ret < 0)
215 return -1; 312 return -1;
216 313
217 return do_write_string(fd, uts.machine); 314 return do_write_string(ff, uts.machine);
218} 315}
219 316
220static int write_version(int fd, struct perf_header *h __maybe_unused, 317static int write_version(struct feat_fd *ff,
221 struct perf_evlist *evlist __maybe_unused) 318 struct perf_evlist *evlist __maybe_unused)
222{ 319{
223 return do_write_string(fd, perf_version_string); 320 return do_write_string(ff, perf_version_string);
224} 321}
225 322
226static int __write_cpudesc(int fd, const char *cpuinfo_proc) 323static int __write_cpudesc(struct feat_fd *ff, const char *cpuinfo_proc)
227{ 324{
228 FILE *file; 325 FILE *file;
229 char *buf = NULL; 326 char *buf = NULL;
@@ -273,25 +370,22 @@ static int __write_cpudesc(int fd, const char *cpuinfo_proc)
273 } 370 }
274 p++; 371 p++;
275 } 372 }
276 ret = do_write_string(fd, s); 373 ret = do_write_string(ff, s);
277done: 374done:
278 free(buf); 375 free(buf);
279 fclose(file); 376 fclose(file);
280 return ret; 377 return ret;
281} 378}
282 379
283static int write_cpudesc(int fd, struct perf_header *h __maybe_unused, 380static int write_cpudesc(struct feat_fd *ff,
284 struct perf_evlist *evlist __maybe_unused) 381 struct perf_evlist *evlist __maybe_unused)
285{ 382{
286#ifndef CPUINFO_PROC
287#define CPUINFO_PROC {"model name", }
288#endif
289 const char *cpuinfo_procs[] = CPUINFO_PROC; 383 const char *cpuinfo_procs[] = CPUINFO_PROC;
290 unsigned int i; 384 unsigned int i;
291 385
292 for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) { 386 for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) {
293 int ret; 387 int ret;
294 ret = __write_cpudesc(fd, cpuinfo_procs[i]); 388 ret = __write_cpudesc(ff, cpuinfo_procs[i]);
295 if (ret >= 0) 389 if (ret >= 0)
296 return ret; 390 return ret;
297 } 391 }
@@ -299,7 +393,7 @@ static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
299} 393}
300 394
301 395
302static int write_nrcpus(int fd, struct perf_header *h __maybe_unused, 396static int write_nrcpus(struct feat_fd *ff,
303 struct perf_evlist *evlist __maybe_unused) 397 struct perf_evlist *evlist __maybe_unused)
304{ 398{
305 long nr; 399 long nr;
@@ -314,14 +408,14 @@ static int write_nrcpus(int fd, struct perf_header *h __maybe_unused,
314 408
315 nra = (u32)(nr & UINT_MAX); 409 nra = (u32)(nr & UINT_MAX);
316 410
317 ret = do_write(fd, &nrc, sizeof(nrc)); 411 ret = do_write(ff, &nrc, sizeof(nrc));
318 if (ret < 0) 412 if (ret < 0)
319 return ret; 413 return ret;
320 414
321 return do_write(fd, &nra, sizeof(nra)); 415 return do_write(ff, &nra, sizeof(nra));
322} 416}
323 417
324static int write_event_desc(int fd, struct perf_header *h __maybe_unused, 418static int write_event_desc(struct feat_fd *ff,
325 struct perf_evlist *evlist) 419 struct perf_evlist *evlist)
326{ 420{
327 struct perf_evsel *evsel; 421 struct perf_evsel *evsel;
@@ -333,7 +427,7 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
333 /* 427 /*
334 * write number of events 428 * write number of events
335 */ 429 */
336 ret = do_write(fd, &nre, sizeof(nre)); 430 ret = do_write(ff, &nre, sizeof(nre));
337 if (ret < 0) 431 if (ret < 0)
338 return ret; 432 return ret;
339 433
@@ -341,12 +435,12 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
341 * size of perf_event_attr struct 435 * size of perf_event_attr struct
342 */ 436 */
343 sz = (u32)sizeof(evsel->attr); 437 sz = (u32)sizeof(evsel->attr);
344 ret = do_write(fd, &sz, sizeof(sz)); 438 ret = do_write(ff, &sz, sizeof(sz));
345 if (ret < 0) 439 if (ret < 0)
346 return ret; 440 return ret;
347 441
348 evlist__for_each_entry(evlist, evsel) { 442 evlist__for_each_entry(evlist, evsel) {
349 ret = do_write(fd, &evsel->attr, sz); 443 ret = do_write(ff, &evsel->attr, sz);
350 if (ret < 0) 444 if (ret < 0)
351 return ret; 445 return ret;
352 /* 446 /*
@@ -357,27 +451,27 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
357 * type of ids, 451 * type of ids,
358 */ 452 */
359 nri = evsel->ids; 453 nri = evsel->ids;
360 ret = do_write(fd, &nri, sizeof(nri)); 454 ret = do_write(ff, &nri, sizeof(nri));
361 if (ret < 0) 455 if (ret < 0)
362 return ret; 456 return ret;
363 457
364 /* 458 /*
365 * write event string as passed on cmdline 459 * write event string as passed on cmdline
366 */ 460 */
367 ret = do_write_string(fd, perf_evsel__name(evsel)); 461 ret = do_write_string(ff, perf_evsel__name(evsel));
368 if (ret < 0) 462 if (ret < 0)
369 return ret; 463 return ret;
370 /* 464 /*
371 * write unique ids for this event 465 * write unique ids for this event
372 */ 466 */
373 ret = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); 467 ret = do_write(ff, evsel->id, evsel->ids * sizeof(u64));
374 if (ret < 0) 468 if (ret < 0)
375 return ret; 469 return ret;
376 } 470 }
377 return 0; 471 return 0;
378} 472}
379 473
380static int write_cmdline(int fd, struct perf_header *h __maybe_unused, 474static int write_cmdline(struct feat_fd *ff,
381 struct perf_evlist *evlist __maybe_unused) 475 struct perf_evlist *evlist __maybe_unused)
382{ 476{
383 char buf[MAXPATHLEN]; 477 char buf[MAXPATHLEN];
@@ -395,16 +489,16 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
395 /* account for binary path */ 489 /* account for binary path */
396 n = perf_env.nr_cmdline + 1; 490 n = perf_env.nr_cmdline + 1;
397 491
398 ret = do_write(fd, &n, sizeof(n)); 492 ret = do_write(ff, &n, sizeof(n));
399 if (ret < 0) 493 if (ret < 0)
400 return ret; 494 return ret;
401 495
402 ret = do_write_string(fd, buf); 496 ret = do_write_string(ff, buf);
403 if (ret < 0) 497 if (ret < 0)
404 return ret; 498 return ret;
405 499
406 for (i = 0 ; i < perf_env.nr_cmdline; i++) { 500 for (i = 0 ; i < perf_env.nr_cmdline; i++) {
407 ret = do_write_string(fd, perf_env.cmdline_argv[i]); 501 ret = do_write_string(ff, perf_env.cmdline_argv[i]);
408 if (ret < 0) 502 if (ret < 0)
409 return ret; 503 return ret;
410 } 504 }
@@ -557,8 +651,8 @@ out_free:
557 return tp; 651 return tp;
558} 652}
559 653
560static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, 654static int write_cpu_topology(struct feat_fd *ff,
561 struct perf_evlist *evlist __maybe_unused) 655 struct perf_evlist *evlist __maybe_unused)
562{ 656{
563 struct cpu_topo *tp; 657 struct cpu_topo *tp;
564 u32 i; 658 u32 i;
@@ -568,21 +662,21 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
568 if (!tp) 662 if (!tp)
569 return -1; 663 return -1;
570 664
571 ret = do_write(fd, &tp->core_sib, sizeof(tp->core_sib)); 665 ret = do_write(ff, &tp->core_sib, sizeof(tp->core_sib));
572 if (ret < 0) 666 if (ret < 0)
573 goto done; 667 goto done;
574 668
575 for (i = 0; i < tp->core_sib; i++) { 669 for (i = 0; i < tp->core_sib; i++) {
576 ret = do_write_string(fd, tp->core_siblings[i]); 670 ret = do_write_string(ff, tp->core_siblings[i]);
577 if (ret < 0) 671 if (ret < 0)
578 goto done; 672 goto done;
579 } 673 }
580 ret = do_write(fd, &tp->thread_sib, sizeof(tp->thread_sib)); 674 ret = do_write(ff, &tp->thread_sib, sizeof(tp->thread_sib));
581 if (ret < 0) 675 if (ret < 0)
582 goto done; 676 goto done;
583 677
584 for (i = 0; i < tp->thread_sib; i++) { 678 for (i = 0; i < tp->thread_sib; i++) {
585 ret = do_write_string(fd, tp->thread_siblings[i]); 679 ret = do_write_string(ff, tp->thread_siblings[i]);
586 if (ret < 0) 680 if (ret < 0)
587 break; 681 break;
588 } 682 }
@@ -592,11 +686,11 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
592 goto done; 686 goto done;
593 687
594 for (j = 0; j < perf_env.nr_cpus_avail; j++) { 688 for (j = 0; j < perf_env.nr_cpus_avail; j++) {
595 ret = do_write(fd, &perf_env.cpu[j].core_id, 689 ret = do_write(ff, &perf_env.cpu[j].core_id,
596 sizeof(perf_env.cpu[j].core_id)); 690 sizeof(perf_env.cpu[j].core_id));
597 if (ret < 0) 691 if (ret < 0)
598 return ret; 692 return ret;
599 ret = do_write(fd, &perf_env.cpu[j].socket_id, 693 ret = do_write(ff, &perf_env.cpu[j].socket_id,
600 sizeof(perf_env.cpu[j].socket_id)); 694 sizeof(perf_env.cpu[j].socket_id));
601 if (ret < 0) 695 if (ret < 0)
602 return ret; 696 return ret;
@@ -608,8 +702,8 @@ done:
608 702
609 703
610 704
611static int write_total_mem(int fd, struct perf_header *h __maybe_unused, 705static int write_total_mem(struct feat_fd *ff,
612 struct perf_evlist *evlist __maybe_unused) 706 struct perf_evlist *evlist __maybe_unused)
613{ 707{
614 char *buf = NULL; 708 char *buf = NULL;
615 FILE *fp; 709 FILE *fp;
@@ -629,7 +723,7 @@ static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
629 if (!ret) { 723 if (!ret) {
630 n = sscanf(buf, "%*s %"PRIu64, &mem); 724 n = sscanf(buf, "%*s %"PRIu64, &mem);
631 if (n == 1) 725 if (n == 1)
632 ret = do_write(fd, &mem, sizeof(mem)); 726 ret = do_write(ff, &mem, sizeof(mem));
633 } else 727 } else
634 ret = -1; 728 ret = -1;
635 free(buf); 729 free(buf);
@@ -637,7 +731,7 @@ static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
637 return ret; 731 return ret;
638} 732}
639 733
640static int write_topo_node(int fd, int node) 734static int write_topo_node(struct feat_fd *ff, int node)
641{ 735{
642 char str[MAXPATHLEN]; 736 char str[MAXPATHLEN];
643 char field[32]; 737 char field[32];
@@ -667,11 +761,11 @@ static int write_topo_node(int fd, int node)
667 fclose(fp); 761 fclose(fp);
668 fp = NULL; 762 fp = NULL;
669 763
670 ret = do_write(fd, &mem_total, sizeof(u64)); 764 ret = do_write(ff, &mem_total, sizeof(u64));
671 if (ret) 765 if (ret)
672 goto done; 766 goto done;
673 767
674 ret = do_write(fd, &mem_free, sizeof(u64)); 768 ret = do_write(ff, &mem_free, sizeof(u64));
675 if (ret) 769 if (ret)
676 goto done; 770 goto done;
677 771
@@ -689,7 +783,7 @@ static int write_topo_node(int fd, int node)
689 if (p) 783 if (p)
690 *p = '\0'; 784 *p = '\0';
691 785
692 ret = do_write_string(fd, buf); 786 ret = do_write_string(ff, buf);
693done: 787done:
694 free(buf); 788 free(buf);
695 if (fp) 789 if (fp)
@@ -697,8 +791,8 @@ done:
697 return ret; 791 return ret;
698} 792}
699 793
700static int write_numa_topology(int fd, struct perf_header *h __maybe_unused, 794static int write_numa_topology(struct feat_fd *ff,
701 struct perf_evlist *evlist __maybe_unused) 795 struct perf_evlist *evlist __maybe_unused)
702{ 796{
703 char *buf = NULL; 797 char *buf = NULL;
704 size_t len = 0; 798 size_t len = 0;
@@ -725,17 +819,17 @@ static int write_numa_topology(int fd, struct perf_header *h __maybe_unused,
725 819
726 nr = (u32)node_map->nr; 820 nr = (u32)node_map->nr;
727 821
728 ret = do_write(fd, &nr, sizeof(nr)); 822 ret = do_write(ff, &nr, sizeof(nr));
729 if (ret < 0) 823 if (ret < 0)
730 goto done; 824 goto done;
731 825
732 for (i = 0; i < nr; i++) { 826 for (i = 0; i < nr; i++) {
733 j = (u32)node_map->map[i]; 827 j = (u32)node_map->map[i];
734 ret = do_write(fd, &j, sizeof(j)); 828 ret = do_write(ff, &j, sizeof(j));
735 if (ret < 0) 829 if (ret < 0)
736 break; 830 break;
737 831
738 ret = write_topo_node(fd, i); 832 ret = write_topo_node(ff, i);
739 if (ret < 0) 833 if (ret < 0)
740 break; 834 break;
741 } 835 }
@@ -758,39 +852,40 @@ done:
758 * }; 852 * };
759 */ 853 */
760 854
761static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused, 855static int write_pmu_mappings(struct feat_fd *ff,
762 struct perf_evlist *evlist __maybe_unused) 856 struct perf_evlist *evlist __maybe_unused)
763{ 857{
764 struct perf_pmu *pmu = NULL; 858 struct perf_pmu *pmu = NULL;
765 off_t offset = lseek(fd, 0, SEEK_CUR); 859 u32 pmu_num = 0;
766 __u32 pmu_num = 0;
767 int ret; 860 int ret;
768 861
769 /* write real pmu_num later */ 862 /*
770 ret = do_write(fd, &pmu_num, sizeof(pmu_num)); 863 * Do a first pass to count number of pmu to avoid lseek so this
864 * works in pipe mode as well.
865 */
866 while ((pmu = perf_pmu__scan(pmu))) {
867 if (!pmu->name)
868 continue;
869 pmu_num++;
870 }
871
872 ret = do_write(ff, &pmu_num, sizeof(pmu_num));
771 if (ret < 0) 873 if (ret < 0)
772 return ret; 874 return ret;
773 875
774 while ((pmu = perf_pmu__scan(pmu))) { 876 while ((pmu = perf_pmu__scan(pmu))) {
775 if (!pmu->name) 877 if (!pmu->name)
776 continue; 878 continue;
777 pmu_num++;
778 879
779 ret = do_write(fd, &pmu->type, sizeof(pmu->type)); 880 ret = do_write(ff, &pmu->type, sizeof(pmu->type));
780 if (ret < 0) 881 if (ret < 0)
781 return ret; 882 return ret;
782 883
783 ret = do_write_string(fd, pmu->name); 884 ret = do_write_string(ff, pmu->name);
784 if (ret < 0) 885 if (ret < 0)
785 return ret; 886 return ret;
786 } 887 }
787 888
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; 889 return 0;
795} 890}
796 891
@@ -806,14 +901,14 @@ static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused,
806 * }[nr_groups]; 901 * }[nr_groups];
807 * }; 902 * };
808 */ 903 */
809static int write_group_desc(int fd, struct perf_header *h __maybe_unused, 904static int write_group_desc(struct feat_fd *ff,
810 struct perf_evlist *evlist) 905 struct perf_evlist *evlist)
811{ 906{
812 u32 nr_groups = evlist->nr_groups; 907 u32 nr_groups = evlist->nr_groups;
813 struct perf_evsel *evsel; 908 struct perf_evsel *evsel;
814 int ret; 909 int ret;
815 910
816 ret = do_write(fd, &nr_groups, sizeof(nr_groups)); 911 ret = do_write(ff, &nr_groups, sizeof(nr_groups));
817 if (ret < 0) 912 if (ret < 0)
818 return ret; 913 return ret;
819 914
@@ -824,15 +919,15 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
824 u32 leader_idx = evsel->idx; 919 u32 leader_idx = evsel->idx;
825 u32 nr_members = evsel->nr_members; 920 u32 nr_members = evsel->nr_members;
826 921
827 ret = do_write_string(fd, name); 922 ret = do_write_string(ff, name);
828 if (ret < 0) 923 if (ret < 0)
829 return ret; 924 return ret;
830 925
831 ret = do_write(fd, &leader_idx, sizeof(leader_idx)); 926 ret = do_write(ff, &leader_idx, sizeof(leader_idx));
832 if (ret < 0) 927 if (ret < 0)
833 return ret; 928 return ret;
834 929
835 ret = do_write(fd, &nr_members, sizeof(nr_members)); 930 ret = do_write(ff, &nr_members, sizeof(nr_members));
836 if (ret < 0) 931 if (ret < 0)
837 return ret; 932 return ret;
838 } 933 }
@@ -849,7 +944,7 @@ int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
849 return -1; 944 return -1;
850} 945}
851 946
852static int write_cpuid(int fd, struct perf_header *h __maybe_unused, 947static int write_cpuid(struct feat_fd *ff,
853 struct perf_evlist *evlist __maybe_unused) 948 struct perf_evlist *evlist __maybe_unused)
854{ 949{
855 char buffer[64]; 950 char buffer[64];
@@ -861,25 +956,27 @@ static int write_cpuid(int fd, struct perf_header *h __maybe_unused,
861 956
862 return -1; 957 return -1;
863write_it: 958write_it:
864 return do_write_string(fd, buffer); 959 return do_write_string(ff, buffer);
865} 960}
866 961
867static int write_branch_stack(int fd __maybe_unused, 962static int write_branch_stack(struct feat_fd *ff __maybe_unused,
868 struct perf_header *h __maybe_unused, 963 struct perf_evlist *evlist __maybe_unused)
869 struct perf_evlist *evlist __maybe_unused)
870{ 964{
871 return 0; 965 return 0;
872} 966}
873 967
874static int write_auxtrace(int fd, struct perf_header *h, 968static int write_auxtrace(struct feat_fd *ff,
875 struct perf_evlist *evlist __maybe_unused) 969 struct perf_evlist *evlist __maybe_unused)
876{ 970{
877 struct perf_session *session; 971 struct perf_session *session;
878 int err; 972 int err;
879 973
880 session = container_of(h, struct perf_session, header); 974 if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
975 return -1;
976
977 session = container_of(ff->ph, struct perf_session, header);
881 978
882 err = auxtrace_index__write(fd, &session->auxtrace_index); 979 err = auxtrace_index__write(ff->fd, &session->auxtrace_index);
883 if (err < 0) 980 if (err < 0)
884 pr_err("Failed to write auxtrace index\n"); 981 pr_err("Failed to write auxtrace index\n");
885 return err; 982 return err;
@@ -1026,8 +1123,8 @@ static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)
1026 1123
1027#define MAX_CACHES 2000 1124#define MAX_CACHES 2000
1028 1125
1029static int write_cache(int fd, struct perf_header *h __maybe_unused, 1126static int write_cache(struct feat_fd *ff,
1030 struct perf_evlist *evlist __maybe_unused) 1127 struct perf_evlist *evlist __maybe_unused)
1031{ 1128{
1032 struct cpu_cache_level caches[MAX_CACHES]; 1129 struct cpu_cache_level caches[MAX_CACHES];
1033 u32 cnt = 0, i, version = 1; 1130 u32 cnt = 0, i, version = 1;
@@ -1039,11 +1136,11 @@ static int write_cache(int fd, struct perf_header *h __maybe_unused,
1039 1136
1040 qsort(&caches, cnt, sizeof(struct cpu_cache_level), cpu_cache_level__sort); 1137 qsort(&caches, cnt, sizeof(struct cpu_cache_level), cpu_cache_level__sort);
1041 1138
1042 ret = do_write(fd, &version, sizeof(u32)); 1139 ret = do_write(ff, &version, sizeof(u32));
1043 if (ret < 0) 1140 if (ret < 0)
1044 goto out; 1141 goto out;
1045 1142
1046 ret = do_write(fd, &cnt, sizeof(u32)); 1143 ret = do_write(ff, &cnt, sizeof(u32));
1047 if (ret < 0) 1144 if (ret < 0)
1048 goto out; 1145 goto out;
1049 1146
@@ -1051,7 +1148,7 @@ static int write_cache(int fd, struct perf_header *h __maybe_unused,
1051 struct cpu_cache_level *c = &caches[i]; 1148 struct cpu_cache_level *c = &caches[i];
1052 1149
1053 #define _W(v) \ 1150 #define _W(v) \
1054 ret = do_write(fd, &c->v, sizeof(u32)); \ 1151 ret = do_write(ff, &c->v, sizeof(u32)); \
1055 if (ret < 0) \ 1152 if (ret < 0) \
1056 goto out; 1153 goto out;
1057 1154
@@ -1062,7 +1159,7 @@ static int write_cache(int fd, struct perf_header *h __maybe_unused,
1062 #undef _W 1159 #undef _W
1063 1160
1064 #define _W(v) \ 1161 #define _W(v) \
1065 ret = do_write_string(fd, (const char *) c->v); \ 1162 ret = do_write_string(ff, (const char *) c->v); \
1066 if (ret < 0) \ 1163 if (ret < 0) \
1067 goto out; 1164 goto out;
1068 1165
@@ -1078,69 +1175,62 @@ out:
1078 return ret; 1175 return ret;
1079} 1176}
1080 1177
1081static int write_stat(int fd __maybe_unused, 1178static int write_stat(struct feat_fd *ff __maybe_unused,
1082 struct perf_header *h __maybe_unused,
1083 struct perf_evlist *evlist __maybe_unused) 1179 struct perf_evlist *evlist __maybe_unused)
1084{ 1180{
1085 return 0; 1181 return 0;
1086} 1182}
1087 1183
1088static void print_hostname(struct perf_header *ph, int fd __maybe_unused, 1184static void print_hostname(struct feat_fd *ff, FILE *fp)
1089 FILE *fp)
1090{ 1185{
1091 fprintf(fp, "# hostname : %s\n", ph->env.hostname); 1186 fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname);
1092} 1187}
1093 1188
1094static void print_osrelease(struct perf_header *ph, int fd __maybe_unused, 1189static void print_osrelease(struct feat_fd *ff, FILE *fp)
1095 FILE *fp)
1096{ 1190{
1097 fprintf(fp, "# os release : %s\n", ph->env.os_release); 1191 fprintf(fp, "# os release : %s\n", ff->ph->env.os_release);
1098} 1192}
1099 1193
1100static void print_arch(struct perf_header *ph, int fd __maybe_unused, FILE *fp) 1194static void print_arch(struct feat_fd *ff, FILE *fp)
1101{ 1195{
1102 fprintf(fp, "# arch : %s\n", ph->env.arch); 1196 fprintf(fp, "# arch : %s\n", ff->ph->env.arch);
1103} 1197}
1104 1198
1105static void print_cpudesc(struct perf_header *ph, int fd __maybe_unused, 1199static void print_cpudesc(struct feat_fd *ff, FILE *fp)
1106 FILE *fp)
1107{ 1200{
1108 fprintf(fp, "# cpudesc : %s\n", ph->env.cpu_desc); 1201 fprintf(fp, "# cpudesc : %s\n", ff->ph->env.cpu_desc);
1109} 1202}
1110 1203
1111static void print_nrcpus(struct perf_header *ph, int fd __maybe_unused, 1204static void print_nrcpus(struct feat_fd *ff, FILE *fp)
1112 FILE *fp)
1113{ 1205{
1114 fprintf(fp, "# nrcpus online : %u\n", ph->env.nr_cpus_online); 1206 fprintf(fp, "# nrcpus online : %u\n", ff->ph->env.nr_cpus_online);
1115 fprintf(fp, "# nrcpus avail : %u\n", ph->env.nr_cpus_avail); 1207 fprintf(fp, "# nrcpus avail : %u\n", ff->ph->env.nr_cpus_avail);
1116} 1208}
1117 1209
1118static void print_version(struct perf_header *ph, int fd __maybe_unused, 1210static void print_version(struct feat_fd *ff, FILE *fp)
1119 FILE *fp)
1120{ 1211{
1121 fprintf(fp, "# perf version : %s\n", ph->env.version); 1212 fprintf(fp, "# perf version : %s\n", ff->ph->env.version);
1122} 1213}
1123 1214
1124static void print_cmdline(struct perf_header *ph, int fd __maybe_unused, 1215static void print_cmdline(struct feat_fd *ff, FILE *fp)
1125 FILE *fp)
1126{ 1216{
1127 int nr, i; 1217 int nr, i;
1128 1218
1129 nr = ph->env.nr_cmdline; 1219 nr = ff->ph->env.nr_cmdline;
1130 1220
1131 fprintf(fp, "# cmdline : "); 1221 fprintf(fp, "# cmdline : ");
1132 1222
1133 for (i = 0; i < nr; i++) 1223 for (i = 0; i < nr; i++)
1134 fprintf(fp, "%s ", ph->env.cmdline_argv[i]); 1224 fprintf(fp, "%s ", ff->ph->env.cmdline_argv[i]);
1135 fputc('\n', fp); 1225 fputc('\n', fp);
1136} 1226}
1137 1227
1138static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused, 1228static void print_cpu_topology(struct feat_fd *ff, FILE *fp)
1139 FILE *fp)
1140{ 1229{
1230 struct perf_header *ph = ff->ph;
1231 int cpu_nr = ph->env.nr_cpus_avail;
1141 int nr, i; 1232 int nr, i;
1142 char *str; 1233 char *str;
1143 int cpu_nr = ph->env.nr_cpus_avail;
1144 1234
1145 nr = ph->env.nr_sibling_cores; 1235 nr = ph->env.nr_sibling_cores;
1146 str = ph->env.sibling_cores; 1236 str = ph->env.sibling_cores;
@@ -1181,31 +1271,21 @@ static void free_event_desc(struct perf_evsel *events)
1181 free(events); 1271 free(events);
1182} 1272}
1183 1273
1184static struct perf_evsel * 1274static struct perf_evsel *read_event_desc(struct feat_fd *ff)
1185read_event_desc(struct perf_header *ph, int fd)
1186{ 1275{
1187 struct perf_evsel *evsel, *events = NULL; 1276 struct perf_evsel *evsel, *events = NULL;
1188 u64 *id; 1277 u64 *id;
1189 void *buf = NULL; 1278 void *buf = NULL;
1190 u32 nre, sz, nr, i, j; 1279 u32 nre, sz, nr, i, j;
1191 ssize_t ret;
1192 size_t msz; 1280 size_t msz;
1193 1281
1194 /* number of events */ 1282 /* number of events */
1195 ret = readn(fd, &nre, sizeof(nre)); 1283 if (do_read_u32(ff, &nre))
1196 if (ret != (ssize_t)sizeof(nre))
1197 goto error; 1284 goto error;
1198 1285
1199 if (ph->needs_swap) 1286 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; 1287 goto error;
1205 1288
1206 if (ph->needs_swap)
1207 sz = bswap_32(sz);
1208
1209 /* buffer to hold on file attr struct */ 1289 /* buffer to hold on file attr struct */
1210 buf = malloc(sz); 1290 buf = malloc(sz);
1211 if (!buf) 1291 if (!buf)
@@ -1227,25 +1307,23 @@ read_event_desc(struct perf_header *ph, int fd)
1227 * must read entire on-file attr struct to 1307 * must read entire on-file attr struct to
1228 * sync up with layout. 1308 * sync up with layout.
1229 */ 1309 */
1230 ret = readn(fd, buf, sz); 1310 if (__do_read(ff, buf, sz))
1231 if (ret != (ssize_t)sz)
1232 goto error; 1311 goto error;
1233 1312
1234 if (ph->needs_swap) 1313 if (ff->ph->needs_swap)
1235 perf_event__attr_swap(buf); 1314 perf_event__attr_swap(buf);
1236 1315
1237 memcpy(&evsel->attr, buf, msz); 1316 memcpy(&evsel->attr, buf, msz);
1238 1317
1239 ret = readn(fd, &nr, sizeof(nr)); 1318 if (do_read_u32(ff, &nr))
1240 if (ret != (ssize_t)sizeof(nr))
1241 goto error; 1319 goto error;
1242 1320
1243 if (ph->needs_swap) { 1321 if (ff->ph->needs_swap)
1244 nr = bswap_32(nr);
1245 evsel->needs_swap = true; 1322 evsel->needs_swap = true;
1246 }
1247 1323
1248 evsel->name = do_read_string(fd, ph); 1324 evsel->name = do_read_string(ff);
1325 if (!evsel->name)
1326 goto error;
1249 1327
1250 if (!nr) 1328 if (!nr)
1251 continue; 1329 continue;
@@ -1257,11 +1335,8 @@ read_event_desc(struct perf_header *ph, int fd)
1257 evsel->id = id; 1335 evsel->id = id;
1258 1336
1259 for (j = 0 ; j < nr; j++) { 1337 for (j = 0 ; j < nr; j++) {
1260 ret = readn(fd, id, sizeof(*id)); 1338 if (do_read_u64(ff, id))
1261 if (ret != (ssize_t)sizeof(*id))
1262 goto error; 1339 goto error;
1263 if (ph->needs_swap)
1264 *id = bswap_64(*id);
1265 id++; 1340 id++;
1266 } 1341 }
1267 } 1342 }
@@ -1280,12 +1355,17 @@ static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val,
1280 return fprintf(fp, ", %s = %s", name, val); 1355 return fprintf(fp, ", %s = %s", name, val);
1281} 1356}
1282 1357
1283static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) 1358static void print_event_desc(struct feat_fd *ff, FILE *fp)
1284{ 1359{
1285 struct perf_evsel *evsel, *events = read_event_desc(ph, fd); 1360 struct perf_evsel *evsel, *events;
1286 u32 j; 1361 u32 j;
1287 u64 *id; 1362 u64 *id;
1288 1363
1364 if (ff->events)
1365 events = ff->events;
1366 else
1367 events = read_event_desc(ff);
1368
1289 if (!events) { 1369 if (!events) {
1290 fprintf(fp, "# event desc: not available or unable to read\n"); 1370 fprintf(fp, "# event desc: not available or unable to read\n");
1291 return; 1371 return;
@@ -1310,22 +1390,21 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1310 } 1390 }
1311 1391
1312 free_event_desc(events); 1392 free_event_desc(events);
1393 ff->events = NULL;
1313} 1394}
1314 1395
1315static void print_total_mem(struct perf_header *ph, int fd __maybe_unused, 1396static void print_total_mem(struct feat_fd *ff, FILE *fp)
1316 FILE *fp)
1317{ 1397{
1318 fprintf(fp, "# total memory : %Lu kB\n", ph->env.total_mem); 1398 fprintf(fp, "# total memory : %llu kB\n", ff->ph->env.total_mem);
1319} 1399}
1320 1400
1321static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused, 1401static void print_numa_topology(struct feat_fd *ff, FILE *fp)
1322 FILE *fp)
1323{ 1402{
1324 int i; 1403 int i;
1325 struct numa_node *n; 1404 struct numa_node *n;
1326 1405
1327 for (i = 0; i < ph->env.nr_numa_nodes; i++) { 1406 for (i = 0; i < ff->ph->env.nr_numa_nodes; i++) {
1328 n = &ph->env.numa_nodes[i]; 1407 n = &ff->ph->env.numa_nodes[i];
1329 1408
1330 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB," 1409 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB,"
1331 " free = %"PRIu64" kB\n", 1410 " free = %"PRIu64" kB\n",
@@ -1336,56 +1415,51 @@ static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused,
1336 } 1415 }
1337} 1416}
1338 1417
1339static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp) 1418static void print_cpuid(struct feat_fd *ff, FILE *fp)
1340{ 1419{
1341 fprintf(fp, "# cpuid : %s\n", ph->env.cpuid); 1420 fprintf(fp, "# cpuid : %s\n", ff->ph->env.cpuid);
1342} 1421}
1343 1422
1344static void print_branch_stack(struct perf_header *ph __maybe_unused, 1423static void print_branch_stack(struct feat_fd *ff __maybe_unused, FILE *fp)
1345 int fd __maybe_unused, FILE *fp)
1346{ 1424{
1347 fprintf(fp, "# contains samples with branch stack\n"); 1425 fprintf(fp, "# contains samples with branch stack\n");
1348} 1426}
1349 1427
1350static void print_auxtrace(struct perf_header *ph __maybe_unused, 1428static void print_auxtrace(struct feat_fd *ff __maybe_unused, FILE *fp)
1351 int fd __maybe_unused, FILE *fp)
1352{ 1429{
1353 fprintf(fp, "# contains AUX area data (e.g. instruction trace)\n"); 1430 fprintf(fp, "# contains AUX area data (e.g. instruction trace)\n");
1354} 1431}
1355 1432
1356static void print_stat(struct perf_header *ph __maybe_unused, 1433static void print_stat(struct feat_fd *ff __maybe_unused, FILE *fp)
1357 int fd __maybe_unused, FILE *fp)
1358{ 1434{
1359 fprintf(fp, "# contains stat data\n"); 1435 fprintf(fp, "# contains stat data\n");
1360} 1436}
1361 1437
1362static void print_cache(struct perf_header *ph __maybe_unused, 1438static void print_cache(struct feat_fd *ff, FILE *fp __maybe_unused)
1363 int fd __maybe_unused, FILE *fp __maybe_unused)
1364{ 1439{
1365 int i; 1440 int i;
1366 1441
1367 fprintf(fp, "# CPU cache info:\n"); 1442 fprintf(fp, "# CPU cache info:\n");
1368 for (i = 0; i < ph->env.caches_cnt; i++) { 1443 for (i = 0; i < ff->ph->env.caches_cnt; i++) {
1369 fprintf(fp, "# "); 1444 fprintf(fp, "# ");
1370 cpu_cache_level__fprintf(fp, &ph->env.caches[i]); 1445 cpu_cache_level__fprintf(fp, &ff->ph->env.caches[i]);
1371 } 1446 }
1372} 1447}
1373 1448
1374static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused, 1449static void print_pmu_mappings(struct feat_fd *ff, FILE *fp)
1375 FILE *fp)
1376{ 1450{
1377 const char *delimiter = "# pmu mappings: "; 1451 const char *delimiter = "# pmu mappings: ";
1378 char *str, *tmp; 1452 char *str, *tmp;
1379 u32 pmu_num; 1453 u32 pmu_num;
1380 u32 type; 1454 u32 type;
1381 1455
1382 pmu_num = ph->env.nr_pmu_mappings; 1456 pmu_num = ff->ph->env.nr_pmu_mappings;
1383 if (!pmu_num) { 1457 if (!pmu_num) {
1384 fprintf(fp, "# pmu mappings: not available\n"); 1458 fprintf(fp, "# pmu mappings: not available\n");
1385 return; 1459 return;
1386 } 1460 }
1387 1461
1388 str = ph->env.pmu_mappings; 1462 str = ff->ph->env.pmu_mappings;
1389 1463
1390 while (pmu_num) { 1464 while (pmu_num) {
1391 type = strtoul(str, &tmp, 0); 1465 type = strtoul(str, &tmp, 0);
@@ -1408,14 +1482,13 @@ error:
1408 fprintf(fp, "# pmu mappings: unable to read\n"); 1482 fprintf(fp, "# pmu mappings: unable to read\n");
1409} 1483}
1410 1484
1411static void print_group_desc(struct perf_header *ph, int fd __maybe_unused, 1485static void print_group_desc(struct feat_fd *ff, FILE *fp)
1412 FILE *fp)
1413{ 1486{
1414 struct perf_session *session; 1487 struct perf_session *session;
1415 struct perf_evsel *evsel; 1488 struct perf_evsel *evsel;
1416 u32 nr = 0; 1489 u32 nr = 0;
1417 1490
1418 session = container_of(ph, struct perf_session, header); 1491 session = container_of(ff->ph, struct perf_session, header);
1419 1492
1420 evlist__for_each_entry(session->evlist, evsel) { 1493 evlist__for_each_entry(session->evlist, evsel) {
1421 if (perf_evsel__is_group_leader(evsel) && 1494 if (perf_evsel__is_group_leader(evsel) &&
@@ -1588,113 +1661,61 @@ out:
1588 return err; 1661 return err;
1589} 1662}
1590 1663
1591static int process_tracing_data(struct perf_file_section *section __maybe_unused, 1664/* Macro for features that simply need to read and store a string. */
1592 struct perf_header *ph __maybe_unused, 1665#define FEAT_PROCESS_STR_FUN(__feat, __feat_env) \
1593 int fd, void *data) 1666static int process_##__feat(struct feat_fd *ff, void *data __maybe_unused) \
1594{ 1667{\
1595 ssize_t ret = trace_report(fd, data, false); 1668 ff->ph->env.__feat_env = do_read_string(ff); \
1596 return ret < 0 ? -1 : 0; 1669 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} 1670}
1607 1671
1608static int process_hostname(struct perf_file_section *section __maybe_unused, 1672FEAT_PROCESS_STR_FUN(hostname, hostname);
1609 struct perf_header *ph, int fd, 1673FEAT_PROCESS_STR_FUN(osrelease, os_release);
1610 void *data __maybe_unused) 1674FEAT_PROCESS_STR_FUN(version, version);
1611{ 1675FEAT_PROCESS_STR_FUN(arch, arch);
1612 ph->env.hostname = do_read_string(fd, ph); 1676FEAT_PROCESS_STR_FUN(cpudesc, cpu_desc);
1613 return ph->env.hostname ? 0 : -ENOMEM; 1677FEAT_PROCESS_STR_FUN(cpuid, cpuid);
1614}
1615 1678
1616static int process_osrelease(struct perf_file_section *section __maybe_unused, 1679static int process_tracing_data(struct feat_fd *ff, void *data)
1617 struct perf_header *ph, int fd,
1618 void *data __maybe_unused)
1619{ 1680{
1620 ph->env.os_release = do_read_string(fd, ph); 1681 ssize_t ret = trace_report(ff->fd, data, false);
1621 return ph->env.os_release ? 0 : -ENOMEM;
1622}
1623 1682
1624static int process_version(struct perf_file_section *section __maybe_unused, 1683 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} 1684}
1631 1685
1632static int process_arch(struct perf_file_section *section __maybe_unused, 1686static 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{ 1687{
1636 ph->env.arch = do_read_string(fd, ph); 1688 if (perf_header__read_build_ids(ff->ph, ff->fd, ff->offset, ff->size))
1637 return ph->env.arch ? 0 : -ENOMEM; 1689 pr_debug("Failed to read buildids, continuing...\n");
1690 return 0;
1638} 1691}
1639 1692
1640static int process_nrcpus(struct perf_file_section *section __maybe_unused, 1693static int process_nrcpus(struct feat_fd *ff, void *data __maybe_unused)
1641 struct perf_header *ph, int fd,
1642 void *data __maybe_unused)
1643{ 1694{
1644 ssize_t ret; 1695 int ret;
1645 u32 nr; 1696 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 1697
1660 if (ph->needs_swap) 1698 ret = do_read_u32(ff, &nr_cpus_avail);
1661 nr = bswap_32(nr); 1699 if (ret)
1700 return ret;
1662 1701
1663 ph->env.nr_cpus_online = nr; 1702 ret = do_read_u32(ff, &nr_cpus_online);
1703 if (ret)
1704 return ret;
1705 ff->ph->env.nr_cpus_avail = (int)nr_cpus_avail;
1706 ff->ph->env.nr_cpus_online = (int)nr_cpus_online;
1664 return 0; 1707 return 0;
1665} 1708}
1666 1709
1667static int process_cpudesc(struct perf_file_section *section __maybe_unused, 1710static 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{ 1711{
1687 uint64_t mem; 1712 u64 total_mem;
1688 ssize_t ret; 1713 int ret;
1689 1714
1690 ret = readn(fd, &mem, sizeof(mem)); 1715 ret = do_read_u64(ff, &total_mem);
1691 if (ret != sizeof(mem)) 1716 if (ret)
1692 return -1; 1717 return -1;
1693 1718 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; 1719 return 0;
1699} 1720}
1700 1721
@@ -1731,43 +1752,42 @@ perf_evlist__set_event_name(struct perf_evlist *evlist,
1731} 1752}
1732 1753
1733static int 1754static int
1734process_event_desc(struct perf_file_section *section __maybe_unused, 1755process_event_desc(struct feat_fd *ff, void *data __maybe_unused)
1735 struct perf_header *header, int fd,
1736 void *data __maybe_unused)
1737{ 1756{
1738 struct perf_session *session; 1757 struct perf_session *session;
1739 struct perf_evsel *evsel, *events = read_event_desc(header, fd); 1758 struct perf_evsel *evsel, *events = read_event_desc(ff);
1740 1759
1741 if (!events) 1760 if (!events)
1742 return 0; 1761 return 0;
1743 1762
1744 session = container_of(header, struct perf_session, header); 1763 session = container_of(ff->ph, struct perf_session, header);
1764
1765 if (session->file->is_pipe) {
1766 /* Save events for reading later by print_event_desc,
1767 * since they can't be read again in pipe mode. */
1768 ff->events = events;
1769 }
1770
1745 for (evsel = events; evsel->attr.size; evsel++) 1771 for (evsel = events; evsel->attr.size; evsel++)
1746 perf_evlist__set_event_name(session->evlist, evsel); 1772 perf_evlist__set_event_name(session->evlist, evsel);
1747 1773
1748 free_event_desc(events); 1774 if (!session->file->is_pipe)
1775 free_event_desc(events);
1749 1776
1750 return 0; 1777 return 0;
1751} 1778}
1752 1779
1753static int process_cmdline(struct perf_file_section *section, 1780static int process_cmdline(struct feat_fd *ff, void *data __maybe_unused)
1754 struct perf_header *ph, int fd,
1755 void *data __maybe_unused)
1756{ 1781{
1757 ssize_t ret;
1758 char *str, *cmdline = NULL, **argv = NULL; 1782 char *str, *cmdline = NULL, **argv = NULL;
1759 u32 nr, i, len = 0; 1783 u32 nr, i, len = 0;
1760 1784
1761 ret = readn(fd, &nr, sizeof(nr)); 1785 if (do_read_u32(ff, &nr))
1762 if (ret != sizeof(nr))
1763 return -1; 1786 return -1;
1764 1787
1765 if (ph->needs_swap) 1788 ff->ph->env.nr_cmdline = nr;
1766 nr = bswap_32(nr);
1767
1768 ph->env.nr_cmdline = nr;
1769 1789
1770 cmdline = zalloc(section->size + nr + 1); 1790 cmdline = zalloc(ff->size + nr + 1);
1771 if (!cmdline) 1791 if (!cmdline)
1772 return -1; 1792 return -1;
1773 1793
@@ -1776,7 +1796,7 @@ static int process_cmdline(struct perf_file_section *section,
1776 goto error; 1796 goto error;
1777 1797
1778 for (i = 0; i < nr; i++) { 1798 for (i = 0; i < nr; i++) {
1779 str = do_read_string(fd, ph); 1799 str = do_read_string(ff);
1780 if (!str) 1800 if (!str)
1781 goto error; 1801 goto error;
1782 1802
@@ -1785,8 +1805,8 @@ static int process_cmdline(struct perf_file_section *section,
1785 len += strlen(str) + 1; 1805 len += strlen(str) + 1;
1786 free(str); 1806 free(str);
1787 } 1807 }
1788 ph->env.cmdline = cmdline; 1808 ff->ph->env.cmdline = cmdline;
1789 ph->env.cmdline_argv = (const char **) argv; 1809 ff->ph->env.cmdline_argv = (const char **) argv;
1790 return 0; 1810 return 0;
1791 1811
1792error: 1812error:
@@ -1795,35 +1815,29 @@ error:
1795 return -1; 1815 return -1;
1796} 1816}
1797 1817
1798static int process_cpu_topology(struct perf_file_section *section, 1818static 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{ 1819{
1802 ssize_t ret;
1803 u32 nr, i; 1820 u32 nr, i;
1804 char *str; 1821 char *str;
1805 struct strbuf sb; 1822 struct strbuf sb;
1806 int cpu_nr = ph->env.nr_cpus_avail; 1823 int cpu_nr = ff->ph->env.nr_cpus_avail;
1807 u64 size = 0; 1824 u64 size = 0;
1825 struct perf_header *ph = ff->ph;
1808 1826
1809 ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu)); 1827 ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu));
1810 if (!ph->env.cpu) 1828 if (!ph->env.cpu)
1811 return -1; 1829 return -1;
1812 1830
1813 ret = readn(fd, &nr, sizeof(nr)); 1831 if (do_read_u32(ff, &nr))
1814 if (ret != sizeof(nr))
1815 goto free_cpu; 1832 goto free_cpu;
1816 1833
1817 if (ph->needs_swap)
1818 nr = bswap_32(nr);
1819
1820 ph->env.nr_sibling_cores = nr; 1834 ph->env.nr_sibling_cores = nr;
1821 size += sizeof(u32); 1835 size += sizeof(u32);
1822 if (strbuf_init(&sb, 128) < 0) 1836 if (strbuf_init(&sb, 128) < 0)
1823 goto free_cpu; 1837 goto free_cpu;
1824 1838
1825 for (i = 0; i < nr; i++) { 1839 for (i = 0; i < nr; i++) {
1826 str = do_read_string(fd, ph); 1840 str = do_read_string(ff);
1827 if (!str) 1841 if (!str)
1828 goto error; 1842 goto error;
1829 1843
@@ -1835,18 +1849,14 @@ static int process_cpu_topology(struct perf_file_section *section,
1835 } 1849 }
1836 ph->env.sibling_cores = strbuf_detach(&sb, NULL); 1850 ph->env.sibling_cores = strbuf_detach(&sb, NULL);
1837 1851
1838 ret = readn(fd, &nr, sizeof(nr)); 1852 if (do_read_u32(ff, &nr))
1839 if (ret != sizeof(nr))
1840 return -1; 1853 return -1;
1841 1854
1842 if (ph->needs_swap)
1843 nr = bswap_32(nr);
1844
1845 ph->env.nr_sibling_threads = nr; 1855 ph->env.nr_sibling_threads = nr;
1846 size += sizeof(u32); 1856 size += sizeof(u32);
1847 1857
1848 for (i = 0; i < nr; i++) { 1858 for (i = 0; i < nr; i++) {
1849 str = do_read_string(fd, ph); 1859 str = do_read_string(ff);
1850 if (!str) 1860 if (!str)
1851 goto error; 1861 goto error;
1852 1862
@@ -1862,28 +1872,20 @@ static int process_cpu_topology(struct perf_file_section *section,
1862 * The header may be from old perf, 1872 * The header may be from old perf,
1863 * which doesn't include core id and socket id information. 1873 * which doesn't include core id and socket id information.
1864 */ 1874 */
1865 if (section->size <= size) { 1875 if (ff->size <= size) {
1866 zfree(&ph->env.cpu); 1876 zfree(&ph->env.cpu);
1867 return 0; 1877 return 0;
1868 } 1878 }
1869 1879
1870 for (i = 0; i < (u32)cpu_nr; i++) { 1880 for (i = 0; i < (u32)cpu_nr; i++) {
1871 ret = readn(fd, &nr, sizeof(nr)); 1881 if (do_read_u32(ff, &nr))
1872 if (ret != sizeof(nr))
1873 goto free_cpu; 1882 goto free_cpu;
1874 1883
1875 if (ph->needs_swap)
1876 nr = bswap_32(nr);
1877
1878 ph->env.cpu[i].core_id = nr; 1884 ph->env.cpu[i].core_id = nr;
1879 1885
1880 ret = readn(fd, &nr, sizeof(nr)); 1886 if (do_read_u32(ff, &nr))
1881 if (ret != sizeof(nr))
1882 goto free_cpu; 1887 goto free_cpu;
1883 1888
1884 if (ph->needs_swap)
1885 nr = bswap_32(nr);
1886
1887 if (nr != (u32)-1 && nr > (u32)cpu_nr) { 1889 if (nr != (u32)-1 && nr > (u32)cpu_nr) {
1888 pr_debug("socket_id number is too big." 1890 pr_debug("socket_id number is too big."
1889 "You may need to upgrade the perf tool.\n"); 1891 "You may need to upgrade the perf tool.\n");
@@ -1902,23 +1904,16 @@ free_cpu:
1902 return -1; 1904 return -1;
1903} 1905}
1904 1906
1905static int process_numa_topology(struct perf_file_section *section __maybe_unused, 1907static 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{ 1908{
1909 struct numa_node *nodes, *n; 1909 struct numa_node *nodes, *n;
1910 ssize_t ret;
1911 u32 nr, i; 1910 u32 nr, i;
1912 char *str; 1911 char *str;
1913 1912
1914 /* nr nodes */ 1913 /* nr nodes */
1915 ret = readn(fd, &nr, sizeof(nr)); 1914 if (do_read_u32(ff, &nr))
1916 if (ret != sizeof(nr))
1917 return -1; 1915 return -1;
1918 1916
1919 if (ph->needs_swap)
1920 nr = bswap_32(nr);
1921
1922 nodes = zalloc(sizeof(*nodes) * nr); 1917 nodes = zalloc(sizeof(*nodes) * nr);
1923 if (!nodes) 1918 if (!nodes)
1924 return -ENOMEM; 1919 return -ENOMEM;
@@ -1927,25 +1922,16 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
1927 n = &nodes[i]; 1922 n = &nodes[i];
1928 1923
1929 /* node number */ 1924 /* node number */
1930 ret = readn(fd, &n->node, sizeof(u32)); 1925 if (do_read_u32(ff, &n->node))
1931 if (ret != sizeof(n->node))
1932 goto error; 1926 goto error;
1933 1927
1934 ret = readn(fd, &n->mem_total, sizeof(u64)); 1928 if (do_read_u64(ff, &n->mem_total))
1935 if (ret != sizeof(u64))
1936 goto error; 1929 goto error;
1937 1930
1938 ret = readn(fd, &n->mem_free, sizeof(u64)); 1931 if (do_read_u64(ff, &n->mem_free))
1939 if (ret != sizeof(u64))
1940 goto error; 1932 goto error;
1941 1933
1942 if (ph->needs_swap) { 1934 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) 1935 if (!str)
1950 goto error; 1936 goto error;
1951 1937
@@ -1955,8 +1941,8 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
1955 1941
1956 free(str); 1942 free(str);
1957 } 1943 }
1958 ph->env.nr_numa_nodes = nr; 1944 ff->ph->env.nr_numa_nodes = nr;
1959 ph->env.numa_nodes = nodes; 1945 ff->ph->env.numa_nodes = nodes;
1960 return 0; 1946 return 0;
1961 1947
1962error: 1948error:
@@ -1964,39 +1950,30 @@ error:
1964 return -1; 1950 return -1;
1965} 1951}
1966 1952
1967static int process_pmu_mappings(struct perf_file_section *section __maybe_unused, 1953static 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{ 1954{
1971 ssize_t ret;
1972 char *name; 1955 char *name;
1973 u32 pmu_num; 1956 u32 pmu_num;
1974 u32 type; 1957 u32 type;
1975 struct strbuf sb; 1958 struct strbuf sb;
1976 1959
1977 ret = readn(fd, &pmu_num, sizeof(pmu_num)); 1960 if (do_read_u32(ff, &pmu_num))
1978 if (ret != sizeof(pmu_num))
1979 return -1; 1961 return -1;
1980 1962
1981 if (ph->needs_swap)
1982 pmu_num = bswap_32(pmu_num);
1983
1984 if (!pmu_num) { 1963 if (!pmu_num) {
1985 pr_debug("pmu mappings not available\n"); 1964 pr_debug("pmu mappings not available\n");
1986 return 0; 1965 return 0;
1987 } 1966 }
1988 1967
1989 ph->env.nr_pmu_mappings = pmu_num; 1968 ff->ph->env.nr_pmu_mappings = pmu_num;
1990 if (strbuf_init(&sb, 128) < 0) 1969 if (strbuf_init(&sb, 128) < 0)
1991 return -1; 1970 return -1;
1992 1971
1993 while (pmu_num) { 1972 while (pmu_num) {
1994 if (readn(fd, &type, sizeof(type)) != sizeof(type)) 1973 if (do_read_u32(ff, &type))
1995 goto error; 1974 goto error;
1996 if (ph->needs_swap)
1997 type = bswap_32(type);
1998 1975
1999 name = do_read_string(fd, ph); 1976 name = do_read_string(ff);
2000 if (!name) 1977 if (!name)
2001 goto error; 1978 goto error;
2002 1979
@@ -2007,12 +1984,12 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
2007 goto error; 1984 goto error;
2008 1985
2009 if (!strcmp(name, "msr")) 1986 if (!strcmp(name, "msr"))
2010 ph->env.msr_pmu_type = type; 1987 ff->ph->env.msr_pmu_type = type;
2011 1988
2012 free(name); 1989 free(name);
2013 pmu_num--; 1990 pmu_num--;
2014 } 1991 }
2015 ph->env.pmu_mappings = strbuf_detach(&sb, NULL); 1992 ff->ph->env.pmu_mappings = strbuf_detach(&sb, NULL);
2016 return 0; 1993 return 0;
2017 1994
2018error: 1995error:
@@ -2020,9 +1997,7 @@ error:
2020 return -1; 1997 return -1;
2021} 1998}
2022 1999
2023static int process_group_desc(struct perf_file_section *section __maybe_unused, 2000static 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{ 2001{
2027 size_t ret = -1; 2002 size_t ret = -1;
2028 u32 i, nr, nr_groups; 2003 u32 i, nr, nr_groups;
@@ -2034,13 +2009,10 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
2034 u32 nr_members; 2009 u32 nr_members;
2035 } *desc; 2010 } *desc;
2036 2011
2037 if (readn(fd, &nr_groups, sizeof(nr_groups)) != sizeof(nr_groups)) 2012 if (do_read_u32(ff, &nr_groups))
2038 return -1; 2013 return -1;
2039 2014
2040 if (ph->needs_swap) 2015 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) { 2016 if (!nr_groups) {
2045 pr_debug("group desc not available\n"); 2017 pr_debug("group desc not available\n");
2046 return 0; 2018 return 0;
@@ -2051,26 +2023,21 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
2051 return -1; 2023 return -1;
2052 2024
2053 for (i = 0; i < nr_groups; i++) { 2025 for (i = 0; i < nr_groups; i++) {
2054 desc[i].name = do_read_string(fd, ph); 2026 desc[i].name = do_read_string(ff);
2055 if (!desc[i].name) 2027 if (!desc[i].name)
2056 goto out_free; 2028 goto out_free;
2057 2029
2058 if (readn(fd, &desc[i].leader_idx, sizeof(u32)) != sizeof(u32)) 2030 if (do_read_u32(ff, &desc[i].leader_idx))
2059 goto out_free; 2031 goto out_free;
2060 2032
2061 if (readn(fd, &desc[i].nr_members, sizeof(u32)) != sizeof(u32)) 2033 if (do_read_u32(ff, &desc[i].nr_members))
2062 goto out_free; 2034 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 } 2035 }
2069 2036
2070 /* 2037 /*
2071 * Rebuild group relationship based on the group_desc 2038 * Rebuild group relationship based on the group_desc
2072 */ 2039 */
2073 session = container_of(ph, struct perf_session, header); 2040 session = container_of(ff->ph, struct perf_session, header);
2074 session->evlist->nr_groups = nr_groups; 2041 session->evlist->nr_groups = nr_groups;
2075 2042
2076 i = nr = 0; 2043 i = nr = 0;
@@ -2114,44 +2081,34 @@ out_free:
2114 return ret; 2081 return ret;
2115} 2082}
2116 2083
2117static int process_auxtrace(struct perf_file_section *section, 2084static int process_auxtrace(struct feat_fd *ff, void *data __maybe_unused)
2118 struct perf_header *ph, int fd,
2119 void *data __maybe_unused)
2120{ 2085{
2121 struct perf_session *session; 2086 struct perf_session *session;
2122 int err; 2087 int err;
2123 2088
2124 session = container_of(ph, struct perf_session, header); 2089 session = container_of(ff->ph, struct perf_session, header);
2125 2090
2126 err = auxtrace_index__process(fd, section->size, session, 2091 err = auxtrace_index__process(ff->fd, ff->size, session,
2127 ph->needs_swap); 2092 ff->ph->needs_swap);
2128 if (err < 0) 2093 if (err < 0)
2129 pr_err("Failed to process auxtrace index\n"); 2094 pr_err("Failed to process auxtrace index\n");
2130 return err; 2095 return err;
2131} 2096}
2132 2097
2133static int process_cache(struct perf_file_section *section __maybe_unused, 2098static 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{ 2099{
2137 struct cpu_cache_level *caches; 2100 struct cpu_cache_level *caches;
2138 u32 cnt, i, version; 2101 u32 cnt, i, version;
2139 2102
2140 if (readn(fd, &version, sizeof(version)) != sizeof(version)) 2103 if (do_read_u32(ff, &version))
2141 return -1; 2104 return -1;
2142 2105
2143 if (ph->needs_swap)
2144 version = bswap_32(version);
2145
2146 if (version != 1) 2106 if (version != 1)
2147 return -1; 2107 return -1;
2148 2108
2149 if (readn(fd, &cnt, sizeof(cnt)) != sizeof(cnt)) 2109 if (do_read_u32(ff, &cnt))
2150 return -1; 2110 return -1;
2151 2111
2152 if (ph->needs_swap)
2153 cnt = bswap_32(cnt);
2154
2155 caches = zalloc(sizeof(*caches) * cnt); 2112 caches = zalloc(sizeof(*caches) * cnt);
2156 if (!caches) 2113 if (!caches)
2157 return -1; 2114 return -1;
@@ -2160,10 +2117,8 @@ static int process_cache(struct perf_file_section *section __maybe_unused,
2160 struct cpu_cache_level c; 2117 struct cpu_cache_level c;
2161 2118
2162 #define _R(v) \ 2119 #define _R(v) \
2163 if (readn(fd, &c.v, sizeof(u32)) != sizeof(u32))\ 2120 if (do_read_u32(ff, &c.v))\
2164 goto out_free_caches; \ 2121 goto out_free_caches; \
2165 if (ph->needs_swap) \
2166 c.v = bswap_32(c.v); \
2167 2122
2168 _R(level) 2123 _R(level)
2169 _R(line_size) 2124 _R(line_size)
@@ -2171,9 +2126,9 @@ static int process_cache(struct perf_file_section *section __maybe_unused,
2171 _R(ways) 2126 _R(ways)
2172 #undef _R 2127 #undef _R
2173 2128
2174 #define _R(v) \ 2129 #define _R(v) \
2175 c.v = do_read_string(fd, ph); \ 2130 c.v = do_read_string(ff); \
2176 if (!c.v) \ 2131 if (!c.v) \
2177 goto out_free_caches; 2132 goto out_free_caches;
2178 2133
2179 _R(type) 2134 _R(type)
@@ -2184,8 +2139,8 @@ static int process_cache(struct perf_file_section *section __maybe_unused,
2184 caches[i] = c; 2139 caches[i] = c;
2185 } 2140 }
2186 2141
2187 ph->env.caches = caches; 2142 ff->ph->env.caches = caches;
2188 ph->env.caches_cnt = cnt; 2143 ff->ph->env.caches_cnt = cnt;
2189 return 0; 2144 return 0;
2190out_free_caches: 2145out_free_caches:
2191 free(caches); 2146 free(caches);
@@ -2193,48 +2148,62 @@ out_free_caches:
2193} 2148}
2194 2149
2195struct feature_ops { 2150struct feature_ops {
2196 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); 2151 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
2197 void (*print)(struct perf_header *h, int fd, FILE *fp); 2152 void (*print)(struct feat_fd *ff, FILE *fp);
2198 int (*process)(struct perf_file_section *section, 2153 int (*process)(struct feat_fd *ff, void *data);
2199 struct perf_header *h, int fd, void *data);
2200 const char *name; 2154 const char *name;
2201 bool full_only; 2155 bool full_only;
2156 bool synthesize;
2202}; 2157};
2203 2158
2204#define FEAT_OPA(n, func) \ 2159#define FEAT_OPR(n, func, __full_only) \
2205 [n] = { .name = #n, .write = write_##func, .print = print_##func } 2160 [HEADER_##n] = { \
2206#define FEAT_OPP(n, func) \ 2161 .name = __stringify(n), \
2207 [n] = { .name = #n, .write = write_##func, .print = print_##func, \ 2162 .write = write_##func, \
2208 .process = process_##func } 2163 .print = print_##func, \
2209#define FEAT_OPF(n, func) \ 2164 .full_only = __full_only, \
2210 [n] = { .name = #n, .write = write_##func, .print = print_##func, \ 2165 .process = process_##func, \
2211 .process = process_##func, .full_only = true } 2166 .synthesize = true \
2167 }
2168
2169#define FEAT_OPN(n, func, __full_only) \
2170 [HEADER_##n] = { \
2171 .name = __stringify(n), \
2172 .write = write_##func, \
2173 .print = print_##func, \
2174 .full_only = __full_only, \
2175 .process = process_##func \
2176 }
2212 2177
2213/* feature_ops not implemented: */ 2178/* feature_ops not implemented: */
2214#define print_tracing_data NULL 2179#define print_tracing_data NULL
2215#define print_build_id NULL 2180#define print_build_id NULL
2216 2181
2182#define process_branch_stack NULL
2183#define process_stat NULL
2184
2185
2217static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { 2186static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
2218 FEAT_OPP(HEADER_TRACING_DATA, tracing_data), 2187 FEAT_OPN(TRACING_DATA, tracing_data, false),
2219 FEAT_OPP(HEADER_BUILD_ID, build_id), 2188 FEAT_OPN(BUILD_ID, build_id, false),
2220 FEAT_OPP(HEADER_HOSTNAME, hostname), 2189 FEAT_OPR(HOSTNAME, hostname, false),
2221 FEAT_OPP(HEADER_OSRELEASE, osrelease), 2190 FEAT_OPR(OSRELEASE, osrelease, false),
2222 FEAT_OPP(HEADER_VERSION, version), 2191 FEAT_OPR(VERSION, version, false),
2223 FEAT_OPP(HEADER_ARCH, arch), 2192 FEAT_OPR(ARCH, arch, false),
2224 FEAT_OPP(HEADER_NRCPUS, nrcpus), 2193 FEAT_OPR(NRCPUS, nrcpus, false),
2225 FEAT_OPP(HEADER_CPUDESC, cpudesc), 2194 FEAT_OPR(CPUDESC, cpudesc, false),
2226 FEAT_OPP(HEADER_CPUID, cpuid), 2195 FEAT_OPR(CPUID, cpuid, false),
2227 FEAT_OPP(HEADER_TOTAL_MEM, total_mem), 2196 FEAT_OPR(TOTAL_MEM, total_mem, false),
2228 FEAT_OPP(HEADER_EVENT_DESC, event_desc), 2197 FEAT_OPR(EVENT_DESC, event_desc, false),
2229 FEAT_OPP(HEADER_CMDLINE, cmdline), 2198 FEAT_OPR(CMDLINE, cmdline, false),
2230 FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology), 2199 FEAT_OPR(CPU_TOPOLOGY, cpu_topology, true),
2231 FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology), 2200 FEAT_OPR(NUMA_TOPOLOGY, numa_topology, true),
2232 FEAT_OPA(HEADER_BRANCH_STACK, branch_stack), 2201 FEAT_OPN(BRANCH_STACK, branch_stack, false),
2233 FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings), 2202 FEAT_OPR(PMU_MAPPINGS, pmu_mappings, false),
2234 FEAT_OPP(HEADER_GROUP_DESC, group_desc), 2203 FEAT_OPN(GROUP_DESC, group_desc, false),
2235 FEAT_OPP(HEADER_AUXTRACE, auxtrace), 2204 FEAT_OPN(AUXTRACE, auxtrace, false),
2236 FEAT_OPA(HEADER_STAT, stat), 2205 FEAT_OPN(STAT, stat, false),
2237 FEAT_OPF(HEADER_CACHE, cache), 2206 FEAT_OPN(CACHE, cache, true),
2238}; 2207};
2239 2208
2240struct header_print_data { 2209struct header_print_data {
@@ -2247,6 +2216,7 @@ static int perf_file_section__fprintf_info(struct perf_file_section *section,
2247 int feat, int fd, void *data) 2216 int feat, int fd, void *data)
2248{ 2217{
2249 struct header_print_data *hd = data; 2218 struct header_print_data *hd = data;
2219 struct feat_fd ff;
2250 2220
2251 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) { 2221 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
2252 pr_debug("Failed to lseek to %" PRIu64 " offset for feature " 2222 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
@@ -2260,8 +2230,13 @@ static int perf_file_section__fprintf_info(struct perf_file_section *section,
2260 if (!feat_ops[feat].print) 2230 if (!feat_ops[feat].print)
2261 return 0; 2231 return 0;
2262 2232
2233 ff = (struct feat_fd) {
2234 .fd = fd,
2235 .ph = ph,
2236 };
2237
2263 if (!feat_ops[feat].full_only || hd->full) 2238 if (!feat_ops[feat].full_only || hd->full)
2264 feat_ops[feat].print(ph, fd, hd->fp); 2239 feat_ops[feat].print(&ff, hd->fp);
2265 else 2240 else
2266 fprintf(hd->fp, "# %s info available, use -I to display\n", 2241 fprintf(hd->fp, "# %s info available, use -I to display\n",
2267 feat_ops[feat].name); 2242 feat_ops[feat].name);
@@ -2302,29 +2277,32 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2302 return 0; 2277 return 0;
2303} 2278}
2304 2279
2305static int do_write_feat(int fd, struct perf_header *h, int type, 2280static int do_write_feat(struct feat_fd *ff, int type,
2306 struct perf_file_section **p, 2281 struct perf_file_section **p,
2307 struct perf_evlist *evlist) 2282 struct perf_evlist *evlist)
2308{ 2283{
2309 int err; 2284 int err;
2310 int ret = 0; 2285 int ret = 0;
2311 2286
2312 if (perf_header__has_feat(h, type)) { 2287 if (perf_header__has_feat(ff->ph, type)) {
2313 if (!feat_ops[type].write) 2288 if (!feat_ops[type].write)
2314 return -1; 2289 return -1;
2315 2290
2316 (*p)->offset = lseek(fd, 0, SEEK_CUR); 2291 if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
2292 return -1;
2317 2293
2318 err = feat_ops[type].write(fd, h, evlist); 2294 (*p)->offset = lseek(ff->fd, 0, SEEK_CUR);
2295
2296 err = feat_ops[type].write(ff, evlist);
2319 if (err < 0) { 2297 if (err < 0) {
2320 pr_debug("failed to write feature %s\n", feat_ops[type].name); 2298 pr_debug("failed to write feature %s\n", feat_ops[type].name);
2321 2299
2322 /* undo anything written */ 2300 /* undo anything written */
2323 lseek(fd, (*p)->offset, SEEK_SET); 2301 lseek(ff->fd, (*p)->offset, SEEK_SET);
2324 2302
2325 return -1; 2303 return -1;
2326 } 2304 }
2327 (*p)->size = lseek(fd, 0, SEEK_CUR) - (*p)->offset; 2305 (*p)->size = lseek(ff->fd, 0, SEEK_CUR) - (*p)->offset;
2328 (*p)++; 2306 (*p)++;
2329 } 2307 }
2330 return ret; 2308 return ret;
@@ -2334,12 +2312,18 @@ static int perf_header__adds_write(struct perf_header *header,
2334 struct perf_evlist *evlist, int fd) 2312 struct perf_evlist *evlist, int fd)
2335{ 2313{
2336 int nr_sections; 2314 int nr_sections;
2315 struct feat_fd ff;
2337 struct perf_file_section *feat_sec, *p; 2316 struct perf_file_section *feat_sec, *p;
2338 int sec_size; 2317 int sec_size;
2339 u64 sec_start; 2318 u64 sec_start;
2340 int feat; 2319 int feat;
2341 int err; 2320 int err;
2342 2321
2322 ff = (struct feat_fd){
2323 .fd = fd,
2324 .ph = header,
2325 };
2326
2343 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); 2327 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
2344 if (!nr_sections) 2328 if (!nr_sections)
2345 return 0; 2329 return 0;
@@ -2354,7 +2338,7 @@ static int perf_header__adds_write(struct perf_header *header,
2354 lseek(fd, sec_start + sec_size, SEEK_SET); 2338 lseek(fd, sec_start + sec_size, SEEK_SET);
2355 2339
2356 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) { 2340 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
2357 if (do_write_feat(fd, header, feat, &p, evlist)) 2341 if (do_write_feat(&ff, feat, &p, evlist))
2358 perf_header__clear_feat(header, feat); 2342 perf_header__clear_feat(header, feat);
2359 } 2343 }
2360 2344
@@ -2363,7 +2347,7 @@ static int perf_header__adds_write(struct perf_header *header,
2363 * may write more than needed due to dropped feature, but 2347 * may write more than needed due to dropped feature, but
2364 * this is okay, reader will skip the mising entries 2348 * this is okay, reader will skip the mising entries
2365 */ 2349 */
2366 err = do_write(fd, feat_sec, sec_size); 2350 err = do_write(&ff, feat_sec, sec_size);
2367 if (err < 0) 2351 if (err < 0)
2368 pr_debug("failed to write feature section\n"); 2352 pr_debug("failed to write feature section\n");
2369 free(feat_sec); 2353 free(feat_sec);
@@ -2373,14 +2357,17 @@ static int perf_header__adds_write(struct perf_header *header,
2373int perf_header__write_pipe(int fd) 2357int perf_header__write_pipe(int fd)
2374{ 2358{
2375 struct perf_pipe_file_header f_header; 2359 struct perf_pipe_file_header f_header;
2360 struct feat_fd ff;
2376 int err; 2361 int err;
2377 2362
2363 ff = (struct feat_fd){ .fd = fd };
2364
2378 f_header = (struct perf_pipe_file_header){ 2365 f_header = (struct perf_pipe_file_header){
2379 .magic = PERF_MAGIC, 2366 .magic = PERF_MAGIC,
2380 .size = sizeof(f_header), 2367 .size = sizeof(f_header),
2381 }; 2368 };
2382 2369
2383 err = do_write(fd, &f_header, sizeof(f_header)); 2370 err = do_write(&ff, &f_header, sizeof(f_header));
2384 if (err < 0) { 2371 if (err < 0) {
2385 pr_debug("failed to write perf pipe header\n"); 2372 pr_debug("failed to write perf pipe header\n");
2386 return err; 2373 return err;
@@ -2397,21 +2384,23 @@ int perf_session__write_header(struct perf_session *session,
2397 struct perf_file_attr f_attr; 2384 struct perf_file_attr f_attr;
2398 struct perf_header *header = &session->header; 2385 struct perf_header *header = &session->header;
2399 struct perf_evsel *evsel; 2386 struct perf_evsel *evsel;
2387 struct feat_fd ff;
2400 u64 attr_offset; 2388 u64 attr_offset;
2401 int err; 2389 int err;
2402 2390
2391 ff = (struct feat_fd){ .fd = fd};
2403 lseek(fd, sizeof(f_header), SEEK_SET); 2392 lseek(fd, sizeof(f_header), SEEK_SET);
2404 2393
2405 evlist__for_each_entry(session->evlist, evsel) { 2394 evlist__for_each_entry(session->evlist, evsel) {
2406 evsel->id_offset = lseek(fd, 0, SEEK_CUR); 2395 evsel->id_offset = lseek(fd, 0, SEEK_CUR);
2407 err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); 2396 err = do_write(&ff, evsel->id, evsel->ids * sizeof(u64));
2408 if (err < 0) { 2397 if (err < 0) {
2409 pr_debug("failed to write perf header\n"); 2398 pr_debug("failed to write perf header\n");
2410 return err; 2399 return err;
2411 } 2400 }
2412 } 2401 }
2413 2402
2414 attr_offset = lseek(fd, 0, SEEK_CUR); 2403 attr_offset = lseek(ff.fd, 0, SEEK_CUR);
2415 2404
2416 evlist__for_each_entry(evlist, evsel) { 2405 evlist__for_each_entry(evlist, evsel) {
2417 f_attr = (struct perf_file_attr){ 2406 f_attr = (struct perf_file_attr){
@@ -2421,7 +2410,7 @@ int perf_session__write_header(struct perf_session *session,
2421 .size = evsel->ids * sizeof(u64), 2410 .size = evsel->ids * sizeof(u64),
2422 } 2411 }
2423 }; 2412 };
2424 err = do_write(fd, &f_attr, sizeof(f_attr)); 2413 err = do_write(&ff, &f_attr, sizeof(f_attr));
2425 if (err < 0) { 2414 if (err < 0) {
2426 pr_debug("failed to write perf header attribute\n"); 2415 pr_debug("failed to write perf header attribute\n");
2427 return err; 2416 return err;
@@ -2456,7 +2445,7 @@ int perf_session__write_header(struct perf_session *session,
2456 memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features)); 2445 memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features));
2457 2446
2458 lseek(fd, 0, SEEK_SET); 2447 lseek(fd, 0, SEEK_SET);
2459 err = do_write(fd, &f_header, sizeof(f_header)); 2448 err = do_write(&ff, &f_header, sizeof(f_header));
2460 if (err < 0) { 2449 if (err < 0) {
2461 pr_debug("failed to write perf header\n"); 2450 pr_debug("failed to write perf header\n");
2462 return err; 2451 return err;
@@ -2710,6 +2699,13 @@ static int perf_file_section__process(struct perf_file_section *section,
2710 struct perf_header *ph, 2699 struct perf_header *ph,
2711 int feat, int fd, void *data) 2700 int feat, int fd, void *data)
2712{ 2701{
2702 struct feat_fd fdd = {
2703 .fd = fd,
2704 .ph = ph,
2705 .size = section->size,
2706 .offset = section->offset,
2707 };
2708
2713 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) { 2709 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
2714 pr_debug("Failed to lseek to %" PRIu64 " offset for feature " 2710 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
2715 "%d, continuing...\n", section->offset, feat); 2711 "%d, continuing...\n", section->offset, feat);
@@ -2724,13 +2720,17 @@ static int perf_file_section__process(struct perf_file_section *section,
2724 if (!feat_ops[feat].process) 2720 if (!feat_ops[feat].process)
2725 return 0; 2721 return 0;
2726 2722
2727 return feat_ops[feat].process(section, ph, fd, data); 2723 return feat_ops[feat].process(&fdd, data);
2728} 2724}
2729 2725
2730static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, 2726static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
2731 struct perf_header *ph, int fd, 2727 struct perf_header *ph, int fd,
2732 bool repipe) 2728 bool repipe)
2733{ 2729{
2730 struct feat_fd ff = {
2731 .fd = STDOUT_FILENO,
2732 .ph = ph,
2733 };
2734 ssize_t ret; 2734 ssize_t ret;
2735 2735
2736 ret = readn(fd, header, sizeof(*header)); 2736 ret = readn(fd, header, sizeof(*header));
@@ -2745,7 +2745,7 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
2745 if (ph->needs_swap) 2745 if (ph->needs_swap)
2746 header->size = bswap_64(header->size); 2746 header->size = bswap_64(header->size);
2747 2747
2748 if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0) 2748 if (repipe && do_write(&ff, header, sizeof(*header)) < 0)
2749 return -1; 2749 return -1;
2750 2750
2751 return 0; 2751 return 0;
@@ -2995,6 +2995,103 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
2995 return err; 2995 return err;
2996} 2996}
2997 2997
2998int perf_event__synthesize_features(struct perf_tool *tool,
2999 struct perf_session *session,
3000 struct perf_evlist *evlist,
3001 perf_event__handler_t process)
3002{
3003 struct perf_header *header = &session->header;
3004 struct feat_fd ff;
3005 struct feature_event *fe;
3006 size_t sz, sz_hdr;
3007 int feat, ret;
3008
3009 sz_hdr = sizeof(fe->header);
3010 sz = sizeof(union perf_event);
3011 /* get a nice alignment */
3012 sz = PERF_ALIGN(sz, page_size);
3013
3014 memset(&ff, 0, sizeof(ff));
3015
3016 ff.buf = malloc(sz);
3017 if (!ff.buf)
3018 return -ENOMEM;
3019
3020 ff.size = sz - sz_hdr;
3021
3022 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
3023 if (!feat_ops[feat].synthesize) {
3024 pr_debug("No record header feature for header :%d\n", feat);
3025 continue;
3026 }
3027
3028 ff.offset = sizeof(*fe);
3029
3030 ret = feat_ops[feat].write(&ff, evlist);
3031 if (ret || ff.offset <= (ssize_t)sizeof(*fe)) {
3032 pr_debug("Error writing feature\n");
3033 continue;
3034 }
3035 /* ff.buf may have changed due to realloc in do_write() */
3036 fe = ff.buf;
3037 memset(fe, 0, sizeof(*fe));
3038
3039 fe->feat_id = feat;
3040 fe->header.type = PERF_RECORD_HEADER_FEATURE;
3041 fe->header.size = ff.offset;
3042
3043 ret = process(tool, ff.buf, NULL, NULL);
3044 if (ret) {
3045 free(ff.buf);
3046 return ret;
3047 }
3048 }
3049 free(ff.buf);
3050 return 0;
3051}
3052
3053int perf_event__process_feature(struct perf_tool *tool,
3054 union perf_event *event,
3055 struct perf_session *session __maybe_unused)
3056{
3057 struct feat_fd ff = { .fd = 0 };
3058 struct feature_event *fe = (struct feature_event *)event;
3059 int type = fe->header.type;
3060 u64 feat = fe->feat_id;
3061
3062 if (type < 0 || type >= PERF_RECORD_HEADER_MAX) {
3063 pr_warning("invalid record type %d in pipe-mode\n", type);
3064 return 0;
3065 }
3066 if (feat == HEADER_RESERVED || feat > HEADER_LAST_FEATURE) {
3067 pr_warning("invalid record type %d in pipe-mode\n", type);
3068 return -1;
3069 }
3070
3071 if (!feat_ops[feat].process)
3072 return 0;
3073
3074 ff.buf = (void *)fe->data;
3075 ff.size = event->header.size - sizeof(event->header);
3076 ff.ph = &session->header;
3077
3078 if (feat_ops[feat].process(&ff, NULL))
3079 return -1;
3080
3081 if (!feat_ops[feat].print || !tool->show_feat_hdr)
3082 return 0;
3083
3084 if (!feat_ops[feat].full_only ||
3085 tool->show_feat_hdr >= SHOW_FEAT_HEADER_FULL_INFO) {
3086 feat_ops[feat].print(&ff, stdout);
3087 } else {
3088 fprintf(stdout, "# %s info available, use -I to display\n",
3089 feat_ops[feat].name);
3090 }
3091
3092 return 0;
3093}
3094
2998static struct event_update_event * 3095static struct event_update_event *
2999event_update_event__new(size_t size, u64 type, u64 id) 3096event_update_event__new(size_t size, u64 type, u64 id)
3000{ 3097{
@@ -3253,6 +3350,7 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
3253 union perf_event ev; 3350 union perf_event ev;
3254 struct tracing_data *tdata; 3351 struct tracing_data *tdata;
3255 ssize_t size = 0, aligned_size = 0, padding; 3352 ssize_t size = 0, aligned_size = 0, padding;
3353 struct feat_fd ff;
3256 int err __maybe_unused = 0; 3354 int err __maybe_unused = 0;
3257 3355
3258 /* 3356 /*
@@ -3287,7 +3385,9 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
3287 */ 3385 */
3288 tracing_data_put(tdata); 3386 tracing_data_put(tdata);
3289 3387
3290 write_padded(fd, NULL, 0, padding); 3388 ff = (struct feat_fd){ .fd = fd };
3389 if (write_padded(&ff, NULL, 0, padding))
3390 return -1;
3291 3391
3292 return aligned_size; 3392 return aligned_size;
3293} 3393}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index d30109b421ee..f7a16ee527b8 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -101,6 +101,15 @@ int perf_header__process_sections(struct perf_header *header, int fd,
101 101
102int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full); 102int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);
103 103
104int perf_event__synthesize_features(struct perf_tool *tool,
105 struct perf_session *session,
106 struct perf_evlist *evlist,
107 perf_event__handler_t process);
108
109int perf_event__process_feature(struct perf_tool *tool,
110 union perf_event *event,
111 struct perf_session *session);
112
104int perf_event__synthesize_attr(struct perf_tool *tool, 113int perf_event__synthesize_attr(struct perf_tool *tool,
105 struct perf_event_attr *attr, u32 ids, u64 *id, 114 struct perf_event_attr *attr, u32 ids, u64 *id,
106 perf_event__handler_t process); 115 perf_event__handler_t process);
@@ -144,7 +153,12 @@ bool is_perf_magic(u64 magic);
144 153
145#define NAME_ALIGN 64 154#define NAME_ALIGN 64
146 155
147int write_padded(int fd, const void *bf, size_t count, size_t count_aligned); 156struct feat_fd;
157
158int do_write(struct feat_fd *fd, const void *buf, size_t size);
159
160int write_padded(struct feat_fd *fd, const void *bf,
161 size_t count, size_t count_aligned);
148 162
149/* 163/*
150 * arch specific callback 164 * arch specific callback
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index cf0186a088c1..e60d8d8ea4c2 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -167,6 +167,10 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
167 symlen = unresolved_col_width + 4 + 2; 167 symlen = unresolved_col_width + 4 + 2;
168 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO); 168 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
169 } 169 }
170
171 hists__new_col_len(hists, HISTC_MEM_PHYS_DADDR,
172 unresolved_col_width + 4 + 2);
173
170 } else { 174 } else {
171 symlen = unresolved_col_width + 4 + 2; 175 symlen = unresolved_col_width + 4 + 2;
172 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen); 176 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen);
@@ -749,12 +753,9 @@ iter_prepare_branch_entry(struct hist_entry_iter *iter, struct addr_location *al
749} 753}
750 754
751static int 755static int
752iter_add_single_branch_entry(struct hist_entry_iter *iter, 756iter_add_single_branch_entry(struct hist_entry_iter *iter __maybe_unused,
753 struct addr_location *al __maybe_unused) 757 struct addr_location *al __maybe_unused)
754{ 758{
755 /* to avoid calling callback function */
756 iter->he = NULL;
757
758 return 0; 759 return 0;
759} 760}
760 761
@@ -1762,6 +1763,8 @@ void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *pro
1762 else 1763 else
1763 use_callchain = symbol_conf.use_callchain; 1764 use_callchain = symbol_conf.use_callchain;
1764 1765
1766 use_callchain |= symbol_conf.show_branchflag_count;
1767
1765 output_resort(evsel__hists(evsel), prog, use_callchain, NULL); 1768 output_resort(evsel__hists(evsel), prog, use_callchain, NULL);
1766} 1769}
1767 1770
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ee3670a388df..e60dda26a920 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -47,6 +47,7 @@ enum hist_column {
47 HISTC_GLOBAL_WEIGHT, 47 HISTC_GLOBAL_WEIGHT,
48 HISTC_MEM_DADDR_SYMBOL, 48 HISTC_MEM_DADDR_SYMBOL,
49 HISTC_MEM_DADDR_DSO, 49 HISTC_MEM_DADDR_DSO,
50 HISTC_MEM_PHYS_DADDR,
50 HISTC_MEM_LOCKED, 51 HISTC_MEM_LOCKED,
51 HISTC_MEM_TLB, 52 HISTC_MEM_TLB,
52 HISTC_MEM_LVL, 53 HISTC_MEM_LVL,
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/llvm-utils.c b/tools/perf/util/llvm-utils.c
index c6a15f204c03..209b0c82eff4 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -33,7 +33,7 @@ struct llvm_param llvm_param = {
33 33
34int perf_llvm_config(const char *var, const char *value) 34int perf_llvm_config(const char *var, const char *value)
35{ 35{
36 if (prefixcmp(var, "llvm.")) 36 if (!strstarts(var, "llvm."))
37 return 0; 37 return 0;
38 var += sizeof("llvm.") - 1; 38 var += sizeof("llvm.") - 1;
39 39
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 5de2b86b9880..df709363ef69 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -705,7 +705,8 @@ size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
705 705
706 if (kdso->has_build_id) { 706 if (kdso->has_build_id) {
707 char filename[PATH_MAX]; 707 char filename[PATH_MAX];
708 if (dso__build_id_filename(kdso, filename, sizeof(filename))) 708 if (dso__build_id_filename(kdso, filename, sizeof(filename),
709 false))
709 printed += fprintf(fp, "[0] %s\n", filename); 710 printed += fprintf(fp, "[0] %s\n", filename);
710 } 711 }
711 712
@@ -1137,7 +1138,8 @@ int __weak arch__fix_module_text_start(u64 *start __maybe_unused,
1137 return 0; 1138 return 0;
1138} 1139}
1139 1140
1140static int machine__create_module(void *arg, const char *name, u64 start) 1141static int machine__create_module(void *arg, const char *name, u64 start,
1142 u64 size)
1141{ 1143{
1142 struct machine *machine = arg; 1144 struct machine *machine = arg;
1143 struct map *map; 1145 struct map *map;
@@ -1148,6 +1150,7 @@ static int machine__create_module(void *arg, const char *name, u64 start)
1148 map = machine__findnew_module_map(machine, start, name); 1150 map = machine__findnew_module_map(machine, start, name);
1149 if (map == NULL) 1151 if (map == NULL)
1150 return -1; 1152 return -1;
1153 map->end = start + size;
1151 1154
1152 dso__kernel_module_get_build_id(map->dso, machine->root_dir); 1155 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
1153 1156
@@ -1392,7 +1395,7 @@ int machine__process_mmap2_event(struct machine *machine,
1392 1395
1393 map = map__new(machine, event->mmap2.start, 1396 map = map__new(machine, event->mmap2.start,
1394 event->mmap2.len, event->mmap2.pgoff, 1397 event->mmap2.len, event->mmap2.pgoff,
1395 event->mmap2.pid, event->mmap2.maj, 1398 event->mmap2.maj,
1396 event->mmap2.min, event->mmap2.ino, 1399 event->mmap2.min, event->mmap2.ino,
1397 event->mmap2.ino_generation, 1400 event->mmap2.ino_generation,
1398 event->mmap2.prot, 1401 event->mmap2.prot,
@@ -1450,7 +1453,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
1450 1453
1451 map = map__new(machine, event->mmap.start, 1454 map = map__new(machine, event->mmap.start,
1452 event->mmap.len, event->mmap.pgoff, 1455 event->mmap.len, event->mmap.pgoff,
1453 event->mmap.pid, 0, 0, 0, 0, 0, 0, 1456 0, 0, 0, 0, 0, 0,
1454 event->mmap.filename, 1457 event->mmap.filename,
1455 type, thread); 1458 type, thread);
1456 1459
@@ -1632,10 +1635,12 @@ static void ip__resolve_ams(struct thread *thread,
1632 ams->al_addr = al.addr; 1635 ams->al_addr = al.addr;
1633 ams->sym = al.sym; 1636 ams->sym = al.sym;
1634 ams->map = al.map; 1637 ams->map = al.map;
1638 ams->phys_addr = 0;
1635} 1639}
1636 1640
1637static void ip__resolve_data(struct thread *thread, 1641static void ip__resolve_data(struct thread *thread,
1638 u8 m, struct addr_map_symbol *ams, u64 addr) 1642 u8 m, struct addr_map_symbol *ams,
1643 u64 addr, u64 phys_addr)
1639{ 1644{
1640 struct addr_location al; 1645 struct addr_location al;
1641 1646
@@ -1655,6 +1660,7 @@ static void ip__resolve_data(struct thread *thread,
1655 ams->al_addr = al.addr; 1660 ams->al_addr = al.addr;
1656 ams->sym = al.sym; 1661 ams->sym = al.sym;
1657 ams->map = al.map; 1662 ams->map = al.map;
1663 ams->phys_addr = phys_addr;
1658} 1664}
1659 1665
1660struct mem_info *sample__resolve_mem(struct perf_sample *sample, 1666struct mem_info *sample__resolve_mem(struct perf_sample *sample,
@@ -1666,12 +1672,18 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1666 return NULL; 1672 return NULL;
1667 1673
1668 ip__resolve_ams(al->thread, &mi->iaddr, sample->ip); 1674 ip__resolve_ams(al->thread, &mi->iaddr, sample->ip);
1669 ip__resolve_data(al->thread, al->cpumode, &mi->daddr, sample->addr); 1675 ip__resolve_data(al->thread, al->cpumode, &mi->daddr,
1676 sample->addr, sample->phys_addr);
1670 mi->data_src.val = sample->data_src; 1677 mi->data_src.val = sample->data_src;
1671 1678
1672 return mi; 1679 return mi;
1673} 1680}
1674 1681
1682struct iterations {
1683 int nr_loop_iter;
1684 u64 cycles;
1685};
1686
1675static int add_callchain_ip(struct thread *thread, 1687static int add_callchain_ip(struct thread *thread,
1676 struct callchain_cursor *cursor, 1688 struct callchain_cursor *cursor,
1677 struct symbol **parent, 1689 struct symbol **parent,
@@ -1680,10 +1692,12 @@ static int add_callchain_ip(struct thread *thread,
1680 u64 ip, 1692 u64 ip,
1681 bool branch, 1693 bool branch,
1682 struct branch_flags *flags, 1694 struct branch_flags *flags,
1683 int nr_loop_iter, 1695 struct iterations *iter,
1684 int samples) 1696 u64 branch_from)
1685{ 1697{
1686 struct addr_location al; 1698 struct addr_location al;
1699 int nr_loop_iter = 0;
1700 u64 iter_cycles = 0;
1687 1701
1688 al.filtered = 0; 1702 al.filtered = 0;
1689 al.sym = NULL; 1703 al.sym = NULL;
@@ -1733,8 +1747,15 @@ static int add_callchain_ip(struct thread *thread,
1733 1747
1734 if (symbol_conf.hide_unresolved && al.sym == NULL) 1748 if (symbol_conf.hide_unresolved && al.sym == NULL)
1735 return 0; 1749 return 0;
1750
1751 if (iter) {
1752 nr_loop_iter = iter->nr_loop_iter;
1753 iter_cycles = iter->cycles;
1754 }
1755
1736 return callchain_cursor_append(cursor, al.addr, al.map, al.sym, 1756 return callchain_cursor_append(cursor, al.addr, al.map, al.sym,
1737 branch, flags, nr_loop_iter, samples); 1757 branch, flags, nr_loop_iter,
1758 iter_cycles, branch_from);
1738} 1759}
1739 1760
1740struct branch_info *sample__resolve_bstack(struct perf_sample *sample, 1761struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
@@ -1755,6 +1776,18 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
1755 return bi; 1776 return bi;
1756} 1777}
1757 1778
1779static void save_iterations(struct iterations *iter,
1780 struct branch_entry *be, int nr)
1781{
1782 int i;
1783
1784 iter->nr_loop_iter = nr;
1785 iter->cycles = 0;
1786
1787 for (i = 0; i < nr; i++)
1788 iter->cycles += be[i].flags.cycles;
1789}
1790
1758#define CHASHSZ 127 1791#define CHASHSZ 127
1759#define CHASHBITS 7 1792#define CHASHBITS 7
1760#define NO_ENTRY 0xff 1793#define NO_ENTRY 0xff
@@ -1762,7 +1795,8 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
1762#define PERF_MAX_BRANCH_DEPTH 127 1795#define PERF_MAX_BRANCH_DEPTH 127
1763 1796
1764/* Remove loops. */ 1797/* Remove loops. */
1765static int remove_loops(struct branch_entry *l, int nr) 1798static int remove_loops(struct branch_entry *l, int nr,
1799 struct iterations *iter)
1766{ 1800{
1767 int i, j, off; 1801 int i, j, off;
1768 unsigned char chash[CHASHSZ]; 1802 unsigned char chash[CHASHSZ];
@@ -1787,8 +1821,18 @@ static int remove_loops(struct branch_entry *l, int nr)
1787 break; 1821 break;
1788 } 1822 }
1789 if (is_loop) { 1823 if (is_loop) {
1790 memmove(l + i, l + i + off, 1824 j = nr - (i + off);
1791 (nr - (i + off)) * sizeof(*l)); 1825 if (j > 0) {
1826 save_iterations(iter + i + off,
1827 l + i, off);
1828
1829 memmove(iter + i, iter + i + off,
1830 j * sizeof(*iter));
1831
1832 memmove(l + i, l + i + off,
1833 j * sizeof(*l));
1834 }
1835
1792 nr -= off; 1836 nr -= off;
1793 } 1837 }
1794 } 1838 }
@@ -1813,7 +1857,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1813 struct ip_callchain *chain = sample->callchain; 1857 struct ip_callchain *chain = sample->callchain;
1814 int chain_nr = min(max_stack, (int)chain->nr), i; 1858 int chain_nr = min(max_stack, (int)chain->nr), i;
1815 u8 cpumode = PERF_RECORD_MISC_USER; 1859 u8 cpumode = PERF_RECORD_MISC_USER;
1816 u64 ip; 1860 u64 ip, branch_from = 0;
1817 1861
1818 for (i = 0; i < chain_nr; i++) { 1862 for (i = 0; i < chain_nr; i++) {
1819 if (chain->ips[i] == PERF_CONTEXT_USER) 1863 if (chain->ips[i] == PERF_CONTEXT_USER)
@@ -1855,6 +1899,8 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1855 ip = lbr_stack->entries[0].to; 1899 ip = lbr_stack->entries[0].to;
1856 branch = true; 1900 branch = true;
1857 flags = &lbr_stack->entries[0].flags; 1901 flags = &lbr_stack->entries[0].flags;
1902 branch_from =
1903 lbr_stack->entries[0].from;
1858 } 1904 }
1859 } else { 1905 } else {
1860 if (j < lbr_nr) { 1906 if (j < lbr_nr) {
@@ -1869,12 +1915,15 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1869 ip = lbr_stack->entries[0].to; 1915 ip = lbr_stack->entries[0].to;
1870 branch = true; 1916 branch = true;
1871 flags = &lbr_stack->entries[0].flags; 1917 flags = &lbr_stack->entries[0].flags;
1918 branch_from =
1919 lbr_stack->entries[0].from;
1872 } 1920 }
1873 } 1921 }
1874 1922
1875 err = add_callchain_ip(thread, cursor, parent, 1923 err = add_callchain_ip(thread, cursor, parent,
1876 root_al, &cpumode, ip, 1924 root_al, &cpumode, ip,
1877 branch, flags, 0, 0); 1925 branch, flags, NULL,
1926 branch_from);
1878 if (err) 1927 if (err)
1879 return (err < 0) ? err : 0; 1928 return (err < 0) ? err : 0;
1880 } 1929 }
@@ -1894,12 +1943,14 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1894{ 1943{
1895 struct branch_stack *branch = sample->branch_stack; 1944 struct branch_stack *branch = sample->branch_stack;
1896 struct ip_callchain *chain = sample->callchain; 1945 struct ip_callchain *chain = sample->callchain;
1897 int chain_nr = chain->nr; 1946 int chain_nr = 0;
1898 u8 cpumode = PERF_RECORD_MISC_USER; 1947 u8 cpumode = PERF_RECORD_MISC_USER;
1899 int i, j, err, nr_entries; 1948 int i, j, err, nr_entries;
1900 int skip_idx = -1; 1949 int skip_idx = -1;
1901 int first_call = 0; 1950 int first_call = 0;
1902 int nr_loop_iter; 1951
1952 if (chain)
1953 chain_nr = chain->nr;
1903 1954
1904 if (perf_evsel__has_branch_callstack(evsel)) { 1955 if (perf_evsel__has_branch_callstack(evsel)) {
1905 err = resolve_lbr_callchain_sample(thread, cursor, sample, parent, 1956 err = resolve_lbr_callchain_sample(thread, cursor, sample, parent,
@@ -1929,6 +1980,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1929 if (branch && callchain_param.branch_callstack) { 1980 if (branch && callchain_param.branch_callstack) {
1930 int nr = min(max_stack, (int)branch->nr); 1981 int nr = min(max_stack, (int)branch->nr);
1931 struct branch_entry be[nr]; 1982 struct branch_entry be[nr];
1983 struct iterations iter[nr];
1932 1984
1933 if (branch->nr > PERF_MAX_BRANCH_DEPTH) { 1985 if (branch->nr > PERF_MAX_BRANCH_DEPTH) {
1934 pr_warning("corrupted branch chain. skipping...\n"); 1986 pr_warning("corrupted branch chain. skipping...\n");
@@ -1938,6 +1990,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1938 for (i = 0; i < nr; i++) { 1990 for (i = 0; i < nr; i++) {
1939 if (callchain_param.order == ORDER_CALLEE) { 1991 if (callchain_param.order == ORDER_CALLEE) {
1940 be[i] = branch->entries[i]; 1992 be[i] = branch->entries[i];
1993
1994 if (chain == NULL)
1995 continue;
1996
1941 /* 1997 /*
1942 * Check for overlap into the callchain. 1998 * Check for overlap into the callchain.
1943 * The return address is one off compared to 1999 * The return address is one off compared to
@@ -1955,42 +2011,30 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1955 be[i] = branch->entries[branch->nr - i - 1]; 2011 be[i] = branch->entries[branch->nr - i - 1];
1956 } 2012 }
1957 2013
1958 nr_loop_iter = nr; 2014 memset(iter, 0, sizeof(struct iterations) * nr);
1959 nr = remove_loops(be, nr); 2015 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 2016
1970 for (i = 0; i < nr; i++) { 2017 for (i = 0; i < nr; i++) {
1971 if (i == nr - 1) 2018 err = add_callchain_ip(thread, cursor, parent,
1972 err = add_callchain_ip(thread, cursor, parent, 2019 root_al,
1973 root_al, 2020 NULL, be[i].to,
1974 NULL, be[i].to, 2021 true, &be[i].flags,
1975 true, &be[i].flags, 2022 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 2023
1984 if (!err) 2024 if (!err)
1985 err = add_callchain_ip(thread, cursor, parent, root_al, 2025 err = add_callchain_ip(thread, cursor, parent, root_al,
1986 NULL, be[i].from, 2026 NULL, be[i].from,
1987 true, &be[i].flags, 2027 true, &be[i].flags,
1988 0, 0); 2028 &iter[i], 0);
1989 if (err == -EINVAL) 2029 if (err == -EINVAL)
1990 break; 2030 break;
1991 if (err) 2031 if (err)
1992 return err; 2032 return err;
1993 } 2033 }
2034
2035 if (chain_nr == 0)
2036 return 0;
2037
1994 chain_nr -= nr; 2038 chain_nr -= nr;
1995 } 2039 }
1996 2040
@@ -2015,7 +2059,7 @@ check_calls:
2015 2059
2016 err = add_callchain_ip(thread, cursor, parent, 2060 err = add_callchain_ip(thread, cursor, parent,
2017 root_al, &cpumode, ip, 2061 root_al, &cpumode, ip,
2018 false, NULL, 0, 0); 2062 false, NULL, NULL, 0);
2019 2063
2020 if (err) 2064 if (err)
2021 return (err < 0) ? err : 0; 2065 return (err < 0) ? err : 0;
@@ -2032,7 +2076,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
2032 return 0; 2076 return 0;
2033 return callchain_cursor_append(cursor, entry->ip, 2077 return callchain_cursor_append(cursor, entry->ip,
2034 entry->map, entry->sym, 2078 entry->map, entry->sym,
2035 false, NULL, 0, 0); 2079 false, NULL, 0, 0, 0);
2036} 2080}
2037 2081
2038static int thread__resolve_callchain_unwind(struct thread *thread, 2082static int thread__resolve_callchain_unwind(struct thread *thread,
@@ -2209,7 +2253,7 @@ int machine__get_kernel_start(struct machine *machine)
2209 machine->kernel_start = 1ULL << 63; 2253 machine->kernel_start = 1ULL << 63;
2210 if (map) { 2254 if (map) {
2211 err = map__load(map); 2255 err = map__load(map);
2212 if (map->start) 2256 if (!err)
2213 machine->kernel_start = map->start; 2257 machine->kernel_start = map->start;
2214 } 2258 }
2215 return err; 2259 return err;
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 2179b2deb730..bdaa0a4edc17 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -16,6 +16,7 @@
16#include "machine.h" 16#include "machine.h"
17#include <linux/string.h> 17#include <linux/string.h>
18#include "srcline.h" 18#include "srcline.h"
19#include "namespaces.h"
19#include "unwind.h" 20#include "unwind.h"
20 21
21static void __maps__insert(struct maps *maps, struct map *map); 22static void __maps__insert(struct maps *maps, struct map *map);
@@ -145,11 +146,13 @@ void map__init(struct map *map, enum map_type type,
145} 146}
146 147
147struct map *map__new(struct machine *machine, u64 start, u64 len, 148struct map *map__new(struct machine *machine, u64 start, u64 len,
148 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, 149 u64 pgoff, u32 d_maj, u32 d_min, u64 ino,
149 u64 ino_gen, u32 prot, u32 flags, char *filename, 150 u64 ino_gen, u32 prot, u32 flags, char *filename,
150 enum map_type type, struct thread *thread) 151 enum map_type type, struct thread *thread)
151{ 152{
152 struct map *map = malloc(sizeof(*map)); 153 struct map *map = malloc(sizeof(*map));
154 struct nsinfo *nsi = NULL;
155 struct nsinfo *nnsi;
153 156
154 if (map != NULL) { 157 if (map != NULL) {
155 char newfilename[PATH_MAX]; 158 char newfilename[PATH_MAX];
@@ -167,9 +170,11 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
167 map->ino_generation = ino_gen; 170 map->ino_generation = ino_gen;
168 map->prot = prot; 171 map->prot = prot;
169 map->flags = flags; 172 map->flags = flags;
173 nsi = nsinfo__get(thread->nsinfo);
170 174
171 if ((anon || no_dso) && type == MAP__FUNCTION) { 175 if ((anon || no_dso) && nsi && type == MAP__FUNCTION) {
172 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); 176 snprintf(newfilename, sizeof(newfilename),
177 "/tmp/perf-%d.map", nsi->pid);
173 filename = newfilename; 178 filename = newfilename;
174 } 179 }
175 180
@@ -179,6 +184,16 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
179 } 184 }
180 185
181 if (vdso) { 186 if (vdso) {
187 /* The vdso maps are always on the host and not the
188 * container. Ensure that we don't use setns to look
189 * them up.
190 */
191 nnsi = nsinfo__copy(nsi);
192 if (nnsi) {
193 nsinfo__put(nsi);
194 nnsi->need_setns = false;
195 nsi = nnsi;
196 }
182 pgoff = 0; 197 pgoff = 0;
183 dso = machine__findnew_vdso(machine, thread); 198 dso = machine__findnew_vdso(machine, thread);
184 } else 199 } else
@@ -200,10 +215,12 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
200 if (type != MAP__FUNCTION) 215 if (type != MAP__FUNCTION)
201 dso__set_loaded(dso, map->type); 216 dso__set_loaded(dso, map->type);
202 } 217 }
218 dso->nsinfo = nsi;
203 dso__put(dso); 219 dso__put(dso);
204 } 220 }
205 return map; 221 return map;
206out_delete: 222out_delete:
223 nsinfo__put(nsi);
207 free(map); 224 free(map);
208 return NULL; 225 return NULL;
209} 226}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index f9e8ac8a52cd..73aacf7a7dc4 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -141,7 +141,7 @@ struct thread;
141void map__init(struct map *map, enum map_type type, 141void map__init(struct map *map, enum map_type type,
142 u64 start, u64 end, u64 pgoff, struct dso *dso); 142 u64 start, u64 end, u64 pgoff, struct dso *dso);
143struct map *map__new(struct machine *machine, u64 start, u64 len, 143struct map *map__new(struct machine *machine, u64 start, u64 len,
144 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, 144 u64 pgoff, u32 d_maj, u32 d_min, u64 ino,
145 u64 ino_gen, u32 prot, u32 flags, 145 u64 ino_gen, u32 prot, u32 flags,
146 char *filename, enum map_type type, struct thread *thread); 146 char *filename, enum map_type type, struct thread *thread);
147struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 147struct 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..28afe5fa84d6 100644
--- a/tools/perf/util/mem-events.c
+++ b/tools/perf/util/mem-events.c
@@ -166,11 +166,20 @@ static const char * const mem_lvl[] = {
166 "Uncached", 166 "Uncached",
167}; 167};
168 168
169static const char * const mem_lvlnum[] = {
170 [PERF_MEM_LVLNUM_ANY_CACHE] = "Any cache",
171 [PERF_MEM_LVLNUM_LFB] = "LFB",
172 [PERF_MEM_LVLNUM_RAM] = "RAM",
173 [PERF_MEM_LVLNUM_PMEM] = "PMEM",
174 [PERF_MEM_LVLNUM_NA] = "N/A",
175};
176
169int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info) 177int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
170{ 178{
171 size_t i, l = 0; 179 size_t i, l = 0;
172 u64 m = PERF_MEM_LVL_NA; 180 u64 m = PERF_MEM_LVL_NA;
173 u64 hit, miss; 181 u64 hit, miss;
182 int printed;
174 183
175 if (mem_info) 184 if (mem_info)
176 m = mem_info->data_src.mem_lvl; 185 m = mem_info->data_src.mem_lvl;
@@ -184,17 +193,37 @@ int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
184 /* already taken care of */ 193 /* already taken care of */
185 m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS); 194 m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
186 195
196
197 if (mem_info && mem_info->data_src.mem_remote) {
198 strcat(out, "Remote ");
199 l += 7;
200 }
201
202 printed = 0;
187 for (i = 0; m && i < ARRAY_SIZE(mem_lvl); i++, m >>= 1) { 203 for (i = 0; m && i < ARRAY_SIZE(mem_lvl); i++, m >>= 1) {
188 if (!(m & 0x1)) 204 if (!(m & 0x1))
189 continue; 205 continue;
190 if (l) { 206 if (printed++) {
191 strcat(out, " or "); 207 strcat(out, " or ");
192 l += 4; 208 l += 4;
193 } 209 }
194 l += scnprintf(out + l, sz - l, mem_lvl[i]); 210 l += scnprintf(out + l, sz - l, mem_lvl[i]);
195 } 211 }
196 if (*out == '\0') 212
197 l += scnprintf(out, sz - l, "N/A"); 213 if (mem_info && mem_info->data_src.mem_lvl_num) {
214 int lvl = mem_info->data_src.mem_lvl_num;
215 if (printed++) {
216 strcat(out, " or ");
217 l += 4;
218 }
219 if (mem_lvlnum[lvl])
220 l += scnprintf(out + l, sz - l, mem_lvlnum[lvl]);
221 else
222 l += scnprintf(out + l, sz - l, "L%d", lvl);
223 }
224
225 if (l == 0)
226 l += scnprintf(out + l, sz - l, "N/A");
198 if (hit) 227 if (hit)
199 l += scnprintf(out + l, sz - l, " hit"); 228 l += scnprintf(out + l, sz - l, " hit");
200 if (miss) 229 if (miss)
@@ -231,6 +260,14 @@ int perf_mem__snp_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
231 } 260 }
232 l += scnprintf(out + l, sz - l, snoop_access[i]); 261 l += scnprintf(out + l, sz - l, snoop_access[i]);
233 } 262 }
263 if (mem_info &&
264 (mem_info->data_src.mem_snoopx & PERF_MEM_SNOOPX_FWD)) {
265 if (l) {
266 strcat(out, " or ");
267 l += 4;
268 }
269 l += scnprintf(out + l, sz - l, "Fwd");
270 }
234 271
235 if (*out == '\0') 272 if (*out == '\0')
236 l += scnprintf(out, sz - l, "N/A"); 273 l += scnprintf(out, sz - l, "N/A");
@@ -279,6 +316,11 @@ int c2c_decode_stats(struct c2c_stats *stats, struct mem_info *mi)
279 u64 lvl = data_src->mem_lvl; 316 u64 lvl = data_src->mem_lvl;
280 u64 snoop = data_src->mem_snoop; 317 u64 snoop = data_src->mem_snoop;
281 u64 lock = data_src->mem_lock; 318 u64 lock = data_src->mem_lock;
319 /*
320 * Skylake might report unknown remote level via this
321 * bit, consider it when evaluating remote HITMs.
322 */
323 bool mrem = data_src->mem_remote;
282 int err = 0; 324 int err = 0;
283 325
284#define HITM_INC(__f) \ 326#define HITM_INC(__f) \
@@ -324,7 +366,8 @@ do { \
324 } 366 }
325 367
326 if ((lvl & P(LVL, REM_RAM1)) || 368 if ((lvl & P(LVL, REM_RAM1)) ||
327 (lvl & P(LVL, REM_RAM2))) { 369 (lvl & P(LVL, REM_RAM2)) ||
370 mrem) {
328 stats->rmt_dram++; 371 stats->rmt_dram++;
329 if (snoop & P(SNOOP, HIT)) 372 if (snoop & P(SNOOP, HIT))
330 stats->ld_shared++; 373 stats->ld_shared++;
@@ -334,7 +377,8 @@ do { \
334 } 377 }
335 378
336 if ((lvl & P(LVL, REM_CCE1)) || 379 if ((lvl & P(LVL, REM_CCE1)) ||
337 (lvl & P(LVL, REM_CCE2))) { 380 (lvl & P(LVL, REM_CCE2)) ||
381 mrem) {
338 if (snoop & P(SNOOP, HIT)) 382 if (snoop & P(SNOOP, HIT))
339 stats->rmt_hit++; 383 stats->rmt_hit++;
340 else if (snoop & P(SNOOP, HITM)) 384 else if (snoop & P(SNOOP, HITM))
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
index 67dcbcc73c7d..a58e91197729 100644
--- a/tools/perf/util/namespaces.c
+++ b/tools/perf/util/namespaces.c
@@ -9,9 +9,14 @@
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 <limits.h>
15#include <sched.h>
12#include <stdlib.h> 16#include <stdlib.h>
13#include <stdio.h> 17#include <stdio.h>
14#include <string.h> 18#include <string.h>
19#include <unistd.h>
15 20
16struct namespaces *namespaces__new(struct namespaces_event *event) 21struct namespaces *namespaces__new(struct namespaces_event *event)
17{ 22{
@@ -35,3 +40,209 @@ void namespaces__free(struct namespaces *namespaces)
35{ 40{
36 free(namespaces); 41 free(namespaces);
37} 42}
43
44int nsinfo__init(struct nsinfo *nsi)
45{
46 char oldns[PATH_MAX];
47 char spath[PATH_MAX];
48 char *newns = NULL;
49 char *statln = NULL;
50 struct stat old_stat;
51 struct stat new_stat;
52 FILE *f = NULL;
53 size_t linesz = 0;
54 int rv = -1;
55
56 if (snprintf(oldns, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
57 return rv;
58
59 if (asprintf(&newns, "/proc/%d/ns/mnt", nsi->pid) == -1)
60 return rv;
61
62 if (stat(oldns, &old_stat) < 0)
63 goto out;
64
65 if (stat(newns, &new_stat) < 0)
66 goto out;
67
68 /* Check if the mount namespaces differ, if so then indicate that we
69 * want to switch as part of looking up dso/map data.
70 */
71 if (old_stat.st_ino != new_stat.st_ino) {
72 nsi->need_setns = true;
73 nsi->mntns_path = newns;
74 newns = NULL;
75 }
76
77 /* If we're dealing with a process that is in a different PID namespace,
78 * attempt to work out the innermost tgid for the process.
79 */
80 if (snprintf(spath, PATH_MAX, "/proc/%d/status", nsi->pid) >= PATH_MAX)
81 goto out;
82
83 f = fopen(spath, "r");
84 if (f == NULL)
85 goto out;
86
87 while (getline(&statln, &linesz, f) != -1) {
88 /* Use tgid if CONFIG_PID_NS is not defined. */
89 if (strstr(statln, "Tgid:") != NULL) {
90 nsi->tgid = (pid_t)strtol(strrchr(statln, '\t'),
91 NULL, 10);
92 nsi->nstgid = nsi->tgid;
93 }
94
95 if (strstr(statln, "NStgid:") != NULL) {
96 nsi->nstgid = (pid_t)strtol(strrchr(statln, '\t'),
97 NULL, 10);
98 break;
99 }
100 }
101 rv = 0;
102
103out:
104 if (f != NULL)
105 (void) fclose(f);
106 free(statln);
107 free(newns);
108 return rv;
109}
110
111struct nsinfo *nsinfo__new(pid_t pid)
112{
113 struct nsinfo *nsi;
114
115 if (pid == 0)
116 return NULL;
117
118 nsi = calloc(1, sizeof(*nsi));
119 if (nsi != NULL) {
120 nsi->pid = pid;
121 nsi->tgid = pid;
122 nsi->nstgid = pid;
123 nsi->need_setns = false;
124 /* Init may fail if the process exits while we're trying to look
125 * at its proc information. In that case, save the pid but
126 * don't try to enter the namespace.
127 */
128 if (nsinfo__init(nsi) == -1)
129 nsi->need_setns = false;
130
131 refcount_set(&nsi->refcnt, 1);
132 }
133
134 return nsi;
135}
136
137struct nsinfo *nsinfo__copy(struct nsinfo *nsi)
138{
139 struct nsinfo *nnsi;
140
141 nnsi = calloc(1, sizeof(*nnsi));
142 if (nnsi != NULL) {
143 nnsi->pid = nsi->pid;
144 nnsi->tgid = nsi->tgid;
145 nnsi->nstgid = nsi->nstgid;
146 nnsi->need_setns = nsi->need_setns;
147 if (nsi->mntns_path) {
148 nnsi->mntns_path = strdup(nsi->mntns_path);
149 if (!nnsi->mntns_path) {
150 free(nnsi);
151 return NULL;
152 }
153 }
154 refcount_set(&nnsi->refcnt, 1);
155 }
156
157 return nnsi;
158}
159
160void nsinfo__delete(struct nsinfo *nsi)
161{
162 zfree(&nsi->mntns_path);
163 free(nsi);
164}
165
166struct nsinfo *nsinfo__get(struct nsinfo *nsi)
167{
168 if (nsi)
169 refcount_inc(&nsi->refcnt);
170 return nsi;
171}
172
173void nsinfo__put(struct nsinfo *nsi)
174{
175 if (nsi && refcount_dec_and_test(&nsi->refcnt))
176 nsinfo__delete(nsi);
177}
178
179void nsinfo__mountns_enter(struct nsinfo *nsi,
180 struct nscookie *nc)
181{
182 char curpath[PATH_MAX];
183 int oldns = -1;
184 int newns = -1;
185
186 if (nc == NULL)
187 return;
188
189 nc->oldns = -1;
190 nc->newns = -1;
191
192 if (!nsi || !nsi->need_setns)
193 return;
194
195 if (snprintf(curpath, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
196 return;
197
198 oldns = open(curpath, O_RDONLY);
199 if (oldns < 0)
200 return;
201
202 newns = open(nsi->mntns_path, O_RDONLY);
203 if (newns < 0)
204 goto errout;
205
206 if (setns(newns, CLONE_NEWNS) < 0)
207 goto errout;
208
209 nc->oldns = oldns;
210 nc->newns = newns;
211 return;
212
213errout:
214 if (oldns > -1)
215 close(oldns);
216 if (newns > -1)
217 close(newns);
218}
219
220void nsinfo__mountns_exit(struct nscookie *nc)
221{
222 if (nc == NULL || nc->oldns == -1 || nc->newns == -1)
223 return;
224
225 setns(nc->oldns, CLONE_NEWNS);
226
227 if (nc->oldns > -1) {
228 close(nc->oldns);
229 nc->oldns = -1;
230 }
231
232 if (nc->newns > -1) {
233 close(nc->newns);
234 nc->newns = -1;
235 }
236}
237
238char *nsinfo__realpath(const char *path, struct nsinfo *nsi)
239{
240 char *rpath;
241 struct nscookie nsc;
242
243 nsinfo__mountns_enter(nsi, &nsc);
244 rpath = realpath(path, NULL);
245 nsinfo__mountns_exit(&nsc);
246
247 return rpath;
248}
diff --git a/tools/perf/util/namespaces.h b/tools/perf/util/namespaces.h
index 468f1e9a1484..05d82601c9a6 100644
--- a/tools/perf/util/namespaces.h
+++ b/tools/perf/util/namespaces.h
@@ -11,6 +11,7 @@
11 11
12#include "../perf.h" 12#include "../perf.h"
13#include <linux/list.h> 13#include <linux/list.h>
14#include <linux/refcount.h>
14 15
15struct namespaces_event; 16struct namespaces_event;
16 17
@@ -23,4 +24,41 @@ struct namespaces {
23struct namespaces *namespaces__new(struct namespaces_event *event); 24struct namespaces *namespaces__new(struct namespaces_event *event);
24void namespaces__free(struct namespaces *namespaces); 25void namespaces__free(struct namespaces *namespaces);
25 26
27struct nsinfo {
28 pid_t pid;
29 pid_t tgid;
30 pid_t nstgid;
31 bool need_setns;
32 char *mntns_path;
33 refcount_t refcnt;
34};
35
36struct nscookie {
37 int oldns;
38 int newns;
39};
40
41int nsinfo__init(struct nsinfo *nsi);
42struct nsinfo *nsinfo__new(pid_t pid);
43struct nsinfo *nsinfo__copy(struct nsinfo *nsi);
44void nsinfo__delete(struct nsinfo *nsi);
45
46struct nsinfo *nsinfo__get(struct nsinfo *nsi);
47void nsinfo__put(struct nsinfo *nsi);
48
49void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc);
50void nsinfo__mountns_exit(struct nscookie *nc);
51
52char *nsinfo__realpath(const char *path, struct nsinfo *nsi);
53
54static inline void __nsinfo__zput(struct nsinfo **nsip)
55{
56 if (nsip) {
57 nsinfo__put(*nsip);
58 *nsip = NULL;
59 }
60}
61
62#define nsinfo__zput(nsi) __nsinfo__zput(&nsi)
63
26#endif /* __PERF_NAMESPACES_H */ 64#endif /* __PERF_NAMESPACES_H */
diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c
index 38fd11504015..e71fb5f31e84 100644
--- a/tools/perf/util/parse-branch-options.c
+++ b/tools/perf/util/parse-branch-options.c
@@ -28,6 +28,7 @@ static const struct branch_mode branch_modes[] = {
28 BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND), 28 BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND),
29 BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP), 29 BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP),
30 BRANCH_OPT("call", PERF_SAMPLE_BRANCH_CALL), 30 BRANCH_OPT("call", PERF_SAMPLE_BRANCH_CALL),
31 BRANCH_OPT("save_type", PERF_SAMPLE_BRANCH_TYPE_SAVE),
31 BRANCH_END 32 BRANCH_END
32}; 33};
33 34
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 01e779b91c8e..f6257fb4f08c 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -34,7 +34,7 @@
34#ifdef PARSER_DEBUG 34#ifdef PARSER_DEBUG
35extern int parse_events_debug; 35extern int parse_events_debug;
36#endif 36#endif
37int parse_events_parse(void *data, void *scanner); 37int parse_events_parse(void *parse_state, void *scanner);
38static int get_config_terms(struct list_head *head_config, 38static int get_config_terms(struct list_head *head_config,
39 struct list_head *head_terms __maybe_unused); 39 struct list_head *head_terms __maybe_unused);
40 40
@@ -310,7 +310,7 @@ static struct perf_evsel *
310__add_event(struct list_head *list, int *idx, 310__add_event(struct list_head *list, int *idx,
311 struct perf_event_attr *attr, 311 struct perf_event_attr *attr,
312 char *name, struct cpu_map *cpus, 312 char *name, struct cpu_map *cpus,
313 struct list_head *config_terms) 313 struct list_head *config_terms, bool auto_merge_stats)
314{ 314{
315 struct perf_evsel *evsel; 315 struct perf_evsel *evsel;
316 316
@@ -324,6 +324,7 @@ __add_event(struct list_head *list, int *idx,
324 evsel->cpus = cpu_map__get(cpus); 324 evsel->cpus = cpu_map__get(cpus);
325 evsel->own_cpus = cpu_map__get(cpus); 325 evsel->own_cpus = cpu_map__get(cpus);
326 evsel->system_wide = !!cpus; 326 evsel->system_wide = !!cpus;
327 evsel->auto_merge_stats = auto_merge_stats;
327 328
328 if (name) 329 if (name)
329 evsel->name = strdup(name); 330 evsel->name = strdup(name);
@@ -339,7 +340,7 @@ static int add_event(struct list_head *list, int *idx,
339 struct perf_event_attr *attr, char *name, 340 struct perf_event_attr *attr, char *name,
340 struct list_head *config_terms) 341 struct list_head *config_terms)
341{ 342{
342 return __add_event(list, idx, attr, name, NULL, config_terms) ? 0 : -ENOMEM; 343 return __add_event(list, idx, attr, name, NULL, config_terms, false) ? 0 : -ENOMEM;
343} 344}
344 345
345static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) 346static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
@@ -589,7 +590,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
589} 590}
590 591
591struct __add_bpf_event_param { 592struct __add_bpf_event_param {
592 struct parse_events_evlist *data; 593 struct parse_events_state *parse_state;
593 struct list_head *list; 594 struct list_head *list;
594 struct list_head *head_config; 595 struct list_head *head_config;
595}; 596};
@@ -599,7 +600,7 @@ static int add_bpf_event(const char *group, const char *event, int fd,
599{ 600{
600 LIST_HEAD(new_evsels); 601 LIST_HEAD(new_evsels);
601 struct __add_bpf_event_param *param = _param; 602 struct __add_bpf_event_param *param = _param;
602 struct parse_events_evlist *evlist = param->data; 603 struct parse_events_state *parse_state = param->parse_state;
603 struct list_head *list = param->list; 604 struct list_head *list = param->list;
604 struct perf_evsel *pos; 605 struct perf_evsel *pos;
605 int err; 606 int err;
@@ -607,8 +608,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", 608 pr_debug("add bpf event %s:%s and attach bpf program %d\n",
608 group, event, fd); 609 group, event, fd);
609 610
610 err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, group, 611 err = parse_events_add_tracepoint(&new_evsels, &parse_state->idx, group,
611 event, evlist->error, 612 event, parse_state->error,
612 param->head_config); 613 param->head_config);
613 if (err) { 614 if (err) {
614 struct perf_evsel *evsel, *tmp; 615 struct perf_evsel *evsel, *tmp;
@@ -632,14 +633,14 @@ static int add_bpf_event(const char *group, const char *event, int fd,
632 return 0; 633 return 0;
633} 634}
634 635
635int parse_events_load_bpf_obj(struct parse_events_evlist *data, 636int parse_events_load_bpf_obj(struct parse_events_state *parse_state,
636 struct list_head *list, 637 struct list_head *list,
637 struct bpf_object *obj, 638 struct bpf_object *obj,
638 struct list_head *head_config) 639 struct list_head *head_config)
639{ 640{
640 int err; 641 int err;
641 char errbuf[BUFSIZ]; 642 char errbuf[BUFSIZ];
642 struct __add_bpf_event_param param = {data, list, head_config}; 643 struct __add_bpf_event_param param = {parse_state, list, head_config};
643 static bool registered_unprobe_atexit = false; 644 static bool registered_unprobe_atexit = false;
644 645
645 if (IS_ERR(obj) || !obj) { 646 if (IS_ERR(obj) || !obj) {
@@ -680,13 +681,13 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data,
680 681
681 return 0; 682 return 0;
682errout: 683errout:
683 data->error->help = strdup("(add -v to see detail)"); 684 parse_state->error->help = strdup("(add -v to see detail)");
684 data->error->str = strdup(errbuf); 685 parse_state->error->str = strdup(errbuf);
685 return err; 686 return err;
686} 687}
687 688
688static int 689static int
689parse_events_config_bpf(struct parse_events_evlist *data, 690parse_events_config_bpf(struct parse_events_state *parse_state,
690 struct bpf_object *obj, 691 struct bpf_object *obj,
691 struct list_head *head_config) 692 struct list_head *head_config)
692{ 693{
@@ -705,28 +706,28 @@ parse_events_config_bpf(struct parse_events_evlist *data,
705 "Invalid config term for BPF object"); 706 "Invalid config term for BPF object");
706 errbuf[BUFSIZ - 1] = '\0'; 707 errbuf[BUFSIZ - 1] = '\0';
707 708
708 data->error->idx = term->err_term; 709 parse_state->error->idx = term->err_term;
709 data->error->str = strdup(errbuf); 710 parse_state->error->str = strdup(errbuf);
710 return -EINVAL; 711 return -EINVAL;
711 } 712 }
712 713
713 err = bpf__config_obj(obj, term, data->evlist, &error_pos); 714 err = bpf__config_obj(obj, term, parse_state->evlist, &error_pos);
714 if (err) { 715 if (err) {
715 bpf__strerror_config_obj(obj, term, data->evlist, 716 bpf__strerror_config_obj(obj, term, parse_state->evlist,
716 &error_pos, err, errbuf, 717 &error_pos, err, errbuf,
717 sizeof(errbuf)); 718 sizeof(errbuf));
718 data->error->help = strdup( 719 parse_state->error->help = strdup(
719"Hint:\tValid config terms:\n" 720"Hint:\tValid config terms:\n"
720" \tmap:[<arraymap>].value<indices>=[value]\n" 721" \tmap:[<arraymap>].value<indices>=[value]\n"
721" \tmap:[<eventmap>].event<indices>=[event]\n" 722" \tmap:[<eventmap>].event<indices>=[event]\n"
722"\n" 723"\n"
723" \twhere <indices> is something like [0,3...5] or [all]\n" 724" \twhere <indices> is something like [0,3...5] or [all]\n"
724" \t(add -v to see detail)"); 725" \t(add -v to see detail)");
725 data->error->str = strdup(errbuf); 726 parse_state->error->str = strdup(errbuf);
726 if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE) 727 if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
727 data->error->idx = term->err_val; 728 parse_state->error->idx = term->err_val;
728 else 729 else
729 data->error->idx = term->err_term + error_pos; 730 parse_state->error->idx = term->err_term + error_pos;
730 return err; 731 return err;
731 } 732 }
732 } 733 }
@@ -762,7 +763,7 @@ split_bpf_config_terms(struct list_head *evt_head_config,
762 list_move_tail(&term->list, obj_head_config); 763 list_move_tail(&term->list, obj_head_config);
763} 764}
764 765
765int parse_events_load_bpf(struct parse_events_evlist *data, 766int parse_events_load_bpf(struct parse_events_state *parse_state,
766 struct list_head *list, 767 struct list_head *list,
767 char *bpf_file_name, 768 char *bpf_file_name,
768 bool source, 769 bool source,
@@ -790,15 +791,15 @@ int parse_events_load_bpf(struct parse_events_evlist *data,
790 -err, errbuf, 791 -err, errbuf,
791 sizeof(errbuf)); 792 sizeof(errbuf));
792 793
793 data->error->help = strdup("(add -v to see detail)"); 794 parse_state->error->help = strdup("(add -v to see detail)");
794 data->error->str = strdup(errbuf); 795 parse_state->error->str = strdup(errbuf);
795 return err; 796 return err;
796 } 797 }
797 798
798 err = parse_events_load_bpf_obj(data, list, obj, head_config); 799 err = parse_events_load_bpf_obj(parse_state, list, obj, head_config);
799 if (err) 800 if (err)
800 return err; 801 return err;
801 err = parse_events_config_bpf(data, obj, &obj_head_config); 802 err = parse_events_config_bpf(parse_state, obj, &obj_head_config);
802 803
803 /* 804 /*
804 * Caller doesn't know anything about obj_head_config, 805 * Caller doesn't know anything about obj_head_config,
@@ -1184,7 +1185,7 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
1184 err, head_config); 1185 err, head_config);
1185} 1186}
1186 1187
1187int parse_events_add_numeric(struct parse_events_evlist *data, 1188int parse_events_add_numeric(struct parse_events_state *parse_state,
1188 struct list_head *list, 1189 struct list_head *list,
1189 u32 type, u64 config, 1190 u32 type, u64 config,
1190 struct list_head *head_config) 1191 struct list_head *head_config)
@@ -1197,7 +1198,7 @@ int parse_events_add_numeric(struct parse_events_evlist *data,
1197 attr.config = config; 1198 attr.config = config;
1198 1199
1199 if (head_config) { 1200 if (head_config) {
1200 if (config_attr(&attr, head_config, data->error, 1201 if (config_attr(&attr, head_config, parse_state->error,
1201 config_term_common)) 1202 config_term_common))
1202 return -EINVAL; 1203 return -EINVAL;
1203 1204
@@ -1205,13 +1206,13 @@ int parse_events_add_numeric(struct parse_events_evlist *data,
1205 return -ENOMEM; 1206 return -ENOMEM;
1206 } 1207 }
1207 1208
1208 return add_event(list, &data->idx, &attr, 1209 return add_event(list, &parse_state->idx, &attr,
1209 get_config_name(head_config), &config_terms); 1210 get_config_name(head_config), &config_terms);
1210} 1211}
1211 1212
1212int parse_events_add_pmu(struct parse_events_evlist *data, 1213static int __parse_events_add_pmu(struct parse_events_state *parse_state,
1213 struct list_head *list, char *name, 1214 struct list_head *list, char *name,
1214 struct list_head *head_config) 1215 struct list_head *head_config, bool auto_merge_stats)
1215{ 1216{
1216 struct perf_event_attr attr; 1217 struct perf_event_attr attr;
1217 struct perf_pmu_info info; 1218 struct perf_pmu_info info;
@@ -1232,7 +1233,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
1232 1233
1233 if (!head_config) { 1234 if (!head_config) {
1234 attr.type = pmu->type; 1235 attr.type = pmu->type;
1235 evsel = __add_event(list, &data->idx, &attr, NULL, pmu->cpus, NULL); 1236 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu->cpus, NULL, auto_merge_stats);
1236 return evsel ? 0 : -ENOMEM; 1237 return evsel ? 0 : -ENOMEM;
1237 } 1238 }
1238 1239
@@ -1243,18 +1244,18 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
1243 * Configure hardcoded terms first, no need to check 1244 * Configure hardcoded terms first, no need to check
1244 * return value when called with fail == 0 ;) 1245 * return value when called with fail == 0 ;)
1245 */ 1246 */
1246 if (config_attr(&attr, head_config, data->error, config_term_pmu)) 1247 if (config_attr(&attr, head_config, parse_state->error, config_term_pmu))
1247 return -EINVAL; 1248 return -EINVAL;
1248 1249
1249 if (get_config_terms(head_config, &config_terms)) 1250 if (get_config_terms(head_config, &config_terms))
1250 return -ENOMEM; 1251 return -ENOMEM;
1251 1252
1252 if (perf_pmu__config(pmu, &attr, head_config, data->error)) 1253 if (perf_pmu__config(pmu, &attr, head_config, parse_state->error))
1253 return -EINVAL; 1254 return -EINVAL;
1254 1255
1255 evsel = __add_event(list, &data->idx, &attr, 1256 evsel = __add_event(list, &parse_state->idx, &attr,
1256 get_config_name(head_config), pmu->cpus, 1257 get_config_name(head_config), pmu->cpus,
1257 &config_terms); 1258 &config_terms, auto_merge_stats);
1258 if (evsel) { 1259 if (evsel) {
1259 evsel->unit = info.unit; 1260 evsel->unit = info.unit;
1260 evsel->scale = info.scale; 1261 evsel->scale = info.scale;
@@ -1267,7 +1268,14 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
1267 return evsel ? 0 : -ENOMEM; 1268 return evsel ? 0 : -ENOMEM;
1268} 1269}
1269 1270
1270int parse_events_multi_pmu_add(struct parse_events_evlist *data, 1271int parse_events_add_pmu(struct parse_events_state *parse_state,
1272 struct list_head *list, char *name,
1273 struct list_head *head_config)
1274{
1275 return __parse_events_add_pmu(parse_state, list, name, head_config, false);
1276}
1277
1278int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1271 char *str, struct list_head **listp) 1279 char *str, struct list_head **listp)
1272{ 1280{
1273 struct list_head *head; 1281 struct list_head *head;
@@ -1296,8 +1304,8 @@ int parse_events_multi_pmu_add(struct parse_events_evlist *data,
1296 return -1; 1304 return -1;
1297 list_add_tail(&term->list, head); 1305 list_add_tail(&term->list, head);
1298 1306
1299 if (!parse_events_add_pmu(data, list, 1307 if (!__parse_events_add_pmu(parse_state, list,
1300 pmu->name, head)) { 1308 pmu->name, head, true)) {
1301 pr_debug("%s -> %s/%s/\n", str, 1309 pr_debug("%s -> %s/%s/\n", str,
1302 pmu->name, alias->str); 1310 pmu->name, alias->str);
1303 ok++; 1311 ok++;
@@ -1628,7 +1636,7 @@ perf_pmu__parse_check(const char *name)
1628 return r ? r->type : PMU_EVENT_SYMBOL_ERR; 1636 return r ? r->type : PMU_EVENT_SYMBOL_ERR;
1629} 1637}
1630 1638
1631static int parse_events__scanner(const char *str, void *data, int start_token) 1639static int parse_events__scanner(const char *str, void *parse_state, int start_token)
1632{ 1640{
1633 YY_BUFFER_STATE buffer; 1641 YY_BUFFER_STATE buffer;
1634 void *scanner; 1642 void *scanner;
@@ -1643,7 +1651,7 @@ static int parse_events__scanner(const char *str, void *data, int start_token)
1643#ifdef PARSER_DEBUG 1651#ifdef PARSER_DEBUG
1644 parse_events_debug = 1; 1652 parse_events_debug = 1;
1645#endif 1653#endif
1646 ret = parse_events_parse(data, scanner); 1654 ret = parse_events_parse(parse_state, scanner);
1647 1655
1648 parse_events__flush_buffer(buffer, scanner); 1656 parse_events__flush_buffer(buffer, scanner);
1649 parse_events__delete_buffer(buffer, scanner); 1657 parse_events__delete_buffer(buffer, scanner);
@@ -1656,45 +1664,45 @@ static int parse_events__scanner(const char *str, void *data, int start_token)
1656 */ 1664 */
1657int parse_events_terms(struct list_head *terms, const char *str) 1665int parse_events_terms(struct list_head *terms, const char *str)
1658{ 1666{
1659 struct parse_events_terms data = { 1667 struct parse_events_state parse_state = {
1660 .terms = NULL, 1668 .terms = NULL,
1661 }; 1669 };
1662 int ret; 1670 int ret;
1663 1671
1664 ret = parse_events__scanner(str, &data, PE_START_TERMS); 1672 ret = parse_events__scanner(str, &parse_state, PE_START_TERMS);
1665 if (!ret) { 1673 if (!ret) {
1666 list_splice(data.terms, terms); 1674 list_splice(parse_state.terms, terms);
1667 zfree(&data.terms); 1675 zfree(&parse_state.terms);
1668 return 0; 1676 return 0;
1669 } 1677 }
1670 1678
1671 parse_events_terms__delete(data.terms); 1679 parse_events_terms__delete(parse_state.terms);
1672 return ret; 1680 return ret;
1673} 1681}
1674 1682
1675int parse_events(struct perf_evlist *evlist, const char *str, 1683int parse_events(struct perf_evlist *evlist, const char *str,
1676 struct parse_events_error *err) 1684 struct parse_events_error *err)
1677{ 1685{
1678 struct parse_events_evlist data = { 1686 struct parse_events_state parse_state = {
1679 .list = LIST_HEAD_INIT(data.list), 1687 .list = LIST_HEAD_INIT(parse_state.list),
1680 .idx = evlist->nr_entries, 1688 .idx = evlist->nr_entries,
1681 .error = err, 1689 .error = err,
1682 .evlist = evlist, 1690 .evlist = evlist,
1683 }; 1691 };
1684 int ret; 1692 int ret;
1685 1693
1686 ret = parse_events__scanner(str, &data, PE_START_EVENTS); 1694 ret = parse_events__scanner(str, &parse_state, PE_START_EVENTS);
1687 perf_pmu__parse_cleanup(); 1695 perf_pmu__parse_cleanup();
1688 if (!ret) { 1696 if (!ret) {
1689 struct perf_evsel *last; 1697 struct perf_evsel *last;
1690 1698
1691 if (list_empty(&data.list)) { 1699 if (list_empty(&parse_state.list)) {
1692 WARN_ONCE(true, "WARNING: event parser found nothing"); 1700 WARN_ONCE(true, "WARNING: event parser found nothing");
1693 return -1; 1701 return -1;
1694 } 1702 }
1695 1703
1696 perf_evlist__splice_list_tail(evlist, &data.list); 1704 perf_evlist__splice_list_tail(evlist, &parse_state.list);
1697 evlist->nr_groups += data.nr_groups; 1705 evlist->nr_groups += parse_state.nr_groups;
1698 last = perf_evlist__last(evlist); 1706 last = perf_evlist__last(evlist);
1699 last->cmdline_group_boundary = true; 1707 last->cmdline_group_boundary = true;
1700 1708
@@ -2124,7 +2132,7 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob,
2124 return; 2132 return;
2125 } 2133 }
2126 strlist__for_each_entry(nd, bidlist) { 2134 strlist__for_each_entry(nd, bidlist) {
2127 pcache = probe_cache__new(nd->s); 2135 pcache = probe_cache__new(nd->s, NULL);
2128 if (!pcache) 2136 if (!pcache)
2129 continue; 2137 continue;
2130 list_for_each_entry(ent, &pcache->entries, node) { 2138 list_for_each_entry(ent, &pcache->entries, node) {
@@ -2520,10 +2528,10 @@ void parse_events__clear_array(struct parse_events_array *a)
2520 zfree(&a->ranges); 2528 zfree(&a->ranges);
2521} 2529}
2522 2530
2523void parse_events_evlist_error(struct parse_events_evlist *data, 2531void parse_events_evlist_error(struct parse_events_state *parse_state,
2524 int idx, const char *str) 2532 int idx, const char *str)
2525{ 2533{
2526 struct parse_events_error *err = data->error; 2534 struct parse_events_error *err = parse_state->error;
2527 2535
2528 if (!err) 2536 if (!err)
2529 return; 2537 return;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index a235f4d6d5e5..635135125111 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -108,16 +108,13 @@ struct parse_events_error {
108 char *help; /* optional help string */ 108 char *help; /* optional help string */
109}; 109};
110 110
111struct parse_events_evlist { 111struct parse_events_state {
112 struct list_head list; 112 struct list_head list;
113 int idx; 113 int idx;
114 int nr_groups; 114 int nr_groups;
115 struct parse_events_error *error; 115 struct parse_events_error *error;
116 struct perf_evlist *evlist; 116 struct perf_evlist *evlist;
117}; 117 struct list_head *terms;
118
119struct parse_events_terms {
120 struct list_head *terms;
121}; 118};
122 119
123void parse_events__shrink_config_terms(void); 120void parse_events__shrink_config_terms(void);
@@ -143,18 +140,18 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
143 const char *sys, const char *event, 140 const char *sys, const char *event,
144 struct parse_events_error *error, 141 struct parse_events_error *error,
145 struct list_head *head_config); 142 struct list_head *head_config);
146int parse_events_load_bpf(struct parse_events_evlist *data, 143int parse_events_load_bpf(struct parse_events_state *parse_state,
147 struct list_head *list, 144 struct list_head *list,
148 char *bpf_file_name, 145 char *bpf_file_name,
149 bool source, 146 bool source,
150 struct list_head *head_config); 147 struct list_head *head_config);
151/* Provide this function for perf test */ 148/* Provide this function for perf test */
152struct bpf_object; 149struct bpf_object;
153int parse_events_load_bpf_obj(struct parse_events_evlist *data, 150int parse_events_load_bpf_obj(struct parse_events_state *parse_state,
154 struct list_head *list, 151 struct list_head *list,
155 struct bpf_object *obj, 152 struct bpf_object *obj,
156 struct list_head *head_config); 153 struct list_head *head_config);
157int parse_events_add_numeric(struct parse_events_evlist *data, 154int parse_events_add_numeric(struct parse_events_state *parse_state,
158 struct list_head *list, 155 struct list_head *list,
159 u32 type, u64 config, 156 u32 type, u64 config,
160 struct list_head *head_config); 157 struct list_head *head_config);
@@ -164,11 +161,11 @@ int parse_events_add_cache(struct list_head *list, int *idx,
164 struct list_head *head_config); 161 struct list_head *head_config);
165int parse_events_add_breakpoint(struct list_head *list, int *idx, 162int parse_events_add_breakpoint(struct list_head *list, int *idx,
166 void *ptr, char *type, u64 len); 163 void *ptr, char *type, u64 len);
167int parse_events_add_pmu(struct parse_events_evlist *data, 164int parse_events_add_pmu(struct parse_events_state *parse_state,
168 struct list_head *list, char *name, 165 struct list_head *list, char *name,
169 struct list_head *head_config); 166 struct list_head *head_config);
170 167
171int parse_events_multi_pmu_add(struct parse_events_evlist *data, 168int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
172 char *str, 169 char *str,
173 struct list_head **listp); 170 struct list_head **listp);
174 171
@@ -180,7 +177,7 @@ perf_pmu__parse_check(const char *name);
180void parse_events__set_leader(char *name, struct list_head *list); 177void parse_events__set_leader(char *name, struct list_head *list);
181void parse_events_update_lists(struct list_head *list_event, 178void parse_events_update_lists(struct list_head *list_event,
182 struct list_head *list_all); 179 struct list_head *list_all);
183void parse_events_evlist_error(struct parse_events_evlist *data, 180void parse_events_evlist_error(struct parse_events_state *parse_state,
184 int idx, const char *str); 181 int idx, const char *str);
185 182
186void print_events(const char *event_glob, bool name_only, bool quiet, 183void print_events(const char *event_glob, bool name_only, bool quiet,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 660fca05bc93..c42edeac451f 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -53,6 +53,21 @@ static int str(yyscan_t scanner, int token)
53 return token; 53 return token;
54} 54}
55 55
56static bool isbpf(yyscan_t scanner)
57{
58 char *text = parse_events_get_text(scanner);
59 int len = strlen(text);
60
61 if (len < 2)
62 return false;
63 if ((text[len - 1] == 'c' || text[len - 1] == 'o') &&
64 text[len - 2] == '.')
65 return true;
66 if (len > 4 && !strcmp(text + len - 4, ".obj"))
67 return true;
68 return false;
69}
70
56/* 71/*
57 * This function is called when the parser gets two kind of input: 72 * This function is called when the parser gets two kind of input:
58 * 73 *
@@ -136,8 +151,8 @@ do { \
136group [^,{}/]*[{][^}]*[}][^,{}/]* 151group [^,{}/]*[{][^}]*[}][^,{}/]*
137event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* 152event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
138event [^,{}/]+ 153event [^,{}/]+
139bpf_object [^,{}]+\.(o|bpf) 154bpf_object [^,{}]+\.(o|bpf)[a-zA-Z0-9._]*
140bpf_source [^,{}]+\.c 155bpf_source [^,{}]+\.c[a-zA-Z0-9._]*
141 156
142num_dec [0-9]+ 157num_dec [0-9]+
143num_hex 0x[a-fA-F0-9]+ 158num_hex 0x[a-fA-F0-9]+
@@ -307,8 +322,8 @@ r{num_raw_hex} { return raw(yyscanner); }
307{num_hex} { return value(yyscanner, 16); } 322{num_hex} { return value(yyscanner, 16); }
308 323
309{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } 324{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
310{bpf_object} { return str(yyscanner, PE_BPF_OBJECT); } 325{bpf_object} { if (!isbpf(yyscanner)) REJECT; return str(yyscanner, PE_BPF_OBJECT); }
311{bpf_source} { return str(yyscanner, PE_BPF_SOURCE); } 326{bpf_source} { if (!isbpf(yyscanner)) REJECT; return str(yyscanner, PE_BPF_SOURCE); }
312{name} { return pmu_str_check(yyscanner); } 327{name} { return pmu_str_check(yyscanner); }
313"/" { BEGIN(config); return '/'; } 328"/" { BEGIN(config); return '/'; }
314- { return '-'; } 329- { 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/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..078681d12168 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -4,6 +4,7 @@
4#include <linux/compiler.h> 4#include <linux/compiler.h>
5#include <stdbool.h> 5#include <stdbool.h>
6#include "intlist.h" 6#include "intlist.h"
7#include "namespaces.h"
7 8
8/* Probe related configurations */ 9/* Probe related configurations */
9struct probe_conf { 10struct probe_conf {
@@ -92,6 +93,7 @@ struct perf_probe_event {
92 struct perf_probe_arg *args; /* Arguments */ 93 struct perf_probe_arg *args; /* Arguments */
93 struct probe_trace_event *tevs; 94 struct probe_trace_event *tevs;
94 int ntevs; 95 int ntevs;
96 struct nsinfo *nsi; /* Target namespace */
95}; 97};
96 98
97/* Line range */ 99/* Line range */
@@ -163,10 +165,12 @@ int show_perf_probe_event(const char *group, const char *event,
163 struct perf_probe_event *pev, 165 struct perf_probe_event *pev,
164 const char *module, bool use_stdout); 166 const char *module, bool use_stdout);
165int show_perf_probe_events(struct strfilter *filter); 167int show_perf_probe_events(struct strfilter *filter);
166int show_line_range(struct line_range *lr, const char *module, bool user); 168int show_line_range(struct line_range *lr, const char *module,
169 struct nsinfo *nsi, bool user);
167int show_available_vars(struct perf_probe_event *pevs, int npevs, 170int show_available_vars(struct perf_probe_event *pevs, int npevs,
168 struct strfilter *filter); 171 struct strfilter *filter);
169int show_available_funcs(const char *module, struct strfilter *filter, bool user); 172int show_available_funcs(const char *module, struct nsinfo *nsi,
173 struct strfilter *filter, bool user);
170void arch__fix_tev_from_maps(struct perf_probe_event *pev, 174void arch__fix_tev_from_maps(struct perf_probe_event *pev,
171 struct probe_trace_event *tev, struct map *map, 175 struct probe_trace_event *tev, struct map *map,
172 struct symbol *sym); 176 struct symbol *sym);
@@ -180,7 +184,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, 184int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
181 struct perf_probe_arg *pvar); 185 struct perf_probe_arg *pvar);
182 186
183struct map *get_target_map(const char *target, bool user); 187struct map *get_target_map(const char *target, struct nsinfo *nsi, bool user);
184 188
185void arch__post_process_probe_trace_events(struct perf_probe_event *pev, 189void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
186 int ntevs); 190 int ntevs);
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index d679389e627c..cdf8d83a484c 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -412,13 +412,15 @@ int probe_cache_entry__get_event(struct probe_cache_entry *entry,
412} 412}
413 413
414/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */ 414/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
415static int probe_cache__open(struct probe_cache *pcache, const char *target) 415static int probe_cache__open(struct probe_cache *pcache, const char *target,
416 struct nsinfo *nsi)
416{ 417{
417 char cpath[PATH_MAX]; 418 char cpath[PATH_MAX];
418 char sbuildid[SBUILD_ID_SIZE]; 419 char sbuildid[SBUILD_ID_SIZE];
419 char *dir_name = NULL; 420 char *dir_name = NULL;
420 bool is_kallsyms = false; 421 bool is_kallsyms = false;
421 int ret, fd; 422 int ret, fd;
423 struct nscookie nsc;
422 424
423 if (target && build_id_cache__cached(target)) { 425 if (target && build_id_cache__cached(target)) {
424 /* This is a cached buildid */ 426 /* This is a cached buildid */
@@ -431,8 +433,11 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
431 target = DSO__NAME_KALLSYMS; 433 target = DSO__NAME_KALLSYMS;
432 is_kallsyms = true; 434 is_kallsyms = true;
433 ret = sysfs__sprintf_build_id("/", sbuildid); 435 ret = sysfs__sprintf_build_id("/", sbuildid);
434 } else 436 } else {
437 nsinfo__mountns_enter(nsi, &nsc);
435 ret = filename__sprintf_build_id(target, sbuildid); 438 ret = filename__sprintf_build_id(target, sbuildid);
439 nsinfo__mountns_exit(&nsc);
440 }
436 441
437 if (ret < 0) { 442 if (ret < 0) {
438 pr_debug("Failed to get build-id from %s.\n", target); 443 pr_debug("Failed to get build-id from %s.\n", target);
@@ -441,7 +446,7 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
441 446
442 /* If we have no buildid cache, make it */ 447 /* If we have no buildid cache, make it */
443 if (!build_id_cache__cached(sbuildid)) { 448 if (!build_id_cache__cached(sbuildid)) {
444 ret = build_id_cache__add_s(sbuildid, target, 449 ret = build_id_cache__add_s(sbuildid, target, nsi,
445 is_kallsyms, NULL); 450 is_kallsyms, NULL);
446 if (ret < 0) { 451 if (ret < 0) {
447 pr_debug("Failed to add build-id cache: %s\n", target); 452 pr_debug("Failed to add build-id cache: %s\n", target);
@@ -449,7 +454,7 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
449 } 454 }
450 } 455 }
451 456
452 dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms, 457 dir_name = build_id_cache__cachedir(sbuildid, target, nsi, is_kallsyms,
453 false); 458 false);
454found: 459found:
455 if (!dir_name) { 460 if (!dir_name) {
@@ -554,7 +559,7 @@ void probe_cache__delete(struct probe_cache *pcache)
554 free(pcache); 559 free(pcache);
555} 560}
556 561
557struct probe_cache *probe_cache__new(const char *target) 562struct probe_cache *probe_cache__new(const char *target, struct nsinfo *nsi)
558{ 563{
559 struct probe_cache *pcache = probe_cache__alloc(); 564 struct probe_cache *pcache = probe_cache__alloc();
560 int ret; 565 int ret;
@@ -562,7 +567,7 @@ struct probe_cache *probe_cache__new(const char *target)
562 if (!pcache) 567 if (!pcache)
563 return NULL; 568 return NULL;
564 569
565 ret = probe_cache__open(pcache, target); 570 ret = probe_cache__open(pcache, target, nsi);
566 if (ret < 0) { 571 if (ret < 0) {
567 pr_debug("Cache open error: %d\n", ret); 572 pr_debug("Cache open error: %d\n", ret);
568 goto out_err; 573 goto out_err;
@@ -974,7 +979,7 @@ int probe_cache__show_all_caches(struct strfilter *filter)
974 return -EINVAL; 979 return -EINVAL;
975 } 980 }
976 strlist__for_each_entry(nd, bidlist) { 981 strlist__for_each_entry(nd, bidlist) {
977 pcache = probe_cache__new(nd->s); 982 pcache = probe_cache__new(nd->s, NULL);
978 if (!pcache) 983 if (!pcache)
979 continue; 984 continue;
980 if (!list_empty(&pcache->entries)) { 985 if (!list_empty(&pcache->entries)) {
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 5ecc9d3925db..2ca4163abafe 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -51,7 +51,7 @@ int probe_file__del_strlist(int fd, struct strlist *namelist);
51int probe_cache_entry__get_event(struct probe_cache_entry *entry, 51int probe_cache_entry__get_event(struct probe_cache_entry *entry,
52 struct probe_trace_event **tevs); 52 struct probe_trace_event **tevs);
53 53
54struct probe_cache *probe_cache__new(const char *target); 54struct probe_cache *probe_cache__new(const char *target, struct nsinfo *nsi);
55int probe_cache__add_entry(struct probe_cache *pcache, 55int probe_cache__add_entry(struct probe_cache *pcache,
56 struct perf_probe_event *pev, 56 struct perf_probe_event *pev,
57 struct probe_trace_event *tevs, int ntevs); 57 struct probe_trace_event *tevs, int ntevs);
@@ -69,7 +69,7 @@ int probe_cache__show_all_caches(struct strfilter *filter);
69bool probe_type_is_available(enum probe_type type); 69bool probe_type_is_available(enum probe_type type);
70bool kretprobe_offset_is_supported(void); 70bool kretprobe_offset_is_supported(void);
71#else /* ! HAVE_LIBELF_SUPPORT */ 71#else /* ! HAVE_LIBELF_SUPPORT */
72static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused) 72static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused, struct nsinfo *nsi __maybe_unused)
73{ 73{
74 return NULL; 74 return NULL;
75} 75}
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 9f3b0d9754a8..e66dc495809a 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -10,6 +10,7 @@ util/ctype.c
10util/evlist.c 10util/evlist.c
11util/evsel.c 11util/evsel.c
12util/cpumap.c 12util/cpumap.c
13util/namespaces.c
13../lib/bitmap.c 14../lib/bitmap.c
14../lib/find_bit.c 15../lib/find_bit.c
15../lib/hweight.c 16../lib/hweight.c
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..a7ebd9fe8e40 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -428,6 +428,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
428 tool->stat_round = process_stat_round_stub; 428 tool->stat_round = process_stat_round_stub;
429 if (tool->time_conv == NULL) 429 if (tool->time_conv == NULL)
430 tool->time_conv = process_event_op2_stub; 430 tool->time_conv = process_event_op2_stub;
431 if (tool->feature == NULL)
432 tool->feature = process_event_op2_stub;
431} 433}
432 434
433static void swap_sample_id_all(union perf_event *event, void *data) 435static void swap_sample_id_all(union perf_event *event, void *data)
@@ -1118,6 +1120,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
1118 if (sample_type & PERF_SAMPLE_DATA_SRC) 1120 if (sample_type & PERF_SAMPLE_DATA_SRC)
1119 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src); 1121 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src);
1120 1122
1123 if (sample_type & PERF_SAMPLE_PHYS_ADDR)
1124 printf(" .. phys_addr: 0x%"PRIx64"\n", sample->phys_addr);
1125
1121 if (sample_type & PERF_SAMPLE_TRANSACTION) 1126 if (sample_type & PERF_SAMPLE_TRANSACTION)
1122 printf("... transaction: %" PRIx64 "\n", sample->transaction); 1127 printf("... transaction: %" PRIx64 "\n", sample->transaction);
1123 1128
@@ -1125,6 +1130,30 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
1125 sample_read__printf(sample, evsel->attr.read_format); 1130 sample_read__printf(sample, evsel->attr.read_format);
1126} 1131}
1127 1132
1133static void dump_read(struct perf_evsel *evsel, union perf_event *event)
1134{
1135 struct read_event *read_event = &event->read;
1136 u64 read_format;
1137
1138 if (!dump_trace)
1139 return;
1140
1141 printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
1142 evsel ? perf_evsel__name(evsel) : "FAIL",
1143 event->read.value);
1144
1145 read_format = evsel->attr.read_format;
1146
1147 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1148 printf("... time enabled : %" PRIu64 "\n", read_event->time_enabled);
1149
1150 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1151 printf("... time running : %" PRIu64 "\n", read_event->time_running);
1152
1153 if (read_format & PERF_FORMAT_ID)
1154 printf("... id : %" PRIu64 "\n", read_event->id);
1155}
1156
1128static struct machine *machines__find_for_cpumode(struct machines *machines, 1157static struct machine *machines__find_for_cpumode(struct machines *machines,
1129 union perf_event *event, 1158 union perf_event *event,
1130 struct perf_sample *sample) 1159 struct perf_sample *sample)
@@ -1269,6 +1298,7 @@ static int machines__deliver_event(struct machines *machines,
1269 evlist->stats.total_lost_samples += event->lost_samples.lost; 1298 evlist->stats.total_lost_samples += event->lost_samples.lost;
1270 return tool->lost_samples(tool, event, sample, machine); 1299 return tool->lost_samples(tool, event, sample, machine);
1271 case PERF_RECORD_READ: 1300 case PERF_RECORD_READ:
1301 dump_read(evsel, event);
1272 return tool->read(tool, event, sample, evsel, machine); 1302 return tool->read(tool, event, sample, evsel, machine);
1273 case PERF_RECORD_THROTTLE: 1303 case PERF_RECORD_THROTTLE:
1274 return tool->throttle(tool, event, sample, machine); 1304 return tool->throttle(tool, event, sample, machine);
@@ -1371,6 +1401,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1371 case PERF_RECORD_TIME_CONV: 1401 case PERF_RECORD_TIME_CONV:
1372 session->time_conv = event->time_conv; 1402 session->time_conv = event->time_conv;
1373 return tool->time_conv(tool, event, session); 1403 return tool->time_conv(tool, event, session);
1404 case PERF_RECORD_HEADER_FEATURE:
1405 return tool->feature(tool, event, session);
1374 default: 1406 default:
1375 return -EINVAL; 1407 return -EINVAL;
1376 } 1408 }
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..eb3ab902a1c0 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1316,6 +1316,47 @@ struct sort_entry sort_mem_dcacheline = {
1316}; 1316};
1317 1317
1318static int64_t 1318static int64_t
1319sort__phys_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
1320{
1321 uint64_t l = 0, r = 0;
1322
1323 if (left->mem_info)
1324 l = left->mem_info->daddr.phys_addr;
1325 if (right->mem_info)
1326 r = right->mem_info->daddr.phys_addr;
1327
1328 return (int64_t)(r - l);
1329}
1330
1331static int hist_entry__phys_daddr_snprintf(struct hist_entry *he, char *bf,
1332 size_t size, unsigned int width)
1333{
1334 uint64_t addr = 0;
1335 size_t ret = 0;
1336 size_t len = BITS_PER_LONG / 4;
1337
1338 addr = he->mem_info->daddr.phys_addr;
1339
1340 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", he->level);
1341
1342 ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx", len, addr);
1343
1344 ret += repsep_snprintf(bf + ret, size - ret, "%-*s", width - ret, "");
1345
1346 if (ret > width)
1347 bf[width] = '\0';
1348
1349 return width;
1350}
1351
1352struct sort_entry sort_mem_phys_daddr = {
1353 .se_header = "Data Physical Address",
1354 .se_cmp = sort__phys_daddr_cmp,
1355 .se_snprintf = hist_entry__phys_daddr_snprintf,
1356 .se_width_idx = HISTC_MEM_PHYS_DADDR,
1357};
1358
1359static int64_t
1319sort__abort_cmp(struct hist_entry *left, struct hist_entry *right) 1360sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
1320{ 1361{
1321 if (!left->branch_info || !right->branch_info) 1362 if (!left->branch_info || !right->branch_info)
@@ -1547,6 +1588,7 @@ static struct sort_dimension memory_sort_dimensions[] = {
1547 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl), 1588 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
1548 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop), 1589 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
1549 DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline), 1590 DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline),
1591 DIM(SORT_MEM_PHYS_DADDR, "phys_daddr", sort_mem_phys_daddr),
1550}; 1592};
1551 1593
1552#undef DIM 1594#undef DIM
@@ -2563,7 +2605,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist)
2563 2605
2564 BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders)); 2606 BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
2565 2607
2566 if (evlist == NULL) 2608 if (evlist == NULL || perf_evlist__empty(evlist))
2567 goto out_no_evlist; 2609 goto out_no_evlist;
2568 2610
2569 evlist__for_each_entry(evlist, evsel) { 2611 evlist__for_each_entry(evlist, evsel) {
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index b7c75597e18f..f36dc4980a6c 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -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..ed8e8d2de942 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -155,6 +155,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, 155 a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma,
156 &a2l->filename, &a2l->funcname, 156 &a2l->filename, &a2l->funcname,
157 &a2l->line); 157 &a2l->line);
158
159 if (a2l->filename && !strlen(a2l->filename))
160 a2l->filename = NULL;
158} 161}
159 162
160static struct a2l_data *addr2line_init(const char *path) 163static struct a2l_data *addr2line_init(const char *path)
@@ -248,6 +251,9 @@ static int addr2line(const char *dso_name, u64 addr,
248 &a2l->funcname, &a2l->line) && 251 &a2l->funcname, &a2l->line) &&
249 cnt++ < MAX_INLINE_NEST) { 252 cnt++ < MAX_INLINE_NEST) {
250 253
254 if (a2l->filename && !strlen(a2l->filename))
255 a2l->filename = NULL;
256
251 if (node != NULL) { 257 if (node != NULL) {
252 if (inline_list__append_dso_a2l(dso, node)) 258 if (inline_list__append_dso_a2l(dso, node))
253 return 0; 259 return 0;
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 719d6cb86952..a04cf56d3517 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -70,7 +70,11 @@ static int saved_value_cmp(struct rb_node *rb_node, const void *entry)
70 return a->ctx - b->ctx; 70 return a->ctx - b->ctx;
71 if (a->cpu != b->cpu) 71 if (a->cpu != b->cpu)
72 return a->cpu - b->cpu; 72 return a->cpu - b->cpu;
73 return a->evsel - b->evsel; 73 if (a->evsel == b->evsel)
74 return 0;
75 if ((char *)a->evsel < (char *)b->evsel)
76 return -1;
77 return +1;
74} 78}
75 79
76static struct rb_node *saved_value_new(struct rblist *rblist __maybe_unused, 80static struct rb_node *saved_value_new(struct rblist *rblist __maybe_unused,
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 53b9a994a3dc..35e9848734d6 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -128,6 +128,10 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
128 128
129static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) 129static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
130{ 130{
131 struct perf_stat_evsel *ps = evsel->priv;
132
133 if (ps)
134 free(ps->group_data);
131 zfree(&evsel->priv); 135 zfree(&evsel->priv);
132} 136}
133 137
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 7522bf10b03e..eacaf958e19d 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -28,8 +28,9 @@ enum perf_stat_evsel_id {
28}; 28};
29 29
30struct perf_stat_evsel { 30struct perf_stat_evsel {
31 struct stats res_stats[3]; 31 struct stats res_stats[3];
32 enum perf_stat_evsel_id id; 32 enum perf_stat_evsel_id id;
33 u64 *group_data;
33}; 34};
34 35
35enum aggr_mode { 36enum aggr_mode {
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 502505cf236a..5c39f420111e 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -259,7 +259,7 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
259{ 259{
260 uint32_t nr_rel_entries, idx; 260 uint32_t nr_rel_entries, idx;
261 GElf_Sym sym; 261 GElf_Sym sym;
262 u64 plt_offset; 262 u64 plt_offset, plt_header_size, plt_entry_size;
263 GElf_Shdr shdr_plt; 263 GElf_Shdr shdr_plt;
264 struct symbol *f; 264 struct symbol *f;
265 GElf_Shdr shdr_rel_plt, shdr_dynsym; 265 GElf_Shdr shdr_rel_plt, shdr_dynsym;
@@ -326,6 +326,23 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
326 326
327 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; 327 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
328 plt_offset = shdr_plt.sh_offset; 328 plt_offset = shdr_plt.sh_offset;
329 switch (ehdr.e_machine) {
330 case EM_ARM:
331 plt_header_size = 20;
332 plt_entry_size = 12;
333 break;
334
335 case EM_AARCH64:
336 plt_header_size = 32;
337 plt_entry_size = 16;
338 break;
339
340 default: /* FIXME: s390/alpha/mips/parisc/poperpc/sh/sparc/xtensa need to be checked */
341 plt_header_size = shdr_plt.sh_entsize;
342 plt_entry_size = shdr_plt.sh_entsize;
343 break;
344 }
345 plt_offset += plt_header_size;
329 346
330 if (shdr_rel_plt.sh_type == SHT_RELA) { 347 if (shdr_rel_plt.sh_type == SHT_RELA) {
331 GElf_Rela pos_mem, *pos; 348 GElf_Rela pos_mem, *pos;
@@ -335,7 +352,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
335 const char *elf_name = NULL; 352 const char *elf_name = NULL;
336 char *demangled = NULL; 353 char *demangled = NULL;
337 symidx = GELF_R_SYM(pos->r_info); 354 symidx = GELF_R_SYM(pos->r_info);
338 plt_offset += shdr_plt.sh_entsize;
339 gelf_getsym(syms, symidx, &sym); 355 gelf_getsym(syms, symidx, &sym);
340 356
341 elf_name = elf_sym__name(&sym, symstrs); 357 elf_name = elf_sym__name(&sym, symstrs);
@@ -346,11 +362,12 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
346 "%s@plt", elf_name); 362 "%s@plt", elf_name);
347 free(demangled); 363 free(demangled);
348 364
349 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 365 f = symbol__new(plt_offset, plt_entry_size,
350 STB_GLOBAL, sympltname); 366 STB_GLOBAL, sympltname);
351 if (!f) 367 if (!f)
352 goto out_elf_end; 368 goto out_elf_end;
353 369
370 plt_offset += plt_entry_size;
354 symbols__insert(&dso->symbols[map->type], f); 371 symbols__insert(&dso->symbols[map->type], f);
355 ++nr; 372 ++nr;
356 } 373 }
@@ -361,7 +378,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
361 const char *elf_name = NULL; 378 const char *elf_name = NULL;
362 char *demangled = NULL; 379 char *demangled = NULL;
363 symidx = GELF_R_SYM(pos->r_info); 380 symidx = GELF_R_SYM(pos->r_info);
364 plt_offset += shdr_plt.sh_entsize;
365 gelf_getsym(syms, symidx, &sym); 381 gelf_getsym(syms, symidx, &sym);
366 382
367 elf_name = elf_sym__name(&sym, symstrs); 383 elf_name = elf_sym__name(&sym, symstrs);
@@ -372,11 +388,12 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
372 "%s@plt", elf_name); 388 "%s@plt", elf_name);
373 free(demangled); 389 free(demangled);
374 390
375 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 391 f = symbol__new(plt_offset, plt_entry_size,
376 STB_GLOBAL, sympltname); 392 STB_GLOBAL, sympltname);
377 if (!f) 393 if (!f)
378 goto out_elf_end; 394 goto out_elf_end;
379 395
396 plt_offset += plt_entry_size;
380 symbols__insert(&dso->symbols[map->type], f); 397 symbols__insert(&dso->symbols[map->type], f);
381 ++nr; 398 ++nr;
382 } 399 }
@@ -391,7 +408,7 @@ out_elf_end:
391 return 0; 408 return 0;
392} 409}
393 410
394char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name) 411char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
395{ 412{
396 return demangle_sym(dso, kmodule, elf_name); 413 return demangle_sym(dso, kmodule, elf_name);
397} 414}
@@ -793,6 +810,12 @@ static u64 ref_reloc(struct kmap *kmap)
793void __weak arch__sym_update(struct symbol *s __maybe_unused, 810void __weak arch__sym_update(struct symbol *s __maybe_unused,
794 GElf_Sym *sym __maybe_unused) { } 811 GElf_Sym *sym __maybe_unused) { }
795 812
813void __weak arch__adjust_sym_map_offset(GElf_Sym *sym, GElf_Shdr *shdr,
814 struct map *map __maybe_unused)
815{
816 sym->st_value -= shdr->sh_addr - shdr->sh_offset;
817}
818
796int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 819int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
797 struct symsrc *runtime_ss, int kmodule) 820 struct symsrc *runtime_ss, int kmodule)
798{ 821{
@@ -973,7 +996,7 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
973 996
974 /* Adjust symbol to map to file offset */ 997 /* Adjust symbol to map to file offset */
975 if (adjust_kernel_syms) 998 if (adjust_kernel_syms)
976 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 999 arch__adjust_sym_map_offset(&sym, &shdr, map);
977 1000
978 if (strcmp(section_name, 1001 if (strcmp(section_name,
979 (curr_dso->short_name + 1002 (curr_dso->short_name +
@@ -1442,7 +1465,7 @@ static int kcore_copy__parse_kallsyms(struct kcore_copy_info *kci,
1442 1465
1443static int kcore_copy__process_modules(void *arg, 1466static int kcore_copy__process_modules(void *arg,
1444 const char *name __maybe_unused, 1467 const char *name __maybe_unused,
1445 u64 start) 1468 u64 start, u64 size __maybe_unused)
1446{ 1469{
1447 struct kcore_copy_info *kci = arg; 1470 struct kcore_copy_info *kci = arg;
1448 1471
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 40bf5d4c0bfd..1a5aa35b0100 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -377,7 +377,7 @@ void symbol__elf_init(void)
377 377
378char *dso__demangle_sym(struct dso *dso __maybe_unused, 378char *dso__demangle_sym(struct dso *dso __maybe_unused,
379 int kmodule __maybe_unused, 379 int kmodule __maybe_unused,
380 char *elf_name __maybe_unused) 380 const char *elf_name __maybe_unused)
381{ 381{
382 return NULL; 382 return NULL;
383} 383}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e7a98dbd2aed..5909ee4c7ade 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -18,6 +18,7 @@
18#include "symbol.h" 18#include "symbol.h"
19#include "strlist.h" 19#include "strlist.h"
20#include "intlist.h" 20#include "intlist.h"
21#include "namespaces.h"
21#include "header.h" 22#include "header.h"
22#include "path.h" 23#include "path.h"
23#include "sane_ctype.h" 24#include "sane_ctype.h"
@@ -52,6 +53,7 @@ static enum dso_binary_type binary_type_symtab[] = {
52 DSO_BINARY_TYPE__JAVA_JIT, 53 DSO_BINARY_TYPE__JAVA_JIT,
53 DSO_BINARY_TYPE__DEBUGLINK, 54 DSO_BINARY_TYPE__DEBUGLINK,
54 DSO_BINARY_TYPE__BUILD_ID_CACHE, 55 DSO_BINARY_TYPE__BUILD_ID_CACHE,
56 DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
55 DSO_BINARY_TYPE__FEDORA_DEBUGINFO, 57 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
56 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO, 58 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
57 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 59 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
@@ -231,7 +233,8 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
231 goto out_unlock; 233 goto out_unlock;
232 234
233 for (next = map__next(curr); next; next = map__next(curr)) { 235 for (next = map__next(curr); next; next = map__next(curr)) {
234 curr->end = next->start; 236 if (!curr->end)
237 curr->end = next->start;
235 curr = next; 238 curr = next;
236 } 239 }
237 240
@@ -239,7 +242,8 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
239 * We still haven't the actual symbols, so guess the 242 * We still haven't the actual symbols, so guess the
240 * last map final address. 243 * last map final address.
241 */ 244 */
242 curr->end = ~0ULL; 245 if (!curr->end)
246 curr->end = ~0ULL;
243 247
244out_unlock: 248out_unlock:
245 pthread_rwlock_unlock(&maps->lock); 249 pthread_rwlock_unlock(&maps->lock);
@@ -550,7 +554,7 @@ void dso__sort_by_name(struct dso *dso, enum map_type type)
550 554
551int modules__parse(const char *filename, void *arg, 555int modules__parse(const char *filename, void *arg,
552 int (*process_module)(void *arg, const char *name, 556 int (*process_module)(void *arg, const char *name,
553 u64 start)) 557 u64 start, u64 size))
554{ 558{
555 char *line = NULL; 559 char *line = NULL;
556 size_t n; 560 size_t n;
@@ -563,8 +567,8 @@ int modules__parse(const char *filename, void *arg,
563 567
564 while (1) { 568 while (1) {
565 char name[PATH_MAX]; 569 char name[PATH_MAX];
566 u64 start; 570 u64 start, size;
567 char *sep; 571 char *sep, *endptr;
568 ssize_t line_len; 572 ssize_t line_len;
569 573
570 line_len = getline(&line, &n, file); 574 line_len = getline(&line, &n, file);
@@ -596,7 +600,11 @@ int modules__parse(const char *filename, void *arg,
596 600
597 scnprintf(name, sizeof(name), "[%s]", line); 601 scnprintf(name, sizeof(name), "[%s]", line);
598 602
599 err = process_module(arg, name, start); 603 size = strtoul(sep + 1, &endptr, 0);
604 if (*endptr != ' ' && *endptr != '\t')
605 continue;
606
607 err = process_module(arg, name, start, size);
600 if (err) 608 if (err)
601 break; 609 break;
602 } 610 }
@@ -943,7 +951,8 @@ static struct module_info *find_module(const char *name,
943 return NULL; 951 return NULL;
944} 952}
945 953
946static int __read_proc_modules(void *arg, const char *name, u64 start) 954static int __read_proc_modules(void *arg, const char *name, u64 start,
955 u64 size __maybe_unused)
947{ 956{
948 struct rb_root *modules = arg; 957 struct rb_root *modules = arg;
949 struct module_info *mi; 958 struct module_info *mi;
@@ -1325,14 +1334,15 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
1325 return __dso__load_kallsyms(dso, filename, map, false); 1334 return __dso__load_kallsyms(dso, filename, map, false);
1326} 1335}
1327 1336
1328static int dso__load_perf_map(struct dso *dso, struct map *map) 1337static int dso__load_perf_map(const char *map_path, struct dso *dso,
1338 struct map *map)
1329{ 1339{
1330 char *line = NULL; 1340 char *line = NULL;
1331 size_t n; 1341 size_t n;
1332 FILE *file; 1342 FILE *file;
1333 int nr_syms = 0; 1343 int nr_syms = 0;
1334 1344
1335 file = fopen(dso->long_name, "r"); 1345 file = fopen(map_path, "r");
1336 if (file == NULL) 1346 if (file == NULL)
1337 goto out_failure; 1347 goto out_failure;
1338 1348
@@ -1416,6 +1426,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1416 return kmod && dso->symtab_type == type; 1426 return kmod && dso->symtab_type == type;
1417 1427
1418 case DSO_BINARY_TYPE__BUILD_ID_CACHE: 1428 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
1429 case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
1419 return true; 1430 return true;
1420 1431
1421 case DSO_BINARY_TYPE__NOT_FOUND: 1432 case DSO_BINARY_TYPE__NOT_FOUND:
@@ -1424,6 +1435,44 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1424 } 1435 }
1425} 1436}
1426 1437
1438/* Checks for the existence of the perf-<pid>.map file in two different
1439 * locations. First, if the process is a separate mount namespace, check in
1440 * that namespace using the pid of the innermost pid namespace. If's not in a
1441 * namespace, or the file can't be found there, try in the mount namespace of
1442 * the tracing process using our view of its pid.
1443 */
1444static int dso__find_perf_map(char *filebuf, size_t bufsz,
1445 struct nsinfo **nsip)
1446{
1447 struct nscookie nsc;
1448 struct nsinfo *nsi;
1449 struct nsinfo *nnsi;
1450 int rc = -1;
1451
1452 nsi = *nsip;
1453
1454 if (nsi->need_setns) {
1455 snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nsi->nstgid);
1456 nsinfo__mountns_enter(nsi, &nsc);
1457 rc = access(filebuf, R_OK);
1458 nsinfo__mountns_exit(&nsc);
1459 if (rc == 0)
1460 return rc;
1461 }
1462
1463 nnsi = nsinfo__copy(nsi);
1464 if (nnsi) {
1465 nsinfo__put(nsi);
1466
1467 nnsi->need_setns = false;
1468 snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nnsi->tgid);
1469 *nsip = nnsi;
1470 rc = 0;
1471 }
1472
1473 return rc;
1474}
1475
1427int dso__load(struct dso *dso, struct map *map) 1476int dso__load(struct dso *dso, struct map *map)
1428{ 1477{
1429 char *name; 1478 char *name;
@@ -1435,8 +1484,21 @@ int dso__load(struct dso *dso, struct map *map)
1435 struct symsrc ss_[2]; 1484 struct symsrc ss_[2];
1436 struct symsrc *syms_ss = NULL, *runtime_ss = NULL; 1485 struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
1437 bool kmod; 1486 bool kmod;
1487 bool perfmap;
1438 unsigned char build_id[BUILD_ID_SIZE]; 1488 unsigned char build_id[BUILD_ID_SIZE];
1489 struct nscookie nsc;
1490 char newmapname[PATH_MAX];
1491 const char *map_path = dso->long_name;
1492
1493 perfmap = strncmp(dso->name, "/tmp/perf-", 10) == 0;
1494 if (perfmap) {
1495 if (dso->nsinfo && (dso__find_perf_map(newmapname,
1496 sizeof(newmapname), &dso->nsinfo) == 0)) {
1497 map_path = newmapname;
1498 }
1499 }
1439 1500
1501 nsinfo__mountns_enter(dso->nsinfo, &nsc);
1440 pthread_mutex_lock(&dso->lock); 1502 pthread_mutex_lock(&dso->lock);
1441 1503
1442 /* check again under the dso->lock */ 1504 /* check again under the dso->lock */
@@ -1461,19 +1523,19 @@ int dso__load(struct dso *dso, struct map *map)
1461 1523
1462 dso->adjust_symbols = 0; 1524 dso->adjust_symbols = 0;
1463 1525
1464 if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { 1526 if (perfmap) {
1465 struct stat st; 1527 struct stat st;
1466 1528
1467 if (lstat(dso->name, &st) < 0) 1529 if (lstat(map_path, &st) < 0)
1468 goto out; 1530 goto out;
1469 1531
1470 if (!symbol_conf.force && st.st_uid && (st.st_uid != geteuid())) { 1532 if (!symbol_conf.force && st.st_uid && (st.st_uid != geteuid())) {
1471 pr_warning("File %s not owned by current user or root, " 1533 pr_warning("File %s not owned by current user or root, "
1472 "ignoring it (use -f to override).\n", dso->name); 1534 "ignoring it (use -f to override).\n", map_path);
1473 goto out; 1535 goto out;
1474 } 1536 }
1475 1537
1476 ret = dso__load_perf_map(dso, map); 1538 ret = dso__load_perf_map(map_path, dso, map);
1477 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : 1539 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
1478 DSO_BINARY_TYPE__NOT_FOUND; 1540 DSO_BINARY_TYPE__NOT_FOUND;
1479 goto out; 1541 goto out;
@@ -1511,9 +1573,15 @@ int dso__load(struct dso *dso, struct map *map)
1511 for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) { 1573 for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) {
1512 struct symsrc *ss = &ss_[ss_pos]; 1574 struct symsrc *ss = &ss_[ss_pos];
1513 bool next_slot = false; 1575 bool next_slot = false;
1576 bool is_reg;
1577 bool nsexit;
1578 int sirc;
1514 1579
1515 enum dso_binary_type symtab_type = binary_type_symtab[i]; 1580 enum dso_binary_type symtab_type = binary_type_symtab[i];
1516 1581
1582 nsexit = (symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE ||
1583 symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO);
1584
1517 if (!dso__is_compatible_symtab_type(dso, kmod, symtab_type)) 1585 if (!dso__is_compatible_symtab_type(dso, kmod, symtab_type))
1518 continue; 1586 continue;
1519 1587
@@ -1521,12 +1589,20 @@ int dso__load(struct dso *dso, struct map *map)
1521 root_dir, name, PATH_MAX)) 1589 root_dir, name, PATH_MAX))
1522 continue; 1590 continue;
1523 1591
1524 if (!is_regular_file(name)) 1592 if (nsexit)
1525 continue; 1593 nsinfo__mountns_exit(&nsc);
1594
1595 is_reg = is_regular_file(name);
1596 sirc = symsrc__init(ss, dso, name, symtab_type);
1526 1597
1527 /* Name is now the name of the next image to try */ 1598 if (nsexit)
1528 if (symsrc__init(ss, dso, name, symtab_type) < 0) 1599 nsinfo__mountns_enter(dso->nsinfo, &nsc);
1600
1601 if (!is_reg || sirc < 0) {
1602 if (sirc >= 0)
1603 symsrc__destroy(ss);
1529 continue; 1604 continue;
1605 }
1530 1606
1531 if (!syms_ss && symsrc__has_symtab(ss)) { 1607 if (!syms_ss && symsrc__has_symtab(ss)) {
1532 syms_ss = ss; 1608 syms_ss = ss;
@@ -1584,6 +1660,7 @@ out_free:
1584out: 1660out:
1585 dso__set_loaded(dso, map->type); 1661 dso__set_loaded(dso, map->type);
1586 pthread_mutex_unlock(&dso->lock); 1662 pthread_mutex_unlock(&dso->lock);
1663 nsinfo__mountns_exit(&nsc);
1587 1664
1588 return ret; 1665 return ret;
1589} 1666}
@@ -1660,7 +1737,7 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map)
1660 } 1737 }
1661 1738
1662 if (!symbol_conf.ignore_vmlinux_buildid) 1739 if (!symbol_conf.ignore_vmlinux_buildid)
1663 filename = dso__build_id_filename(dso, NULL, 0); 1740 filename = dso__build_id_filename(dso, NULL, 0, false);
1664 if (filename != NULL) { 1741 if (filename != NULL) {
1665 err = dso__load_vmlinux(dso, map, filename, true); 1742 err = dso__load_vmlinux(dso, map, filename, true);
1666 if (err > 0) 1743 if (err > 0)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 41ebba9a2eb2..2bd6a1f01a1c 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -186,6 +186,7 @@ struct addr_map_symbol {
186 struct symbol *sym; 186 struct symbol *sym;
187 u64 addr; 187 u64 addr;
188 u64 al_addr; 188 u64 al_addr;
189 u64 phys_addr;
189}; 190};
190 191
191struct branch_info { 192struct branch_info {
@@ -273,7 +274,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); 274int sysfs__read_build_id(const char *filename, void *bf, size_t size);
274int modules__parse(const char *filename, void *arg, 275int modules__parse(const char *filename, void *arg,
275 int (*process_module)(void *arg, const char *name, 276 int (*process_module)(void *arg, const char *name,
276 u64 start)); 277 u64 start, u64 size));
277int filename__read_debuglink(const char *filename, char *debuglink, 278int filename__read_debuglink(const char *filename, char *debuglink,
278 size_t size); 279 size_t size);
279 280
@@ -306,7 +307,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, 307int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss,
307 struct map *map); 308 struct map *map);
308 309
309char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name); 310char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name);
310 311
311void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel); 312void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
312void symbols__insert(struct rb_root *symbols, struct symbol *sym); 313void symbols__insert(struct rb_root *symbols, struct symbol *sym);
@@ -343,6 +344,9 @@ int setup_intlist(struct intlist **list, const char *list_str,
343#ifdef HAVE_LIBELF_SUPPORT 344#ifdef HAVE_LIBELF_SUPPORT
344bool elf__needs_adjust_symbols(GElf_Ehdr ehdr); 345bool elf__needs_adjust_symbols(GElf_Ehdr ehdr);
345void arch__sym_update(struct symbol *s, GElf_Sym *sym); 346void arch__sym_update(struct symbol *s, GElf_Sym *sym);
347void arch__adjust_sym_map_offset(GElf_Sym *sym,
348 GElf_Shdr *shdr __maybe_unused,
349 struct map *map __maybe_unused);
346#endif 350#endif
347 351
348#define SYMBOL_A 0 352#define SYMBOL_A 0
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index bbb4c1957578..19e5db90394c 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -19,6 +19,7 @@
19#ifdef HAVE_SYSCALL_TABLE 19#ifdef HAVE_SYSCALL_TABLE
20#include <linux/compiler.h> 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..e9fb8786da7c 100644
--- a/tools/perf/util/syscalltbl.h
+++ b/tools/perf/util/syscalltbl.h
@@ -17,4 +17,7 @@ void syscalltbl__delete(struct syscalltbl *tbl);
17const char *syscalltbl__name(const struct syscalltbl *tbl, int id); 17const char *syscalltbl__name(const struct syscalltbl *tbl, int id);
18int syscalltbl__id(struct syscalltbl *tbl, const char *name); 18int syscalltbl__id(struct syscalltbl *tbl, const char *name);
19 19
20int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
21int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx);
22
20#endif /* __PERF_SYSCALLTBL_H */ 23#endif /* __PERF_SYSCALLTBL_H */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 378c418ca0c1..aee9a42102ba 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -59,6 +59,8 @@ struct thread *thread__new(pid_t pid, pid_t tid)
59 list_add(&comm->list, &thread->comm_list); 59 list_add(&comm->list, &thread->comm_list);
60 refcount_set(&thread->refcnt, 1); 60 refcount_set(&thread->refcnt, 1);
61 RB_CLEAR_NODE(&thread->rb_node); 61 RB_CLEAR_NODE(&thread->rb_node);
62 /* Thread holds first ref to nsdata. */
63 thread->nsinfo = nsinfo__new(pid);
62 } 64 }
63 65
64 return thread; 66 return thread;
@@ -91,6 +93,7 @@ void thread__delete(struct thread *thread)
91 comm__free(comm); 93 comm__free(comm);
92 } 94 }
93 unwind__finish_access(thread); 95 unwind__finish_access(thread);
96 nsinfo__zput(thread->nsinfo);
94 97
95 free(thread); 98 free(thread);
96} 99}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 4eb849e9098f..cb1a5dd5c2b9 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -34,6 +34,7 @@ struct thread {
34 34
35 void *priv; 35 void *priv;
36 struct thread_stack *ts; 36 struct thread_stack *ts;
37 struct nsinfo *nsinfo;
37#ifdef HAVE_LIBUNWIND_SUPPORT 38#ifdef HAVE_LIBUNWIND_SUPPORT
38 void *addr_space; 39 void *addr_space;
39 struct unwind_libunwind_ops *unwind_libunwind_ops; 40 struct unwind_libunwind_ops *unwind_libunwind_ops;
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 829471a1c6d7..d549e50db397 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -34,6 +34,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, 34typedef s64 (*event_op3)(struct perf_tool *tool, union perf_event *event,
35 struct perf_session *session); 35 struct perf_session *session);
36 36
37enum show_feature_header {
38 SHOW_FEAT_NO_HEADER = 0,
39 SHOW_FEAT_HEADER,
40 SHOW_FEAT_HEADER_FULL_INFO,
41};
42
37struct perf_tool { 43struct perf_tool {
38 event_sample sample, 44 event_sample sample,
39 read; 45 read;
@@ -63,11 +69,13 @@ struct perf_tool {
63 cpu_map, 69 cpu_map,
64 stat_config, 70 stat_config,
65 stat, 71 stat,
66 stat_round; 72 stat_round,
73 feature;
67 event_op3 auxtrace; 74 event_op3 auxtrace;
68 bool ordered_events; 75 bool ordered_events;
69 bool ordering_requires_timestamps; 76 bool ordering_requires_timestamps;
70 bool namespace_events; 77 bool namespace_events;
78 enum show_feature_header show_feat_hdr;
71}; 79};
72 80
73#endif /* __PERF_TOOL_H */ 81#endif /* __PERF_TOOL_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 988111e0bab5..4c360daa4e24 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -143,13 +143,17 @@ out:
143 return list; 143 return list;
144} 144}
145 145
146static int slow_copyfile(const char *from, const char *to) 146static int slow_copyfile(const char *from, const char *to, struct nsinfo *nsi)
147{ 147{
148 int err = -1; 148 int err = -1;
149 char *line = NULL; 149 char *line = NULL;
150 size_t n; 150 size_t n;
151 FILE *from_fp = fopen(from, "r"), *to_fp; 151 FILE *from_fp, *to_fp;
152 struct nscookie nsc;
152 153
154 nsinfo__mountns_enter(nsi, &nsc);
155 from_fp = fopen(from, "r");
156 nsinfo__mountns_exit(&nsc);
153 if (from_fp == NULL) 157 if (from_fp == NULL)
154 goto out; 158 goto out;
155 159
@@ -198,15 +202,21 @@ int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
198 return size ? -1 : 0; 202 return size ? -1 : 0;
199} 203}
200 204
201int copyfile_mode(const char *from, const char *to, mode_t mode) 205static int copyfile_mode_ns(const char *from, const char *to, mode_t mode,
206 struct nsinfo *nsi)
202{ 207{
203 int fromfd, tofd; 208 int fromfd, tofd;
204 struct stat st; 209 struct stat st;
205 int err = -1; 210 int err;
206 char *tmp = NULL, *ptr = NULL; 211 char *tmp = NULL, *ptr = NULL;
212 struct nscookie nsc;
207 213
208 if (stat(from, &st)) 214 nsinfo__mountns_enter(nsi, &nsc);
215 err = stat(from, &st);
216 nsinfo__mountns_exit(&nsc);
217 if (err)
209 goto out; 218 goto out;
219 err = -1;
210 220
211 /* extra 'x' at the end is to reserve space for '.' */ 221 /* extra 'x' at the end is to reserve space for '.' */
212 if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) { 222 if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) {
@@ -227,11 +237,13 @@ int copyfile_mode(const char *from, const char *to, mode_t mode)
227 goto out_close_to; 237 goto out_close_to;
228 238
229 if (st.st_size == 0) { /* /proc? do it slowly... */ 239 if (st.st_size == 0) { /* /proc? do it slowly... */
230 err = slow_copyfile(from, tmp); 240 err = slow_copyfile(from, tmp, nsi);
231 goto out_close_to; 241 goto out_close_to;
232 } 242 }
233 243
244 nsinfo__mountns_enter(nsi, &nsc);
234 fromfd = open(from, O_RDONLY); 245 fromfd = open(from, O_RDONLY);
246 nsinfo__mountns_exit(&nsc);
235 if (fromfd < 0) 247 if (fromfd < 0)
236 goto out_close_to; 248 goto out_close_to;
237 249
@@ -248,6 +260,16 @@ out:
248 return err; 260 return err;
249} 261}
250 262
263int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi)
264{
265 return copyfile_mode_ns(from, to, 0755, nsi);
266}
267
268int copyfile_mode(const char *from, const char *to, mode_t mode)
269{
270 return copyfile_mode_ns(from, to, mode, NULL);
271}
272
251int copyfile(const char *from, const char *to) 273int copyfile(const char *from, const char *to)
252{ 274{
253 return copyfile_mode(from, to, 0755); 275 return copyfile_mode(from, to, 0755);
@@ -259,6 +281,7 @@ static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
259 size_t left = n; 281 size_t left = n;
260 282
261 while (left) { 283 while (left) {
284 /* buf must be treated as const if !is_read. */
262 ssize_t ret = is_read ? read(fd, buf, left) : 285 ssize_t ret = is_read ? read(fd, buf, left) :
263 write(fd, buf, left); 286 write(fd, buf, left);
264 287
@@ -286,9 +309,10 @@ ssize_t readn(int fd, void *buf, size_t n)
286/* 309/*
287 * Write exactly 'n' bytes or return an error. 310 * Write exactly 'n' bytes or return an error.
288 */ 311 */
289ssize_t writen(int fd, void *buf, size_t n) 312ssize_t writen(int fd, const void *buf, size_t n)
290{ 313{
291 return ion(false, fd, buf, n); 314 /* ion does not modify buf. */
315 return ion(false, fd, (void *)buf, n);
292} 316}
293 317
294size_t hex_width(u64 v) 318size_t hex_width(u64 v)
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 2c9e58a45310..b136c271125f 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -12,6 +12,7 @@
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,11 @@ 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);
37int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi);
36int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size); 38int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size);
37 39
38ssize_t readn(int fd, void *buf, size_t n); 40ssize_t readn(int fd, void *buf, size_t n);
39ssize_t writen(int fd, void *buf, size_t n); 41ssize_t writen(int fd, const void *buf, size_t n);
40 42
41size_t hex_width(u64 v); 43size_t hex_width(u64 v);
42int hex2u64(const char *ptr, u64 *val); 44int hex2u64(const char *ptr, u64 *val);
@@ -58,4 +60,8 @@ const char *perf_tip(const char *dirpath);
58int sched_getcpu(void); 60int sched_getcpu(void);
59#endif 61#endif
60 62
63#ifndef HAVE_SETNS_SUPPORT
64int setns(int fd, int nstype);
65#endif
66
61#endif /* GIT_COMPAT_UTIL_H */ 67#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
index 5de2e15e2eda..8a32bb0095e5 100644
--- a/tools/perf/util/values.c
+++ b/tools/perf/util/values.c
@@ -12,7 +12,7 @@ int perf_read_values_init(struct perf_read_values *values)
12 values->threads_max = 16; 12 values->threads_max = 16;
13 values->pid = malloc(values->threads_max * sizeof(*values->pid)); 13 values->pid = malloc(values->threads_max * sizeof(*values->pid));
14 values->tid = malloc(values->threads_max * sizeof(*values->tid)); 14 values->tid = malloc(values->threads_max * sizeof(*values->tid));
15 values->value = malloc(values->threads_max * sizeof(*values->value)); 15 values->value = zalloc(values->threads_max * sizeof(*values->value));
16 if (!values->pid || !values->tid || !values->value) { 16 if (!values->pid || !values->tid || !values->value) {
17 pr_debug("failed to allocate read_values threads arrays"); 17 pr_debug("failed to allocate read_values threads arrays");
18 goto out_free_pid; 18 goto out_free_pid;
@@ -98,15 +98,16 @@ static int perf_read_values__findnew_thread(struct perf_read_values *values,
98 return i; 98 return i;
99 } 99 }
100 100
101 i = values->threads + 1; 101 i = values->threads;
102 values->value[i] = malloc(values->counters_max * sizeof(**values->value)); 102
103 values->value[i] = zalloc(values->counters_max * sizeof(**values->value));
103 if (!values->value[i]) { 104 if (!values->value[i]) {
104 pr_debug("failed to allocate read_values counters array"); 105 pr_debug("failed to allocate read_values counters array");
105 return -ENOMEM; 106 return -ENOMEM;
106 } 107 }
107 values->pid[i] = pid; 108 values->pid[i] = pid;
108 values->tid[i] = tid; 109 values->tid[i] = tid;
109 values->threads = i; 110 values->threads = i + 1;
110 111
111 return i; 112 return i;
112} 113}
@@ -130,12 +131,16 @@ static int perf_read_values__enlarge_counters(struct perf_read_values *values)
130 131
131 for (i = 0; i < values->threads; i++) { 132 for (i = 0; i < values->threads; i++) {
132 u64 *value = realloc(values->value[i], counters_max * sizeof(**values->value)); 133 u64 *value = realloc(values->value[i], counters_max * sizeof(**values->value));
134 int j;
133 135
134 if (value) { 136 if (!value) {
135 pr_debug("failed to enlarge read_values ->values array"); 137 pr_debug("failed to enlarge read_values ->values array");
136 goto out_free_name; 138 goto out_free_name;
137 } 139 }
138 140
141 for (j = values->counters_max; j < counters_max; j++)
142 value[j] = 0;
143
139 values->value[i] = value; 144 values->value[i] = value;
140 } 145 }
141 146
@@ -187,7 +192,7 @@ int perf_read_values_add_value(struct perf_read_values *values,
187 if (cindex < 0) 192 if (cindex < 0)
188 return cindex; 193 return cindex;
189 194
190 values->value[tindex][cindex] = value; 195 values->value[tindex][cindex] += value;
191 return 0; 196 return 0;
192} 197}
193 198
diff --git a/tools/perf/util/xyarray.c b/tools/perf/util/xyarray.c
index 7251fdbabced..c8f415d9877b 100644
--- a/tools/perf/util/xyarray.c
+++ b/tools/perf/util/xyarray.c
@@ -12,6 +12,8 @@ struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)
12 xy->entry_size = entry_size; 12 xy->entry_size = entry_size;
13 xy->row_size = row_size; 13 xy->row_size = row_size;
14 xy->entries = xlen * ylen; 14 xy->entries = xlen * ylen;
15 xy->max_x = xlen;
16 xy->max_y = ylen;
15 } 17 }
16 18
17 return xy; 19 return xy;
diff --git a/tools/perf/util/xyarray.h b/tools/perf/util/xyarray.h
index 7f30af371b7e..4ba726c90870 100644
--- a/tools/perf/util/xyarray.h
+++ b/tools/perf/util/xyarray.h
@@ -7,6 +7,8 @@ struct xyarray {
7 size_t row_size; 7 size_t row_size;
8 size_t entry_size; 8 size_t entry_size;
9 size_t entries; 9 size_t entries;
10 size_t max_x;
11 size_t max_y;
10 char contents[]; 12 char contents[];
11}; 13};
12 14
@@ -19,4 +21,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]; 21 return &xy->contents[x * xy->row_size + y * xy->entry_size];
20} 22}
21 23
24static inline int xyarray__max_y(struct xyarray *xy)
25{
26 return xy->max_x;
27}
28
29static inline int xyarray__max_x(struct xyarray *xy)
30{
31 return xy->max_y;
32}
33
22#endif /* _PERF_XYARRAY_H_ */ 34#endif /* _PERF_XYARRAY_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/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..943b6b614683 100644
--- a/tools/power/acpi/tools/acpidump/apmain.c
+++ b/tools/power/acpi/tools/acpidump/apmain.c
@@ -300,7 +300,7 @@ static int ap_do_options(int argc, char **argv)
300 * 300 *
301 ******************************************************************************/ 301 ******************************************************************************/
302 302
303#ifndef _GNU_EFI 303#if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
304int ACPI_SYSTEM_XFACE main(int argc, char *argv[]) 304int ACPI_SYSTEM_XFACE main(int argc, char *argv[])
305#else 305#else
306int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[]) 306int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[])
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index d6e1c02ddcfe..4c5a481a850c 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -26,7 +26,7 @@ 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 := $(realpath $(OUTPUT))
30$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist)) 30$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
31endif 31endif
32 32
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/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
index 39c2c7d067bb..32d37c9be791 100644
--- a/tools/power/cpupower/utils/helpers/cpuid.c
+++ b/tools/power/cpupower/utils/helpers/cpuid.c
@@ -42,7 +42,7 @@ cpuid_func(edx);
42 * 42 *
43 * TBD: Should there be a cpuid alternative for this if /proc is not mounted? 43 * TBD: Should there be a cpuid alternative for this if /proc is not mounted?
44 */ 44 */
45int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info) 45int get_cpu_info(struct cpupower_cpu_info *cpu_info)
46{ 46{
47 FILE *fp; 47 FILE *fp;
48 char value[64]; 48 char value[64];
@@ -70,7 +70,7 @@ int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info)
70 if (!strncmp(value, "processor\t: ", 12)) 70 if (!strncmp(value, "processor\t: ", 12))
71 sscanf(value, "processor\t: %u", &proc); 71 sscanf(value, "processor\t: %u", &proc);
72 72
73 if (proc != cpu) 73 if (proc != (unsigned int)base_cpu)
74 continue; 74 continue;
75 75
76 /* Get CPU vendor */ 76 /* 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..a5e7ddf19dbd 100644
--- a/tools/power/cpupower/utils/helpers/misc.c
+++ b/tools/power/cpupower/utils/helpers/misc.c
@@ -13,7 +13,7 @@ int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
13 13
14 *support = *active = *states = 0; 14 *support = *active = *states = 0;
15 15
16 ret = get_cpu_info(0, &cpu_info); 16 ret = get_cpu_info(&cpu_info);
17 if (ret) 17 if (ret)
18 return ret; 18 return ret;
19 19
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/pm-graph/Makefile b/tools/power/pm-graph/Makefile
index 4d0ccc89e6c6..32f40eacdafe 100644
--- a/tools/power/pm-graph/Makefile
+++ b/tools/power/pm-graph/Makefile
@@ -4,7 +4,7 @@ DESTDIR ?=
4all: 4all:
5 @echo "Nothing to build" 5 @echo "Nothing to build"
6 6
7install : 7install : uninstall
8 install -d $(DESTDIR)$(PREFIX)/lib/pm-graph 8 install -d $(DESTDIR)$(PREFIX)/lib/pm-graph
9 install analyze_suspend.py $(DESTDIR)$(PREFIX)/lib/pm-graph 9 install analyze_suspend.py $(DESTDIR)$(PREFIX)/lib/pm-graph
10 install analyze_boot.py $(DESTDIR)$(PREFIX)/lib/pm-graph 10 install analyze_boot.py $(DESTDIR)$(PREFIX)/lib/pm-graph
@@ -17,12 +17,15 @@ install :
17 install sleepgraph.8 $(DESTDIR)$(PREFIX)/share/man/man8 17 install sleepgraph.8 $(DESTDIR)$(PREFIX)/share/man/man8
18 18
19uninstall : 19uninstall :
20 rm $(DESTDIR)$(PREFIX)/share/man/man8/bootgraph.8 20 rm -f $(DESTDIR)$(PREFIX)/share/man/man8/bootgraph.8
21 rm $(DESTDIR)$(PREFIX)/share/man/man8/sleepgraph.8 21 rm -f $(DESTDIR)$(PREFIX)/share/man/man8/sleepgraph.8
22 22
23 rm $(DESTDIR)$(PREFIX)/bin/bootgraph 23 rm -f $(DESTDIR)$(PREFIX)/bin/bootgraph
24 rm $(DESTDIR)$(PREFIX)/bin/sleepgraph 24 rm -f $(DESTDIR)$(PREFIX)/bin/sleepgraph
25 25
26 rm $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_boot.py 26 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_boot.py
27 rm $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_suspend.py 27 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_suspend.py
28 rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph 28 rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/*.pyc
29 if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph ] ; then \
30 rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph; \
31 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/scripts/Makefile.include b/tools/scripts/Makefile.include
index ccad8ce925e4..9dc8f078a83c 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -1,7 +1,7 @@
1ifneq ($(O),) 1ifneq ($(O),)
2ifeq ($(origin O), command line) 2ifeq ($(origin O), command line)
3 dummy := $(if $(shell test -d $(O) || echo $(O)),$(error O=$(O) does not exist),) 3 ABSOLUTE_O := $(realpath $(O))
4 ABSOLUTE_O := $(shell cd $(O) ; pwd) 4 dummy := $(if $(ABSOLUTE_O),,$(error O=$(O) does not exist))
5 OUTPUT := $(ABSOLUTE_O)/$(if $(subdir),$(subdir)/) 5 OUTPUT := $(ABSOLUTE_O)/$(if $(subdir),$(subdir)/)
6 COMMAND_O := O=$(ABSOLUTE_O) 6 COMMAND_O := O=$(ABSOLUTE_O)
7ifeq ($(objtree),) 7ifeq ($(objtree),)
@@ -12,7 +12,7 @@ endif
12 12
13# check that the output directory actually exists 13# check that the output directory actually exists
14ifneq ($(OUTPUT),) 14ifneq ($(OUTPUT),)
15OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd) 15OUTDIR := $(realpath $(OUTPUT))
16$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist)) 16$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
17endif 17endif
18 18
@@ -39,7 +39,9 @@ EXTRA_WARNINGS += -Wundef
39EXTRA_WARNINGS += -Wwrite-strings 39EXTRA_WARNINGS += -Wwrite-strings
40EXTRA_WARNINGS += -Wformat 40EXTRA_WARNINGS += -Wformat
41 41
42ifneq ($(CC), clang) 42CC_NO_CLANG := $(shell $(CC) -dM -E -x c /dev/null | grep -Fq "__clang__"; echo $$?)
43
44ifeq ($(CC_NO_CLANG), 1)
43EXTRA_WARNINGS += -Wstrict-aliasing=3 45EXTRA_WARNINGS += -Wstrict-aliasing=3
44endif 46endif
45 47
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/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 4c2fa98ef39d..d20791c3f499 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -1546,8 +1546,8 @@ static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
1546 else { 1546 else {
1547 memcpy(iobuf, mmio->addr.base + dpa, len); 1547 memcpy(iobuf, mmio->addr.base + dpa, len);
1548 1548
1549 /* give us some some coverage of the mmio_flush_range() API */ 1549 /* give us some some coverage of the arch_invalidate_pmem() API */
1550 mmio_flush_range(mmio->addr.base + dpa, len); 1550 arch_invalidate_pmem(mmio->addr.base + dpa, len);
1551 } 1551 }
1552 nd_region_release_lane(nd_region, lane); 1552 nd_region_release_lane(nd_region, lane);
1553 1553
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 153c3a181a4c..f4b23d697448 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -15,9 +15,9 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test
15 test_align 15 test_align
16 16
17TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \ 17TEST_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 18 test_pkt_md_access.o test_xdp_redirect.o sockmap_parse_prog.o sockmap_verdict_prog.o
19 19
20TEST_PROGS := test_kmod.sh 20TEST_PROGS := test_kmod.sh test_xdp_redirect.sh
21 21
22include ../lib.mk 22include ../lib.mk
23 23
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index d50ac342dc92..36fb9161b34a 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -38,6 +38,8 @@ static int (*bpf_clone_redirect)(void *ctx, int ifindex, int flags) =
38 (void *) BPF_FUNC_clone_redirect; 38 (void *) BPF_FUNC_clone_redirect;
39static int (*bpf_redirect)(int ifindex, int flags) = 39static int (*bpf_redirect)(int ifindex, int flags) =
40 (void *) BPF_FUNC_redirect; 40 (void *) BPF_FUNC_redirect;
41static int (*bpf_redirect_map)(void *map, int key, int flags) =
42 (void *) BPF_FUNC_redirect_map;
41static int (*bpf_perf_event_output)(void *ctx, void *map, 43static int (*bpf_perf_event_output)(void *ctx, void *map,
42 unsigned long long flags, void *data, 44 unsigned long long flags, void *data,
43 int size) = 45 int size) =
@@ -63,6 +65,12 @@ static int (*bpf_xdp_adjust_head)(void *ctx, int offset) =
63static int (*bpf_setsockopt)(void *ctx, int level, int optname, void *optval, 65static int (*bpf_setsockopt)(void *ctx, int level, int optname, void *optval,
64 int optlen) = 66 int optlen) =
65 (void *) BPF_FUNC_setsockopt; 67 (void *) BPF_FUNC_setsockopt;
68static int (*bpf_sk_redirect_map)(void *map, int key, int flags) =
69 (void *) BPF_FUNC_sk_redirect_map;
70static int (*bpf_sock_map_update)(void *map, void *key, void *value,
71 unsigned long long flags) =
72 (void *) BPF_FUNC_sock_map_update;
73
66 74
67/* llvm builtin functions that eBPF C program may use to 75/* llvm builtin functions that eBPF C program may use to
68 * emit BPF_LD_ABS and BPF_LD_IND instructions 76 * emit BPF_LD_ABS and BPF_LD_IND instructions
@@ -85,6 +93,7 @@ struct bpf_map_def {
85 unsigned int max_entries; 93 unsigned int max_entries;
86 unsigned int map_flags; 94 unsigned int map_flags;
87 unsigned int inner_map_idx; 95 unsigned int inner_map_idx;
96 unsigned int numa_node;
88}; 97};
89 98
90static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) = 99static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) =
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..fae3b96c3aa4
--- /dev/null
+++ b/tools/testing/selftests/bpf/sockmap_parse_prog.c
@@ -0,0 +1,38 @@
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
33 bpf_printk("parse: data[0] = (%u): local_port %i remote %i\n",
34 d[0], lport, bpf_ntohl(rport));
35 return skb->len;
36}
37
38char _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..9b99bd10807d
--- /dev/null
+++ b/tools/testing/selftests/bpf/sockmap_verdict_prog.c
@@ -0,0 +1,68 @@
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 bpf_printk("verdict: data[0] = redir(%u:%u)\n", map, sk);
62
63 if (!map)
64 return bpf_sk_redirect_map(&sock_map_rx, sk, 0);
65 return bpf_sk_redirect_map(&sock_map_tx, sk, 0);
66}
67
68char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/test_align.c b/tools/testing/selftests/bpf/test_align.c
index bccebd935907..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;
@@ -380,27 +629,50 @@ static int do_test_single(struct bpf_align_test *test)
380 prog_len = probe_filter_length(prog); 629 prog_len = probe_filter_length(prog);
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)); 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_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 79601c81e169..fe3a443a1102 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,444 @@ 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, 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 without programs */
552 for (i = 0; i < 6; i++) {
553 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
554 if (err) {
555 printf("Failed noprog update sockmap '%i:%i'\n",
556 i, sfd[i]);
557 goto out_sockmap;
558 }
559 }
560
561 /* Test attaching/detaching bad fds */
562 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0);
563 if (!err) {
564 printf("Failed invalid parser prog attach\n");
565 goto out_sockmap;
566 }
567
568 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0);
569 if (!err) {
570 printf("Failed invalid verdict prog attach\n");
571 goto out_sockmap;
572 }
573
574 err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
575 if (!err) {
576 printf("Failed unknown prog attach\n");
577 goto out_sockmap;
578 }
579
580 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
581 if (err) {
582 printf("Failed empty parser prog detach\n");
583 goto out_sockmap;
584 }
585
586 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
587 if (err) {
588 printf("Failed empty verdict prog detach\n");
589 goto out_sockmap;
590 }
591
592 err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
593 if (!err) {
594 printf("Detach invalid prog successful\n");
595 goto out_sockmap;
596 }
597
598 /* Load SK_SKB program and Attach */
599 err = bpf_prog_load(SOCKMAP_PARSE_PROG,
600 BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog);
601 if (err) {
602 printf("Failed to load SK_SKB parse prog\n");
603 goto out_sockmap;
604 }
605
606 err = bpf_prog_load(SOCKMAP_VERDICT_PROG,
607 BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog);
608 if (err) {
609 printf("Failed to load SK_SKB verdict prog\n");
610 goto out_sockmap;
611 }
612
613 bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx");
614 if (IS_ERR(bpf_map_rx)) {
615 printf("Failed to load map rx from verdict prog\n");
616 goto out_sockmap;
617 }
618
619 map_fd_rx = bpf_map__fd(bpf_map_rx);
620 if (map_fd_rx < 0) {
621 printf("Failed to get map fd\n");
622 goto out_sockmap;
623 }
624
625 bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx");
626 if (IS_ERR(bpf_map_tx)) {
627 printf("Failed to load map tx from verdict prog\n");
628 goto out_sockmap;
629 }
630
631 map_fd_tx = bpf_map__fd(bpf_map_tx);
632 if (map_fd_tx < 0) {
633 printf("Failed to get map tx fd\n");
634 goto out_sockmap;
635 }
636
637 bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break");
638 if (IS_ERR(bpf_map_break)) {
639 printf("Failed to load map tx from verdict prog\n");
640 goto out_sockmap;
641 }
642
643 map_fd_break = bpf_map__fd(bpf_map_break);
644 if (map_fd_break < 0) {
645 printf("Failed to get map tx fd\n");
646 goto out_sockmap;
647 }
648
649 err = bpf_prog_attach(parse_prog, map_fd_break,
650 BPF_SK_SKB_STREAM_PARSER, 0);
651 if (!err) {
652 printf("Allowed attaching SK_SKB program to invalid map\n");
653 goto out_sockmap;
654 }
655
656 err = bpf_prog_attach(parse_prog, map_fd_rx,
657 BPF_SK_SKB_STREAM_PARSER, 0);
658 if (err) {
659 printf("Failed stream parser bpf prog attach\n");
660 goto out_sockmap;
661 }
662
663 err = bpf_prog_attach(verdict_prog, map_fd_rx,
664 BPF_SK_SKB_STREAM_VERDICT, 0);
665 if (err) {
666 printf("Failed stream verdict bpf prog attach\n");
667 goto out_sockmap;
668 }
669
670 err = bpf_prog_attach(verdict_prog, map_fd_rx,
671 __MAX_BPF_ATTACH_TYPE, 0);
672 if (!err) {
673 printf("Attached unknown bpf prog\n");
674 goto out_sockmap;
675 }
676
677 /* Test map update elem afterwards fd lives in fd and map_fd */
678 for (i = 0; i < 6; i++) {
679 err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY);
680 if (err) {
681 printf("Failed map_fd_rx update sockmap %i '%i:%i'\n",
682 err, i, sfd[i]);
683 goto out_sockmap;
684 }
685 err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY);
686 if (err) {
687 printf("Failed map_fd_tx update sockmap %i '%i:%i'\n",
688 err, i, sfd[i]);
689 goto out_sockmap;
690 }
691 }
692
693 /* Test map delete elem and remove send/recv sockets */
694 for (i = 2; i < 4; i++) {
695 err = bpf_map_delete_elem(map_fd_rx, &i);
696 if (err) {
697 printf("Failed delete sockmap rx %i '%i:%i'\n",
698 err, i, sfd[i]);
699 goto out_sockmap;
700 }
701 err = bpf_map_delete_elem(map_fd_tx, &i);
702 if (err) {
703 printf("Failed delete sockmap tx %i '%i:%i'\n",
704 err, i, sfd[i]);
705 goto out_sockmap;
706 }
707 }
708
709 /* Test map send/recv */
710 for (i = 0; i < 2; i++) {
711 buf[0] = i;
712 buf[1] = 0x5;
713 sc = send(sfd[2], buf, 20, 0);
714 if (sc < 0) {
715 printf("Failed sockmap send\n");
716 goto out_sockmap;
717 }
718
719 FD_ZERO(&w);
720 FD_SET(sfd[3], &w);
721 to.tv_sec = 1;
722 to.tv_usec = 0;
723 s = select(sfd[3] + 1, &w, NULL, NULL, &to);
724 if (s == -1) {
725 perror("Failed sockmap select()");
726 goto out_sockmap;
727 } else if (!s) {
728 printf("Failed sockmap unexpected timeout\n");
729 goto out_sockmap;
730 }
731
732 if (!FD_ISSET(sfd[3], &w)) {
733 printf("Failed sockmap select/recv\n");
734 goto out_sockmap;
735 }
736
737 rc = recv(sfd[3], buf, sizeof(buf), 0);
738 if (rc < 0) {
739 printf("Failed sockmap recv\n");
740 goto out_sockmap;
741 }
742 }
743
744 /* Negative null entry lookup from datapath should be dropped */
745 buf[0] = 1;
746 buf[1] = 12;
747 sc = send(sfd[2], buf, 20, 0);
748 if (sc < 0) {
749 printf("Failed sockmap send\n");
750 goto out_sockmap;
751 }
752
753 /* Push fd into same slot */
754 i = 2;
755 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
756 if (!err) {
757 printf("Failed allowed sockmap dup slot BPF_NOEXIST\n");
758 goto out_sockmap;
759 }
760
761 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
762 if (err) {
763 printf("Failed sockmap update new slot BPF_ANY\n");
764 goto out_sockmap;
765 }
766
767 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
768 if (err) {
769 printf("Failed sockmap update new slot BPF_EXIST\n");
770 goto out_sockmap;
771 }
772
773 /* Delete the elems without programs */
774 for (i = 0; i < 6; i++) {
775 err = bpf_map_delete_elem(fd, &i);
776 if (err) {
777 printf("Failed delete sockmap %i '%i:%i'\n",
778 err, i, sfd[i]);
779 }
780 }
781
782 /* Test having multiple maps open and set with programs on same fds */
783 err = bpf_prog_attach(parse_prog, fd,
784 BPF_SK_SKB_STREAM_PARSER, 0);
785 if (err) {
786 printf("Failed fd bpf parse prog attach\n");
787 goto out_sockmap;
788 }
789 err = bpf_prog_attach(verdict_prog, fd,
790 BPF_SK_SKB_STREAM_VERDICT, 0);
791 if (err) {
792 printf("Failed fd bpf verdict prog attach\n");
793 goto out_sockmap;
794 }
795
796 for (i = 4; i < 6; i++) {
797 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
798 if (!err) {
799 printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n",
800 err, i, sfd[i]);
801 goto out_sockmap;
802 }
803 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
804 if (!err) {
805 printf("Failed allowed duplicate program in update NOEXIST sockmap %i '%i:%i'\n",
806 err, i, sfd[i]);
807 goto out_sockmap;
808 }
809 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
810 if (!err) {
811 printf("Failed allowed duplicate program in update EXIST sockmap %i '%i:%i'\n",
812 err, i, sfd[i]);
813 goto out_sockmap;
814 }
815 }
816
817 /* Test tasks number of forked operations */
818 for (i = 0; i < tasks; i++) {
819 pid[i] = fork();
820 if (pid[i] == 0) {
821 for (i = 0; i < 6; i++) {
822 bpf_map_delete_elem(map_fd_tx, &i);
823 bpf_map_delete_elem(map_fd_rx, &i);
824 bpf_map_update_elem(map_fd_tx, &i,
825 &sfd[i], BPF_ANY);
826 bpf_map_update_elem(map_fd_rx, &i,
827 &sfd[i], BPF_ANY);
828 }
829 exit(0);
830 } else if (pid[i] == -1) {
831 printf("Couldn't spawn #%d process!\n", i);
832 exit(1);
833 }
834 }
835
836 for (i = 0; i < tasks; i++) {
837 int status;
838
839 assert(waitpid(pid[i], &status, 0) == pid[i]);
840 assert(status == 0);
841 }
842
843 err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
844 if (!err) {
845 printf("Detached an invalid prog type.\n");
846 goto out_sockmap;
847 }
848
849 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
850 if (err) {
851 printf("Failed parser prog detach\n");
852 goto out_sockmap;
853 }
854
855 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
856 if (err) {
857 printf("Failed parser prog detach\n");
858 goto out_sockmap;
859 }
860
861 /* Test map close sockets */
862 for (i = 0; i < 6; i++)
863 close(sfd[i]);
864 close(fd);
865 close(map_fd_rx);
866 bpf_object__close(obj);
867 return;
868out:
869 for (i = 0; i < 6; i++)
870 close(sfd[i]);
871 printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno));
872 exit(1);
873out_sockmap:
874 for (i = 0; i < 6; i++)
875 close(sfd[i]);
876 close(fd);
877 exit(1);
878}
879
441#define MAP_SIZE (32 * 1024) 880#define MAP_SIZE (32 * 1024)
442 881
443static void test_map_large(void) 882static void test_map_large(void)
@@ -605,6 +1044,9 @@ static void run_all_tests(void)
605 1044
606 test_arraymap_percpu_many_keys(); 1045 test_arraymap_percpu_many_keys();
607 1046
1047 test_devmap(0, NULL);
1048 test_sockmap(0, NULL);
1049
608 test_map_large(); 1050 test_map_large();
609 test_map_parallel(); 1051 test_map_parallel();
610 test_map_stress(); 1052 test_map_stress();
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..11ee25cea227 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -75,39 +75,6 @@ static struct {
75 __ret; \ 75 __ret; \
76}) 76})
77 77
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, 78static int bpf_find_map(const char *test, struct bpf_object *obj,
112 const char *name) 79 const char *name)
113{ 80{
@@ -130,8 +97,10 @@ static void test_pkt_access(void)
130 int err, prog_fd; 97 int err, prog_fd;
131 98
132 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd); 99 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
133 if (err) 100 if (err) {
101 error_cnt++;
134 return; 102 return;
103 }
135 104
136 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v4, sizeof(pkt_v4), 105 err = bpf_prog_test_run(prog_fd, 100000, &pkt_v4, sizeof(pkt_v4),
137 NULL, NULL, &retval, &duration); 106 NULL, NULL, &retval, &duration);
@@ -162,8 +131,10 @@ static void test_xdp(void)
162 int err, prog_fd, map_fd; 131 int err, prog_fd, map_fd;
163 132
164 err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd); 133 err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
165 if (err) 134 if (err) {
135 error_cnt++;
166 return; 136 return;
137 }
167 138
168 map_fd = bpf_find_map(__func__, obj, "vip2tnl"); 139 map_fd = bpf_find_map(__func__, obj, "vip2tnl");
169 if (map_fd < 0) 140 if (map_fd < 0)
@@ -223,8 +194,10 @@ static void test_l4lb(void)
223 u32 *magic = (u32 *)buf; 194 u32 *magic = (u32 *)buf;
224 195
225 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd); 196 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
226 if (err) 197 if (err) {
198 error_cnt++;
227 return; 199 return;
200 }
228 201
229 map_fd = bpf_find_map(__func__, obj, "vip_map"); 202 map_fd = bpf_find_map(__func__, obj, "vip_map");
230 if (map_fd < 0) 203 if (map_fd < 0)
@@ -280,8 +253,10 @@ static void test_tcp_estats(void)
280 253
281 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd); 254 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
282 CHECK(err, "", "err %d errno %d\n", err, errno); 255 CHECK(err, "", "err %d errno %d\n", err, errno);
283 if (err) 256 if (err) {
257 error_cnt++;
284 return; 258 return;
259 }
285 260
286 bpf_object__close(obj); 261 bpf_object__close(obj);
287} 262}
@@ -304,7 +279,7 @@ static void test_bpf_obj_id(void)
304 /* +1 to test for the info_len returned by kernel */ 279 /* +1 to test for the info_len returned by kernel */
305 struct bpf_prog_info prog_infos[nr_iters + 1]; 280 struct bpf_prog_info prog_infos[nr_iters + 1];
306 struct bpf_map_info map_infos[nr_iters + 1]; 281 struct bpf_map_info map_infos[nr_iters + 1];
307 char jited_insns[128], xlated_insns[128]; 282 char jited_insns[128], xlated_insns[128], zeros[128];
308 __u32 i, next_id, info_len, nr_id_found, duration = 0; 283 __u32 i, next_id, info_len, nr_id_found, duration = 0;
309 int sysctl_fd, jit_enabled = 0, err = 0; 284 int sysctl_fd, jit_enabled = 0, err = 0;
310 __u64 array_value; 285 __u64 array_value;
@@ -330,16 +305,22 @@ static void test_bpf_obj_id(void)
330 objs[i] = NULL; 305 objs[i] = NULL;
331 306
332 /* Check bpf_obj_get_info_by_fd() */ 307 /* Check bpf_obj_get_info_by_fd() */
308 bzero(zeros, sizeof(zeros));
333 for (i = 0; i < nr_iters; i++) { 309 for (i = 0; i < nr_iters; i++) {
334 err = bpf_prog_load(file, BPF_PROG_TYPE_SOCKET_FILTER, 310 err = bpf_prog_load(file, BPF_PROG_TYPE_SOCKET_FILTER,
335 &objs[i], &prog_fds[i]); 311 &objs[i], &prog_fds[i]);
336 /* test_obj_id.o is a dumb prog. It should never fail 312 /* test_obj_id.o is a dumb prog. It should never fail
337 * to load. 313 * to load.
338 */ 314 */
315 if (err)
316 error_cnt++;
339 assert(!err); 317 assert(!err);
340 318
341 /* Check getting prog info */ 319 /* Check getting prog info */
342 info_len = sizeof(struct bpf_prog_info) * 2; 320 info_len = sizeof(struct bpf_prog_info) * 2;
321 bzero(&prog_infos[i], info_len);
322 bzero(jited_insns, sizeof(jited_insns));
323 bzero(xlated_insns, sizeof(xlated_insns));
343 prog_infos[i].jited_prog_insns = ptr_to_u64(jited_insns); 324 prog_infos[i].jited_prog_insns = ptr_to_u64(jited_insns);
344 prog_infos[i].jited_prog_len = sizeof(jited_insns); 325 prog_infos[i].jited_prog_len = sizeof(jited_insns);
345 prog_infos[i].xlated_prog_insns = ptr_to_u64(xlated_insns); 326 prog_infos[i].xlated_prog_insns = ptr_to_u64(xlated_insns);
@@ -350,15 +331,20 @@ static void test_bpf_obj_id(void)
350 prog_infos[i].type != BPF_PROG_TYPE_SOCKET_FILTER || 331 prog_infos[i].type != BPF_PROG_TYPE_SOCKET_FILTER ||
351 info_len != sizeof(struct bpf_prog_info) || 332 info_len != sizeof(struct bpf_prog_info) ||
352 (jit_enabled && !prog_infos[i].jited_prog_len) || 333 (jit_enabled && !prog_infos[i].jited_prog_len) ||
353 !prog_infos[i].xlated_prog_len, 334 (jit_enabled &&
335 !memcmp(jited_insns, zeros, sizeof(zeros))) ||
336 !prog_infos[i].xlated_prog_len ||
337 !memcmp(xlated_insns, zeros, sizeof(zeros)),
354 "get-prog-info(fd)", 338 "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", 339 "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\n",
356 err, errno, i, 340 err, errno, i,
357 prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER, 341 prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER,
358 info_len, sizeof(struct bpf_prog_info), 342 info_len, sizeof(struct bpf_prog_info),
359 jit_enabled, 343 jit_enabled,
360 prog_infos[i].jited_prog_len, 344 prog_infos[i].jited_prog_len,
361 prog_infos[i].xlated_prog_len)) 345 prog_infos[i].xlated_prog_len,
346 !!memcmp(jited_insns, zeros, sizeof(zeros)),
347 !!memcmp(xlated_insns, zeros, sizeof(zeros))))
362 goto done; 348 goto done;
363 349
364 map_fds[i] = bpf_find_map(__func__, objs[i], "test_map_id"); 350 map_fds[i] = bpf_find_map(__func__, objs[i], "test_map_id");
@@ -369,6 +355,7 @@ static void test_bpf_obj_id(void)
369 355
370 /* Check getting map info */ 356 /* Check getting map info */
371 info_len = sizeof(struct bpf_map_info) * 2; 357 info_len = sizeof(struct bpf_map_info) * 2;
358 bzero(&map_infos[i], info_len);
372 err = bpf_obj_get_info_by_fd(map_fds[i], &map_infos[i], 359 err = bpf_obj_get_info_by_fd(map_fds[i], &map_infos[i],
373 &info_len); 360 &info_len);
374 if (CHECK(err || 361 if (CHECK(err ||
@@ -394,7 +381,7 @@ static void test_bpf_obj_id(void)
394 nr_id_found = 0; 381 nr_id_found = 0;
395 next_id = 0; 382 next_id = 0;
396 while (!bpf_prog_get_next_id(next_id, &next_id)) { 383 while (!bpf_prog_get_next_id(next_id, &next_id)) {
397 struct bpf_prog_info prog_info; 384 struct bpf_prog_info prog_info = {};
398 int prog_fd; 385 int prog_fd;
399 386
400 info_len = sizeof(prog_info); 387 info_len = sizeof(prog_info);
@@ -418,6 +405,8 @@ static void test_bpf_obj_id(void)
418 nr_id_found++; 405 nr_id_found++;
419 406
420 err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len); 407 err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len);
408 prog_infos[i].jited_prog_insns = 0;
409 prog_infos[i].xlated_prog_insns = 0;
421 CHECK(err || info_len != sizeof(struct bpf_prog_info) || 410 CHECK(err || info_len != sizeof(struct bpf_prog_info) ||
422 memcmp(&prog_info, &prog_infos[i], info_len), 411 memcmp(&prog_info, &prog_infos[i], info_len),
423 "get-prog-info(next_id->fd)", 412 "get-prog-info(next_id->fd)",
@@ -436,7 +425,7 @@ static void test_bpf_obj_id(void)
436 nr_id_found = 0; 425 nr_id_found = 0;
437 next_id = 0; 426 next_id = 0;
438 while (!bpf_map_get_next_id(next_id, &next_id)) { 427 while (!bpf_map_get_next_id(next_id, &next_id)) {
439 struct bpf_map_info map_info; 428 struct bpf_map_info map_info = {};
440 int map_fd; 429 int map_fd;
441 430
442 info_len = sizeof(map_info); 431 info_len = sizeof(map_info);
@@ -492,8 +481,10 @@ static void test_pkt_md_access(void)
492 int err, prog_fd; 481 int err, prog_fd;
493 482
494 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd); 483 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
495 if (err) 484 if (err) {
485 error_cnt++;
496 return; 486 return;
487 }
497 488
498 err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4), 489 err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4),
499 NULL, NULL, &retval, &duration); 490 NULL, NULL, &retval, &duration);
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 404aec520812..26f3250bdcd2 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,256 @@ 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 "check skb->mark is writeable by SK_SKB",
1134 .insns = {
1135 BPF_MOV64_IMM(BPF_REG_0, 0),
1136 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1137 offsetof(struct __sk_buff, mark)),
1138 BPF_EXIT_INSN(),
1139 },
1140 .result = ACCEPT,
1141 .prog_type = BPF_PROG_TYPE_SK_SKB,
1142 },
1143 {
1144 "check skb->tc_index is 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, tc_index)),
1149 BPF_EXIT_INSN(),
1150 },
1151 .result = ACCEPT,
1152 .prog_type = BPF_PROG_TYPE_SK_SKB,
1153 },
1154 {
1155 "check skb->priority is writeable by SK_SKB",
1156 .insns = {
1157 BPF_MOV64_IMM(BPF_REG_0, 0),
1158 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1159 offsetof(struct __sk_buff, priority)),
1160 BPF_EXIT_INSN(),
1161 },
1162 .result = ACCEPT,
1163 .prog_type = BPF_PROG_TYPE_SK_SKB,
1164 },
1165 {
1166 "direct packet read for SK_SKB",
1167 .insns = {
1168 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
1169 offsetof(struct __sk_buff, data)),
1170 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
1171 offsetof(struct __sk_buff, data_end)),
1172 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
1173 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
1174 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
1175 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
1176 BPF_MOV64_IMM(BPF_REG_0, 0),
1177 BPF_EXIT_INSN(),
1178 },
1179 .result = ACCEPT,
1180 .prog_type = BPF_PROG_TYPE_SK_SKB,
1181 },
1182 {
1183 "direct packet write for SK_SKB",
1184 .insns = {
1185 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
1186 offsetof(struct __sk_buff, data)),
1187 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
1188 offsetof(struct __sk_buff, data_end)),
1189 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
1190 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
1191 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
1192 BPF_STX_MEM(BPF_B, BPF_REG_2, BPF_REG_2, 0),
1193 BPF_MOV64_IMM(BPF_REG_0, 0),
1194 BPF_EXIT_INSN(),
1195 },
1196 .result = ACCEPT,
1197 .prog_type = BPF_PROG_TYPE_SK_SKB,
1198 },
1199 {
1200 "overlapping checks for direct packet access SK_SKB",
1201 .insns = {
1202 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
1203 offsetof(struct __sk_buff, data)),
1204 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
1205 offsetof(struct __sk_buff, data_end)),
1206 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
1207 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
1208 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 4),
1209 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
1210 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6),
1211 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
1212 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_2, 6),
1213 BPF_MOV64_IMM(BPF_REG_0, 0),
1214 BPF_EXIT_INSN(),
1215 },
1216 .result = ACCEPT,
1217 .prog_type = BPF_PROG_TYPE_SK_SKB,
1218 },
1219 {
966 "check skb->mark is not writeable by sockets", 1220 "check skb->mark is not writeable by sockets",
967 .insns = { 1221 .insns = {
968 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 1222 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
@@ -1098,7 +1352,7 @@ static struct bpf_test tests[] = {
1098 "check skb->hash byte load permitted", 1352 "check skb->hash byte load permitted",
1099 .insns = { 1353 .insns = {
1100 BPF_MOV64_IMM(BPF_REG_0, 0), 1354 BPF_MOV64_IMM(BPF_REG_0, 0),
1101#ifdef __LITTLE_ENDIAN 1355#if __BYTE_ORDER == __LITTLE_ENDIAN
1102 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 1356 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
1103 offsetof(struct __sk_buff, hash)), 1357 offsetof(struct __sk_buff, hash)),
1104#else 1358#else
@@ -1135,7 +1389,7 @@ static struct bpf_test tests[] = {
1135 "check skb->hash byte load not permitted 3", 1389 "check skb->hash byte load not permitted 3",
1136 .insns = { 1390 .insns = {
1137 BPF_MOV64_IMM(BPF_REG_0, 0), 1391 BPF_MOV64_IMM(BPF_REG_0, 0),
1138#ifdef __LITTLE_ENDIAN 1392#if __BYTE_ORDER == __LITTLE_ENDIAN
1139 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 1393 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
1140 offsetof(struct __sk_buff, hash) + 3), 1394 offsetof(struct __sk_buff, hash) + 3),
1141#else 1395#else
@@ -1215,8 +1469,9 @@ static struct bpf_test tests[] = {
1215 offsetof(struct __sk_buff, cb[0]) + 1), 1469 offsetof(struct __sk_buff, cb[0]) + 1),
1216 BPF_EXIT_INSN(), 1470 BPF_EXIT_INSN(),
1217 }, 1471 },
1218 .errstr = "misaligned access", 1472 .errstr = "misaligned context access",
1219 .result = REJECT, 1473 .result = REJECT,
1474 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1220 }, 1475 },
1221 { 1476 {
1222 "check __sk_buff->hash, offset 0, half store not permitted", 1477 "check __sk_buff->hash, offset 0, half store not permitted",
@@ -1244,7 +1499,7 @@ static struct bpf_test tests[] = {
1244 "check skb->hash half load permitted", 1499 "check skb->hash half load permitted",
1245 .insns = { 1500 .insns = {
1246 BPF_MOV64_IMM(BPF_REG_0, 0), 1501 BPF_MOV64_IMM(BPF_REG_0, 0),
1247#ifdef __LITTLE_ENDIAN 1502#if __BYTE_ORDER == __LITTLE_ENDIAN
1248 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 1503 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1249 offsetof(struct __sk_buff, hash)), 1504 offsetof(struct __sk_buff, hash)),
1250#else 1505#else
@@ -1259,7 +1514,7 @@ static struct bpf_test tests[] = {
1259 "check skb->hash half load not permitted", 1514 "check skb->hash half load not permitted",
1260 .insns = { 1515 .insns = {
1261 BPF_MOV64_IMM(BPF_REG_0, 0), 1516 BPF_MOV64_IMM(BPF_REG_0, 0),
1262#ifdef __LITTLE_ENDIAN 1517#if __BYTE_ORDER == __LITTLE_ENDIAN
1263 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 1518 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1264 offsetof(struct __sk_buff, hash) + 2), 1519 offsetof(struct __sk_buff, hash) + 2),
1265#else 1520#else
@@ -1319,8 +1574,9 @@ static struct bpf_test tests[] = {
1319 offsetof(struct __sk_buff, cb[0]) + 2), 1574 offsetof(struct __sk_buff, cb[0]) + 2),
1320 BPF_EXIT_INSN(), 1575 BPF_EXIT_INSN(),
1321 }, 1576 },
1322 .errstr = "misaligned access", 1577 .errstr = "misaligned context access",
1323 .result = REJECT, 1578 .result = REJECT,
1579 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1324 }, 1580 },
1325 { 1581 {
1326 "check cb access: word, unaligned 2", 1582 "check cb access: word, unaligned 2",
@@ -1330,8 +1586,9 @@ static struct bpf_test tests[] = {
1330 offsetof(struct __sk_buff, cb[4]) + 1), 1586 offsetof(struct __sk_buff, cb[4]) + 1),
1331 BPF_EXIT_INSN(), 1587 BPF_EXIT_INSN(),
1332 }, 1588 },
1333 .errstr = "misaligned access", 1589 .errstr = "misaligned context access",
1334 .result = REJECT, 1590 .result = REJECT,
1591 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1335 }, 1592 },
1336 { 1593 {
1337 "check cb access: word, unaligned 3", 1594 "check cb access: word, unaligned 3",
@@ -1341,8 +1598,9 @@ static struct bpf_test tests[] = {
1341 offsetof(struct __sk_buff, cb[4]) + 2), 1598 offsetof(struct __sk_buff, cb[4]) + 2),
1342 BPF_EXIT_INSN(), 1599 BPF_EXIT_INSN(),
1343 }, 1600 },
1344 .errstr = "misaligned access", 1601 .errstr = "misaligned context access",
1345 .result = REJECT, 1602 .result = REJECT,
1603 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1346 }, 1604 },
1347 { 1605 {
1348 "check cb access: word, unaligned 4", 1606 "check cb access: word, unaligned 4",
@@ -1352,8 +1610,9 @@ static struct bpf_test tests[] = {
1352 offsetof(struct __sk_buff, cb[4]) + 3), 1610 offsetof(struct __sk_buff, cb[4]) + 3),
1353 BPF_EXIT_INSN(), 1611 BPF_EXIT_INSN(),
1354 }, 1612 },
1355 .errstr = "misaligned access", 1613 .errstr = "misaligned context access",
1356 .result = REJECT, 1614 .result = REJECT,
1615 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1357 }, 1616 },
1358 { 1617 {
1359 "check cb access: double", 1618 "check cb access: double",
@@ -1379,8 +1638,9 @@ static struct bpf_test tests[] = {
1379 offsetof(struct __sk_buff, cb[1])), 1638 offsetof(struct __sk_buff, cb[1])),
1380 BPF_EXIT_INSN(), 1639 BPF_EXIT_INSN(),
1381 }, 1640 },
1382 .errstr = "misaligned access", 1641 .errstr = "misaligned context access",
1383 .result = REJECT, 1642 .result = REJECT,
1643 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1384 }, 1644 },
1385 { 1645 {
1386 "check cb access: double, unaligned 2", 1646 "check cb access: double, unaligned 2",
@@ -1390,8 +1650,9 @@ static struct bpf_test tests[] = {
1390 offsetof(struct __sk_buff, cb[3])), 1650 offsetof(struct __sk_buff, cb[3])),
1391 BPF_EXIT_INSN(), 1651 BPF_EXIT_INSN(),
1392 }, 1652 },
1393 .errstr = "misaligned access", 1653 .errstr = "misaligned context access",
1394 .result = REJECT, 1654 .result = REJECT,
1655 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1395 }, 1656 },
1396 { 1657 {
1397 "check cb access: double, oob 1", 1658 "check cb access: double, oob 1",
@@ -1523,7 +1784,8 @@ static struct bpf_test tests[] = {
1523 BPF_EXIT_INSN(), 1784 BPF_EXIT_INSN(),
1524 }, 1785 },
1525 .result = REJECT, 1786 .result = REJECT,
1526 .errstr = "misaligned access off -6 size 8", 1787 .errstr = "misaligned stack access off (0x0; 0x0)+-8+2 size 8",
1788 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1527 }, 1789 },
1528 { 1790 {
1529 "PTR_TO_STACK store/load - bad alignment on reg", 1791 "PTR_TO_STACK store/load - bad alignment on reg",
@@ -1535,7 +1797,8 @@ static struct bpf_test tests[] = {
1535 BPF_EXIT_INSN(), 1797 BPF_EXIT_INSN(),
1536 }, 1798 },
1537 .result = REJECT, 1799 .result = REJECT,
1538 .errstr = "misaligned access off -2 size 8", 1800 .errstr = "misaligned stack access off (0x0; 0x0)+-10+8 size 8",
1801 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
1539 }, 1802 },
1540 { 1803 {
1541 "PTR_TO_STACK store/load - out of bounds low", 1804 "PTR_TO_STACK store/load - out of bounds low",
@@ -1579,8 +1842,6 @@ static struct bpf_test tests[] = {
1579 BPF_EXIT_INSN(), 1842 BPF_EXIT_INSN(),
1580 }, 1843 },
1581 .result = ACCEPT, 1844 .result = ACCEPT,
1582 .result_unpriv = REJECT,
1583 .errstr_unpriv = "R1 pointer arithmetic",
1584 }, 1845 },
1585 { 1846 {
1586 "unpriv: add pointer to pointer", 1847 "unpriv: add pointer to pointer",
@@ -1591,7 +1852,7 @@ static struct bpf_test tests[] = {
1591 }, 1852 },
1592 .result = ACCEPT, 1853 .result = ACCEPT,
1593 .result_unpriv = REJECT, 1854 .result_unpriv = REJECT,
1594 .errstr_unpriv = "R1 pointer arithmetic", 1855 .errstr_unpriv = "R1 pointer += pointer",
1595 }, 1856 },
1596 { 1857 {
1597 "unpriv: neg pointer", 1858 "unpriv: neg pointer",
@@ -1932,10 +2193,7 @@ static struct bpf_test tests[] = {
1932 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8), 2193 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8),
1933 BPF_EXIT_INSN(), 2194 BPF_EXIT_INSN(),
1934 }, 2195 },
1935 .errstr_unpriv = "pointer arithmetic prohibited", 2196 .result = ACCEPT,
1936 .result_unpriv = REJECT,
1937 .errstr = "R1 invalid mem access",
1938 .result = REJECT,
1939 }, 2197 },
1940 { 2198 {
1941 "unpriv: cmp of stack pointer", 2199 "unpriv: cmp of stack pointer",
@@ -1999,7 +2257,7 @@ static struct bpf_test tests[] = {
1999 BPF_EXIT_INSN(), 2257 BPF_EXIT_INSN(),
2000 }, 2258 },
2001 .result = REJECT, 2259 .result = REJECT,
2002 .errstr = "invalid stack type R3", 2260 .errstr = "R4 min value is negative",
2003 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2261 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2004 }, 2262 },
2005 { 2263 {
@@ -2016,7 +2274,7 @@ static struct bpf_test tests[] = {
2016 BPF_EXIT_INSN(), 2274 BPF_EXIT_INSN(),
2017 }, 2275 },
2018 .result = REJECT, 2276 .result = REJECT,
2019 .errstr = "invalid stack type R3", 2277 .errstr = "R4 min value is negative",
2020 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2278 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2021 }, 2279 },
2022 { 2280 {
@@ -2218,7 +2476,7 @@ static struct bpf_test tests[] = {
2218 BPF_EXIT_INSN(), 2476 BPF_EXIT_INSN(),
2219 }, 2477 },
2220 .result = REJECT, 2478 .result = REJECT,
2221 .errstr = "invalid stack type R3 off=-1 access_size=-1", 2479 .errstr = "R4 min value is negative",
2222 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2480 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2223 }, 2481 },
2224 { 2482 {
@@ -2235,7 +2493,7 @@ static struct bpf_test tests[] = {
2235 BPF_EXIT_INSN(), 2493 BPF_EXIT_INSN(),
2236 }, 2494 },
2237 .result = REJECT, 2495 .result = REJECT,
2238 .errstr = "invalid stack type R3 off=-1 access_size=2147483647", 2496 .errstr = "R4 unbounded memory access, use 'var &= const' or 'if (var < const)'",
2239 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2497 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2240 }, 2498 },
2241 { 2499 {
@@ -2252,7 +2510,7 @@ static struct bpf_test tests[] = {
2252 BPF_EXIT_INSN(), 2510 BPF_EXIT_INSN(),
2253 }, 2511 },
2254 .result = REJECT, 2512 .result = REJECT,
2255 .errstr = "invalid stack type R3 off=-512 access_size=2147483647", 2513 .errstr = "R4 unbounded memory access, use 'var &= const' or 'if (var < const)'",
2256 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2514 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2257 }, 2515 },
2258 { 2516 {
@@ -2323,8 +2581,8 @@ static struct bpf_test tests[] = {
2323 offsetof(struct __sk_buff, data)), 2581 offsetof(struct __sk_buff, data)),
2324 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_4), 2582 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_4),
2325 BPF_MOV64_REG(BPF_REG_2, BPF_REG_1), 2583 BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
2326 BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 48), 2584 BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 49),
2327 BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 48), 2585 BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 49),
2328 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_2), 2586 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_2),
2329 BPF_MOV64_REG(BPF_REG_2, BPF_REG_3), 2587 BPF_MOV64_REG(BPF_REG_2, BPF_REG_3),
2330 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 8), 2588 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 8),
@@ -2652,7 +2910,7 @@ static struct bpf_test tests[] = {
2652 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1), 2910 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
2653 BPF_JMP_A(-6), 2911 BPF_JMP_A(-6),
2654 }, 2912 },
2655 .errstr = "misaligned packet access off 2+15+-4 size 4", 2913 .errstr = "misaligned packet access off 2+(0x0; 0x0)+15+-4 size 4",
2656 .result = REJECT, 2914 .result = REJECT,
2657 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2915 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2658 .flags = F_LOAD_WITH_STRICT_ALIGNMENT, 2916 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
@@ -2703,11 +2961,11 @@ static struct bpf_test tests[] = {
2703 BPF_MOV64_IMM(BPF_REG_0, 0xffffffff), 2961 BPF_MOV64_IMM(BPF_REG_0, 0xffffffff),
2704 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8), 2962 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), 2963 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
2706 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffff), 2964 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0x7fff),
2707 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0), 2965 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
2708 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2), 2966 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2),
2709 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4), 2967 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4),
2710 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0xffff - 1), 2968 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0x7fff - 1),
2711 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1), 2969 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), 2970 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
2713 BPF_MOV64_IMM(BPF_REG_0, 0), 2971 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -2729,10 +2987,10 @@ static struct bpf_test tests[] = {
2729 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff), 2987 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff),
2730 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_4, -8), 2988 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), 2989 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8),
2732 BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 0xffff), 2990 BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 0x7fff),
2733 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2), 2991 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2),
2734 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4), 2992 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4),
2735 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0xffff - 1), 2993 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0x7fff - 1),
2736 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1), 2994 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), 2995 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
2738 BPF_MOV64_IMM(BPF_REG_0, 0), 2996 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -2758,7 +3016,7 @@ static struct bpf_test tests[] = {
2758 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff), 3016 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff),
2759 BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_4, -8), 3017 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), 3018 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8),
2761 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 48), 3019 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 49),
2762 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2), 3020 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2),
2763 BPF_MOV64_REG(BPF_REG_0, BPF_REG_4), 3021 BPF_MOV64_REG(BPF_REG_0, BPF_REG_4),
2764 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2), 3022 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2),
@@ -2795,7 +3053,7 @@ static struct bpf_test tests[] = {
2795 }, 3053 },
2796 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3054 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2797 .result = REJECT, 3055 .result = REJECT,
2798 .errstr = "cannot add integer value with 47 upper zero bits to ptr_to_packet", 3056 .errstr = "invalid access to packet, off=0 size=8, R5(id=1,off=0,r=0)",
2799 }, 3057 },
2800 { 3058 {
2801 "direct packet access: test24 (x += pkt_ptr, 5)", 3059 "direct packet access: test24 (x += pkt_ptr, 5)",
@@ -2813,7 +3071,7 @@ static struct bpf_test tests[] = {
2813 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_4), 3071 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_4),
2814 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2), 3072 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
2815 BPF_MOV64_REG(BPF_REG_5, BPF_REG_0), 3073 BPF_MOV64_REG(BPF_REG_5, BPF_REG_0),
2816 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0xffff - 1), 3074 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x7fff - 1),
2817 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1), 3075 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), 3076 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_0, 0),
2819 BPF_MOV64_IMM(BPF_REG_0, 0), 3077 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -2823,6 +3081,79 @@ static struct bpf_test tests[] = {
2823 .result = ACCEPT, 3081 .result = ACCEPT,
2824 }, 3082 },
2825 { 3083 {
3084 "direct packet access: test25 (marking on <, good access)",
3085 .insns = {
3086 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
3087 offsetof(struct __sk_buff, data)),
3088 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
3089 offsetof(struct __sk_buff, data_end)),
3090 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3091 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
3092 BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_3, 2),
3093 BPF_MOV64_IMM(BPF_REG_0, 0),
3094 BPF_EXIT_INSN(),
3095 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
3096 BPF_JMP_IMM(BPF_JA, 0, 0, -4),
3097 },
3098 .result = ACCEPT,
3099 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3100 },
3101 {
3102 "direct packet access: test26 (marking on <, bad access)",
3103 .insns = {
3104 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
3105 offsetof(struct __sk_buff, data)),
3106 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
3107 offsetof(struct __sk_buff, data_end)),
3108 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3109 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
3110 BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_3, 3),
3111 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
3112 BPF_MOV64_IMM(BPF_REG_0, 0),
3113 BPF_EXIT_INSN(),
3114 BPF_JMP_IMM(BPF_JA, 0, 0, -3),
3115 },
3116 .result = REJECT,
3117 .errstr = "invalid access to packet",
3118 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3119 },
3120 {
3121 "direct packet access: test27 (marking on <=, good access)",
3122 .insns = {
3123 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
3124 offsetof(struct __sk_buff, data)),
3125 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
3126 offsetof(struct __sk_buff, data_end)),
3127 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3128 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
3129 BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_0, 1),
3130 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
3131 BPF_MOV64_IMM(BPF_REG_0, 1),
3132 BPF_EXIT_INSN(),
3133 },
3134 .result = ACCEPT,
3135 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3136 },
3137 {
3138 "direct packet access: test28 (marking on <=, bad access)",
3139 .insns = {
3140 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
3141 offsetof(struct __sk_buff, data)),
3142 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
3143 offsetof(struct __sk_buff, data_end)),
3144 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3145 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
3146 BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_0, 2),
3147 BPF_MOV64_IMM(BPF_REG_0, 1),
3148 BPF_EXIT_INSN(),
3149 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
3150 BPF_JMP_IMM(BPF_JA, 0, 0, -4),
3151 },
3152 .result = REJECT,
3153 .errstr = "invalid access to packet",
3154 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3155 },
3156 {
2826 "helper access to packet: test1, valid packet_ptr range", 3157 "helper access to packet: test1, valid packet_ptr range",
2827 .insns = { 3158 .insns = {
2828 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 3159 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
@@ -3112,7 +3443,7 @@ static struct bpf_test tests[] = {
3112 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3443 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3113 }, 3444 },
3114 { 3445 {
3115 "helper access to packet: test14, cls helper fail sub", 3446 "helper access to packet: test14, cls helper ok sub",
3116 .insns = { 3447 .insns = {
3117 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3448 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3118 offsetof(struct __sk_buff, data)), 3449 offsetof(struct __sk_buff, data)),
@@ -3132,12 +3463,36 @@ static struct bpf_test tests[] = {
3132 BPF_MOV64_IMM(BPF_REG_0, 0), 3463 BPF_MOV64_IMM(BPF_REG_0, 0),
3133 BPF_EXIT_INSN(), 3464 BPF_EXIT_INSN(),
3134 }, 3465 },
3466 .result = ACCEPT,
3467 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3468 },
3469 {
3470 "helper access to packet: test15, cls helper fail sub",
3471 .insns = {
3472 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3473 offsetof(struct __sk_buff, data)),
3474 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
3475 offsetof(struct __sk_buff, data_end)),
3476 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
3477 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
3478 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7),
3479 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_7, 6),
3480 BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 12),
3481 BPF_MOV64_IMM(BPF_REG_2, 4),
3482 BPF_MOV64_IMM(BPF_REG_3, 0),
3483 BPF_MOV64_IMM(BPF_REG_4, 0),
3484 BPF_MOV64_IMM(BPF_REG_5, 0),
3485 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
3486 BPF_FUNC_csum_diff),
3487 BPF_MOV64_IMM(BPF_REG_0, 0),
3488 BPF_EXIT_INSN(),
3489 },
3135 .result = REJECT, 3490 .result = REJECT,
3136 .errstr = "type=inv expected=fp", 3491 .errstr = "invalid access to packet",
3137 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3492 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3138 }, 3493 },
3139 { 3494 {
3140 "helper access to packet: test15, cls helper fail range 1", 3495 "helper access to packet: test16, cls helper fail range 1",
3141 .insns = { 3496 .insns = {
3142 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3497 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3143 offsetof(struct __sk_buff, data)), 3498 offsetof(struct __sk_buff, data)),
@@ -3162,7 +3517,7 @@ static struct bpf_test tests[] = {
3162 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3517 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3163 }, 3518 },
3164 { 3519 {
3165 "helper access to packet: test16, cls helper fail range 2", 3520 "helper access to packet: test17, cls helper fail range 2",
3166 .insns = { 3521 .insns = {
3167 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3522 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3168 offsetof(struct __sk_buff, data)), 3523 offsetof(struct __sk_buff, data)),
@@ -3183,11 +3538,11 @@ static struct bpf_test tests[] = {
3183 BPF_EXIT_INSN(), 3538 BPF_EXIT_INSN(),
3184 }, 3539 },
3185 .result = REJECT, 3540 .result = REJECT,
3186 .errstr = "invalid access to packet", 3541 .errstr = "R2 min value is negative",
3187 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3542 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3188 }, 3543 },
3189 { 3544 {
3190 "helper access to packet: test17, cls helper fail range 3", 3545 "helper access to packet: test18, cls helper fail range 3",
3191 .insns = { 3546 .insns = {
3192 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3547 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3193 offsetof(struct __sk_buff, data)), 3548 offsetof(struct __sk_buff, data)),
@@ -3208,11 +3563,11 @@ static struct bpf_test tests[] = {
3208 BPF_EXIT_INSN(), 3563 BPF_EXIT_INSN(),
3209 }, 3564 },
3210 .result = REJECT, 3565 .result = REJECT,
3211 .errstr = "invalid access to packet", 3566 .errstr = "R2 min value is negative",
3212 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3567 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3213 }, 3568 },
3214 { 3569 {
3215 "helper access to packet: test18, cls helper fail range zero", 3570 "helper access to packet: test19, cls helper fail range zero",
3216 .insns = { 3571 .insns = {
3217 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3572 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3218 offsetof(struct __sk_buff, data)), 3573 offsetof(struct __sk_buff, data)),
@@ -3237,7 +3592,7 @@ static struct bpf_test tests[] = {
3237 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3592 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3238 }, 3593 },
3239 { 3594 {
3240 "helper access to packet: test19, pkt end as input", 3595 "helper access to packet: test20, pkt end as input",
3241 .insns = { 3596 .insns = {
3242 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3597 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3243 offsetof(struct __sk_buff, data)), 3598 offsetof(struct __sk_buff, data)),
@@ -3262,7 +3617,7 @@ static struct bpf_test tests[] = {
3262 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 3617 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
3263 }, 3618 },
3264 { 3619 {
3265 "helper access to packet: test20, wrong reg", 3620 "helper access to packet: test21, wrong reg",
3266 .insns = { 3621 .insns = {
3267 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 3622 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
3268 offsetof(struct __sk_buff, data)), 3623 offsetof(struct __sk_buff, data)),
@@ -3322,7 +3677,7 @@ static struct bpf_test tests[] = {
3322 BPF_EXIT_INSN(), 3677 BPF_EXIT_INSN(),
3323 }, 3678 },
3324 .fixup_map2 = { 3 }, 3679 .fixup_map2 = { 3 },
3325 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3680 .errstr_unpriv = "R0 leaks addr",
3326 .result_unpriv = REJECT, 3681 .result_unpriv = REJECT,
3327 .result = ACCEPT, 3682 .result = ACCEPT,
3328 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3683 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3346,7 +3701,7 @@ static struct bpf_test tests[] = {
3346 BPF_EXIT_INSN(), 3701 BPF_EXIT_INSN(),
3347 }, 3702 },
3348 .fixup_map2 = { 3 }, 3703 .fixup_map2 = { 3 },
3349 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3704 .errstr_unpriv = "R0 leaks addr",
3350 .result_unpriv = REJECT, 3705 .result_unpriv = REJECT,
3351 .result = ACCEPT, 3706 .result = ACCEPT,
3352 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3707 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3374,7 +3729,7 @@ static struct bpf_test tests[] = {
3374 BPF_EXIT_INSN(), 3729 BPF_EXIT_INSN(),
3375 }, 3730 },
3376 .fixup_map2 = { 3 }, 3731 .fixup_map2 = { 3 },
3377 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3732 .errstr_unpriv = "R0 leaks addr",
3378 .result_unpriv = REJECT, 3733 .result_unpriv = REJECT,
3379 .result = ACCEPT, 3734 .result = ACCEPT,
3380 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3735 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3415,9 +3770,7 @@ static struct bpf_test tests[] = {
3415 BPF_EXIT_INSN(), 3770 BPF_EXIT_INSN(),
3416 }, 3771 },
3417 .fixup_map2 = { 3 }, 3772 .fixup_map2 = { 3 },
3418 .errstr_unpriv = "R0 pointer arithmetic prohibited",
3419 .errstr = "R0 min value is outside of the array range", 3773 .errstr = "R0 min value is outside of the array range",
3420 .result_unpriv = REJECT,
3421 .result = REJECT, 3774 .result = REJECT,
3422 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3775 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3423 }, 3776 },
@@ -3439,9 +3792,7 @@ static struct bpf_test tests[] = {
3439 BPF_EXIT_INSN(), 3792 BPF_EXIT_INSN(),
3440 }, 3793 },
3441 .fixup_map2 = { 3 }, 3794 .fixup_map2 = { 3 },
3442 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3795 .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, 3796 .result = REJECT,
3446 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3797 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3447 }, 3798 },
@@ -3455,7 +3806,7 @@ static struct bpf_test tests[] = {
3455 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 3806 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
3456 BPF_FUNC_map_lookup_elem), 3807 BPF_FUNC_map_lookup_elem),
3457 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7), 3808 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
3458 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0), 3809 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
3459 BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES), 3810 BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES),
3460 BPF_JMP_REG(BPF_JSGT, BPF_REG_2, BPF_REG_1, 1), 3811 BPF_JMP_REG(BPF_JSGT, BPF_REG_2, BPF_REG_1, 1),
3461 BPF_MOV32_IMM(BPF_REG_1, 0), 3812 BPF_MOV32_IMM(BPF_REG_1, 0),
@@ -3466,8 +3817,8 @@ static struct bpf_test tests[] = {
3466 BPF_EXIT_INSN(), 3817 BPF_EXIT_INSN(),
3467 }, 3818 },
3468 .fixup_map2 = { 3 }, 3819 .fixup_map2 = { 3 },
3469 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3820 .errstr_unpriv = "R0 leaks addr",
3470 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", 3821 .errstr = "R0 unbounded memory access",
3471 .result_unpriv = REJECT, 3822 .result_unpriv = REJECT,
3472 .result = REJECT, 3823 .result = REJECT,
3473 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3824 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3493,7 +3844,7 @@ static struct bpf_test tests[] = {
3493 BPF_EXIT_INSN(), 3844 BPF_EXIT_INSN(),
3494 }, 3845 },
3495 .fixup_map2 = { 3 }, 3846 .fixup_map2 = { 3 },
3496 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3847 .errstr_unpriv = "R0 leaks addr",
3497 .errstr = "invalid access to map value, value_size=48 off=44 size=8", 3848 .errstr = "invalid access to map value, value_size=48 off=44 size=8",
3498 .result_unpriv = REJECT, 3849 .result_unpriv = REJECT,
3499 .result = REJECT, 3850 .result = REJECT,
@@ -3523,8 +3874,8 @@ static struct bpf_test tests[] = {
3523 BPF_EXIT_INSN(), 3874 BPF_EXIT_INSN(),
3524 }, 3875 },
3525 .fixup_map2 = { 3, 11 }, 3876 .fixup_map2 = { 3, 11 },
3526 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3877 .errstr_unpriv = "R0 pointer += pointer",
3527 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", 3878 .errstr = "R0 invalid mem access 'inv'",
3528 .result_unpriv = REJECT, 3879 .result_unpriv = REJECT,
3529 .result = REJECT, 3880 .result = REJECT,
3530 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3881 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -3666,34 +4017,6 @@ static struct bpf_test tests[] = {
3666 .prog_type = BPF_PROG_TYPE_SCHED_CLS 4017 .prog_type = BPF_PROG_TYPE_SCHED_CLS
3667 }, 4018 },
3668 { 4019 {
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", 4020 "invalid map access from else condition",
3698 .insns = { 4021 .insns = {
3699 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 4022 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
@@ -3711,9 +4034,9 @@ static struct bpf_test tests[] = {
3711 BPF_EXIT_INSN(), 4034 BPF_EXIT_INSN(),
3712 }, 4035 },
3713 .fixup_map2 = { 3 }, 4036 .fixup_map2 = { 3 },
3714 .errstr = "R0 unbounded memory access, make sure to bounds check any array access into a map", 4037 .errstr = "R0 unbounded memory access",
3715 .result = REJECT, 4038 .result = REJECT,
3716 .errstr_unpriv = "R0 pointer arithmetic prohibited", 4039 .errstr_unpriv = "R0 leaks addr",
3717 .result_unpriv = REJECT, 4040 .result_unpriv = REJECT,
3718 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 4041 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3719 }, 4042 },
@@ -4091,7 +4414,7 @@ static struct bpf_test tests[] = {
4091 BPF_EXIT_INSN(), 4414 BPF_EXIT_INSN(),
4092 }, 4415 },
4093 .fixup_map2 = { 3 }, 4416 .fixup_map2 = { 3 },
4094 .errstr = "invalid access to map value, value_size=48 off=0 size=-8", 4417 .errstr = "R2 min value is negative",
4095 .result = REJECT, 4418 .result = REJECT,
4096 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4419 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4097 }, 4420 },
@@ -4157,7 +4480,7 @@ static struct bpf_test tests[] = {
4157 BPF_EXIT_INSN(), 4480 BPF_EXIT_INSN(),
4158 }, 4481 },
4159 .fixup_map2 = { 3 }, 4482 .fixup_map2 = { 3 },
4160 .errstr = "R1 min value is outside of the array range", 4483 .errstr = "invalid access to map value, value_size=48 off=4 size=0",
4161 .result = REJECT, 4484 .result = REJECT,
4162 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4485 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4163 }, 4486 },
@@ -4203,7 +4526,7 @@ static struct bpf_test tests[] = {
4203 BPF_EXIT_INSN(), 4526 BPF_EXIT_INSN(),
4204 }, 4527 },
4205 .fixup_map2 = { 3 }, 4528 .fixup_map2 = { 3 },
4206 .errstr = "invalid access to map value, value_size=48 off=4 size=-8", 4529 .errstr = "R2 min value is negative",
4207 .result = REJECT, 4530 .result = REJECT,
4208 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4531 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4209 }, 4532 },
@@ -4225,7 +4548,7 @@ static struct bpf_test tests[] = {
4225 BPF_EXIT_INSN(), 4548 BPF_EXIT_INSN(),
4226 }, 4549 },
4227 .fixup_map2 = { 3 }, 4550 .fixup_map2 = { 3 },
4228 .errstr = "R1 min value is outside of the array range", 4551 .errstr = "R2 min value is negative",
4229 .result = REJECT, 4552 .result = REJECT,
4230 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4553 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4231 }, 4554 },
@@ -4341,7 +4664,7 @@ static struct bpf_test tests[] = {
4341 BPF_EXIT_INSN(), 4664 BPF_EXIT_INSN(),
4342 }, 4665 },
4343 .fixup_map2 = { 3 }, 4666 .fixup_map2 = { 3 },
4344 .errstr = "invalid access to map value, value_size=48 off=4 size=-8", 4667 .errstr = "R2 min value is negative",
4345 .result = REJECT, 4668 .result = REJECT,
4346 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4669 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4347 }, 4670 },
@@ -4364,7 +4687,7 @@ static struct bpf_test tests[] = {
4364 BPF_EXIT_INSN(), 4687 BPF_EXIT_INSN(),
4365 }, 4688 },
4366 .fixup_map2 = { 3 }, 4689 .fixup_map2 = { 3 },
4367 .errstr = "R1 min value is outside of the array range", 4690 .errstr = "R2 min value is negative",
4368 .result = REJECT, 4691 .result = REJECT,
4369 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4692 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4370 }, 4693 },
@@ -4452,13 +4775,13 @@ static struct bpf_test tests[] = {
4452 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 4775 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4453 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0), 4776 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4454 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3), 4777 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4455 BPF_MOV64_IMM(BPF_REG_2, 0), 4778 BPF_MOV64_IMM(BPF_REG_2, 1),
4456 BPF_MOV64_IMM(BPF_REG_3, 0), 4779 BPF_MOV64_IMM(BPF_REG_3, 0),
4457 BPF_EMIT_CALL(BPF_FUNC_probe_read), 4780 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4458 BPF_EXIT_INSN(), 4781 BPF_EXIT_INSN(),
4459 }, 4782 },
4460 .fixup_map2 = { 3 }, 4783 .fixup_map2 = { 3 },
4461 .errstr = "R1 min value is negative, either use unsigned index or do a if (index >=0) check", 4784 .errstr = "R1 unbounded memory access",
4462 .result = REJECT, 4785 .result = REJECT,
4463 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4786 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4464 }, 4787 },
@@ -4489,6 +4812,246 @@ static struct bpf_test tests[] = {
4489 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 4812 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4490 }, 4813 },
4491 { 4814 {
4815 "helper access to map: bounds check using <, good access",
4816 .insns = {
4817 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4818 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4819 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4820 BPF_LD_MAP_FD(BPF_REG_1, 0),
4821 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4822 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4823 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4824 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4825 BPF_JMP_IMM(BPF_JLT, BPF_REG_3, 32, 2),
4826 BPF_MOV64_IMM(BPF_REG_0, 0),
4827 BPF_EXIT_INSN(),
4828 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4829 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4830 BPF_MOV64_IMM(BPF_REG_0, 0),
4831 BPF_EXIT_INSN(),
4832 },
4833 .fixup_map2 = { 3 },
4834 .result = ACCEPT,
4835 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4836 },
4837 {
4838 "helper access to map: bounds check using <, bad access",
4839 .insns = {
4840 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4841 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4842 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4843 BPF_LD_MAP_FD(BPF_REG_1, 0),
4844 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4845 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4846 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4847 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4848 BPF_JMP_IMM(BPF_JLT, BPF_REG_3, 32, 4),
4849 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4850 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4851 BPF_MOV64_IMM(BPF_REG_0, 0),
4852 BPF_EXIT_INSN(),
4853 BPF_MOV64_IMM(BPF_REG_0, 0),
4854 BPF_EXIT_INSN(),
4855 },
4856 .fixup_map2 = { 3 },
4857 .result = REJECT,
4858 .errstr = "R1 unbounded memory access",
4859 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4860 },
4861 {
4862 "helper access to map: bounds check using <=, good access",
4863 .insns = {
4864 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4865 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4866 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4867 BPF_LD_MAP_FD(BPF_REG_1, 0),
4868 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4869 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4870 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4871 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4872 BPF_JMP_IMM(BPF_JLE, BPF_REG_3, 32, 2),
4873 BPF_MOV64_IMM(BPF_REG_0, 0),
4874 BPF_EXIT_INSN(),
4875 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4876 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4877 BPF_MOV64_IMM(BPF_REG_0, 0),
4878 BPF_EXIT_INSN(),
4879 },
4880 .fixup_map2 = { 3 },
4881 .result = ACCEPT,
4882 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4883 },
4884 {
4885 "helper access to map: bounds check using <=, bad access",
4886 .insns = {
4887 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4888 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4889 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4890 BPF_LD_MAP_FD(BPF_REG_1, 0),
4891 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4892 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4893 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4894 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4895 BPF_JMP_IMM(BPF_JLE, BPF_REG_3, 32, 4),
4896 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4897 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4898 BPF_MOV64_IMM(BPF_REG_0, 0),
4899 BPF_EXIT_INSN(),
4900 BPF_MOV64_IMM(BPF_REG_0, 0),
4901 BPF_EXIT_INSN(),
4902 },
4903 .fixup_map2 = { 3 },
4904 .result = REJECT,
4905 .errstr = "R1 unbounded memory access",
4906 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4907 },
4908 {
4909 "helper access to map: bounds check using s<, good access",
4910 .insns = {
4911 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4912 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4913 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4914 BPF_LD_MAP_FD(BPF_REG_1, 0),
4915 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4916 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4917 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4918 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4919 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, 32, 2),
4920 BPF_MOV64_IMM(BPF_REG_0, 0),
4921 BPF_EXIT_INSN(),
4922 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, 0, -3),
4923 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4924 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4925 BPF_MOV64_IMM(BPF_REG_0, 0),
4926 BPF_EXIT_INSN(),
4927 },
4928 .fixup_map2 = { 3 },
4929 .result = ACCEPT,
4930 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4931 },
4932 {
4933 "helper access to map: bounds check using s<, good access 2",
4934 .insns = {
4935 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4936 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4937 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4938 BPF_LD_MAP_FD(BPF_REG_1, 0),
4939 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4940 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4941 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4942 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4943 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, 32, 2),
4944 BPF_MOV64_IMM(BPF_REG_0, 0),
4945 BPF_EXIT_INSN(),
4946 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, -3, -3),
4947 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4948 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4949 BPF_MOV64_IMM(BPF_REG_0, 0),
4950 BPF_EXIT_INSN(),
4951 },
4952 .fixup_map2 = { 3 },
4953 .result = ACCEPT,
4954 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4955 },
4956 {
4957 "helper access to map: bounds check using s<, bad access",
4958 .insns = {
4959 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4960 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4961 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4962 BPF_LD_MAP_FD(BPF_REG_1, 0),
4963 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4964 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4965 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4966 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, 0),
4967 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, 32, 2),
4968 BPF_MOV64_IMM(BPF_REG_0, 0),
4969 BPF_EXIT_INSN(),
4970 BPF_JMP_IMM(BPF_JSLT, BPF_REG_3, -3, -3),
4971 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4972 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4973 BPF_MOV64_IMM(BPF_REG_0, 0),
4974 BPF_EXIT_INSN(),
4975 },
4976 .fixup_map2 = { 3 },
4977 .result = REJECT,
4978 .errstr = "R1 min value is negative",
4979 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4980 },
4981 {
4982 "helper access to map: bounds check using s<=, good access",
4983 .insns = {
4984 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4985 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4986 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4987 BPF_LD_MAP_FD(BPF_REG_1, 0),
4988 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4989 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4990 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4991 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
4992 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, 32, 2),
4993 BPF_MOV64_IMM(BPF_REG_0, 0),
4994 BPF_EXIT_INSN(),
4995 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, 0, -3),
4996 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
4997 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
4998 BPF_MOV64_IMM(BPF_REG_0, 0),
4999 BPF_EXIT_INSN(),
5000 },
5001 .fixup_map2 = { 3 },
5002 .result = ACCEPT,
5003 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5004 },
5005 {
5006 "helper access to map: bounds check using s<=, good access 2",
5007 .insns = {
5008 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5009 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5010 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
5011 BPF_LD_MAP_FD(BPF_REG_1, 0),
5012 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
5013 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
5014 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
5015 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
5016 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, 32, 2),
5017 BPF_MOV64_IMM(BPF_REG_0, 0),
5018 BPF_EXIT_INSN(),
5019 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, -3, -3),
5020 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
5021 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
5022 BPF_MOV64_IMM(BPF_REG_0, 0),
5023 BPF_EXIT_INSN(),
5024 },
5025 .fixup_map2 = { 3 },
5026 .result = ACCEPT,
5027 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5028 },
5029 {
5030 "helper access to map: bounds check using s<=, bad access",
5031 .insns = {
5032 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
5033 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
5034 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
5035 BPF_LD_MAP_FD(BPF_REG_1, 0),
5036 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
5037 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
5038 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
5039 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, 0),
5040 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, 32, 2),
5041 BPF_MOV64_IMM(BPF_REG_0, 0),
5042 BPF_EXIT_INSN(),
5043 BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, -3, -3),
5044 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
5045 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 0),
5046 BPF_MOV64_IMM(BPF_REG_0, 0),
5047 BPF_EXIT_INSN(),
5048 },
5049 .fixup_map2 = { 3 },
5050 .result = REJECT,
5051 .errstr = "R1 min value is negative",
5052 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5053 },
5054 {
4492 "map element value is preserved across register spilling", 5055 "map element value is preserved across register spilling",
4493 .insns = { 5056 .insns = {
4494 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 5057 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -4578,7 +5141,7 @@ static struct bpf_test tests[] = {
4578 BPF_EXIT_INSN(), 5141 BPF_EXIT_INSN(),
4579 }, 5142 },
4580 .fixup_map2 = { 3 }, 5143 .fixup_map2 = { 3 },
4581 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5144 .errstr_unpriv = "R0 leaks addr",
4582 .result = ACCEPT, 5145 .result = ACCEPT,
4583 .result_unpriv = REJECT, 5146 .result_unpriv = REJECT,
4584 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5147 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -4606,7 +5169,7 @@ static struct bpf_test tests[] = {
4606 BPF_EXIT_INSN(), 5169 BPF_EXIT_INSN(),
4607 }, 5170 },
4608 .fixup_map2 = { 3 }, 5171 .fixup_map2 = { 3 },
4609 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5172 .errstr_unpriv = "R0 leaks addr",
4610 .result = ACCEPT, 5173 .result = ACCEPT,
4611 .result_unpriv = REJECT, 5174 .result_unpriv = REJECT,
4612 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5175 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -4625,7 +5188,7 @@ static struct bpf_test tests[] = {
4625 BPF_EXIT_INSN(), 5188 BPF_EXIT_INSN(),
4626 }, 5189 },
4627 .fixup_map2 = { 3 }, 5190 .fixup_map2 = { 3 },
4628 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5191 .errstr_unpriv = "R0 bitwise operator &= on pointer",
4629 .errstr = "invalid mem access 'inv'", 5192 .errstr = "invalid mem access 'inv'",
4630 .result = REJECT, 5193 .result = REJECT,
4631 .result_unpriv = REJECT, 5194 .result_unpriv = REJECT,
@@ -4644,7 +5207,7 @@ static struct bpf_test tests[] = {
4644 BPF_EXIT_INSN(), 5207 BPF_EXIT_INSN(),
4645 }, 5208 },
4646 .fixup_map2 = { 3 }, 5209 .fixup_map2 = { 3 },
4647 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5210 .errstr_unpriv = "R0 32-bit pointer arithmetic prohibited",
4648 .errstr = "invalid mem access 'inv'", 5211 .errstr = "invalid mem access 'inv'",
4649 .result = REJECT, 5212 .result = REJECT,
4650 .result_unpriv = REJECT, 5213 .result_unpriv = REJECT,
@@ -4663,7 +5226,7 @@ static struct bpf_test tests[] = {
4663 BPF_EXIT_INSN(), 5226 BPF_EXIT_INSN(),
4664 }, 5227 },
4665 .fixup_map2 = { 3 }, 5228 .fixup_map2 = { 3 },
4666 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5229 .errstr_unpriv = "R0 pointer arithmetic with /= operator",
4667 .errstr = "invalid mem access 'inv'", 5230 .errstr = "invalid mem access 'inv'",
4668 .result = REJECT, 5231 .result = REJECT,
4669 .result_unpriv = REJECT, 5232 .result_unpriv = REJECT,
@@ -4706,10 +5269,8 @@ static struct bpf_test tests[] = {
4706 BPF_EXIT_INSN(), 5269 BPF_EXIT_INSN(),
4707 }, 5270 },
4708 .fixup_map2 = { 3 }, 5271 .fixup_map2 = { 3 },
4709 .errstr_unpriv = "R0 invalid mem access 'inv'",
4710 .errstr = "R0 invalid mem access 'inv'", 5272 .errstr = "R0 invalid mem access 'inv'",
4711 .result = REJECT, 5273 .result = REJECT,
4712 .result_unpriv = REJECT,
4713 }, 5274 },
4714 { 5275 {
4715 "map element value is preserved across register spilling", 5276 "map element value is preserved across register spilling",
@@ -4731,7 +5292,7 @@ static struct bpf_test tests[] = {
4731 BPF_EXIT_INSN(), 5292 BPF_EXIT_INSN(),
4732 }, 5293 },
4733 .fixup_map2 = { 3 }, 5294 .fixup_map2 = { 3 },
4734 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5295 .errstr_unpriv = "R0 leaks addr",
4735 .result = ACCEPT, 5296 .result = ACCEPT,
4736 .result_unpriv = REJECT, 5297 .result_unpriv = REJECT,
4737 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5298 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
@@ -4913,7 +5474,8 @@ static struct bpf_test tests[] = {
4913 BPF_MOV64_IMM(BPF_REG_0, 0), 5474 BPF_MOV64_IMM(BPF_REG_0, 0),
4914 BPF_EXIT_INSN(), 5475 BPF_EXIT_INSN(),
4915 }, 5476 },
4916 .errstr = "R2 unbounded memory access", 5477 /* because max wasn't checked, signed min is negative */
5478 .errstr = "R2 min value is negative, either use unsigned or 'var &= const'",
4917 .result = REJECT, 5479 .result = REJECT,
4918 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5480 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4919 }, 5481 },
@@ -4969,7 +5531,7 @@ static struct bpf_test tests[] = {
4969 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, 5531 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2,
4970 sizeof(struct test_val), 4), 5532 sizeof(struct test_val), 4),
4971 BPF_MOV64_IMM(BPF_REG_4, 0), 5533 BPF_MOV64_IMM(BPF_REG_4, 0),
4972 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2), 5534 BPF_JMP_REG(BPF_JSGE, BPF_REG_4, BPF_REG_2, 2),
4973 BPF_MOV64_IMM(BPF_REG_3, 0), 5535 BPF_MOV64_IMM(BPF_REG_3, 0),
4974 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5536 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4975 BPF_MOV64_IMM(BPF_REG_0, 0), 5537 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -4995,7 +5557,7 @@ static struct bpf_test tests[] = {
4995 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, 5557 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2,
4996 sizeof(struct test_val) + 1, 4), 5558 sizeof(struct test_val) + 1, 4),
4997 BPF_MOV64_IMM(BPF_REG_4, 0), 5559 BPF_MOV64_IMM(BPF_REG_4, 0),
4998 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2), 5560 BPF_JMP_REG(BPF_JSGE, BPF_REG_4, BPF_REG_2, 2),
4999 BPF_MOV64_IMM(BPF_REG_3, 0), 5561 BPF_MOV64_IMM(BPF_REG_3, 0),
5000 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5562 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5001 BPF_MOV64_IMM(BPF_REG_0, 0), 5563 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -5023,7 +5585,7 @@ static struct bpf_test tests[] = {
5023 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, 5585 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2,
5024 sizeof(struct test_val) - 20, 4), 5586 sizeof(struct test_val) - 20, 4),
5025 BPF_MOV64_IMM(BPF_REG_4, 0), 5587 BPF_MOV64_IMM(BPF_REG_4, 0),
5026 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2), 5588 BPF_JMP_REG(BPF_JSGE, BPF_REG_4, BPF_REG_2, 2),
5027 BPF_MOV64_IMM(BPF_REG_3, 0), 5589 BPF_MOV64_IMM(BPF_REG_3, 0),
5028 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5590 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5029 BPF_MOV64_IMM(BPF_REG_0, 0), 5591 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -5050,7 +5612,7 @@ static struct bpf_test tests[] = {
5050 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, 5612 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2,
5051 sizeof(struct test_val) - 19, 4), 5613 sizeof(struct test_val) - 19, 4),
5052 BPF_MOV64_IMM(BPF_REG_4, 0), 5614 BPF_MOV64_IMM(BPF_REG_4, 0),
5053 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2), 5615 BPF_JMP_REG(BPF_JSGE, BPF_REG_4, BPF_REG_2, 2),
5054 BPF_MOV64_IMM(BPF_REG_3, 0), 5616 BPF_MOV64_IMM(BPF_REG_3, 0),
5055 BPF_EMIT_CALL(BPF_FUNC_probe_read), 5617 BPF_EMIT_CALL(BPF_FUNC_probe_read),
5056 BPF_MOV64_IMM(BPF_REG_0, 0), 5618 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -5062,6 +5624,20 @@ static struct bpf_test tests[] = {
5062 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 5624 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
5063 }, 5625 },
5064 { 5626 {
5627 "helper access to variable memory: size = 0 allowed on NULL",
5628 .insns = {
5629 BPF_MOV64_IMM(BPF_REG_1, 0),
5630 BPF_MOV64_IMM(BPF_REG_2, 0),
5631 BPF_MOV64_IMM(BPF_REG_3, 0),
5632 BPF_MOV64_IMM(BPF_REG_4, 0),
5633 BPF_MOV64_IMM(BPF_REG_5, 0),
5634 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
5635 BPF_EXIT_INSN(),
5636 },
5637 .result = ACCEPT,
5638 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
5639 },
5640 {
5065 "helper access to variable memory: size > 0 not allowed on NULL", 5641 "helper access to variable memory: size > 0 not allowed on NULL",
5066 .insns = { 5642 .insns = {
5067 BPF_MOV64_IMM(BPF_REG_1, 0), 5643 BPF_MOV64_IMM(BPF_REG_1, 0),
@@ -5075,7 +5651,7 @@ static struct bpf_test tests[] = {
5075 BPF_EMIT_CALL(BPF_FUNC_csum_diff), 5651 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
5076 BPF_EXIT_INSN(), 5652 BPF_EXIT_INSN(),
5077 }, 5653 },
5078 .errstr = "R1 type=imm expected=fp", 5654 .errstr = "R1 type=inv expected=fp",
5079 .result = REJECT, 5655 .result = REJECT,
5080 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 5656 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
5081 }, 5657 },
@@ -5160,7 +5736,7 @@ static struct bpf_test tests[] = {
5160 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 5736 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
5161 BPF_FUNC_map_lookup_elem), 5737 BPF_FUNC_map_lookup_elem),
5162 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4), 5738 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
5163 BPF_MOV64_IMM(BPF_REG_1, 6), 5739 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
5164 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, -4), 5740 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, -4),
5165 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2), 5741 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
5166 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 5742 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
@@ -5169,10 +5745,8 @@ static struct bpf_test tests[] = {
5169 BPF_EXIT_INSN(), 5745 BPF_EXIT_INSN(),
5170 }, 5746 },
5171 .fixup_map2 = { 3 }, 5747 .fixup_map2 = { 3 },
5172 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5748 .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, 5749 .result = REJECT,
5175 .result_unpriv = REJECT,
5176 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5750 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
5177 }, 5751 },
5178 { 5752 {
@@ -5201,10 +5775,8 @@ static struct bpf_test tests[] = {
5201 BPF_EXIT_INSN(), 5775 BPF_EXIT_INSN(),
5202 }, 5776 },
5203 .fixup_map2 = { 3 }, 5777 .fixup_map2 = { 3 },
5204 .errstr_unpriv = "R0 pointer arithmetic prohibited", 5778 .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, 5779 .result = REJECT,
5207 .result_unpriv = REJECT,
5208 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 5780 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
5209 }, 5781 },
5210 { 5782 {
@@ -5251,7 +5823,7 @@ static struct bpf_test tests[] = {
5251 }, 5823 },
5252 .fixup_map_in_map = { 3 }, 5824 .fixup_map_in_map = { 3 },
5253 .errstr = "R1 type=inv expected=map_ptr", 5825 .errstr = "R1 type=inv expected=map_ptr",
5254 .errstr_unpriv = "R1 pointer arithmetic prohibited", 5826 .errstr_unpriv = "R1 pointer arithmetic on CONST_PTR_TO_MAP prohibited",
5255 .result = REJECT, 5827 .result = REJECT,
5256 }, 5828 },
5257 { 5829 {
@@ -5422,7 +5994,7 @@ static struct bpf_test tests[] = {
5422 "check bpf_perf_event_data->sample_period byte load permitted", 5994 "check bpf_perf_event_data->sample_period byte load permitted",
5423 .insns = { 5995 .insns = {
5424 BPF_MOV64_IMM(BPF_REG_0, 0), 5996 BPF_MOV64_IMM(BPF_REG_0, 0),
5425#ifdef __LITTLE_ENDIAN 5997#if __BYTE_ORDER == __LITTLE_ENDIAN
5426 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 5998 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
5427 offsetof(struct bpf_perf_event_data, sample_period)), 5999 offsetof(struct bpf_perf_event_data, sample_period)),
5428#else 6000#else
@@ -5438,7 +6010,7 @@ static struct bpf_test tests[] = {
5438 "check bpf_perf_event_data->sample_period half load permitted", 6010 "check bpf_perf_event_data->sample_period half load permitted",
5439 .insns = { 6011 .insns = {
5440 BPF_MOV64_IMM(BPF_REG_0, 0), 6012 BPF_MOV64_IMM(BPF_REG_0, 0),
5441#ifdef __LITTLE_ENDIAN 6013#if __BYTE_ORDER == __LITTLE_ENDIAN
5442 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 6014 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
5443 offsetof(struct bpf_perf_event_data, sample_period)), 6015 offsetof(struct bpf_perf_event_data, sample_period)),
5444#else 6016#else
@@ -5454,7 +6026,7 @@ static struct bpf_test tests[] = {
5454 "check bpf_perf_event_data->sample_period word load permitted", 6026 "check bpf_perf_event_data->sample_period word load permitted",
5455 .insns = { 6027 .insns = {
5456 BPF_MOV64_IMM(BPF_REG_0, 0), 6028 BPF_MOV64_IMM(BPF_REG_0, 0),
5457#ifdef __LITTLE_ENDIAN 6029#if __BYTE_ORDER == __LITTLE_ENDIAN
5458 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 6030 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
5459 offsetof(struct bpf_perf_event_data, sample_period)), 6031 offsetof(struct bpf_perf_event_data, sample_period)),
5460#else 6032#else
@@ -5481,7 +6053,7 @@ static struct bpf_test tests[] = {
5481 "check skb->data half load not permitted", 6053 "check skb->data half load not permitted",
5482 .insns = { 6054 .insns = {
5483 BPF_MOV64_IMM(BPF_REG_0, 0), 6055 BPF_MOV64_IMM(BPF_REG_0, 0),
5484#ifdef __LITTLE_ENDIAN 6056#if __BYTE_ORDER == __LITTLE_ENDIAN
5485 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 6057 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
5486 offsetof(struct __sk_buff, data)), 6058 offsetof(struct __sk_buff, data)),
5487#else 6059#else
@@ -5497,7 +6069,7 @@ static struct bpf_test tests[] = {
5497 "check skb->tc_classid half load not permitted for lwt prog", 6069 "check skb->tc_classid half load not permitted for lwt prog",
5498 .insns = { 6070 .insns = {
5499 BPF_MOV64_IMM(BPF_REG_0, 0), 6071 BPF_MOV64_IMM(BPF_REG_0, 0),
5500#ifdef __LITTLE_ENDIAN 6072#if __BYTE_ORDER == __LITTLE_ENDIAN
5501 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 6073 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
5502 offsetof(struct __sk_buff, tc_classid)), 6074 offsetof(struct __sk_buff, tc_classid)),
5503#else 6075#else
@@ -5510,6 +6082,569 @@ static struct bpf_test tests[] = {
5510 .errstr = "invalid bpf_context access", 6082 .errstr = "invalid bpf_context access",
5511 .prog_type = BPF_PROG_TYPE_LWT_IN, 6083 .prog_type = BPF_PROG_TYPE_LWT_IN,
5512 }, 6084 },
6085 {
6086 "bounds checks mixing signed and unsigned, positive bounds",
6087 .insns = {
6088 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6089 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6090 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6091 BPF_LD_MAP_FD(BPF_REG_1, 0),
6092 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6093 BPF_FUNC_map_lookup_elem),
6094 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
6095 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6096 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6097 BPF_MOV64_IMM(BPF_REG_2, 2),
6098 BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 3),
6099 BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 4, 2),
6100 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6101 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
6102 BPF_MOV64_IMM(BPF_REG_0, 0),
6103 BPF_EXIT_INSN(),
6104 },
6105 .fixup_map1 = { 3 },
6106 .errstr = "R0 min value is negative",
6107 .result = REJECT,
6108 },
6109 {
6110 "bounds checks mixing signed and unsigned",
6111 .insns = {
6112 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6113 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6114 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6115 BPF_LD_MAP_FD(BPF_REG_1, 0),
6116 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6117 BPF_FUNC_map_lookup_elem),
6118 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
6119 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6120 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6121 BPF_MOV64_IMM(BPF_REG_2, -1),
6122 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 3),
6123 BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 1, 2),
6124 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6125 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
6126 BPF_MOV64_IMM(BPF_REG_0, 0),
6127 BPF_EXIT_INSN(),
6128 },
6129 .fixup_map1 = { 3 },
6130 .errstr = "R0 min value is negative",
6131 .result = REJECT,
6132 },
6133 {
6134 "bounds checks mixing signed and unsigned, variant 2",
6135 .insns = {
6136 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6137 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6138 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6139 BPF_LD_MAP_FD(BPF_REG_1, 0),
6140 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6141 BPF_FUNC_map_lookup_elem),
6142 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
6143 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6144 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6145 BPF_MOV64_IMM(BPF_REG_2, -1),
6146 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 5),
6147 BPF_MOV64_IMM(BPF_REG_8, 0),
6148 BPF_ALU64_REG(BPF_ADD, BPF_REG_8, BPF_REG_1),
6149 BPF_JMP_IMM(BPF_JSGT, BPF_REG_8, 1, 2),
6150 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_8),
6151 BPF_ST_MEM(BPF_B, BPF_REG_8, 0, 0),
6152 BPF_MOV64_IMM(BPF_REG_0, 0),
6153 BPF_EXIT_INSN(),
6154 },
6155 .fixup_map1 = { 3 },
6156 .errstr = "R8 invalid mem access 'inv'",
6157 .result = REJECT,
6158 },
6159 {
6160 "bounds checks mixing signed and unsigned, variant 3",
6161 .insns = {
6162 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6163 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6164 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6165 BPF_LD_MAP_FD(BPF_REG_1, 0),
6166 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6167 BPF_FUNC_map_lookup_elem),
6168 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
6169 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6170 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6171 BPF_MOV64_IMM(BPF_REG_2, -1),
6172 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 4),
6173 BPF_MOV64_REG(BPF_REG_8, BPF_REG_1),
6174 BPF_JMP_IMM(BPF_JSGT, BPF_REG_8, 1, 2),
6175 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_8),
6176 BPF_ST_MEM(BPF_B, BPF_REG_8, 0, 0),
6177 BPF_MOV64_IMM(BPF_REG_0, 0),
6178 BPF_EXIT_INSN(),
6179 },
6180 .fixup_map1 = { 3 },
6181 .errstr = "R8 invalid mem access 'inv'",
6182 .result = REJECT,
6183 },
6184 {
6185 "bounds checks mixing signed and unsigned, variant 4",
6186 .insns = {
6187 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6188 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6189 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6190 BPF_LD_MAP_FD(BPF_REG_1, 0),
6191 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6192 BPF_FUNC_map_lookup_elem),
6193 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
6194 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6195 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6196 BPF_MOV64_IMM(BPF_REG_2, 1),
6197 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
6198 BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 1, 2),
6199 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6200 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
6201 BPF_MOV64_IMM(BPF_REG_0, 0),
6202 BPF_EXIT_INSN(),
6203 },
6204 .fixup_map1 = { 3 },
6205 .result = ACCEPT,
6206 },
6207 {
6208 "bounds checks mixing signed and unsigned, variant 5",
6209 .insns = {
6210 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6211 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6212 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6213 BPF_LD_MAP_FD(BPF_REG_1, 0),
6214 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6215 BPF_FUNC_map_lookup_elem),
6216 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
6217 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6218 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6219 BPF_MOV64_IMM(BPF_REG_2, -1),
6220 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 5),
6221 BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 1, 4),
6222 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 4),
6223 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
6224 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
6225 BPF_MOV64_IMM(BPF_REG_0, 0),
6226 BPF_EXIT_INSN(),
6227 },
6228 .fixup_map1 = { 3 },
6229 .errstr = "R0 min value is negative",
6230 .result = REJECT,
6231 },
6232 {
6233 "bounds checks mixing signed and unsigned, variant 6",
6234 .insns = {
6235 BPF_MOV64_IMM(BPF_REG_2, 0),
6236 BPF_MOV64_REG(BPF_REG_3, BPF_REG_10),
6237 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, -512),
6238 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6239 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -16),
6240 BPF_MOV64_IMM(BPF_REG_6, -1),
6241 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_6, 5),
6242 BPF_JMP_IMM(BPF_JSGT, BPF_REG_4, 1, 4),
6243 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 1),
6244 BPF_MOV64_IMM(BPF_REG_5, 0),
6245 BPF_ST_MEM(BPF_H, BPF_REG_10, -512, 0),
6246 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6247 BPF_FUNC_skb_load_bytes),
6248 BPF_MOV64_IMM(BPF_REG_0, 0),
6249 BPF_EXIT_INSN(),
6250 },
6251 .errstr = "R4 min value is negative, either use unsigned",
6252 .result = REJECT,
6253 },
6254 {
6255 "bounds checks mixing signed and unsigned, variant 7",
6256 .insns = {
6257 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6258 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6259 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6260 BPF_LD_MAP_FD(BPF_REG_1, 0),
6261 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6262 BPF_FUNC_map_lookup_elem),
6263 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
6264 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6265 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6266 BPF_MOV64_IMM(BPF_REG_2, 1024 * 1024 * 1024),
6267 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 3),
6268 BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 1, 2),
6269 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6270 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
6271 BPF_MOV64_IMM(BPF_REG_0, 0),
6272 BPF_EXIT_INSN(),
6273 },
6274 .fixup_map1 = { 3 },
6275 .result = ACCEPT,
6276 },
6277 {
6278 "bounds checks mixing signed and unsigned, variant 8",
6279 .insns = {
6280 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6281 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6282 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6283 BPF_LD_MAP_FD(BPF_REG_1, 0),
6284 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6285 BPF_FUNC_map_lookup_elem),
6286 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
6287 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6288 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6289 BPF_MOV64_IMM(BPF_REG_2, -1),
6290 BPF_JMP_REG(BPF_JGT, BPF_REG_2, BPF_REG_1, 2),
6291 BPF_MOV64_IMM(BPF_REG_0, 0),
6292 BPF_EXIT_INSN(),
6293 BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 1, 2),
6294 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6295 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
6296 BPF_MOV64_IMM(BPF_REG_0, 0),
6297 BPF_EXIT_INSN(),
6298 },
6299 .fixup_map1 = { 3 },
6300 .errstr = "R0 min value is negative",
6301 .result = REJECT,
6302 },
6303 {
6304 "bounds checks mixing signed and unsigned, variant 9",
6305 .insns = {
6306 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6307 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6308 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6309 BPF_LD_MAP_FD(BPF_REG_1, 0),
6310 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6311 BPF_FUNC_map_lookup_elem),
6312 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 10),
6313 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6314 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6315 BPF_LD_IMM64(BPF_REG_2, -9223372036854775808ULL),
6316 BPF_JMP_REG(BPF_JGT, BPF_REG_2, BPF_REG_1, 2),
6317 BPF_MOV64_IMM(BPF_REG_0, 0),
6318 BPF_EXIT_INSN(),
6319 BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 1, 2),
6320 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6321 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
6322 BPF_MOV64_IMM(BPF_REG_0, 0),
6323 BPF_EXIT_INSN(),
6324 },
6325 .fixup_map1 = { 3 },
6326 .result = ACCEPT,
6327 },
6328 {
6329 "bounds checks mixing signed and unsigned, variant 10",
6330 .insns = {
6331 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6332 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6333 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6334 BPF_LD_MAP_FD(BPF_REG_1, 0),
6335 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6336 BPF_FUNC_map_lookup_elem),
6337 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
6338 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6339 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6340 BPF_MOV64_IMM(BPF_REG_2, 0),
6341 BPF_JMP_REG(BPF_JGT, BPF_REG_2, BPF_REG_1, 2),
6342 BPF_MOV64_IMM(BPF_REG_0, 0),
6343 BPF_EXIT_INSN(),
6344 BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 1, 2),
6345 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6346 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
6347 BPF_MOV64_IMM(BPF_REG_0, 0),
6348 BPF_EXIT_INSN(),
6349 },
6350 .fixup_map1 = { 3 },
6351 .errstr = "R0 min value is negative",
6352 .result = REJECT,
6353 },
6354 {
6355 "bounds checks mixing signed and unsigned, variant 11",
6356 .insns = {
6357 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6358 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6359 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6360 BPF_LD_MAP_FD(BPF_REG_1, 0),
6361 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6362 BPF_FUNC_map_lookup_elem),
6363 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
6364 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6365 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6366 BPF_MOV64_IMM(BPF_REG_2, -1),
6367 BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 2),
6368 /* Dead branch. */
6369 BPF_MOV64_IMM(BPF_REG_0, 0),
6370 BPF_EXIT_INSN(),
6371 BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 1, 2),
6372 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6373 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
6374 BPF_MOV64_IMM(BPF_REG_0, 0),
6375 BPF_EXIT_INSN(),
6376 },
6377 .fixup_map1 = { 3 },
6378 .errstr = "R0 min value is negative",
6379 .result = REJECT,
6380 },
6381 {
6382 "bounds checks mixing signed and unsigned, variant 12",
6383 .insns = {
6384 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6385 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6386 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6387 BPF_LD_MAP_FD(BPF_REG_1, 0),
6388 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6389 BPF_FUNC_map_lookup_elem),
6390 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
6391 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6392 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6393 BPF_MOV64_IMM(BPF_REG_2, -6),
6394 BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 2),
6395 BPF_MOV64_IMM(BPF_REG_0, 0),
6396 BPF_EXIT_INSN(),
6397 BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 1, 2),
6398 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6399 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
6400 BPF_MOV64_IMM(BPF_REG_0, 0),
6401 BPF_EXIT_INSN(),
6402 },
6403 .fixup_map1 = { 3 },
6404 .errstr = "R0 min value is negative",
6405 .result = REJECT,
6406 },
6407 {
6408 "bounds checks mixing signed and unsigned, variant 13",
6409 .insns = {
6410 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6411 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6412 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6413 BPF_LD_MAP_FD(BPF_REG_1, 0),
6414 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6415 BPF_FUNC_map_lookup_elem),
6416 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
6417 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6418 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6419 BPF_MOV64_IMM(BPF_REG_2, 2),
6420 BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 2),
6421 BPF_MOV64_IMM(BPF_REG_7, 1),
6422 BPF_JMP_IMM(BPF_JSGT, BPF_REG_7, 0, 2),
6423 BPF_MOV64_IMM(BPF_REG_0, 0),
6424 BPF_EXIT_INSN(),
6425 BPF_ALU64_REG(BPF_ADD, BPF_REG_7, BPF_REG_1),
6426 BPF_JMP_IMM(BPF_JSGT, BPF_REG_7, 4, 2),
6427 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_7),
6428 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
6429 BPF_MOV64_IMM(BPF_REG_0, 0),
6430 BPF_EXIT_INSN(),
6431 },
6432 .fixup_map1 = { 3 },
6433 .errstr = "R0 min value is negative",
6434 .result = REJECT,
6435 },
6436 {
6437 "bounds checks mixing signed and unsigned, variant 14",
6438 .insns = {
6439 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1,
6440 offsetof(struct __sk_buff, mark)),
6441 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6442 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6443 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6444 BPF_LD_MAP_FD(BPF_REG_1, 0),
6445 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6446 BPF_FUNC_map_lookup_elem),
6447 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
6448 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6449 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6450 BPF_MOV64_IMM(BPF_REG_2, -1),
6451 BPF_MOV64_IMM(BPF_REG_8, 2),
6452 BPF_JMP_IMM(BPF_JEQ, BPF_REG_9, 42, 6),
6453 BPF_JMP_REG(BPF_JSGT, BPF_REG_8, BPF_REG_1, 3),
6454 BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 1, 2),
6455 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6456 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
6457 BPF_MOV64_IMM(BPF_REG_0, 0),
6458 BPF_EXIT_INSN(),
6459 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, -3),
6460 BPF_JMP_IMM(BPF_JA, 0, 0, -7),
6461 },
6462 .fixup_map1 = { 4 },
6463 .errstr = "R0 min value is negative",
6464 .result = REJECT,
6465 },
6466 {
6467 "bounds checks mixing signed and unsigned, variant 15",
6468 .insns = {
6469 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6470 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6471 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6472 BPF_LD_MAP_FD(BPF_REG_1, 0),
6473 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6474 BPF_FUNC_map_lookup_elem),
6475 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
6476 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
6477 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
6478 BPF_MOV64_IMM(BPF_REG_2, -6),
6479 BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 2),
6480 BPF_MOV64_IMM(BPF_REG_0, 0),
6481 BPF_EXIT_INSN(),
6482 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6483 BPF_JMP_IMM(BPF_JGT, BPF_REG_0, 1, 2),
6484 BPF_MOV64_IMM(BPF_REG_0, 0),
6485 BPF_EXIT_INSN(),
6486 BPF_ST_MEM(BPF_B, BPF_REG_0, 0, 0),
6487 BPF_MOV64_IMM(BPF_REG_0, 0),
6488 BPF_EXIT_INSN(),
6489 },
6490 .fixup_map1 = { 3 },
6491 .errstr_unpriv = "R0 pointer comparison prohibited",
6492 .errstr = "R0 min value is negative",
6493 .result = REJECT,
6494 .result_unpriv = REJECT,
6495 },
6496 {
6497 "subtraction bounds (map value) variant 1",
6498 .insns = {
6499 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6500 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6501 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6502 BPF_LD_MAP_FD(BPF_REG_1, 0),
6503 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6504 BPF_FUNC_map_lookup_elem),
6505 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
6506 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6507 BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0xff, 7),
6508 BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_0, 1),
6509 BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 0xff, 5),
6510 BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_3),
6511 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 56),
6512 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6513 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
6514 BPF_EXIT_INSN(),
6515 BPF_MOV64_IMM(BPF_REG_0, 0),
6516 BPF_EXIT_INSN(),
6517 },
6518 .fixup_map1 = { 3 },
6519 .errstr = "R0 max value is outside of the array range",
6520 .result = REJECT,
6521 },
6522 {
6523 "subtraction bounds (map value) variant 2",
6524 .insns = {
6525 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6526 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6527 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6528 BPF_LD_MAP_FD(BPF_REG_1, 0),
6529 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6530 BPF_FUNC_map_lookup_elem),
6531 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
6532 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6533 BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0xff, 6),
6534 BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_0, 1),
6535 BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 0xff, 4),
6536 BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_3),
6537 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6538 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
6539 BPF_EXIT_INSN(),
6540 BPF_MOV64_IMM(BPF_REG_0, 0),
6541 BPF_EXIT_INSN(),
6542 },
6543 .fixup_map1 = { 3 },
6544 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
6545 .result = REJECT,
6546 },
6547 {
6548 "variable-offset ctx access",
6549 .insns = {
6550 /* Get an unknown value */
6551 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
6552 /* Make it small and 4-byte aligned */
6553 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
6554 /* add it to skb. We now have either &skb->len or
6555 * &skb->pkt_type, but we don't know which
6556 */
6557 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2),
6558 /* dereference it */
6559 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
6560 BPF_EXIT_INSN(),
6561 },
6562 .errstr = "variable ctx access var_off=(0x0; 0x4)",
6563 .result = REJECT,
6564 .prog_type = BPF_PROG_TYPE_LWT_IN,
6565 },
6566 {
6567 "variable-offset stack access",
6568 .insns = {
6569 /* Fill the top 8 bytes of the stack */
6570 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6571 /* Get an unknown value */
6572 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
6573 /* Make it small and 4-byte aligned */
6574 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
6575 BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 8),
6576 /* add it to fp. We now have either fp-4 or fp-8, but
6577 * we don't know which
6578 */
6579 BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
6580 /* dereference it */
6581 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_2, 0),
6582 BPF_EXIT_INSN(),
6583 },
6584 .errstr = "variable stack access var_off=(0xfffffffffffffff8; 0x4)",
6585 .result = REJECT,
6586 .prog_type = BPF_PROG_TYPE_LWT_IN,
6587 },
6588 {
6589 "liveness pruning and write screening",
6590 .insns = {
6591 /* Get an unknown value */
6592 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
6593 /* branch conditions teach us nothing about R2 */
6594 BPF_JMP_IMM(BPF_JGE, BPF_REG_2, 0, 1),
6595 BPF_MOV64_IMM(BPF_REG_0, 0),
6596 BPF_JMP_IMM(BPF_JGE, BPF_REG_2, 0, 1),
6597 BPF_MOV64_IMM(BPF_REG_0, 0),
6598 BPF_EXIT_INSN(),
6599 },
6600 .errstr = "R0 !read_ok",
6601 .result = REJECT,
6602 .prog_type = BPF_PROG_TYPE_LWT_IN,
6603 },
6604 {
6605 "varlen_map_value_access pruning",
6606 .insns = {
6607 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6608 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6609 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6610 BPF_LD_MAP_FD(BPF_REG_1, 0),
6611 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6612 BPF_FUNC_map_lookup_elem),
6613 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
6614 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
6615 BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES),
6616 BPF_JMP_REG(BPF_JSGT, BPF_REG_2, BPF_REG_1, 1),
6617 BPF_MOV32_IMM(BPF_REG_1, 0),
6618 BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2),
6619 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6620 BPF_JMP_IMM(BPF_JA, 0, 0, 0),
6621 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
6622 offsetof(struct test_val, foo)),
6623 BPF_EXIT_INSN(),
6624 },
6625 .fixup_map2 = { 3 },
6626 .errstr_unpriv = "R0 leaks addr",
6627 .errstr = "R0 unbounded memory access",
6628 .result_unpriv = REJECT,
6629 .result = REJECT,
6630 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
6631 },
6632 {
6633 "invalid 64-bit BPF_END",
6634 .insns = {
6635 BPF_MOV32_IMM(BPF_REG_0, 0),
6636 {
6637 .code = BPF_ALU64 | BPF_END | BPF_TO_LE,
6638 .dst_reg = BPF_REG_0,
6639 .src_reg = 0,
6640 .off = 0,
6641 .imm = 32,
6642 },
6643 BPF_EXIT_INSN(),
6644 },
6645 .errstr = "BPF_END uses reserved fields",
6646 .result = REJECT,
6647 },
5513}; 6648};
5514 6649
5515static int probe_filter_length(const struct bpf_insn *fp) 6650static int probe_filter_length(const struct bpf_insn *fp)
@@ -5633,7 +6768,7 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
5633 6768
5634 fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, 6769 fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
5635 prog, prog_len, test->flags & F_LOAD_WITH_STRICT_ALIGNMENT, 6770 prog, prog_len, test->flags & F_LOAD_WITH_STRICT_ALIGNMENT,
5636 "GPL", 0, bpf_vlog, sizeof(bpf_vlog)); 6771 "GPL", 0, bpf_vlog, sizeof(bpf_vlog), 1);
5637 6772
5638 expected_ret = unpriv && test->result_unpriv != UNDEF ? 6773 expected_ret = unpriv && test->result_unpriv != UNDEF ?
5639 test->result_unpriv : test->result; 6774 test->result_unpriv : test->result;
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/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/capabilities/test_execve.c b/tools/testing/selftests/capabilities/test_execve.c
index 763f37fecfb8..cf6778441381 100644
--- a/tools/testing/selftests/capabilities/test_execve.c
+++ b/tools/testing/selftests/capabilities/test_execve.c
@@ -1,7 +1,6 @@
1#define _GNU_SOURCE 1#define _GNU_SOURCE
2 2
3#include <cap-ng.h> 3#include <cap-ng.h>
4#include <err.h>
5#include <linux/capability.h> 4#include <linux/capability.h>
6#include <stdbool.h> 5#include <stdbool.h>
7#include <string.h> 6#include <string.h>
@@ -18,6 +17,8 @@
18#include <sys/prctl.h> 17#include <sys/prctl.h>
19#include <sys/stat.h> 18#include <sys/stat.h>
20 19
20#include "../kselftest.h"
21
21#ifndef PR_CAP_AMBIENT 22#ifndef PR_CAP_AMBIENT
22#define PR_CAP_AMBIENT 47 23#define PR_CAP_AMBIENT 47
23# define PR_CAP_AMBIENT_IS_SET 1 24# define PR_CAP_AMBIENT_IS_SET 1
@@ -27,6 +28,7 @@
27#endif 28#endif
28 29
29static int nerrs; 30static int nerrs;
31static pid_t mpid; /* main() pid is used to avoid duplicate test counts */
30 32
31static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap) 33static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap)
32{ 34{
@@ -36,29 +38,32 @@ static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list
36 int buf_len; 38 int buf_len;
37 39
38 buf_len = vsnprintf(buf, sizeof(buf), fmt, ap); 40 buf_len = vsnprintf(buf, sizeof(buf), fmt, ap);
39 if (buf_len < 0) { 41 if (buf_len < 0)
40 err(1, "vsnprintf failed"); 42 ksft_exit_fail_msg("vsnprintf failed - %s\n", strerror(errno));
41 } 43
42 if (buf_len >= sizeof(buf)) { 44 if (buf_len >= sizeof(buf))
43 errx(1, "vsnprintf output truncated"); 45 ksft_exit_fail_msg("vsnprintf output truncated\n");
44 } 46
45 47
46 fd = open(filename, O_WRONLY); 48 fd = open(filename, O_WRONLY);
47 if (fd < 0) { 49 if (fd < 0) {
48 if ((errno == ENOENT) && enoent_ok) 50 if ((errno == ENOENT) && enoent_ok)
49 return; 51 return;
50 err(1, "open of %s failed", filename); 52 ksft_exit_fail_msg("open of %s failed - %s\n",
53 filename, strerror(errno));
51 } 54 }
52 written = write(fd, buf, buf_len); 55 written = write(fd, buf, buf_len);
53 if (written != buf_len) { 56 if (written != buf_len) {
54 if (written >= 0) { 57 if (written >= 0) {
55 errx(1, "short write to %s", filename); 58 ksft_exit_fail_msg("short write to %s\n", filename);
56 } else { 59 } else {
57 err(1, "write to %s failed", filename); 60 ksft_exit_fail_msg("write to %s failed - %s\n",
61 filename, strerror(errno));
58 } 62 }
59 } 63 }
60 if (close(fd) != 0) { 64 if (close(fd) != 0) {
61 err(1, "close of %s failed", filename); 65 ksft_exit_fail_msg("close of %s failed - %s\n",
66 filename, strerror(errno));
62 } 67 }
63} 68}
64 69
@@ -95,11 +100,12 @@ static bool create_and_enter_ns(uid_t inner_uid)
95 */ 100 */
96 101
97 if (unshare(CLONE_NEWNS) == 0) { 102 if (unshare(CLONE_NEWNS) == 0) {
98 printf("[NOTE]\tUsing global UIDs for tests\n"); 103 ksft_print_msg("[NOTE]\tUsing global UIDs for tests\n");
99 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) 104 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0)
100 err(1, "PR_SET_KEEPCAPS"); 105 ksft_exit_fail_msg("PR_SET_KEEPCAPS - %s\n",
106 strerror(errno));
101 if (setresuid(inner_uid, inner_uid, -1) != 0) 107 if (setresuid(inner_uid, inner_uid, -1) != 0)
102 err(1, "setresuid"); 108 ksft_exit_fail_msg("setresuid - %s\n", strerror(errno));
103 109
104 // Re-enable effective caps 110 // Re-enable effective caps
105 capng_get_caps_process(); 111 capng_get_caps_process();
@@ -107,22 +113,24 @@ static bool create_and_enter_ns(uid_t inner_uid)
107 if (capng_have_capability(CAPNG_PERMITTED, i)) 113 if (capng_have_capability(CAPNG_PERMITTED, i))
108 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, i); 114 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, i);
109 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 115 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
110 err(1, "capng_apply"); 116 ksft_exit_fail_msg(
117 "capng_apply - %s\n", strerror(errno));
111 118
112 have_outer_privilege = true; 119 have_outer_privilege = true;
113 } else if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == 0) { 120 } else if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == 0) {
114 printf("[NOTE]\tUsing a user namespace for tests\n"); 121 ksft_print_msg("[NOTE]\tUsing a user namespace for tests\n");
115 maybe_write_file("/proc/self/setgroups", "deny"); 122 maybe_write_file("/proc/self/setgroups", "deny");
116 write_file("/proc/self/uid_map", "%d %d 1", inner_uid, outer_uid); 123 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); 124 write_file("/proc/self/gid_map", "0 %d 1", outer_gid);
118 125
119 have_outer_privilege = false; 126 have_outer_privilege = false;
120 } else { 127 } else {
121 errx(1, "must be root or be able to create a userns"); 128 ksft_exit_skip("must be root or be able to create a userns\n");
122 } 129 }
123 130
124 if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0) 131 if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0)
125 err(1, "remount everything private"); 132 ksft_exit_fail_msg("remount everything private - %s\n",
133 strerror(errno));
126 134
127 return have_outer_privilege; 135 return have_outer_privilege;
128} 136}
@@ -131,20 +139,22 @@ static void chdir_to_tmpfs(void)
131{ 139{
132 char cwd[PATH_MAX]; 140 char cwd[PATH_MAX];
133 if (getcwd(cwd, sizeof(cwd)) != cwd) 141 if (getcwd(cwd, sizeof(cwd)) != cwd)
134 err(1, "getcwd"); 142 ksft_exit_fail_msg("getcwd - %s\n", strerror(errno));
135 143
136 if (mount("private_tmp", ".", "tmpfs", 0, "mode=0777") != 0) 144 if (mount("private_tmp", ".", "tmpfs", 0, "mode=0777") != 0)
137 err(1, "mount private tmpfs"); 145 ksft_exit_fail_msg("mount private tmpfs - %s\n",
146 strerror(errno));
138 147
139 if (chdir(cwd) != 0) 148 if (chdir(cwd) != 0)
140 err(1, "chdir to private tmpfs"); 149 ksft_exit_fail_msg("chdir to private tmpfs - %s\n",
150 strerror(errno));
141} 151}
142 152
143static void copy_fromat_to(int fromfd, const char *fromname, const char *toname) 153static void copy_fromat_to(int fromfd, const char *fromname, const char *toname)
144{ 154{
145 int from = openat(fromfd, fromname, O_RDONLY); 155 int from = openat(fromfd, fromname, O_RDONLY);
146 if (from == -1) 156 if (from == -1)
147 err(1, "open copy source"); 157 ksft_exit_fail_msg("open copy source - %s\n", strerror(errno));
148 158
149 int to = open(toname, O_CREAT | O_WRONLY | O_EXCL, 0700); 159 int to = open(toname, O_CREAT | O_WRONLY | O_EXCL, 0700);
150 160
@@ -154,10 +164,11 @@ static void copy_fromat_to(int fromfd, const char *fromname, const char *toname)
154 if (sz == 0) 164 if (sz == 0)
155 break; 165 break;
156 if (sz < 0) 166 if (sz < 0)
157 err(1, "read"); 167 ksft_exit_fail_msg("read - %s\n", strerror(errno));
158 168
159 if (write(to, buf, sz) != sz) 169 if (write(to, buf, sz) != sz)
160 err(1, "write"); /* no short writes on tmpfs */ 170 /* no short writes on tmpfs */
171 ksft_exit_fail_msg("write - %s\n", strerror(errno));
161 } 172 }
162 173
163 close(from); 174 close(from);
@@ -174,18 +185,20 @@ static bool fork_wait(void)
174 int status; 185 int status;
175 if (waitpid(child, &status, 0) != child || 186 if (waitpid(child, &status, 0) != child ||
176 !WIFEXITED(status)) { 187 !WIFEXITED(status)) {
177 printf("[FAIL]\tChild died\n"); 188 ksft_print_msg("Child died\n");
178 nerrs++; 189 nerrs++;
179 } else if (WEXITSTATUS(status) != 0) { 190 } else if (WEXITSTATUS(status) != 0) {
180 printf("[FAIL]\tChild failed\n"); 191 ksft_print_msg("Child failed\n");
181 nerrs++; 192 nerrs++;
182 } else { 193 } else {
183 printf("[OK]\tChild succeeded\n"); 194 /* don't print this message for mpid */
195 if (getpid() != mpid)
196 ksft_test_result_pass("Passed\n");
184 } 197 }
185
186 return false; 198 return false;
187 } else { 199 } else {
188 err(1, "fork"); 200 ksft_exit_fail_msg("fork - %s\n", strerror(errno));
201 return false;
189 } 202 }
190} 203}
191 204
@@ -195,7 +208,7 @@ static void exec_other_validate_cap(const char *name,
195 execl(name, name, (eff ? "1" : "0"), 208 execl(name, name, (eff ? "1" : "0"),
196 (perm ? "1" : "0"), (inh ? "1" : "0"), (ambient ? "1" : "0"), 209 (perm ? "1" : "0"), (inh ? "1" : "0"), (ambient ? "1" : "0"),
197 NULL); 210 NULL);
198 err(1, "execl"); 211 ksft_exit_fail_msg("execl - %s\n", strerror(errno));
199} 212}
200 213
201static void exec_validate_cap(bool eff, bool perm, bool inh, bool ambient) 214static void exec_validate_cap(bool eff, bool perm, bool inh, bool ambient)
@@ -209,7 +222,8 @@ static int do_tests(int uid, const char *our_path)
209 222
210 int ourpath_fd = open(our_path, O_RDONLY | O_DIRECTORY); 223 int ourpath_fd = open(our_path, O_RDONLY | O_DIRECTORY);
211 if (ourpath_fd == -1) 224 if (ourpath_fd == -1)
212 err(1, "open '%s'", our_path); 225 ksft_exit_fail_msg("open '%s' - %s\n",
226 our_path, strerror(errno));
213 227
214 chdir_to_tmpfs(); 228 chdir_to_tmpfs();
215 229
@@ -221,30 +235,30 @@ static int do_tests(int uid, const char *our_path)
221 copy_fromat_to(ourpath_fd, "validate_cap", 235 copy_fromat_to(ourpath_fd, "validate_cap",
222 "validate_cap_suidroot"); 236 "validate_cap_suidroot");
223 if (chown("validate_cap_suidroot", 0, -1) != 0) 237 if (chown("validate_cap_suidroot", 0, -1) != 0)
224 err(1, "chown"); 238 ksft_exit_fail_msg("chown - %s\n", strerror(errno));
225 if (chmod("validate_cap_suidroot", S_ISUID | 0700) != 0) 239 if (chmod("validate_cap_suidroot", S_ISUID | 0700) != 0)
226 err(1, "chmod"); 240 ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
227 241
228 copy_fromat_to(ourpath_fd, "validate_cap", 242 copy_fromat_to(ourpath_fd, "validate_cap",
229 "validate_cap_suidnonroot"); 243 "validate_cap_suidnonroot");
230 if (chown("validate_cap_suidnonroot", uid + 1, -1) != 0) 244 if (chown("validate_cap_suidnonroot", uid + 1, -1) != 0)
231 err(1, "chown"); 245 ksft_exit_fail_msg("chown - %s\n", strerror(errno));
232 if (chmod("validate_cap_suidnonroot", S_ISUID | 0700) != 0) 246 if (chmod("validate_cap_suidnonroot", S_ISUID | 0700) != 0)
233 err(1, "chmod"); 247 ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
234 248
235 copy_fromat_to(ourpath_fd, "validate_cap", 249 copy_fromat_to(ourpath_fd, "validate_cap",
236 "validate_cap_sgidroot"); 250 "validate_cap_sgidroot");
237 if (chown("validate_cap_sgidroot", -1, 0) != 0) 251 if (chown("validate_cap_sgidroot", -1, 0) != 0)
238 err(1, "chown"); 252 ksft_exit_fail_msg("chown - %s\n", strerror(errno));
239 if (chmod("validate_cap_sgidroot", S_ISGID | 0710) != 0) 253 if (chmod("validate_cap_sgidroot", S_ISGID | 0710) != 0)
240 err(1, "chmod"); 254 ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
241 255
242 copy_fromat_to(ourpath_fd, "validate_cap", 256 copy_fromat_to(ourpath_fd, "validate_cap",
243 "validate_cap_sgidnonroot"); 257 "validate_cap_sgidnonroot");
244 if (chown("validate_cap_sgidnonroot", -1, gid + 1) != 0) 258 if (chown("validate_cap_sgidnonroot", -1, gid + 1) != 0)
245 err(1, "chown"); 259 ksft_exit_fail_msg("chown - %s\n", strerror(errno));
246 if (chmod("validate_cap_sgidnonroot", S_ISGID | 0710) != 0) 260 if (chmod("validate_cap_sgidnonroot", S_ISGID | 0710) != 0)
247 err(1, "chmod"); 261 ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
248 } 262 }
249 263
250 capng_get_caps_process(); 264 capng_get_caps_process();
@@ -252,147 +266,162 @@ static int do_tests(int uid, const char *our_path)
252 /* Make sure that i starts out clear */ 266 /* Make sure that i starts out clear */
253 capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); 267 capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
254 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 268 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
255 err(1, "capng_apply"); 269 ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
256 270
257 if (uid == 0) { 271 if (uid == 0) {
258 printf("[RUN]\tRoot => ep\n"); 272 ksft_print_msg("[RUN]\tRoot => ep\n");
259 if (fork_wait()) 273 if (fork_wait())
260 exec_validate_cap(true, true, false, false); 274 exec_validate_cap(true, true, false, false);
261 } else { 275 } else {
262 printf("[RUN]\tNon-root => no caps\n"); 276 ksft_print_msg("[RUN]\tNon-root => no caps\n");
263 if (fork_wait()) 277 if (fork_wait())
264 exec_validate_cap(false, false, false, false); 278 exec_validate_cap(false, false, false, false);
265 } 279 }
266 280
267 printf("[OK]\tCheck cap_ambient manipulation rules\n"); 281 ksft_print_msg("Check cap_ambient manipulation rules\n");
268 282
269 /* We should not be able to add ambient caps yet. */ 283 /* 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) { 284 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != -1 || errno != EPERM) {
271 if (errno == EINVAL) 285 if (errno == EINVAL)
272 printf("[FAIL]\tPR_CAP_AMBIENT_RAISE isn't supported\n"); 286 ksft_test_result_fail(
287 "PR_CAP_AMBIENT_RAISE isn't supported\n");
273 else 288 else
274 printf("[FAIL]\tPR_CAP_AMBIENT_RAISE should have failed eith EPERM on a non-inheritable cap\n"); 289 ksft_test_result_fail(
290 "PR_CAP_AMBIENT_RAISE should have failed eith EPERM on a non-inheritable cap\n");
275 return 1; 291 return 1;
276 } 292 }
277 printf("[OK]\tPR_CAP_AMBIENT_RAISE failed on non-inheritable cap\n"); 293 ksft_test_result_pass(
294 "PR_CAP_AMBIENT_RAISE failed on non-inheritable cap\n");
278 295
279 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_RAW); 296 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_RAW);
280 capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_NET_RAW); 297 capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_NET_RAW);
281 capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_NET_RAW); 298 capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_NET_RAW);
282 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 299 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
283 err(1, "capng_apply"); 300 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) { 301 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"); 302 ksft_test_result_fail(
303 "PR_CAP_AMBIENT_RAISE should have failed on a non-permitted cap\n");
286 return 1; 304 return 1;
287 } 305 }
288 printf("[OK]\tPR_CAP_AMBIENT_RAISE failed on non-permitted cap\n"); 306 ksft_test_result_pass(
307 "PR_CAP_AMBIENT_RAISE failed on non-permitted cap\n");
289 308
290 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); 309 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
291 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 310 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
292 err(1, "capng_apply"); 311 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) { 312 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"); 313 ksft_test_result_fail(
314 "PR_CAP_AMBIENT_RAISE should have succeeded\n");
295 return 1; 315 return 1;
296 } 316 }
297 printf("[OK]\tPR_CAP_AMBIENT_RAISE worked\n"); 317 ksft_test_result_pass("PR_CAP_AMBIENT_RAISE worked\n");
298 318
299 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 1) { 319 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"); 320 ksft_test_result_fail("PR_CAP_AMBIENT_IS_SET is broken\n");
301 return 1; 321 return 1;
302 } 322 }
303 323
304 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0, 0) != 0) 324 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0, 0) != 0)
305 err(1, "PR_CAP_AMBIENT_CLEAR_ALL"); 325 ksft_exit_fail_msg("PR_CAP_AMBIENT_CLEAR_ALL - %s\n",
326 strerror(errno));
306 327
307 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) { 328 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"); 329 ksft_test_result_fail(
330 "PR_CAP_AMBIENT_CLEAR_ALL didn't work\n");
309 return 1; 331 return 1;
310 } 332 }
311 333
312 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) 334 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0)
313 err(1, "PR_CAP_AMBIENT_RAISE"); 335 ksft_exit_fail_msg("PR_CAP_AMBIENT_RAISE - %s\n",
336 strerror(errno));
314 337
315 capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); 338 capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
316 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 339 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
317 err(1, "capng_apply"); 340 ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
318 341
319 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) { 342 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"); 343 ksft_test_result_fail("Dropping I should have dropped A\n");
321 return 1; 344 return 1;
322 } 345 }
323 346
324 printf("[OK]\tBasic manipulation appears to work\n"); 347 ksft_test_result_pass("Basic manipulation appears to work\n");
325 348
326 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); 349 capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
327 if (capng_apply(CAPNG_SELECT_CAPS) != 0) 350 if (capng_apply(CAPNG_SELECT_CAPS) != 0)
328 err(1, "capng_apply"); 351 ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
329 if (uid == 0) { 352 if (uid == 0) {
330 printf("[RUN]\tRoot +i => eip\n"); 353 ksft_print_msg("[RUN]\tRoot +i => eip\n");
331 if (fork_wait()) 354 if (fork_wait())
332 exec_validate_cap(true, true, true, false); 355 exec_validate_cap(true, true, true, false);
333 } else { 356 } else {
334 printf("[RUN]\tNon-root +i => i\n"); 357 ksft_print_msg("[RUN]\tNon-root +i => i\n");
335 if (fork_wait()) 358 if (fork_wait())
336 exec_validate_cap(false, false, true, false); 359 exec_validate_cap(false, false, true, false);
337 } 360 }
338 361
339 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) 362 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0)
340 err(1, "PR_CAP_AMBIENT_RAISE"); 363 ksft_exit_fail_msg("PR_CAP_AMBIENT_RAISE - %s\n",
364 strerror(errno));
341 365
342 printf("[RUN]\tUID %d +ia => eipa\n", uid); 366 ksft_print_msg("[RUN]\tUID %d +ia => eipa\n", uid);
343 if (fork_wait()) 367 if (fork_wait())
344 exec_validate_cap(true, true, true, true); 368 exec_validate_cap(true, true, true, true);
345 369
346 /* The remaining tests need real privilege */ 370 /* The remaining tests need real privilege */
347 371
348 if (!have_outer_privilege) { 372 if (!have_outer_privilege) {
349 printf("[SKIP]\tSUID/SGID tests (needs privilege)\n"); 373 ksft_test_result_skip("SUID/SGID tests (needs privilege)\n");
350 goto done; 374 goto done;
351 } 375 }
352 376
353 if (uid == 0) { 377 if (uid == 0) {
354 printf("[RUN]\tRoot +ia, suidroot => eipa\n"); 378 ksft_print_msg("[RUN]\tRoot +ia, suidroot => eipa\n");
355 if (fork_wait()) 379 if (fork_wait())
356 exec_other_validate_cap("./validate_cap_suidroot", 380 exec_other_validate_cap("./validate_cap_suidroot",
357 true, true, true, true); 381 true, true, true, true);
358 382
359 printf("[RUN]\tRoot +ia, suidnonroot => ip\n"); 383 ksft_print_msg("[RUN]\tRoot +ia, suidnonroot => ip\n");
360 if (fork_wait()) 384 if (fork_wait())
361 exec_other_validate_cap("./validate_cap_suidnonroot", 385 exec_other_validate_cap("./validate_cap_suidnonroot",
362 false, true, true, false); 386 false, true, true, false);
363 387
364 printf("[RUN]\tRoot +ia, sgidroot => eipa\n"); 388 ksft_print_msg("[RUN]\tRoot +ia, sgidroot => eipa\n");
365 if (fork_wait()) 389 if (fork_wait())
366 exec_other_validate_cap("./validate_cap_sgidroot", 390 exec_other_validate_cap("./validate_cap_sgidroot",
367 true, true, true, true); 391 true, true, true, true);
368 392
369 if (fork_wait()) { 393 if (fork_wait()) {
370 printf("[RUN]\tRoot, gid != 0, +ia, sgidroot => eip\n"); 394 ksft_print_msg(
395 "[RUN]\tRoot, gid != 0, +ia, sgidroot => eip\n");
371 if (setresgid(1, 1, 1) != 0) 396 if (setresgid(1, 1, 1) != 0)
372 err(1, "setresgid"); 397 ksft_exit_fail_msg("setresgid - %s\n",
398 strerror(errno));
373 exec_other_validate_cap("./validate_cap_sgidroot", 399 exec_other_validate_cap("./validate_cap_sgidroot",
374 true, true, true, false); 400 true, true, true, false);
375 } 401 }
376 402
377 printf("[RUN]\tRoot +ia, sgidnonroot => eip\n"); 403 ksft_print_msg("[RUN]\tRoot +ia, sgidnonroot => eip\n");
378 if (fork_wait()) 404 if (fork_wait())
379 exec_other_validate_cap("./validate_cap_sgidnonroot", 405 exec_other_validate_cap("./validate_cap_sgidnonroot",
380 true, true, true, false); 406 true, true, true, false);
381 } else { 407 } else {
382 printf("[RUN]\tNon-root +ia, sgidnonroot => i\n"); 408 ksft_print_msg("[RUN]\tNon-root +ia, sgidnonroot => i\n");
383 exec_other_validate_cap("./validate_cap_sgidnonroot", 409 if (fork_wait())
410 exec_other_validate_cap("./validate_cap_sgidnonroot",
384 false, false, true, false); 411 false, false, true, false);
385 412
386 if (fork_wait()) { 413 if (fork_wait()) {
387 printf("[RUN]\tNon-root +ia, sgidroot => i\n"); 414 ksft_print_msg("[RUN]\tNon-root +ia, sgidroot => i\n");
388 if (setresgid(1, 1, 1) != 0) 415 if (setresgid(1, 1, 1) != 0)
389 err(1, "setresgid"); 416 ksft_exit_fail_msg("setresgid - %s\n",
417 strerror(errno));
390 exec_other_validate_cap("./validate_cap_sgidroot", 418 exec_other_validate_cap("./validate_cap_sgidroot",
391 false, false, true, false); 419 false, false, true, false);
392 } 420 }
393 } 421 }
394 422
395done: 423done:
424 ksft_print_cnts();
396 return nerrs ? 1 : 0; 425 return nerrs ? 1 : 0;
397} 426}
398 427
@@ -400,23 +429,29 @@ int main(int argc, char **argv)
400{ 429{
401 char *tmp1, *tmp2, *our_path; 430 char *tmp1, *tmp2, *our_path;
402 431
432 ksft_print_header();
433
403 /* Find our path */ 434 /* Find our path */
404 tmp1 = strdup(argv[0]); 435 tmp1 = strdup(argv[0]);
405 if (!tmp1) 436 if (!tmp1)
406 err(1, "strdup"); 437 ksft_exit_fail_msg("strdup - %s\n", strerror(errno));
407 tmp2 = dirname(tmp1); 438 tmp2 = dirname(tmp1);
408 our_path = strdup(tmp2); 439 our_path = strdup(tmp2);
409 if (!our_path) 440 if (!our_path)
410 err(1, "strdup"); 441 ksft_exit_fail_msg("strdup - %s\n", strerror(errno));
411 free(tmp1); 442 free(tmp1);
412 443
444 mpid = getpid();
445
413 if (fork_wait()) { 446 if (fork_wait()) {
414 printf("[RUN]\t+++ Tests with uid == 0 +++\n"); 447 ksft_print_msg("[RUN]\t+++ Tests with uid == 0 +++\n");
415 return do_tests(0, our_path); 448 return do_tests(0, our_path);
416 } 449 }
417 450
451 ksft_print_msg("==================================================\n");
452
418 if (fork_wait()) { 453 if (fork_wait()) {
419 printf("[RUN]\t+++ Tests with uid != 0 +++\n"); 454 ksft_print_msg("[RUN]\t+++ Tests with uid != 0 +++\n");
420 return do_tests(1, our_path); 455 return do_tests(1, our_path);
421 } 456 }
422 457
diff --git a/tools/testing/selftests/capabilities/validate_cap.c b/tools/testing/selftests/capabilities/validate_cap.c
index dd3c45f7b23c..694cd73d4493 100644
--- a/tools/testing/selftests/capabilities/validate_cap.c
+++ b/tools/testing/selftests/capabilities/validate_cap.c
@@ -1,5 +1,4 @@
1#include <cap-ng.h> 1#include <cap-ng.h>
2#include <err.h>
3#include <linux/capability.h> 2#include <linux/capability.h>
4#include <stdbool.h> 3#include <stdbool.h>
5#include <string.h> 4#include <string.h>
@@ -7,6 +6,8 @@
7#include <sys/prctl.h> 6#include <sys/prctl.h>
8#include <sys/auxv.h> 7#include <sys/auxv.h>
9 8
9#include "../kselftest.h"
10
10#ifndef PR_CAP_AMBIENT 11#ifndef PR_CAP_AMBIENT
11#define PR_CAP_AMBIENT 47 12#define PR_CAP_AMBIENT 47
12# define PR_CAP_AMBIENT_IS_SET 1 13# define PR_CAP_AMBIENT_IS_SET 1
@@ -25,8 +26,10 @@ static bool bool_arg(char **argv, int i)
25 return false; 26 return false;
26 else if (!strcmp(argv[i], "1")) 27 else if (!strcmp(argv[i], "1"))
27 return true; 28 return true;
28 else 29 else {
29 errx(1, "wrong argv[%d]", i); 30 ksft_exit_fail_msg("wrong argv[%d]\n", i);
31 return false;
32 }
30} 33}
31 34
32int main(int argc, char **argv) 35int main(int argc, char **argv)
@@ -39,7 +42,7 @@ int main(int argc, char **argv)
39 */ 42 */
40 43
41 if (argc != 5) 44 if (argc != 5)
42 errx(1, "wrong argc"); 45 ksft_exit_fail_msg("wrong argc\n");
43 46
44#ifdef HAVE_GETAUXVAL 47#ifdef HAVE_GETAUXVAL
45 if (getauxval(AT_SECURE)) 48 if (getauxval(AT_SECURE))
@@ -51,23 +54,26 @@ int main(int argc, char **argv)
51 capng_get_caps_process(); 54 capng_get_caps_process();
52 55
53 if (capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 1)) { 56 if (capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 1)) {
54 printf("[FAIL]\tWrong effective state%s\n", atsec); 57 ksft_print_msg("Wrong effective state%s\n", atsec);
55 return 1; 58 return 1;
56 } 59 }
60
57 if (capng_have_capability(CAPNG_PERMITTED, CAP_NET_BIND_SERVICE) != bool_arg(argv, 2)) { 61 if (capng_have_capability(CAPNG_PERMITTED, CAP_NET_BIND_SERVICE) != bool_arg(argv, 2)) {
58 printf("[FAIL]\tWrong permitted state%s\n", atsec); 62 ksft_print_msg("Wrong permitted state%s\n", atsec);
59 return 1; 63 return 1;
60 } 64 }
65
61 if (capng_have_capability(CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 3)) { 66 if (capng_have_capability(CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 3)) {
62 printf("[FAIL]\tWrong inheritable state%s\n", atsec); 67 ksft_print_msg("Wrong inheritable state%s\n", atsec);
63 return 1; 68 return 1;
64 } 69 }
65 70
66 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != bool_arg(argv, 4)) { 71 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); 72 ksft_print_msg("Wrong ambient state%s\n", atsec);
68 return 1; 73 return 1;
69 } 74 }
70 75
71 printf("[OK]\tCapabilities after execve were correct\n"); 76 ksft_print_msg("%s: Capabilities after execve were correct\n",
77 "validate_cap:");
72 return 0; 78 return 0;
73} 79}
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..b18b253d7bfb 100755
--- a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
+++ b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
@@ -28,6 +28,12 @@ prerequisite()
28 echo "CPU online/offline summary:" 28 echo "CPU online/offline summary:"
29 online_cpus=`cat $SYSFS/devices/system/cpu/online` 29 online_cpus=`cat $SYSFS/devices/system/cpu/online`
30 online_max=${online_cpus##*-} 30 online_max=${online_cpus##*-}
31
32 if [[ "$online_cpus" = "$online_max" ]]; then
33 echo "$msg: since there is only one cpu: $online_cpus"
34 exit 0
35 fi
36
31 echo -e "\t Cpus in online state: $online_cpus" 37 echo -e "\t Cpus in online state: $online_cpus"
32 38
33 offline_cpus=`cat $SYSFS/devices/system/cpu/offline` 39 offline_cpus=`cat $SYSFS/devices/system/cpu/offline`
@@ -89,8 +95,10 @@ online_cpu_expect_success()
89 95
90 if ! online_cpu $cpu; then 96 if ! online_cpu $cpu; then
91 echo $FUNCNAME $cpu: unexpected fail >&2 97 echo $FUNCNAME $cpu: unexpected fail >&2
98 exit 1
92 elif ! cpu_is_online $cpu; then 99 elif ! cpu_is_online $cpu; then
93 echo $FUNCNAME $cpu: unexpected offline >&2 100 echo $FUNCNAME $cpu: unexpected offline >&2
101 exit 1
94 fi 102 fi
95} 103}
96 104
@@ -100,8 +108,10 @@ online_cpu_expect_fail()
100 108
101 if online_cpu $cpu 2> /dev/null; then 109 if online_cpu $cpu 2> /dev/null; then
102 echo $FUNCNAME $cpu: unexpected success >&2 110 echo $FUNCNAME $cpu: unexpected success >&2
111 exit 1
103 elif ! cpu_is_offline $cpu; then 112 elif ! cpu_is_offline $cpu; then
104 echo $FUNCNAME $cpu: unexpected online >&2 113 echo $FUNCNAME $cpu: unexpected online >&2
114 exit 1
105 fi 115 fi
106} 116}
107 117
@@ -111,8 +121,10 @@ offline_cpu_expect_success()
111 121
112 if ! offline_cpu $cpu; then 122 if ! offline_cpu $cpu; then
113 echo $FUNCNAME $cpu: unexpected fail >&2 123 echo $FUNCNAME $cpu: unexpected fail >&2
124 exit 1
114 elif ! cpu_is_offline $cpu; then 125 elif ! cpu_is_offline $cpu; then
115 echo $FUNCNAME $cpu: unexpected offline >&2 126 echo $FUNCNAME $cpu: unexpected offline >&2
127 exit 1
116 fi 128 fi
117} 129}
118 130
@@ -122,8 +134,10 @@ offline_cpu_expect_fail()
122 134
123 if offline_cpu $cpu 2> /dev/null; then 135 if offline_cpu $cpu 2> /dev/null; then
124 echo $FUNCNAME $cpu: unexpected success >&2 136 echo $FUNCNAME $cpu: unexpected success >&2
137 exit 1
125 elif ! cpu_is_online $cpu; then 138 elif ! cpu_is_online $cpu; then
126 echo $FUNCNAME $cpu: unexpected offline >&2 139 echo $FUNCNAME $cpu: unexpected offline >&2
140 exit 1
127 fi 141 fi
128} 142}
129 143
diff --git a/tools/testing/selftests/firmware/fw_fallback.sh b/tools/testing/selftests/firmware/fw_fallback.sh
index 2e4c22d5abf7..8f511035f783 100755
--- a/tools/testing/selftests/firmware/fw_fallback.sh
+++ b/tools/testing/selftests/firmware/fw_fallback.sh
@@ -134,6 +134,27 @@ load_fw_custom_cancel()
134 wait 134 wait
135} 135}
136 136
137load_fw_fallback_with_child()
138{
139 local name="$1"
140 local file="$2"
141
142 # This is the value already set but we want to be explicit
143 echo 4 >/sys/class/firmware/timeout
144
145 sleep 1 &
146 SECONDS_BEFORE=$(date +%s)
147 echo -n "$name" >"$DIR"/trigger_request 2>/dev/null
148 SECONDS_AFTER=$(date +%s)
149 SECONDS_DELTA=$(($SECONDS_AFTER - $SECONDS_BEFORE))
150 if [ "$SECONDS_DELTA" -lt 4 ]; then
151 RET=1
152 else
153 RET=0
154 fi
155 wait
156 return $RET
157}
137 158
138trap "test_finish" EXIT 159trap "test_finish" EXIT
139 160
@@ -221,4 +242,14 @@ else
221 echo "$0: cancelling custom fallback mechanism works" 242 echo "$0: cancelling custom fallback mechanism works"
222fi 243fi
223 244
245set +e
246load_fw_fallback_with_child "nope-signal-$NAME" "$FW"
247if [ "$?" -eq 0 ]; then
248 echo "$0: SIGCHLD on sync ignored as expected" >&2
249else
250 echo "$0: error - sync firmware request cancelled due to SIGCHLD" >&2
251 exit 1
252fi
253set -e
254
224exit 0 255exit 0
diff --git a/tools/testing/selftests/firmware/fw_filesystem.sh b/tools/testing/selftests/firmware/fw_filesystem.sh
index e35691239350..7d8fd2e3695a 100755
--- a/tools/testing/selftests/firmware/fw_filesystem.sh
+++ b/tools/testing/selftests/firmware/fw_filesystem.sh
@@ -25,8 +25,9 @@ if [ ! -d $DIR ]; then
25fi 25fi
26 26
27# CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/ 27# 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 28# These days most distros enable CONFIG_FW_LOADER_USER_HELPER but disable
29# as an indicator for CONFIG_FW_LOADER_USER_HELPER. 29# CONFIG_FW_LOADER_USER_HELPER_FALLBACK. We use /sys/class/firmware/ as an
30# indicator for CONFIG_FW_LOADER_USER_HELPER.
30HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi) 31HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
31 32
32if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then 33if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
@@ -116,4 +117,240 @@ else
116 echo "$0: async filesystem loading works" 117 echo "$0: async filesystem loading works"
117fi 118fi
118 119
120### Batched requests tests
121test_config_present()
122{
123 if [ ! -f $DIR/reset ]; then
124 echo "Configuration triggers not present, ignoring test"
125 exit 0
126 fi
127}
128
129# Defaults :
130#
131# send_uevent: 1
132# sync_direct: 0
133# name: test-firmware.bin
134# num_requests: 4
135config_reset()
136{
137 echo 1 > $DIR/reset
138}
139
140release_all_firmware()
141{
142 echo 1 > $DIR/release_all_firmware
143}
144
145config_set_name()
146{
147 echo -n $1 > $DIR/config_name
148}
149
150config_set_sync_direct()
151{
152 echo 1 > $DIR/config_sync_direct
153}
154
155config_unset_sync_direct()
156{
157 echo 0 > $DIR/config_sync_direct
158}
159
160config_set_uevent()
161{
162 echo 1 > $DIR/config_send_uevent
163}
164
165config_unset_uevent()
166{
167 echo 0 > $DIR/config_send_uevent
168}
169
170config_trigger_sync()
171{
172 echo -n 1 > $DIR/trigger_batched_requests 2>/dev/null
173}
174
175config_trigger_async()
176{
177 echo -n 1 > $DIR/trigger_batched_requests_async 2> /dev/null
178}
179
180config_set_read_fw_idx()
181{
182 echo -n $1 > $DIR/config_read_fw_idx 2> /dev/null
183}
184
185read_firmwares()
186{
187 for i in $(seq 0 3); do
188 config_set_read_fw_idx $i
189 # Verify the contents are what we expect.
190 # -Z required for now -- check for yourself, md5sum
191 # on $FW and DIR/read_firmware will yield the same. Even
192 # cmp agrees, so something is off.
193 if ! diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
194 echo "request #$i: firmware was not loaded" >&2
195 exit 1
196 fi
197 done
198}
199
200read_firmwares_expect_nofile()
201{
202 for i in $(seq 0 3); do
203 config_set_read_fw_idx $i
204 # Ensures contents differ
205 if diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
206 echo "request $i: file was not expected to match" >&2
207 exit 1
208 fi
209 done
210}
211
212test_batched_request_firmware_nofile()
213{
214 echo -n "Batched request_firmware() nofile try #$1: "
215 config_reset
216 config_set_name nope-test-firmware.bin
217 config_trigger_sync
218 read_firmwares_expect_nofile
219 release_all_firmware
220 echo "OK"
221}
222
223test_batched_request_firmware_direct_nofile()
224{
225 echo -n "Batched request_firmware_direct() nofile try #$1: "
226 config_reset
227 config_set_name nope-test-firmware.bin
228 config_set_sync_direct
229 config_trigger_sync
230 release_all_firmware
231 echo "OK"
232}
233
234test_request_firmware_nowait_uevent_nofile()
235{
236 echo -n "Batched request_firmware_nowait(uevent=true) nofile try #$1: "
237 config_reset
238 config_set_name nope-test-firmware.bin
239 config_trigger_async
240 release_all_firmware
241 echo "OK"
242}
243
244test_wait_and_cancel_custom_load()
245{
246 if [ "$HAS_FW_LOADER_USER_HELPER" != "yes" ]; then
247 return
248 fi
249 local timeout=10
250 name=$1
251 while [ ! -e "$DIR"/"$name"/loading ]; do
252 sleep 0.1
253 timeout=$(( $timeout - 1 ))
254 if [ "$timeout" -eq 0 ]; then
255 echo "firmware interface never appeared:" >&2
256 echo "$DIR/$name/loading" >&2
257 exit 1
258 fi
259 done
260 echo -1 >"$DIR"/"$name"/loading
261}
262
263test_request_firmware_nowait_custom_nofile()
264{
265 echo -n "Batched request_firmware_nowait(uevent=false) nofile try #$1: "
266 config_unset_uevent
267 config_set_name nope-test-firmware.bin
268 config_trigger_async &
269 test_wait_and_cancel_custom_load nope-test-firmware.bin
270 wait
271 release_all_firmware
272 echo "OK"
273}
274
275test_batched_request_firmware()
276{
277 echo -n "Batched request_firmware() try #$1: "
278 config_reset
279 config_trigger_sync
280 read_firmwares
281 release_all_firmware
282 echo "OK"
283}
284
285test_batched_request_firmware_direct()
286{
287 echo -n "Batched request_firmware_direct() try #$1: "
288 config_reset
289 config_set_sync_direct
290 config_trigger_sync
291 release_all_firmware
292 echo "OK"
293}
294
295test_request_firmware_nowait_uevent()
296{
297 echo -n "Batched request_firmware_nowait(uevent=true) try #$1: "
298 config_reset
299 config_trigger_async
300 release_all_firmware
301 echo "OK"
302}
303
304test_request_firmware_nowait_custom()
305{
306 echo -n "Batched request_firmware_nowait(uevent=false) try #$1: "
307 config_unset_uevent
308 config_trigger_async
309 release_all_firmware
310 echo "OK"
311}
312
313# Only continue if batched request triggers are present on the
314# test-firmware driver
315test_config_present
316
317# test with the file present
318echo
319echo "Testing with the file present..."
320for i in $(seq 1 5); do
321 test_batched_request_firmware $i
322done
323
324for i in $(seq 1 5); do
325 test_batched_request_firmware_direct $i
326done
327
328for i in $(seq 1 5); do
329 test_request_firmware_nowait_uevent $i
330done
331
332for i in $(seq 1 5); do
333 test_request_firmware_nowait_custom $i
334done
335
336# Test for file not found, errors are expected, the failure would be
337# a hung task, which would require a hard reset.
338echo
339echo "Testing with the file missing..."
340for i in $(seq 1 5); do
341 test_batched_request_firmware_nofile $i
342done
343
344for i in $(seq 1 5); do
345 test_batched_request_firmware_direct_nofile $i
346done
347
348for i in $(seq 1 5); do
349 test_request_firmware_nowait_uevent_nofile $i
350done
351
352for i in $(seq 1 5); do
353 test_request_firmware_nowait_custom_nofile $i
354done
355
119exit 0 356exit 0
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index 14a03ea1e21d..abc706cf7702 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]"
@@ -247,12 +262,20 @@ __run_test() { # testfile
247# Run one test case 262# Run one test case
248run_test() { # testfile 263run_test() { # testfile
249 local testname=`basename $1` 264 local testname=`basename $1`
250 local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX` 265 if [ ! -z "$LOG_FILE" ] ; then
266 local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX`
267 else
268 local testlog=/proc/self/fd/1
269 fi
251 export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX` 270 export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX`
252 testcase $1 271 testcase $1
253 echo "execute$INSTANCE: "$1 > $testlog 272 echo "execute$INSTANCE: "$1 > $testlog
254 SIG_RESULT=0 273 SIG_RESULT=0
255 if [ $VERBOSE -ge 2 ]; then 274 if [ -z "$LOG_FILE" ]; then
275 __run_test $1 2>&1
276 elif [ $VERBOSE -ge 3 ]; then
277 __run_test $1 | tee -a $testlog 2>&1
278 elif [ $VERBOSE -eq 2 ]; then
256 __run_test $1 2>> $testlog | tee -a $testlog 279 __run_test $1 2>> $testlog | tee -a $testlog
257 else 280 else
258 __run_test $1 >> $testlog 2>&1 281 __run_test $1 >> $testlog 2>&1
@@ -260,9 +283,9 @@ run_test() { # testfile
260 eval_result $SIG_RESULT 283 eval_result $SIG_RESULT
261 if [ $? -eq 0 ]; then 284 if [ $? -eq 0 ]; then
262 # Remove test log if the test was done as it was expected. 285 # Remove test log if the test was done as it was expected.
263 [ $KEEP_LOG -eq 0 ] && rm $testlog 286 [ $KEEP_LOG -eq 0 -a ! -z "$LOG_FILE" ] && rm $testlog
264 else 287 else
265 [ $VERBOSE -ge 1 ] && catlog $testlog 288 [ $VERBOSE -eq 1 -o $VERBOSE -eq 2 ] && catlog $testlog
266 TOTAL_RESULT=1 289 TOTAL_RESULT=1
267 fi 290 fi
268 rm -rf $TMPDIR 291 rm -rf $TMPDIR
diff --git a/tools/testing/selftests/futex/Makefile b/tools/testing/selftests/futex/Makefile
index e2fbb890aef9..7c647f619d63 100644
--- a/tools/testing/selftests/futex/Makefile
+++ b/tools/testing/selftests/futex/Makefile
@@ -14,7 +14,7 @@ all:
14 done 14 done
15 15
16override define RUN_TESTS 16override define RUN_TESTS
17 @if [ `dirname $(OUTPUT)` = $(PWD) ]; then ./run.sh; fi 17 $(OUTPUT)/run.sh
18endef 18endef
19 19
20override define INSTALL_RULE 20override define INSTALL_RULE
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/kcmp/kcmp_test.c b/tools/testing/selftests/kcmp/kcmp_test.c
index a5a4da856dfe..73684c4a1ed6 100644
--- a/tools/testing/selftests/kcmp/kcmp_test.c
+++ b/tools/testing/selftests/kcmp/kcmp_test.c
@@ -8,7 +8,6 @@
8#include <errno.h> 8#include <errno.h>
9#include <string.h> 9#include <string.h>
10#include <fcntl.h> 10#include <fcntl.h>
11
12#include <linux/unistd.h> 11#include <linux/unistd.h>
13#include <linux/kcmp.h> 12#include <linux/kcmp.h>
14 13
@@ -16,20 +15,28 @@
16#include <sys/types.h> 15#include <sys/types.h>
17#include <sys/stat.h> 16#include <sys/stat.h>
18#include <sys/wait.h> 17#include <sys/wait.h>
18#include <sys/epoll.h>
19 19
20#include "../kselftest.h" 20#include "../kselftest.h"
21 21
22static long sys_kcmp(int pid1, int pid2, int type, int fd1, int fd2) 22static long sys_kcmp(int pid1, int pid2, int type, unsigned long fd1, unsigned long fd2)
23{ 23{
24 return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2); 24 return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2);
25} 25}
26 26
27static const unsigned int duped_num = 64;
28
27int main(int argc, char **argv) 29int main(int argc, char **argv)
28{ 30{
29 const char kpath[] = "kcmp-test-file"; 31 const char kpath[] = "kcmp-test-file";
32 struct kcmp_epoll_slot epoll_slot;
33 struct epoll_event ev;
30 int pid1, pid2; 34 int pid1, pid2;
35 int pipefd[2];
31 int fd1, fd2; 36 int fd1, fd2;
37 int epollfd;
32 int status; 38 int status;
39 int fddup;
33 40
34 fd1 = open(kpath, O_RDWR | O_CREAT | O_TRUNC, 0644); 41 fd1 = open(kpath, O_RDWR | O_CREAT | O_TRUNC, 0644);
35 pid1 = getpid(); 42 pid1 = getpid();
@@ -39,6 +46,37 @@ int main(int argc, char **argv)
39 ksft_exit_fail(); 46 ksft_exit_fail();
40 } 47 }
41 48
49 if (pipe(pipefd)) {
50 perror("Can't create pipe");
51 ksft_exit_fail();
52 }
53
54 epollfd = epoll_create1(0);
55 if (epollfd < 0) {
56 perror("epoll_create1 failed");
57 ksft_exit_fail();
58 }
59
60 memset(&ev, 0xff, sizeof(ev));
61 ev.events = EPOLLIN | EPOLLOUT;
62
63 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd[0], &ev)) {
64 perror("epoll_ctl failed");
65 ksft_exit_fail();
66 }
67
68 fddup = dup2(pipefd[1], duped_num);
69 if (fddup < 0) {
70 perror("dup2 failed");
71 ksft_exit_fail();
72 }
73
74 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fddup, &ev)) {
75 perror("epoll_ctl failed");
76 ksft_exit_fail();
77 }
78 close(fddup);
79
42 pid2 = fork(); 80 pid2 = fork();
43 if (pid2 < 0) { 81 if (pid2 < 0) {
44 perror("fork failed"); 82 perror("fork failed");
@@ -95,6 +133,24 @@ int main(int argc, char **argv)
95 ksft_inc_pass_cnt(); 133 ksft_inc_pass_cnt();
96 } 134 }
97 135
136 /* Compare epoll target */
137 epoll_slot = (struct kcmp_epoll_slot) {
138 .efd = epollfd,
139 .tfd = duped_num,
140 .toff = 0,
141 };
142 ret = sys_kcmp(pid1, pid1, KCMP_EPOLL_TFD, pipefd[1],
143 (unsigned long)(void *)&epoll_slot);
144 if (ret) {
145 printf("FAIL: 0 expected but %d returned (%s)\n",
146 ret, strerror(errno));
147 ksft_inc_fail_cnt();
148 ret = -1;
149 } else {
150 printf("PASS: 0 returned as expected\n");
151 ksft_inc_pass_cnt();
152 }
153
98 ksft_print_cnts(); 154 ksft_print_cnts();
99 155
100 if (ret) 156 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..693616651da5 100644
--- a/tools/testing/selftests/lib.mk
+++ b/tools/testing/selftests/lib.mk
@@ -11,15 +11,26 @@ TEST_GEN_FILES := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_FILES))
11 11
12all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) 12all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES)
13 13
14.ONESHELL:
14define RUN_TESTS 15define RUN_TESTS
15 @for TEST in $(TEST_GEN_PROGS) $(TEST_PROGS); do \ 16 @test_num=`echo 0`;
17 @echo "TAP version 13";
18 @for TEST in $(1); do \
16 BASENAME_TEST=`basename $$TEST`; \ 19 BASENAME_TEST=`basename $$TEST`; \
17 cd `dirname $$TEST`; (./$$BASENAME_TEST && echo "selftests: $$BASENAME_TEST [PASS]") || echo "selftests: $$BASENAME_TEST [FAIL]"; cd -;\ 20 test_num=`echo $$test_num+1 | bc`; \
21 echo "selftests: $$BASENAME_TEST"; \
22 echo "========================================"; \
23 if [ ! -x $$BASENAME_TEST ]; then \
24 echo "selftests: Warning: file $$BASENAME_TEST is not executable, correct this.";\
25 echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; \
26 else \
27 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;\
28 fi; \
18 done; 29 done;
19endef 30endef
20 31
21run_tests: all 32run_tests: all
22 $(RUN_TESTS) 33 $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_PROGS))
23 34
24define INSTALL_RULE 35define INSTALL_RULE
25 @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then \ 36 @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then \
diff --git a/tools/testing/selftests/memfd/Makefile b/tools/testing/selftests/memfd/Makefile
index ad8a0897e47f..bc9d02d615da 100644
--- a/tools/testing/selftests/memfd/Makefile
+++ b/tools/testing/selftests/memfd/Makefile
@@ -3,7 +3,7 @@ CFLAGS += -I../../../../include/uapi/
3CFLAGS += -I../../../../include/ 3CFLAGS += -I../../../../include/
4CFLAGS += -I../../../../usr/include/ 4CFLAGS += -I../../../../usr/include/
5 5
6TEST_PROGS := run_fuse_test.sh 6TEST_PROGS := run_tests.sh
7TEST_GEN_FILES := memfd_test fuse_mnt fuse_test 7TEST_GEN_FILES := memfd_test fuse_mnt fuse_test
8 8
9fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags) 9fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags)
diff --git a/tools/testing/selftests/memfd/fuse_test.c b/tools/testing/selftests/memfd/fuse_test.c
index 67908b18f035..7f3617274bf5 100644
--- a/tools/testing/selftests/memfd/fuse_test.c
+++ b/tools/testing/selftests/memfd/fuse_test.c
@@ -33,7 +33,7 @@
33#include <unistd.h> 33#include <unistd.h>
34 34
35#define MFD_DEF_SIZE 8192 35#define MFD_DEF_SIZE 8192
36#define STACK_SIZE 65535 36#define STACK_SIZE 65536
37 37
38static int sys_memfd_create(const char *name, 38static int sys_memfd_create(const char *name,
39 unsigned int flags) 39 unsigned int flags)
diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c
index 26546892cd54..f94c6d1fb46f 100644
--- a/tools/testing/selftests/memfd/memfd_test.c
+++ b/tools/testing/selftests/memfd/memfd_test.c
@@ -18,12 +18,48 @@
18#include <sys/wait.h> 18#include <sys/wait.h>
19#include <unistd.h> 19#include <unistd.h>
20 20
21#define MEMFD_STR "memfd:"
22#define SHARED_FT_STR "(shared file-table)"
23
21#define MFD_DEF_SIZE 8192 24#define MFD_DEF_SIZE 8192
22#define STACK_SIZE 65536 25#define STACK_SIZE 65536
23 26
27/*
28 * Default is not to test hugetlbfs
29 */
30static int hugetlbfs_test;
31static size_t mfd_def_size = MFD_DEF_SIZE;
32
33/*
34 * Copied from mlock2-tests.c
35 */
36static unsigned long default_huge_page_size(void)
37{
38 unsigned long hps = 0;
39 char *line = NULL;
40 size_t linelen = 0;
41 FILE *f = fopen("/proc/meminfo", "r");
42
43 if (!f)
44 return 0;
45 while (getline(&line, &linelen, f) > 0) {
46 if (sscanf(line, "Hugepagesize: %lu kB", &hps) == 1) {
47 hps <<= 10;
48 break;
49 }
50 }
51
52 free(line);
53 fclose(f);
54 return hps;
55}
56
24static int sys_memfd_create(const char *name, 57static int sys_memfd_create(const char *name,
25 unsigned int flags) 58 unsigned int flags)
26{ 59{
60 if (hugetlbfs_test)
61 flags |= MFD_HUGETLB;
62
27 return syscall(__NR_memfd_create, name, flags); 63 return syscall(__NR_memfd_create, name, flags);
28} 64}
29 65
@@ -150,7 +186,7 @@ static void *mfd_assert_mmap_shared(int fd)
150 void *p; 186 void *p;
151 187
152 p = mmap(NULL, 188 p = mmap(NULL,
153 MFD_DEF_SIZE, 189 mfd_def_size,
154 PROT_READ | PROT_WRITE, 190 PROT_READ | PROT_WRITE,
155 MAP_SHARED, 191 MAP_SHARED,
156 fd, 192 fd,
@@ -168,7 +204,7 @@ static void *mfd_assert_mmap_private(int fd)
168 void *p; 204 void *p;
169 205
170 p = mmap(NULL, 206 p = mmap(NULL,
171 MFD_DEF_SIZE, 207 mfd_def_size,
172 PROT_READ, 208 PROT_READ,
173 MAP_PRIVATE, 209 MAP_PRIVATE,
174 fd, 210 fd,
@@ -223,7 +259,7 @@ static void mfd_assert_read(int fd)
223 259
224 /* verify PROT_READ *is* allowed */ 260 /* verify PROT_READ *is* allowed */
225 p = mmap(NULL, 261 p = mmap(NULL,
226 MFD_DEF_SIZE, 262 mfd_def_size,
227 PROT_READ, 263 PROT_READ,
228 MAP_PRIVATE, 264 MAP_PRIVATE,
229 fd, 265 fd,
@@ -232,11 +268,11 @@ static void mfd_assert_read(int fd)
232 printf("mmap() failed: %m\n"); 268 printf("mmap() failed: %m\n");
233 abort(); 269 abort();
234 } 270 }
235 munmap(p, MFD_DEF_SIZE); 271 munmap(p, mfd_def_size);
236 272
237 /* verify MAP_PRIVATE is *always* allowed (even writable) */ 273 /* verify MAP_PRIVATE is *always* allowed (even writable) */
238 p = mmap(NULL, 274 p = mmap(NULL,
239 MFD_DEF_SIZE, 275 mfd_def_size,
240 PROT_READ | PROT_WRITE, 276 PROT_READ | PROT_WRITE,
241 MAP_PRIVATE, 277 MAP_PRIVATE,
242 fd, 278 fd,
@@ -245,7 +281,7 @@ static void mfd_assert_read(int fd)
245 printf("mmap() failed: %m\n"); 281 printf("mmap() failed: %m\n");
246 abort(); 282 abort();
247 } 283 }
248 munmap(p, MFD_DEF_SIZE); 284 munmap(p, mfd_def_size);
249} 285}
250 286
251static void mfd_assert_write(int fd) 287static void mfd_assert_write(int fd)
@@ -254,16 +290,22 @@ static void mfd_assert_write(int fd)
254 void *p; 290 void *p;
255 int r; 291 int r;
256 292
257 /* verify write() succeeds */ 293 /*
258 l = write(fd, "\0\0\0\0", 4); 294 * huegtlbfs does not support write, but we want to
259 if (l != 4) { 295 * verify everything else here.
260 printf("write() failed: %m\n"); 296 */
261 abort(); 297 if (!hugetlbfs_test) {
298 /* verify write() succeeds */
299 l = write(fd, "\0\0\0\0", 4);
300 if (l != 4) {
301 printf("write() failed: %m\n");
302 abort();
303 }
262 } 304 }
263 305
264 /* verify PROT_READ | PROT_WRITE is allowed */ 306 /* verify PROT_READ | PROT_WRITE is allowed */
265 p = mmap(NULL, 307 p = mmap(NULL,
266 MFD_DEF_SIZE, 308 mfd_def_size,
267 PROT_READ | PROT_WRITE, 309 PROT_READ | PROT_WRITE,
268 MAP_SHARED, 310 MAP_SHARED,
269 fd, 311 fd,
@@ -273,11 +315,11 @@ static void mfd_assert_write(int fd)
273 abort(); 315 abort();
274 } 316 }
275 *(char *)p = 0; 317 *(char *)p = 0;
276 munmap(p, MFD_DEF_SIZE); 318 munmap(p, mfd_def_size);
277 319
278 /* verify PROT_WRITE is allowed */ 320 /* verify PROT_WRITE is allowed */
279 p = mmap(NULL, 321 p = mmap(NULL,
280 MFD_DEF_SIZE, 322 mfd_def_size,
281 PROT_WRITE, 323 PROT_WRITE,
282 MAP_SHARED, 324 MAP_SHARED,
283 fd, 325 fd,
@@ -287,12 +329,12 @@ static void mfd_assert_write(int fd)
287 abort(); 329 abort();
288 } 330 }
289 *(char *)p = 0; 331 *(char *)p = 0;
290 munmap(p, MFD_DEF_SIZE); 332 munmap(p, mfd_def_size);
291 333
292 /* verify PROT_READ with MAP_SHARED is allowed and a following 334 /* verify PROT_READ with MAP_SHARED is allowed and a following
293 * mprotect(PROT_WRITE) allows writing */ 335 * mprotect(PROT_WRITE) allows writing */
294 p = mmap(NULL, 336 p = mmap(NULL,
295 MFD_DEF_SIZE, 337 mfd_def_size,
296 PROT_READ, 338 PROT_READ,
297 MAP_SHARED, 339 MAP_SHARED,
298 fd, 340 fd,
@@ -302,20 +344,20 @@ static void mfd_assert_write(int fd)
302 abort(); 344 abort();
303 } 345 }
304 346
305 r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE); 347 r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
306 if (r < 0) { 348 if (r < 0) {
307 printf("mprotect() failed: %m\n"); 349 printf("mprotect() failed: %m\n");
308 abort(); 350 abort();
309 } 351 }
310 352
311 *(char *)p = 0; 353 *(char *)p = 0;
312 munmap(p, MFD_DEF_SIZE); 354 munmap(p, mfd_def_size);
313 355
314 /* verify PUNCH_HOLE works */ 356 /* verify PUNCH_HOLE works */
315 r = fallocate(fd, 357 r = fallocate(fd,
316 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 358 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
317 0, 359 0,
318 MFD_DEF_SIZE); 360 mfd_def_size);
319 if (r < 0) { 361 if (r < 0) {
320 printf("fallocate(PUNCH_HOLE) failed: %m\n"); 362 printf("fallocate(PUNCH_HOLE) failed: %m\n");
321 abort(); 363 abort();
@@ -337,7 +379,7 @@ static void mfd_fail_write(int fd)
337 379
338 /* verify PROT_READ | PROT_WRITE is not allowed */ 380 /* verify PROT_READ | PROT_WRITE is not allowed */
339 p = mmap(NULL, 381 p = mmap(NULL,
340 MFD_DEF_SIZE, 382 mfd_def_size,
341 PROT_READ | PROT_WRITE, 383 PROT_READ | PROT_WRITE,
342 MAP_SHARED, 384 MAP_SHARED,
343 fd, 385 fd,
@@ -349,7 +391,7 @@ static void mfd_fail_write(int fd)
349 391
350 /* verify PROT_WRITE is not allowed */ 392 /* verify PROT_WRITE is not allowed */
351 p = mmap(NULL, 393 p = mmap(NULL,
352 MFD_DEF_SIZE, 394 mfd_def_size,
353 PROT_WRITE, 395 PROT_WRITE,
354 MAP_SHARED, 396 MAP_SHARED,
355 fd, 397 fd,
@@ -362,13 +404,13 @@ static void mfd_fail_write(int fd)
362 /* Verify PROT_READ with MAP_SHARED with a following mprotect is not 404 /* 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. */ 405 * allowed. Note that for r/w the kernel already prevents the mmap. */
364 p = mmap(NULL, 406 p = mmap(NULL,
365 MFD_DEF_SIZE, 407 mfd_def_size,
366 PROT_READ, 408 PROT_READ,
367 MAP_SHARED, 409 MAP_SHARED,
368 fd, 410 fd,
369 0); 411 0);
370 if (p != MAP_FAILED) { 412 if (p != MAP_FAILED) {
371 r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE); 413 r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
372 if (r >= 0) { 414 if (r >= 0) {
373 printf("mmap()+mprotect() didn't fail as expected\n"); 415 printf("mmap()+mprotect() didn't fail as expected\n");
374 abort(); 416 abort();
@@ -379,7 +421,7 @@ static void mfd_fail_write(int fd)
379 r = fallocate(fd, 421 r = fallocate(fd,
380 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 422 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
381 0, 423 0,
382 MFD_DEF_SIZE); 424 mfd_def_size);
383 if (r >= 0) { 425 if (r >= 0) {
384 printf("fallocate(PUNCH_HOLE) didn't fail as expected\n"); 426 printf("fallocate(PUNCH_HOLE) didn't fail as expected\n");
385 abort(); 427 abort();
@@ -390,13 +432,13 @@ static void mfd_assert_shrink(int fd)
390{ 432{
391 int r, fd2; 433 int r, fd2;
392 434
393 r = ftruncate(fd, MFD_DEF_SIZE / 2); 435 r = ftruncate(fd, mfd_def_size / 2);
394 if (r < 0) { 436 if (r < 0) {
395 printf("ftruncate(SHRINK) failed: %m\n"); 437 printf("ftruncate(SHRINK) failed: %m\n");
396 abort(); 438 abort();
397 } 439 }
398 440
399 mfd_assert_size(fd, MFD_DEF_SIZE / 2); 441 mfd_assert_size(fd, mfd_def_size / 2);
400 442
401 fd2 = mfd_assert_open(fd, 443 fd2 = mfd_assert_open(fd,
402 O_RDWR | O_CREAT | O_TRUNC, 444 O_RDWR | O_CREAT | O_TRUNC,
@@ -410,7 +452,7 @@ static void mfd_fail_shrink(int fd)
410{ 452{
411 int r; 453 int r;
412 454
413 r = ftruncate(fd, MFD_DEF_SIZE / 2); 455 r = ftruncate(fd, mfd_def_size / 2);
414 if (r >= 0) { 456 if (r >= 0) {
415 printf("ftruncate(SHRINK) didn't fail as expected\n"); 457 printf("ftruncate(SHRINK) didn't fail as expected\n");
416 abort(); 458 abort();
@@ -425,31 +467,31 @@ static void mfd_assert_grow(int fd)
425{ 467{
426 int r; 468 int r;
427 469
428 r = ftruncate(fd, MFD_DEF_SIZE * 2); 470 r = ftruncate(fd, mfd_def_size * 2);
429 if (r < 0) { 471 if (r < 0) {
430 printf("ftruncate(GROW) failed: %m\n"); 472 printf("ftruncate(GROW) failed: %m\n");
431 abort(); 473 abort();
432 } 474 }
433 475
434 mfd_assert_size(fd, MFD_DEF_SIZE * 2); 476 mfd_assert_size(fd, mfd_def_size * 2);
435 477
436 r = fallocate(fd, 478 r = fallocate(fd,
437 0, 479 0,
438 0, 480 0,
439 MFD_DEF_SIZE * 4); 481 mfd_def_size * 4);
440 if (r < 0) { 482 if (r < 0) {
441 printf("fallocate(ALLOC) failed: %m\n"); 483 printf("fallocate(ALLOC) failed: %m\n");
442 abort(); 484 abort();
443 } 485 }
444 486
445 mfd_assert_size(fd, MFD_DEF_SIZE * 4); 487 mfd_assert_size(fd, mfd_def_size * 4);
446} 488}
447 489
448static void mfd_fail_grow(int fd) 490static void mfd_fail_grow(int fd)
449{ 491{
450 int r; 492 int r;
451 493
452 r = ftruncate(fd, MFD_DEF_SIZE * 2); 494 r = ftruncate(fd, mfd_def_size * 2);
453 if (r >= 0) { 495 if (r >= 0) {
454 printf("ftruncate(GROW) didn't fail as expected\n"); 496 printf("ftruncate(GROW) didn't fail as expected\n");
455 abort(); 497 abort();
@@ -458,7 +500,7 @@ static void mfd_fail_grow(int fd)
458 r = fallocate(fd, 500 r = fallocate(fd,
459 0, 501 0,
460 0, 502 0,
461 MFD_DEF_SIZE * 4); 503 mfd_def_size * 4);
462 if (r >= 0) { 504 if (r >= 0) {
463 printf("fallocate(ALLOC) didn't fail as expected\n"); 505 printf("fallocate(ALLOC) didn't fail as expected\n");
464 abort(); 506 abort();
@@ -467,25 +509,37 @@ static void mfd_fail_grow(int fd)
467 509
468static void mfd_assert_grow_write(int fd) 510static void mfd_assert_grow_write(int fd)
469{ 511{
470 static char buf[MFD_DEF_SIZE * 8]; 512 static char *buf;
471 ssize_t l; 513 ssize_t l;
472 514
473 l = pwrite(fd, buf, sizeof(buf), 0); 515 buf = malloc(mfd_def_size * 8);
474 if (l != sizeof(buf)) { 516 if (!buf) {
517 printf("malloc(%d) failed: %m\n", mfd_def_size * 8);
518 abort();
519 }
520
521 l = pwrite(fd, buf, mfd_def_size * 8, 0);
522 if (l != (mfd_def_size * 8)) {
475 printf("pwrite() failed: %m\n"); 523 printf("pwrite() failed: %m\n");
476 abort(); 524 abort();
477 } 525 }
478 526
479 mfd_assert_size(fd, MFD_DEF_SIZE * 8); 527 mfd_assert_size(fd, mfd_def_size * 8);
480} 528}
481 529
482static void mfd_fail_grow_write(int fd) 530static void mfd_fail_grow_write(int fd)
483{ 531{
484 static char buf[MFD_DEF_SIZE * 8]; 532 static char *buf;
485 ssize_t l; 533 ssize_t l;
486 534
487 l = pwrite(fd, buf, sizeof(buf), 0); 535 buf = malloc(mfd_def_size * 8);
488 if (l == sizeof(buf)) { 536 if (!buf) {
537 printf("malloc(%d) failed: %m\n", mfd_def_size * 8);
538 abort();
539 }
540
541 l = pwrite(fd, buf, mfd_def_size * 8, 0);
542 if (l == (mfd_def_size * 8)) {
489 printf("pwrite() didn't fail as expected\n"); 543 printf("pwrite() didn't fail as expected\n");
490 abort(); 544 abort();
491 } 545 }
@@ -543,6 +597,8 @@ static void test_create(void)
543 char buf[2048]; 597 char buf[2048];
544 int fd; 598 int fd;
545 599
600 printf("%s CREATE\n", MEMFD_STR);
601
546 /* test NULL name */ 602 /* test NULL name */
547 mfd_fail_new(NULL, 0); 603 mfd_fail_new(NULL, 0);
548 604
@@ -570,13 +626,18 @@ static void test_create(void)
570 fd = mfd_assert_new("", 0, MFD_CLOEXEC); 626 fd = mfd_assert_new("", 0, MFD_CLOEXEC);
571 close(fd); 627 close(fd);
572 628
573 /* verify MFD_ALLOW_SEALING is allowed */ 629 if (!hugetlbfs_test) {
574 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING); 630 /* verify MFD_ALLOW_SEALING is allowed */
575 close(fd); 631 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING);
576 632 close(fd);
577 /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */ 633
578 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC); 634 /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */
579 close(fd); 635 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC);
636 close(fd);
637 } else {
638 /* sealing is not supported on hugetlbfs */
639 mfd_fail_new("", MFD_ALLOW_SEALING);
640 }
580} 641}
581 642
582/* 643/*
@@ -587,8 +648,14 @@ static void test_basic(void)
587{ 648{
588 int fd; 649 int fd;
589 650
651 /* hugetlbfs does not contain sealing support */
652 if (hugetlbfs_test)
653 return;
654
655 printf("%s BASIC\n", MEMFD_STR);
656
590 fd = mfd_assert_new("kern_memfd_basic", 657 fd = mfd_assert_new("kern_memfd_basic",
591 MFD_DEF_SIZE, 658 mfd_def_size,
592 MFD_CLOEXEC | MFD_ALLOW_SEALING); 659 MFD_CLOEXEC | MFD_ALLOW_SEALING);
593 660
594 /* add basic seals */ 661 /* add basic seals */
@@ -619,7 +686,7 @@ static void test_basic(void)
619 686
620 /* verify sealing does not work without MFD_ALLOW_SEALING */ 687 /* verify sealing does not work without MFD_ALLOW_SEALING */
621 fd = mfd_assert_new("kern_memfd_basic", 688 fd = mfd_assert_new("kern_memfd_basic",
622 MFD_DEF_SIZE, 689 mfd_def_size,
623 MFD_CLOEXEC); 690 MFD_CLOEXEC);
624 mfd_assert_has_seals(fd, F_SEAL_SEAL); 691 mfd_assert_has_seals(fd, F_SEAL_SEAL);
625 mfd_fail_add_seals(fd, F_SEAL_SHRINK | 692 mfd_fail_add_seals(fd, F_SEAL_SHRINK |
@@ -630,6 +697,28 @@ static void test_basic(void)
630} 697}
631 698
632/* 699/*
700 * hugetlbfs doesn't support seals or write, so just verify grow and shrink
701 * on a hugetlbfs file created via memfd_create.
702 */
703static void test_hugetlbfs_grow_shrink(void)
704{
705 int fd;
706
707 printf("%s HUGETLBFS-GROW-SHRINK\n", MEMFD_STR);
708
709 fd = mfd_assert_new("kern_memfd_seal_write",
710 mfd_def_size,
711 MFD_CLOEXEC);
712
713 mfd_assert_read(fd);
714 mfd_assert_write(fd);
715 mfd_assert_shrink(fd);
716 mfd_assert_grow(fd);
717
718 close(fd);
719}
720
721/*
633 * Test SEAL_WRITE 722 * Test SEAL_WRITE
634 * Test whether SEAL_WRITE actually prevents modifications. 723 * Test whether SEAL_WRITE actually prevents modifications.
635 */ 724 */
@@ -637,8 +726,17 @@ static void test_seal_write(void)
637{ 726{
638 int fd; 727 int fd;
639 728
729 /*
730 * hugetlbfs does not contain sealing or write support. Just test
731 * basic grow and shrink via test_hugetlbfs_grow_shrink.
732 */
733 if (hugetlbfs_test)
734 return test_hugetlbfs_grow_shrink();
735
736 printf("%s SEAL-WRITE\n", MEMFD_STR);
737
640 fd = mfd_assert_new("kern_memfd_seal_write", 738 fd = mfd_assert_new("kern_memfd_seal_write",
641 MFD_DEF_SIZE, 739 mfd_def_size,
642 MFD_CLOEXEC | MFD_ALLOW_SEALING); 740 MFD_CLOEXEC | MFD_ALLOW_SEALING);
643 mfd_assert_has_seals(fd, 0); 741 mfd_assert_has_seals(fd, 0);
644 mfd_assert_add_seals(fd, F_SEAL_WRITE); 742 mfd_assert_add_seals(fd, F_SEAL_WRITE);
@@ -661,8 +759,14 @@ static void test_seal_shrink(void)
661{ 759{
662 int fd; 760 int fd;
663 761
762 /* hugetlbfs does not contain sealing support */
763 if (hugetlbfs_test)
764 return;
765
766 printf("%s SEAL-SHRINK\n", MEMFD_STR);
767
664 fd = mfd_assert_new("kern_memfd_seal_shrink", 768 fd = mfd_assert_new("kern_memfd_seal_shrink",
665 MFD_DEF_SIZE, 769 mfd_def_size,
666 MFD_CLOEXEC | MFD_ALLOW_SEALING); 770 MFD_CLOEXEC | MFD_ALLOW_SEALING);
667 mfd_assert_has_seals(fd, 0); 771 mfd_assert_has_seals(fd, 0);
668 mfd_assert_add_seals(fd, F_SEAL_SHRINK); 772 mfd_assert_add_seals(fd, F_SEAL_SHRINK);
@@ -685,8 +789,14 @@ static void test_seal_grow(void)
685{ 789{
686 int fd; 790 int fd;
687 791
792 /* hugetlbfs does not contain sealing support */
793 if (hugetlbfs_test)
794 return;
795
796 printf("%s SEAL-GROW\n", MEMFD_STR);
797
688 fd = mfd_assert_new("kern_memfd_seal_grow", 798 fd = mfd_assert_new("kern_memfd_seal_grow",
689 MFD_DEF_SIZE, 799 mfd_def_size,
690 MFD_CLOEXEC | MFD_ALLOW_SEALING); 800 MFD_CLOEXEC | MFD_ALLOW_SEALING);
691 mfd_assert_has_seals(fd, 0); 801 mfd_assert_has_seals(fd, 0);
692 mfd_assert_add_seals(fd, F_SEAL_GROW); 802 mfd_assert_add_seals(fd, F_SEAL_GROW);
@@ -709,8 +819,14 @@ static void test_seal_resize(void)
709{ 819{
710 int fd; 820 int fd;
711 821
822 /* hugetlbfs does not contain sealing support */
823 if (hugetlbfs_test)
824 return;
825
826 printf("%s SEAL-RESIZE\n", MEMFD_STR);
827
712 fd = mfd_assert_new("kern_memfd_seal_resize", 828 fd = mfd_assert_new("kern_memfd_seal_resize",
713 MFD_DEF_SIZE, 829 mfd_def_size,
714 MFD_CLOEXEC | MFD_ALLOW_SEALING); 830 MFD_CLOEXEC | MFD_ALLOW_SEALING);
715 mfd_assert_has_seals(fd, 0); 831 mfd_assert_has_seals(fd, 0);
716 mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW); 832 mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
@@ -726,15 +842,52 @@ static void test_seal_resize(void)
726} 842}
727 843
728/* 844/*
845 * hugetlbfs does not support seals. Basic test to dup the memfd created
846 * fd and perform some basic operations on it.
847 */
848static void hugetlbfs_dup(char *b_suffix)
849{
850 int fd, fd2;
851
852 printf("%s HUGETLBFS-DUP %s\n", MEMFD_STR, b_suffix);
853
854 fd = mfd_assert_new("kern_memfd_share_dup",
855 mfd_def_size,
856 MFD_CLOEXEC);
857
858 fd2 = mfd_assert_dup(fd);
859
860 mfd_assert_read(fd);
861 mfd_assert_write(fd);
862
863 mfd_assert_shrink(fd2);
864 mfd_assert_grow(fd2);
865
866 close(fd2);
867 close(fd);
868}
869
870/*
729 * Test sharing via dup() 871 * Test sharing via dup()
730 * Test that seals are shared between dupped FDs and they're all equal. 872 * Test that seals are shared between dupped FDs and they're all equal.
731 */ 873 */
732static void test_share_dup(void) 874static void test_share_dup(char *banner, char *b_suffix)
733{ 875{
734 int fd, fd2; 876 int fd, fd2;
735 877
878 /*
879 * hugetlbfs does not contain sealing support. Perform some
880 * basic testing on dup'ed fd instead via hugetlbfs_dup.
881 */
882 if (hugetlbfs_test) {
883 hugetlbfs_dup(b_suffix);
884 return;
885 }
886
887 printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
888
736 fd = mfd_assert_new("kern_memfd_share_dup", 889 fd = mfd_assert_new("kern_memfd_share_dup",
737 MFD_DEF_SIZE, 890 mfd_def_size,
738 MFD_CLOEXEC | MFD_ALLOW_SEALING); 891 MFD_CLOEXEC | MFD_ALLOW_SEALING);
739 mfd_assert_has_seals(fd, 0); 892 mfd_assert_has_seals(fd, 0);
740 893
@@ -768,13 +921,19 @@ static void test_share_dup(void)
768 * Test sealing with active mmap()s 921 * Test sealing with active mmap()s
769 * Modifying seals is only allowed if no other mmap() refs exist. 922 * Modifying seals is only allowed if no other mmap() refs exist.
770 */ 923 */
771static void test_share_mmap(void) 924static void test_share_mmap(char *banner, char *b_suffix)
772{ 925{
773 int fd; 926 int fd;
774 void *p; 927 void *p;
775 928
929 /* hugetlbfs does not contain sealing support */
930 if (hugetlbfs_test)
931 return;
932
933 printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
934
776 fd = mfd_assert_new("kern_memfd_share_mmap", 935 fd = mfd_assert_new("kern_memfd_share_mmap",
777 MFD_DEF_SIZE, 936 mfd_def_size,
778 MFD_CLOEXEC | MFD_ALLOW_SEALING); 937 MFD_CLOEXEC | MFD_ALLOW_SEALING);
779 mfd_assert_has_seals(fd, 0); 938 mfd_assert_has_seals(fd, 0);
780 939
@@ -784,14 +943,40 @@ static void test_share_mmap(void)
784 mfd_assert_has_seals(fd, 0); 943 mfd_assert_has_seals(fd, 0);
785 mfd_assert_add_seals(fd, F_SEAL_SHRINK); 944 mfd_assert_add_seals(fd, F_SEAL_SHRINK);
786 mfd_assert_has_seals(fd, F_SEAL_SHRINK); 945 mfd_assert_has_seals(fd, F_SEAL_SHRINK);
787 munmap(p, MFD_DEF_SIZE); 946 munmap(p, mfd_def_size);
788 947
789 /* readable ref allows sealing */ 948 /* readable ref allows sealing */
790 p = mfd_assert_mmap_private(fd); 949 p = mfd_assert_mmap_private(fd);
791 mfd_assert_add_seals(fd, F_SEAL_WRITE); 950 mfd_assert_add_seals(fd, F_SEAL_WRITE);
792 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK); 951 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
793 munmap(p, MFD_DEF_SIZE); 952 munmap(p, mfd_def_size);
953
954 close(fd);
955}
956
957/*
958 * Basic test to make sure we can open the hugetlbfs fd via /proc and
959 * perform some simple operations on it.
960 */
961static void hugetlbfs_proc_open(char *b_suffix)
962{
963 int fd, fd2;
964
965 printf("%s HUGETLBFS-PROC-OPEN %s\n", MEMFD_STR, b_suffix);
794 966
967 fd = mfd_assert_new("kern_memfd_share_open",
968 mfd_def_size,
969 MFD_CLOEXEC);
970
971 fd2 = mfd_assert_open(fd, O_RDWR, 0);
972
973 mfd_assert_read(fd);
974 mfd_assert_write(fd);
975
976 mfd_assert_shrink(fd2);
977 mfd_assert_grow(fd2);
978
979 close(fd2);
795 close(fd); 980 close(fd);
796} 981}
797 982
@@ -801,12 +986,23 @@ static void test_share_mmap(void)
801 * This is *not* like dup(), but like a real separate open(). Make sure the 986 * 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. 987 * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
803 */ 988 */
804static void test_share_open(void) 989static void test_share_open(char *banner, char *b_suffix)
805{ 990{
806 int fd, fd2; 991 int fd, fd2;
807 992
993 /*
994 * hugetlbfs does not contain sealing support. So test basic
995 * functionality of using /proc fd via hugetlbfs_proc_open
996 */
997 if (hugetlbfs_test) {
998 hugetlbfs_proc_open(b_suffix);
999 return;
1000 }
1001
1002 printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
1003
808 fd = mfd_assert_new("kern_memfd_share_open", 1004 fd = mfd_assert_new("kern_memfd_share_open",
809 MFD_DEF_SIZE, 1005 mfd_def_size,
810 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1006 MFD_CLOEXEC | MFD_ALLOW_SEALING);
811 mfd_assert_has_seals(fd, 0); 1007 mfd_assert_has_seals(fd, 0);
812 1008
@@ -841,13 +1037,19 @@ static void test_share_open(void)
841 * Test sharing via fork() 1037 * Test sharing via fork()
842 * Test whether seal-modifications work as expected with forked childs. 1038 * Test whether seal-modifications work as expected with forked childs.
843 */ 1039 */
844static void test_share_fork(void) 1040static void test_share_fork(char *banner, char *b_suffix)
845{ 1041{
846 int fd; 1042 int fd;
847 pid_t pid; 1043 pid_t pid;
848 1044
1045 /* hugetlbfs does not contain sealing support */
1046 if (hugetlbfs_test)
1047 return;
1048
1049 printf("%s %s %s\n", MEMFD_STR, banner, b_suffix);
1050
849 fd = mfd_assert_new("kern_memfd_share_fork", 1051 fd = mfd_assert_new("kern_memfd_share_fork",
850 MFD_DEF_SIZE, 1052 mfd_def_size,
851 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1053 MFD_CLOEXEC | MFD_ALLOW_SEALING);
852 mfd_assert_has_seals(fd, 0); 1054 mfd_assert_has_seals(fd, 0);
853 1055
@@ -870,40 +1072,40 @@ int main(int argc, char **argv)
870{ 1072{
871 pid_t pid; 1073 pid_t pid;
872 1074
873 printf("memfd: CREATE\n"); 1075 if (argc == 2) {
1076 if (!strcmp(argv[1], "hugetlbfs")) {
1077 unsigned long hpage_size = default_huge_page_size();
1078
1079 if (!hpage_size) {
1080 printf("Unable to determine huge page size\n");
1081 abort();
1082 }
1083
1084 hugetlbfs_test = 1;
1085 mfd_def_size = hpage_size * 2;
1086 }
1087 }
1088
874 test_create(); 1089 test_create();
875 printf("memfd: BASIC\n");
876 test_basic(); 1090 test_basic();
877 1091
878 printf("memfd: SEAL-WRITE\n");
879 test_seal_write(); 1092 test_seal_write();
880 printf("memfd: SEAL-SHRINK\n");
881 test_seal_shrink(); 1093 test_seal_shrink();
882 printf("memfd: SEAL-GROW\n");
883 test_seal_grow(); 1094 test_seal_grow();
884 printf("memfd: SEAL-RESIZE\n");
885 test_seal_resize(); 1095 test_seal_resize();
886 1096
887 printf("memfd: SHARE-DUP\n"); 1097 test_share_dup("SHARE-DUP", "");
888 test_share_dup(); 1098 test_share_mmap("SHARE-MMAP", "");
889 printf("memfd: SHARE-MMAP\n"); 1099 test_share_open("SHARE-OPEN", "");
890 test_share_mmap(); 1100 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 1101
896 /* Run test-suite in a multi-threaded environment with a shared 1102 /* Run test-suite in a multi-threaded environment with a shared
897 * file-table. */ 1103 * file-table. */
898 pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM); 1104 pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM);
899 printf("memfd: SHARE-DUP (shared file-table)\n"); 1105 test_share_dup("SHARE-DUP", SHARED_FT_STR);
900 test_share_dup(); 1106 test_share_mmap("SHARE-MMAP", SHARED_FT_STR);
901 printf("memfd: SHARE-MMAP (shared file-table)\n"); 1107 test_share_open("SHARE-OPEN", SHARED_FT_STR);
902 test_share_mmap(); 1108 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); 1109 join_idle_thread(pid);
908 1110
909 printf("memfd: DONE\n"); 1111 printf("memfd: DONE\n");
diff --git a/tools/testing/selftests/memfd/run_tests.sh b/tools/testing/selftests/memfd/run_tests.sh
new file mode 100644
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/net/.gitignore b/tools/testing/selftests/net/.gitignore
index afe109e5508a..9801253e4802 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
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index f6c9dbf478f8..de1f5772b878 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -3,11 +3,11 @@
3CFLAGS = -Wall -Wl,--no-as-needed -O2 -g 3CFLAGS = -Wall -Wl,--no-as-needed -O2 -g
4CFLAGS += -I../../../../usr/include/ 4CFLAGS += -I../../../../usr/include/
5 5
6TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh 6TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh
7TEST_GEN_FILES = socket 7TEST_GEN_FILES = socket
8TEST_GEN_FILES += psock_fanout psock_tpacket 8TEST_GEN_FILES += psock_fanout psock_tpacket
9TEST_GEN_FILES += reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa 9TEST_GEN_FILES += reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
10TEST_GEN_FILES += reuseport_dualstack 10TEST_GEN_FILES += reuseport_dualstack msg_zerocopy
11 11
12include ../lib.mk 12include ../lib.mk
13 13
diff --git a/tools/testing/selftests/net/msg_zerocopy.c b/tools/testing/selftests/net/msg_zerocopy.c
new file mode 100644
index 000000000000..40232af5b023
--- /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 SO_EE_ORIGIN_UPAGE
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/rtnetlink.sh b/tools/testing/selftests/net/rtnetlink.sh
new file mode 100755
index 000000000000..57b5ff576240
--- /dev/null
+++ b/tools/testing/selftests/net/rtnetlink.sh
@@ -0,0 +1,272 @@
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
18kci_add_dummy()
19{
20 ip link add name "$devdummy" type dummy
21 check_err $?
22 ip link set "$devdummy" up
23 check_err $?
24}
25
26kci_del_dummy()
27{
28 ip link del dev "$devdummy"
29 check_err $?
30}
31
32# add a bridge with vlans on top
33kci_test_bridge()
34{
35 devbr="test-br0"
36 vlandev="testbr-vlan1"
37
38 ret=0
39 ip link add name "$devbr" type bridge
40 check_err $?
41
42 ip link set dev "$devdummy" master "$devbr"
43 check_err $?
44
45 ip link set "$devbr" up
46 check_err $?
47
48 ip link add link "$devbr" name "$vlandev" type vlan id 1
49 check_err $?
50 ip addr add dev "$vlandev" 10.200.7.23/30
51 check_err $?
52 ip -6 addr add dev "$vlandev" dead:42::1234/64
53 check_err $?
54 ip -d link > /dev/null
55 check_err $?
56 ip r s t all > /dev/null
57 check_err $?
58 ip -6 addr del dev "$vlandev" dead:42::1234/64
59 check_err $?
60
61 ip link del dev "$vlandev"
62 check_err $?
63 ip link del dev "$devbr"
64 check_err $?
65
66 if [ $ret -ne 0 ];then
67 echo "FAIL: bridge setup"
68 return 1
69 fi
70 echo "PASS: bridge setup"
71
72}
73
74kci_test_gre()
75{
76 gredev=neta
77 rem=10.42.42.1
78 loc=10.0.0.1
79
80 ret=0
81 ip tunnel add $gredev mode gre remote $rem local $loc ttl 1
82 check_err $?
83 ip link set $gredev up
84 check_err $?
85 ip addr add 10.23.7.10 dev $gredev
86 check_err $?
87 ip route add 10.23.8.0/30 dev $gredev
88 check_err $?
89 ip addr add dev "$devdummy" 10.23.7.11/24
90 check_err $?
91 ip link > /dev/null
92 check_err $?
93 ip addr > /dev/null
94 check_err $?
95 ip addr del dev "$devdummy" 10.23.7.11/24
96 check_err $?
97
98 ip link del $gredev
99 check_err $?
100
101 if [ $ret -ne 0 ];then
102 echo "FAIL: gre tunnel endpoint"
103 return 1
104 fi
105 echo "PASS: gre tunnel endpoint"
106}
107
108# tc uses rtnetlink too, for full tc testing
109# please see tools/testing/selftests/tc-testing.
110kci_test_tc()
111{
112 dev=lo
113 ret=0
114
115 tc qdisc add dev "$dev" root handle 1: htb
116 check_err $?
117 tc class add dev "$dev" parent 1: classid 1:10 htb rate 1mbit
118 check_err $?
119 tc filter add dev "$dev" parent 1:0 prio 5 handle ffe: protocol ip u32 divisor 256
120 check_err $?
121 tc filter add dev "$dev" parent 1:0 prio 5 handle ffd: protocol ip u32 divisor 256
122 check_err $?
123 tc filter add dev "$dev" parent 1:0 prio 5 handle ffc: protocol ip u32 divisor 256
124 check_err $?
125 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
126 check_err $?
127 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
128 check_err $?
129 tc filter show dev "$dev" parent 1:0 > /dev/null
130 check_err $?
131 tc filter del dev "$dev" protocol ip parent 1: prio 5 handle ffe:2:3 u32
132 check_err $?
133 tc filter show dev "$dev" parent 1:0 > /dev/null
134 check_err $?
135 tc qdisc del dev "$dev" root handle 1: htb
136 check_err $?
137
138 if [ $ret -ne 0 ];then
139 echo "FAIL: tc htb hierarchy"
140 return 1
141 fi
142 echo "PASS: tc htb hierarchy"
143
144}
145
146kci_test_polrouting()
147{
148 ret=0
149 ip rule add fwmark 1 lookup 100
150 check_err $?
151 ip route add local 0.0.0.0/0 dev lo table 100
152 check_err $?
153 ip r s t all > /dev/null
154 check_err $?
155 ip rule del fwmark 1 lookup 100
156 check_err $?
157 ip route del local 0.0.0.0/0 dev lo table 100
158 check_err $?
159
160 if [ $ret -ne 0 ];then
161 echo "FAIL: policy route test"
162 return 1
163 fi
164 echo "PASS: policy routing"
165}
166
167kci_test_route_get()
168{
169 ret=0
170
171 ip route get 127.0.0.1 > /dev/null
172 check_err $?
173 ip route get 127.0.0.1 dev "$devdummy" > /dev/null
174 check_err $?
175 ip route get ::1 > /dev/null
176 check_err $?
177 ip route get fe80::1 dev "$devdummy" > /dev/null
178 check_err $?
179 ip route get 127.0.0.1 from 127.0.0.1 oif lo tos 0x1 mark 0x1 > /dev/null
180 check_err $?
181 ip route get ::1 from ::1 iif lo oif lo tos 0x1 mark 0x1 > /dev/null
182 check_err $?
183 ip addr add dev "$devdummy" 10.23.7.11/24
184 check_err $?
185 ip route get 10.23.7.11 from 10.23.7.12 iif "$devdummy" > /dev/null
186 check_err $?
187 ip addr del dev "$devdummy" 10.23.7.11/24
188 check_err $?
189
190 if [ $ret -ne 0 ];then
191 echo "FAIL: route get"
192 return 1
193 fi
194
195 echo "PASS: route get"
196}
197
198kci_test_addrlabel()
199{
200 ret=0
201
202 ip addrlabel add prefix dead::/64 dev lo label 1
203 check_err $?
204
205 ip addrlabel list |grep -q "prefix dead::/64 dev lo label 1"
206 check_err $?
207
208 ip addrlabel del prefix dead::/64 dev lo label 1 2> /dev/null
209 check_err $?
210
211 ip addrlabel add prefix dead::/64 label 1 2> /dev/null
212 check_err $?
213
214 ip addrlabel del prefix dead::/64 label 1 2> /dev/null
215 check_err $?
216
217 # concurrent add/delete
218 for i in $(seq 1 1000); do
219 ip addrlabel add prefix 1c3::/64 label 12345 2>/dev/null
220 done &
221
222 for i in $(seq 1 1000); do
223 ip addrlabel del prefix 1c3::/64 label 12345 2>/dev/null
224 done
225
226 wait
227
228 ip addrlabel del prefix 1c3::/64 label 12345 2>/dev/null
229
230 if [ $ret -ne 0 ];then
231 echo "FAIL: ipv6 addrlabel"
232 return 1
233 fi
234
235 echo "PASS: ipv6 addrlabel"
236}
237
238kci_test_rtnl()
239{
240 kci_add_dummy
241 if [ $ret -ne 0 ];then
242 echo "FAIL: cannot add dummy interface"
243 return 1
244 fi
245
246 kci_test_polrouting
247 kci_test_route_get
248 kci_test_tc
249 kci_test_gre
250 kci_test_bridge
251 kci_test_addrlabel
252
253 kci_del_dummy
254}
255
256#check for needed privileges
257if [ "$(id -u)" -ne 0 ];then
258 echo "SKIP: Need root privileges"
259 exit 0
260fi
261
262for x in ip tc;do
263 $x -Version 2>/dev/null >/dev/null
264 if [ $? -ne 0 ];then
265 echo "SKIP: Could not run test without the $x tool"
266 exit 0
267 fi
268done
269
270kci_test_rtnl
271
272exit $ret
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..92fb8ee917c5 100644
--- a/tools/testing/selftests/networking/timestamping/Makefile
+++ b/tools/testing/selftests/networking/timestamping/Makefile
@@ -1,4 +1,6 @@
1TEST_PROGS := hwtstamp_config timestamping txtimestamp 1CFLAGS += -I../../../../../usr/include
2
3TEST_PROGS := hwtstamp_config rxtimestamp timestamping txtimestamp
2 4
3all: $(TEST_PROGS) 5all: $(TEST_PROGS)
4 6
diff --git a/tools/testing/selftests/networking/timestamping/rxtimestamp.c b/tools/testing/selftests/networking/timestamping/rxtimestamp.c
new file mode 100644
index 000000000000..00f286661dcd
--- /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/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/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile
index fe6bc60dfc60..8932263e5a74 100644
--- a/tools/testing/selftests/powerpc/ptrace/Makefile
+++ b/tools/testing/selftests/powerpc/ptrace/Makefile
@@ -6,7 +6,7 @@ include ../../lib.mk
6 6
7all: $(TEST_PROGS) 7all: $(TEST_PROGS)
8 8
9CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm 9CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm -fno-pie
10 10
11$(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h 11$(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h
12 12
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..bceb53f57573 100644
--- a/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
+++ b/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
@@ -8,7 +8,7 @@ message:
8 .section ".toc" 8 .section ".toc"
9 .balign 8 9 .balign 8
10pattern: 10pattern:
11 .llong 0x5555AAAA5555AAAA 11 .8byte 0x5555AAAA5555AAAA
12 12
13 .text 13 .text
14FUNC_START(_start) 14FUNC_START(_start)
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 958c11c14acd..7bfcd454fb2a 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -15,6 +15,7 @@ $(OUTPUT)/tm-syscall: tm-syscall-asm.S
15$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include 15$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include
16$(OUTPUT)/tm-tmspr: CFLAGS += -pthread 16$(OUTPUT)/tm-tmspr: CFLAGS += -pthread
17$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64 17$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64
18$(OUTPUT)/tm-resched-dscr: ../pmu/lib.o
18 19
19SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS)) 20SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS))
20$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S 21$(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..a7ac2e4c60d9 100644
--- a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
@@ -30,6 +30,7 @@
30 30
31#include "utils.h" 31#include "utils.h"
32#include "tm.h" 32#include "tm.h"
33#include "../pmu/lib.h"
33 34
34#define SPRN_DSCR 0x03 35#define SPRN_DSCR 0x03
35 36
@@ -75,8 +76,6 @@ int test_body(void)
75 ); 76 );
76 assert(rv); /* make sure the transaction aborted */ 77 assert(rv); /* make sure the transaction aborted */
77 if ((texasr >> 56) != TM_CAUSE_RESCHED) { 78 if ((texasr >> 56) != TM_CAUSE_RESCHED) {
78 putchar('.');
79 fflush(stdout);
80 continue; 79 continue;
81 } 80 }
82 if (dscr2 != dscr1) { 81 if (dscr2 != dscr1) {
@@ -89,7 +88,12 @@ int test_body(void)
89 } 88 }
90} 89}
91 90
92int main(void) 91static int tm_resched_dscr(void)
93{ 92{
94 return test_harness(test_body, "tm_resched_dscr"); 93 return eat_cpu(test_body);
94}
95
96int main(int argc, const char *argv[])
97{
98 return test_harness(tm_resched_dscr, "tm_resched_dscr");
95} 99}
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/ptp/Makefile b/tools/testing/selftests/ptp/Makefile
index 83dd42b2129e..d4064c742c26 100644
--- a/tools/testing/selftests/ptp/Makefile
+++ b/tools/testing/selftests/ptp/Makefile
@@ -1,3 +1,4 @@
1CFLAGS += -I../../../../usr/include/
1TEST_PROGS := testptp 2TEST_PROGS := testptp
2LDLIBS += -lrt 3LDLIBS += -lrt
3all: $(TEST_PROGS) 4all: $(TEST_PROGS)
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..49fa51726ce3
--- /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=/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/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..46752c164676 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=/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..0af36a721b9c 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
@@ -40,7 +40,7 @@
40 40
41T=/tmp/kvm-test-1-run.sh.$$ 41T=/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..b55895fb10ed 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -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
@@ -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/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/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 73f5ea6778ce..4d6f92a9df6b 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -107,7 +107,7 @@ TEST(mode_strict_support)
107 ASSERT_EQ(0, ret) { 107 ASSERT_EQ(0, ret) {
108 TH_LOG("Kernel does not support CONFIG_SECCOMP"); 108 TH_LOG("Kernel does not support CONFIG_SECCOMP");
109 } 109 }
110 syscall(__NR_exit, 1); 110 syscall(__NR_exit, 0);
111} 111}
112 112
113TEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL) 113TEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL)
diff --git a/tools/testing/selftests/sigaltstack/sas.c b/tools/testing/selftests/sigaltstack/sas.c
index ccd07343d418..7d406c3973ba 100644
--- a/tools/testing/selftests/sigaltstack/sas.c
+++ b/tools/testing/selftests/sigaltstack/sas.c
@@ -17,6 +17,8 @@
17#include <assert.h> 17#include <assert.h>
18#include <errno.h> 18#include <errno.h>
19 19
20#include "../kselftest.h"
21
20#ifndef SS_AUTODISARM 22#ifndef SS_AUTODISARM
21#define SS_AUTODISARM (1U << 31) 23#define SS_AUTODISARM (1U << 31)
22#endif 24#endif
@@ -41,8 +43,7 @@ void my_usr1(int sig, siginfo_t *si, void *u)
41 43
42 if (sp < (unsigned long)sstack || 44 if (sp < (unsigned long)sstack ||
43 sp >= (unsigned long)sstack + SIGSTKSZ) { 45 sp >= (unsigned long)sstack + SIGSTKSZ) {
44 printf("[FAIL]\tSP is not on sigaltstack\n"); 46 ksft_exit_fail_msg("SP is not on sigaltstack\n");
45 exit(EXIT_FAILURE);
46 } 47 }
47 /* put some data on stack. other sighandler will try to overwrite it */ 48 /* put some data on stack. other sighandler will try to overwrite it */
48 aa = alloca(1024); 49 aa = alloca(1024);
@@ -50,21 +51,22 @@ void my_usr1(int sig, siginfo_t *si, void *u)
50 p = (struct stk_data *)(aa + 512); 51 p = (struct stk_data *)(aa + 512);
51 strcpy(p->msg, msg); 52 strcpy(p->msg, msg);
52 p->flag = 1; 53 p->flag = 1;
53 printf("[RUN]\tsignal USR1\n"); 54 ksft_print_msg("[RUN]\tsignal USR1\n");
54 err = sigaltstack(NULL, &stk); 55 err = sigaltstack(NULL, &stk);
55 if (err) { 56 if (err) {
56 perror("[FAIL]\tsigaltstack()"); 57 ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
57 exit(EXIT_FAILURE); 58 exit(EXIT_FAILURE);
58 } 59 }
59 if (stk.ss_flags != SS_DISABLE) 60 if (stk.ss_flags != SS_DISABLE)
60 printf("[FAIL]\tss_flags=%x, should be SS_DISABLE\n", 61 ksft_test_result_fail("tss_flags=%x, should be SS_DISABLE\n",
61 stk.ss_flags); 62 stk.ss_flags);
62 else 63 else
63 printf("[OK]\tsigaltstack is disabled in sighandler\n"); 64 ksft_test_result_pass(
65 "sigaltstack is disabled in sighandler\n");
64 swapcontext(&sc, &uc); 66 swapcontext(&sc, &uc);
65 printf("%s\n", p->msg); 67 ksft_print_msg("%s\n", p->msg);
66 if (!p->flag) { 68 if (!p->flag) {
67 printf("[RUN]\tAborting\n"); 69 ksft_exit_skip("[RUN]\tAborting\n");
68 exit(EXIT_FAILURE); 70 exit(EXIT_FAILURE);
69 } 71 }
70} 72}
@@ -74,13 +76,13 @@ void my_usr2(int sig, siginfo_t *si, void *u)
74 char *aa; 76 char *aa;
75 struct stk_data *p; 77 struct stk_data *p;
76 78
77 printf("[RUN]\tsignal USR2\n"); 79 ksft_print_msg("[RUN]\tsignal USR2\n");
78 aa = alloca(1024); 80 aa = alloca(1024);
79 /* dont run valgrind on this */ 81 /* dont run valgrind on this */
80 /* try to find the data stored by previous sighandler */ 82 /* try to find the data stored by previous sighandler */
81 p = memmem(aa, 1024, msg, strlen(msg)); 83 p = memmem(aa, 1024, msg, strlen(msg));
82 if (p) { 84 if (p) {
83 printf("[FAIL]\tsigaltstack re-used\n"); 85 ksft_test_result_fail("sigaltstack re-used\n");
84 /* corrupt the data */ 86 /* corrupt the data */
85 strcpy(p->msg, msg2); 87 strcpy(p->msg, msg2);
86 /* tell other sighandler that his data is corrupted */ 88 /* tell other sighandler that his data is corrupted */
@@ -90,7 +92,7 @@ void my_usr2(int sig, siginfo_t *si, void *u)
90 92
91static void switch_fn(void) 93static void switch_fn(void)
92{ 94{
93 printf("[RUN]\tswitched to user ctx\n"); 95 ksft_print_msg("[RUN]\tswitched to user ctx\n");
94 raise(SIGUSR2); 96 raise(SIGUSR2);
95 setcontext(&sc); 97 setcontext(&sc);
96} 98}
@@ -101,6 +103,8 @@ int main(void)
101 stack_t stk; 103 stack_t stk;
102 int err; 104 int err;
103 105
106 ksft_print_header();
107
104 sigemptyset(&act.sa_mask); 108 sigemptyset(&act.sa_mask);
105 act.sa_flags = SA_ONSTACK | SA_SIGINFO; 109 act.sa_flags = SA_ONSTACK | SA_SIGINFO;
106 act.sa_sigaction = my_usr1; 110 act.sa_sigaction = my_usr1;
@@ -110,19 +114,20 @@ int main(void)
110 sstack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, 114 sstack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
111 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); 115 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
112 if (sstack == MAP_FAILED) { 116 if (sstack == MAP_FAILED) {
113 perror("mmap()"); 117 ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));
114 return EXIT_FAILURE; 118 return EXIT_FAILURE;
115 } 119 }
116 120
117 err = sigaltstack(NULL, &stk); 121 err = sigaltstack(NULL, &stk);
118 if (err) { 122 if (err) {
119 perror("[FAIL]\tsigaltstack()"); 123 ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
120 exit(EXIT_FAILURE); 124 exit(EXIT_FAILURE);
121 } 125 }
122 if (stk.ss_flags == SS_DISABLE) { 126 if (stk.ss_flags == SS_DISABLE) {
123 printf("[OK]\tInitial sigaltstack state was SS_DISABLE\n"); 127 ksft_test_result_pass(
128 "Initial sigaltstack state was SS_DISABLE\n");
124 } else { 129 } else {
125 printf("[FAIL]\tInitial sigaltstack state was %x; " 130 ksft_exit_fail_msg("Initial sigaltstack state was %x; "
126 "should have been SS_DISABLE\n", stk.ss_flags); 131 "should have been SS_DISABLE\n", stk.ss_flags);
127 return EXIT_FAILURE; 132 return EXIT_FAILURE;
128 } 133 }
@@ -133,7 +138,8 @@ int main(void)
133 err = sigaltstack(&stk, NULL); 138 err = sigaltstack(&stk, NULL);
134 if (err) { 139 if (err) {
135 if (errno == EINVAL) { 140 if (errno == EINVAL) {
136 printf("[NOTE]\tThe running kernel doesn't support SS_AUTODISARM\n"); 141 ksft_exit_skip(
142 "[NOTE]\tThe running kernel doesn't support SS_AUTODISARM\n");
137 /* 143 /*
138 * If test cases for the !SS_AUTODISARM variant were 144 * If test cases for the !SS_AUTODISARM variant were
139 * added, we could still run them. We don't have any 145 * added, we could still run them. We don't have any
@@ -142,7 +148,9 @@ int main(void)
142 */ 148 */
143 return 0; 149 return 0;
144 } else { 150 } else {
145 perror("[FAIL]\tsigaltstack(SS_ONSTACK | SS_AUTODISARM)"); 151 ksft_exit_fail_msg(
152 "sigaltstack(SS_ONSTACK | SS_AUTODISARM) %s\n",
153 strerror(errno));
146 return EXIT_FAILURE; 154 return EXIT_FAILURE;
147 } 155 }
148 } 156 }
@@ -150,7 +158,7 @@ int main(void)
150 ustack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, 158 ustack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
151 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); 159 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
152 if (ustack == MAP_FAILED) { 160 if (ustack == MAP_FAILED) {
153 perror("mmap()"); 161 ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));
154 return EXIT_FAILURE; 162 return EXIT_FAILURE;
155 } 163 }
156 getcontext(&uc); 164 getcontext(&uc);
@@ -162,16 +170,17 @@ int main(void)
162 170
163 err = sigaltstack(NULL, &stk); 171 err = sigaltstack(NULL, &stk);
164 if (err) { 172 if (err) {
165 perror("[FAIL]\tsigaltstack()"); 173 ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
166 exit(EXIT_FAILURE); 174 exit(EXIT_FAILURE);
167 } 175 }
168 if (stk.ss_flags != SS_AUTODISARM) { 176 if (stk.ss_flags != SS_AUTODISARM) {
169 printf("[FAIL]\tss_flags=%x, should be SS_AUTODISARM\n", 177 ksft_exit_fail_msg("ss_flags=%x, should be SS_AUTODISARM\n",
170 stk.ss_flags); 178 stk.ss_flags);
171 exit(EXIT_FAILURE); 179 exit(EXIT_FAILURE);
172 } 180 }
173 printf("[OK]\tsigaltstack is still SS_AUTODISARM after signal\n"); 181 ksft_test_result_pass(
182 "sigaltstack is still SS_AUTODISARM after signal\n");
174 183
175 printf("[OK]\tTest passed\n"); 184 ksft_exit_pass();
176 return 0; 185 return 0;
177} 186}
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..7e1187e007fa 100644
--- a/tools/testing/selftests/splice/Makefile
+++ b/tools/testing/selftests/splice/Makefile
@@ -1,7 +1,4 @@
1TEST_PROGS := default_file_splice_read.sh 1TEST_PROGS := default_file_splice_read.sh
2EXTRA := default_file_splice_read 2TEST_GEN_PROGS_EXTENDED := default_file_splice_read
3all: $(TEST_PROGS) $(EXTRA)
4 3
5include ../lib.mk 4include ../lib.mk
6
7EXTRA_CLEAN := $(EXTRA)
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/tc-tests/actions/tests.json b/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
index af519bc97a8e..6973bdc5b5bf 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
@@ -1111,5 +1111,55 @@
1111 "teardown": [ 1111 "teardown": [
1112 "$TC actions flush action gact" 1112 "$TC actions flush action gact"
1113 ] 1113 ]
1114 },
1115 {
1116 "id": "a568",
1117 "name": "Add action with ife type",
1118 "category": [
1119 "actions",
1120 "ife"
1121 ],
1122 "setup": [
1123 [
1124 "$TC actions flush action ife",
1125 0,
1126 1,
1127 255
1128 ],
1129 "$TC actions add action ife encode type 0xDEAD index 1"
1130 ],
1131 "cmdUnderTest": "$TC actions get action ife index 1",
1132 "expExitCode": "0",
1133 "verifyCmd": "$TC actions get action ife index 1",
1134 "matchPattern": "type 0xDEAD",
1135 "matchCount": "1",
1136 "teardown": [
1137 "$TC actions flush action ife"
1138 ]
1139 },
1140 {
1141 "id": "b983",
1142 "name": "Add action without ife type",
1143 "category": [
1144 "actions",
1145 "ife"
1146 ],
1147 "setup": [
1148 [
1149 "$TC actions flush action ife",
1150 0,
1151 1,
1152 255
1153 ],
1154 "$TC actions add action ife encode index 1"
1155 ],
1156 "cmdUnderTest": "$TC actions get action ife index 1",
1157 "expExitCode": "0",
1158 "verifyCmd": "$TC actions get action ife index 1",
1159 "matchPattern": "type 0xED3E",
1160 "matchCount": "1",
1161 "teardown": [
1162 "$TC actions flush action ife"
1163 ]
1114 } 1164 }
1115] \ No newline at end of file 1165] \ No newline at end of file
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile
index a9b86133b9b3..ae4593115408 100644
--- a/tools/testing/selftests/timers/Makefile
+++ b/tools/testing/selftests/timers/Makefile
@@ -1,5 +1,4 @@
1BUILD_FLAGS = -DKTEST 1CFLAGS += -O3 -Wl,-no-as-needed -Wall
2CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS)
3LDFLAGS += -lrt -lpthread -lm 2LDFLAGS += -lrt -lpthread -lm
4 3
5# these are all "safe" tests that don't modify 4# these are all "safe" tests that don't modify
@@ -7,9 +6,11 @@ LDFLAGS += -lrt -lpthread -lm
7TEST_GEN_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \ 6TEST_GEN_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
8 inconsistency-check raw_skew threadtest rtctest 7 inconsistency-check raw_skew threadtest rtctest
9 8
10TEST_GEN_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \ 9DESTRUCTIVE_TESTS = alarmtimer-suspend valid-adjtimex adjtick change_skew \
11 skew_consistency clocksource-switch freq-step leap-a-day \ 10 skew_consistency clocksource-switch freq-step leap-a-day \
12 leapcrash set-tai set-2038 set-tz rtctest_setdate 11 leapcrash set-tai set-2038 set-tz
12
13TEST_GEN_PROGS_EXTENDED = $(DESTRUCTIVE_TESTS) rtctest_setdate
13 14
14 15
15include ../lib.mk 16include ../lib.mk
@@ -18,16 +19,4 @@ include ../lib.mk
18# and may modify the system time or trigger 19# and may modify the system time or trigger
19# other behavior like suspend 20# other behavior like suspend
20run_destructive_tests: run_tests 21run_destructive_tests: run_tests
21 ./alarmtimer-suspend 22 $(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..9c92b7bd5641 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,8 +134,9 @@ 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)) {
@@ -158,32 +157,97 @@ int do_timer(int clock_id, int flags)
158 its1.it_value.tv_sec = TIMER_SECS; 157 its1.it_value.tv_sec = TIMER_SECS;
159 its1.it_value.tv_nsec = 0; 158 its1.it_value.tv_nsec = 0;
160 } 159 }
161 its1.it_interval.tv_sec = TIMER_SECS; 160 its1.it_interval.tv_sec = interval;
162 its1.it_interval.tv_nsec = 0; 161 its1.it_interval.tv_nsec = 0;
163 162
164 err = timer_settime(tm1, flags, &its1, &its2); 163 err = timer_settime(*tm1, flags, &its1, &its2);
165 if (err) { 164 if (err) {
166 printf("%s - timer_settime() failed\n", clockstring(clock_id)); 165 printf("%s - timer_settime() failed\n", clockstring(clock_id));
167 return -1; 166 return -1;
168 } 167 }
169 168
170 while (alarmcount < 5) 169 return 0;
171 sleep(1); 170}
172 171
173 printf("%-22s %s max latency: %10lld ns : ", 172int check_timer_latency(int flags, int interval)
174 clockstring(clock_id), 173{
175 flags ? "ABSTIME":"RELTIME", 174 int err = 0;
176 max_latency_ns); 175
176 describe_timer(flags, interval);
177 printf("timer fired early: %7d : ", timer_fired_early);
178 if (!timer_fired_early) {
179 printf("[OK]\n");
180 } else {
181 printf("[FAILED]\n");
182 err = -1;
183 }
184
185 describe_timer(flags, interval);
186 printf("max latency: %10lld ns : ", max_latency_ns);
177 187
178 timer_delete(tm1);
179 if (max_latency_ns < UNRESONABLE_LATENCY) { 188 if (max_latency_ns < UNRESONABLE_LATENCY) {
180 printf("[OK]\n"); 189 printf("[OK]\n");
190 } else {
191 printf("[FAILED]\n");
192 err = -1;
193 }
194 return err;
195}
196
197int check_alarmcount(int flags, int interval)
198{
199 describe_timer(flags, interval);
200 printf("count: %19d : ", alarmcount);
201 if (alarmcount == 1) {
202 printf("[OK]\n");
181 return 0; 203 return 0;
182 } 204 }
183 printf("[FAILED]\n"); 205 printf("[FAILED]\n");
184 return -1; 206 return -1;
185} 207}
186 208
209int do_timer(int clock_id, int flags)
210{
211 timer_t tm1;
212 const int interval = TIMER_SECS;
213 int err;
214
215 err = setup_timer(clock_id, flags, interval, &tm1);
216 if (err)
217 return err;
218
219 while (alarmcount < 5)
220 sleep(1);
221
222 timer_delete(tm1);
223 return check_timer_latency(flags, interval);
224}
225
226int do_timer_oneshot(int clock_id, int flags)
227{
228 timer_t tm1;
229 const int interval = 0;
230 struct timeval timeout;
231 fd_set fds;
232 int err;
233
234 err = setup_timer(clock_id, flags, interval, &tm1);
235 if (err)
236 return err;
237
238 memset(&timeout, 0, sizeof(timeout));
239 timeout.tv_sec = 5;
240 FD_ZERO(&fds);
241 do {
242 err = select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
243 } while (err == -1 && errno == EINTR);
244
245 timer_delete(tm1);
246 err = check_timer_latency(flags, interval);
247 err |= check_alarmcount(flags, interval);
248 return err;
249}
250
187int main(void) 251int main(void)
188{ 252{
189 struct sigaction act; 253 struct sigaction act;
@@ -209,6 +273,8 @@ int main(void)
209 273
210 ret |= do_timer(clock_id, TIMER_ABSTIME); 274 ret |= do_timer(clock_id, TIMER_ABSTIME);
211 ret |= do_timer(clock_id, 0); 275 ret |= do_timer(clock_id, 0);
276 ret |= do_timer_oneshot(clock_id, TIMER_ABSTIME);
277 ret |= do_timer_oneshot(clock_id, 0);
212 } 278 }
213 if (ret) 279 if (ret)
214 return ksft_exit_fail(); 280 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/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c
index 1eae79ae5b4e..a2c53a3d223d 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,6 +380,23 @@ static void *locking_thread(void *arg)
331 return NULL; 380 return NULL;
332} 381}
333 382
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
334static int copy_page(int ufd, unsigned long offset) 400static int copy_page(int ufd, unsigned long offset)
335{ 401{
336 struct uffdio_copy uffdio_copy; 402 struct uffdio_copy uffdio_copy;
@@ -351,8 +417,13 @@ 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) {
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
@@ -408,6 +479,7 @@ static void *uffd_poll_thread(void *arg)
408 userfaults++; 479 userfaults++;
409 break; 480 break;
410 case UFFD_EVENT_FORK: 481 case UFFD_EVENT_FORK:
482 close(uffd);
411 uffd = msg.arg.fork.ufd; 483 uffd = msg.arg.fork.ufd;
412 pollfd[0].fd = uffd; 484 pollfd[0].fd = uffd;
413 break; 485 break;
@@ -572,6 +644,17 @@ static int userfaultfd_open(int features)
572 return 0; 644 return 0;
573} 645}
574 646
647sigjmp_buf jbuf, *sigbuf;
648
649static void sighndl(int sig, siginfo_t *siginfo, void *ptr)
650{
651 if (sig == SIGBUS) {
652 if (sigbuf)
653 siglongjmp(*sigbuf, 1);
654 abort();
655 }
656}
657
575/* 658/*
576 * For non-cooperative userfaultfd test we fork() a process that will 659 * For non-cooperative userfaultfd test we fork() a process that will
577 * generate pagefaults, will mremap the area monitored by the 660 * generate pagefaults, will mremap the area monitored by the
@@ -585,19 +668,59 @@ static int userfaultfd_open(int features)
585 * The release of the pages currently generates event for shmem and 668 * The release of the pages currently generates event for shmem and
586 * anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked 669 * anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked
587 * for hugetlb. 670 * for hugetlb.
671 * For signal test(UFFD_FEATURE_SIGBUS), signal_test = 1, we register
672 * monitored area, generate pagefaults and test that signal is delivered.
673 * Use UFFDIO_COPY to allocate missing page and retry. For signal_test = 2
674 * test robustness use case - we release monitored area, fork a process
675 * that will generate pagefaults and verify signal is generated.
676 * This also tests UFFD_FEATURE_EVENT_FORK event along with the signal
677 * feature. Using monitor thread, verify no userfault events are generated.
588 */ 678 */
589static int faulting_process(void) 679static int faulting_process(int signal_test)
590{ 680{
591 unsigned long nr; 681 unsigned long nr;
592 unsigned long long count; 682 unsigned long long count;
593 unsigned long split_nr_pages; 683 unsigned long split_nr_pages;
684 unsigned long lastnr;
685 struct sigaction act;
686 unsigned long signalled = 0;
594 687
595 if (test_type != TEST_HUGETLB) 688 if (test_type != TEST_HUGETLB)
596 split_nr_pages = (nr_pages + 1) / 2; 689 split_nr_pages = (nr_pages + 1) / 2;
597 else 690 else
598 split_nr_pages = nr_pages; 691 split_nr_pages = nr_pages;
599 692
693 if (signal_test) {
694 sigbuf = &jbuf;
695 memset(&act, 0, sizeof(act));
696 act.sa_sigaction = sighndl;
697 act.sa_flags = SA_SIGINFO;
698 if (sigaction(SIGBUS, &act, 0)) {
699 perror("sigaction");
700 return 1;
701 }
702 lastnr = (unsigned long)-1;
703 }
704
600 for (nr = 0; nr < split_nr_pages; nr++) { 705 for (nr = 0; nr < split_nr_pages; nr++) {
706 if (signal_test) {
707 if (sigsetjmp(*sigbuf, 1) != 0) {
708 if (nr == lastnr) {
709 fprintf(stderr, "Signal repeated\n");
710 return 1;
711 }
712
713 lastnr = nr;
714 if (signal_test == 1) {
715 if (copy_page(uffd, nr * page_size))
716 signalled++;
717 } else {
718 signalled++;
719 continue;
720 }
721 }
722 }
723
601 count = *area_count(area_dst, nr); 724 count = *area_count(area_dst, nr);
602 if (count != count_verify[nr]) { 725 if (count != count_verify[nr]) {
603 fprintf(stderr, 726 fprintf(stderr,
@@ -607,6 +730,9 @@ static int faulting_process(void)
607 } 730 }
608 } 731 }
609 732
733 if (signal_test)
734 return signalled != split_nr_pages;
735
610 if (test_type == TEST_HUGETLB) 736 if (test_type == TEST_HUGETLB)
611 return 0; 737 return 0;
612 738
@@ -636,6 +762,23 @@ static int faulting_process(void)
636 return 0; 762 return 0;
637} 763}
638 764
765static void retry_uffdio_zeropage(int ufd,
766 struct uffdio_zeropage *uffdio_zeropage,
767 unsigned long offset)
768{
769 uffd_test_ops->alias_mapping(&uffdio_zeropage->range.start,
770 uffdio_zeropage->range.len,
771 offset);
772 if (ioctl(ufd, UFFDIO_ZEROPAGE, uffdio_zeropage)) {
773 if (uffdio_zeropage->zeropage != -EEXIST)
774 fprintf(stderr, "UFFDIO_ZEROPAGE retry error %Ld\n",
775 uffdio_zeropage->zeropage), exit(1);
776 } else {
777 fprintf(stderr, "UFFDIO_ZEROPAGE retry unexpected %Ld\n",
778 uffdio_zeropage->zeropage), exit(1);
779 }
780}
781
639static int uffdio_zeropage(int ufd, unsigned long offset) 782static int uffdio_zeropage(int ufd, unsigned long offset)
640{ 783{
641 struct uffdio_zeropage uffdio_zeropage; 784 struct uffdio_zeropage uffdio_zeropage;
@@ -670,8 +813,14 @@ static int uffdio_zeropage(int ufd, unsigned long offset)
670 if (uffdio_zeropage.zeropage != page_size) { 813 if (uffdio_zeropage.zeropage != page_size) {
671 fprintf(stderr, "UFFDIO_ZEROPAGE unexpected %Ld\n", 814 fprintf(stderr, "UFFDIO_ZEROPAGE unexpected %Ld\n",
672 uffdio_zeropage.zeropage), exit(1); 815 uffdio_zeropage.zeropage), exit(1);
673 } else 816 } else {
817 if (test_uffdio_zeropage_eexist) {
818 test_uffdio_zeropage_eexist = false;
819 retry_uffdio_zeropage(ufd, &uffdio_zeropage,
820 offset);
821 }
674 return 1; 822 return 1;
823 }
675 } else { 824 } else {
676 fprintf(stderr, 825 fprintf(stderr,
677 "UFFDIO_ZEROPAGE succeeded %Ld\n", 826 "UFFDIO_ZEROPAGE succeeded %Ld\n",
@@ -761,7 +910,7 @@ static int userfaultfd_events_test(void)
761 perror("fork"), exit(1); 910 perror("fork"), exit(1);
762 911
763 if (!pid) 912 if (!pid)
764 return faulting_process(); 913 return faulting_process(0);
765 914
766 waitpid(pid, &err, 0); 915 waitpid(pid, &err, 0);
767 if (err) 916 if (err)
@@ -778,6 +927,72 @@ static int userfaultfd_events_test(void)
778 return userfaults != nr_pages; 927 return userfaults != nr_pages;
779} 928}
780 929
930static int userfaultfd_sig_test(void)
931{
932 struct uffdio_register uffdio_register;
933 unsigned long expected_ioctls;
934 unsigned long userfaults;
935 pthread_t uffd_mon;
936 int err, features;
937 pid_t pid;
938 char c;
939
940 printf("testing signal delivery: ");
941 fflush(stdout);
942
943 if (uffd_test_ops->release_pages(area_dst))
944 return 1;
945
946 features = UFFD_FEATURE_EVENT_FORK|UFFD_FEATURE_SIGBUS;
947 if (userfaultfd_open(features) < 0)
948 return 1;
949 fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
950
951 uffdio_register.range.start = (unsigned long) area_dst;
952 uffdio_register.range.len = nr_pages * page_size;
953 uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
954 if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
955 fprintf(stderr, "register failure\n"), exit(1);
956
957 expected_ioctls = uffd_test_ops->expected_ioctls;
958 if ((uffdio_register.ioctls & expected_ioctls) !=
959 expected_ioctls)
960 fprintf(stderr,
961 "unexpected missing ioctl for anon memory\n"),
962 exit(1);
963
964 if (faulting_process(1))
965 fprintf(stderr, "faulting process failed\n"), exit(1);
966
967 if (uffd_test_ops->release_pages(area_dst))
968 return 1;
969
970 if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, NULL))
971 perror("uffd_poll_thread create"), exit(1);
972
973 pid = fork();
974 if (pid < 0)
975 perror("fork"), exit(1);
976
977 if (!pid)
978 exit(faulting_process(2));
979
980 waitpid(pid, &err, 0);
981 if (err)
982 fprintf(stderr, "faulting process failed\n"), exit(1);
983
984 if (write(pipefd[1], &c, sizeof(c)) != sizeof(c))
985 perror("pipe write"), exit(1);
986 if (pthread_join(uffd_mon, (void **)&userfaults))
987 return 1;
988
989 printf("done.\n");
990 if (userfaults)
991 fprintf(stderr, "Signal test failed, userfaults: %ld\n",
992 userfaults);
993 close(uffd);
994 return userfaults != 0;
995}
781static int userfaultfd_stress(void) 996static int userfaultfd_stress(void)
782{ 997{
783 void *area; 998 void *area;
@@ -879,6 +1094,15 @@ static int userfaultfd_stress(void)
879 return 1; 1094 return 1;
880 } 1095 }
881 1096
1097 if (area_dst_alias) {
1098 uffdio_register.range.start = (unsigned long)
1099 area_dst_alias;
1100 if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) {
1101 fprintf(stderr, "register failure alias\n");
1102 return 1;
1103 }
1104 }
1105
882 /* 1106 /*
883 * The madvise done previously isn't enough: some 1107 * The madvise done previously isn't enough: some
884 * uffd_thread could have read userfaults (one of 1108 * uffd_thread could have read userfaults (one of
@@ -912,9 +1136,17 @@ static int userfaultfd_stress(void)
912 1136
913 /* unregister */ 1137 /* unregister */
914 if (ioctl(uffd, UFFDIO_UNREGISTER, &uffdio_register.range)) { 1138 if (ioctl(uffd, UFFDIO_UNREGISTER, &uffdio_register.range)) {
915 fprintf(stderr, "register failure\n"); 1139 fprintf(stderr, "unregister failure\n");
916 return 1; 1140 return 1;
917 } 1141 }
1142 if (area_dst_alias) {
1143 uffdio_register.range.start = (unsigned long) area_dst;
1144 if (ioctl(uffd, UFFDIO_UNREGISTER,
1145 &uffdio_register.range)) {
1146 fprintf(stderr, "unregister failure alias\n");
1147 return 1;
1148 }
1149 }
918 1150
919 /* verification */ 1151 /* verification */
920 if (bounces & BOUNCE_VERIFY) { 1152 if (bounces & BOUNCE_VERIFY) {
@@ -936,6 +1168,10 @@ static int userfaultfd_stress(void)
936 area_src = area_dst; 1168 area_src = area_dst;
937 area_dst = tmp_area; 1169 area_dst = tmp_area;
938 1170
1171 tmp_area = area_src_alias;
1172 area_src_alias = area_dst_alias;
1173 area_dst_alias = tmp_area;
1174
939 printf("userfaults:"); 1175 printf("userfaults:");
940 for (cpu = 0; cpu < nr_cpus; cpu++) 1176 for (cpu = 0; cpu < nr_cpus; cpu++)
941 printf(" %lu", userfaults[cpu]); 1177 printf(" %lu", userfaults[cpu]);
@@ -946,7 +1182,8 @@ static int userfaultfd_stress(void)
946 return err; 1182 return err;
947 1183
948 close(uffd); 1184 close(uffd);
949 return userfaultfd_zeropage_test() || userfaultfd_events_test(); 1185 return userfaultfd_zeropage_test() || userfaultfd_sig_test()
1186 || userfaultfd_events_test();
950} 1187}
951 1188
952/* 1189/*
@@ -981,7 +1218,12 @@ static void set_test_type(const char *type)
981 } else if (!strcmp(type, "hugetlb")) { 1218 } else if (!strcmp(type, "hugetlb")) {
982 test_type = TEST_HUGETLB; 1219 test_type = TEST_HUGETLB;
983 uffd_test_ops = &hugetlb_uffd_test_ops; 1220 uffd_test_ops = &hugetlb_uffd_test_ops;
1221 } else if (!strcmp(type, "hugetlb_shared")) {
1222 map_shared = true;
1223 test_type = TEST_HUGETLB;
1224 uffd_test_ops = &hugetlb_uffd_test_ops;
984 } else if (!strcmp(type, "shmem")) { 1225 } else if (!strcmp(type, "shmem")) {
1226 map_shared = true;
985 test_type = TEST_SHMEM; 1227 test_type = TEST_SHMEM;
986 uffd_test_ops = &shmem_uffd_test_ops; 1228 uffd_test_ops = &shmem_uffd_test_ops;
987 } else { 1229 } else {
@@ -1001,12 +1243,25 @@ static void set_test_type(const char *type)
1001 fprintf(stderr, "Impossible to run this test\n"), exit(2); 1243 fprintf(stderr, "Impossible to run this test\n"), exit(2);
1002} 1244}
1003 1245
1246static void sigalrm(int sig)
1247{
1248 if (sig != SIGALRM)
1249 abort();
1250 test_uffdio_copy_eexist = true;
1251 test_uffdio_zeropage_eexist = true;
1252 alarm(ALARM_INTERVAL_SECS);
1253}
1254
1004int main(int argc, char **argv) 1255int main(int argc, char **argv)
1005{ 1256{
1006 if (argc < 4) 1257 if (argc < 4)
1007 fprintf(stderr, "Usage: <test type> <MiB> <bounces> [hugetlbfs_file]\n"), 1258 fprintf(stderr, "Usage: <test type> <MiB> <bounces> [hugetlbfs_file]\n"),
1008 exit(1); 1259 exit(1);
1009 1260
1261 if (signal(SIGALRM, sigalrm) == SIG_ERR)
1262 fprintf(stderr, "failed to arm SIGALRM"), exit(1);
1263 alarm(ALARM_INTERVAL_SECS);
1264
1010 set_test_type(argv[1]); 1265 set_test_type(argv[1]);
1011 1266
1012 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 1267 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
diff --git a/tools/testing/selftests/watchdog/watchdog-test.c b/tools/testing/selftests/watchdog/watchdog-test.c
index a74c9d739d07..a1391be2dc1e 100644
--- a/tools/testing/selftests/watchdog/watchdog-test.c
+++ b/tools/testing/selftests/watchdog/watchdog-test.c
@@ -9,12 +9,25 @@
9#include <unistd.h> 9#include <unistd.h>
10#include <fcntl.h> 10#include <fcntl.h>
11#include <signal.h> 11#include <signal.h>
12#include <getopt.h>
12#include <sys/ioctl.h> 13#include <sys/ioctl.h>
13#include <linux/types.h> 14#include <linux/types.h>
14#include <linux/watchdog.h> 15#include <linux/watchdog.h>
15 16
17#define DEFAULT_PING_RATE 1
18
16int fd; 19int fd;
17const char v = 'V'; 20const char v = 'V';
21static const char sopts[] = "bdehp:t:";
22static const struct option lopts[] = {
23 {"bootstatus", no_argument, NULL, 'b'},
24 {"disable", no_argument, NULL, 'd'},
25 {"enable", no_argument, NULL, 'e'},
26 {"help", no_argument, NULL, 'h'},
27 {"pingrate", required_argument, NULL, 'p'},
28 {"timeout", required_argument, NULL, 't'},
29 {NULL, no_argument, NULL, 0x0}
30};
18 31
19/* 32/*
20 * This function simply sends an IOCTL to the driver, which in turn ticks 33 * This function simply sends an IOCTL to the driver, which in turn ticks
@@ -23,12 +36,12 @@ const char v = 'V';
23 */ 36 */
24static void keep_alive(void) 37static void keep_alive(void)
25{ 38{
26 int dummy; 39 int dummy;
27 int ret; 40 int ret;
28 41
29 ret = ioctl(fd, WDIOC_KEEPALIVE, &dummy); 42 ret = ioctl(fd, WDIOC_KEEPALIVE, &dummy);
30 if (!ret) 43 if (!ret)
31 printf("."); 44 printf(".");
32} 45}
33 46
34/* 47/*
@@ -38,75 +51,110 @@ static void keep_alive(void)
38 51
39static void term(int sig) 52static void term(int sig)
40{ 53{
41 int ret = write(fd, &v, 1); 54 int ret = write(fd, &v, 1);
42 55
43 close(fd); 56 close(fd);
44 if (ret < 0) 57 if (ret < 0)
45 printf("\nStopping watchdog ticks failed (%d)...\n", errno); 58 printf("\nStopping watchdog ticks failed (%d)...\n", errno);
46 else 59 else
47 printf("\nStopping watchdog ticks...\n"); 60 printf("\nStopping watchdog ticks...\n");
48 exit(0); 61 exit(0);
62}
63
64static void usage(char *progname)
65{
66 printf("Usage: %s [options]\n", progname);
67 printf(" -b, --bootstatus Get last boot status (Watchdog/POR)\n");
68 printf(" -d, --disable Turn off the watchdog timer\n");
69 printf(" -e, --enable Turn on the watchdog timer\n");
70 printf(" -h, --help Print the help message\n");
71 printf(" -p, --pingrate=P Set ping rate to P seconds (default %d)\n", DEFAULT_PING_RATE);
72 printf(" -t, --timeout=T Set timeout to T seconds\n");
73 printf("\n");
74 printf("Parameters are parsed left-to-right in real-time.\n");
75 printf("Example: %s -d -t 10 -p 5 -e\n", progname);
49} 76}
50 77
51int main(int argc, char *argv[]) 78int main(int argc, char *argv[])
52{ 79{
53 int flags; 80 int flags;
54 unsigned int ping_rate = 1; 81 unsigned int ping_rate = DEFAULT_PING_RATE;
55 int ret; 82 int ret;
56 int i; 83 int c;
57 84 int oneshot = 0;
58 setbuf(stdout, NULL); 85
59 86 setbuf(stdout, NULL);
60 fd = open("/dev/watchdog", O_WRONLY); 87
61 88 fd = open("/dev/watchdog", O_WRONLY);
62 if (fd == -1) { 89
63 printf("Watchdog device not enabled.\n"); 90 if (fd == -1) {
64 exit(-1); 91 printf("Watchdog device not enabled.\n");
65 } 92 exit(-1);
66 93 }
67 for (i = 1; i < argc; i++) { 94
68 if (!strncasecmp(argv[i], "-d", 2)) { 95 while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
69 flags = WDIOS_DISABLECARD; 96 switch (c) {
70 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags); 97 case 'b':
71 if (!ret) 98 flags = 0;
72 printf("Watchdog card disabled.\n"); 99 oneshot = 1;
73 } else if (!strncasecmp(argv[i], "-e", 2)) { 100 ret = ioctl(fd, WDIOC_GETBOOTSTATUS, &flags);
74 flags = WDIOS_ENABLECARD; 101 if (!ret)
75 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags); 102 printf("Last boot is caused by: %s.\n", (flags != 0) ?
76 if (!ret) 103 "Watchdog" : "Power-On-Reset");
77 printf("Watchdog card enabled.\n"); 104 else
78 } else if (!strncasecmp(argv[i], "-t", 2) && argv[2]) { 105 printf("WDIOC_GETBOOTSTATUS errno '%s'\n", strerror(errno));
79 flags = atoi(argv[i + 1]); 106 break;
80 ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags); 107 case 'd':
81 if (!ret) 108 flags = WDIOS_DISABLECARD;
82 printf("Watchdog timeout set to %u seconds.\n", flags); 109 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
83 i++; 110 if (!ret)
84 } else if (!strncasecmp(argv[i], "-p", 2) && argv[2]) { 111 printf("Watchdog card disabled.\n");
85 ping_rate = strtoul(argv[i + 1], NULL, 0); 112 else
86 printf("Watchdog ping rate set to %u seconds.\n", ping_rate); 113 printf("WDIOS_DISABLECARD errno '%s'\n", strerror(errno));
87 i++; 114 break;
88 } else { 115 case 'e':
89 printf("-d to disable, -e to enable, -t <n> to set " 116 flags = WDIOS_ENABLECARD;
90 "the timeout,\n-p <n> to set the ping rate, and "); 117 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
91 printf("run by itself to tick the card.\n"); 118 if (!ret)
92 printf("Parameters are parsed left-to-right in real-time.\n"); 119 printf("Watchdog card enabled.\n");
93 printf("Example: %s -d -t 10 -p 5 -e\n", argv[0]); 120 else
94 goto end; 121 printf("WDIOS_ENABLECARD errno '%s'\n", strerror(errno));
95 } 122 break;
96 } 123 case 'p':
97 124 ping_rate = strtoul(optarg, NULL, 0);
98 printf("Watchdog Ticking Away!\n"); 125 if (!ping_rate)
99 126 ping_rate = DEFAULT_PING_RATE;
100 signal(SIGINT, term); 127 printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
101 128 break;
102 while(1) { 129 case 't':
103 keep_alive(); 130 flags = strtoul(optarg, NULL, 0);
104 sleep(ping_rate); 131 ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags);
105 } 132 if (!ret)
133 printf("Watchdog timeout set to %u seconds.\n", flags);
134 else
135 printf("WDIOC_SETTIMEOUT errno '%s'\n", strerror(errno));
136 break;
137 default:
138 usage(argv[0]);
139 goto end;
140 }
141 }
142
143 if (oneshot)
144 goto end;
145
146 printf("Watchdog Ticking Away!\n");
147
148 signal(SIGINT, term);
149
150 while (1) {
151 keep_alive();
152 sleep(ping_rate);
153 }
106end: 154end:
107 ret = write(fd, &v, 1); 155 ret = write(fd, &v, 1);
108 if (ret < 0) 156 if (ret < 0)
109 printf("Stopping watchdog ticks failed (%d)...\n", errno); 157 printf("Stopping watchdog ticks failed (%d)...\n", errno);
110 close(fd); 158 close(fd);
111 return 0; 159 return 0;
112} 160}
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/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/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c
index 3237bc010e1c..23927845518d 100644
--- a/tools/testing/selftests/x86/protection_keys.c
+++ b/tools/testing/selftests/x86/protection_keys.c
@@ -212,19 +212,18 @@ void dump_mem(void *dumpme, int len_bytes)
212 } 212 }
213} 213}
214 214
215#define __SI_FAULT (3 << 16) 215#define SEGV_BNDERR 3 /* failed address bound checks */
216#define SEGV_BNDERR (__SI_FAULT|3) /* failed address bound checks */ 216#define SEGV_PKUERR 4
217#define SEGV_PKUERR (__SI_FAULT|4)
218 217
219static char *si_code_str(int si_code) 218static char *si_code_str(int si_code)
220{ 219{
221 if (si_code & SEGV_MAPERR) 220 if (si_code == SEGV_MAPERR)
222 return "SEGV_MAPERR"; 221 return "SEGV_MAPERR";
223 if (si_code & SEGV_ACCERR) 222 if (si_code == SEGV_ACCERR)
224 return "SEGV_ACCERR"; 223 return "SEGV_ACCERR";
225 if (si_code & SEGV_BNDERR) 224 if (si_code == SEGV_BNDERR)
226 return "SEGV_BNDERR"; 225 return "SEGV_BNDERR";
227 if (si_code & SEGV_PKUERR) 226 if (si_code == SEGV_PKUERR)
228 return "SEGV_PKUERR"; 227 return "SEGV_PKUERR";
229 return "UNKNOWN"; 228 return "UNKNOWN";
230} 229}
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)