aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2017-03-14 10:07:33 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2017-03-14 10:07:33 -0400
commitb70366e5d31788650b2a5cec5cd13ea80ac7e44a (patch)
treed972ffd190111d699200448494fda333d28b2486 /tools
parentf42e181935d5e5670c87d31ae48063a495bbacae (diff)
parentdb6ccf23e8ba40fc2e8914ec9c0eb950df71d9fe (diff)
Merge tag 'doc-4.11-images' of git://git.lwn.net/linux into drm-misc-next
Pointer for Markus's image conversion work. We need this so we can merge all the pretty drm graphs for 4.12. Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/arch/arm/include/uapi/asm/kvm.h9
-rw-r--r--tools/arch/powerpc/include/uapi/asm/kvm.h5
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h12
-rw-r--r--tools/arch/x86/include/uapi/asm/vmx.h5
-rw-r--r--tools/build/Makefile4
-rw-r--r--tools/build/Makefile.build10
-rw-r--r--tools/build/Makefile.include3
-rw-r--r--tools/gpio/.gitignore4
-rw-r--r--tools/gpio/gpio-hammer.c2
-rw-r--r--tools/iio/iio_event_monitor.c2
-rw-r--r--tools/include/asm-generic/bitops/atomic.h3
-rw-r--r--tools/include/asm/bug.h8
-rw-r--r--tools/include/linux/bitmap.h1
-rw-r--r--tools/include/linux/bitops.h1
-rw-r--r--tools/include/linux/compiler-gcc.h14
-rw-r--r--tools/include/linux/compiler.h13
-rw-r--r--tools/include/linux/log2.h13
-rw-r--r--tools/include/linux/spinlock.h5
-rw-r--r--tools/include/uapi/linux/bpf.h30
-rw-r--r--tools/leds/Makefile4
-rw-r--r--tools/leds/led_hw_brightness_mon.c84
-rw-r--r--tools/lib/api/Makefile8
-rw-r--r--tools/lib/api/fs/fs.c16
-rw-r--r--tools/lib/api/fs/fs.h1
-rw-r--r--tools/lib/api/fs/tracing_path.c32
-rw-r--r--tools/lib/bpf/bpf.c24
-rw-r--r--tools/lib/bpf/bpf.h16
-rw-r--r--tools/lib/bpf/libbpf.c264
-rw-r--r--tools/lib/bpf/libbpf.h19
-rw-r--r--tools/lib/find_bit.c2
-rw-r--r--tools/lib/subcmd/Makefile8
-rw-r--r--tools/lib/subcmd/parse-options.c4
-rw-r--r--tools/lib/subcmd/parse-options.h19
-rw-r--r--tools/lib/traceevent/Makefile14
-rw-r--r--tools/lib/traceevent/event-parse.c38
-rw-r--r--tools/lib/traceevent/event-parse.h3
-rw-r--r--tools/lib/traceevent/kbuffer-parse.c1
-rw-r--r--tools/lib/traceevent/plugin_function.c2
-rw-r--r--tools/objtool/arch.h5
-rw-r--r--tools/objtool/arch/x86/decode.c3
-rw-r--r--tools/objtool/builtin-check.c62
-rw-r--r--tools/perf/Build5
-rw-r--r--tools/perf/Documentation/perf-annotate.txt4
-rw-r--r--tools/perf/Documentation/perf-c2c.txt2
-rw-r--r--tools/perf/Documentation/perf-config.txt12
-rw-r--r--tools/perf/Documentation/perf-diff.txt19
-rw-r--r--tools/perf/Documentation/perf-ftrace.txt36
-rw-r--r--tools/perf/Documentation/perf-kallsyms.txt24
-rw-r--r--tools/perf/Documentation/perf-record.txt16
-rw-r--r--tools/perf/Documentation/perf-report.txt4
-rw-r--r--tools/perf/Documentation/perf-sched.txt2
-rw-r--r--tools/perf/Documentation/perf-script.txt4
-rw-r--r--tools/perf/Documentation/perf-stat.txt2
-rw-r--r--tools/perf/Documentation/perf-trace.txt8
-rw-r--r--tools/perf/Documentation/tips.txt2
-rw-r--r--tools/perf/MANIFEST1
-rw-r--r--tools/perf/Makefile.config17
-rw-r--r--tools/perf/Makefile.perf5
-rw-r--r--tools/perf/arch/arm64/Makefile1
-rw-r--r--tools/perf/arch/arm64/include/dwarf-regs-table.h12
-rw-r--r--tools/perf/arch/arm64/util/dwarf-regs.c15
-rw-r--r--tools/perf/bench/futex-hash.c4
-rw-r--r--tools/perf/bench/futex-lock-pi.c3
-rw-r--r--tools/perf/bench/futex-requeue.c2
-rw-r--r--tools/perf/bench/futex-wake-parallel.c4
-rw-r--r--tools/perf/bench/futex-wake.c3
-rw-r--r--tools/perf/bench/futex.h4
-rw-r--r--tools/perf/bench/numa.c7
-rw-r--r--tools/perf/builtin-annotate.c4
-rw-r--r--tools/perf/builtin-c2c.c3
-rw-r--r--tools/perf/builtin-diff.c92
-rw-r--r--tools/perf/builtin-ftrace.c265
-rw-r--r--tools/perf/builtin-help.c8
-rw-r--r--tools/perf/builtin-kallsyms.c67
-rw-r--r--tools/perf/builtin-kmem.c12
-rw-r--r--tools/perf/builtin-list.c3
-rw-r--r--tools/perf/builtin-mem.c4
-rw-r--r--tools/perf/builtin-probe.c2
-rw-r--r--tools/perf/builtin-record.c185
-rw-r--r--tools/perf/builtin-report.c25
-rw-r--r--tools/perf/builtin-sched.c144
-rw-r--r--tools/perf/builtin-script.c3
-rw-r--r--tools/perf/builtin-stat.c13
-rw-r--r--tools/perf/builtin-top.c10
-rw-r--r--tools/perf/builtin-trace.c126
-rw-r--r--tools/perf/builtin.h2
-rw-r--r--tools/perf/command-list.txt2
-rw-r--r--tools/perf/perf.c20
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/uncore-cache.json317
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/uncore-memory.json83
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/uncore-power.json84
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/uncore-cache.json317
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json28
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/uncore-memory.json83
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/uncore-power.json84
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/uncore-cache.json317
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json28
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/uncore-memory.json83
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/uncore-power.json84
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/uncore-cache.json322
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json46
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/uncore-memory.json75
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json249
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/uncore-cache.json209
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json46
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/uncore-memory.json79
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json248
-rw-r--r--tools/perf/pmu-events/arch/x86/knightslanding/uncore-memory.json42
-rw-r--r--tools/perf/pmu-events/jevents.c84
-rw-r--r--tools/perf/pmu-events/jevents.h4
-rw-r--r--tools/perf/pmu-events/json.c2
-rw-r--r--tools/perf/pmu-events/pmu-events.h3
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/attr.c2
-rw-r--r--tools/perf/tests/bpf.c42
-rw-r--r--tools/perf/tests/builtin-test.c6
-rw-r--r--tools/perf/tests/code-reading.c2
-rw-r--r--tools/perf/tests/fdarray.c2
-rw-r--r--tools/perf/tests/llvm.c4
-rw-r--r--tools/perf/tests/parse-events.c10
-rw-r--r--tools/perf/tests/parse-no-sample-id-all.c19
-rw-r--r--tools/perf/tests/perf-record.c6
-rw-r--r--tools/perf/tests/python-use.c2
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/tests/thread-map.c6
-rw-r--r--tools/perf/tests/topology.c4
-rw-r--r--tools/perf/tests/unit_number__scnprintf.c37
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c2
-rw-r--r--tools/perf/ui/browsers/hists.c60
-rw-r--r--tools/perf/ui/browsers/map.c6
-rw-r--r--tools/perf/ui/hist.c2
-rw-r--r--tools/perf/ui/setup.c1
-rw-r--r--tools/perf/util/Build1
-rw-r--r--tools/perf/util/annotate.c2
-rw-r--r--tools/perf/util/bpf-loader.c4
-rw-r--r--tools/perf/util/callchain.c16
-rw-r--r--tools/perf/util/cgroup.c26
-rw-r--r--tools/perf/util/config.c23
-rw-r--r--tools/perf/util/cpumap.c22
-rw-r--r--tools/perf/util/cpumap.h1
-rw-r--r--tools/perf/util/data-convert-bt.c7
-rw-r--r--tools/perf/util/debug.c17
-rw-r--r--tools/perf/util/debug.h1
-rw-r--r--tools/perf/util/dso.c52
-rw-r--r--tools/perf/util/env.c2
-rw-r--r--tools/perf/util/event.c2
-rw-r--r--tools/perf/util/evlist.c12
-rw-r--r--tools/perf/util/evlist.h2
-rw-r--r--tools/perf/util/evsel.c66
-rw-r--r--tools/perf/util/evsel_fprintf.c1
-rw-r--r--tools/perf/util/header.c40
-rw-r--r--tools/perf/util/hist.c10
-rw-r--r--tools/perf/util/intel-pt-decoder/Build6
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c5
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c2
-rw-r--r--tools/perf/util/intel-pt.c4
-rw-r--r--tools/perf/util/llvm-utils.c4
-rw-r--r--tools/perf/util/machine.c25
-rw-r--r--tools/perf/util/machine.h1
-rw-r--r--tools/perf/util/map.c4
-rw-r--r--tools/perf/util/parse-events.c155
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/parse-events.y49
-rw-r--r--tools/perf/util/pmu.c132
-rw-r--r--tools/perf/util/pmu.h1
-rw-r--r--tools/perf/util/probe-event.c15
-rw-r--r--tools/perf/util/probe-finder.c4
-rw-r--r--tools/perf/util/scripting-engines/Build2
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c11
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c5
-rw-r--r--tools/perf/util/session.c6
-rw-r--r--tools/perf/util/setup.py9
-rw-r--r--tools/perf/util/sort.c8
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/stat.c2
-rw-r--r--tools/perf/util/strfilter.c1
-rw-r--r--tools/perf/util/string.c2
-rw-r--r--tools/perf/util/symbol-elf.c2
-rw-r--r--tools/perf/util/symbol.c6
-rw-r--r--tools/perf/util/symbol_fprintf.c2
-rw-r--r--tools/perf/util/thread_map.c2
-rw-r--r--tools/perf/util/trace-event-info.c71
-rw-r--r--tools/perf/util/trace-event-parse.c17
-rw-r--r--tools/perf/util/trace-event-read.c77
-rw-r--r--tools/perf/util/trace-event.h1
-rw-r--r--tools/perf/util/unwind-libunwind-local.c54
-rw-r--r--tools/perf/util/util.c15
-rw-r--r--tools/perf/util/util.h3
-rw-r--r--tools/power/acpi/common/cmfsize.c2
-rw-r--r--tools/power/acpi/common/getopt.c2
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslinuxtbl.c2
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixdir.c2
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixmap.c2
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixxf.c24
-rw-r--r--tools/power/acpi/tools/acpidump/acpidump.h2
-rw-r--r--tools/power/acpi/tools/acpidump/apdump.c2
-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/utils/cpufreq-info.c21
-rwxr-xr-xtools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py569
-rw-r--r--tools/power/x86/turbostat/turbostat.8253
-rw-r--r--tools/power/x86/turbostat/turbostat.c1880
-rw-r--r--tools/scripts/Makefile.include17
-rwxr-xr-xtools/testing/ktest/ktest.pl111
-rw-r--r--tools/testing/nvdimm/test/nfit.c14
-rw-r--r--tools/testing/radix-tree/.gitignore4
-rw-r--r--tools/testing/radix-tree/Makefile46
-rw-r--r--tools/testing/radix-tree/benchmark.c6
-rw-r--r--tools/testing/radix-tree/generated/autoconf.h2
-rw-r--r--tools/testing/radix-tree/idr-test.c444
-rw-r--r--tools/testing/radix-tree/iteration_check.c2
-rw-r--r--tools/testing/radix-tree/linux.c39
-rw-r--r--tools/testing/radix-tree/linux/bitops.h160
-rw-r--r--tools/testing/radix-tree/linux/bitops/__ffs.h43
-rw-r--r--tools/testing/radix-tree/linux/bitops/ffs.h41
-rw-r--r--tools/testing/radix-tree/linux/bitops/ffz.h12
-rw-r--r--tools/testing/radix-tree/linux/bitops/find.h13
-rw-r--r--tools/testing/radix-tree/linux/bitops/fls.h41
-rw-r--r--tools/testing/radix-tree/linux/bitops/fls64.h14
-rw-r--r--tools/testing/radix-tree/linux/bitops/hweight.h11
-rw-r--r--tools/testing/radix-tree/linux/bitops/le.h53
-rw-r--r--tools/testing/radix-tree/linux/bitops/non-atomic.h110
-rw-r--r--tools/testing/radix-tree/linux/export.h2
-rw-r--r--tools/testing/radix-tree/linux/gfp.h10
-rw-r--r--tools/testing/radix-tree/linux/idr.h1
-rw-r--r--tools/testing/radix-tree/linux/init.h2
-rw-r--r--tools/testing/radix-tree/linux/kernel.h55
-rw-r--r--tools/testing/radix-tree/linux/mempool.h16
-rw-r--r--tools/testing/radix-tree/linux/percpu.h5
-rw-r--r--tools/testing/radix-tree/linux/preempt.h10
-rw-r--r--tools/testing/radix-tree/linux/radix-tree.h25
-rw-r--r--tools/testing/radix-tree/linux/types.h23
-rw-r--r--tools/testing/radix-tree/main.c53
-rw-r--r--tools/testing/radix-tree/multiorder.c39
-rw-r--r--tools/testing/radix-tree/regression1.c4
-rw-r--r--tools/testing/radix-tree/regression2.c10
-rw-r--r--tools/testing/radix-tree/regression3.c28
-rw-r--r--tools/testing/radix-tree/tag_check.c22
-rw-r--r--tools/testing/radix-tree/test.c28
-rw-r--r--tools/testing/radix-tree/test.h2
-rw-r--r--tools/testing/selftests/Makefile39
-rw-r--r--tools/testing/selftests/bpf/.gitignore2
-rw-r--r--tools/testing/selftests/bpf/Makefile23
-rw-r--r--tools/testing/selftests/bpf/bpf_sys.h108
-rw-r--r--tools/testing/selftests/bpf/test_lpm_map.c358
-rw-r--r--tools/testing/selftests/bpf/test_lru_map.c138
-rw-r--r--tools/testing/selftests/bpf/test_maps.c162
-rw-r--r--tools/testing/selftests/bpf/test_tag.c203
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c1633
-rw-r--r--tools/testing/selftests/breakpoints/Makefile10
-rw-r--r--tools/testing/selftests/capabilities/Makefile11
-rw-r--r--tools/testing/selftests/cpufreq/Makefile8
-rwxr-xr-xtools/testing/selftests/cpufreq/cpu.sh84
-rwxr-xr-xtools/testing/selftests/cpufreq/cpufreq.sh241
-rwxr-xr-xtools/testing/selftests/cpufreq/governor.sh153
-rwxr-xr-xtools/testing/selftests/cpufreq/main.sh194
-rwxr-xr-xtools/testing/selftests/cpufreq/module.sh243
-rwxr-xr-xtools/testing/selftests/cpufreq/special-tests.sh115
-rw-r--r--tools/testing/selftests/efivarfs/Makefile8
-rw-r--r--tools/testing/selftests/exec/Makefile32
-rw-r--r--tools/testing/selftests/firmware/Makefile2
-rwxr-xr-xtools/testing/selftests/firmware/fw_fallback.sh224
-rwxr-xr-xtools/testing/selftests/firmware/fw_filesystem.sh25
-rwxr-xr-xtools/testing/selftests/firmware/fw_userhelper.sh99
-rw-r--r--tools/testing/selftests/ftrace/Makefile6
-rw-r--r--tools/testing/selftests/futex/Makefile21
-rw-r--r--tools/testing/selftests/futex/functional/Makefile17
-rw-r--r--tools/testing/selftests/futex/include/logging.h1
-rw-r--r--tools/testing/selftests/gpio/.gitignore1
-rw-r--r--tools/testing/selftests/intel_pstate/Makefile13
-rw-r--r--tools/testing/selftests/intel_pstate/aperf.c2
-rw-r--r--tools/testing/selftests/ipc/.gitignore1
-rw-r--r--tools/testing/selftests/ipc/Makefile7
-rw-r--r--tools/testing/selftests/kcmp/Makefile6
-rw-r--r--tools/testing/selftests/lib.mk40
-rw-r--r--tools/testing/selftests/locking/ww_mutex.sh10
-rw-r--r--tools/testing/selftests/membarrier/Makefile6
-rw-r--r--tools/testing/selftests/memfd/Makefile15
-rw-r--r--tools/testing/selftests/mount/Makefile7
-rw-r--r--tools/testing/selftests/mqueue/Makefile6
-rw-r--r--tools/testing/selftests/net/Makefile15
-rw-r--r--tools/testing/selftests/net/psock_lib.h39
-rw-r--r--tools/testing/selftests/net/psock_tpacket.c97
-rw-r--r--tools/testing/selftests/nsfs/Makefile9
-rw-r--r--tools/testing/selftests/powerpc/Makefile14
-rw-r--r--tools/testing/selftests/powerpc/alignment/Makefile9
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/Makefile17
-rw-r--r--tools/testing/selftests/powerpc/context_switch/Makefile9
-rw-r--r--tools/testing/selftests/powerpc/copyloops/Makefile19
-rw-r--r--tools/testing/selftests/powerpc/dscr/Makefile13
-rw-r--r--tools/testing/selftests/powerpc/math/Makefile29
-rw-r--r--tools/testing/selftests/powerpc/mm/Makefile18
-rw-r--r--tools/testing/selftests/powerpc/pmu/Makefile26
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/Makefile15
-rw-r--r--tools/testing/selftests/powerpc/primitives/Makefile9
-rw-r--r--tools/testing/selftests/powerpc/stringloops/Makefile9
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/Makefile17
-rw-r--r--tools/testing/selftests/powerpc/syscalls/Makefile9
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile18
-rw-r--r--tools/testing/selftests/powerpc/vphn/Makefile10
-rw-r--r--tools/testing/selftests/pstore/Makefile4
-rw-r--r--tools/testing/selftests/ptrace/Makefile8
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/CFLIST1
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/LOCK076
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/LOCK07.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/CFcommon3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TINY011
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TINY023
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE013
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE024
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE033
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE044
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE053
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE063
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE073
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE084
-rw-r--r--tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt33
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/.gitignore1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/Makefile16
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/delay.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/export.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/mutex.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/percpu.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/preempt.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/rcupdate.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/sched.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/smp.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/workqueue.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/uapi/linux/types.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/.gitignore1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/kconfig.h1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h155
-rwxr-xr-xtools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk375
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/assume.h16
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/barriers.h41
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/bug_on.h13
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/combined_source.c13
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/config.h27
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/include_srcu.c31
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/int_typedefs.h33
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/locks.h220
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.c11
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.h58
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/percpu.h92
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.c78
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h58
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/simple_sync_srcu.c50
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/workqueues.h102
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/.gitignore1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/Makefile11
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/assert_end.fail1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force.fail1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force2.fail1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force3.fail1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/main.pass0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/test.c72
-rwxr-xr-xtools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/test_script.sh102
-rw-r--r--tools/testing/selftests/seccomp/Makefile6
-rw-r--r--tools/testing/selftests/sigaltstack/Makefile5
-rw-r--r--tools/testing/selftests/sigaltstack/sas.c7
-rw-r--r--tools/testing/selftests/size/Makefile10
-rw-r--r--tools/testing/selftests/splice/Makefile8
-rw-r--r--tools/testing/selftests/splice/default_file_splice_read.c8
-rwxr-xr-xtools/testing/selftests/splice/default_file_splice_read.sh7
-rw-r--r--tools/testing/selftests/timers/Makefile10
-rw-r--r--tools/testing/selftests/vm/Makefile50
-rwxr-xr-xtools/testing/selftests/vm/run_vmtests24
-rw-r--r--tools/testing/selftests/vm/userfaultfd.c484
-rw-r--r--tools/testing/selftests/x86/Makefile21
-rw-r--r--tools/testing/selftests/x86/ioperm.c170
-rw-r--r--tools/testing/selftests/x86/protection_keys.c19
-rw-r--r--tools/testing/selftests/x86/sysret_rip.c195
-rw-r--r--tools/testing/selftests/zram/Makefile3
-rw-r--r--tools/usb/ffs-test.c52
-rw-r--r--tools/usb/usbip/README57
-rwxr-xr-xtools/usb/usbip/vudc/vudc_server_example.sh107
-rw-r--r--tools/vm/Makefile8
377 files changed, 15159 insertions, 2846 deletions
diff --git a/tools/arch/arm/include/uapi/asm/kvm.h b/tools/arch/arm/include/uapi/asm/kvm.h
index a2b3eb313a25..af05f8e0903e 100644
--- a/tools/arch/arm/include/uapi/asm/kvm.h
+++ b/tools/arch/arm/include/uapi/asm/kvm.h
@@ -84,6 +84,15 @@ struct kvm_regs {
84#define KVM_VGIC_V2_DIST_SIZE 0x1000 84#define KVM_VGIC_V2_DIST_SIZE 0x1000
85#define KVM_VGIC_V2_CPU_SIZE 0x2000 85#define KVM_VGIC_V2_CPU_SIZE 0x2000
86 86
87/* Supported VGICv3 address types */
88#define KVM_VGIC_V3_ADDR_TYPE_DIST 2
89#define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
90#define KVM_VGIC_ITS_ADDR_TYPE 4
91
92#define KVM_VGIC_V3_DIST_SIZE SZ_64K
93#define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
94#define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
95
87#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ 96#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
88#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */ 97#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
89 98
diff --git a/tools/arch/powerpc/include/uapi/asm/kvm.h b/tools/arch/powerpc/include/uapi/asm/kvm.h
index c93cf35ce379..3603b6f51b11 100644
--- a/tools/arch/powerpc/include/uapi/asm/kvm.h
+++ b/tools/arch/powerpc/include/uapi/asm/kvm.h
@@ -573,6 +573,10 @@ struct kvm_get_htab_header {
573#define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba) 573#define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
574#define KVM_REG_PPC_DBSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbb) 574#define KVM_REG_PPC_DBSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbb)
575 575
576/* POWER9 registers */
577#define KVM_REG_PPC_TIDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbc)
578#define KVM_REG_PPC_PSSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd)
579
576/* Transactional Memory checkpointed state: 580/* Transactional Memory checkpointed state:
577 * This is all GPRs, all VSX regs and a subset of SPRs 581 * This is all GPRs, all VSX regs and a subset of SPRs
578 */ 582 */
@@ -596,6 +600,7 @@ struct kvm_get_htab_header {
596#define KVM_REG_PPC_TM_VSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U32 | 0x67) 600#define KVM_REG_PPC_TM_VSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U32 | 0x67)
597#define KVM_REG_PPC_TM_DSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x68) 601#define KVM_REG_PPC_TM_DSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x68)
598#define KVM_REG_PPC_TM_TAR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x69) 602#define KVM_REG_PPC_TM_TAR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x69)
603#define KVM_REG_PPC_TM_XER (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x6a)
599 604
600/* PPC64 eXternal Interrupt Controller Specification */ 605/* PPC64 eXternal Interrupt Controller Specification */
601#define KVM_DEV_XICS_GRP_SOURCES 1 /* 64-bit source attributes */ 606#define KVM_DEV_XICS_GRP_SOURCES 1 /* 64-bit source attributes */
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index cddd5d06e1cb..293149a1c6a1 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -105,6 +105,7 @@
105#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */ 105#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */
106#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */ 106#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */
107#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */ 107#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */
108#define X86_FEATURE_TSC_KNOWN_FREQ ( 3*32+31) /* TSC has known frequency */
108 109
109/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ 110/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
110#define X86_FEATURE_XMM3 ( 4*32+ 0) /* "pni" SSE-3 */ 111#define X86_FEATURE_XMM3 ( 4*32+ 0) /* "pni" SSE-3 */
@@ -188,10 +189,14 @@
188 189
189#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */ 190#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */
190#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ 191#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
192#define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation Technology L3 */
193#define X86_FEATURE_CAT_L2 ( 7*32+ 5) /* Cache Allocation Technology L2 */
194#define X86_FEATURE_CDP_L3 ( 7*32+ 6) /* Code and Data Prioritization L3 */
191 195
192#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */ 196#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */
193#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ 197#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
194 198
199#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */
195#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */ 200#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */
196#define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */ 201#define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */
197#define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */ 202#define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */
@@ -220,11 +225,13 @@
220#define X86_FEATURE_RTM ( 9*32+11) /* Restricted Transactional Memory */ 225#define X86_FEATURE_RTM ( 9*32+11) /* Restricted Transactional Memory */
221#define X86_FEATURE_CQM ( 9*32+12) /* Cache QoS Monitoring */ 226#define X86_FEATURE_CQM ( 9*32+12) /* Cache QoS Monitoring */
222#define X86_FEATURE_MPX ( 9*32+14) /* Memory Protection Extension */ 227#define X86_FEATURE_MPX ( 9*32+14) /* Memory Protection Extension */
228#define X86_FEATURE_RDT_A ( 9*32+15) /* Resource Director Technology Allocation */
223#define X86_FEATURE_AVX512F ( 9*32+16) /* AVX-512 Foundation */ 229#define X86_FEATURE_AVX512F ( 9*32+16) /* AVX-512 Foundation */
224#define X86_FEATURE_AVX512DQ ( 9*32+17) /* AVX-512 DQ (Double/Quad granular) Instructions */ 230#define X86_FEATURE_AVX512DQ ( 9*32+17) /* AVX-512 DQ (Double/Quad granular) Instructions */
225#define X86_FEATURE_RDSEED ( 9*32+18) /* The RDSEED instruction */ 231#define X86_FEATURE_RDSEED ( 9*32+18) /* The RDSEED instruction */
226#define X86_FEATURE_ADX ( 9*32+19) /* The ADCX and ADOX instructions */ 232#define X86_FEATURE_ADX ( 9*32+19) /* The ADCX and ADOX instructions */
227#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */ 233#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */
234#define X86_FEATURE_AVX512IFMA ( 9*32+21) /* AVX-512 Integer Fused Multiply-Add instructions */
228#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */ 235#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
229#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */ 236#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */
230#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */ 237#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */
@@ -278,8 +285,11 @@
278#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */ 285#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */
279 286
280/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */ 287/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
288#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
281#define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */ 289#define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */
282#define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */ 290#define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */
291#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */
292#define X86_FEATURE_RDPID (16*32+ 22) /* RDPID instruction */
283 293
284/* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */ 294/* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */
285#define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */ 295#define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */
@@ -310,4 +320,6 @@
310#define X86_BUG_NULL_SEG X86_BUG(10) /* Nulling a selector preserves the base */ 320#define X86_BUG_NULL_SEG X86_BUG(10) /* Nulling a selector preserves the base */
311#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */ 321#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */
312#define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */ 322#define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */
323#define X86_BUG_AMD_E400 X86_BUG(13) /* CPU is among the affected by Erratum 400 */
324
313#endif /* _ASM_X86_CPUFEATURES_H */ 325#endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/tools/arch/x86/include/uapi/asm/vmx.h b/tools/arch/x86/include/uapi/asm/vmx.h
index 37fee272618f..14458658e988 100644
--- a/tools/arch/x86/include/uapi/asm/vmx.h
+++ b/tools/arch/x86/include/uapi/asm/vmx.h
@@ -65,6 +65,8 @@
65#define EXIT_REASON_TPR_BELOW_THRESHOLD 43 65#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
66#define EXIT_REASON_APIC_ACCESS 44 66#define EXIT_REASON_APIC_ACCESS 44
67#define EXIT_REASON_EOI_INDUCED 45 67#define EXIT_REASON_EOI_INDUCED 45
68#define EXIT_REASON_GDTR_IDTR 46
69#define EXIT_REASON_LDTR_TR 47
68#define EXIT_REASON_EPT_VIOLATION 48 70#define EXIT_REASON_EPT_VIOLATION 48
69#define EXIT_REASON_EPT_MISCONFIG 49 71#define EXIT_REASON_EPT_MISCONFIG 49
70#define EXIT_REASON_INVEPT 50 72#define EXIT_REASON_INVEPT 50
@@ -113,6 +115,8 @@
113 { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \ 115 { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
114 { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \ 116 { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
115 { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \ 117 { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
118 { EXIT_REASON_GDTR_IDTR, "GDTR_IDTR" }, \
119 { EXIT_REASON_LDTR_TR, "LDTR_TR" }, \
116 { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \ 120 { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
117 { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \ 121 { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
118 { EXIT_REASON_INVEPT, "INVEPT" }, \ 122 { EXIT_REASON_INVEPT, "INVEPT" }, \
@@ -129,6 +133,7 @@
129 { EXIT_REASON_XRSTORS, "XRSTORS" } 133 { EXIT_REASON_XRSTORS, "XRSTORS" }
130 134
131#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1 135#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1
136#define VMX_ABORT_LOAD_HOST_PDPTE_FAIL 2
132#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4 137#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4
133 138
134#endif /* _UAPIVMX_H */ 139#endif /* _UAPIVMX_H */
diff --git a/tools/build/Makefile b/tools/build/Makefile
index aaf7ed329a45..477f00eda591 100644
--- a/tools/build/Makefile
+++ b/tools/build/Makefile
@@ -35,8 +35,8 @@ all: $(OUTPUT)fixdep
35 35
36clean: 36clean:
37 $(call QUIET_CLEAN, fixdep) 37 $(call QUIET_CLEAN, fixdep)
38 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 38 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
39 $(Q)rm -f fixdep 39 $(Q)rm -f $(OUTPUT)fixdep
40 40
41$(OUTPUT)fixdep-in.o: FORCE 41$(OUTPUT)fixdep-in.o: FORCE
42 $(Q)$(MAKE) $(build)=fixdep 42 $(Q)$(MAKE) $(build)=fixdep
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
index 99c0ccd2f176..e279a71c650d 100644
--- a/tools/build/Makefile.build
+++ b/tools/build/Makefile.build
@@ -19,6 +19,16 @@ else
19 Q=@ 19 Q=@
20endif 20endif
21 21
22ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4
23ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)
24 quiet=silent_
25endif
26else # make-3.8x
27ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
28 quiet=silent_
29endif
30endif
31
22build-dir := $(srctree)/tools/build 32build-dir := $(srctree)/tools/build
23 33
24# Define $(fixdep) for dep-cmd function 34# Define $(fixdep) for dep-cmd function
diff --git a/tools/build/Makefile.include b/tools/build/Makefile.include
index ad22e4e7bc59..d360f39a445b 100644
--- a/tools/build/Makefile.include
+++ b/tools/build/Makefile.include
@@ -3,4 +3,7 @@ build := -f $(srctree)/tools/build/Makefile.build dir=. obj
3fixdep: 3fixdep:
4 $(Q)$(MAKE) -C $(srctree)/tools/build CFLAGS= LDFLAGS= $(OUTPUT)fixdep 4 $(Q)$(MAKE) -C $(srctree)/tools/build CFLAGS= LDFLAGS= $(OUTPUT)fixdep
5 5
6fixdep-clean:
7 $(Q)$(MAKE) -C $(srctree)/tools/build clean
8
6.PHONY: fixdep 9.PHONY: fixdep
diff --git a/tools/gpio/.gitignore b/tools/gpio/.gitignore
new file mode 100644
index 000000000000..9e9dd4b681b2
--- /dev/null
+++ b/tools/gpio/.gitignore
@@ -0,0 +1,4 @@
1gpio-event-mon
2gpio-hammer
3lsgpio
4
diff --git a/tools/gpio/gpio-hammer.c b/tools/gpio/gpio-hammer.c
index f1eab587dfea..4bcb234c0fca 100644
--- a/tools/gpio/gpio-hammer.c
+++ b/tools/gpio/gpio-hammer.c
@@ -38,7 +38,7 @@ int hammer_device(const char *device_name, unsigned int *lines, int nlines,
38 memset(&data.values, 0, sizeof(data.values)); 38 memset(&data.values, 0, sizeof(data.values));
39 ret = gpiotools_request_linehandle(device_name, lines, nlines, 39 ret = gpiotools_request_linehandle(device_name, lines, nlines,
40 GPIOHANDLE_REQUEST_OUTPUT, &data, 40 GPIOHANDLE_REQUEST_OUTPUT, &data,
41 "gpio-hammler"); 41 "gpio-hammer");
42 if (ret < 0) 42 if (ret < 0)
43 goto exit_error; 43 goto exit_error;
44 else 44 else
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
index d9b7e0f306c6..b61245e1181d 100644
--- a/tools/iio/iio_event_monitor.c
+++ b/tools/iio/iio_event_monitor.c
@@ -57,6 +57,7 @@ static const char * const iio_chan_type_name_spec[] = {
57 [IIO_RESISTANCE] = "resistance", 57 [IIO_RESISTANCE] = "resistance",
58 [IIO_PH] = "ph", 58 [IIO_PH] = "ph",
59 [IIO_UVINDEX] = "uvindex", 59 [IIO_UVINDEX] = "uvindex",
60 [IIO_GRAVITY] = "gravity",
60}; 61};
61 62
62static const char * const iio_ev_type_text[] = { 63static const char * const iio_ev_type_text[] = {
@@ -149,6 +150,7 @@ static bool event_is_known(struct iio_event_data *event)
149 case IIO_RESISTANCE: 150 case IIO_RESISTANCE:
150 case IIO_PH: 151 case IIO_PH:
151 case IIO_UVINDEX: 152 case IIO_UVINDEX:
153 case IIO_GRAVITY:
152 break; 154 break;
153 default: 155 default:
154 return false; 156 return false;
diff --git a/tools/include/asm-generic/bitops/atomic.h b/tools/include/asm-generic/bitops/atomic.h
index 18663f59d72f..68b8c1516c5a 100644
--- a/tools/include/asm-generic/bitops/atomic.h
+++ b/tools/include/asm-generic/bitops/atomic.h
@@ -20,4 +20,7 @@ static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
20 (((unsigned long *)addr)[nr / __BITS_PER_LONG])) != 0; 20 (((unsigned long *)addr)[nr / __BITS_PER_LONG])) != 0;
21} 21}
22 22
23#define __set_bit(nr, addr) set_bit(nr, addr)
24#define __clear_bit(nr, addr) clear_bit(nr, addr)
25
23#endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_ */ 26#endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_ */
diff --git a/tools/include/asm/bug.h b/tools/include/asm/bug.h
index beda1a884b50..4790f047a89c 100644
--- a/tools/include/asm/bug.h
+++ b/tools/include/asm/bug.h
@@ -12,6 +12,14 @@
12 unlikely(__ret_warn_on); \ 12 unlikely(__ret_warn_on); \
13}) 13})
14 14
15#define WARN_ON(condition) ({ \
16 int __ret_warn_on = !!(condition); \
17 if (unlikely(__ret_warn_on)) \
18 __WARN_printf("assertion failed at %s:%d\n", \
19 __FILE__, __LINE__); \
20 unlikely(__ret_warn_on); \
21})
22
15#define WARN_ON_ONCE(condition) ({ \ 23#define WARN_ON_ONCE(condition) ({ \
16 static int __warned; \ 24 static int __warned; \
17 int __ret_warn_once = !!(condition); \ 25 int __ret_warn_once = !!(condition); \
diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index eef41d500e9e..e8b9f518e36b 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -4,6 +4,7 @@
4#include <string.h> 4#include <string.h>
5#include <linux/bitops.h> 5#include <linux/bitops.h>
6#include <stdlib.h> 6#include <stdlib.h>
7#include <linux/kernel.h>
7 8
8#define DECLARE_BITMAP(name,bits) \ 9#define DECLARE_BITMAP(name,bits) \
9 unsigned long name[BITS_TO_LONGS(bits)] 10 unsigned long name[BITS_TO_LONGS(bits)]
diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h
index fc446343ff41..1aecad369af5 100644
--- a/tools/include/linux/bitops.h
+++ b/tools/include/linux/bitops.h
@@ -2,7 +2,6 @@
2#define _TOOLS_LINUX_BITOPS_H_ 2#define _TOOLS_LINUX_BITOPS_H_
3 3
4#include <asm/types.h> 4#include <asm/types.h>
5#include <linux/kernel.h>
6#include <linux/compiler.h> 5#include <linux/compiler.h>
7 6
8#ifndef __WORDSIZE 7#ifndef __WORDSIZE
diff --git a/tools/include/linux/compiler-gcc.h b/tools/include/linux/compiler-gcc.h
new file mode 100644
index 000000000000..48af2f10a42d
--- /dev/null
+++ b/tools/include/linux/compiler-gcc.h
@@ -0,0 +1,14 @@
1#ifndef _TOOLS_LINUX_COMPILER_H_
2#error "Please don't include <linux/compiler-gcc.h> directly, include <linux/compiler.h> instead."
3#endif
4
5/*
6 * Common definitions for all gcc versions go here.
7 */
8#define GCC_VERSION (__GNUC__ * 10000 \
9 + __GNUC_MINOR__ * 100 \
10 + __GNUC_PATCHLEVEL__)
11
12#if GCC_VERSION >= 70000 && !defined(__CHECKER__)
13# define __fallthrough __attribute__ ((fallthrough))
14#endif
diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index e33fc1df3935..8de163b17c0d 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -1,6 +1,10 @@
1#ifndef _TOOLS_LINUX_COMPILER_H_ 1#ifndef _TOOLS_LINUX_COMPILER_H_
2#define _TOOLS_LINUX_COMPILER_H_ 2#define _TOOLS_LINUX_COMPILER_H_
3 3
4#ifdef __GNUC__
5#include <linux/compiler-gcc.h>
6#endif
7
4/* Optimization barrier */ 8/* Optimization barrier */
5/* The "volatile" is due to gcc bugs */ 9/* The "volatile" is due to gcc bugs */
6#define barrier() __asm__ __volatile__("": : :"memory") 10#define barrier() __asm__ __volatile__("": : :"memory")
@@ -21,6 +25,8 @@
21#endif 25#endif
22 26
23#define __user 27#define __user
28#define __rcu
29#define __read_mostly
24 30
25#ifndef __attribute_const__ 31#ifndef __attribute_const__
26# define __attribute_const__ 32# define __attribute_const__
@@ -50,6 +56,8 @@
50# define unlikely(x) __builtin_expect(!!(x), 0) 56# define unlikely(x) __builtin_expect(!!(x), 0)
51#endif 57#endif
52 58
59#define uninitialized_var(x) x = *(&(x))
60
53#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) 61#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
54 62
55#include <linux/types.h> 63#include <linux/types.h>
@@ -126,4 +134,9 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
126#define WRITE_ONCE(x, val) \ 134#define WRITE_ONCE(x, val) \
127 ({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; }) 135 ({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
128 136
137
138#ifndef __fallthrough
139# define __fallthrough
140#endif
141
129#endif /* _TOOLS_LINUX_COMPILER_H */ 142#endif /* _TOOLS_LINUX_COMPILER_H */
diff --git a/tools/include/linux/log2.h b/tools/include/linux/log2.h
index 41446668ccce..d5677d39c1e4 100644
--- a/tools/include/linux/log2.h
+++ b/tools/include/linux/log2.h
@@ -13,12 +13,6 @@
13#define _TOOLS_LINUX_LOG2_H 13#define _TOOLS_LINUX_LOG2_H
14 14
15/* 15/*
16 * deal with unrepresentable constant logarithms
17 */
18extern __attribute__((const, noreturn))
19int ____ilog2_NaN(void);
20
21/*
22 * non-constant log of base 2 calculators 16 * non-constant log of base 2 calculators
23 * - the arch may override these in asm/bitops.h if they can be implemented 17 * - the arch may override these in asm/bitops.h if they can be implemented
24 * more efficiently than using fls() and fls64() 18 * more efficiently than using fls() and fls64()
@@ -78,7 +72,7 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
78#define ilog2(n) \ 72#define ilog2(n) \
79( \ 73( \
80 __builtin_constant_p(n) ? ( \ 74 __builtin_constant_p(n) ? ( \
81 (n) < 1 ? ____ilog2_NaN() : \ 75 (n) < 2 ? 0 : \
82 (n) & (1ULL << 63) ? 63 : \ 76 (n) & (1ULL << 63) ? 63 : \
83 (n) & (1ULL << 62) ? 62 : \ 77 (n) & (1ULL << 62) ? 62 : \
84 (n) & (1ULL << 61) ? 61 : \ 78 (n) & (1ULL << 61) ? 61 : \
@@ -141,10 +135,7 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
141 (n) & (1ULL << 4) ? 4 : \ 135 (n) & (1ULL << 4) ? 4 : \
142 (n) & (1ULL << 3) ? 3 : \ 136 (n) & (1ULL << 3) ? 3 : \
143 (n) & (1ULL << 2) ? 2 : \ 137 (n) & (1ULL << 2) ? 2 : \
144 (n) & (1ULL << 1) ? 1 : \ 138 1 ) : \
145 (n) & (1ULL << 0) ? 0 : \
146 ____ilog2_NaN() \
147 ) : \
148 (sizeof(n) <= 4) ? \ 139 (sizeof(n) <= 4) ? \
149 __ilog2_u32(n) : \ 140 __ilog2_u32(n) : \
150 __ilog2_u64(n) \ 141 __ilog2_u64(n) \
diff --git a/tools/include/linux/spinlock.h b/tools/include/linux/spinlock.h
new file mode 100644
index 000000000000..58397dcb19d6
--- /dev/null
+++ b/tools/include/linux/spinlock.h
@@ -0,0 +1,5 @@
1#define spinlock_t pthread_mutex_t
2#define DEFINE_SPINLOCK(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER;
3
4#define spin_lock_irqsave(x, f) (void)f, pthread_mutex_lock(x)
5#define spin_unlock_irqrestore(x, f) (void)f, pthread_mutex_unlock(x)
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 0eb0e87dbe9f..0539a0ceef38 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -63,6 +63,12 @@ struct bpf_insn {
63 __s32 imm; /* signed immediate constant */ 63 __s32 imm; /* signed immediate constant */
64}; 64};
65 65
66/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */
67struct bpf_lpm_trie_key {
68 __u32 prefixlen; /* up to 32 for AF_INET, 128 for AF_INET6 */
69 __u8 data[0]; /* Arbitrary size */
70};
71
66/* BPF syscall commands, see bpf(2) man-page for details. */ 72/* BPF syscall commands, see bpf(2) man-page for details. */
67enum bpf_cmd { 73enum bpf_cmd {
68 BPF_MAP_CREATE, 74 BPF_MAP_CREATE,
@@ -89,6 +95,7 @@ enum bpf_map_type {
89 BPF_MAP_TYPE_CGROUP_ARRAY, 95 BPF_MAP_TYPE_CGROUP_ARRAY,
90 BPF_MAP_TYPE_LRU_HASH, 96 BPF_MAP_TYPE_LRU_HASH,
91 BPF_MAP_TYPE_LRU_PERCPU_HASH, 97 BPF_MAP_TYPE_LRU_PERCPU_HASH,
98 BPF_MAP_TYPE_LPM_TRIE,
92}; 99};
93 100
94enum bpf_prog_type { 101enum bpf_prog_type {
@@ -116,6 +123,12 @@ enum bpf_attach_type {
116 123
117#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE 124#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
118 125
126/* If BPF_F_ALLOW_OVERRIDE flag is used in BPF_PROG_ATTACH command
127 * to the given target_fd cgroup the descendent cgroup will be able to
128 * override effective bpf program that was inherited from this cgroup
129 */
130#define BPF_F_ALLOW_OVERRIDE (1U << 0)
131
119#define BPF_PSEUDO_MAP_FD 1 132#define BPF_PSEUDO_MAP_FD 1
120 133
121/* flags for BPF_MAP_UPDATE_ELEM command */ 134/* flags for BPF_MAP_UPDATE_ELEM command */
@@ -171,6 +184,7 @@ union bpf_attr {
171 __u32 target_fd; /* container object to attach to */ 184 __u32 target_fd; /* container object to attach to */
172 __u32 attach_bpf_fd; /* eBPF program to attach */ 185 __u32 attach_bpf_fd; /* eBPF program to attach */
173 __u32 attach_type; 186 __u32 attach_type;
187 __u32 attach_flags;
174 }; 188 };
175} __attribute__((aligned(8))); 189} __attribute__((aligned(8)));
176 190
@@ -430,6 +444,18 @@ union bpf_attr {
430 * @xdp_md: pointer to xdp_md 444 * @xdp_md: pointer to xdp_md
431 * @delta: An positive/negative integer to be added to xdp_md.data 445 * @delta: An positive/negative integer to be added to xdp_md.data
432 * Return: 0 on success or negative on error 446 * Return: 0 on success or negative on error
447 *
448 * int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr)
449 * Copy a NUL terminated string from unsafe address. In case the string
450 * length is smaller than size, the target is not padded with further NUL
451 * bytes. In case the string length is larger than size, just count-1
452 * bytes are copied and the last byte is set to NUL.
453 * @dst: destination address
454 * @size: maximum number of bytes to copy, including the trailing NUL
455 * @unsafe_ptr: unsafe address
456 * Return:
457 * > 0 length of the string including the trailing NUL on success
458 * < 0 error
433 */ 459 */
434#define __BPF_FUNC_MAPPER(FN) \ 460#define __BPF_FUNC_MAPPER(FN) \
435 FN(unspec), \ 461 FN(unspec), \
@@ -476,7 +502,8 @@ union bpf_attr {
476 FN(set_hash_invalid), \ 502 FN(set_hash_invalid), \
477 FN(get_numa_node_id), \ 503 FN(get_numa_node_id), \
478 FN(skb_change_head), \ 504 FN(skb_change_head), \
479 FN(xdp_adjust_head), 505 FN(xdp_adjust_head), \
506 FN(probe_read_str),
480 507
481/* integer value in 'imm' field of BPF_CALL instruction selects which helper 508/* integer value in 'imm' field of BPF_CALL instruction selects which helper
482 * function eBPF program intends to call 509 * function eBPF program intends to call
@@ -502,6 +529,7 @@ enum bpf_func_id {
502/* BPF_FUNC_l4_csum_replace flags. */ 529/* BPF_FUNC_l4_csum_replace flags. */
503#define BPF_F_PSEUDO_HDR (1ULL << 4) 530#define BPF_F_PSEUDO_HDR (1ULL << 4)
504#define BPF_F_MARK_MANGLED_0 (1ULL << 5) 531#define BPF_F_MARK_MANGLED_0 (1ULL << 5)
532#define BPF_F_MARK_ENFORCE (1ULL << 6)
505 533
506/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */ 534/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
507#define BPF_F_INGRESS (1ULL << 0) 535#define BPF_F_INGRESS (1ULL << 0)
diff --git a/tools/leds/Makefile b/tools/leds/Makefile
index c03a79ebf9c8..078b666fd78b 100644
--- a/tools/leds/Makefile
+++ b/tools/leds/Makefile
@@ -3,11 +3,11 @@
3CC = $(CROSS_COMPILE)gcc 3CC = $(CROSS_COMPILE)gcc
4CFLAGS = -Wall -Wextra -g -I../../include/uapi 4CFLAGS = -Wall -Wextra -g -I../../include/uapi
5 5
6all: uledmon 6all: uledmon led_hw_brightness_mon
7%: %.c 7%: %.c
8 $(CC) $(CFLAGS) -o $@ $^ 8 $(CC) $(CFLAGS) -o $@ $^
9 9
10clean: 10clean:
11 $(RM) uledmon 11 $(RM) uledmon led_hw_brightness_mon
12 12
13.PHONY: all clean 13.PHONY: all clean
diff --git a/tools/leds/led_hw_brightness_mon.c b/tools/leds/led_hw_brightness_mon.c
new file mode 100644
index 000000000000..64642ccfe442
--- /dev/null
+++ b/tools/leds/led_hw_brightness_mon.c
@@ -0,0 +1,84 @@
1/*
2 * led_hw_brightness_mon.c
3 *
4 * This program monitors LED brightness level changes having its origin
5 * in hardware/firmware, i.e. outside of kernel control.
6 * A timestamp and brightness value is printed each time the brightness changes.
7 *
8 * Usage: led_hw_brightness_mon <device-name>
9 *
10 * <device-name> is the name of the LED class device to be monitored. Pressing
11 * CTRL+C will exit.
12 */
13
14#include <errno.h>
15#include <fcntl.h>
16#include <poll.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <time.h>
21#include <unistd.h>
22
23#include <linux/uleds.h>
24
25int main(int argc, char const *argv[])
26{
27 int fd, ret;
28 char brightness_file_path[LED_MAX_NAME_SIZE + 11];
29 struct pollfd pollfd;
30 struct timespec ts;
31 char buf[11];
32
33 if (argc != 2) {
34 fprintf(stderr, "Requires <device-name> argument\n");
35 return 1;
36 }
37
38 snprintf(brightness_file_path, LED_MAX_NAME_SIZE,
39 "/sys/class/leds/%s/brightness_hw_changed", argv[1]);
40
41 fd = open(brightness_file_path, O_RDONLY);
42 if (fd == -1) {
43 printf("Failed to open %s file\n", brightness_file_path);
44 return 1;
45 }
46
47 /*
48 * read may fail if no hw brightness change has occurred so far,
49 * but it is required to avoid spurious poll notifications in
50 * the opposite case.
51 */
52 read(fd, buf, sizeof(buf));
53
54 pollfd.fd = fd;
55 pollfd.events = POLLPRI;
56
57 while (1) {
58 ret = poll(&pollfd, 1, -1);
59 if (ret == -1) {
60 printf("Failed to poll %s file (%d)\n",
61 brightness_file_path, ret);
62 ret = 1;
63 break;
64 }
65
66 clock_gettime(CLOCK_MONOTONIC, &ts);
67
68 ret = read(fd, buf, sizeof(buf));
69 if (ret < 0)
70 break;
71
72 ret = lseek(pollfd.fd, 0, SEEK_SET);
73 if (ret < 0) {
74 printf("lseek failed (%d)\n", ret);
75 break;
76 }
77
78 printf("[%ld.%09ld] %d\n", ts.tv_sec, ts.tv_nsec, atoi(buf));
79 }
80
81 close(fd);
82
83 return ret;
84}
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index adba83b325d5..eb6e0b36bfc1 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -17,7 +17,13 @@ MAKEFLAGS += --no-print-directory
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 -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC 20CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
21
22ifeq ($(CC), clang)
23 CFLAGS += -O3
24else
25 CFLAGS += -O6
26endif
21 27
22# Treat warnings as errors unless directed not to 28# Treat warnings as errors unless directed not to
23ifneq ($(WERROR),0) 29ifneq ($(WERROR),0)
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
index f99f49e4a31e..4b6bfc43cccf 100644
--- a/tools/lib/api/fs/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -38,6 +38,10 @@
38#define HUGETLBFS_MAGIC 0x958458f6 38#define HUGETLBFS_MAGIC 0x958458f6
39#endif 39#endif
40 40
41#ifndef BPF_FS_MAGIC
42#define BPF_FS_MAGIC 0xcafe4a11
43#endif
44
41static const char * const sysfs__fs_known_mountpoints[] = { 45static const char * const sysfs__fs_known_mountpoints[] = {
42 "/sys", 46 "/sys",
43 0, 47 0,
@@ -75,6 +79,11 @@ static const char * const hugetlbfs__known_mountpoints[] = {
75 0, 79 0,
76}; 80};
77 81
82static const char * const bpf_fs__known_mountpoints[] = {
83 "/sys/fs/bpf",
84 0,
85};
86
78struct fs { 87struct fs {
79 const char *name; 88 const char *name;
80 const char * const *mounts; 89 const char * const *mounts;
@@ -89,6 +98,7 @@ enum {
89 FS__DEBUGFS = 2, 98 FS__DEBUGFS = 2,
90 FS__TRACEFS = 3, 99 FS__TRACEFS = 3,
91 FS__HUGETLBFS = 4, 100 FS__HUGETLBFS = 4,
101 FS__BPF_FS = 5,
92}; 102};
93 103
94#ifndef TRACEFS_MAGIC 104#ifndef TRACEFS_MAGIC
@@ -121,6 +131,11 @@ static struct fs fs__entries[] = {
121 .mounts = hugetlbfs__known_mountpoints, 131 .mounts = hugetlbfs__known_mountpoints,
122 .magic = HUGETLBFS_MAGIC, 132 .magic = HUGETLBFS_MAGIC,
123 }, 133 },
134 [FS__BPF_FS] = {
135 .name = "bpf",
136 .mounts = bpf_fs__known_mountpoints,
137 .magic = BPF_FS_MAGIC,
138 },
124}; 139};
125 140
126static bool fs__read_mounts(struct fs *fs) 141static bool fs__read_mounts(struct fs *fs)
@@ -280,6 +295,7 @@ FS(procfs, FS__PROCFS);
280FS(debugfs, FS__DEBUGFS); 295FS(debugfs, FS__DEBUGFS);
281FS(tracefs, FS__TRACEFS); 296FS(tracefs, FS__TRACEFS);
282FS(hugetlbfs, FS__HUGETLBFS); 297FS(hugetlbfs, FS__HUGETLBFS);
298FS(bpf_fs, FS__BPF_FS);
283 299
284int filename__read_int(const char *filename, int *value) 300int filename__read_int(const char *filename, int *value)
285{ 301{
diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h
index a63269f5d20c..6b332dc74498 100644
--- a/tools/lib/api/fs/fs.h
+++ b/tools/lib/api/fs/fs.h
@@ -22,6 +22,7 @@ FS(procfs)
22FS(debugfs) 22FS(debugfs)
23FS(tracefs) 23FS(tracefs)
24FS(hugetlbfs) 24FS(hugetlbfs)
25FS(bpf_fs)
25 26
26#undef FS 27#undef FS
27 28
diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c
index 251b7c342a87..3e606b9c443e 100644
--- a/tools/lib/api/fs/tracing_path.c
+++ b/tools/lib/api/fs/tracing_path.c
@@ -86,9 +86,13 @@ void put_tracing_file(char *file)
86 free(file); 86 free(file);
87} 87}
88 88
89static int strerror_open(int err, char *buf, size_t size, const char *filename) 89int tracing_path__strerror_open_tp(int err, char *buf, size_t size,
90 const char *sys, const char *name)
90{ 91{
91 char sbuf[128]; 92 char sbuf[128];
93 char filename[PATH_MAX];
94
95 snprintf(filename, PATH_MAX, "%s/%s", sys, name ?: "*");
92 96
93 switch (err) { 97 switch (err) {
94 case ENOENT: 98 case ENOENT:
@@ -99,10 +103,19 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
99 * - jirka 103 * - jirka
100 */ 104 */
101 if (debugfs__configured() || tracefs__configured()) { 105 if (debugfs__configured() || tracefs__configured()) {
102 snprintf(buf, size, 106 /* sdt markers */
103 "Error:\tFile %s/%s not found.\n" 107 if (!strncmp(filename, "sdt_", 4)) {
104 "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n", 108 snprintf(buf, size,
105 tracing_events_path, filename); 109 "Error:\tFile %s/%s not found.\n"
110 "Hint:\tSDT event cannot be directly recorded on.\n"
111 "\tPlease first use 'perf probe %s:%s' before recording it.\n",
112 tracing_events_path, filename, sys, name);
113 } else {
114 snprintf(buf, size,
115 "Error:\tFile %s/%s not found.\n"
116 "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
117 tracing_events_path, filename);
118 }
106 break; 119 break;
107 } 120 }
108 snprintf(buf, size, "%s", 121 snprintf(buf, size, "%s",
@@ -125,12 +138,3 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
125 138
126 return 0; 139 return 0;
127} 140}
128
129int tracing_path__strerror_open_tp(int err, char *buf, size_t size, const char *sys, const char *name)
130{
131 char path[PATH_MAX];
132
133 snprintf(path, PATH_MAX, "%s/%s", sys, name ?: "*");
134
135 return strerror_open(err, buf, size, path);
136}
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 3ddb58a36d3c..207c2eeddab0 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -27,7 +27,7 @@
27#include "bpf.h" 27#include "bpf.h"
28 28
29/* 29/*
30 * When building perf, unistd.h is overrided. __NR_bpf is 30 * When building perf, unistd.h is overridden. __NR_bpf is
31 * required to be defined explicitly. 31 * required to be defined explicitly.
32 */ 32 */
33#ifndef __NR_bpf 33#ifndef __NR_bpf
@@ -42,13 +42,13 @@
42# endif 42# endif
43#endif 43#endif
44 44
45static __u64 ptr_to_u64(void *ptr) 45static inline __u64 ptr_to_u64(const void *ptr)
46{ 46{
47 return (__u64) (unsigned long) ptr; 47 return (__u64) (unsigned long) ptr;
48} 48}
49 49
50static int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, 50static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
51 unsigned int size) 51 unsigned int size)
52{ 52{
53 return syscall(__NR_bpf, cmd, attr, size); 53 return syscall(__NR_bpf, cmd, attr, size);
54} 54}
@@ -69,8 +69,8 @@ int bpf_create_map(enum bpf_map_type map_type, int key_size,
69 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 69 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
70} 70}
71 71
72int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns, 72int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
73 size_t insns_cnt, char *license, 73 size_t insns_cnt, const char *license,
74 __u32 kern_version, char *log_buf, size_t log_buf_sz) 74 __u32 kern_version, char *log_buf, size_t log_buf_sz)
75{ 75{
76 int fd; 76 int fd;
@@ -98,7 +98,7 @@ int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
98 return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 98 return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
99} 99}
100 100
101int bpf_map_update_elem(int fd, void *key, void *value, 101int bpf_map_update_elem(int fd, const void *key, const void *value,
102 __u64 flags) 102 __u64 flags)
103{ 103{
104 union bpf_attr attr; 104 union bpf_attr attr;
@@ -112,7 +112,7 @@ int bpf_map_update_elem(int fd, void *key, void *value,
112 return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); 112 return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
113} 113}
114 114
115int bpf_map_lookup_elem(int fd, void *key, void *value) 115int bpf_map_lookup_elem(int fd, const void *key, void *value)
116{ 116{
117 union bpf_attr attr; 117 union bpf_attr attr;
118 118
@@ -124,7 +124,7 @@ int bpf_map_lookup_elem(int fd, void *key, void *value)
124 return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); 124 return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
125} 125}
126 126
127int bpf_map_delete_elem(int fd, void *key) 127int bpf_map_delete_elem(int fd, const void *key)
128{ 128{
129 union bpf_attr attr; 129 union bpf_attr attr;
130 130
@@ -135,7 +135,7 @@ int bpf_map_delete_elem(int fd, void *key)
135 return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr)); 135 return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
136} 136}
137 137
138int bpf_map_get_next_key(int fd, void *key, void *next_key) 138int bpf_map_get_next_key(int fd, const void *key, void *next_key)
139{ 139{
140 union bpf_attr attr; 140 union bpf_attr attr;
141 141
@@ -168,7 +168,8 @@ int bpf_obj_get(const char *pathname)
168 return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr)); 168 return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
169} 169}
170 170
171int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type) 171int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
172 unsigned int flags)
172{ 173{
173 union bpf_attr attr; 174 union bpf_attr attr;
174 175
@@ -176,6 +177,7 @@ int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type)
176 attr.target_fd = target_fd; 177 attr.target_fd = target_fd;
177 attr.attach_bpf_fd = prog_fd; 178 attr.attach_bpf_fd = prog_fd;
178 attr.attach_type = type; 179 attr.attach_type = type;
180 attr.attach_flags = flags;
179 181
180 return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)); 182 return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
181} 183}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index a2f9853dd882..09c3dcac0496 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -22,26 +22,28 @@
22#define __BPF_BPF_H 22#define __BPF_BPF_H
23 23
24#include <linux/bpf.h> 24#include <linux/bpf.h>
25#include <stddef.h>
25 26
26int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, 27int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
27 int max_entries, __u32 map_flags); 28 int max_entries, __u32 map_flags);
28 29
29/* Recommend log buffer size */ 30/* Recommend log buffer size */
30#define BPF_LOG_BUF_SIZE 65536 31#define BPF_LOG_BUF_SIZE 65536
31int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns, 32int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
32 size_t insns_cnt, char *license, 33 size_t insns_cnt, const char *license,
33 __u32 kern_version, char *log_buf, 34 __u32 kern_version, char *log_buf,
34 size_t log_buf_sz); 35 size_t log_buf_sz);
35 36
36int bpf_map_update_elem(int fd, void *key, void *value, 37int bpf_map_update_elem(int fd, const void *key, const void *value,
37 __u64 flags); 38 __u64 flags);
38 39
39int bpf_map_lookup_elem(int fd, void *key, void *value); 40int bpf_map_lookup_elem(int fd, const void *key, void *value);
40int bpf_map_delete_elem(int fd, void *key); 41int bpf_map_delete_elem(int fd, const void *key);
41int bpf_map_get_next_key(int fd, void *key, void *next_key); 42int bpf_map_get_next_key(int fd, const void *key, void *next_key);
42int bpf_obj_pin(int fd, const char *pathname); 43int bpf_obj_pin(int fd, const char *pathname);
43int bpf_obj_get(const char *pathname); 44int bpf_obj_get(const char *pathname);
44int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type); 45int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type,
46 unsigned int flags);
45int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type); 47int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
46 48
47 49
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 84e6b35da4bd..ac6eb863b2a4 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -4,6 +4,7 @@
4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> 4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> 5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
6 * Copyright (C) 2015 Huawei Inc. 6 * Copyright (C) 2015 Huawei Inc.
7 * Copyright (C) 2017 Nicira, Inc.
7 * 8 *
8 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public 10 * modify it under the terms of the GNU Lesser General Public
@@ -22,15 +23,21 @@
22#include <stdlib.h> 23#include <stdlib.h>
23#include <stdio.h> 24#include <stdio.h>
24#include <stdarg.h> 25#include <stdarg.h>
26#include <libgen.h>
25#include <inttypes.h> 27#include <inttypes.h>
26#include <string.h> 28#include <string.h>
27#include <unistd.h> 29#include <unistd.h>
28#include <fcntl.h> 30#include <fcntl.h>
29#include <errno.h> 31#include <errno.h>
30#include <asm/unistd.h> 32#include <asm/unistd.h>
33#include <linux/err.h>
31#include <linux/kernel.h> 34#include <linux/kernel.h>
32#include <linux/bpf.h> 35#include <linux/bpf.h>
33#include <linux/list.h> 36#include <linux/list.h>
37#include <linux/limits.h>
38#include <sys/stat.h>
39#include <sys/types.h>
40#include <sys/vfs.h>
34#include <libelf.h> 41#include <libelf.h>
35#include <gelf.h> 42#include <gelf.h>
36 43
@@ -41,6 +48,10 @@
41#define EM_BPF 247 48#define EM_BPF 247
42#endif 49#endif
43 50
51#ifndef BPF_FS_MAGIC
52#define BPF_FS_MAGIC 0xcafe4a11
53#endif
54
44#define __printf(a, b) __attribute__((format(printf, a, b))) 55#define __printf(a, b) __attribute__((format(printf, a, b)))
45 56
46__printf(1, 2) 57__printf(1, 2)
@@ -779,7 +790,7 @@ static int
779bpf_program__collect_reloc(struct bpf_program *prog, 790bpf_program__collect_reloc(struct bpf_program *prog,
780 size_t nr_maps, GElf_Shdr *shdr, 791 size_t nr_maps, GElf_Shdr *shdr,
781 Elf_Data *data, Elf_Data *symbols, 792 Elf_Data *data, Elf_Data *symbols,
782 int maps_shndx) 793 int maps_shndx, struct bpf_map *maps)
783{ 794{
784 int i, nrels; 795 int i, nrels;
785 796
@@ -829,7 +840,15 @@ bpf_program__collect_reloc(struct bpf_program *prog,
829 return -LIBBPF_ERRNO__RELOC; 840 return -LIBBPF_ERRNO__RELOC;
830 } 841 }
831 842
832 map_idx = sym.st_value / sizeof(struct bpf_map_def); 843 /* TODO: 'maps' is sorted. We can use bsearch to make it faster. */
844 for (map_idx = 0; map_idx < nr_maps; map_idx++) {
845 if (maps[map_idx].offset == sym.st_value) {
846 pr_debug("relocation: find map %zd (%s) for insn %u\n",
847 map_idx, maps[map_idx].name, insn_idx);
848 break;
849 }
850 }
851
833 if (map_idx >= nr_maps) { 852 if (map_idx >= nr_maps) {
834 pr_warning("bpf relocation: map_idx %d large than %d\n", 853 pr_warning("bpf relocation: map_idx %d large than %d\n",
835 (int)map_idx, (int)nr_maps - 1); 854 (int)map_idx, (int)nr_maps - 1);
@@ -953,7 +972,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
953 err = bpf_program__collect_reloc(prog, nr_maps, 972 err = bpf_program__collect_reloc(prog, nr_maps,
954 shdr, data, 973 shdr, data,
955 obj->efile.symbols, 974 obj->efile.symbols,
956 obj->efile.maps_shndx); 975 obj->efile.maps_shndx,
976 obj->maps);
957 if (err) 977 if (err)
958 return err; 978 return err;
959 } 979 }
@@ -1227,6 +1247,191 @@ out:
1227 return err; 1247 return err;
1228} 1248}
1229 1249
1250static int check_path(const char *path)
1251{
1252 struct statfs st_fs;
1253 char *dname, *dir;
1254 int err = 0;
1255
1256 if (path == NULL)
1257 return -EINVAL;
1258
1259 dname = strdup(path);
1260 if (dname == NULL)
1261 return -ENOMEM;
1262
1263 dir = dirname(dname);
1264 if (statfs(dir, &st_fs)) {
1265 pr_warning("failed to statfs %s: %s\n", dir, strerror(errno));
1266 err = -errno;
1267 }
1268 free(dname);
1269
1270 if (!err && st_fs.f_type != BPF_FS_MAGIC) {
1271 pr_warning("specified path %s is not on BPF FS\n", path);
1272 err = -EINVAL;
1273 }
1274
1275 return err;
1276}
1277
1278int bpf_program__pin_instance(struct bpf_program *prog, const char *path,
1279 int instance)
1280{
1281 int err;
1282
1283 err = check_path(path);
1284 if (err)
1285 return err;
1286
1287 if (prog == NULL) {
1288 pr_warning("invalid program pointer\n");
1289 return -EINVAL;
1290 }
1291
1292 if (instance < 0 || instance >= prog->instances.nr) {
1293 pr_warning("invalid prog instance %d of prog %s (max %d)\n",
1294 instance, prog->section_name, prog->instances.nr);
1295 return -EINVAL;
1296 }
1297
1298 if (bpf_obj_pin(prog->instances.fds[instance], path)) {
1299 pr_warning("failed to pin program: %s\n", strerror(errno));
1300 return -errno;
1301 }
1302 pr_debug("pinned program '%s'\n", path);
1303
1304 return 0;
1305}
1306
1307static int make_dir(const char *path)
1308{
1309 int err = 0;
1310
1311 if (mkdir(path, 0700) && errno != EEXIST)
1312 err = -errno;
1313
1314 if (err)
1315 pr_warning("failed to mkdir %s: %s\n", path, strerror(-err));
1316 return err;
1317}
1318
1319int bpf_program__pin(struct bpf_program *prog, const char *path)
1320{
1321 int i, err;
1322
1323 err = check_path(path);
1324 if (err)
1325 return err;
1326
1327 if (prog == NULL) {
1328 pr_warning("invalid program pointer\n");
1329 return -EINVAL;
1330 }
1331
1332 if (prog->instances.nr <= 0) {
1333 pr_warning("no instances of prog %s to pin\n",
1334 prog->section_name);
1335 return -EINVAL;
1336 }
1337
1338 err = make_dir(path);
1339 if (err)
1340 return err;
1341
1342 for (i = 0; i < prog->instances.nr; i++) {
1343 char buf[PATH_MAX];
1344 int len;
1345
1346 len = snprintf(buf, PATH_MAX, "%s/%d", path, i);
1347 if (len < 0)
1348 return -EINVAL;
1349 else if (len >= PATH_MAX)
1350 return -ENAMETOOLONG;
1351
1352 err = bpf_program__pin_instance(prog, buf, i);
1353 if (err)
1354 return err;
1355 }
1356
1357 return 0;
1358}
1359
1360int bpf_map__pin(struct bpf_map *map, const char *path)
1361{
1362 int err;
1363
1364 err = check_path(path);
1365 if (err)
1366 return err;
1367
1368 if (map == NULL) {
1369 pr_warning("invalid map pointer\n");
1370 return -EINVAL;
1371 }
1372
1373 if (bpf_obj_pin(map->fd, path)) {
1374 pr_warning("failed to pin map: %s\n", strerror(errno));
1375 return -errno;
1376 }
1377
1378 pr_debug("pinned map '%s'\n", path);
1379 return 0;
1380}
1381
1382int bpf_object__pin(struct bpf_object *obj, const char *path)
1383{
1384 struct bpf_program *prog;
1385 struct bpf_map *map;
1386 int err;
1387
1388 if (!obj)
1389 return -ENOENT;
1390
1391 if (!obj->loaded) {
1392 pr_warning("object not yet loaded; load it first\n");
1393 return -ENOENT;
1394 }
1395
1396 err = make_dir(path);
1397 if (err)
1398 return err;
1399
1400 bpf_map__for_each(map, obj) {
1401 char buf[PATH_MAX];
1402 int len;
1403
1404 len = snprintf(buf, PATH_MAX, "%s/%s", path,
1405 bpf_map__name(map));
1406 if (len < 0)
1407 return -EINVAL;
1408 else if (len >= PATH_MAX)
1409 return -ENAMETOOLONG;
1410
1411 err = bpf_map__pin(map, buf);
1412 if (err)
1413 return err;
1414 }
1415
1416 bpf_object__for_each_program(prog, obj) {
1417 char buf[PATH_MAX];
1418 int len;
1419
1420 len = snprintf(buf, PATH_MAX, "%s/%s", path,
1421 prog->section_name);
1422 if (len < 0)
1423 return -EINVAL;
1424 else if (len >= PATH_MAX)
1425 return -ENAMETOOLONG;
1426
1427 err = bpf_program__pin(prog, buf);
1428 if (err)
1429 return err;
1430 }
1431
1432 return 0;
1433}
1434
1230void bpf_object__close(struct bpf_object *obj) 1435void bpf_object__close(struct bpf_object *obj)
1231{ 1436{
1232 size_t i; 1437 size_t i;
@@ -1419,37 +1624,33 @@ static void bpf_program__set_type(struct bpf_program *prog,
1419 prog->type = type; 1624 prog->type = type;
1420} 1625}
1421 1626
1422int bpf_program__set_tracepoint(struct bpf_program *prog)
1423{
1424 if (!prog)
1425 return -EINVAL;
1426 bpf_program__set_type(prog, BPF_PROG_TYPE_TRACEPOINT);
1427 return 0;
1428}
1429
1430int bpf_program__set_kprobe(struct bpf_program *prog)
1431{
1432 if (!prog)
1433 return -EINVAL;
1434 bpf_program__set_type(prog, BPF_PROG_TYPE_KPROBE);
1435 return 0;
1436}
1437
1438static bool bpf_program__is_type(struct bpf_program *prog, 1627static bool bpf_program__is_type(struct bpf_program *prog,
1439 enum bpf_prog_type type) 1628 enum bpf_prog_type type)
1440{ 1629{
1441 return prog ? (prog->type == type) : false; 1630 return prog ? (prog->type == type) : false;
1442} 1631}
1443 1632
1444bool bpf_program__is_tracepoint(struct bpf_program *prog) 1633#define BPF_PROG_TYPE_FNS(NAME, TYPE) \
1445{ 1634int bpf_program__set_##NAME(struct bpf_program *prog) \
1446 return bpf_program__is_type(prog, BPF_PROG_TYPE_TRACEPOINT); 1635{ \
1447} 1636 if (!prog) \
1448 1637 return -EINVAL; \
1449bool bpf_program__is_kprobe(struct bpf_program *prog) 1638 bpf_program__set_type(prog, TYPE); \
1450{ 1639 return 0; \
1451 return bpf_program__is_type(prog, BPF_PROG_TYPE_KPROBE); 1640} \
1452} 1641 \
1642bool bpf_program__is_##NAME(struct bpf_program *prog) \
1643{ \
1644 return bpf_program__is_type(prog, TYPE); \
1645} \
1646
1647BPF_PROG_TYPE_FNS(socket_filter, BPF_PROG_TYPE_SOCKET_FILTER);
1648BPF_PROG_TYPE_FNS(kprobe, BPF_PROG_TYPE_KPROBE);
1649BPF_PROG_TYPE_FNS(sched_cls, BPF_PROG_TYPE_SCHED_CLS);
1650BPF_PROG_TYPE_FNS(sched_act, BPF_PROG_TYPE_SCHED_ACT);
1651BPF_PROG_TYPE_FNS(tracepoint, BPF_PROG_TYPE_TRACEPOINT);
1652BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP);
1653BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT);
1453 1654
1454int bpf_map__fd(struct bpf_map *map) 1655int bpf_map__fd(struct bpf_map *map)
1455{ 1656{
@@ -1537,3 +1738,10 @@ bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset)
1537 } 1738 }
1538 return ERR_PTR(-ENOENT); 1739 return ERR_PTR(-ENOENT);
1539} 1740}
1741
1742long libbpf_get_error(const void *ptr)
1743{
1744 if (IS_ERR(ptr))
1745 return PTR_ERR(ptr);
1746 return 0;
1747}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index a5a8b86a06fe..b30394f9947a 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -22,8 +22,8 @@
22#define __BPF_LIBBPF_H 22#define __BPF_LIBBPF_H
23 23
24#include <stdio.h> 24#include <stdio.h>
25#include <stdint.h>
25#include <stdbool.h> 26#include <stdbool.h>
26#include <linux/err.h>
27#include <sys/types.h> // for size_t 27#include <sys/types.h> // for size_t
28 28
29enum libbpf_errno { 29enum libbpf_errno {
@@ -65,6 +65,7 @@ struct bpf_object *bpf_object__open(const char *path);
65struct bpf_object *bpf_object__open_buffer(void *obj_buf, 65struct bpf_object *bpf_object__open_buffer(void *obj_buf,
66 size_t obj_buf_sz, 66 size_t obj_buf_sz,
67 const char *name); 67 const char *name);
68int bpf_object__pin(struct bpf_object *object, const char *path);
68void bpf_object__close(struct bpf_object *object); 69void bpf_object__close(struct bpf_object *object);
69 70
70/* Load/unload object into/from kernel */ 71/* Load/unload object into/from kernel */
@@ -106,6 +107,9 @@ void *bpf_program__priv(struct bpf_program *prog);
106const char *bpf_program__title(struct bpf_program *prog, bool needs_copy); 107const char *bpf_program__title(struct bpf_program *prog, bool needs_copy);
107 108
108int bpf_program__fd(struct bpf_program *prog); 109int bpf_program__fd(struct bpf_program *prog);
110int bpf_program__pin_instance(struct bpf_program *prog, const char *path,
111 int instance);
112int bpf_program__pin(struct bpf_program *prog, const char *path);
109 113
110struct bpf_insn; 114struct bpf_insn;
111 115
@@ -174,11 +178,21 @@ int bpf_program__nth_fd(struct bpf_program *prog, int n);
174/* 178/*
175 * Adjust type of bpf program. Default is kprobe. 179 * Adjust type of bpf program. Default is kprobe.
176 */ 180 */
181int bpf_program__set_socket_filter(struct bpf_program *prog);
177int bpf_program__set_tracepoint(struct bpf_program *prog); 182int bpf_program__set_tracepoint(struct bpf_program *prog);
178int bpf_program__set_kprobe(struct bpf_program *prog); 183int bpf_program__set_kprobe(struct bpf_program *prog);
184int bpf_program__set_sched_cls(struct bpf_program *prog);
185int bpf_program__set_sched_act(struct bpf_program *prog);
186int bpf_program__set_xdp(struct bpf_program *prog);
187int bpf_program__set_perf_event(struct bpf_program *prog);
179 188
189bool bpf_program__is_socket_filter(struct bpf_program *prog);
180bool bpf_program__is_tracepoint(struct bpf_program *prog); 190bool bpf_program__is_tracepoint(struct bpf_program *prog);
181bool bpf_program__is_kprobe(struct bpf_program *prog); 191bool bpf_program__is_kprobe(struct bpf_program *prog);
192bool bpf_program__is_sched_cls(struct bpf_program *prog);
193bool bpf_program__is_sched_act(struct bpf_program *prog);
194bool bpf_program__is_xdp(struct bpf_program *prog);
195bool bpf_program__is_perf_event(struct bpf_program *prog);
182 196
183/* 197/*
184 * We don't need __attribute__((packed)) now since it is 198 * We don't need __attribute__((packed)) now since it is
@@ -223,5 +237,8 @@ typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
223int bpf_map__set_priv(struct bpf_map *map, void *priv, 237int bpf_map__set_priv(struct bpf_map *map, void *priv,
224 bpf_map_clear_priv_t clear_priv); 238 bpf_map_clear_priv_t clear_priv);
225void *bpf_map__priv(struct bpf_map *map); 239void *bpf_map__priv(struct bpf_map *map);
240int bpf_map__pin(struct bpf_map *map, const char *path);
241
242long libbpf_get_error(const void *ptr);
226 243
227#endif 244#endif
diff --git a/tools/lib/find_bit.c b/tools/lib/find_bit.c
index 6d8b8f22cf55..42c15f906aac 100644
--- a/tools/lib/find_bit.c
+++ b/tools/lib/find_bit.c
@@ -34,7 +34,7 @@ static unsigned long _find_next_bit(const unsigned long *addr,
34{ 34{
35 unsigned long tmp; 35 unsigned long tmp;
36 36
37 if (!nbits || start >= nbits) 37 if (unlikely(start >= nbits))
38 return nbits; 38 return nbits;
39 39
40 tmp = addr[start / BITS_PER_LONG] ^ invert; 40 tmp = addr[start / BITS_PER_LONG] ^ invert;
diff --git a/tools/lib/subcmd/Makefile b/tools/lib/subcmd/Makefile
index 3f8cc44a0dbd..3d1c3b5b5150 100644
--- a/tools/lib/subcmd/Makefile
+++ b/tools/lib/subcmd/Makefile
@@ -19,7 +19,13 @@ MAKEFLAGS += --no-print-directory
19LIBFILE = $(OUTPUT)libsubcmd.a 19LIBFILE = $(OUTPUT)libsubcmd.a
20 20
21CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 21CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
22CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC 22CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
23
24ifeq ($(CC), clang)
25 CFLAGS += -O3
26else
27 CFLAGS += -O6
28endif
23 29
24# Treat warnings as errors unless directed not to 30# Treat warnings as errors unless directed not to
25ifneq ($(WERROR),0) 31ifneq ($(WERROR),0)
diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c
index 8aad81151d50..6bc24025d054 100644
--- a/tools/lib/subcmd/parse-options.c
+++ b/tools/lib/subcmd/parse-options.c
@@ -270,6 +270,8 @@ static int get_value(struct parse_opt_ctx_t *p,
270 } 270 }
271 if (get_arg(p, opt, flags, &arg)) 271 if (get_arg(p, opt, flags, &arg))
272 return -1; 272 return -1;
273 if (arg[0] == '-')
274 return opterror(opt, "expects an unsigned numerical value", flags);
273 *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10); 275 *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10);
274 if (*s) 276 if (*s)
275 return opterror(opt, "expects a numerical value", flags); 277 return opterror(opt, "expects a numerical value", flags);
@@ -302,6 +304,8 @@ static int get_value(struct parse_opt_ctx_t *p,
302 } 304 }
303 if (get_arg(p, opt, flags, &arg)) 305 if (get_arg(p, opt, flags, &arg))
304 return -1; 306 return -1;
307 if (arg[0] == '-')
308 return opterror(opt, "expects an unsigned numerical value", flags);
305 *(u64 *)opt->value = strtoull(arg, (char **)&s, 10); 309 *(u64 *)opt->value = strtoull(arg, (char **)&s, 10);
306 if (*s) 310 if (*s)
307 return opterror(opt, "expects a numerical value", flags); 311 return opterror(opt, "expects a numerical value", flags);
diff --git a/tools/lib/subcmd/parse-options.h b/tools/lib/subcmd/parse-options.h
index 11c3be3bcce7..f054ca1b899d 100644
--- a/tools/lib/subcmd/parse-options.h
+++ b/tools/lib/subcmd/parse-options.h
@@ -1,6 +1,7 @@
1#ifndef __SUBCMD_PARSE_OPTIONS_H 1#ifndef __SUBCMD_PARSE_OPTIONS_H
2#define __SUBCMD_PARSE_OPTIONS_H 2#define __SUBCMD_PARSE_OPTIONS_H
3 3
4#include <linux/kernel.h>
4#include <stdbool.h> 5#include <stdbool.h>
5#include <stdint.h> 6#include <stdint.h>
6 7
@@ -132,32 +133,32 @@ struct option {
132#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) } 133#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) }
133#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } 134#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
134#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } 135#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
135#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) } 136#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), .argh = (a), .help = (h) }
136#define OPT_STRING_OPTARG(s, l, v, a, h, d) \ 137#define OPT_STRING_OPTARG(s, l, v, a, h, d) \
137 { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ 138 { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \
138 .value = check_vtype(v, const char **), (a), .help = (h), \ 139 .value = check_vtype(v, const char **), .argh =(a), .help = (h), \
139 .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) } 140 .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) }
140#define OPT_STRING_OPTARG_SET(s, l, v, os, a, h, d) \ 141#define OPT_STRING_OPTARG_SET(s, l, v, os, a, h, d) \
141 { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ 142 { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \
142 .value = check_vtype(v, const char **), (a), .help = (h), \ 143 .value = check_vtype(v, const char **), .argh = (a), .help = (h), \
143 .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d), \ 144 .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d), \
144 .set = check_vtype(os, bool *)} 145 .set = check_vtype(os, bool *)}
145#define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY} 146#define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), .argh = (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}
146#define OPT_DATE(s, l, v, h) \ 147#define OPT_DATE(s, l, v, h) \
147 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } 148 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
148#define OPT_CALLBACK(s, l, v, a, h, f) \ 149#define OPT_CALLBACK(s, l, v, a, h, f) \
149 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) } 150 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f) }
150#define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \ 151#define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \
151 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG } 152 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG }
152#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \ 153#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
153 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT } 154 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }
154#define OPT_CALLBACK_DEFAULT_NOOPT(s, l, v, a, h, f, d) \ 155#define OPT_CALLBACK_DEFAULT_NOOPT(s, l, v, a, h, f, d) \
155 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\ 156 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\
156 .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\ 157 .value = (v), .arg = (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\
157 .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG} 158 .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG}
158#define OPT_CALLBACK_OPTARG(s, l, v, d, a, h, f) \ 159#define OPT_CALLBACK_OPTARG(s, l, v, d, a, h, f) \
159 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \ 160 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \
160 .value = (v), (a), .help = (h), .callback = (f), \ 161 .value = (v), .argh = (a), .help = (h), .callback = (f), \
161 .flags = PARSE_OPT_OPTARG, .data = (d) } 162 .flags = PARSE_OPT_OPTARG, .data = (d) }
162 163
163/* parse_options() will filter out the processed options and leave the 164/* parse_options() will filter out the processed options and leave the
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 2616c66e10c1..47076b15eebe 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -257,10 +257,16 @@ define do_install_plugins
257endef 257endef
258 258
259define do_generate_dynamic_list_file 259define do_generate_dynamic_list_file
260 (echo '{'; \ 260 symbol_type=`$(NM) -u -D $1 | awk 'NF>1 {print $$1}' | \
261 $(NM) -u -D $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u; \ 261 xargs echo "U W w" | tr ' ' '\n' | sort -u | xargs echo`;\
262 echo '};'; \ 262 if [ "$$symbol_type" = "U W w" ];then \
263 ) > $2 263 (echo '{'; \
264 $(NM) -u -D $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u;\
265 echo '};'; \
266 ) > $2; \
267 else \
268 (echo Either missing one of [$1] or bad version of $(NM)) 1>&2;\
269 fi
264endef 270endef
265 271
266install_lib: all_cmd install_plugins 272install_lib: all_cmd install_plugins
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 14a4f623c1a5..7ce724fc0544 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -831,6 +831,7 @@ static void free_arg(struct print_arg *arg)
831 free_flag_sym(arg->symbol.symbols); 831 free_flag_sym(arg->symbol.symbols);
832 break; 832 break;
833 case PRINT_HEX: 833 case PRINT_HEX:
834 case PRINT_HEX_STR:
834 free_arg(arg->hex.field); 835 free_arg(arg->hex.field);
835 free_arg(arg->hex.size); 836 free_arg(arg->hex.size);
836 break; 837 break;
@@ -2629,10 +2630,11 @@ out_free:
2629} 2630}
2630 2631
2631static enum event_type 2632static enum event_type
2632process_hex(struct event_format *event, struct print_arg *arg, char **tok) 2633process_hex_common(struct event_format *event, struct print_arg *arg,
2634 char **tok, enum print_arg_type type)
2633{ 2635{
2634 memset(arg, 0, sizeof(*arg)); 2636 memset(arg, 0, sizeof(*arg));
2635 arg->type = PRINT_HEX; 2637 arg->type = type;
2636 2638
2637 if (alloc_and_process_delim(event, ",", &arg->hex.field)) 2639 if (alloc_and_process_delim(event, ",", &arg->hex.field))
2638 goto out; 2640 goto out;
@@ -2651,6 +2653,19 @@ out:
2651} 2653}
2652 2654
2653static enum event_type 2655static enum event_type
2656process_hex(struct event_format *event, struct print_arg *arg, char **tok)
2657{
2658 return process_hex_common(event, arg, tok, PRINT_HEX);
2659}
2660
2661static enum event_type
2662process_hex_str(struct event_format *event, struct print_arg *arg,
2663 char **tok)
2664{
2665 return process_hex_common(event, arg, tok, PRINT_HEX_STR);
2666}
2667
2668static enum event_type
2654process_int_array(struct event_format *event, struct print_arg *arg, char **tok) 2669process_int_array(struct event_format *event, struct print_arg *arg, char **tok)
2655{ 2670{
2656 memset(arg, 0, sizeof(*arg)); 2671 memset(arg, 0, sizeof(*arg));
@@ -3009,6 +3024,10 @@ process_function(struct event_format *event, struct print_arg *arg,
3009 free_token(token); 3024 free_token(token);
3010 return process_hex(event, arg, tok); 3025 return process_hex(event, arg, tok);
3011 } 3026 }
3027 if (strcmp(token, "__print_hex_str") == 0) {
3028 free_token(token);
3029 return process_hex_str(event, arg, tok);
3030 }
3012 if (strcmp(token, "__print_array") == 0) { 3031 if (strcmp(token, "__print_array") == 0) {
3013 free_token(token); 3032 free_token(token);
3014 return process_int_array(event, arg, tok); 3033 return process_int_array(event, arg, tok);
@@ -3547,6 +3566,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
3547 case PRINT_SYMBOL: 3566 case PRINT_SYMBOL:
3548 case PRINT_INT_ARRAY: 3567 case PRINT_INT_ARRAY:
3549 case PRINT_HEX: 3568 case PRINT_HEX:
3569 case PRINT_HEX_STR:
3550 break; 3570 break;
3551 case PRINT_TYPE: 3571 case PRINT_TYPE:
3552 val = eval_num_arg(data, size, event, arg->typecast.item); 3572 val = eval_num_arg(data, size, event, arg->typecast.item);
@@ -3962,6 +3982,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3962 } 3982 }
3963 break; 3983 break;
3964 case PRINT_HEX: 3984 case PRINT_HEX:
3985 case PRINT_HEX_STR:
3965 if (arg->hex.field->type == PRINT_DYNAMIC_ARRAY) { 3986 if (arg->hex.field->type == PRINT_DYNAMIC_ARRAY) {
3966 unsigned long offset; 3987 unsigned long offset;
3967 offset = pevent_read_number(pevent, 3988 offset = pevent_read_number(pevent,
@@ -3981,7 +4002,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3981 } 4002 }
3982 len = eval_num_arg(data, size, event, arg->hex.size); 4003 len = eval_num_arg(data, size, event, arg->hex.size);
3983 for (i = 0; i < len; i++) { 4004 for (i = 0; i < len; i++) {
3984 if (i) 4005 if (i && arg->type == PRINT_HEX)
3985 trace_seq_putc(s, ' '); 4006 trace_seq_putc(s, ' ');
3986 trace_seq_printf(s, "%02x", hex[i]); 4007 trace_seq_printf(s, "%02x", hex[i]);
3987 } 4008 }
@@ -5204,13 +5225,13 @@ int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec)
5204} 5225}
5205 5226
5206/** 5227/**
5207 * pevent_data_prempt_count - parse the preempt count from the record 5228 * pevent_data_preempt_count - parse the preempt count from the record
5208 * @pevent: a handle to the pevent 5229 * @pevent: a handle to the pevent
5209 * @rec: the record to parse 5230 * @rec: the record to parse
5210 * 5231 *
5211 * This returns the preempt count from a record. 5232 * This returns the preempt count from a record.
5212 */ 5233 */
5213int pevent_data_prempt_count(struct pevent *pevent, struct pevent_record *rec) 5234int pevent_data_preempt_count(struct pevent *pevent, struct pevent_record *rec)
5214{ 5235{
5215 return parse_common_pc(pevent, rec->data); 5236 return parse_common_pc(pevent, rec->data);
5216} 5237}
@@ -5727,6 +5748,13 @@ static void print_args(struct print_arg *args)
5727 print_args(args->hex.size); 5748 print_args(args->hex.size);
5728 printf(")"); 5749 printf(")");
5729 break; 5750 break;
5751 case PRINT_HEX_STR:
5752 printf("__print_hex_str(");
5753 print_args(args->hex.field);
5754 printf(", ");
5755 print_args(args->hex.size);
5756 printf(")");
5757 break;
5730 case PRINT_INT_ARRAY: 5758 case PRINT_INT_ARRAY:
5731 printf("__print_array("); 5759 printf("__print_array(");
5732 print_args(args->int_array.field); 5760 print_args(args->int_array.field);
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 7aae746ec2fe..66342804161c 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -292,6 +292,7 @@ enum print_arg_type {
292 PRINT_FUNC, 292 PRINT_FUNC,
293 PRINT_BITMASK, 293 PRINT_BITMASK,
294 PRINT_DYNAMIC_ARRAY_LEN, 294 PRINT_DYNAMIC_ARRAY_LEN,
295 PRINT_HEX_STR,
295}; 296};
296 297
297struct print_arg { 298struct print_arg {
@@ -709,7 +710,7 @@ void pevent_data_lat_fmt(struct pevent *pevent,
709int pevent_data_type(struct pevent *pevent, struct pevent_record *rec); 710int pevent_data_type(struct pevent *pevent, struct pevent_record *rec);
710struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type); 711struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type);
711int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec); 712int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec);
712int pevent_data_prempt_count(struct pevent *pevent, struct pevent_record *rec); 713int pevent_data_preempt_count(struct pevent *pevent, struct pevent_record *rec);
713int pevent_data_flags(struct pevent *pevent, struct pevent_record *rec); 714int pevent_data_flags(struct pevent *pevent, struct pevent_record *rec);
714const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid); 715const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid);
715struct cmdline; 716struct cmdline;
diff --git a/tools/lib/traceevent/kbuffer-parse.c b/tools/lib/traceevent/kbuffer-parse.c
index 65984f1c2974..c94e3641b046 100644
--- a/tools/lib/traceevent/kbuffer-parse.c
+++ b/tools/lib/traceevent/kbuffer-parse.c
@@ -315,6 +315,7 @@ static unsigned int old_update_pointers(struct kbuffer *kbuf)
315 extend += delta; 315 extend += delta;
316 delta = extend; 316 delta = extend;
317 ptr += 4; 317 ptr += 4;
318 length = 0;
318 break; 319 break;
319 320
320 case OLD_RINGBUF_TYPE_TIME_STAMP: 321 case OLD_RINGBUF_TYPE_TIME_STAMP:
diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugin_function.c
index a00ec190821a..42dbf73758f3 100644
--- a/tools/lib/traceevent/plugin_function.c
+++ b/tools/lib/traceevent/plugin_function.c
@@ -130,7 +130,7 @@ static int function_handler(struct trace_seq *s, struct pevent_record *record,
130 unsigned long long pfunction; 130 unsigned long long pfunction;
131 const char *func; 131 const char *func;
132 const char *parent; 132 const char *parent;
133 int index; 133 int index = 0;
134 134
135 if (pevent_get_field_val(s, event, "ip", record, &function, 1)) 135 if (pevent_get_field_val(s, event, "ip", record, &function, 1))
136 return trace_seq_putc(s, '!'); 136 return trace_seq_putc(s, '!');
diff --git a/tools/objtool/arch.h b/tools/objtool/arch.h
index f7350fcedc70..a59e061c0b4a 100644
--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@ -31,9 +31,8 @@
31#define INSN_CALL_DYNAMIC 8 31#define INSN_CALL_DYNAMIC 8
32#define INSN_RETURN 9 32#define INSN_RETURN 9
33#define INSN_CONTEXT_SWITCH 10 33#define INSN_CONTEXT_SWITCH 10
34#define INSN_BUG 11 34#define INSN_NOP 11
35#define INSN_NOP 12 35#define INSN_OTHER 12
36#define INSN_OTHER 13
37#define INSN_LAST INSN_OTHER 36#define INSN_LAST INSN_OTHER
38 37
39int arch_decode_instruction(struct elf *elf, struct section *sec, 38int arch_decode_instruction(struct elf *elf, struct section *sec,
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 039636ffb6c8..6ac99e3266eb 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -118,9 +118,6 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
118 op2 == 0x35) 118 op2 == 0x35)
119 /* sysenter, sysret */ 119 /* sysenter, sysret */
120 *type = INSN_CONTEXT_SWITCH; 120 *type = INSN_CONTEXT_SWITCH;
121 else if (op2 == 0x0b || op2 == 0xb9)
122 /* ud2 */
123 *type = INSN_BUG;
124 else if (op2 == 0x0d || op2 == 0x1f) 121 else if (op2 == 0x0d || op2 == 0x1f)
125 /* nopl/nopw */ 122 /* nopl/nopw */
126 *type = INSN_NOP; 123 *type = INSN_NOP;
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index e8a1f699058a..4cfdbb5b6967 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -51,7 +51,7 @@ struct instruction {
51 unsigned int len, state; 51 unsigned int len, state;
52 unsigned char type; 52 unsigned char type;
53 unsigned long immediate; 53 unsigned long immediate;
54 bool alt_group, visited; 54 bool alt_group, visited, dead_end;
55 struct symbol *call_dest; 55 struct symbol *call_dest;
56 struct instruction *jump_dest; 56 struct instruction *jump_dest;
57 struct list_head alts; 57 struct list_head alts;
@@ -330,6 +330,54 @@ static int decode_instructions(struct objtool_file *file)
330} 330}
331 331
332/* 332/*
333 * Find all uses of the unreachable() macro, which are code path dead ends.
334 */
335static int add_dead_ends(struct objtool_file *file)
336{
337 struct section *sec;
338 struct rela *rela;
339 struct instruction *insn;
340 bool found;
341
342 sec = find_section_by_name(file->elf, ".rela.discard.unreachable");
343 if (!sec)
344 return 0;
345
346 list_for_each_entry(rela, &sec->rela_list, list) {
347 if (rela->sym->type != STT_SECTION) {
348 WARN("unexpected relocation symbol type in %s", sec->name);
349 return -1;
350 }
351 insn = find_insn(file, rela->sym->sec, rela->addend);
352 if (insn)
353 insn = list_prev_entry(insn, list);
354 else if (rela->addend == rela->sym->sec->len) {
355 found = false;
356 list_for_each_entry_reverse(insn, &file->insn_list, list) {
357 if (insn->sec == rela->sym->sec) {
358 found = true;
359 break;
360 }
361 }
362
363 if (!found) {
364 WARN("can't find unreachable insn at %s+0x%x",
365 rela->sym->sec->name, rela->addend);
366 return -1;
367 }
368 } else {
369 WARN("can't find unreachable insn at %s+0x%x",
370 rela->sym->sec->name, rela->addend);
371 return -1;
372 }
373
374 insn->dead_end = true;
375 }
376
377 return 0;
378}
379
380/*
333 * Warnings shouldn't be reported for ignored functions. 381 * Warnings shouldn't be reported for ignored functions.
334 */ 382 */
335static void add_ignores(struct objtool_file *file) 383static void add_ignores(struct objtool_file *file)
@@ -843,6 +891,10 @@ static int decode_sections(struct objtool_file *file)
843 if (ret) 891 if (ret)
844 return ret; 892 return ret;
845 893
894 ret = add_dead_ends(file);
895 if (ret)
896 return ret;
897
846 add_ignores(file); 898 add_ignores(file);
847 899
848 ret = add_jump_destinations(file); 900 ret = add_jump_destinations(file);
@@ -1037,13 +1089,13 @@ static int validate_branch(struct objtool_file *file,
1037 1089
1038 return 0; 1090 return 0;
1039 1091
1040 case INSN_BUG:
1041 return 0;
1042
1043 default: 1092 default:
1044 break; 1093 break;
1045 } 1094 }
1046 1095
1096 if (insn->dead_end)
1097 return 0;
1098
1047 insn = next_insn_same_sec(file, insn); 1099 insn = next_insn_same_sec(file, insn);
1048 if (!insn) { 1100 if (!insn) {
1049 WARN("%s: unexpected end of section", sec->name); 1101 WARN("%s: unexpected end of section", sec->name);
@@ -1220,7 +1272,7 @@ int cmd_check(int argc, const char **argv)
1220 1272
1221 INIT_LIST_HEAD(&file.insn_list); 1273 INIT_LIST_HEAD(&file.insn_list);
1222 hash_init(file.insn_hash); 1274 hash_init(file.insn_hash);
1223 file.whitelist = find_section_by_name(file.elf, "__func_stack_frame_non_standard"); 1275 file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard");
1224 file.rodata = find_section_by_name(file.elf, ".rodata"); 1276 file.rodata = find_section_by_name(file.elf, ".rodata");
1225 file.ignore_unreachables = false; 1277 file.ignore_unreachables = false;
1226 file.c_file = find_section_by_name(file.elf, ".comment"); 1278 file.c_file = find_section_by_name(file.elf, ".comment");
diff --git a/tools/perf/Build b/tools/perf/Build
index b12d5d1666e3..9b79f8d7db50 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -3,10 +3,12 @@ perf-y += builtin-annotate.o
3perf-y += builtin-config.o 3perf-y += builtin-config.o
4perf-y += builtin-diff.o 4perf-y += builtin-diff.o
5perf-y += builtin-evlist.o 5perf-y += builtin-evlist.o
6perf-y += builtin-ftrace.o
6perf-y += builtin-help.o 7perf-y += builtin-help.o
7perf-y += builtin-sched.o 8perf-y += builtin-sched.o
8perf-y += builtin-buildid-list.o 9perf-y += builtin-buildid-list.o
9perf-y += builtin-buildid-cache.o 10perf-y += builtin-buildid-cache.o
11perf-y += builtin-kallsyms.o
10perf-y += builtin-list.o 12perf-y += builtin-list.o
11perf-y += builtin-record.o 13perf-y += builtin-record.o
12perf-y += builtin-report.o 14perf-y += builtin-report.o
@@ -39,8 +41,7 @@ CFLAGS_builtin-help.o += $(paths)
39CFLAGS_builtin-timechart.o += $(paths) 41CFLAGS_builtin-timechart.o += $(paths)
40CFLAGS_perf.o += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" \ 42CFLAGS_perf.o += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" \
41 -DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" \ 43 -DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" \
42 -DPREFIX="BUILD_STR($(prefix_SQ))" \ 44 -DPREFIX="BUILD_STR($(prefix_SQ))"
43 -include $(OUTPUT)PERF-VERSION-FILE
44CFLAGS_builtin-trace.o += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_SQ))" 45CFLAGS_builtin-trace.o += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_SQ))"
45CFLAGS_builtin-report.o += -DTIPDIR="BUILD_STR($(tipdir_SQ))" 46CFLAGS_builtin-report.o += -DTIPDIR="BUILD_STR($(tipdir_SQ))"
46CFLAGS_builtin-report.o += -DDOCDIR="BUILD_STR($(srcdir_SQ)/Documentation)" 47CFLAGS_builtin-report.o += -DDOCDIR="BUILD_STR($(srcdir_SQ)/Documentation)"
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index 8ffbd272952d..a89273d8e744 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -39,6 +39,10 @@ OPTIONS
39--verbose:: 39--verbose::
40 Be more verbose. (Show symbol address, etc) 40 Be more verbose. (Show symbol address, etc)
41 41
42-q::
43--quiet::
44 Do not show any message. (Suppress -v)
45
42-D:: 46-D::
43--dump-raw-trace:: 47--dump-raw-trace::
44 Dump raw trace in ASCII. 48 Dump raw trace in ASCII.
diff --git a/tools/perf/Documentation/perf-c2c.txt b/tools/perf/Documentation/perf-c2c.txt
index 3f06730c7f47..2da07e51e119 100644
--- a/tools/perf/Documentation/perf-c2c.txt
+++ b/tools/perf/Documentation/perf-c2c.txt
@@ -248,7 +248,7 @@ output fields set for caheline offsets output:
248 Code address, Code symbol, Shared Object, Source line 248 Code address, Code symbol, Shared Object, Source line
249 dso - coalesced by shared object 249 dso - coalesced by shared object
250 250
251By default the coalescing is setup with 'pid,tid,iaddr'. 251By default the coalescing is setup with 'pid,iaddr'.
252 252
253STDIO OUTPUT 253STDIO OUTPUT
254------------ 254------------
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index 9365b75fd04f..5b4fff3adc4b 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -498,6 +498,18 @@ record.*::
498 But if this option is 'no-cache', it will not update the build-id cache. 498 But if this option is 'no-cache', it will not update the build-id cache.
499 'skip' skips post-processing and does not update the cache. 499 'skip' skips post-processing and does not update the cache.
500 500
501diff.*::
502 diff.order::
503 This option sets the number of columns to sort the result.
504 The default is 0, which means sorting by baseline.
505 Setting it to 1 will sort the result by delta (or other
506 compute method selected).
507
508 diff.compute::
509 This options sets the method for computing the diff result.
510 Possible values are 'delta', 'delta-abs', 'ratio' and
511 'wdiff'. Default is 'delta'.
512
501SEE ALSO 513SEE ALSO
502-------- 514--------
503linkperf:perf[1] 515linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index 3e9490b9c533..a79c84ae61aa 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -73,6 +73,10 @@ OPTIONS
73 Be verbose, for instance, show the raw counts in addition to the 73 Be verbose, for instance, show the raw counts in addition to the
74 diff. 74 diff.
75 75
76-q::
77--quiet::
78 Do not show any message. (Suppress -v)
79
76-f:: 80-f::
77--force:: 81--force::
78 Don't do ownership validation. 82 Don't do ownership validation.
@@ -86,8 +90,9 @@ OPTIONS
86 90
87-c:: 91-c::
88--compute:: 92--compute::
89 Differential computation selection - delta,ratio,wdiff (default is delta). 93 Differential computation selection - delta, ratio, wdiff, delta-abs
90 See COMPARISON METHODS section for more info. 94 (default is delta-abs). Default can be changed using diff.compute
95 config option. See COMPARISON METHODS section for more info.
91 96
92-p:: 97-p::
93--period:: 98--period::
@@ -99,7 +104,11 @@ OPTIONS
99 104
100-o:: 105-o::
101--order:: 106--order::
102 Specify compute sorting column number. 107 Specify compute sorting column number. 0 means sorting by baseline
108 overhead and 1 (default) means sorting by computed value of column 1
109 (data from the first file other base baseline). Values more than 1
110 can be used only if enough data files are provided.
111 The default value can be set using the diff.order config option.
103 112
104--percentage:: 113--percentage::
105 Determine how to display the overhead percentage of filtered entries. 114 Determine how to display the overhead percentage of filtered entries.
@@ -181,6 +190,10 @@ with:
181 relative to how entries are filtered. Use --percentage=absolute to 190 relative to how entries are filtered. Use --percentage=absolute to
182 prevent such fluctuation. 191 prevent such fluctuation.
183 192
193delta-abs
194~~~~~~~~~
195Same as 'delta` method, but sort the result with the absolute values.
196
184ratio 197ratio
185~~~~~ 198~~~~~
186If specified the 'Ratio' column is displayed with value 'r' computed as: 199If specified the 'Ratio' column is displayed with value 'r' computed as:
diff --git a/tools/perf/Documentation/perf-ftrace.txt b/tools/perf/Documentation/perf-ftrace.txt
new file mode 100644
index 000000000000..2d96de6132a9
--- /dev/null
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -0,0 +1,36 @@
1perf-ftrace(1)
2=============
3
4NAME
5----
6perf-ftrace - simple wrapper for kernel's ftrace functionality
7
8
9SYNOPSIS
10--------
11[verse]
12'perf ftrace' <command>
13
14DESCRIPTION
15-----------
16The 'perf ftrace' command is a simple wrapper of kernel's ftrace
17functionality. It only supports single thread tracing currently and
18just reads trace_pipe in text and then write it to stdout.
19
20The following options apply to perf ftrace.
21
22OPTIONS
23-------
24
25-t::
26--tracer=::
27 Tracer to use: function_graph or function.
28
29-v::
30--verbose=::
31 Verbosity level.
32
33
34SEE ALSO
35--------
36linkperf:perf-record[1], linkperf:perf-trace[1]
diff --git a/tools/perf/Documentation/perf-kallsyms.txt b/tools/perf/Documentation/perf-kallsyms.txt
new file mode 100644
index 000000000000..954ea9e21236
--- /dev/null
+++ b/tools/perf/Documentation/perf-kallsyms.txt
@@ -0,0 +1,24 @@
1perf-kallsyms(1)
2==============
3
4NAME
5----
6perf-kallsyms - Searches running kernel for symbols
7
8SYNOPSIS
9--------
10[verse]
11'perf kallsyms <options> symbol_name[,symbol_name...]'
12
13DESCRIPTION
14-----------
15This command searches the running kernel kallsyms file for the given symbol(s)
16and prints information about it, including the DSO, the kallsyms begin/end
17addresses and the addresses in the ELF kallsyms symbol table (for symbols in
18modules).
19
20OPTIONS
21-------
22-v::
23--verbose=::
24 Increase verbosity level, showing details about symbol table loading, etc.
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 5054d9147f0f..b16003ec14a7 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -157,7 +157,7 @@ OPTIONS
157 157
158-a:: 158-a::
159--all-cpus:: 159--all-cpus::
160 System-wide collection from all CPUs. 160 System-wide collection from all CPUs (default if no target is specified).
161 161
162-p:: 162-p::
163--pid=:: 163--pid=::
@@ -421,9 +421,19 @@ Configure all used events to run in user space.
421--timestamp-filename 421--timestamp-filename
422Append timestamp to output file name. 422Append timestamp to output file name.
423 423
424--switch-output:: 424--switch-output[=mode]::
425Generate multiple perf.data files, timestamp prefixed, switching to a new one 425Generate multiple perf.data files, timestamp prefixed, switching to a new one
426when receiving a SIGUSR2. 426based on 'mode' value:
427 "signal" - when receiving a SIGUSR2 (default value) or
428 <size> - when reaching the size threshold, size is expected to
429 be a number with appended unit character - B/K/M/G
430 <time> - when reaching the time threshold, size is expected to
431 be a number with appended unit character - s/m/h/d
432
433 Note: the precision of the size threshold hugely depends
434 on your configuration - the number and size of your ring
435 buffers (-m). It is generally more precise for higher sizes
436 (like >5M), for lower values expect different sizes.
427 437
428A possible use case is to, given an external event, slice the perf.data file 438A possible use case is to, given an external event, slice the perf.data file
429that gets then processed, possibly via a perf script, to decide if that 439that gets then processed, possibly via a perf script, to decide if that
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index f2914f03ae7b..c04cc0647c16 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -25,6 +25,10 @@ OPTIONS
25--verbose:: 25--verbose::
26 Be more verbose. (show symbol address, etc) 26 Be more verbose. (show symbol address, etc)
27 27
28-q::
29--quiet::
30 Do not show any message. (Suppress -v)
31
28-n:: 32-n::
29--show-nr-samples:: 33--show-nr-samples::
30 Show the number of samples for each symbol 34 Show the number of samples for each symbol
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index 76173969ab80..d33deddb0146 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -143,6 +143,8 @@ OPTIONS for 'perf sched timehist'
143 stop time is not given (i.e, time string is 'x.y,') then analysis goes 143 stop time is not given (i.e, time string is 'x.y,') then analysis goes
144 to end of file. 144 to end of file.
145 145
146--state::
147 Show task state when it switched out.
146 148
147SEE ALSO 149SEE ALSO
148-------- 150--------
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 5dc5c6a09ac4..4ed5f239ba7d 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -36,7 +36,7 @@ There are several variants of perf script:
36 36
37 'perf script report <script> [args]' to run and display the results 37 'perf script report <script> [args]' to run and display the results
38 of <script>. <script> is the name displayed in the output of 'perf 38 of <script>. <script> is the name displayed in the output of 'perf
39 trace --list' i.e. the actual script name minus any language 39 script --list' i.e. the actual script name minus any language
40 extension. The perf.data output from a previous run of 'perf script 40 extension. The perf.data output from a previous run of 'perf script
41 record <script>' is used and should be present for this command to 41 record <script>' is used and should be present for this command to
42 succeed. [args] refers to the (mainly optional) args expected by 42 succeed. [args] refers to the (mainly optional) args expected by
@@ -76,7 +76,7 @@ OPTIONS
76 Any command you can specify in a shell. 76 Any command you can specify in a shell.
77 77
78-D:: 78-D::
79--dump-raw-script=:: 79--dump-raw-trace=::
80 Display verbose dump of the trace data. 80 Display verbose dump of the trace data.
81 81
82-L:: 82-L::
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index d96ccd4844df..aecf2a87e7d6 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -63,7 +63,7 @@ report::
63 63
64-a:: 64-a::
65--all-cpus:: 65--all-cpus::
66 system-wide collection from all CPUs 66 system-wide collection from all CPUs (default if no target is specified)
67 67
68-c:: 68-c::
69--scale:: 69--scale::
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 781b019751a4..afd728672b6f 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -35,7 +35,10 @@ OPTIONS
35 35
36-e:: 36-e::
37--expr:: 37--expr::
38 List of syscalls to show, currently only syscall names. 38--event::
39 List of syscalls and other perf events (tracepoints, HW cache events,
40 etc) to show.
41 See 'perf list' for a complete list of events.
39 Prefixing with ! shows all syscalls but the ones specified. You may 42 Prefixing with ! shows all syscalls but the ones specified. You may
40 need to escape it. 43 need to escape it.
41 44
@@ -135,9 +138,6 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
135--kernel-syscall-graph:: 138--kernel-syscall-graph::
136 Show the kernel callchains on the syscall exit path. 139 Show the kernel callchains on the syscall exit path.
137 140
138--event::
139 Trace other events, see 'perf list' for a complete list.
140
141--max-stack:: 141--max-stack::
142 Set the stack depth limit when parsing the callchain, anything 142 Set the stack depth limit when parsing the callchain, anything
143 beyond the specified depth will be ignored. Note that at this point 143 beyond the specified depth will be ignored. Note that at this point
diff --git a/tools/perf/Documentation/tips.txt b/tools/perf/Documentation/tips.txt
index 8a6479c0eac9..170b0289a7bc 100644
--- a/tools/perf/Documentation/tips.txt
+++ b/tools/perf/Documentation/tips.txt
@@ -22,7 +22,7 @@ If you have debuginfo enabled, try: perf report -s sym,srcline
22For memory address profiling, try: perf mem record / perf mem report 22For memory address profiling, try: perf mem record / perf mem report
23For tracepoint events, try: perf report -s trace_fields 23For tracepoint events, try: perf report -s trace_fields
24To record callchains for each sample: perf record -g 24To record callchains for each sample: perf record -g
25To record every process run by an user: perf record -u <user> 25To record every process run by a user: perf record -u <user>
26Skip collecing build-id when recording: perf record -B 26Skip collecing build-id when recording: perf record -B
27To change sampling frequency to 100 Hz: perf record -F 100 27To change sampling frequency to 100 Hz: perf record -F 100
28See assembly instructions with percentage: perf annotate <symbol> 28See assembly instructions with percentage: perf annotate <symbol>
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index a511e5f31e36..8672f835ae4e 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -61,6 +61,7 @@ tools/include/asm-generic/bitops.h
61tools/include/linux/atomic.h 61tools/include/linux/atomic.h
62tools/include/linux/bitops.h 62tools/include/linux/bitops.h
63tools/include/linux/compiler.h 63tools/include/linux/compiler.h
64tools/include/linux/compiler-gcc.h
64tools/include/linux/coresight-pmu.h 65tools/include/linux/coresight-pmu.h
65tools/include/linux/filter.h 66tools/include/linux/filter.h
66tools/include/linux/hash.h 67tools/include/linux/hash.h
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 76c84f0eec52..27c9fbca7bd9 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -144,8 +144,12 @@ ifndef DEBUG
144endif 144endif
145 145
146ifeq ($(DEBUG),0) 146ifeq ($(DEBUG),0)
147ifeq ($(CC), clang)
148 CFLAGS += -O3
149else
147 CFLAGS += -O6 150 CFLAGS += -O6
148endif 151endif
152endif
149 153
150ifdef PARSER_DEBUG 154ifdef PARSER_DEBUG
151 PARSER_DEBUG_BISON := -t 155 PARSER_DEBUG_BISON := -t
@@ -171,6 +175,10 @@ PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
171PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null) 175PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
172PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) 176PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
173 177
178ifeq ($(CC), clang)
179 PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS))
180endif
181
174FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS) 182FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS)
175FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS) 183FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS)
176FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS) 184FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS)
@@ -291,8 +299,10 @@ else
291 endif 299 endif
292 endif 300 endif
293 ifneq ($(feature-dwarf), 1) 301 ifneq ($(feature-dwarf), 1)
294 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); 302 ifndef NO_DWARF
295 NO_DWARF := 1 303 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
304 NO_DWARF := 1
305 endif
296 else 306 else
297 ifneq ($(feature-dwarf_getlocations), 1) 307 ifneq ($(feature-dwarf_getlocations), 1)
298 msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157); 308 msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157);
@@ -595,6 +605,9 @@ else
595 PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) 605 PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
596 PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil 606 PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil
597 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) 607 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
608 ifeq ($(CC), clang)
609 PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS))
610 endif
598 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 611 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
599 612
600 ifneq ($(feature-libpython), 1) 613 ifneq ($(feature-libpython), 1)
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 8bb16aa9d661..79fe31f20a17 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -661,6 +661,7 @@ ifndef NO_PERF_READ_VDSOX32
661endif 661endif
662ifndef NO_JVMTI 662ifndef NO_JVMTI
663 $(call QUIET_INSTALL, $(LIBJVMTI)) \ 663 $(call QUIET_INSTALL, $(LIBJVMTI)) \
664 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \
664 $(INSTALL) $(OUTPUT)$(LIBJVMTI) '$(DESTDIR_SQ)$(libdir_SQ)'; 665 $(INSTALL) $(OUTPUT)$(LIBJVMTI) '$(DESTDIR_SQ)$(libdir_SQ)';
665endif 666endif
666 $(call QUIET_INSTALL, libexec) \ 667 $(call QUIET_INSTALL, libexec) \
@@ -725,13 +726,13 @@ config-clean:
725 $(call QUIET_CLEAN, config) 726 $(call QUIET_CLEAN, config)
726 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null 727 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null
727 728
728clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean 729clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean fixdep-clean
729 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) 730 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
730 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 731 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
731 $(Q)$(RM) $(OUTPUT).config-detected 732 $(Q)$(RM) $(OUTPUT).config-detected
732 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(OUTPUT)pmu-events/jevents $(OUTPUT)$(LIBJVMTI).so 733 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(OUTPUT)pmu-events/jevents $(OUTPUT)$(LIBJVMTI).so
733 $(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* \ 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* \
734 $(OUTPUT)util/intel-pt-decoder/inat-tables.c $(OUTPUT)fixdep \ 735 $(OUTPUT)util/intel-pt-decoder/inat-tables.c \
735 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \ 736 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
736 $(OUTPUT)pmu-events/pmu-events.c 737 $(OUTPUT)pmu-events/pmu-events.c
737 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 738 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
diff --git a/tools/perf/arch/arm64/Makefile b/tools/perf/arch/arm64/Makefile
index 18b13518d8d8..eebe1ec9d2ee 100644
--- a/tools/perf/arch/arm64/Makefile
+++ b/tools/perf/arch/arm64/Makefile
@@ -2,3 +2,4 @@ ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3endif 3endif
4PERF_HAVE_JITDUMP := 1 4PERF_HAVE_JITDUMP := 1
5PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
diff --git a/tools/perf/arch/arm64/include/dwarf-regs-table.h b/tools/perf/arch/arm64/include/dwarf-regs-table.h
index 26759363f921..36e375f5a211 100644
--- a/tools/perf/arch/arm64/include/dwarf-regs-table.h
+++ b/tools/perf/arch/arm64/include/dwarf-regs-table.h
@@ -2,12 +2,12 @@
2/* This is included in perf/util/dwarf-regs.c */ 2/* This is included in perf/util/dwarf-regs.c */
3 3
4static const char * const aarch64_regstr_tbl[] = { 4static const char * const aarch64_regstr_tbl[] = {
5 "%r0", "%r1", "%r2", "%r3", "%r4", 5 "%x0", "%x1", "%x2", "%x3", "%x4",
6 "%r5", "%r6", "%r7", "%r8", "%r9", 6 "%x5", "%x6", "%x7", "%x8", "%x9",
7 "%r10", "%r11", "%r12", "%r13", "%r14", 7 "%x10", "%x11", "%x12", "%x13", "%x14",
8 "%r15", "%r16", "%r17", "%r18", "%r19", 8 "%x15", "%x16", "%x17", "%x18", "%x19",
9 "%r20", "%r21", "%r22", "%r23", "%r24", 9 "%x20", "%x21", "%x22", "%x23", "%x24",
10 "%r25", "%r26", "%r27", "%r28", "%r29", 10 "%x25", "%x26", "%x27", "%x28", "%x29",
11 "%lr", "%sp", 11 "%lr", "%sp",
12}; 12};
13#endif 13#endif
diff --git a/tools/perf/arch/arm64/util/dwarf-regs.c b/tools/perf/arch/arm64/util/dwarf-regs.c
index d49efeb8172e..068b6189157b 100644
--- a/tools/perf/arch/arm64/util/dwarf-regs.c
+++ b/tools/perf/arch/arm64/util/dwarf-regs.c
@@ -10,17 +10,20 @@
10 10
11#include <stddef.h> 11#include <stddef.h>
12#include <dwarf-regs.h> 12#include <dwarf-regs.h>
13#include <linux/ptrace.h> /* for struct user_pt_regs */
14#include "util.h"
13 15
14struct pt_regs_dwarfnum { 16struct pt_regs_dwarfnum {
15 const char *name; 17 const char *name;
16 unsigned int dwarfnum; 18 unsigned int dwarfnum;
17}; 19};
18 20
19#define STR(s) #s
20#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num} 21#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
21#define GPR_DWARFNUM_NAME(num) \ 22#define GPR_DWARFNUM_NAME(num) \
22 {.name = STR(%x##num), .dwarfnum = num} 23 {.name = STR(%x##num), .dwarfnum = num}
23#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0} 24#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
25#define DWARFNUM2OFFSET(index) \
26 (index * sizeof((struct user_pt_regs *)0)->regs[0])
24 27
25/* 28/*
26 * Reference: 29 * Reference:
@@ -78,3 +81,13 @@ const char *get_arch_regstr(unsigned int n)
78 return roff->name; 81 return roff->name;
79 return NULL; 82 return NULL;
80} 83}
84
85int regs_query_register_offset(const char *name)
86{
87 const struct pt_regs_dwarfnum *roff;
88
89 for (roff = regdwarfnum_table; roff->name != NULL; roff++)
90 if (!strcmp(roff->name, name))
91 return DWARFNUM2OFFSET(roff->dwarfnum);
92 return -EINVAL;
93}
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index bfbb6b5f609c..da04b8c5568a 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -130,8 +130,6 @@ int bench_futex_hash(int argc, const char **argv,
130 } 130 }
131 131
132 ncpus = sysconf(_SC_NPROCESSORS_ONLN); 132 ncpus = sysconf(_SC_NPROCESSORS_ONLN);
133 nsecs = futexbench_sanitize_numeric(nsecs);
134 nfutexes = futexbench_sanitize_numeric(nfutexes);
135 133
136 sigfillset(&act.sa_mask); 134 sigfillset(&act.sa_mask);
137 act.sa_sigaction = toggle_done; 135 act.sa_sigaction = toggle_done;
@@ -139,8 +137,6 @@ int bench_futex_hash(int argc, const char **argv,
139 137
140 if (!nthreads) /* default to the number of CPUs */ 138 if (!nthreads) /* default to the number of CPUs */
141 nthreads = ncpus; 139 nthreads = ncpus;
142 else
143 nthreads = futexbench_sanitize_numeric(nthreads);
144 140
145 worker = calloc(nthreads, sizeof(*worker)); 141 worker = calloc(nthreads, sizeof(*worker));
146 if (!worker) 142 if (!worker)
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index 6d9d6c40a916..91877777ec6e 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -152,7 +152,6 @@ int bench_futex_lock_pi(int argc, const char **argv,
152 goto err; 152 goto err;
153 153
154 ncpus = sysconf(_SC_NPROCESSORS_ONLN); 154 ncpus = sysconf(_SC_NPROCESSORS_ONLN);
155 nsecs = futexbench_sanitize_numeric(nsecs);
156 155
157 sigfillset(&act.sa_mask); 156 sigfillset(&act.sa_mask);
158 act.sa_sigaction = toggle_done; 157 act.sa_sigaction = toggle_done;
@@ -160,8 +159,6 @@ int bench_futex_lock_pi(int argc, const char **argv,
160 159
161 if (!nthreads) 160 if (!nthreads)
162 nthreads = ncpus; 161 nthreads = ncpus;
163 else
164 nthreads = futexbench_sanitize_numeric(nthreads);
165 162
166 worker = calloc(nthreads, sizeof(*worker)); 163 worker = calloc(nthreads, sizeof(*worker));
167 if (!worker) 164 if (!worker)
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index fd4ee95b689a..2b9705a8734c 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -128,8 +128,6 @@ int bench_futex_requeue(int argc, const char **argv,
128 128
129 if (!nthreads) 129 if (!nthreads)
130 nthreads = ncpus; 130 nthreads = ncpus;
131 else
132 nthreads = futexbench_sanitize_numeric(nthreads);
133 131
134 worker = calloc(nthreads, sizeof(*worker)); 132 worker = calloc(nthreads, sizeof(*worker));
135 if (!worker) 133 if (!worker)
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index beaa6c142477..2c8fa67ad537 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -217,12 +217,8 @@ int bench_futex_wake_parallel(int argc, const char **argv,
217 sigaction(SIGINT, &act, NULL); 217 sigaction(SIGINT, &act, NULL);
218 218
219 ncpus = sysconf(_SC_NPROCESSORS_ONLN); 219 ncpus = sysconf(_SC_NPROCESSORS_ONLN);
220 nwaking_threads = futexbench_sanitize_numeric(nwaking_threads);
221
222 if (!nblocked_threads) 220 if (!nblocked_threads)
223 nblocked_threads = ncpus; 221 nblocked_threads = ncpus;
224 else
225 nblocked_threads = futexbench_sanitize_numeric(nblocked_threads);
226 222
227 /* some sanity checks */ 223 /* some sanity checks */
228 if (nwaking_threads > nblocked_threads || !nwaking_threads) 224 if (nwaking_threads > nblocked_threads || !nwaking_threads)
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 46efcb98b5a4..e246b1b8388a 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -129,7 +129,6 @@ int bench_futex_wake(int argc, const char **argv,
129 } 129 }
130 130
131 ncpus = sysconf(_SC_NPROCESSORS_ONLN); 131 ncpus = sysconf(_SC_NPROCESSORS_ONLN);
132 nwakes = futexbench_sanitize_numeric(nwakes);
133 132
134 sigfillset(&act.sa_mask); 133 sigfillset(&act.sa_mask);
135 act.sa_sigaction = toggle_done; 134 act.sa_sigaction = toggle_done;
@@ -137,8 +136,6 @@ int bench_futex_wake(int argc, const char **argv,
137 136
138 if (!nthreads) 137 if (!nthreads)
139 nthreads = ncpus; 138 nthreads = ncpus;
140 else
141 nthreads = futexbench_sanitize_numeric(nthreads);
142 139
143 worker = calloc(nthreads, sizeof(*worker)); 140 worker = calloc(nthreads, sizeof(*worker));
144 if (!worker) 141 if (!worker)
diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index ba7c735c0c62..b2e06d1190d0 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -7,7 +7,6 @@
7#ifndef _FUTEX_H 7#ifndef _FUTEX_H
8#define _FUTEX_H 8#define _FUTEX_H
9 9
10#include <stdlib.h>
11#include <unistd.h> 10#include <unistd.h>
12#include <sys/syscall.h> 11#include <sys/syscall.h>
13#include <sys/types.h> 12#include <sys/types.h>
@@ -100,7 +99,4 @@ static inline int pthread_attr_setaffinity_np(pthread_attr_t *attr,
100} 99}
101#endif 100#endif
102 101
103/* User input sanitation */
104#define futexbench_sanitize_numeric(__n) abs((__n))
105
106#endif /* _FUTEX_H */ 102#endif /* _FUTEX_H */
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 8efe904e486b..3083fc36282b 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -43,6 +43,7 @@
43/* 43/*
44 * Debug printf: 44 * Debug printf:
45 */ 45 */
46#undef dprintf
46#define dprintf(x...) do { if (g && g->p.show_details >= 1) printf(x); } while (0) 47#define dprintf(x...) do { if (g && g->p.show_details >= 1) printf(x); } while (0)
47 48
48struct thread_data { 49struct thread_data {
@@ -1573,13 +1574,13 @@ static int __bench_numa(const char *name)
1573 "GB/sec,", "total-speed", "GB/sec total speed"); 1574 "GB/sec,", "total-speed", "GB/sec total speed");
1574 1575
1575 if (g->p.show_details >= 2) { 1576 if (g->p.show_details >= 2) {
1576 char tname[32]; 1577 char tname[14 + 2 * 10 + 1];
1577 struct thread_data *td; 1578 struct thread_data *td;
1578 for (p = 0; p < g->p.nr_proc; p++) { 1579 for (p = 0; p < g->p.nr_proc; p++) {
1579 for (t = 0; t < g->p.nr_threads; t++) { 1580 for (t = 0; t < g->p.nr_threads; t++) {
1580 memset(tname, 0, 32); 1581 memset(tname, 0, sizeof(tname));
1581 td = g->threads + p*g->p.nr_threads + t; 1582 td = g->threads + p*g->p.nr_threads + t;
1582 snprintf(tname, 32, "process%d:thread%d", p, t); 1583 snprintf(tname, sizeof(tname), "process%d:thread%d", p, t);
1583 print_res(tname, td->speed_gbs, 1584 print_res(tname, td->speed_gbs,
1584 "GB/sec", "thread-speed", "GB/sec/thread speed"); 1585 "GB/sec", "thread-speed", "GB/sec/thread speed");
1585 print_res(tname, td->system_time_ns / NSEC_PER_SEC, 1586 print_res(tname, td->system_time_ns / NSEC_PER_SEC,
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index ebb628332a6e..4f52d85f5ebc 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -410,6 +410,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
410 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), 410 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
411 OPT_INCR('v', "verbose", &verbose, 411 OPT_INCR('v', "verbose", &verbose,
412 "be more verbose (show symbol address, etc)"), 412 "be more verbose (show symbol address, etc)"),
413 OPT_BOOLEAN('q', "quiet", &quiet, "do now show any message"),
413 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 414 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
414 "dump raw trace in ASCII"), 415 "dump raw trace in ASCII"),
415 OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"), 416 OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"),
@@ -463,6 +464,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
463 annotate.sym_hist_filter = argv[0]; 464 annotate.sym_hist_filter = argv[0];
464 } 465 }
465 466
467 if (quiet)
468 perf_quiet_option();
469
466 file.path = input_name; 470 file.path = input_name;
467 471
468 annotate.session = perf_session__new(&file, false, &annotate.tool); 472 annotate.session = perf_session__new(&file, false, &annotate.tool);
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index f8ca7a4ebabc..e2b21723bbf8 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -58,7 +58,7 @@ struct c2c_hist_entry {
58 struct hist_entry he; 58 struct hist_entry he;
59}; 59};
60 60
61static char const *coalesce_default = "pid,tid,iaddr"; 61static char const *coalesce_default = "pid,iaddr";
62 62
63struct perf_c2c { 63struct perf_c2c {
64 struct perf_tool tool; 64 struct perf_tool tool;
@@ -2476,6 +2476,7 @@ static int build_cl_output(char *cl_sort, bool no_source)
2476 "mean_rmt," 2476 "mean_rmt,"
2477 "mean_lcl," 2477 "mean_lcl,"
2478 "mean_load," 2478 "mean_load,"
2479 "tot_recs,"
2479 "cpucnt,", 2480 "cpucnt,",
2480 add_sym ? "symbol," : "", 2481 add_sym ? "symbol," : "",
2481 add_dso ? "dso," : "", 2482 add_dso ? "dso," : "",
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 933aeec46f4a..1b96a3122228 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -17,6 +17,7 @@
17#include "util/symbol.h" 17#include "util/symbol.h"
18#include "util/util.h" 18#include "util/util.h"
19#include "util/data.h" 19#include "util/data.h"
20#include "util/config.h"
20 21
21#include <stdlib.h> 22#include <stdlib.h>
22#include <math.h> 23#include <math.h>
@@ -30,6 +31,7 @@ enum {
30 PERF_HPP_DIFF__RATIO, 31 PERF_HPP_DIFF__RATIO,
31 PERF_HPP_DIFF__WEIGHTED_DIFF, 32 PERF_HPP_DIFF__WEIGHTED_DIFF,
32 PERF_HPP_DIFF__FORMULA, 33 PERF_HPP_DIFF__FORMULA,
34 PERF_HPP_DIFF__DELTA_ABS,
33 35
34 PERF_HPP_DIFF__MAX_INDEX 36 PERF_HPP_DIFF__MAX_INDEX
35}; 37};
@@ -64,7 +66,7 @@ static bool force;
64static bool show_period; 66static bool show_period;
65static bool show_formula; 67static bool show_formula;
66static bool show_baseline_only; 68static bool show_baseline_only;
67static unsigned int sort_compute; 69static unsigned int sort_compute = 1;
68 70
69static s64 compute_wdiff_w1; 71static s64 compute_wdiff_w1;
70static s64 compute_wdiff_w2; 72static s64 compute_wdiff_w2;
@@ -73,19 +75,22 @@ enum {
73 COMPUTE_DELTA, 75 COMPUTE_DELTA,
74 COMPUTE_RATIO, 76 COMPUTE_RATIO,
75 COMPUTE_WEIGHTED_DIFF, 77 COMPUTE_WEIGHTED_DIFF,
78 COMPUTE_DELTA_ABS,
76 COMPUTE_MAX, 79 COMPUTE_MAX,
77}; 80};
78 81
79const char *compute_names[COMPUTE_MAX] = { 82const char *compute_names[COMPUTE_MAX] = {
80 [COMPUTE_DELTA] = "delta", 83 [COMPUTE_DELTA] = "delta",
84 [COMPUTE_DELTA_ABS] = "delta-abs",
81 [COMPUTE_RATIO] = "ratio", 85 [COMPUTE_RATIO] = "ratio",
82 [COMPUTE_WEIGHTED_DIFF] = "wdiff", 86 [COMPUTE_WEIGHTED_DIFF] = "wdiff",
83}; 87};
84 88
85static int compute; 89static int compute = COMPUTE_DELTA_ABS;
86 90
87static int compute_2_hpp[COMPUTE_MAX] = { 91static int compute_2_hpp[COMPUTE_MAX] = {
88 [COMPUTE_DELTA] = PERF_HPP_DIFF__DELTA, 92 [COMPUTE_DELTA] = PERF_HPP_DIFF__DELTA,
93 [COMPUTE_DELTA_ABS] = PERF_HPP_DIFF__DELTA_ABS,
89 [COMPUTE_RATIO] = PERF_HPP_DIFF__RATIO, 94 [COMPUTE_RATIO] = PERF_HPP_DIFF__RATIO,
90 [COMPUTE_WEIGHTED_DIFF] = PERF_HPP_DIFF__WEIGHTED_DIFF, 95 [COMPUTE_WEIGHTED_DIFF] = PERF_HPP_DIFF__WEIGHTED_DIFF,
91}; 96};
@@ -111,6 +116,10 @@ static struct header_column {
111 .name = "Delta", 116 .name = "Delta",
112 .width = 7, 117 .width = 7,
113 }, 118 },
119 [PERF_HPP_DIFF__DELTA_ABS] = {
120 .name = "Delta Abs",
121 .width = 7,
122 },
114 [PERF_HPP_DIFF__RATIO] = { 123 [PERF_HPP_DIFF__RATIO] = {
115 .name = "Ratio", 124 .name = "Ratio",
116 .width = 14, 125 .width = 14,
@@ -298,6 +307,7 @@ static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
298{ 307{
299 switch (compute) { 308 switch (compute) {
300 case COMPUTE_DELTA: 309 case COMPUTE_DELTA:
310 case COMPUTE_DELTA_ABS:
301 return formula_delta(he, pair, buf, size); 311 return formula_delta(he, pair, buf, size);
302 case COMPUTE_RATIO: 312 case COMPUTE_RATIO:
303 return formula_ratio(he, pair, buf, size); 313 return formula_ratio(he, pair, buf, size);
@@ -461,6 +471,7 @@ static void hists__precompute(struct hists *hists)
461 471
462 switch (compute) { 472 switch (compute) {
463 case COMPUTE_DELTA: 473 case COMPUTE_DELTA:
474 case COMPUTE_DELTA_ABS:
464 compute_delta(he, pair); 475 compute_delta(he, pair);
465 break; 476 break;
466 case COMPUTE_RATIO: 477 case COMPUTE_RATIO:
@@ -498,6 +509,13 @@ __hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
498 509
499 return cmp_doubles(l, r); 510 return cmp_doubles(l, r);
500 } 511 }
512 case COMPUTE_DELTA_ABS:
513 {
514 double l = fabs(left->diff.period_ratio_delta);
515 double r = fabs(right->diff.period_ratio_delta);
516
517 return cmp_doubles(l, r);
518 }
501 case COMPUTE_RATIO: 519 case COMPUTE_RATIO:
502 { 520 {
503 double l = left->diff.period_ratio; 521 double l = left->diff.period_ratio;
@@ -564,7 +582,7 @@ hist_entry__cmp_compute_idx(struct hist_entry *left, struct hist_entry *right,
564 if (!p_left || !p_right) 582 if (!p_left || !p_right)
565 return p_left ? -1 : 1; 583 return p_left ? -1 : 1;
566 584
567 if (c != COMPUTE_DELTA) { 585 if (c != COMPUTE_DELTA && c != COMPUTE_DELTA_ABS) {
568 /* 586 /*
569 * The delta can be computed without the baseline, but 587 * The delta can be computed without the baseline, but
570 * others are not. Put those entries which have no 588 * others are not. Put those entries which have no
@@ -607,6 +625,15 @@ hist_entry__cmp_delta(struct perf_hpp_fmt *fmt,
607} 625}
608 626
609static int64_t 627static int64_t
628hist_entry__cmp_delta_abs(struct perf_hpp_fmt *fmt,
629 struct hist_entry *left, struct hist_entry *right)
630{
631 struct data__file *d = fmt_to_data_file(fmt);
632
633 return hist_entry__cmp_compute(right, left, COMPUTE_DELTA_ABS, d->idx);
634}
635
636static int64_t
610hist_entry__cmp_ratio(struct perf_hpp_fmt *fmt, 637hist_entry__cmp_ratio(struct perf_hpp_fmt *fmt,
611 struct hist_entry *left, struct hist_entry *right) 638 struct hist_entry *left, struct hist_entry *right)
612{ 639{
@@ -633,6 +660,14 @@ hist_entry__cmp_delta_idx(struct perf_hpp_fmt *fmt __maybe_unused,
633} 660}
634 661
635static int64_t 662static int64_t
663hist_entry__cmp_delta_abs_idx(struct perf_hpp_fmt *fmt __maybe_unused,
664 struct hist_entry *left, struct hist_entry *right)
665{
666 return hist_entry__cmp_compute_idx(right, left, COMPUTE_DELTA_ABS,
667 sort_compute);
668}
669
670static int64_t
636hist_entry__cmp_ratio_idx(struct perf_hpp_fmt *fmt __maybe_unused, 671hist_entry__cmp_ratio_idx(struct perf_hpp_fmt *fmt __maybe_unused,
637 struct hist_entry *left, struct hist_entry *right) 672 struct hist_entry *left, struct hist_entry *right)
638{ 673{
@@ -656,7 +691,7 @@ static void hists__process(struct hists *hists)
656 hists__precompute(hists); 691 hists__precompute(hists);
657 hists__output_resort(hists, NULL); 692 hists__output_resort(hists, NULL);
658 693
659 hists__fprintf(hists, true, 0, 0, 0, stdout, 694 hists__fprintf(hists, !quiet, 0, 0, 0, stdout,
660 symbol_conf.use_callchain); 695 symbol_conf.use_callchain);
661} 696}
662 697
@@ -704,12 +739,14 @@ static void data_process(void)
704 hists__link(hists_base, hists); 739 hists__link(hists_base, hists);
705 } 740 }
706 741
707 fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n", 742 if (!quiet) {
708 perf_evsel__name(evsel_base)); 743 fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n",
744 perf_evsel__name(evsel_base));
745 }
709 746
710 first = false; 747 first = false;
711 748
712 if (verbose || data__files_cnt > 2) 749 if (verbose > 0 || ((data__files_cnt > 2) && !quiet))
713 data__fprintf(); 750 data__fprintf();
714 751
715 /* Don't sort callchain for perf diff */ 752 /* Don't sort callchain for perf diff */
@@ -772,10 +809,11 @@ static const char * const diff_usage[] = {
772static const struct option options[] = { 809static const struct option options[] = {
773 OPT_INCR('v', "verbose", &verbose, 810 OPT_INCR('v', "verbose", &verbose,
774 "be more verbose (show symbol address, etc)"), 811 "be more verbose (show symbol address, etc)"),
812 OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any message"),
775 OPT_BOOLEAN('b', "baseline-only", &show_baseline_only, 813 OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
776 "Show only items with match in baseline"), 814 "Show only items with match in baseline"),
777 OPT_CALLBACK('c', "compute", &compute, 815 OPT_CALLBACK('c', "compute", &compute,
778 "delta,ratio,wdiff:w1,w2 (default delta)", 816 "delta,delta-abs,ratio,wdiff:w1,w2 (default delta-abs)",
779 "Entries differential computation selection", 817 "Entries differential computation selection",
780 setup_compute), 818 setup_compute),
781 OPT_BOOLEAN('p', "period", &show_period, 819 OPT_BOOLEAN('p', "period", &show_period,
@@ -945,6 +983,7 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair,
945 983
946 switch (idx) { 984 switch (idx) {
947 case PERF_HPP_DIFF__DELTA: 985 case PERF_HPP_DIFF__DELTA:
986 case PERF_HPP_DIFF__DELTA_ABS:
948 if (pair->diff.computed) 987 if (pair->diff.computed)
949 diff = pair->diff.period_ratio_delta; 988 diff = pair->diff.period_ratio_delta;
950 else 989 else
@@ -1118,6 +1157,10 @@ static void data__hpp_register(struct data__file *d, int idx)
1118 fmt->color = hpp__color_wdiff; 1157 fmt->color = hpp__color_wdiff;
1119 fmt->sort = hist_entry__cmp_wdiff; 1158 fmt->sort = hist_entry__cmp_wdiff;
1120 break; 1159 break;
1160 case PERF_HPP_DIFF__DELTA_ABS:
1161 fmt->color = hpp__color_delta;
1162 fmt->sort = hist_entry__cmp_delta_abs;
1163 break;
1121 default: 1164 default:
1122 fmt->sort = hist_entry__cmp_nop; 1165 fmt->sort = hist_entry__cmp_nop;
1123 break; 1166 break;
@@ -1195,6 +1238,9 @@ static int ui_init(void)
1195 case COMPUTE_WEIGHTED_DIFF: 1238 case COMPUTE_WEIGHTED_DIFF:
1196 fmt->sort = hist_entry__cmp_wdiff_idx; 1239 fmt->sort = hist_entry__cmp_wdiff_idx;
1197 break; 1240 break;
1241 case COMPUTE_DELTA_ABS:
1242 fmt->sort = hist_entry__cmp_delta_abs_idx;
1243 break;
1198 default: 1244 default:
1199 BUG_ON(1); 1245 BUG_ON(1);
1200 } 1246 }
@@ -1249,6 +1295,31 @@ static int data_init(int argc, const char **argv)
1249 return 0; 1295 return 0;
1250} 1296}
1251 1297
1298static int diff__config(const char *var, const char *value,
1299 void *cb __maybe_unused)
1300{
1301 if (!strcmp(var, "diff.order")) {
1302 sort_compute = perf_config_int(var, value);
1303 return 0;
1304 }
1305 if (!strcmp(var, "diff.compute")) {
1306 if (!strcmp(value, "delta")) {
1307 compute = COMPUTE_DELTA;
1308 } else if (!strcmp(value, "delta-abs")) {
1309 compute = COMPUTE_DELTA_ABS;
1310 } else if (!strcmp(value, "ratio")) {
1311 compute = COMPUTE_RATIO;
1312 } else if (!strcmp(value, "wdiff")) {
1313 compute = COMPUTE_WEIGHTED_DIFF;
1314 } else {
1315 pr_err("Invalid compute method: %s\n", value);
1316 return -1;
1317 }
1318 }
1319
1320 return 0;
1321}
1322
1252int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) 1323int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
1253{ 1324{
1254 int ret = hists__init(); 1325 int ret = hists__init();
@@ -1256,8 +1327,13 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
1256 if (ret < 0) 1327 if (ret < 0)
1257 return ret; 1328 return ret;
1258 1329
1330 perf_config(diff__config, NULL);
1331
1259 argc = parse_options(argc, argv, options, diff_usage, 0); 1332 argc = parse_options(argc, argv, options, diff_usage, 0);
1260 1333
1334 if (quiet)
1335 perf_quiet_option();
1336
1261 if (symbol__init(NULL) < 0) 1337 if (symbol__init(NULL) < 0)
1262 return -1; 1338 return -1;
1263 1339
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
new file mode 100644
index 000000000000..c3e643666c72
--- /dev/null
+++ b/tools/perf/builtin-ftrace.c
@@ -0,0 +1,265 @@
1/*
2 * builtin-ftrace.c
3 *
4 * Copyright (c) 2013 LG Electronics, Namhyung Kim <namhyung@kernel.org>
5 *
6 * Released under the GPL v2.
7 */
8
9#include "builtin.h"
10#include "perf.h"
11
12#include <unistd.h>
13#include <signal.h>
14
15#include "debug.h"
16#include <subcmd/parse-options.h>
17#include "evlist.h"
18#include "target.h"
19#include "thread_map.h"
20#include "util/config.h"
21
22
23#define DEFAULT_TRACER "function_graph"
24
25struct perf_ftrace {
26 struct perf_evlist *evlist;
27 struct target target;
28 const char *tracer;
29};
30
31static bool done;
32
33static void sig_handler(int sig __maybe_unused)
34{
35 done = true;
36}
37
38/*
39 * perf_evlist__prepare_workload will send a SIGUSR1 if the fork fails, since
40 * we asked by setting its exec_error to the function below,
41 * ftrace__workload_exec_failed_signal.
42 *
43 * XXX We need to handle this more appropriately, emitting an error, etc.
44 */
45static void ftrace__workload_exec_failed_signal(int signo __maybe_unused,
46 siginfo_t *info __maybe_unused,
47 void *ucontext __maybe_unused)
48{
49 /* workload_exec_errno = info->si_value.sival_int; */
50 done = true;
51}
52
53static int write_tracing_file(const char *name, const char *val)
54{
55 char *file;
56 int fd, ret = -1;
57 ssize_t size = strlen(val);
58
59 file = get_tracing_file(name);
60 if (!file) {
61 pr_debug("cannot get tracing file: %s\n", name);
62 return -1;
63 }
64
65 fd = open(file, O_WRONLY);
66 if (fd < 0) {
67 pr_debug("cannot open tracing file: %s\n", name);
68 goto out;
69 }
70
71 if (write(fd, val, size) == size)
72 ret = 0;
73 else
74 pr_debug("write '%s' to tracing/%s failed\n", val, name);
75
76 close(fd);
77out:
78 put_tracing_file(file);
79 return ret;
80}
81
82static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
83{
84 if (write_tracing_file("tracing_on", "0") < 0)
85 return -1;
86
87 if (write_tracing_file("current_tracer", "nop") < 0)
88 return -1;
89
90 if (write_tracing_file("set_ftrace_pid", " ") < 0)
91 return -1;
92
93 return 0;
94}
95
96static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
97{
98 char *trace_file;
99 int trace_fd;
100 char *trace_pid;
101 char buf[4096];
102 struct pollfd pollfd = {
103 .events = POLLIN,
104 };
105
106 if (geteuid() != 0) {
107 pr_err("ftrace only works for root!\n");
108 return -1;
109 }
110
111 if (argc < 1)
112 return -1;
113
114 signal(SIGINT, sig_handler);
115 signal(SIGUSR1, sig_handler);
116 signal(SIGCHLD, sig_handler);
117
118 reset_tracing_files(ftrace);
119
120 /* reset ftrace buffer */
121 if (write_tracing_file("trace", "0") < 0)
122 goto out;
123
124 if (perf_evlist__prepare_workload(ftrace->evlist, &ftrace->target,
125 argv, false, ftrace__workload_exec_failed_signal) < 0)
126 goto out;
127
128 if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
129 pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
130 goto out;
131 }
132
133 if (asprintf(&trace_pid, "%d", thread_map__pid(ftrace->evlist->threads, 0)) < 0) {
134 pr_err("failed to allocate pid string\n");
135 goto out;
136 }
137
138 if (write_tracing_file("set_ftrace_pid", trace_pid) < 0) {
139 pr_err("failed to set pid: %s\n", trace_pid);
140 goto out_free_pid;
141 }
142
143 trace_file = get_tracing_file("trace_pipe");
144 if (!trace_file) {
145 pr_err("failed to open trace_pipe\n");
146 goto out_free_pid;
147 }
148
149 trace_fd = open(trace_file, O_RDONLY);
150
151 put_tracing_file(trace_file);
152
153 if (trace_fd < 0) {
154 pr_err("failed to open trace_pipe\n");
155 goto out_free_pid;
156 }
157
158 fcntl(trace_fd, F_SETFL, O_NONBLOCK);
159 pollfd.fd = trace_fd;
160
161 if (write_tracing_file("tracing_on", "1") < 0) {
162 pr_err("can't enable tracing\n");
163 goto out_close_fd;
164 }
165
166 perf_evlist__start_workload(ftrace->evlist);
167
168 while (!done) {
169 if (poll(&pollfd, 1, -1) < 0)
170 break;
171
172 if (pollfd.revents & POLLIN) {
173 int n = read(trace_fd, buf, sizeof(buf));
174 if (n < 0)
175 break;
176 if (fwrite(buf, n, 1, stdout) != 1)
177 break;
178 }
179 }
180
181 write_tracing_file("tracing_on", "0");
182
183 /* read remaining buffer contents */
184 while (true) {
185 int n = read(trace_fd, buf, sizeof(buf));
186 if (n <= 0)
187 break;
188 if (fwrite(buf, n, 1, stdout) != 1)
189 break;
190 }
191
192out_close_fd:
193 close(trace_fd);
194out_free_pid:
195 free(trace_pid);
196out:
197 reset_tracing_files(ftrace);
198
199 return done ? 0 : -1;
200}
201
202static int perf_ftrace_config(const char *var, const char *value, void *cb)
203{
204 struct perf_ftrace *ftrace = cb;
205
206 if (prefixcmp(var, "ftrace."))
207 return 0;
208
209 if (strcmp(var, "ftrace.tracer"))
210 return -1;
211
212 if (!strcmp(value, "function_graph") ||
213 !strcmp(value, "function")) {
214 ftrace->tracer = value;
215 return 0;
216 }
217
218 pr_err("Please select \"function_graph\" (default) or \"function\"\n");
219 return -1;
220}
221
222int cmd_ftrace(int argc, const char **argv, const char *prefix __maybe_unused)
223{
224 int ret;
225 struct perf_ftrace ftrace = {
226 .tracer = DEFAULT_TRACER,
227 .target = { .uid = UINT_MAX, },
228 };
229 const char * const ftrace_usage[] = {
230 "perf ftrace [<options>] <command>",
231 "perf ftrace [<options>] -- <command> [<options>]",
232 NULL
233 };
234 const struct option ftrace_options[] = {
235 OPT_STRING('t', "tracer", &ftrace.tracer, "tracer",
236 "tracer to use: function_graph(default) or function"),
237 OPT_INCR('v', "verbose", &verbose,
238 "be more verbose"),
239 OPT_END()
240 };
241
242 ret = perf_config(perf_ftrace_config, &ftrace);
243 if (ret < 0)
244 return -1;
245
246 argc = parse_options(argc, argv, ftrace_options, ftrace_usage,
247 PARSE_OPT_STOP_AT_NON_OPTION);
248 if (!argc)
249 usage_with_options(ftrace_usage, ftrace_options);
250
251 ftrace.evlist = perf_evlist__new();
252 if (ftrace.evlist == NULL)
253 return -ENOMEM;
254
255 ret = perf_evlist__create_maps(ftrace.evlist, &ftrace.target);
256 if (ret < 0)
257 goto out_delete_evlist;
258
259 ret = __cmd_ftrace(&ftrace, argc, argv);
260
261out_delete_evlist:
262 perf_evlist__delete(ftrace.evlist);
263
264 return ret;
265}
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 3bdb2c78a21b..aed0d844e8c2 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -434,7 +434,7 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
434 const char * const builtin_help_subcommands[] = { 434 const char * const builtin_help_subcommands[] = {
435 "buildid-cache", "buildid-list", "diff", "evlist", "help", "list", 435 "buildid-cache", "buildid-list", "diff", "evlist", "help", "list",
436 "record", "report", "bench", "stat", "timechart", "top", "annotate", 436 "record", "report", "bench", "stat", "timechart", "top", "annotate",
437 "script", "sched", "kmem", "lock", "kvm", "test", "inject", "mem", "data", 437 "script", "sched", "kallsyms", "kmem", "lock", "kvm", "test", "inject", "mem", "data",
438#ifdef HAVE_LIBELF_SUPPORT 438#ifdef HAVE_LIBELF_SUPPORT
439 "probe", 439 "probe",
440#endif 440#endif
@@ -447,11 +447,13 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
447 NULL 447 NULL
448 }; 448 };
449 const char *alias; 449 const char *alias;
450 int rc = 0; 450 int rc;
451 451
452 load_command_list("perf-", &main_cmds, &other_cmds); 452 load_command_list("perf-", &main_cmds, &other_cmds);
453 453
454 perf_config(perf_help_config, &help_format); 454 rc = perf_config(perf_help_config, &help_format);
455 if (rc)
456 return rc;
455 457
456 argc = parse_options_subcommand(argc, argv, builtin_help_options, 458 argc = parse_options_subcommand(argc, argv, builtin_help_options,
457 builtin_help_subcommands, builtin_help_usage, 0); 459 builtin_help_subcommands, builtin_help_usage, 0);
diff --git a/tools/perf/builtin-kallsyms.c b/tools/perf/builtin-kallsyms.c
new file mode 100644
index 000000000000..224bfc454b4a
--- /dev/null
+++ b/tools/perf/builtin-kallsyms.c
@@ -0,0 +1,67 @@
1/*
2 * builtin-kallsyms.c
3 *
4 * Builtin command: Look for a symbol in the running kernel and its modules
5 *
6 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
7 *
8 * Released under the GPL v2. (and only v2, not any later version)
9 */
10#include "builtin.h"
11#include <linux/compiler.h>
12#include <subcmd/parse-options.h>
13#include "debug.h"
14#include "machine.h"
15#include "symbol.h"
16
17static int __cmd_kallsyms(int argc, const char **argv)
18{
19 int i;
20 struct machine *machine = machine__new_kallsyms();
21
22 if (machine == NULL) {
23 pr_err("Couldn't read /proc/kallsyms\n");
24 return -1;
25 }
26
27 for (i = 0; i < argc; ++i) {
28 struct map *map;
29 struct symbol *symbol = machine__find_kernel_function_by_name(machine, argv[i], &map);
30
31 if (symbol == NULL) {
32 printf("%s: not found\n", argv[i]);
33 continue;
34 }
35
36 printf("%s: %s %s %#" PRIx64 "-%#" PRIx64 " (%#" PRIx64 "-%#" PRIx64")\n",
37 symbol->name, map->dso->short_name, map->dso->long_name,
38 map->unmap_ip(map, symbol->start), map->unmap_ip(map, symbol->end),
39 symbol->start, symbol->end);
40 }
41
42 machine__delete(machine);
43 return 0;
44}
45
46int cmd_kallsyms(int argc, const char **argv, const char *prefix __maybe_unused)
47{
48 const struct option options[] = {
49 OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"),
50 OPT_END()
51 };
52 const char * const kallsyms_usage[] = {
53 "perf kallsyms [<options>] symbol_name",
54 NULL
55 };
56
57 argc = parse_options(argc, argv, options, kallsyms_usage, 0);
58 if (argc < 1)
59 usage_with_options(kallsyms_usage, options);
60
61 symbol_conf.sort_by_name = true;
62 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
63 if (symbol__init(NULL) < 0)
64 return -1;
65
66 return __cmd_kallsyms(argc, argv);
67}
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 915869e00d86..6da8d083e4e5 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1065,7 +1065,7 @@ static void __print_page_alloc_result(struct perf_session *session, int n_lines)
1065 1065
1066 data = rb_entry(next, struct page_stat, node); 1066 data = rb_entry(next, struct page_stat, node);
1067 sym = machine__find_kernel_function(machine, data->callsite, &map); 1067 sym = machine__find_kernel_function(machine, data->callsite, &map);
1068 if (sym && sym->name) 1068 if (sym)
1069 caller = sym->name; 1069 caller = sym->name;
1070 else 1070 else
1071 scnprintf(buf, sizeof(buf), "%"PRIx64, data->callsite); 1071 scnprintf(buf, sizeof(buf), "%"PRIx64, data->callsite);
@@ -1107,7 +1107,7 @@ static void __print_page_caller_result(struct perf_session *session, int n_lines
1107 1107
1108 data = rb_entry(next, struct page_stat, node); 1108 data = rb_entry(next, struct page_stat, node);
1109 sym = machine__find_kernel_function(machine, data->callsite, &map); 1109 sym = machine__find_kernel_function(machine, data->callsite, &map);
1110 if (sym && sym->name) 1110 if (sym)
1111 caller = sym->name; 1111 caller = sym->name;
1112 else 1112 else
1113 scnprintf(buf, sizeof(buf), "%"PRIx64, data->callsite); 1113 scnprintf(buf, sizeof(buf), "%"PRIx64, data->callsite);
@@ -1920,10 +1920,12 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
1920 NULL 1920 NULL
1921 }; 1921 };
1922 struct perf_session *session; 1922 struct perf_session *session;
1923 int ret = -1;
1924 const char errmsg[] = "No %s allocation events found. Have you run 'perf kmem record --%s'?\n"; 1923 const char errmsg[] = "No %s allocation events found. Have you run 'perf kmem record --%s'?\n";
1924 int ret = perf_config(kmem_config, NULL);
1925
1926 if (ret)
1927 return ret;
1925 1928
1926 perf_config(kmem_config, NULL);
1927 argc = parse_options_subcommand(argc, argv, kmem_options, 1929 argc = parse_options_subcommand(argc, argv, kmem_options,
1928 kmem_subcommands, kmem_usage, 0); 1930 kmem_subcommands, kmem_usage, 0);
1929 1931
@@ -1948,6 +1950,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
1948 if (session == NULL) 1950 if (session == NULL)
1949 return -1; 1951 return -1;
1950 1952
1953 ret = -1;
1954
1951 if (kmem_slab) { 1955 if (kmem_slab) {
1952 if (!perf_evlist__find_tracepoint_by_name(session->evlist, 1956 if (!perf_evlist__find_tracepoint_by_name(session->evlist,
1953 "kmem:kmalloc")) { 1957 "kmem:kmalloc")) {
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index ba9322ff858b..3b9d98b5feef 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -14,6 +14,7 @@
14#include "util/parse-events.h" 14#include "util/parse-events.h"
15#include "util/cache.h" 15#include "util/cache.h"
16#include "util/pmu.h" 16#include "util/pmu.h"
17#include "util/debug.h"
17#include <subcmd/parse-options.h> 18#include <subcmd/parse-options.h>
18 19
19static bool desc_flag = true; 20static bool desc_flag = true;
@@ -29,6 +30,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
29 "Print extra event descriptions. --no-desc to not print."), 30 "Print extra event descriptions. --no-desc to not print."),
30 OPT_BOOLEAN('v', "long-desc", &long_desc_flag, 31 OPT_BOOLEAN('v', "long-desc", &long_desc_flag,
31 "Print longer event descriptions."), 32 "Print longer event descriptions."),
33 OPT_INCR(0, "debug", &verbose,
34 "Enable debugging output"),
32 OPT_END() 35 OPT_END()
33 }; 36 };
34 const char * const list_usage[] = { 37 const char * const list_usage[] = {
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index cd7bc4d104e2..6114e07ca613 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -42,8 +42,8 @@ static int parse_record_events(const struct option *opt,
42 42
43 fprintf(stderr, "%-13s%-*s%s\n", 43 fprintf(stderr, "%-13s%-*s%s\n",
44 e->tag, 44 e->tag,
45 verbose ? 25 : 0, 45 verbose > 0 ? 25 : 0,
46 verbose ? perf_mem_events__name(j) : "", 46 verbose > 0 ? perf_mem_events__name(j) : "",
47 e->supported ? ": available" : ""); 47 e->supported ? ": available" : "");
48 } 48 }
49 exit(0); 49 exit(0);
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index f87996b0cb29..1fcebc31a508 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -552,6 +552,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
552 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, 552 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
553 "Enable kernel symbol demangling"), 553 "Enable kernel symbol demangling"),
554 OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"), 554 OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
555 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
556 "Look for files with symbols relative to this directory"),
555 OPT_END() 557 OPT_END()
556 }; 558 };
557 int ret; 559 int ret;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4ec10e9427d9..bc84a375295d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -46,6 +46,15 @@
46#include <asm/bug.h> 46#include <asm/bug.h>
47#include <linux/time64.h> 47#include <linux/time64.h>
48 48
49struct switch_output {
50 bool enabled;
51 bool signal;
52 unsigned long size;
53 unsigned long time;
54 const char *str;
55 bool set;
56};
57
49struct record { 58struct record {
50 struct perf_tool tool; 59 struct perf_tool tool;
51 struct record_opts opts; 60 struct record_opts opts;
@@ -62,10 +71,33 @@ struct record {
62 bool no_buildid_cache_set; 71 bool no_buildid_cache_set;
63 bool buildid_all; 72 bool buildid_all;
64 bool timestamp_filename; 73 bool timestamp_filename;
65 bool switch_output; 74 struct switch_output switch_output;
66 unsigned long long samples; 75 unsigned long long samples;
67}; 76};
68 77
78static volatile int auxtrace_record__snapshot_started;
79static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
80static DEFINE_TRIGGER(switch_output_trigger);
81
82static bool switch_output_signal(struct record *rec)
83{
84 return rec->switch_output.signal &&
85 trigger_is_ready(&switch_output_trigger);
86}
87
88static bool switch_output_size(struct record *rec)
89{
90 return rec->switch_output.size &&
91 trigger_is_ready(&switch_output_trigger) &&
92 (rec->bytes_written >= rec->switch_output.size);
93}
94
95static bool switch_output_time(struct record *rec)
96{
97 return rec->switch_output.time &&
98 trigger_is_ready(&switch_output_trigger);
99}
100
69static int record__write(struct record *rec, void *bf, size_t size) 101static int record__write(struct record *rec, void *bf, size_t size)
70{ 102{
71 if (perf_data_file__write(rec->session->file, bf, size) < 0) { 103 if (perf_data_file__write(rec->session->file, bf, size) < 0) {
@@ -74,6 +106,10 @@ static int record__write(struct record *rec, void *bf, size_t size)
74 } 106 }
75 107
76 rec->bytes_written += size; 108 rec->bytes_written += size;
109
110 if (switch_output_size(rec))
111 trigger_hit(&switch_output_trigger);
112
77 return 0; 113 return 0;
78} 114}
79 115
@@ -193,10 +229,6 @@ static volatile int done;
193static volatile int signr = -1; 229static volatile int signr = -1;
194static volatile int child_finished; 230static volatile int child_finished;
195 231
196static volatile int auxtrace_record__snapshot_started;
197static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
198static DEFINE_TRIGGER(switch_output_trigger);
199
200static void sig_handler(int sig) 232static void sig_handler(int sig)
201{ 233{
202 if (sig == SIGCHLD) 234 if (sig == SIGCHLD)
@@ -386,7 +418,7 @@ static int record__mmap(struct record *rec)
386 418
387static int record__open(struct record *rec) 419static int record__open(struct record *rec)
388{ 420{
389 char msg[512]; 421 char msg[BUFSIZ];
390 struct perf_evsel *pos; 422 struct perf_evsel *pos;
391 struct perf_evlist *evlist = rec->evlist; 423 struct perf_evlist *evlist = rec->evlist;
392 struct perf_session *session = rec->session; 424 struct perf_session *session = rec->session;
@@ -400,7 +432,7 @@ static int record__open(struct record *rec)
400try_again: 432try_again:
401 if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 433 if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
402 if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 434 if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
403 if (verbose) 435 if (verbose > 0)
404 ui__warning("%s\n", msg); 436 ui__warning("%s\n", msg);
405 goto try_again; 437 goto try_again;
406 } 438 }
@@ -623,22 +655,23 @@ record__finish_output(struct record *rec)
623 655
624static int record__synthesize_workload(struct record *rec, bool tail) 656static int record__synthesize_workload(struct record *rec, bool tail)
625{ 657{
626 struct { 658 int err;
627 struct thread_map map; 659 struct thread_map *thread_map;
628 struct thread_map_data map_data;
629 } thread_map;
630 660
631 if (rec->opts.tail_synthesize != tail) 661 if (rec->opts.tail_synthesize != tail)
632 return 0; 662 return 0;
633 663
634 thread_map.map.nr = 1; 664 thread_map = thread_map__new_by_tid(rec->evlist->workload.pid);
635 thread_map.map.map[0].pid = rec->evlist->workload.pid; 665 if (thread_map == NULL)
636 thread_map.map.map[0].comm = NULL; 666 return -1;
637 return perf_event__synthesize_thread_map(&rec->tool, &thread_map.map, 667
668 err = perf_event__synthesize_thread_map(&rec->tool, thread_map,
638 process_synthesized_event, 669 process_synthesized_event,
639 &rec->session->machines.host, 670 &rec->session->machines.host,
640 rec->opts.sample_address, 671 rec->opts.sample_address,
641 rec->opts.proc_map_timeout); 672 rec->opts.proc_map_timeout);
673 thread_map__put(thread_map);
674 return err;
642} 675}
643 676
644static int record__synthesize(struct record *rec, bool tail); 677static int record__synthesize(struct record *rec, bool tail);
@@ -712,6 +745,7 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
712} 745}
713 746
714static void snapshot_sig_handler(int sig); 747static void snapshot_sig_handler(int sig);
748static void alarm_sig_handler(int sig);
715 749
716int __weak 750int __weak
717perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused, 751perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
@@ -842,11 +876,11 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
842 signal(SIGTERM, sig_handler); 876 signal(SIGTERM, sig_handler);
843 signal(SIGSEGV, sigsegv_handler); 877 signal(SIGSEGV, sigsegv_handler);
844 878
845 if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) { 879 if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
846 signal(SIGUSR2, snapshot_sig_handler); 880 signal(SIGUSR2, snapshot_sig_handler);
847 if (rec->opts.auxtrace_snapshot_mode) 881 if (rec->opts.auxtrace_snapshot_mode)
848 trigger_on(&auxtrace_snapshot_trigger); 882 trigger_on(&auxtrace_snapshot_trigger);
849 if (rec->switch_output) 883 if (rec->switch_output.enabled)
850 trigger_on(&switch_output_trigger); 884 trigger_on(&switch_output_trigger);
851 } else { 885 } else {
852 signal(SIGUSR2, SIG_IGN); 886 signal(SIGUSR2, SIG_IGN);
@@ -1043,6 +1077,10 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
1043 err = fd; 1077 err = fd;
1044 goto out_child; 1078 goto out_child;
1045 } 1079 }
1080
1081 /* re-arm the alarm */
1082 if (rec->switch_output.time)
1083 alarm(rec->switch_output.time);
1046 } 1084 }
1047 1085
1048 if (hits == rec->samples) { 1086 if (hits == rec->samples) {
@@ -1352,6 +1390,78 @@ out_free:
1352 return ret; 1390 return ret;
1353} 1391}
1354 1392
1393static void switch_output_size_warn(struct record *rec)
1394{
1395 u64 wakeup_size = perf_evlist__mmap_size(rec->opts.mmap_pages);
1396 struct switch_output *s = &rec->switch_output;
1397
1398 wakeup_size /= 2;
1399
1400 if (s->size < wakeup_size) {
1401 char buf[100];
1402
1403 unit_number__scnprintf(buf, sizeof(buf), wakeup_size);
1404 pr_warning("WARNING: switch-output data size lower than "
1405 "wakeup kernel buffer size (%s) "
1406 "expect bigger perf.data sizes\n", buf);
1407 }
1408}
1409
1410static int switch_output_setup(struct record *rec)
1411{
1412 struct switch_output *s = &rec->switch_output;
1413 static struct parse_tag tags_size[] = {
1414 { .tag = 'B', .mult = 1 },
1415 { .tag = 'K', .mult = 1 << 10 },
1416 { .tag = 'M', .mult = 1 << 20 },
1417 { .tag = 'G', .mult = 1 << 30 },
1418 { .tag = 0 },
1419 };
1420 static struct parse_tag tags_time[] = {
1421 { .tag = 's', .mult = 1 },
1422 { .tag = 'm', .mult = 60 },
1423 { .tag = 'h', .mult = 60*60 },
1424 { .tag = 'd', .mult = 60*60*24 },
1425 { .tag = 0 },
1426 };
1427 unsigned long val;
1428
1429 if (!s->set)
1430 return 0;
1431
1432 if (!strcmp(s->str, "signal")) {
1433 s->signal = true;
1434 pr_debug("switch-output with SIGUSR2 signal\n");
1435 goto enabled;
1436 }
1437
1438 val = parse_tag_value(s->str, tags_size);
1439 if (val != (unsigned long) -1) {
1440 s->size = val;
1441 pr_debug("switch-output with %s size threshold\n", s->str);
1442 goto enabled;
1443 }
1444
1445 val = parse_tag_value(s->str, tags_time);
1446 if (val != (unsigned long) -1) {
1447 s->time = val;
1448 pr_debug("switch-output with %s time threshold (%lu seconds)\n",
1449 s->str, s->time);
1450 goto enabled;
1451 }
1452
1453 return -1;
1454
1455enabled:
1456 rec->timestamp_filename = true;
1457 s->enabled = true;
1458
1459 if (s->size && !rec->opts.no_buffering)
1460 switch_output_size_warn(rec);
1461
1462 return 0;
1463}
1464
1355static const char * const __record_usage[] = { 1465static const char * const __record_usage[] = {
1356 "perf record [<options>] [<command>]", 1466 "perf record [<options>] [<command>]",
1357 "perf record [<options>] -- <command> [<options>]", 1467 "perf record [<options>] -- <command> [<options>]",
@@ -1519,8 +1629,10 @@ static struct option __record_options[] = {
1519 "Record build-id of all DSOs regardless of hits"), 1629 "Record build-id of all DSOs regardless of hits"),
1520 OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 1630 OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
1521 "append timestamp to output filename"), 1631 "append timestamp to output filename"),
1522 OPT_BOOLEAN(0, "switch-output", &record.switch_output, 1632 OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
1523 "Switch output when receive SIGUSR2"), 1633 &record.switch_output.set, "signal,size,time",
1634 "Switch output when receive SIGUSR2 or cross size,time threshold",
1635 "signal"),
1524 OPT_BOOLEAN(0, "dry-run", &dry_run, 1636 OPT_BOOLEAN(0, "dry-run", &dry_run,
1525 "Parse options then exit"), 1637 "Parse options then exit"),
1526 OPT_END() 1638 OPT_END()
@@ -1559,12 +1671,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1559 if (rec->evlist == NULL) 1671 if (rec->evlist == NULL)
1560 return -ENOMEM; 1672 return -ENOMEM;
1561 1673
1562 perf_config(perf_record_config, rec); 1674 err = perf_config(perf_record_config, rec);
1675 if (err)
1676 return err;
1563 1677
1564 argc = parse_options(argc, argv, record_options, record_usage, 1678 argc = parse_options(argc, argv, record_options, record_usage,
1565 PARSE_OPT_STOP_AT_NON_OPTION); 1679 PARSE_OPT_STOP_AT_NON_OPTION);
1680 if (quiet)
1681 perf_quiet_option();
1682
1683 /* Make system wide (-a) the default target. */
1566 if (!argc && target__none(&rec->opts.target)) 1684 if (!argc && target__none(&rec->opts.target))
1567 usage_with_options(record_usage, record_options); 1685 rec->opts.target.system_wide = true;
1568 1686
1569 if (nr_cgroups && !rec->opts.target.system_wide) { 1687 if (nr_cgroups && !rec->opts.target.system_wide) {
1570 usage_with_options_msg(record_usage, record_options, 1688 usage_with_options_msg(record_usage, record_options,
@@ -1578,8 +1696,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1578 return -EINVAL; 1696 return -EINVAL;
1579 } 1697 }
1580 1698
1581 if (rec->switch_output) 1699 if (switch_output_setup(rec)) {
1582 rec->timestamp_filename = true; 1700 parse_options_usage(record_usage, record_options, "switch-output", 0);
1701 return -EINVAL;
1702 }
1703
1704 if (rec->switch_output.time) {
1705 signal(SIGALRM, alarm_sig_handler);
1706 alarm(rec->switch_output.time);
1707 }
1583 1708
1584 if (!rec->itr) { 1709 if (!rec->itr) {
1585 rec->itr = auxtrace_record__init(rec->evlist, &err); 1710 rec->itr = auxtrace_record__init(rec->evlist, &err);
@@ -1629,7 +1754,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1629 1754
1630 if (rec->no_buildid_cache || rec->no_buildid) { 1755 if (rec->no_buildid_cache || rec->no_buildid) {
1631 disable_buildid_cache(); 1756 disable_buildid_cache();
1632 } else if (rec->switch_output) { 1757 } else if (rec->switch_output.enabled) {
1633 /* 1758 /*
1634 * In 'perf record --switch-output', disable buildid 1759 * In 'perf record --switch-output', disable buildid
1635 * generation by default to reduce data file switching 1760 * generation by default to reduce data file switching
@@ -1721,6 +1846,8 @@ out:
1721 1846
1722static void snapshot_sig_handler(int sig __maybe_unused) 1847static void snapshot_sig_handler(int sig __maybe_unused)
1723{ 1848{
1849 struct record *rec = &record;
1850
1724 if (trigger_is_ready(&auxtrace_snapshot_trigger)) { 1851 if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
1725 trigger_hit(&auxtrace_snapshot_trigger); 1852 trigger_hit(&auxtrace_snapshot_trigger);
1726 auxtrace_record__snapshot_started = 1; 1853 auxtrace_record__snapshot_started = 1;
@@ -1728,6 +1855,14 @@ static void snapshot_sig_handler(int sig __maybe_unused)
1728 trigger_error(&auxtrace_snapshot_trigger); 1855 trigger_error(&auxtrace_snapshot_trigger);
1729 } 1856 }
1730 1857
1731 if (trigger_is_ready(&switch_output_trigger)) 1858 if (switch_output_signal(rec))
1859 trigger_hit(&switch_output_trigger);
1860}
1861
1862static void alarm_sig_handler(int sig __maybe_unused)
1863{
1864 struct record *rec = &record;
1865
1866 if (switch_output_time(rec))
1732 trigger_hit(&switch_output_trigger); 1867 trigger_hit(&switch_output_trigger);
1733} 1868}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 06cc759a4597..0a88670e56f3 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -320,6 +320,9 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
320 size_t size = sizeof(buf); 320 size_t size = sizeof(buf);
321 int socked_id = hists->socket_filter; 321 int socked_id = hists->socket_filter;
322 322
323 if (quiet)
324 return 0;
325
323 if (symbol_conf.filter_relative) { 326 if (symbol_conf.filter_relative) {
324 nr_samples = hists->stats.nr_non_filtered_samples; 327 nr_samples = hists->stats.nr_non_filtered_samples;
325 nr_events = hists->stats.total_non_filtered_period; 328 nr_events = hists->stats.total_non_filtered_period;
@@ -372,7 +375,11 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
372{ 375{
373 struct perf_evsel *pos; 376 struct perf_evsel *pos;
374 377
375 fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples); 378 if (!quiet) {
379 fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n",
380 evlist->stats.total_lost_samples);
381 }
382
376 evlist__for_each_entry(evlist, pos) { 383 evlist__for_each_entry(evlist, pos) {
377 struct hists *hists = evsel__hists(pos); 384 struct hists *hists = evsel__hists(pos);
378 const char *evname = perf_evsel__name(pos); 385 const char *evname = perf_evsel__name(pos);
@@ -382,7 +389,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
382 continue; 389 continue;
383 390
384 hists__fprintf_nr_sample_events(hists, rep, evname, stdout); 391 hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
385 hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout, 392 hists__fprintf(hists, !quiet, 0, 0, rep->min_percent, stdout,
386 symbol_conf.use_callchain); 393 symbol_conf.use_callchain);
387 fprintf(stdout, "\n\n"); 394 fprintf(stdout, "\n\n");
388 } 395 }
@@ -716,6 +723,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
716 "input file name"), 723 "input file name"),
717 OPT_INCR('v', "verbose", &verbose, 724 OPT_INCR('v', "verbose", &verbose,
718 "be more verbose (show symbol address, etc)"), 725 "be more verbose (show symbol address, etc)"),
726 OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any message"),
719 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 727 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
720 "dump raw trace in ASCII"), 728 "dump raw trace in ASCII"),
721 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 729 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
@@ -847,7 +855,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
847 if (ret < 0) 855 if (ret < 0)
848 return ret; 856 return ret;
849 857
850 perf_config(report__config, &report); 858 ret = perf_config(report__config, &report);
859 if (ret)
860 return ret;
851 861
852 argc = parse_options(argc, argv, options, report_usage, 0); 862 argc = parse_options(argc, argv, options, report_usage, 0);
853 if (argc) { 863 if (argc) {
@@ -861,6 +871,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
861 report.symbol_filter_str = argv[0]; 871 report.symbol_filter_str = argv[0];
862 } 872 }
863 873
874 if (quiet)
875 perf_quiet_option();
876
864 if (symbol_conf.vmlinux_name && 877 if (symbol_conf.vmlinux_name &&
865 access(symbol_conf.vmlinux_name, R_OK)) { 878 access(symbol_conf.vmlinux_name, R_OK)) {
866 pr_err("Invalid file: %s\n", symbol_conf.vmlinux_name); 879 pr_err("Invalid file: %s\n", symbol_conf.vmlinux_name);
@@ -981,14 +994,14 @@ repeat:
981 goto error; 994 goto error;
982 } 995 }
983 996
984 if (report.header || report.header_only) { 997 if ((report.header || report.header_only) && !quiet) {
985 perf_session__fprintf_info(session, stdout, 998 perf_session__fprintf_info(session, stdout,
986 report.show_full_info); 999 report.show_full_info);
987 if (report.header_only) { 1000 if (report.header_only) {
988 ret = 0; 1001 ret = 0;
989 goto error; 1002 goto error;
990 } 1003 }
991 } else if (use_browser == 0) { 1004 } else if (use_browser == 0 && !quiet) {
992 fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n", 1005 fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
993 stdout); 1006 stdout);
994 } 1007 }
@@ -1007,7 +1020,7 @@ repeat:
1007 * providing it only in verbose mode not to bloat too 1020 * providing it only in verbose mode not to bloat too
1008 * much struct symbol. 1021 * much struct symbol.
1009 */ 1022 */
1010 if (verbose) { 1023 if (verbose > 0) {
1011 /* 1024 /*
1012 * XXX: Need to provide a less kludgy way to ask for 1025 * XXX: Need to provide a less kludgy way to ask for
1013 * more space per symbol, the u32 is for the index on 1026 * more space per symbol, the u32 is for the index on
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 5b134b0d1ff3..b94cf0de715a 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -77,6 +77,22 @@ struct sched_atom {
77 77
78#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP" 78#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP"
79 79
80/* task state bitmask, copied from include/linux/sched.h */
81#define TASK_RUNNING 0
82#define TASK_INTERRUPTIBLE 1
83#define TASK_UNINTERRUPTIBLE 2
84#define __TASK_STOPPED 4
85#define __TASK_TRACED 8
86/* in tsk->exit_state */
87#define EXIT_DEAD 16
88#define EXIT_ZOMBIE 32
89#define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD)
90/* in tsk->state again */
91#define TASK_DEAD 64
92#define TASK_WAKEKILL 128
93#define TASK_WAKING 256
94#define TASK_PARKED 512
95
80enum thread_state { 96enum thread_state {
81 THREAD_SLEEPING = 0, 97 THREAD_SLEEPING = 0,
82 THREAD_WAIT_CPU, 98 THREAD_WAIT_CPU,
@@ -206,6 +222,7 @@ struct perf_sched {
206 bool show_cpu_visual; 222 bool show_cpu_visual;
207 bool show_wakeups; 223 bool show_wakeups;
208 bool show_migrations; 224 bool show_migrations;
225 bool show_state;
209 u64 skipped_samples; 226 u64 skipped_samples;
210 const char *time_str; 227 const char *time_str;
211 struct perf_time_interval ptime; 228 struct perf_time_interval ptime;
@@ -216,13 +233,20 @@ struct perf_sched {
216struct thread_runtime { 233struct thread_runtime {
217 u64 last_time; /* time of previous sched in/out event */ 234 u64 last_time; /* time of previous sched in/out event */
218 u64 dt_run; /* run time */ 235 u64 dt_run; /* run time */
219 u64 dt_wait; /* time between CPU access (off cpu) */ 236 u64 dt_sleep; /* time between CPU access by sleep (off cpu) */
237 u64 dt_iowait; /* time between CPU access by iowait (off cpu) */
238 u64 dt_preempt; /* time between CPU access by preempt (off cpu) */
220 u64 dt_delay; /* time between wakeup and sched-in */ 239 u64 dt_delay; /* time between wakeup and sched-in */
221 u64 ready_to_run; /* time of wakeup */ 240 u64 ready_to_run; /* time of wakeup */
222 241
223 struct stats run_stats; 242 struct stats run_stats;
224 u64 total_run_time; 243 u64 total_run_time;
244 u64 total_sleep_time;
245 u64 total_iowait_time;
246 u64 total_preempt_time;
247 u64 total_delay_time;
225 248
249 int last_state;
226 u64 migrations; 250 u64 migrations;
227}; 251};
228 252
@@ -436,7 +460,7 @@ static struct task_desc *register_pid(struct perf_sched *sched,
436 BUG_ON(!sched->tasks); 460 BUG_ON(!sched->tasks);
437 sched->tasks[task->nr] = task; 461 sched->tasks[task->nr] = task;
438 462
439 if (verbose) 463 if (verbose > 0)
440 printf("registered task #%ld, PID %ld (%s)\n", sched->nr_tasks, pid, comm); 464 printf("registered task #%ld, PID %ld (%s)\n", sched->nr_tasks, pid, comm);
441 465
442 return task; 466 return task;
@@ -770,7 +794,7 @@ replay_wakeup_event(struct perf_sched *sched,
770 const u32 pid = perf_evsel__intval(evsel, sample, "pid"); 794 const u32 pid = perf_evsel__intval(evsel, sample, "pid");
771 struct task_desc *waker, *wakee; 795 struct task_desc *waker, *wakee;
772 796
773 if (verbose) { 797 if (verbose > 0) {
774 printf("sched_wakeup event %p\n", evsel); 798 printf("sched_wakeup event %p\n", evsel);
775 799
776 printf(" ... pid %d woke up %s/%d\n", sample->tid, comm, pid); 800 printf(" ... pid %d woke up %s/%d\n", sample->tid, comm, pid);
@@ -798,7 +822,7 @@ static int replay_switch_event(struct perf_sched *sched,
798 int cpu = sample->cpu; 822 int cpu = sample->cpu;
799 s64 delta; 823 s64 delta;
800 824
801 if (verbose) 825 if (verbose > 0)
802 printf("sched_switch event %p\n", evsel); 826 printf("sched_switch event %p\n", evsel);
803 827
804 if (cpu >= MAX_CPUS || cpu < 0) 828 if (cpu >= MAX_CPUS || cpu < 0)
@@ -846,7 +870,7 @@ static int replay_fork_event(struct perf_sched *sched,
846 goto out_put; 870 goto out_put;
847 } 871 }
848 872
849 if (verbose) { 873 if (verbose > 0) {
850 printf("fork event\n"); 874 printf("fork event\n");
851 printf("... parent: %s/%d\n", thread__comm_str(parent), parent->tid); 875 printf("... parent: %s/%d\n", thread__comm_str(parent), parent->tid);
852 printf("... child: %s/%d\n", thread__comm_str(child), child->tid); 876 printf("... child: %s/%d\n", thread__comm_str(child), child->tid);
@@ -1549,7 +1573,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1549 1573
1550 timestamp__scnprintf_usec(timestamp, stimestamp, sizeof(stimestamp)); 1574 timestamp__scnprintf_usec(timestamp, stimestamp, sizeof(stimestamp));
1551 color_fprintf(stdout, color, " %12s secs ", stimestamp); 1575 color_fprintf(stdout, color, " %12s secs ", stimestamp);
1552 if (new_shortname || (verbose && sched_in->tid)) { 1576 if (new_shortname || (verbose > 0 && sched_in->tid)) {
1553 const char *pid_color = color; 1577 const char *pid_color = color;
1554 1578
1555 if (thread__has_color(sched_in)) 1579 if (thread__has_color(sched_in))
@@ -1821,6 +1845,9 @@ static void timehist_header(struct perf_sched *sched)
1821 printf(" %-*s %9s %9s %9s", comm_width, 1845 printf(" %-*s %9s %9s %9s", comm_width,
1822 "task name", "wait time", "sch delay", "run time"); 1846 "task name", "wait time", "sch delay", "run time");
1823 1847
1848 if (sched->show_state)
1849 printf(" %s", "state");
1850
1824 printf("\n"); 1851 printf("\n");
1825 1852
1826 /* 1853 /*
@@ -1831,9 +1858,14 @@ static void timehist_header(struct perf_sched *sched)
1831 if (sched->show_cpu_visual) 1858 if (sched->show_cpu_visual)
1832 printf(" %*s ", ncpus, ""); 1859 printf(" %*s ", ncpus, "");
1833 1860
1834 printf(" %-*s %9s %9s %9s\n", comm_width, 1861 printf(" %-*s %9s %9s %9s", comm_width,
1835 "[tid/pid]", "(msec)", "(msec)", "(msec)"); 1862 "[tid/pid]", "(msec)", "(msec)", "(msec)");
1836 1863
1864 if (sched->show_state)
1865 printf(" %5s", "");
1866
1867 printf("\n");
1868
1837 /* 1869 /*
1838 * separator 1870 * separator
1839 */ 1871 */
@@ -1846,18 +1878,34 @@ static void timehist_header(struct perf_sched *sched)
1846 graph_dotted_line, graph_dotted_line, graph_dotted_line, 1878 graph_dotted_line, graph_dotted_line, graph_dotted_line,
1847 graph_dotted_line); 1879 graph_dotted_line);
1848 1880
1881 if (sched->show_state)
1882 printf(" %.5s", graph_dotted_line);
1883
1849 printf("\n"); 1884 printf("\n");
1850} 1885}
1851 1886
1887static char task_state_char(struct thread *thread, int state)
1888{
1889 static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
1890 unsigned bit = state ? ffs(state) : 0;
1891
1892 /* 'I' for idle */
1893 if (thread->tid == 0)
1894 return 'I';
1895
1896 return bit < sizeof(state_to_char) - 1 ? state_to_char[bit] : '?';
1897}
1898
1852static void timehist_print_sample(struct perf_sched *sched, 1899static void timehist_print_sample(struct perf_sched *sched,
1853 struct perf_sample *sample, 1900 struct perf_sample *sample,
1854 struct addr_location *al, 1901 struct addr_location *al,
1855 struct thread *thread, 1902 struct thread *thread,
1856 u64 t) 1903 u64 t, int state)
1857{ 1904{
1858 struct thread_runtime *tr = thread__priv(thread); 1905 struct thread_runtime *tr = thread__priv(thread);
1859 u32 max_cpus = sched->max_cpu + 1; 1906 u32 max_cpus = sched->max_cpu + 1;
1860 char tstr[64]; 1907 char tstr[64];
1908 u64 wait_time;
1861 1909
1862 timestamp__scnprintf_usec(t, tstr, sizeof(tstr)); 1910 timestamp__scnprintf_usec(t, tstr, sizeof(tstr));
1863 printf("%15s [%04d] ", tstr, sample->cpu); 1911 printf("%15s [%04d] ", tstr, sample->cpu);
@@ -1880,10 +1928,15 @@ static void timehist_print_sample(struct perf_sched *sched,
1880 1928
1881 printf(" %-*s ", comm_width, timehist_get_commstr(thread)); 1929 printf(" %-*s ", comm_width, timehist_get_commstr(thread));
1882 1930
1883 print_sched_time(tr->dt_wait, 6); 1931 wait_time = tr->dt_sleep + tr->dt_iowait + tr->dt_preempt;
1932 print_sched_time(wait_time, 6);
1933
1884 print_sched_time(tr->dt_delay, 6); 1934 print_sched_time(tr->dt_delay, 6);
1885 print_sched_time(tr->dt_run, 6); 1935 print_sched_time(tr->dt_run, 6);
1886 1936
1937 if (sched->show_state)
1938 printf(" %5c ", task_state_char(thread, state));
1939
1887 if (sched->show_wakeups) 1940 if (sched->show_wakeups)
1888 printf(" %-*s", comm_width, ""); 1941 printf(" %-*s", comm_width, "");
1889 1942
@@ -1930,8 +1983,11 @@ static void timehist_update_runtime_stats(struct thread_runtime *r,
1930 u64 t, u64 tprev) 1983 u64 t, u64 tprev)
1931{ 1984{
1932 r->dt_delay = 0; 1985 r->dt_delay = 0;
1933 r->dt_wait = 0; 1986 r->dt_sleep = 0;
1987 r->dt_iowait = 0;
1988 r->dt_preempt = 0;
1934 r->dt_run = 0; 1989 r->dt_run = 0;
1990
1935 if (tprev) { 1991 if (tprev) {
1936 r->dt_run = t - tprev; 1992 r->dt_run = t - tprev;
1937 if (r->ready_to_run) { 1993 if (r->ready_to_run) {
@@ -1943,12 +1999,25 @@ static void timehist_update_runtime_stats(struct thread_runtime *r,
1943 1999
1944 if (r->last_time > tprev) 2000 if (r->last_time > tprev)
1945 pr_debug("time travel: last sched out time for task > previous sched_switch event\n"); 2001 pr_debug("time travel: last sched out time for task > previous sched_switch event\n");
1946 else if (r->last_time) 2002 else if (r->last_time) {
1947 r->dt_wait = tprev - r->last_time; 2003 u64 dt_wait = tprev - r->last_time;
2004
2005 if (r->last_state == TASK_RUNNING)
2006 r->dt_preempt = dt_wait;
2007 else if (r->last_state == TASK_UNINTERRUPTIBLE)
2008 r->dt_iowait = dt_wait;
2009 else
2010 r->dt_sleep = dt_wait;
2011 }
1948 } 2012 }
1949 2013
1950 update_stats(&r->run_stats, r->dt_run); 2014 update_stats(&r->run_stats, r->dt_run);
1951 r->total_run_time += r->dt_run; 2015
2016 r->total_run_time += r->dt_run;
2017 r->total_delay_time += r->dt_delay;
2018 r->total_sleep_time += r->dt_sleep;
2019 r->total_iowait_time += r->dt_iowait;
2020 r->total_preempt_time += r->dt_preempt;
1952} 2021}
1953 2022
1954static bool is_idle_sample(struct perf_sample *sample, 2023static bool is_idle_sample(struct perf_sample *sample,
@@ -1981,7 +2050,7 @@ static void save_task_callchain(struct perf_sched *sched,
1981 2050
1982 if (thread__resolve_callchain(thread, cursor, evsel, sample, 2051 if (thread__resolve_callchain(thread, cursor, evsel, sample,
1983 NULL, NULL, sched->max_stack + 2) != 0) { 2052 NULL, NULL, sched->max_stack + 2) != 0) {
1984 if (verbose) 2053 if (verbose > 0)
1985 error("Failed to resolve callchain. Skipping\n"); 2054 error("Failed to resolve callchain. Skipping\n");
1986 2055
1987 return; 2056 return;
@@ -1998,7 +2067,7 @@ static void save_task_callchain(struct perf_sched *sched,
1998 break; 2067 break;
1999 2068
2000 sym = node->sym; 2069 sym = node->sym;
2001 if (sym && sym->name) { 2070 if (sym) {
2002 if (!strcmp(sym->name, "schedule") || 2071 if (!strcmp(sym->name, "schedule") ||
2003 !strcmp(sym->name, "__schedule") || 2072 !strcmp(sym->name, "__schedule") ||
2004 !strcmp(sym->name, "preempt_schedule")) 2073 !strcmp(sym->name, "preempt_schedule"))
@@ -2373,6 +2442,8 @@ static int timehist_sched_change_event(struct perf_tool *tool,
2373 struct thread_runtime *tr = NULL; 2442 struct thread_runtime *tr = NULL;
2374 u64 tprev, t = sample->time; 2443 u64 tprev, t = sample->time;
2375 int rc = 0; 2444 int rc = 0;
2445 int state = perf_evsel__intval(evsel, sample, "prev_state");
2446
2376 2447
2377 if (machine__resolve(machine, &al, sample) < 0) { 2448 if (machine__resolve(machine, &al, sample) < 0) {
2378 pr_err("problem processing %d event. skipping it\n", 2449 pr_err("problem processing %d event. skipping it\n",
@@ -2447,8 +2518,10 @@ static int timehist_sched_change_event(struct perf_tool *tool,
2447 * time. we only care total run time and run stat. 2518 * time. we only care total run time and run stat.
2448 */ 2519 */
2449 last_tr->dt_run = 0; 2520 last_tr->dt_run = 0;
2450 last_tr->dt_wait = 0;
2451 last_tr->dt_delay = 0; 2521 last_tr->dt_delay = 0;
2522 last_tr->dt_sleep = 0;
2523 last_tr->dt_iowait = 0;
2524 last_tr->dt_preempt = 0;
2452 2525
2453 if (itr->cursor.nr) 2526 if (itr->cursor.nr)
2454 callchain_append(&itr->callchain, &itr->cursor, t - tprev); 2527 callchain_append(&itr->callchain, &itr->cursor, t - tprev);
@@ -2458,7 +2531,7 @@ static int timehist_sched_change_event(struct perf_tool *tool,
2458 } 2531 }
2459 2532
2460 if (!sched->summary_only) 2533 if (!sched->summary_only)
2461 timehist_print_sample(sched, sample, &al, thread, t); 2534 timehist_print_sample(sched, sample, &al, thread, t, state);
2462 2535
2463out: 2536out:
2464 if (sched->hist_time.start == 0 && t >= ptime->start) 2537 if (sched->hist_time.start == 0 && t >= ptime->start)
@@ -2470,6 +2543,9 @@ out:
2470 /* time of this sched_switch event becomes last time task seen */ 2543 /* time of this sched_switch event becomes last time task seen */
2471 tr->last_time = sample->time; 2544 tr->last_time = sample->time;
2472 2545
2546 /* last state is used to determine where to account wait time */
2547 tr->last_state = state;
2548
2473 /* sched out event for task so reset ready to run time */ 2549 /* sched out event for task so reset ready to run time */
2474 tr->ready_to_run = 0; 2550 tr->ready_to_run = 0;
2475 } 2551 }
@@ -2526,7 +2602,26 @@ static void print_thread_runtime(struct thread *t,
2526 printf("\n"); 2602 printf("\n");
2527} 2603}
2528 2604
2605static void print_thread_waittime(struct thread *t,
2606 struct thread_runtime *r)
2607{
2608 printf("%*s %5d %9" PRIu64 " ",
2609 comm_width, timehist_get_commstr(t), t->ppid,
2610 (u64) r->run_stats.n);
2611
2612 print_sched_time(r->total_run_time, 8);
2613 print_sched_time(r->total_sleep_time, 6);
2614 printf(" ");
2615 print_sched_time(r->total_iowait_time, 6);
2616 printf(" ");
2617 print_sched_time(r->total_preempt_time, 6);
2618 printf(" ");
2619 print_sched_time(r->total_delay_time, 6);
2620 printf("\n");
2621}
2622
2529struct total_run_stats { 2623struct total_run_stats {
2624 struct perf_sched *sched;
2530 u64 sched_count; 2625 u64 sched_count;
2531 u64 task_count; 2626 u64 task_count;
2532 u64 total_run_time; 2627 u64 total_run_time;
@@ -2545,7 +2640,11 @@ static int __show_thread_runtime(struct thread *t, void *priv)
2545 stats->task_count++; 2640 stats->task_count++;
2546 stats->sched_count += r->run_stats.n; 2641 stats->sched_count += r->run_stats.n;
2547 stats->total_run_time += r->total_run_time; 2642 stats->total_run_time += r->total_run_time;
2548 print_thread_runtime(t, r); 2643
2644 if (stats->sched->show_state)
2645 print_thread_waittime(t, r);
2646 else
2647 print_thread_runtime(t, r);
2549 } 2648 }
2550 2649
2551 return 0; 2650 return 0;
@@ -2633,18 +2732,24 @@ static void timehist_print_summary(struct perf_sched *sched,
2633 u64 hist_time = sched->hist_time.end - sched->hist_time.start; 2732 u64 hist_time = sched->hist_time.end - sched->hist_time.start;
2634 2733
2635 memset(&totals, 0, sizeof(totals)); 2734 memset(&totals, 0, sizeof(totals));
2735 totals.sched = sched;
2636 2736
2637 if (sched->idle_hist) { 2737 if (sched->idle_hist) {
2638 printf("\nIdle-time summary\n"); 2738 printf("\nIdle-time summary\n");
2639 printf("%*s parent sched-out ", comm_width, "comm"); 2739 printf("%*s parent sched-out ", comm_width, "comm");
2640 printf(" idle-time min-idle avg-idle max-idle stddev migrations\n"); 2740 printf(" idle-time min-idle avg-idle max-idle stddev migrations\n");
2741 } else if (sched->show_state) {
2742 printf("\nWait-time summary\n");
2743 printf("%*s parent sched-in ", comm_width, "comm");
2744 printf(" run-time sleep iowait preempt delay\n");
2641 } else { 2745 } else {
2642 printf("\nRuntime summary\n"); 2746 printf("\nRuntime summary\n");
2643 printf("%*s parent sched-in ", comm_width, "comm"); 2747 printf("%*s parent sched-in ", comm_width, "comm");
2644 printf(" run-time min-run avg-run max-run stddev migrations\n"); 2748 printf(" run-time min-run avg-run max-run stddev migrations\n");
2645 } 2749 }
2646 printf("%*s (count) ", comm_width, ""); 2750 printf("%*s (count) ", comm_width, "");
2647 printf(" (msec) (msec) (msec) (msec) %%\n"); 2751 printf(" (msec) (msec) (msec) (msec) %s\n",
2752 sched->show_state ? "(msec)" : "%");
2648 printf("%.117s\n", graph_dotted_line); 2753 printf("%.117s\n", graph_dotted_line);
2649 2754
2650 machine__for_each_thread(m, show_thread_runtime, &totals); 2755 machine__for_each_thread(m, show_thread_runtime, &totals);
@@ -3240,6 +3345,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
3240 OPT_BOOLEAN('I', "idle-hist", &sched.idle_hist, "Show idle events only"), 3345 OPT_BOOLEAN('I', "idle-hist", &sched.idle_hist, "Show idle events only"),
3241 OPT_STRING(0, "time", &sched.time_str, "str", 3346 OPT_STRING(0, "time", &sched.time_str, "str",
3242 "Time span for analysis (start,stop)"), 3347 "Time span for analysis (start,stop)"),
3348 OPT_BOOLEAN(0, "state", &sched.show_state, "Show task state when sched-out"),
3243 OPT_PARENT(sched_options) 3349 OPT_PARENT(sched_options)
3244 }; 3350 };
3245 3351
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 2f3ff69fc4e7..c0783b4f7b6c 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -2180,7 +2180,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2180 "Show the mmap events"), 2180 "Show the mmap events"),
2181 OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events, 2181 OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events,
2182 "Show context switch events (if recorded)"), 2182 "Show context switch events (if recorded)"),
2183 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), 2183 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
2184 OPT_BOOLEAN(0, "ns", &nanosecs, 2184 OPT_BOOLEAN(0, "ns", &nanosecs,
2185 "Use 9 decimal places when displaying time"), 2185 "Use 9 decimal places when displaying time"),
2186 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", 2186 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
@@ -2212,6 +2212,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2212 PARSE_OPT_STOP_AT_NON_OPTION); 2212 PARSE_OPT_STOP_AT_NON_OPTION);
2213 2213
2214 file.path = input_name; 2214 file.path = input_name;
2215 file.force = symbol_conf.force;
2215 2216
2216 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { 2217 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
2217 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); 2218 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a02f2e965628..13b54999ad79 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -533,7 +533,7 @@ static int store_counter_ids(struct perf_evsel *counter)
533static int __run_perf_stat(int argc, const char **argv) 533static int __run_perf_stat(int argc, const char **argv)
534{ 534{
535 int interval = stat_config.interval; 535 int interval = stat_config.interval;
536 char msg[512]; 536 char msg[BUFSIZ];
537 unsigned long long t0, t1; 537 unsigned long long t0, t1;
538 struct perf_evsel *counter; 538 struct perf_evsel *counter;
539 struct timespec ts; 539 struct timespec ts;
@@ -573,7 +573,7 @@ try_again:
573 if (errno == EINVAL || errno == ENOSYS || 573 if (errno == EINVAL || errno == ENOSYS ||
574 errno == ENOENT || errno == EOPNOTSUPP || 574 errno == ENOENT || errno == EOPNOTSUPP ||
575 errno == ENXIO) { 575 errno == ENXIO) {
576 if (verbose) 576 if (verbose > 0)
577 ui__warning("%s event is not supported by the kernel.\n", 577 ui__warning("%s event is not supported by the kernel.\n",
578 perf_evsel__name(counter)); 578 perf_evsel__name(counter));
579 counter->supported = false; 579 counter->supported = false;
@@ -582,7 +582,7 @@ try_again:
582 !(counter->leader->nr_members > 1)) 582 !(counter->leader->nr_members > 1))
583 continue; 583 continue;
584 } else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) { 584 } else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
585 if (verbose) 585 if (verbose > 0)
586 ui__warning("%s\n", msg); 586 ui__warning("%s\n", msg);
587 goto try_again; 587 goto try_again;
588 } 588 }
@@ -1765,7 +1765,7 @@ static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, i
1765 1765
1766 cpu = map->map[idx]; 1766 cpu = map->map[idx];
1767 1767
1768 if (cpu >= env->nr_cpus_online) 1768 if (cpu >= env->nr_cpus_avail)
1769 return -1; 1769 return -1;
1770 1770
1771 return cpu; 1771 return cpu;
@@ -2445,8 +2445,9 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
2445 } else if (big_num_opt == 0) /* User passed --no-big-num */ 2445 } else if (big_num_opt == 0) /* User passed --no-big-num */
2446 big_num = false; 2446 big_num = false;
2447 2447
2448 /* Make system wide (-a) the default target. */
2448 if (!argc && target__none(&target)) 2449 if (!argc && target__none(&target))
2449 usage_with_options(stat_usage, stat_options); 2450 target.system_wide = true;
2450 2451
2451 if (run_count < 0) { 2452 if (run_count < 0) {
2452 pr_err("Run count must be a positive number\n"); 2453 pr_err("Run count must be a positive number\n");
@@ -2538,7 +2539,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
2538 2539
2539 status = 0; 2540 status = 0;
2540 for (run_idx = 0; forever || run_idx < run_count; run_idx++) { 2541 for (run_idx = 0; forever || run_idx < run_count; run_idx++) {
2541 if (run_count != 1 && verbose) 2542 if (run_count != 1 && verbose > 0)
2542 fprintf(output, "[ perf stat: executing run #%d ... ]\n", 2543 fprintf(output, "[ perf stat: executing run #%d ... ]\n",
2543 run_idx + 1); 2544 run_idx + 1);
2544 2545
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 3df4178ba378..ab9077915763 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -643,7 +643,7 @@ repeat:
643 case -1: 643 case -1:
644 if (errno == EINTR) 644 if (errno == EINTR)
645 continue; 645 continue;
646 /* Fall trhu */ 646 __fallthrough;
647 default: 647 default:
648 c = getc(stdin); 648 c = getc(stdin);
649 tcsetattr(0, TCSAFLUSH, &save); 649 tcsetattr(0, TCSAFLUSH, &save);
@@ -859,7 +859,7 @@ static void perf_top__mmap_read(struct perf_top *top)
859 859
860static int perf_top__start_counters(struct perf_top *top) 860static int perf_top__start_counters(struct perf_top *top)
861{ 861{
862 char msg[512]; 862 char msg[BUFSIZ];
863 struct perf_evsel *counter; 863 struct perf_evsel *counter;
864 struct perf_evlist *evlist = top->evlist; 864 struct perf_evlist *evlist = top->evlist;
865 struct record_opts *opts = &top->record_opts; 865 struct record_opts *opts = &top->record_opts;
@@ -871,7 +871,7 @@ try_again:
871 if (perf_evsel__open(counter, top->evlist->cpus, 871 if (perf_evsel__open(counter, top->evlist->cpus,
872 top->evlist->threads) < 0) { 872 top->evlist->threads) < 0) {
873 if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) { 873 if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
874 if (verbose) 874 if (verbose > 0)
875 ui__warning("%s\n", msg); 875 ui__warning("%s\n", msg);
876 goto try_again; 876 goto try_again;
877 } 877 }
@@ -1216,7 +1216,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1216 if (top.evlist == NULL) 1216 if (top.evlist == NULL)
1217 return -ENOMEM; 1217 return -ENOMEM;
1218 1218
1219 perf_config(perf_top_config, &top); 1219 status = perf_config(perf_top_config, &top);
1220 if (status)
1221 return status;
1220 1222
1221 argc = parse_options(argc, argv, options, top_usage, 0); 1223 argc = parse_options(argc, argv, options, top_usage, 0);
1222 if (argc) 1224 if (argc)
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 206bf72b77fc..256f1fac6f7e 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -40,6 +40,7 @@
40 40
41#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */ 41#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
42#include <stdlib.h> 42#include <stdlib.h>
43#include <string.h>
43#include <linux/err.h> 44#include <linux/err.h>
44#include <linux/filter.h> 45#include <linux/filter.h>
45#include <linux/audit.h> 46#include <linux/audit.h>
@@ -1398,7 +1399,7 @@ static struct syscall *trace__syscall_info(struct trace *trace,
1398 return &trace->syscalls.table[id]; 1399 return &trace->syscalls.table[id];
1399 1400
1400out_cant_read: 1401out_cant_read:
1401 if (verbose) { 1402 if (verbose > 0) {
1402 fprintf(trace->output, "Problems reading syscall %d", id); 1403 fprintf(trace->output, "Problems reading syscall %d", id);
1403 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL) 1404 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1404 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name); 1405 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
@@ -1800,10 +1801,10 @@ static void print_location(FILE *f, struct perf_sample *sample,
1800 bool print_dso, bool print_sym) 1801 bool print_dso, bool print_sym)
1801{ 1802{
1802 1803
1803 if ((verbose || print_dso) && al->map) 1804 if ((verbose > 0 || print_dso) && al->map)
1804 fprintf(f, "%s@", al->map->dso->long_name); 1805 fprintf(f, "%s@", al->map->dso->long_name);
1805 1806
1806 if ((verbose || print_sym) && al->sym) 1807 if ((verbose > 0 || print_sym) && al->sym)
1807 fprintf(f, "%s+0x%" PRIx64, al->sym->name, 1808 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
1808 al->addr - al->sym->start); 1809 al->addr - al->sym->start);
1809 else if (al->map) 1810 else if (al->map)
@@ -2699,6 +2700,91 @@ static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2699 evsel->handler = handler; 2700 evsel->handler = handler;
2700} 2701}
2701 2702
2703/*
2704 * XXX: Hackish, just splitting the combined -e+--event (syscalls
2705 * (raw_syscalls:{sys_{enter,exit}} + events (tracepoints, HW, SW, etc) to use
2706 * existing facilities unchanged (trace->ev_qualifier + parse_options()).
2707 *
2708 * It'd be better to introduce a parse_options() variant that would return a
2709 * list with the terms it didn't match to an event...
2710 */
2711static int trace__parse_events_option(const struct option *opt, const char *str,
2712 int unset __maybe_unused)
2713{
2714 struct trace *trace = (struct trace *)opt->value;
2715 const char *s = str;
2716 char *sep = NULL, *lists[2] = { NULL, NULL, };
2717 int len = strlen(str), err = -1, list;
2718 char *strace_groups_dir = system_path(STRACE_GROUPS_DIR);
2719 char group_name[PATH_MAX];
2720
2721 if (strace_groups_dir == NULL)
2722 return -1;
2723
2724 if (*s == '!') {
2725 ++s;
2726 trace->not_ev_qualifier = true;
2727 }
2728
2729 while (1) {
2730 if ((sep = strchr(s, ',')) != NULL)
2731 *sep = '\0';
2732
2733 list = 0;
2734 if (syscalltbl__id(trace->sctbl, s) >= 0) {
2735 list = 1;
2736 } else {
2737 path__join(group_name, sizeof(group_name), strace_groups_dir, s);
2738 if (access(group_name, R_OK) == 0)
2739 list = 1;
2740 }
2741
2742 if (lists[list]) {
2743 sprintf(lists[list] + strlen(lists[list]), ",%s", s);
2744 } else {
2745 lists[list] = malloc(len);
2746 if (lists[list] == NULL)
2747 goto out;
2748 strcpy(lists[list], s);
2749 }
2750
2751 if (!sep)
2752 break;
2753
2754 *sep = ',';
2755 s = sep + 1;
2756 }
2757
2758 if (lists[1] != NULL) {
2759 struct strlist_config slist_config = {
2760 .dirname = strace_groups_dir,
2761 };
2762
2763 trace->ev_qualifier = strlist__new(lists[1], &slist_config);
2764 if (trace->ev_qualifier == NULL) {
2765 fputs("Not enough memory to parse event qualifier", trace->output);
2766 goto out;
2767 }
2768
2769 if (trace__validate_ev_qualifier(trace))
2770 goto out;
2771 }
2772
2773 err = 0;
2774
2775 if (lists[0]) {
2776 struct option o = OPT_CALLBACK('e', "event", &trace->evlist, "event",
2777 "event selector. use 'perf list' to list available events",
2778 parse_events_option);
2779 err = parse_events_option(&o, lists[0], 0);
2780 }
2781out:
2782 if (sep)
2783 *sep = ',';
2784
2785 return err;
2786}
2787
2702int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) 2788int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2703{ 2789{
2704 const char *trace_usage[] = { 2790 const char *trace_usage[] = {
@@ -2730,15 +2816,15 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2730 .max_stack = UINT_MAX, 2816 .max_stack = UINT_MAX,
2731 }; 2817 };
2732 const char *output_name = NULL; 2818 const char *output_name = NULL;
2733 const char *ev_qualifier_str = NULL;
2734 const struct option trace_options[] = { 2819 const struct option trace_options[] = {
2735 OPT_CALLBACK(0, "event", &trace.evlist, "event", 2820 OPT_CALLBACK('e', "event", &trace, "event",
2736 "event selector. use 'perf list' to list available events", 2821 "event/syscall selector. use 'perf list' to list available events",
2737 parse_events_option), 2822 trace__parse_events_option),
2738 OPT_BOOLEAN(0, "comm", &trace.show_comm, 2823 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2739 "show the thread COMM next to its id"), 2824 "show the thread COMM next to its id"),
2740 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"), 2825 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
2741 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"), 2826 OPT_CALLBACK(0, "expr", &trace, "expr", "list of syscalls/events to trace",
2827 trace__parse_events_option),
2742 OPT_STRING('o', "output", &output_name, "file", "output file name"), 2828 OPT_STRING('o', "output", &output_name, "file", "output file name"),
2743 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"), 2829 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
2744 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid", 2830 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
@@ -2863,7 +2949,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2863 return -1; 2949 return -1;
2864 } 2950 }
2865 2951
2866 if (!trace.trace_syscalls && ev_qualifier_str) { 2952 if (!trace.trace_syscalls && trace.ev_qualifier) {
2867 pr_err("The -e option can't be used with --no-syscalls.\n"); 2953 pr_err("The -e option can't be used with --no-syscalls.\n");
2868 goto out; 2954 goto out;
2869 } 2955 }
@@ -2878,28 +2964,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2878 2964
2879 trace.open_id = syscalltbl__id(trace.sctbl, "open"); 2965 trace.open_id = syscalltbl__id(trace.sctbl, "open");
2880 2966
2881 if (ev_qualifier_str != NULL) {
2882 const char *s = ev_qualifier_str;
2883 struct strlist_config slist_config = {
2884 .dirname = system_path(STRACE_GROUPS_DIR),
2885 };
2886
2887 trace.not_ev_qualifier = *s == '!';
2888 if (trace.not_ev_qualifier)
2889 ++s;
2890 trace.ev_qualifier = strlist__new(s, &slist_config);
2891 if (trace.ev_qualifier == NULL) {
2892 fputs("Not enough memory to parse event qualifier",
2893 trace.output);
2894 err = -ENOMEM;
2895 goto out_close;
2896 }
2897
2898 err = trace__validate_ev_qualifier(&trace);
2899 if (err)
2900 goto out_close;
2901 }
2902
2903 err = target__validate(&trace.opts.target); 2967 err = target__validate(&trace.opts.target);
2904 if (err) { 2968 if (err) {
2905 target__strerror(&trace.opts.target, err, bf, sizeof(bf)); 2969 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 0bcf68e98ccc..036e1e35b1a8 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -23,6 +23,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix);
23int cmd_evlist(int argc, const char **argv, const char *prefix); 23int cmd_evlist(int argc, const char **argv, const char *prefix);
24int cmd_help(int argc, const char **argv, const char *prefix); 24int cmd_help(int argc, const char **argv, const char *prefix);
25int cmd_sched(int argc, const char **argv, const char *prefix); 25int cmd_sched(int argc, const char **argv, const char *prefix);
26int cmd_kallsyms(int argc, const char **argv, const char *prefix);
26int cmd_list(int argc, const char **argv, const char *prefix); 27int cmd_list(int argc, const char **argv, const char *prefix);
27int cmd_record(int argc, const char **argv, const char *prefix); 28int cmd_record(int argc, const char **argv, const char *prefix);
28int cmd_report(int argc, const char **argv, const char *prefix); 29int cmd_report(int argc, const char **argv, const char *prefix);
@@ -40,6 +41,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix);
40int cmd_inject(int argc, const char **argv, const char *prefix); 41int cmd_inject(int argc, const char **argv, const char *prefix);
41int cmd_mem(int argc, const char **argv, const char *prefix); 42int cmd_mem(int argc, const char **argv, const char *prefix);
42int cmd_data(int argc, const char **argv, const char *prefix); 43int cmd_data(int argc, const char **argv, const char *prefix);
44int cmd_ftrace(int argc, const char **argv, const char *prefix);
43 45
44int find_scripts(char **scripts_array, char **scripts_path_array); 46int find_scripts(char **scripts_array, char **scripts_path_array);
45#endif 47#endif
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index ab5cbaa170d0..ac3efd396a72 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -11,7 +11,9 @@ perf-data mainporcelain common
11perf-diff mainporcelain common 11perf-diff mainporcelain common
12perf-config mainporcelain common 12perf-config mainporcelain common
13perf-evlist mainporcelain common 13perf-evlist mainporcelain common
14perf-ftrace mainporcelain common
14perf-inject mainporcelain common 15perf-inject mainporcelain common
16perf-kallsyms mainporcelain common
15perf-kmem mainporcelain common 17perf-kmem mainporcelain common
16perf-kvm mainporcelain common 18perf-kvm mainporcelain common
17perf-list mainporcelain common 19perf-list mainporcelain common
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index aa23b3347d6b..6d5479e03e0d 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -29,7 +29,6 @@ const char perf_usage_string[] =
29const char perf_more_info_string[] = 29const char perf_more_info_string[] =
30 "See 'perf help COMMAND' for more information on a specific command."; 30 "See 'perf help COMMAND' for more information on a specific command.";
31 31
32int use_browser = -1;
33static int use_pager = -1; 32static int use_pager = -1;
34const char *input_name; 33const char *input_name;
35 34
@@ -47,6 +46,7 @@ static struct cmd_struct commands[] = {
47 { "diff", cmd_diff, 0 }, 46 { "diff", cmd_diff, 0 },
48 { "evlist", cmd_evlist, 0 }, 47 { "evlist", cmd_evlist, 0 },
49 { "help", cmd_help, 0 }, 48 { "help", cmd_help, 0 },
49 { "kallsyms", cmd_kallsyms, 0 },
50 { "list", cmd_list, 0 }, 50 { "list", cmd_list, 0 },
51 { "record", cmd_record, 0 }, 51 { "record", cmd_record, 0 },
52 { "report", cmd_report, 0 }, 52 { "report", cmd_report, 0 },
@@ -71,6 +71,7 @@ static struct cmd_struct commands[] = {
71 { "inject", cmd_inject, 0 }, 71 { "inject", cmd_inject, 0 },
72 { "mem", cmd_mem, 0 }, 72 { "mem", cmd_mem, 0 },
73 { "data", cmd_data, 0 }, 73 { "data", cmd_data, 0 },
74 { "ftrace", cmd_ftrace, 0 },
74}; 75};
75 76
76struct pager_config { 77struct pager_config {
@@ -89,11 +90,12 @@ static int pager_command_config(const char *var, const char *value, void *data)
89/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */ 90/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
90int check_pager_config(const char *cmd) 91int check_pager_config(const char *cmd)
91{ 92{
93 int err;
92 struct pager_config c; 94 struct pager_config c;
93 c.cmd = cmd; 95 c.cmd = cmd;
94 c.val = -1; 96 c.val = -1;
95 perf_config(pager_command_config, &c); 97 err = perf_config(pager_command_config, &c);
96 return c.val; 98 return err ?: c.val;
97} 99}
98 100
99static int browser_command_config(const char *var, const char *value, void *data) 101static int browser_command_config(const char *var, const char *value, void *data)
@@ -112,11 +114,12 @@ static int browser_command_config(const char *var, const char *value, void *data
112 */ 114 */
113static int check_browser_config(const char *cmd) 115static int check_browser_config(const char *cmd)
114{ 116{
117 int err;
115 struct pager_config c; 118 struct pager_config c;
116 c.cmd = cmd; 119 c.cmd = cmd;
117 c.val = -1; 120 c.val = -1;
118 perf_config(browser_command_config, &c); 121 err = perf_config(browser_command_config, &c);
119 return c.val; 122 return err ?: c.val;
120} 123}
121 124
122static void commit_pager_choice(void) 125static void commit_pager_choice(void)
@@ -329,8 +332,6 @@ static int handle_alias(int *argcp, const char ***argv)
329 return ret; 332 return ret;
330} 333}
331 334
332const char perf_version_string[] = PERF_VERSION;
333
334#define RUN_SETUP (1<<0) 335#define RUN_SETUP (1<<0)
335#define USE_PAGER (1<<1) 336#define USE_PAGER (1<<1)
336 337
@@ -510,6 +511,7 @@ static void cache_line_size(int *cacheline_sizep)
510 511
511int main(int argc, const char **argv) 512int main(int argc, const char **argv)
512{ 513{
514 int err;
513 const char *cmd; 515 const char *cmd;
514 char sbuf[STRERR_BUFSIZE]; 516 char sbuf[STRERR_BUFSIZE];
515 int value; 517 int value;
@@ -535,7 +537,9 @@ int main(int argc, const char **argv)
535 srandom(time(NULL)); 537 srandom(time(NULL));
536 538
537 perf_config__init(); 539 perf_config__init();
538 perf_config(perf_default_config, NULL); 540 err = perf_config(perf_default_config, NULL);
541 if (err)
542 return err;
539 set_buildid_dir(NULL); 543 set_buildid_dir(NULL);
540 544
541 /* get debugfs/tracefs mount point from /proc/mounts */ 545 /* get debugfs/tracefs mount point from /proc/mounts */
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/uncore-cache.json b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-cache.json
new file mode 100644
index 000000000000..076459c51d4e
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-cache.json
@@ -0,0 +1,317 @@
1[
2 {
3 "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
4 "Counter": "0,1,2,3",
5 "EventName": "UNC_C_CLOCKTICKS",
6 "PerPkg": "1",
7 "Unit": "CBO"
8 },
9 {
10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
11 "Counter": "0,1,2,3",
12 "EventCode": "0x34",
13 "EventName": "UNC_C_LLC_LOOKUP.ANY",
14 "Filter": "filter_state=0x1",
15 "PerPkg": "1",
16 "ScaleUnit": "64Bytes",
17 "UMask": "0x11",
18 "Unit": "CBO"
19 },
20 {
21 "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
22 "Counter": "0,1,2,3",
23 "EventCode": "0x37",
24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
25 "PerPkg": "1",
26 "ScaleUnit": "64Bytes",
27 "UMask": "0x1",
28 "Unit": "CBO"
29 },
30 {
31 "BriefDescription": "LLC misses - demand and prefetch data reads - excludes LLC prefetches. Derived from unc_c_tor_inserts.miss_opcode",
32 "Counter": "0,1,2,3",
33 "EventCode": "0x35",
34 "EventName": "LLC_MISSES.DATA_READ",
35 "Filter": "filter_opc=0x182",
36 "PerPkg": "1",
37 "ScaleUnit": "64Bytes",
38 "UMask": "0x3",
39 "Unit": "CBO"
40 },
41 {
42 "BriefDescription": "LLC misses - Uncacheable reads (from cpu) . Derived from unc_c_tor_inserts.miss_opcode",
43 "Counter": "0,1,2,3",
44 "EventCode": "0x35",
45 "EventName": "LLC_MISSES.UNCACHEABLE",
46 "Filter": "filter_opc=0x187",
47 "PerPkg": "1",
48 "ScaleUnit": "64Bytes",
49 "UMask": "0x3",
50 "Unit": "CBO"
51 },
52 {
53 "BriefDescription": "MMIO reads. Derived from unc_c_tor_inserts.miss_opcode",
54 "Counter": "0,1,2,3",
55 "EventCode": "0x35",
56 "EventName": "LLC_MISSES.MMIO_READ",
57 "Filter": "filter_opc=0x187,filter_nc=1",
58 "PerPkg": "1",
59 "ScaleUnit": "64Bytes",
60 "UMask": "0x3",
61 "Unit": "CBO"
62 },
63 {
64 "BriefDescription": "MMIO writes. Derived from unc_c_tor_inserts.miss_opcode",
65 "Counter": "0,1,2,3",
66 "EventCode": "0x35",
67 "EventName": "LLC_MISSES.MMIO_WRITE",
68 "Filter": "filter_opc=0x18f,filter_nc=1",
69 "PerPkg": "1",
70 "ScaleUnit": "64Bytes",
71 "UMask": "0x3",
72 "Unit": "CBO"
73 },
74 {
75 "BriefDescription": "LLC prefetch misses for RFO. Derived from unc_c_tor_inserts.miss_opcode",
76 "Counter": "0,1,2,3",
77 "EventCode": "0x35",
78 "EventName": "LLC_MISSES.RFO_LLC_PREFETCH",
79 "Filter": "filter_opc=0x190",
80 "PerPkg": "1",
81 "ScaleUnit": "64Bytes",
82 "UMask": "0x3",
83 "Unit": "CBO"
84 },
85 {
86 "BriefDescription": "LLC prefetch misses for code reads. Derived from unc_c_tor_inserts.miss_opcode",
87 "Counter": "0,1,2,3",
88 "EventCode": "0x35",
89 "EventName": "LLC_MISSES.CODE_LLC_PREFETCH",
90 "Filter": "filter_opc=0x191",
91 "PerPkg": "1",
92 "ScaleUnit": "64Bytes",
93 "UMask": "0x3",
94 "Unit": "CBO"
95 },
96 {
97 "BriefDescription": "LLC prefetch misses for data reads. Derived from unc_c_tor_inserts.miss_opcode",
98 "Counter": "0,1,2,3",
99 "EventCode": "0x35",
100 "EventName": "LLC_MISSES.DATA_LLC_PREFETCH",
101 "Filter": "filter_opc=0x192",
102 "PerPkg": "1",
103 "ScaleUnit": "64Bytes",
104 "UMask": "0x3",
105 "Unit": "CBO"
106 },
107 {
108 "BriefDescription": "LLC misses for PCIe read current. Derived from unc_c_tor_inserts.miss_opcode",
109 "Counter": "0,1,2,3",
110 "EventCode": "0x35",
111 "EventName": "LLC_MISSES.PCIE_READ",
112 "Filter": "filter_opc=0x19e",
113 "PerPkg": "1",
114 "ScaleUnit": "64Bytes",
115 "UMask": "0x3",
116 "Unit": "CBO"
117 },
118 {
119 "BriefDescription": "ItoM write misses (as part of fast string memcpy stores) + PCIe full line writes. Derived from unc_c_tor_inserts.miss_opcode",
120 "Counter": "0,1,2,3",
121 "EventCode": "0x35",
122 "EventName": "LLC_MISSES.PCIE_WRITE",
123 "Filter": "filter_opc=0x1c8",
124 "PerPkg": "1",
125 "ScaleUnit": "64Bytes",
126 "UMask": "0x3",
127 "Unit": "CBO"
128 },
129 {
130 "BriefDescription": "PCIe write misses (full cache line). Derived from unc_c_tor_inserts.miss_opcode",
131 "Counter": "0,1,2,3",
132 "EventCode": "0x35",
133 "EventName": "LLC_MISSES.PCIE_NON_SNOOP_WRITE",
134 "Filter": "filter_opc=0x1c8,filter_tid=0x3e",
135 "PerPkg": "1",
136 "ScaleUnit": "64Bytes",
137 "UMask": "0x3",
138 "Unit": "CBO"
139 },
140 {
141 "BriefDescription": "PCIe writes (partial cache line). Derived from unc_c_tor_inserts.opcode",
142 "Counter": "0,1,2,3",
143 "EventCode": "0x35",
144 "EventName": "LLC_REFERENCES.PCIE_NS_PARTIAL_WRITE",
145 "Filter": "filter_opc=0x180,filter_tid=0x3e",
146 "PerPkg": "1",
147 "UMask": "0x1",
148 "Unit": "CBO"
149 },
150 {
151 "BriefDescription": "L2 demand and L2 prefetch code references to LLC. Derived from unc_c_tor_inserts.opcode",
152 "Counter": "0,1,2,3",
153 "EventCode": "0x35",
154 "EventName": "LLC_REFERENCES.CODE_LLC_PREFETCH",
155 "Filter": "filter_opc=0x181",
156 "PerPkg": "1",
157 "ScaleUnit": "64Bytes",
158 "UMask": "0x1",
159 "Unit": "CBO"
160 },
161 {
162 "BriefDescription": "Streaming stores (full cache line). Derived from unc_c_tor_inserts.opcode",
163 "Counter": "0,1,2,3",
164 "EventCode": "0x35",
165 "EventName": "LLC_REFERENCES.STREAMING_FULL",
166 "Filter": "filter_opc=0x18c",
167 "PerPkg": "1",
168 "ScaleUnit": "64Bytes",
169 "UMask": "0x1",
170 "Unit": "CBO"
171 },
172 {
173 "BriefDescription": "Streaming stores (partial cache line). Derived from unc_c_tor_inserts.opcode",
174 "Counter": "0,1,2,3",
175 "EventCode": "0x35",
176 "EventName": "LLC_REFERENCES.STREAMING_PARTIAL",
177 "Filter": "filter_opc=0x18d",
178 "PerPkg": "1",
179 "ScaleUnit": "64Bytes",
180 "UMask": "0x1",
181 "Unit": "CBO"
182 },
183 {
184 "BriefDescription": "PCIe read current. Derived from unc_c_tor_inserts.opcode",
185 "Counter": "0,1,2,3",
186 "EventCode": "0x35",
187 "EventName": "LLC_REFERENCES.PCIE_READ",
188 "Filter": "filter_opc=0x19e",
189 "PerPkg": "1",
190 "ScaleUnit": "64Bytes",
191 "UMask": "0x1",
192 "Unit": "CBO"
193 },
194 {
195 "BriefDescription": "PCIe write references (full cache line). Derived from unc_c_tor_inserts.opcode",
196 "Counter": "0,1,2,3",
197 "EventCode": "0x35",
198 "EventName": "LLC_REFERENCES.PCIE_WRITE",
199 "Filter": "filter_opc=0x1c8,filter_tid=0x3e",
200 "PerPkg": "1",
201 "ScaleUnit": "64Bytes",
202 "UMask": "0x1",
203 "Unit": "CBO"
204 },
205 {
206 "BriefDescription": "Occupancy counter for LLC data reads (demand and L2 prefetch). Derived from unc_c_tor_occupancy.miss_opcode",
207 "EventCode": "0x36",
208 "EventName": "UNC_C_TOR_OCCUPANCY.LLC_DATA_READ",
209 "Filter": "filter_opc=0x182",
210 "PerPkg": "1",
211 "UMask": "0x3",
212 "Unit": "CBO"
213 },
214 {
215 "BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads",
216 "Counter": "0,1,2,3",
217 "EventCode": "0x1",
218 "EventName": "UNC_H_REQUESTS.READS",
219 "PerPkg": "1",
220 "UMask": "0x3",
221 "Unit": "HA"
222 },
223 {
224 "BriefDescription": "read requests to local home agent. Derived from unc_h_requests.reads_local",
225 "Counter": "0,1,2,3",
226 "EventCode": "0x1",
227 "EventName": "UNC_H_REQUESTS.READS_LOCAL",
228 "PerPkg": "1",
229 "UMask": "0x1",
230 "Unit": "HA"
231 },
232 {
233 "BriefDescription": "read requests to remote home agent. Derived from unc_h_requests.reads_remote",
234 "Counter": "0,1,2,3",
235 "EventCode": "0x1",
236 "EventName": "UNC_H_REQUESTS.READS_REMOTE",
237 "PerPkg": "1",
238 "UMask": "0x2",
239 "Unit": "HA"
240 },
241 {
242 "BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes",
243 "Counter": "0,1,2,3",
244 "EventCode": "0x1",
245 "EventName": "UNC_H_REQUESTS.WRITES",
246 "PerPkg": "1",
247 "UMask": "0xC",
248 "Unit": "HA"
249 },
250 {
251 "BriefDescription": "write requests to local home agent. Derived from unc_h_requests.writes_local",
252 "Counter": "0,1,2,3",
253 "EventCode": "0x1",
254 "EventName": "UNC_H_REQUESTS.WRITES_LOCAL",
255 "PerPkg": "1",
256 "UMask": "0x4",
257 "Unit": "HA"
258 },
259 {
260 "BriefDescription": "write requests to remote home agent. Derived from unc_h_requests.writes_remote",
261 "Counter": "0,1,2,3",
262 "EventCode": "0x1",
263 "EventName": "UNC_H_REQUESTS.WRITES_REMOTE",
264 "PerPkg": "1",
265 "UMask": "0x8",
266 "Unit": "HA"
267 },
268 {
269 "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously). Derived from unc_h_snoop_resp.rspcnflct",
270 "Counter": "0,1,2,3",
271 "EventCode": "0x21",
272 "EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT",
273 "PerPkg": "1",
274 "UMask": "0x40",
275 "Unit": "HA"
276 },
277 {
278 "BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb",
279 "Counter": "0,1,2,3",
280 "EventCode": "0x21",
281 "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
282 "PerPkg": "1",
283 "ScaleUnit": "64Bytes",
284 "UMask": "0x20",
285 "Unit": "HA"
286 },
287 {
288 "BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd",
289 "Counter": "0,1,2,3",
290 "EventCode": "0x21",
291 "EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
292 "PerPkg": "1",
293 "ScaleUnit": "64Bytes",
294 "UMask": "0x4",
295 "Unit": "HA"
296 },
297 {
298 "BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps",
299 "Counter": "0,1,2,3",
300 "EventCode": "0x21",
301 "EventName": "UNC_H_SNOOP_RESP.RSPS",
302 "PerPkg": "1",
303 "ScaleUnit": "64Bytes",
304 "UMask": "0x2",
305 "Unit": "HA"
306 },
307 {
308 "BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd",
309 "Counter": "0,1,2,3",
310 "EventCode": "0x21",
311 "EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
312 "PerPkg": "1",
313 "ScaleUnit": "64Bytes",
314 "UMask": "0x8",
315 "Unit": "HA"
316 }
317]
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/uncore-memory.json b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-memory.json
new file mode 100644
index 000000000000..d17dc235f734
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-memory.json
@@ -0,0 +1,83 @@
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": "UNC_M_CAS_COUNT.RD",
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": "UNC_M_CAS_COUNT.WR",
17 "PerPkg": "1",
18 "ScaleUnit": "64Bytes",
19 "UMask": "0xC",
20 "Unit": "iMC"
21 },
22 {
23 "BriefDescription": "Memory controller clock ticks. Derived from unc_m_clockticks",
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. Derived from unc_m_power_channel_ppd",
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 "PerPkg": "1",
36 "Unit": "iMC"
37 },
38 {
39 "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
40 "Counter": "0,1,2,3",
41 "EventCode": "0x86",
42 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
43 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
44 "PerPkg": "1",
45 "Unit": "iMC"
46 },
47 {
48 "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
49 "Counter": "0,1,2,3",
50 "EventCode": "0x43",
51 "EventName": "UNC_M_POWER_SELF_REFRESH",
52 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
53 "PerPkg": "1",
54 "Unit": "iMC"
55 },
56 {
57 "BriefDescription": "Pre-charges due to page misses. Derived from unc_m_pre_count.page_miss",
58 "Counter": "0,1,2,3",
59 "EventCode": "0x2",
60 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
61 "PerPkg": "1",
62 "UMask": "0x1",
63 "Unit": "iMC"
64 },
65 {
66 "BriefDescription": "Pre-charge for reads. Derived from unc_m_pre_count.rd",
67 "Counter": "0,1,2,3",
68 "EventCode": "0x2",
69 "EventName": "UNC_M_PRE_COUNT.RD",
70 "PerPkg": "1",
71 "UMask": "0x4",
72 "Unit": "iMC"
73 },
74 {
75 "BriefDescription": "Pre-charge for writes. Derived from unc_m_pre_count.wr",
76 "Counter": "0,1,2,3",
77 "EventCode": "0x2",
78 "EventName": "UNC_M_PRE_COUNT.WR",
79 "PerPkg": "1",
80 "UMask": "0x8",
81 "Unit": "iMC"
82 }
83]
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/uncore-power.json b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-power.json
new file mode 100644
index 000000000000..b44d43088bbb
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-power.json
@@ -0,0 +1,84 @@
1[
2 {
3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
4 "Counter": "0,1,2,3",
5 "EventName": "UNC_P_CLOCKTICKS",
6 "PerPkg": "1",
7 "Unit": "PCU"
8 },
9 {
10 "BriefDescription": "C0 and C1. Derived from unc_p_power_state_occupancy.cores_c0",
11 "Counter": "0,1,2,3",
12 "EventCode": "0x80",
13 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
14 "Filter": "occ_sel=1",
15 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
16 "PerPkg": "1",
17 "Unit": "PCU"
18 },
19 {
20 "BriefDescription": "C3. Derived from unc_p_power_state_occupancy.cores_c3",
21 "Counter": "0,1,2,3",
22 "EventCode": "0x80",
23 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
24 "Filter": "occ_sel=2",
25 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
26 "PerPkg": "1",
27 "Unit": "PCU"
28 },
29 {
30 "BriefDescription": "C6 and C7. Derived from unc_p_power_state_occupancy.cores_c6",
31 "Counter": "0,1,2,3",
32 "EventCode": "0x80",
33 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
34 "Filter": "occ_sel=3",
35 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
36 "PerPkg": "1",
37 "Unit": "PCU"
38 },
39 {
40 "BriefDescription": "External Prochot. Derived from unc_p_prochot_external_cycles",
41 "Counter": "0,1,2,3",
42 "EventCode": "0xA",
43 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
44 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
45 "PerPkg": "1",
46 "Unit": "PCU"
47 },
48 {
49 "BriefDescription": "Thermal Strongest Upper Limit Cycles. Derived from unc_p_freq_max_limit_thermal_cycles",
50 "Counter": "0,1,2,3",
51 "EventCode": "0x4",
52 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
53 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
54 "PerPkg": "1",
55 "Unit": "PCU"
56 },
57 {
58 "BriefDescription": "OS Strongest Upper Limit Cycles. Derived from unc_p_freq_max_os_cycles",
59 "Counter": "0,1,2,3",
60 "EventCode": "0x6",
61 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
62 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
63 "PerPkg": "1",
64 "Unit": "PCU"
65 },
66 {
67 "BriefDescription": "Power Strongest Upper Limit Cycles. Derived from unc_p_freq_max_power_cycles",
68 "Counter": "0,1,2,3",
69 "EventCode": "0x5",
70 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
71 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
72 "PerPkg": "1",
73 "Unit": "PCU"
74 },
75 {
76 "BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles",
77 "Counter": "0,1,2,3",
78 "EventCode": "0x74",
79 "EventName": "UNC_P_FREQ_TRANS_CYCLES",
80 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
81 "PerPkg": "1",
82 "Unit": "PCU"
83 }
84]
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-cache.json b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-cache.json
new file mode 100644
index 000000000000..076459c51d4e
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-cache.json
@@ -0,0 +1,317 @@
1[
2 {
3 "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
4 "Counter": "0,1,2,3",
5 "EventName": "UNC_C_CLOCKTICKS",
6 "PerPkg": "1",
7 "Unit": "CBO"
8 },
9 {
10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
11 "Counter": "0,1,2,3",
12 "EventCode": "0x34",
13 "EventName": "UNC_C_LLC_LOOKUP.ANY",
14 "Filter": "filter_state=0x1",
15 "PerPkg": "1",
16 "ScaleUnit": "64Bytes",
17 "UMask": "0x11",
18 "Unit": "CBO"
19 },
20 {
21 "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
22 "Counter": "0,1,2,3",
23 "EventCode": "0x37",
24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
25 "PerPkg": "1",
26 "ScaleUnit": "64Bytes",
27 "UMask": "0x1",
28 "Unit": "CBO"
29 },
30 {
31 "BriefDescription": "LLC misses - demand and prefetch data reads - excludes LLC prefetches. Derived from unc_c_tor_inserts.miss_opcode",
32 "Counter": "0,1,2,3",
33 "EventCode": "0x35",
34 "EventName": "LLC_MISSES.DATA_READ",
35 "Filter": "filter_opc=0x182",
36 "PerPkg": "1",
37 "ScaleUnit": "64Bytes",
38 "UMask": "0x3",
39 "Unit": "CBO"
40 },
41 {
42 "BriefDescription": "LLC misses - Uncacheable reads (from cpu) . Derived from unc_c_tor_inserts.miss_opcode",
43 "Counter": "0,1,2,3",
44 "EventCode": "0x35",
45 "EventName": "LLC_MISSES.UNCACHEABLE",
46 "Filter": "filter_opc=0x187",
47 "PerPkg": "1",
48 "ScaleUnit": "64Bytes",
49 "UMask": "0x3",
50 "Unit": "CBO"
51 },
52 {
53 "BriefDescription": "MMIO reads. Derived from unc_c_tor_inserts.miss_opcode",
54 "Counter": "0,1,2,3",
55 "EventCode": "0x35",
56 "EventName": "LLC_MISSES.MMIO_READ",
57 "Filter": "filter_opc=0x187,filter_nc=1",
58 "PerPkg": "1",
59 "ScaleUnit": "64Bytes",
60 "UMask": "0x3",
61 "Unit": "CBO"
62 },
63 {
64 "BriefDescription": "MMIO writes. Derived from unc_c_tor_inserts.miss_opcode",
65 "Counter": "0,1,2,3",
66 "EventCode": "0x35",
67 "EventName": "LLC_MISSES.MMIO_WRITE",
68 "Filter": "filter_opc=0x18f,filter_nc=1",
69 "PerPkg": "1",
70 "ScaleUnit": "64Bytes",
71 "UMask": "0x3",
72 "Unit": "CBO"
73 },
74 {
75 "BriefDescription": "LLC prefetch misses for RFO. Derived from unc_c_tor_inserts.miss_opcode",
76 "Counter": "0,1,2,3",
77 "EventCode": "0x35",
78 "EventName": "LLC_MISSES.RFO_LLC_PREFETCH",
79 "Filter": "filter_opc=0x190",
80 "PerPkg": "1",
81 "ScaleUnit": "64Bytes",
82 "UMask": "0x3",
83 "Unit": "CBO"
84 },
85 {
86 "BriefDescription": "LLC prefetch misses for code reads. Derived from unc_c_tor_inserts.miss_opcode",
87 "Counter": "0,1,2,3",
88 "EventCode": "0x35",
89 "EventName": "LLC_MISSES.CODE_LLC_PREFETCH",
90 "Filter": "filter_opc=0x191",
91 "PerPkg": "1",
92 "ScaleUnit": "64Bytes",
93 "UMask": "0x3",
94 "Unit": "CBO"
95 },
96 {
97 "BriefDescription": "LLC prefetch misses for data reads. Derived from unc_c_tor_inserts.miss_opcode",
98 "Counter": "0,1,2,3",
99 "EventCode": "0x35",
100 "EventName": "LLC_MISSES.DATA_LLC_PREFETCH",
101 "Filter": "filter_opc=0x192",
102 "PerPkg": "1",
103 "ScaleUnit": "64Bytes",
104 "UMask": "0x3",
105 "Unit": "CBO"
106 },
107 {
108 "BriefDescription": "LLC misses for PCIe read current. Derived from unc_c_tor_inserts.miss_opcode",
109 "Counter": "0,1,2,3",
110 "EventCode": "0x35",
111 "EventName": "LLC_MISSES.PCIE_READ",
112 "Filter": "filter_opc=0x19e",
113 "PerPkg": "1",
114 "ScaleUnit": "64Bytes",
115 "UMask": "0x3",
116 "Unit": "CBO"
117 },
118 {
119 "BriefDescription": "ItoM write misses (as part of fast string memcpy stores) + PCIe full line writes. Derived from unc_c_tor_inserts.miss_opcode",
120 "Counter": "0,1,2,3",
121 "EventCode": "0x35",
122 "EventName": "LLC_MISSES.PCIE_WRITE",
123 "Filter": "filter_opc=0x1c8",
124 "PerPkg": "1",
125 "ScaleUnit": "64Bytes",
126 "UMask": "0x3",
127 "Unit": "CBO"
128 },
129 {
130 "BriefDescription": "PCIe write misses (full cache line). Derived from unc_c_tor_inserts.miss_opcode",
131 "Counter": "0,1,2,3",
132 "EventCode": "0x35",
133 "EventName": "LLC_MISSES.PCIE_NON_SNOOP_WRITE",
134 "Filter": "filter_opc=0x1c8,filter_tid=0x3e",
135 "PerPkg": "1",
136 "ScaleUnit": "64Bytes",
137 "UMask": "0x3",
138 "Unit": "CBO"
139 },
140 {
141 "BriefDescription": "PCIe writes (partial cache line). Derived from unc_c_tor_inserts.opcode",
142 "Counter": "0,1,2,3",
143 "EventCode": "0x35",
144 "EventName": "LLC_REFERENCES.PCIE_NS_PARTIAL_WRITE",
145 "Filter": "filter_opc=0x180,filter_tid=0x3e",
146 "PerPkg": "1",
147 "UMask": "0x1",
148 "Unit": "CBO"
149 },
150 {
151 "BriefDescription": "L2 demand and L2 prefetch code references to LLC. Derived from unc_c_tor_inserts.opcode",
152 "Counter": "0,1,2,3",
153 "EventCode": "0x35",
154 "EventName": "LLC_REFERENCES.CODE_LLC_PREFETCH",
155 "Filter": "filter_opc=0x181",
156 "PerPkg": "1",
157 "ScaleUnit": "64Bytes",
158 "UMask": "0x1",
159 "Unit": "CBO"
160 },
161 {
162 "BriefDescription": "Streaming stores (full cache line). Derived from unc_c_tor_inserts.opcode",
163 "Counter": "0,1,2,3",
164 "EventCode": "0x35",
165 "EventName": "LLC_REFERENCES.STREAMING_FULL",
166 "Filter": "filter_opc=0x18c",
167 "PerPkg": "1",
168 "ScaleUnit": "64Bytes",
169 "UMask": "0x1",
170 "Unit": "CBO"
171 },
172 {
173 "BriefDescription": "Streaming stores (partial cache line). Derived from unc_c_tor_inserts.opcode",
174 "Counter": "0,1,2,3",
175 "EventCode": "0x35",
176 "EventName": "LLC_REFERENCES.STREAMING_PARTIAL",
177 "Filter": "filter_opc=0x18d",
178 "PerPkg": "1",
179 "ScaleUnit": "64Bytes",
180 "UMask": "0x1",
181 "Unit": "CBO"
182 },
183 {
184 "BriefDescription": "PCIe read current. Derived from unc_c_tor_inserts.opcode",
185 "Counter": "0,1,2,3",
186 "EventCode": "0x35",
187 "EventName": "LLC_REFERENCES.PCIE_READ",
188 "Filter": "filter_opc=0x19e",
189 "PerPkg": "1",
190 "ScaleUnit": "64Bytes",
191 "UMask": "0x1",
192 "Unit": "CBO"
193 },
194 {
195 "BriefDescription": "PCIe write references (full cache line). Derived from unc_c_tor_inserts.opcode",
196 "Counter": "0,1,2,3",
197 "EventCode": "0x35",
198 "EventName": "LLC_REFERENCES.PCIE_WRITE",
199 "Filter": "filter_opc=0x1c8,filter_tid=0x3e",
200 "PerPkg": "1",
201 "ScaleUnit": "64Bytes",
202 "UMask": "0x1",
203 "Unit": "CBO"
204 },
205 {
206 "BriefDescription": "Occupancy counter for LLC data reads (demand and L2 prefetch). Derived from unc_c_tor_occupancy.miss_opcode",
207 "EventCode": "0x36",
208 "EventName": "UNC_C_TOR_OCCUPANCY.LLC_DATA_READ",
209 "Filter": "filter_opc=0x182",
210 "PerPkg": "1",
211 "UMask": "0x3",
212 "Unit": "CBO"
213 },
214 {
215 "BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads",
216 "Counter": "0,1,2,3",
217 "EventCode": "0x1",
218 "EventName": "UNC_H_REQUESTS.READS",
219 "PerPkg": "1",
220 "UMask": "0x3",
221 "Unit": "HA"
222 },
223 {
224 "BriefDescription": "read requests to local home agent. Derived from unc_h_requests.reads_local",
225 "Counter": "0,1,2,3",
226 "EventCode": "0x1",
227 "EventName": "UNC_H_REQUESTS.READS_LOCAL",
228 "PerPkg": "1",
229 "UMask": "0x1",
230 "Unit": "HA"
231 },
232 {
233 "BriefDescription": "read requests to remote home agent. Derived from unc_h_requests.reads_remote",
234 "Counter": "0,1,2,3",
235 "EventCode": "0x1",
236 "EventName": "UNC_H_REQUESTS.READS_REMOTE",
237 "PerPkg": "1",
238 "UMask": "0x2",
239 "Unit": "HA"
240 },
241 {
242 "BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes",
243 "Counter": "0,1,2,3",
244 "EventCode": "0x1",
245 "EventName": "UNC_H_REQUESTS.WRITES",
246 "PerPkg": "1",
247 "UMask": "0xC",
248 "Unit": "HA"
249 },
250 {
251 "BriefDescription": "write requests to local home agent. Derived from unc_h_requests.writes_local",
252 "Counter": "0,1,2,3",
253 "EventCode": "0x1",
254 "EventName": "UNC_H_REQUESTS.WRITES_LOCAL",
255 "PerPkg": "1",
256 "UMask": "0x4",
257 "Unit": "HA"
258 },
259 {
260 "BriefDescription": "write requests to remote home agent. Derived from unc_h_requests.writes_remote",
261 "Counter": "0,1,2,3",
262 "EventCode": "0x1",
263 "EventName": "UNC_H_REQUESTS.WRITES_REMOTE",
264 "PerPkg": "1",
265 "UMask": "0x8",
266 "Unit": "HA"
267 },
268 {
269 "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously). Derived from unc_h_snoop_resp.rspcnflct",
270 "Counter": "0,1,2,3",
271 "EventCode": "0x21",
272 "EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT",
273 "PerPkg": "1",
274 "UMask": "0x40",
275 "Unit": "HA"
276 },
277 {
278 "BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb",
279 "Counter": "0,1,2,3",
280 "EventCode": "0x21",
281 "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
282 "PerPkg": "1",
283 "ScaleUnit": "64Bytes",
284 "UMask": "0x20",
285 "Unit": "HA"
286 },
287 {
288 "BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd",
289 "Counter": "0,1,2,3",
290 "EventCode": "0x21",
291 "EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
292 "PerPkg": "1",
293 "ScaleUnit": "64Bytes",
294 "UMask": "0x4",
295 "Unit": "HA"
296 },
297 {
298 "BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps",
299 "Counter": "0,1,2,3",
300 "EventCode": "0x21",
301 "EventName": "UNC_H_SNOOP_RESP.RSPS",
302 "PerPkg": "1",
303 "ScaleUnit": "64Bytes",
304 "UMask": "0x2",
305 "Unit": "HA"
306 },
307 {
308 "BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd",
309 "Counter": "0,1,2,3",
310 "EventCode": "0x21",
311 "EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
312 "PerPkg": "1",
313 "ScaleUnit": "64Bytes",
314 "UMask": "0x8",
315 "Unit": "HA"
316 }
317]
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json
new file mode 100644
index 000000000000..39387f7909b2
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json
@@ -0,0 +1,28 @@
1[
2 {
3 "BriefDescription": "QPI clock ticks. Derived from unc_q_clockticks",
4 "Counter": "0,1,2,3",
5 "EventCode": "0x14",
6 "EventName": "UNC_Q_CLOCKTICKS",
7 "PerPkg": "1",
8 "Unit": "QPI LL"
9 },
10 {
11 "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
12 "Counter": "0,1,2,3",
13 "EventName": "UNC_Q_TxL_FLITS_G0.DATA",
14 "PerPkg": "1",
15 "ScaleUnit": "8Bytes",
16 "UMask": "0x2",
17 "Unit": "QPI LL"
18 },
19 {
20 "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
21 "Counter": "0,1,2,3",
22 "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
23 "PerPkg": "1",
24 "ScaleUnit": "8Bytes",
25 "UMask": "0x4",
26 "Unit": "QPI LL"
27 }
28]
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-memory.json b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-memory.json
new file mode 100644
index 000000000000..d17dc235f734
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-memory.json
@@ -0,0 +1,83 @@
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": "UNC_M_CAS_COUNT.RD",
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": "UNC_M_CAS_COUNT.WR",
17 "PerPkg": "1",
18 "ScaleUnit": "64Bytes",
19 "UMask": "0xC",
20 "Unit": "iMC"
21 },
22 {
23 "BriefDescription": "Memory controller clock ticks. Derived from unc_m_clockticks",
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. Derived from unc_m_power_channel_ppd",
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 "PerPkg": "1",
36 "Unit": "iMC"
37 },
38 {
39 "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
40 "Counter": "0,1,2,3",
41 "EventCode": "0x86",
42 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
43 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
44 "PerPkg": "1",
45 "Unit": "iMC"
46 },
47 {
48 "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
49 "Counter": "0,1,2,3",
50 "EventCode": "0x43",
51 "EventName": "UNC_M_POWER_SELF_REFRESH",
52 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
53 "PerPkg": "1",
54 "Unit": "iMC"
55 },
56 {
57 "BriefDescription": "Pre-charges due to page misses. Derived from unc_m_pre_count.page_miss",
58 "Counter": "0,1,2,3",
59 "EventCode": "0x2",
60 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
61 "PerPkg": "1",
62 "UMask": "0x1",
63 "Unit": "iMC"
64 },
65 {
66 "BriefDescription": "Pre-charge for reads. Derived from unc_m_pre_count.rd",
67 "Counter": "0,1,2,3",
68 "EventCode": "0x2",
69 "EventName": "UNC_M_PRE_COUNT.RD",
70 "PerPkg": "1",
71 "UMask": "0x4",
72 "Unit": "iMC"
73 },
74 {
75 "BriefDescription": "Pre-charge for writes. Derived from unc_m_pre_count.wr",
76 "Counter": "0,1,2,3",
77 "EventCode": "0x2",
78 "EventName": "UNC_M_PRE_COUNT.WR",
79 "PerPkg": "1",
80 "UMask": "0x8",
81 "Unit": "iMC"
82 }
83]
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-power.json b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-power.json
new file mode 100644
index 000000000000..b44d43088bbb
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-power.json
@@ -0,0 +1,84 @@
1[
2 {
3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
4 "Counter": "0,1,2,3",
5 "EventName": "UNC_P_CLOCKTICKS",
6 "PerPkg": "1",
7 "Unit": "PCU"
8 },
9 {
10 "BriefDescription": "C0 and C1. Derived from unc_p_power_state_occupancy.cores_c0",
11 "Counter": "0,1,2,3",
12 "EventCode": "0x80",
13 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
14 "Filter": "occ_sel=1",
15 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
16 "PerPkg": "1",
17 "Unit": "PCU"
18 },
19 {
20 "BriefDescription": "C3. Derived from unc_p_power_state_occupancy.cores_c3",
21 "Counter": "0,1,2,3",
22 "EventCode": "0x80",
23 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
24 "Filter": "occ_sel=2",
25 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
26 "PerPkg": "1",
27 "Unit": "PCU"
28 },
29 {
30 "BriefDescription": "C6 and C7. Derived from unc_p_power_state_occupancy.cores_c6",
31 "Counter": "0,1,2,3",
32 "EventCode": "0x80",
33 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
34 "Filter": "occ_sel=3",
35 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
36 "PerPkg": "1",
37 "Unit": "PCU"
38 },
39 {
40 "BriefDescription": "External Prochot. Derived from unc_p_prochot_external_cycles",
41 "Counter": "0,1,2,3",
42 "EventCode": "0xA",
43 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
44 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
45 "PerPkg": "1",
46 "Unit": "PCU"
47 },
48 {
49 "BriefDescription": "Thermal Strongest Upper Limit Cycles. Derived from unc_p_freq_max_limit_thermal_cycles",
50 "Counter": "0,1,2,3",
51 "EventCode": "0x4",
52 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
53 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
54 "PerPkg": "1",
55 "Unit": "PCU"
56 },
57 {
58 "BriefDescription": "OS Strongest Upper Limit Cycles. Derived from unc_p_freq_max_os_cycles",
59 "Counter": "0,1,2,3",
60 "EventCode": "0x6",
61 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
62 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
63 "PerPkg": "1",
64 "Unit": "PCU"
65 },
66 {
67 "BriefDescription": "Power Strongest Upper Limit Cycles. Derived from unc_p_freq_max_power_cycles",
68 "Counter": "0,1,2,3",
69 "EventCode": "0x5",
70 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
71 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
72 "PerPkg": "1",
73 "Unit": "PCU"
74 },
75 {
76 "BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles",
77 "Counter": "0,1,2,3",
78 "EventCode": "0x74",
79 "EventName": "UNC_P_FREQ_TRANS_CYCLES",
80 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
81 "PerPkg": "1",
82 "Unit": "PCU"
83 }
84]
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/uncore-cache.json b/tools/perf/pmu-events/arch/x86/haswellx/uncore-cache.json
new file mode 100644
index 000000000000..076459c51d4e
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswellx/uncore-cache.json
@@ -0,0 +1,317 @@
1[
2 {
3 "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
4 "Counter": "0,1,2,3",
5 "EventName": "UNC_C_CLOCKTICKS",
6 "PerPkg": "1",
7 "Unit": "CBO"
8 },
9 {
10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
11 "Counter": "0,1,2,3",
12 "EventCode": "0x34",
13 "EventName": "UNC_C_LLC_LOOKUP.ANY",
14 "Filter": "filter_state=0x1",
15 "PerPkg": "1",
16 "ScaleUnit": "64Bytes",
17 "UMask": "0x11",
18 "Unit": "CBO"
19 },
20 {
21 "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
22 "Counter": "0,1,2,3",
23 "EventCode": "0x37",
24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
25 "PerPkg": "1",
26 "ScaleUnit": "64Bytes",
27 "UMask": "0x1",
28 "Unit": "CBO"
29 },
30 {
31 "BriefDescription": "LLC misses - demand and prefetch data reads - excludes LLC prefetches. Derived from unc_c_tor_inserts.miss_opcode",
32 "Counter": "0,1,2,3",
33 "EventCode": "0x35",
34 "EventName": "LLC_MISSES.DATA_READ",
35 "Filter": "filter_opc=0x182",
36 "PerPkg": "1",
37 "ScaleUnit": "64Bytes",
38 "UMask": "0x3",
39 "Unit": "CBO"
40 },
41 {
42 "BriefDescription": "LLC misses - Uncacheable reads (from cpu) . Derived from unc_c_tor_inserts.miss_opcode",
43 "Counter": "0,1,2,3",
44 "EventCode": "0x35",
45 "EventName": "LLC_MISSES.UNCACHEABLE",
46 "Filter": "filter_opc=0x187",
47 "PerPkg": "1",
48 "ScaleUnit": "64Bytes",
49 "UMask": "0x3",
50 "Unit": "CBO"
51 },
52 {
53 "BriefDescription": "MMIO reads. Derived from unc_c_tor_inserts.miss_opcode",
54 "Counter": "0,1,2,3",
55 "EventCode": "0x35",
56 "EventName": "LLC_MISSES.MMIO_READ",
57 "Filter": "filter_opc=0x187,filter_nc=1",
58 "PerPkg": "1",
59 "ScaleUnit": "64Bytes",
60 "UMask": "0x3",
61 "Unit": "CBO"
62 },
63 {
64 "BriefDescription": "MMIO writes. Derived from unc_c_tor_inserts.miss_opcode",
65 "Counter": "0,1,2,3",
66 "EventCode": "0x35",
67 "EventName": "LLC_MISSES.MMIO_WRITE",
68 "Filter": "filter_opc=0x18f,filter_nc=1",
69 "PerPkg": "1",
70 "ScaleUnit": "64Bytes",
71 "UMask": "0x3",
72 "Unit": "CBO"
73 },
74 {
75 "BriefDescription": "LLC prefetch misses for RFO. Derived from unc_c_tor_inserts.miss_opcode",
76 "Counter": "0,1,2,3",
77 "EventCode": "0x35",
78 "EventName": "LLC_MISSES.RFO_LLC_PREFETCH",
79 "Filter": "filter_opc=0x190",
80 "PerPkg": "1",
81 "ScaleUnit": "64Bytes",
82 "UMask": "0x3",
83 "Unit": "CBO"
84 },
85 {
86 "BriefDescription": "LLC prefetch misses for code reads. Derived from unc_c_tor_inserts.miss_opcode",
87 "Counter": "0,1,2,3",
88 "EventCode": "0x35",
89 "EventName": "LLC_MISSES.CODE_LLC_PREFETCH",
90 "Filter": "filter_opc=0x191",
91 "PerPkg": "1",
92 "ScaleUnit": "64Bytes",
93 "UMask": "0x3",
94 "Unit": "CBO"
95 },
96 {
97 "BriefDescription": "LLC prefetch misses for data reads. Derived from unc_c_tor_inserts.miss_opcode",
98 "Counter": "0,1,2,3",
99 "EventCode": "0x35",
100 "EventName": "LLC_MISSES.DATA_LLC_PREFETCH",
101 "Filter": "filter_opc=0x192",
102 "PerPkg": "1",
103 "ScaleUnit": "64Bytes",
104 "UMask": "0x3",
105 "Unit": "CBO"
106 },
107 {
108 "BriefDescription": "LLC misses for PCIe read current. Derived from unc_c_tor_inserts.miss_opcode",
109 "Counter": "0,1,2,3",
110 "EventCode": "0x35",
111 "EventName": "LLC_MISSES.PCIE_READ",
112 "Filter": "filter_opc=0x19e",
113 "PerPkg": "1",
114 "ScaleUnit": "64Bytes",
115 "UMask": "0x3",
116 "Unit": "CBO"
117 },
118 {
119 "BriefDescription": "ItoM write misses (as part of fast string memcpy stores) + PCIe full line writes. Derived from unc_c_tor_inserts.miss_opcode",
120 "Counter": "0,1,2,3",
121 "EventCode": "0x35",
122 "EventName": "LLC_MISSES.PCIE_WRITE",
123 "Filter": "filter_opc=0x1c8",
124 "PerPkg": "1",
125 "ScaleUnit": "64Bytes",
126 "UMask": "0x3",
127 "Unit": "CBO"
128 },
129 {
130 "BriefDescription": "PCIe write misses (full cache line). Derived from unc_c_tor_inserts.miss_opcode",
131 "Counter": "0,1,2,3",
132 "EventCode": "0x35",
133 "EventName": "LLC_MISSES.PCIE_NON_SNOOP_WRITE",
134 "Filter": "filter_opc=0x1c8,filter_tid=0x3e",
135 "PerPkg": "1",
136 "ScaleUnit": "64Bytes",
137 "UMask": "0x3",
138 "Unit": "CBO"
139 },
140 {
141 "BriefDescription": "PCIe writes (partial cache line). Derived from unc_c_tor_inserts.opcode",
142 "Counter": "0,1,2,3",
143 "EventCode": "0x35",
144 "EventName": "LLC_REFERENCES.PCIE_NS_PARTIAL_WRITE",
145 "Filter": "filter_opc=0x180,filter_tid=0x3e",
146 "PerPkg": "1",
147 "UMask": "0x1",
148 "Unit": "CBO"
149 },
150 {
151 "BriefDescription": "L2 demand and L2 prefetch code references to LLC. Derived from unc_c_tor_inserts.opcode",
152 "Counter": "0,1,2,3",
153 "EventCode": "0x35",
154 "EventName": "LLC_REFERENCES.CODE_LLC_PREFETCH",
155 "Filter": "filter_opc=0x181",
156 "PerPkg": "1",
157 "ScaleUnit": "64Bytes",
158 "UMask": "0x1",
159 "Unit": "CBO"
160 },
161 {
162 "BriefDescription": "Streaming stores (full cache line). Derived from unc_c_tor_inserts.opcode",
163 "Counter": "0,1,2,3",
164 "EventCode": "0x35",
165 "EventName": "LLC_REFERENCES.STREAMING_FULL",
166 "Filter": "filter_opc=0x18c",
167 "PerPkg": "1",
168 "ScaleUnit": "64Bytes",
169 "UMask": "0x1",
170 "Unit": "CBO"
171 },
172 {
173 "BriefDescription": "Streaming stores (partial cache line). Derived from unc_c_tor_inserts.opcode",
174 "Counter": "0,1,2,3",
175 "EventCode": "0x35",
176 "EventName": "LLC_REFERENCES.STREAMING_PARTIAL",
177 "Filter": "filter_opc=0x18d",
178 "PerPkg": "1",
179 "ScaleUnit": "64Bytes",
180 "UMask": "0x1",
181 "Unit": "CBO"
182 },
183 {
184 "BriefDescription": "PCIe read current. Derived from unc_c_tor_inserts.opcode",
185 "Counter": "0,1,2,3",
186 "EventCode": "0x35",
187 "EventName": "LLC_REFERENCES.PCIE_READ",
188 "Filter": "filter_opc=0x19e",
189 "PerPkg": "1",
190 "ScaleUnit": "64Bytes",
191 "UMask": "0x1",
192 "Unit": "CBO"
193 },
194 {
195 "BriefDescription": "PCIe write references (full cache line). Derived from unc_c_tor_inserts.opcode",
196 "Counter": "0,1,2,3",
197 "EventCode": "0x35",
198 "EventName": "LLC_REFERENCES.PCIE_WRITE",
199 "Filter": "filter_opc=0x1c8,filter_tid=0x3e",
200 "PerPkg": "1",
201 "ScaleUnit": "64Bytes",
202 "UMask": "0x1",
203 "Unit": "CBO"
204 },
205 {
206 "BriefDescription": "Occupancy counter for LLC data reads (demand and L2 prefetch). Derived from unc_c_tor_occupancy.miss_opcode",
207 "EventCode": "0x36",
208 "EventName": "UNC_C_TOR_OCCUPANCY.LLC_DATA_READ",
209 "Filter": "filter_opc=0x182",
210 "PerPkg": "1",
211 "UMask": "0x3",
212 "Unit": "CBO"
213 },
214 {
215 "BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads",
216 "Counter": "0,1,2,3",
217 "EventCode": "0x1",
218 "EventName": "UNC_H_REQUESTS.READS",
219 "PerPkg": "1",
220 "UMask": "0x3",
221 "Unit": "HA"
222 },
223 {
224 "BriefDescription": "read requests to local home agent. Derived from unc_h_requests.reads_local",
225 "Counter": "0,1,2,3",
226 "EventCode": "0x1",
227 "EventName": "UNC_H_REQUESTS.READS_LOCAL",
228 "PerPkg": "1",
229 "UMask": "0x1",
230 "Unit": "HA"
231 },
232 {
233 "BriefDescription": "read requests to remote home agent. Derived from unc_h_requests.reads_remote",
234 "Counter": "0,1,2,3",
235 "EventCode": "0x1",
236 "EventName": "UNC_H_REQUESTS.READS_REMOTE",
237 "PerPkg": "1",
238 "UMask": "0x2",
239 "Unit": "HA"
240 },
241 {
242 "BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes",
243 "Counter": "0,1,2,3",
244 "EventCode": "0x1",
245 "EventName": "UNC_H_REQUESTS.WRITES",
246 "PerPkg": "1",
247 "UMask": "0xC",
248 "Unit": "HA"
249 },
250 {
251 "BriefDescription": "write requests to local home agent. Derived from unc_h_requests.writes_local",
252 "Counter": "0,1,2,3",
253 "EventCode": "0x1",
254 "EventName": "UNC_H_REQUESTS.WRITES_LOCAL",
255 "PerPkg": "1",
256 "UMask": "0x4",
257 "Unit": "HA"
258 },
259 {
260 "BriefDescription": "write requests to remote home agent. Derived from unc_h_requests.writes_remote",
261 "Counter": "0,1,2,3",
262 "EventCode": "0x1",
263 "EventName": "UNC_H_REQUESTS.WRITES_REMOTE",
264 "PerPkg": "1",
265 "UMask": "0x8",
266 "Unit": "HA"
267 },
268 {
269 "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously). Derived from unc_h_snoop_resp.rspcnflct",
270 "Counter": "0,1,2,3",
271 "EventCode": "0x21",
272 "EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT",
273 "PerPkg": "1",
274 "UMask": "0x40",
275 "Unit": "HA"
276 },
277 {
278 "BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb",
279 "Counter": "0,1,2,3",
280 "EventCode": "0x21",
281 "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
282 "PerPkg": "1",
283 "ScaleUnit": "64Bytes",
284 "UMask": "0x20",
285 "Unit": "HA"
286 },
287 {
288 "BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd",
289 "Counter": "0,1,2,3",
290 "EventCode": "0x21",
291 "EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
292 "PerPkg": "1",
293 "ScaleUnit": "64Bytes",
294 "UMask": "0x4",
295 "Unit": "HA"
296 },
297 {
298 "BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps",
299 "Counter": "0,1,2,3",
300 "EventCode": "0x21",
301 "EventName": "UNC_H_SNOOP_RESP.RSPS",
302 "PerPkg": "1",
303 "ScaleUnit": "64Bytes",
304 "UMask": "0x2",
305 "Unit": "HA"
306 },
307 {
308 "BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd",
309 "Counter": "0,1,2,3",
310 "EventCode": "0x21",
311 "EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
312 "PerPkg": "1",
313 "ScaleUnit": "64Bytes",
314 "UMask": "0x8",
315 "Unit": "HA"
316 }
317]
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json
new file mode 100644
index 000000000000..39387f7909b2
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json
@@ -0,0 +1,28 @@
1[
2 {
3 "BriefDescription": "QPI clock ticks. Derived from unc_q_clockticks",
4 "Counter": "0,1,2,3",
5 "EventCode": "0x14",
6 "EventName": "UNC_Q_CLOCKTICKS",
7 "PerPkg": "1",
8 "Unit": "QPI LL"
9 },
10 {
11 "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
12 "Counter": "0,1,2,3",
13 "EventName": "UNC_Q_TxL_FLITS_G0.DATA",
14 "PerPkg": "1",
15 "ScaleUnit": "8Bytes",
16 "UMask": "0x2",
17 "Unit": "QPI LL"
18 },
19 {
20 "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
21 "Counter": "0,1,2,3",
22 "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
23 "PerPkg": "1",
24 "ScaleUnit": "8Bytes",
25 "UMask": "0x4",
26 "Unit": "QPI LL"
27 }
28]
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/uncore-memory.json b/tools/perf/pmu-events/arch/x86/haswellx/uncore-memory.json
new file mode 100644
index 000000000000..d17dc235f734
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswellx/uncore-memory.json
@@ -0,0 +1,83 @@
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": "UNC_M_CAS_COUNT.RD",
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": "UNC_M_CAS_COUNT.WR",
17 "PerPkg": "1",
18 "ScaleUnit": "64Bytes",
19 "UMask": "0xC",
20 "Unit": "iMC"
21 },
22 {
23 "BriefDescription": "Memory controller clock ticks. Derived from unc_m_clockticks",
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. Derived from unc_m_power_channel_ppd",
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 "PerPkg": "1",
36 "Unit": "iMC"
37 },
38 {
39 "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
40 "Counter": "0,1,2,3",
41 "EventCode": "0x86",
42 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
43 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
44 "PerPkg": "1",
45 "Unit": "iMC"
46 },
47 {
48 "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
49 "Counter": "0,1,2,3",
50 "EventCode": "0x43",
51 "EventName": "UNC_M_POWER_SELF_REFRESH",
52 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
53 "PerPkg": "1",
54 "Unit": "iMC"
55 },
56 {
57 "BriefDescription": "Pre-charges due to page misses. Derived from unc_m_pre_count.page_miss",
58 "Counter": "0,1,2,3",
59 "EventCode": "0x2",
60 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
61 "PerPkg": "1",
62 "UMask": "0x1",
63 "Unit": "iMC"
64 },
65 {
66 "BriefDescription": "Pre-charge for reads. Derived from unc_m_pre_count.rd",
67 "Counter": "0,1,2,3",
68 "EventCode": "0x2",
69 "EventName": "UNC_M_PRE_COUNT.RD",
70 "PerPkg": "1",
71 "UMask": "0x4",
72 "Unit": "iMC"
73 },
74 {
75 "BriefDescription": "Pre-charge for writes. Derived from unc_m_pre_count.wr",
76 "Counter": "0,1,2,3",
77 "EventCode": "0x2",
78 "EventName": "UNC_M_PRE_COUNT.WR",
79 "PerPkg": "1",
80 "UMask": "0x8",
81 "Unit": "iMC"
82 }
83]
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/uncore-power.json b/tools/perf/pmu-events/arch/x86/haswellx/uncore-power.json
new file mode 100644
index 000000000000..b44d43088bbb
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswellx/uncore-power.json
@@ -0,0 +1,84 @@
1[
2 {
3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
4 "Counter": "0,1,2,3",
5 "EventName": "UNC_P_CLOCKTICKS",
6 "PerPkg": "1",
7 "Unit": "PCU"
8 },
9 {
10 "BriefDescription": "C0 and C1. Derived from unc_p_power_state_occupancy.cores_c0",
11 "Counter": "0,1,2,3",
12 "EventCode": "0x80",
13 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
14 "Filter": "occ_sel=1",
15 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
16 "PerPkg": "1",
17 "Unit": "PCU"
18 },
19 {
20 "BriefDescription": "C3. Derived from unc_p_power_state_occupancy.cores_c3",
21 "Counter": "0,1,2,3",
22 "EventCode": "0x80",
23 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
24 "Filter": "occ_sel=2",
25 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
26 "PerPkg": "1",
27 "Unit": "PCU"
28 },
29 {
30 "BriefDescription": "C6 and C7. Derived from unc_p_power_state_occupancy.cores_c6",
31 "Counter": "0,1,2,3",
32 "EventCode": "0x80",
33 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
34 "Filter": "occ_sel=3",
35 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
36 "PerPkg": "1",
37 "Unit": "PCU"
38 },
39 {
40 "BriefDescription": "External Prochot. Derived from unc_p_prochot_external_cycles",
41 "Counter": "0,1,2,3",
42 "EventCode": "0xA",
43 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
44 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
45 "PerPkg": "1",
46 "Unit": "PCU"
47 },
48 {
49 "BriefDescription": "Thermal Strongest Upper Limit Cycles. Derived from unc_p_freq_max_limit_thermal_cycles",
50 "Counter": "0,1,2,3",
51 "EventCode": "0x4",
52 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
53 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
54 "PerPkg": "1",
55 "Unit": "PCU"
56 },
57 {
58 "BriefDescription": "OS Strongest Upper Limit Cycles. Derived from unc_p_freq_max_os_cycles",
59 "Counter": "0,1,2,3",
60 "EventCode": "0x6",
61 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
62 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
63 "PerPkg": "1",
64 "Unit": "PCU"
65 },
66 {
67 "BriefDescription": "Power Strongest Upper Limit Cycles. Derived from unc_p_freq_max_power_cycles",
68 "Counter": "0,1,2,3",
69 "EventCode": "0x5",
70 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
71 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
72 "PerPkg": "1",
73 "Unit": "PCU"
74 },
75 {
76 "BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles",
77 "Counter": "0,1,2,3",
78 "EventCode": "0x74",
79 "EventName": "UNC_P_FREQ_TRANS_CYCLES",
80 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
81 "PerPkg": "1",
82 "Unit": "PCU"
83 }
84]
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/uncore-cache.json b/tools/perf/pmu-events/arch/x86/ivytown/uncore-cache.json
new file mode 100644
index 000000000000..2efdc6772e0b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivytown/uncore-cache.json
@@ -0,0 +1,322 @@
1[
2 {
3 "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
4 "Counter": "0,1,2,3",
5 "EventName": "UNC_C_CLOCKTICKS",
6 "PerPkg": "1",
7 "Unit": "CBO"
8 },
9 {
10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
11 "Counter": "0,1",
12 "EventCode": "0x34",
13 "EventName": "UNC_C_LLC_LOOKUP.ANY",
14 "Filter": "filter_state=0x1",
15 "PerPkg": "1",
16 "ScaleUnit": "64Bytes",
17 "UMask": "0x11",
18 "Unit": "CBO"
19 },
20 {
21 "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
22 "Counter": "0,1",
23 "EventCode": "0x37",
24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
25 "PerPkg": "1",
26 "ScaleUnit": "64Bytes",
27 "UMask": "0x1",
28 "Unit": "CBO"
29 },
30 {
31 "BriefDescription": "LLC misses - demand and prefetch data reads - excludes LLC prefetches. Derived from unc_c_tor_inserts.miss_opcode.demand",
32 "Counter": "0,1",
33 "EventCode": "0x35",
34 "EventName": "LLC_MISSES.DATA_READ",
35 "Filter": "filter_opc=0x182",
36 "PerPkg": "1",
37 "ScaleUnit": "64Bytes",
38 "UMask": "0x3",
39 "Unit": "CBO"
40 },
41 {
42 "BriefDescription": "LLC misses - Uncacheable reads. Derived from unc_c_tor_inserts.miss_opcode.uncacheable",
43 "Counter": "0,1",
44 "EventCode": "0x35",
45 "EventName": "LLC_MISSES.UNCACHEABLE",
46 "Filter": "filter_opc=0x187",
47 "PerPkg": "1",
48 "ScaleUnit": "64Bytes",
49 "UMask": "0x3",
50 "Unit": "CBO"
51 },
52 {
53 "BriefDescription": "LLC prefetch misses for RFO. Derived from unc_c_tor_inserts.miss_opcode.rfo_prefetch",
54 "Counter": "0,1",
55 "EventCode": "0x35",
56 "EventName": "LLC_MISSES.RFO_LLC_PREFETCH",
57 "Filter": "filter_opc=0x190",
58 "PerPkg": "1",
59 "ScaleUnit": "64Bytes",
60 "UMask": "0x3",
61 "Unit": "CBO"
62 },
63 {
64 "BriefDescription": "LLC prefetch misses for code reads. Derived from unc_c_tor_inserts.miss_opcode.code",
65 "Counter": "0,1",
66 "EventCode": "0x35",
67 "EventName": "LLC_MISSES.CODE_LLC_PREFETCH",
68 "Filter": "filter_opc=0x191",
69 "PerPkg": "1",
70 "ScaleUnit": "64Bytes",
71 "UMask": "0x3",
72 "Unit": "CBO"
73 },
74 {
75 "BriefDescription": "LLC prefetch misses for data reads. Derived from unc_c_tor_inserts.miss_opcode.data_read",
76 "Counter": "0,1",
77 "EventCode": "0x35",
78 "EventName": "LLC_MISSES.DATA_LLC_PREFETCH",
79 "Filter": "filter_opc=0x192",
80 "PerPkg": "1",
81 "ScaleUnit": "64Bytes",
82 "UMask": "0x3",
83 "Unit": "CBO"
84 },
85 {
86 "BriefDescription": "PCIe allocating writes that miss LLC - DDIO misses. Derived from unc_c_tor_inserts.miss_opcode.ddio_miss",
87 "Counter": "0,1",
88 "EventCode": "0x35",
89 "EventName": "LLC_MISSES.PCIE_WRITE",
90 "Filter": "filter_opc=0x19c",
91 "PerPkg": "1",
92 "ScaleUnit": "64Bytes",
93 "UMask": "0x3",
94 "Unit": "CBO"
95 },
96 {
97 "BriefDescription": "LLC misses for PCIe read current. Derived from unc_c_tor_inserts.miss_opcode.pcie_read",
98 "Counter": "0,1",
99 "EventCode": "0x35",
100 "EventName": "LLC_MISSES.PCIE_READ",
101 "Filter": "filter_opc=0x19e",
102 "PerPkg": "1",
103 "ScaleUnit": "64Bytes",
104 "UMask": "0x3",
105 "Unit": "CBO"
106 },
107 {
108 "BriefDescription": "LLC misses for ItoM writes (as part of fast string memcpy stores). Derived from unc_c_tor_inserts.miss_opcode.itom_write",
109 "Counter": "0,1",
110 "EventCode": "0x35",
111 "EventName": "LLC_MISSES.ITOM_WRITE",
112 "Filter": "filter_opc=0x1c8",
113 "PerPkg": "1",
114 "ScaleUnit": "64Bytes",
115 "UMask": "0x3",
116 "Unit": "CBO"
117 },
118 {
119 "BriefDescription": "LLC misses for PCIe non-snoop reads. Derived from unc_c_tor_inserts.miss_opcode.pcie_read",
120 "Counter": "0,1",
121 "EventCode": "0x35",
122 "EventName": "LLC_MISSES.PCIE_NON_SNOOP_READ",
123 "Filter": "filter_opc=0x1e4",
124 "PerPkg": "1",
125 "ScaleUnit": "64Bytes",
126 "UMask": "0x3",
127 "Unit": "CBO"
128 },
129 {
130 "BriefDescription": "LLC misses for PCIe non-snoop writes (full line). Derived from unc_c_tor_inserts.miss_opcode.pcie_write",
131 "Counter": "0,1",
132 "EventCode": "0x35",
133 "EventName": "LLC_MISSES.PCIE_NON_SNOOP_WRITE",
134 "Filter": "filter_opc=0x1e6",
135 "PerPkg": "1",
136 "ScaleUnit": "64Bytes",
137 "UMask": "0x3",
138 "Unit": "CBO"
139 },
140 {
141 "BriefDescription": "Streaming stores (full cache line). Derived from unc_c_tor_inserts.opcode.streaming_full",
142 "Counter": "0,1",
143 "EventCode": "0x35",
144 "EventName": "LLC_REFERENCES.STREAMING_FULL",
145 "Filter": "filter_opc=0x18c",
146 "PerPkg": "1",
147 "ScaleUnit": "64Bytes",
148 "UMask": "0x1",
149 "Unit": "CBO"
150 },
151 {
152 "BriefDescription": "Streaming stores (partial cache line). Derived from unc_c_tor_inserts.opcode.streaming_partial",
153 "Counter": "0,1",
154 "EventCode": "0x35",
155 "EventName": "LLC_REFERENCES.STREAMING_PARTIAL",
156 "Filter": "filter_opc=0x18d",
157 "PerPkg": "1",
158 "ScaleUnit": "64Bytes",
159 "UMask": "0x1",
160 "Unit": "CBO"
161 },
162 {
163 "BriefDescription": "Partial PCIe reads. Derived from unc_c_tor_inserts.opcode.pcie_partial",
164 "Counter": "0,1",
165 "EventCode": "0x35",
166 "EventName": "LLC_REFERENCES.PCIE_PARTIAL_READ",
167 "Filter": "filter_opc=0x195",
168 "PerPkg": "1",
169 "ScaleUnit": "64Bytes",
170 "UMask": "0x1",
171 "Unit": "CBO"
172 },
173 {
174 "BriefDescription": "PCIe allocating writes that hit in LLC (DDIO hits). Derived from unc_c_tor_inserts.opcode.ddio_hit",
175 "Counter": "0,1",
176 "EventCode": "0x35",
177 "EventName": "LLC_REFERENCES.PCIE_WRITE",
178 "Filter": "filter_opc=0x19c",
179 "PerPkg": "1",
180 "ScaleUnit": "64Bytes",
181 "UMask": "0x1",
182 "Unit": "CBO"
183 },
184 {
185 "BriefDescription": "PCIe read current. Derived from unc_c_tor_inserts.opcode.pcie_read_current",
186 "Counter": "0,1",
187 "EventCode": "0x35",
188 "EventName": "LLC_REFERENCES.PCIE_READ",
189 "Filter": "filter_opc=0x19e",
190 "PerPkg": "1",
191 "ScaleUnit": "64Bytes",
192 "UMask": "0x1",
193 "Unit": "CBO"
194 },
195 {
196 "BriefDescription": "ItoM write hits (as part of fast string memcpy stores). Derived from unc_c_tor_inserts.opcode.itom_write_hit",
197 "Counter": "0,1",
198 "EventCode": "0x35",
199 "EventName": "LLC_REFERENCES.ITOM_WRITE",
200 "Filter": "filter_opc=0x1c8",
201 "PerPkg": "1",
202 "ScaleUnit": "64Bytes",
203 "UMask": "0x1",
204 "Unit": "CBO"
205 },
206 {
207 "BriefDescription": "PCIe non-snoop reads. Derived from unc_c_tor_inserts.opcode.pcie_read",
208 "Counter": "0,1",
209 "EventCode": "0x35",
210 "EventName": "LLC_REFERENCES.PCIE_NS_READ",
211 "Filter": "filter_opc=0x1e4",
212 "PerPkg": "1",
213 "ScaleUnit": "64Bytes",
214 "UMask": "0x1",
215 "Unit": "CBO"
216 },
217 {
218 "BriefDescription": "PCIe non-snoop writes (partial). Derived from unc_c_tor_inserts.opcode.pcie_partial_write",
219 "Counter": "0,1",
220 "EventCode": "0x35",
221 "EventName": "LLC_REFERENCES.PCIE_NS_PARTIAL_WRITE",
222 "Filter": "filter_opc=0x1e5",
223 "PerPkg": "1",
224 "ScaleUnit": "64Bytes",
225 "UMask": "0x1",
226 "Unit": "CBO"
227 },
228 {
229 "BriefDescription": "PCIe non-snoop writes (full line). Derived from unc_c_tor_inserts.opcode.pcie_full_write",
230 "Counter": "0,1",
231 "EventCode": "0x35",
232 "EventName": "LLC_REFERENCES.PCIE_NS_WRITE",
233 "Filter": "filter_opc=0x1e6",
234 "PerPkg": "1",
235 "ScaleUnit": "64Bytes",
236 "UMask": "0x1",
237 "Unit": "CBO"
238 },
239 {
240 "BriefDescription": "Occupancy for all LLC misses that are addressed to local memory. Derived from unc_c_tor_occupancy.miss_local",
241 "EventCode": "0x36",
242 "EventName": "UNC_C_TOR_OCCUPANCY.MISS_LOCAL",
243 "PerPkg": "1",
244 "UMask": "0x2A",
245 "Unit": "CBO"
246 },
247 {
248 "BriefDescription": "Occupancy counter for LLC data reads (demand and L2 prefetch). Derived from unc_c_tor_occupancy.miss_opcode.llc_data_read",
249 "EventCode": "0x36",
250 "EventName": "UNC_C_TOR_OCCUPANCY.LLC_DATA_READ",
251 "Filter": "filter_opc=0x182",
252 "PerPkg": "1",
253 "UMask": "0x3",
254 "Unit": "CBO"
255 },
256 {
257 "BriefDescription": "Occupancy for all LLC misses that are addressed to remote memory. Derived from unc_c_tor_occupancy.miss_remote",
258 "EventCode": "0x36",
259 "EventName": "UNC_C_TOR_OCCUPANCY.MISS_REMOTE",
260 "PerPkg": "1",
261 "UMask": "0x8A",
262 "Unit": "CBO"
263 },
264 {
265 "BriefDescription": "Read requests to home agent. Derived from unc_h_requests.reads",
266 "Counter": "0,1,2,3",
267 "EventCode": "0x1",
268 "EventName": "UNC_H_REQUESTS.READS",
269 "PerPkg": "1",
270 "UMask": "0x3",
271 "Unit": "HA"
272 },
273 {
274 "BriefDescription": "Write requests to home agent. Derived from unc_h_requests.writes",
275 "Counter": "0,1,2,3",
276 "EventCode": "0x1",
277 "EventName": "UNC_H_REQUESTS.WRITES",
278 "PerPkg": "1",
279 "UMask": "0xC",
280 "Unit": "HA"
281 },
282 {
283 "BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb",
284 "Counter": "0,1,2,3",
285 "EventCode": "0x21",
286 "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
287 "PerPkg": "1",
288 "ScaleUnit": "64Bytes",
289 "UMask": "0x20",
290 "Unit": "HA"
291 },
292 {
293 "BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd",
294 "Counter": "0,1,2,3",
295 "EventCode": "0x21",
296 "EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
297 "PerPkg": "1",
298 "ScaleUnit": "64Bytes",
299 "UMask": "0x4",
300 "Unit": "HA"
301 },
302 {
303 "BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps",
304 "Counter": "0,1,2,3",
305 "EventCode": "0x21",
306 "EventName": "UNC_H_SNOOP_RESP.RSPS",
307 "PerPkg": "1",
308 "ScaleUnit": "64Bytes",
309 "UMask": "0x2",
310 "Unit": "HA"
311 },
312 {
313 "BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd",
314 "Counter": "0,1,2,3",
315 "EventCode": "0x21",
316 "EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
317 "PerPkg": "1",
318 "ScaleUnit": "64Bytes",
319 "UMask": "0x8",
320 "Unit": "HA"
321 }
322]
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json
new file mode 100644
index 000000000000..d7e2fda1d695
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json
@@ -0,0 +1,46 @@
1[
2 {
3 "BriefDescription": "QPI clock ticks. Use to get percentages for QPI cycles events. Derived from unc_q_clockticks",
4 "Counter": "0,1,2,3",
5 "EventCode": "0x14",
6 "EventName": "UNC_Q_CLOCKTICKS",
7 "PerPkg": "1",
8 "Unit": "QPI LL"
9 },
10 {
11 "BriefDescription": "Cycles where receiving QPI link is in half-width mode. Derived from unc_q_rxl0p_power_cycles",
12 "Counter": "0,1,2,3",
13 "EventCode": "0x10",
14 "EventName": "UNC_Q_RxL0P_POWER_CYCLES",
15 "MetricExpr": "(UNC_Q_RxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
16 "PerPkg": "1",
17 "Unit": "QPI LL"
18 },
19 {
20 "BriefDescription": "Cycles where transmitting QPI link is in half-width mode. Derived from unc_q_txl0p_power_cycles",
21 "Counter": "0,1,2,3",
22 "EventCode": "0xd",
23 "EventName": "UNC_Q_TxL0P_POWER_CYCLES",
24 "MetricExpr": "(UNC_Q_TxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
25 "PerPkg": "1",
26 "Unit": "QPI LL"
27 },
28 {
29 "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
30 "Counter": "0,1,2,3",
31 "EventName": "UNC_Q_TxL_FLITS_G0.DATA",
32 "PerPkg": "1",
33 "ScaleUnit": "8Bytes",
34 "UMask": "0x2",
35 "Unit": "QPI LL"
36 },
37 {
38 "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
39 "Counter": "0,1,2,3",
40 "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
41 "PerPkg": "1",
42 "ScaleUnit": "8Bytes",
43 "UMask": "0x4",
44 "Unit": "QPI LL"
45 }
46]
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/uncore-memory.json b/tools/perf/pmu-events/arch/x86/ivytown/uncore-memory.json
new file mode 100644
index 000000000000..ac4ad4d6357b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivytown/uncore-memory.json
@@ -0,0 +1,75 @@
1[
2 {
3 "BriefDescription": "Memory page activates for reads and writes. Derived from unc_m_act_count.rd",
4 "Counter": "0,1,2,3",
5 "EventCode": "0x1",
6 "EventName": "UNC_M_ACT_COUNT.RD",
7 "PerPkg": "1",
8 "UMask": "0x1",
9 "Umask": "0x3",
10 "Unit": "iMC"
11 },
12 {
13 "BriefDescription": "Read requests to memory controller. Derived from unc_m_cas_count.rd",
14 "Counter": "0,1,2,3",
15 "EventCode": "0x4",
16 "EventName": "UNC_M_CAS_COUNT.RD",
17 "PerPkg": "1",
18 "ScaleUnit": "64Bytes",
19 "UMask": "0x3",
20 "Unit": "iMC"
21 },
22 {
23 "BriefDescription": "Write requests to memory controller. Derived from unc_m_cas_count.wr",
24 "Counter": "0,1,2,3",
25 "EventCode": "0x4",
26 "EventName": "UNC_M_CAS_COUNT.WR",
27 "PerPkg": "1",
28 "ScaleUnit": "64Bytes",
29 "UMask": "0xC",
30 "Unit": "iMC"
31 },
32 {
33 "BriefDescription": "Memory controller clock ticks. Use to generate percentages for memory controller CYCLES events. Derived from unc_m_clockticks",
34 "Counter": "0,1,2,3",
35 "EventName": "UNC_M_CLOCKTICKS",
36 "PerPkg": "1",
37 "Unit": "iMC"
38 },
39 {
40 "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd",
41 "Counter": "0,1,2,3",
42 "EventCode": "0x85",
43 "EventName": "UNC_M_POWER_CHANNEL_PPD",
44 "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
45 "PerPkg": "1",
46 "Unit": "iMC"
47 },
48 {
49 "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
50 "Counter": "0,1,2,3",
51 "EventCode": "0x86",
52 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
53 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
54 "PerPkg": "1",
55 "Unit": "iMC"
56 },
57 {
58 "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
59 "Counter": "0,1,2,3",
60 "EventCode": "0x43",
61 "EventName": "UNC_M_POWER_SELF_REFRESH",
62 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
63 "PerPkg": "1",
64 "Unit": "iMC"
65 },
66 {
67 "BriefDescription": "Memory page conflicts. Derived from unc_m_pre_count.page_miss",
68 "Counter": "0,1,2,3",
69 "EventCode": "0x2",
70 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
71 "PerPkg": "1",
72 "UMask": "0x1",
73 "Unit": "iMC"
74 }
75]
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json b/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
new file mode 100644
index 000000000000..dc2586db0dfc
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
@@ -0,0 +1,249 @@
1[
2 {
3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
4 "Counter": "0,1,2,3",
5 "EventName": "UNC_P_CLOCKTICKS",
6 "PerPkg": "1",
7 "Unit": "PCU"
8 },
9 {
10 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band0=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band0_cycles",
11 "Counter": "0,1,2,3",
12 "EventCode": "0xb",
13 "EventName": "UNC_P_FREQ_BAND0_CYCLES",
14 "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
15 "PerPkg": "1",
16 "Unit": "PCU"
17 },
18 {
19 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band1=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band1_cycles",
20 "Counter": "0,1,2,3",
21 "EventCode": "0xc",
22 "EventName": "UNC_P_FREQ_BAND1_CYCLES",
23 "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
24 "PerPkg": "1",
25 "Unit": "PCU"
26 },
27 {
28 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band2=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band2_cycles",
29 "Counter": "0,1,2,3",
30 "EventCode": "0xd",
31 "EventName": "UNC_P_FREQ_BAND2_CYCLES",
32 "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
33 "PerPkg": "1",
34 "Unit": "PCU"
35 },
36 {
37 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band3_cycles",
38 "Counter": "0,1,2,3",
39 "EventCode": "0xe",
40 "EventName": "UNC_P_FREQ_BAND3_CYCLES",
41 "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
42 "PerPkg": "1",
43 "Unit": "PCU"
44 },
45 {
46 "BriefDescription": "Counts the number of times that the uncore transitioned a frequency greater than or equal to the frequency that is configured in the filter. (filter_band0=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band0_cycles",
47 "Counter": "0,1,2,3",
48 "EventCode": "0xb",
49 "EventName": "UNC_P_FREQ_BAND0_TRANSITIONS",
50 "Filter": "edge=1",
51 "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
52 "PerPkg": "1",
53 "Unit": "PCU"
54 },
55 {
56 "BriefDescription": "Counts the number of times that the uncore transitioned to a frequency greater than or equal to the frequency that is configured in the filter. (filter_band1=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band1_cycles",
57 "Counter": "0,1,2,3",
58 "EventCode": "0xc",
59 "EventName": "UNC_P_FREQ_BAND1_TRANSITIONS",
60 "Filter": "edge=1",
61 "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
62 "PerPkg": "1",
63 "Unit": "PCU"
64 },
65 {
66 "BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to the frequency that is configured in the filter. (filter_band2=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band2_cycles",
67 "Counter": "0,1,2,3",
68 "EventCode": "0xd",
69 "EventName": "UNC_P_FREQ_BAND2_TRANSITIONS",
70 "Filter": "edge=1",
71 "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
72 "PerPkg": "1",
73 "Unit": "PCU"
74 },
75 {
76 "BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to the frequency that is configured in the filter. (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band3_cycles",
77 "Counter": "0,1,2,3",
78 "EventCode": "0xe",
79 "EventName": "UNC_P_FREQ_BAND3_TRANSITIONS",
80 "Filter": "edge=1",
81 "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
82 "PerPkg": "1",
83 "Unit": "PCU"
84 },
85 {
86 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c0",
87 "Counter": "0,1,2,3",
88 "EventCode": "0x80",
89 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
90 "Filter": "occ_sel=1",
91 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
92 "PerPkg": "1",
93 "Unit": "PCU"
94 },
95 {
96 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c3",
97 "Counter": "0,1,2,3",
98 "EventCode": "0x80",
99 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
100 "Filter": "occ_sel=2",
101 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
102 "PerPkg": "1",
103 "Unit": "PCU"
104 },
105 {
106 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c6",
107 "Counter": "0,1,2,3",
108 "EventCode": "0x80",
109 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
110 "Filter": "occ_sel=3",
111 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
112 "PerPkg": "1",
113 "Unit": "PCU"
114 },
115 {
116 "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode. This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip. Derived from unc_p_prochot_external_cycles",
117 "Counter": "0,1,2,3",
118 "EventCode": "0xa",
119 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
120 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
121 "PerPkg": "1",
122 "Unit": "PCU"
123 },
124 {
125 "BriefDescription": "Counts the number of cycles when thermal conditions are the upper limit on frequency. This is related to the THERMAL_THROTTLE CYCLES_ABOVE_TEMP event, which always counts cycles when we are above the thermal temperature. This event (STRONGEST_UPPER_LIMIT) is sampled at the output of the algorithm that determines the actual frequency, while THERMAL_THROTTLE looks at the input. Derived from unc_p_freq_max_limit_thermal_cycles",
126 "Counter": "0,1,2,3",
127 "EventCode": "0x4",
128 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
129 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
130 "PerPkg": "1",
131 "Unit": "PCU"
132 },
133 {
134 "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency. Derived from unc_p_freq_max_os_cycles",
135 "Counter": "0,1,2,3",
136 "EventCode": "0x6",
137 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
138 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
139 "PerPkg": "1",
140 "Unit": "PCU"
141 },
142 {
143 "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency. Derived from unc_p_freq_max_power_cycles",
144 "Counter": "0,1,2,3",
145 "EventCode": "0x5",
146 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
147 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
148 "PerPkg": "1",
149 "Unit": "PCU"
150 },
151 {
152 "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency. Derived from unc_p_freq_max_current_cycles",
153 "Counter": "0,1,2,3",
154 "EventCode": "0x7",
155 "EventName": "UNC_P_FREQ_MAX_CURRENT_CYCLES",
156 "MetricExpr": "(UNC_P_FREQ_MAX_CURRENT_CYCLES / UNC_P_CLOCKTICKS) * 100.",
157 "PerPkg": "1",
158 "Unit": "PCU"
159 },
160 {
161 "BriefDescription": "Counts the number of cycles when the system is changing frequency. This can not be filtered by thread ID. One can also use it with the occupancy counter that monitors number of threads in C0 to estimate the performance impact that frequency transitions had on the system. Derived from unc_p_freq_trans_cycles",
162 "Counter": "0,1,2,3",
163 "EventCode": "0x60",
164 "EventName": "UNC_P_FREQ_TRANS_CYCLES",
165 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
166 "PerPkg": "1",
167 "Unit": "PCU"
168 },
169 {
170 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 1.2Ghz. Derived from unc_p_freq_band0_cycles",
171 "Counter": "0,1,2,3",
172 "EventCode": "0xb",
173 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES",
174 "Filter": "filter_band0=1200",
175 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
176 "PerPkg": "1",
177 "Unit": "PCU"
178 },
179 {
180 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 2Ghz. Derived from unc_p_freq_band1_cycles",
181 "Counter": "0,1,2,3",
182 "EventCode": "0xc",
183 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES",
184 "Filter": "filter_band1=2000",
185 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
186 "PerPkg": "1",
187 "Unit": "PCU"
188 },
189 {
190 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 3Ghz. Derived from unc_p_freq_band2_cycles",
191 "Counter": "0,1,2,3",
192 "EventCode": "0xd",
193 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES",
194 "Filter": "filter_band2=3000",
195 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
196 "PerPkg": "1",
197 "Unit": "PCU"
198 },
199 {
200 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 4Ghz. Derived from unc_p_freq_band3_cycles",
201 "Counter": "0,1,2,3",
202 "EventCode": "0xe",
203 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES",
204 "Filter": "filter_band3=4000",
205 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
206 "PerPkg": "1",
207 "Unit": "PCU"
208 },
209 {
210 "BriefDescription": "Counts the number of times that the uncore transitioned to a frequency greater than or equal to 1.2Ghz. Derived from unc_p_freq_band0_cycles",
211 "Counter": "0,1,2,3",
212 "EventCode": "0xb",
213 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS",
214 "Filter": "edge=1,filter_band0=1200",
215 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
216 "PerPkg": "1",
217 "Unit": "PCU"
218 },
219 {
220 "BriefDescription": "Counts the number of times that the uncore transitioned to a frequency greater than or equal to 2Ghz. Derived from unc_p_freq_band1_cycles",
221 "Counter": "0,1,2,3",
222 "EventCode": "0xc",
223 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS",
224 "Filter": "edge=1,filter_band1=2000",
225 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
226 "PerPkg": "1",
227 "Unit": "PCU"
228 },
229 {
230 "BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to 3Ghz. Derived from unc_p_freq_band2_cycles",
231 "Counter": "0,1,2,3",
232 "EventCode": "0xd",
233 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS",
234 "Filter": "edge=1,filter_band2=4000",
235 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
236 "PerPkg": "1",
237 "Unit": "PCU"
238 },
239 {
240 "BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to 4Ghz. Derived from unc_p_freq_band3_cycles",
241 "Counter": "0,1,2,3",
242 "EventCode": "0xe",
243 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS",
244 "Filter": "edge=1,filter_band3=4000",
245 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
246 "PerPkg": "1",
247 "Unit": "PCU"
248 }
249]
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/uncore-cache.json b/tools/perf/pmu-events/arch/x86/jaketown/uncore-cache.json
new file mode 100644
index 000000000000..2f23cf0129e7
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/jaketown/uncore-cache.json
@@ -0,0 +1,209 @@
1[
2 {
3 "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
4 "Counter": "0,1,2,3",
5 "EventName": "UNC_C_CLOCKTICKS",
6 "PerPkg": "1",
7 "Unit": "CBO"
8 },
9 {
10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
11 "Counter": "0,1",
12 "EventCode": "0x34",
13 "EventName": "UNC_C_LLC_LOOKUP.ANY",
14 "Filter": "filter_state=0x1",
15 "PerPkg": "1",
16 "ScaleUnit": "64Bytes",
17 "UMask": "0x11",
18 "Unit": "CBO"
19 },
20 {
21 "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
22 "Counter": "0,1",
23 "EventCode": "0x37",
24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
25 "PerPkg": "1",
26 "ScaleUnit": "64Bytes",
27 "UMask": "0x1",
28 "Unit": "CBO"
29 },
30 {
31 "BriefDescription": "LLC misses - demand and prefetch data reads - excludes LLC prefetches. Derived from unc_c_tor_inserts.miss_opcode.demand",
32 "Counter": "0,1",
33 "EventCode": "0x35",
34 "EventName": "LLC_MISSES.DATA_READ",
35 "Filter": "filter_opc=0x182",
36 "PerPkg": "1",
37 "ScaleUnit": "64Bytes",
38 "UMask": "0x3",
39 "Unit": "CBO"
40 },
41 {
42 "BriefDescription": "LLC misses - Uncacheable reads. Derived from unc_c_tor_inserts.miss_opcode.uncacheable",
43 "Counter": "0,1",
44 "EventCode": "0x35",
45 "EventName": "LLC_MISSES.UNCACHEABLE",
46 "Filter": "filter_opc=0x187",
47 "PerPkg": "1",
48 "ScaleUnit": "64Bytes",
49 "UMask": "0x3",
50 "Unit": "CBO"
51 },
52 {
53 "BriefDescription": "PCIe allocating writes that miss LLC - DDIO misses. Derived from unc_c_tor_inserts.miss_opcode.ddio_miss",
54 "Counter": "0,1",
55 "EventCode": "0x35",
56 "EventName": "LLC_MISSES.PCIE_WRITE",
57 "Filter": "filter_opc=0x19c",
58 "PerPkg": "1",
59 "ScaleUnit": "64Bytes",
60 "UMask": "0x3",
61 "Unit": "CBO"
62 },
63 {
64 "BriefDescription": "LLC misses for ItoM writes (as part of fast string memcpy stores). Derived from unc_c_tor_inserts.miss_opcode.itom_write",
65 "Counter": "0,1",
66 "EventCode": "0x35",
67 "EventName": "LLC_MISSES.ITOM_WRITE",
68 "Filter": "filter_opc=0x1c8",
69 "PerPkg": "1",
70 "ScaleUnit": "64Bytes",
71 "UMask": "0x3",
72 "Unit": "CBO"
73 },
74 {
75 "BriefDescription": "Streaming stores (full cache line). Derived from unc_c_tor_inserts.opcode.streaming_full",
76 "Counter": "0,1",
77 "EventCode": "0x35",
78 "EventName": "LLC_REFERENCES.STREAMING_FULL",
79 "Filter": "filter_opc=0x18c",
80 "PerPkg": "1",
81 "ScaleUnit": "64Bytes",
82 "UMask": "0x1",
83 "Unit": "CBO"
84 },
85 {
86 "BriefDescription": "Streaming stores (partial cache line). Derived from unc_c_tor_inserts.opcode.streaming_partial",
87 "Counter": "0,1",
88 "EventCode": "0x35",
89 "EventName": "LLC_REFERENCES.STREAMING_PARTIAL",
90 "Filter": "filter_opc=0x18d",
91 "PerPkg": "1",
92 "ScaleUnit": "64Bytes",
93 "UMask": "0x1",
94 "Unit": "CBO"
95 },
96 {
97 "BriefDescription": "Partial PCIe reads. Derived from unc_c_tor_inserts.opcode.pcie_partial",
98 "Counter": "0,1",
99 "EventCode": "0x35",
100 "EventName": "LLC_REFERENCES.PCIE_PARTIAL_READ",
101 "Filter": "filter_opc=0x195",
102 "PerPkg": "1",
103 "ScaleUnit": "64Bytes",
104 "UMask": "0x1",
105 "Unit": "CBO"
106 },
107 {
108 "BriefDescription": "PCIe allocating writes that hit in LLC (DDIO hits). Derived from unc_c_tor_inserts.opcode.ddio_hit",
109 "Counter": "0,1",
110 "EventCode": "0x35",
111 "EventName": "LLC_REFERENCES.PCIE_WRITE",
112 "Filter": "filter_opc=0x19c",
113 "PerPkg": "1",
114 "ScaleUnit": "64Bytes",
115 "UMask": "0x1",
116 "Unit": "CBO"
117 },
118 {
119 "BriefDescription": "PCIe read current. Derived from unc_c_tor_inserts.opcode.pcie_read_current",
120 "Counter": "0,1",
121 "EventCode": "0x35",
122 "EventName": "LLC_REFERENCES.PCIE_READ",
123 "Filter": "filter_opc=0x19e",
124 "PerPkg": "1",
125 "ScaleUnit": "64Bytes",
126 "UMask": "0x1",
127 "Unit": "CBO"
128 },
129 {
130 "BriefDescription": "ItoM write hits (as part of fast string memcpy stores). Derived from unc_c_tor_inserts.opcode.itom_write_hit",
131 "Counter": "0,1",
132 "EventCode": "0x35",
133 "EventName": "LLC_REFERENCES.ITOM_WRITE",
134 "Filter": "filter_opc=0x1c8",
135 "PerPkg": "1",
136 "ScaleUnit": "64Bytes",
137 "UMask": "0x1",
138 "Unit": "CBO"
139 },
140 {
141 "BriefDescription": "PCIe non-snoop reads. Derived from unc_c_tor_inserts.opcode.pcie_read",
142 "Counter": "0,1",
143 "EventCode": "0x35",
144 "EventName": "LLC_REFERENCES.PCIE_NS_READ",
145 "Filter": "filter_opc=0x1e4",
146 "PerPkg": "1",
147 "ScaleUnit": "64Bytes",
148 "UMask": "0x1",
149 "Unit": "CBO"
150 },
151 {
152 "BriefDescription": "PCIe non-snoop writes (partial). Derived from unc_c_tor_inserts.opcode.pcie_partial_write",
153 "Counter": "0,1",
154 "EventCode": "0x35",
155 "EventName": "LLC_REFERENCES.PCIE_NS_PARTIAL_WRITE",
156 "Filter": "filter_opc=0x1e5",
157 "PerPkg": "1",
158 "ScaleUnit": "64Bytes",
159 "UMask": "0x1",
160 "Unit": "CBO"
161 },
162 {
163 "BriefDescription": "PCIe non-snoop writes (full line). Derived from unc_c_tor_inserts.opcode.pcie_full_write",
164 "Counter": "0,1",
165 "EventCode": "0x35",
166 "EventName": "LLC_REFERENCES.PCIE_NS_WRITE",
167 "Filter": "filter_opc=0x1e6",
168 "PerPkg": "1",
169 "ScaleUnit": "64Bytes",
170 "UMask": "0x1",
171 "Unit": "CBO"
172 },
173 {
174 "BriefDescription": "Occupancy counter for all LLC misses; we divide this by UNC_C_CLOCKTICKS to get average Q depth. Derived from unc_c_tor_occupancy.miss_all",
175 "EventCode": "0x36",
176 "EventName": "UNC_C_TOR_OCCUPANCY.MISS_ALL",
177 "Filter": "filter_opc=0x182",
178 "MetricExpr": "(UNC_C_TOR_OCCUPANCY.MISS_ALL / UNC_C_CLOCKTICKS) * 100.",
179 "PerPkg": "1",
180 "UMask": "0xa",
181 "Unit": "CBO"
182 },
183 {
184 "BriefDescription": "Occupancy counter for LLC data reads (demand and L2 prefetch). Derived from unc_c_tor_occupancy.miss_opcode.llc_data_read",
185 "EventCode": "0x36",
186 "EventName": "UNC_C_TOR_OCCUPANCY.LLC_DATA_READ",
187 "PerPkg": "1",
188 "UMask": "0x3",
189 "Unit": "CBO"
190 },
191 {
192 "BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads",
193 "Counter": "0,1,2,3",
194 "EventCode": "0x1",
195 "EventName": "UNC_H_REQUESTS.READS",
196 "PerPkg": "1",
197 "UMask": "0x3",
198 "Unit": "HA"
199 },
200 {
201 "BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes",
202 "Counter": "0,1,2,3",
203 "EventCode": "0x1",
204 "EventName": "UNC_H_REQUESTS.WRITES",
205 "PerPkg": "1",
206 "UMask": "0xc",
207 "Unit": "HA"
208 }
209]
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json
new file mode 100644
index 000000000000..63351876eb57
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json
@@ -0,0 +1,46 @@
1[
2 {
3 "BriefDescription": "QPI clock ticks. Used to get percentages of QPI cycles events. Derived from unc_q_clockticks",
4 "Counter": "0,1,2,3",
5 "EventCode": "0x14",
6 "EventName": "UNC_Q_CLOCKTICKS",
7 "PerPkg": "1",
8 "Unit": "QPI LL"
9 },
10 {
11 "BriefDescription": "Cycles where receiving QPI link is in half-width mode. Derived from unc_q_rxl0p_power_cycles",
12 "Counter": "0,1,2,3",
13 "EventCode": "0x10",
14 "EventName": "UNC_Q_RxL0P_POWER_CYCLES",
15 "MetricExpr": "(UNC_Q_RxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
16 "PerPkg": "1",
17 "Unit": "QPI LL"
18 },
19 {
20 "BriefDescription": "Cycles where transmitting QPI link is in half-width mode. Derived from unc_q_txl0p_power_cycles",
21 "Counter": "0,1,2,3",
22 "EventCode": "0xd",
23 "EventName": "UNC_Q_TxL0P_POWER_CYCLES",
24 "MetricExpr": "(UNC_Q_TxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
25 "PerPkg": "1",
26 "Unit": "QPI LL"
27 },
28 {
29 "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
30 "Counter": "0,1,2,3",
31 "EventName": "UNC_Q_TxL_FLITS_G0.DATA",
32 "PerPkg": "1",
33 "ScaleUnit": "8Bytes",
34 "UMask": "0x2",
35 "Unit": "QPI LL"
36 },
37 {
38 "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
39 "Counter": "0,1,2,3",
40 "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
41 "PerPkg": "1",
42 "ScaleUnit": "8Bytes",
43 "UMask": "0x4",
44 "Unit": "QPI LL"
45 }
46]
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/uncore-memory.json b/tools/perf/pmu-events/arch/x86/jaketown/uncore-memory.json
new file mode 100644
index 000000000000..e2cf6daa7b37
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/jaketown/uncore-memory.json
@@ -0,0 +1,79 @@
1[
2 {
3 "BriefDescription": "Memory page activates. Derived from unc_m_act_count",
4 "Counter": "0,1,2,3",
5 "EventCode": "0x1",
6 "EventName": "UNC_M_ACT_COUNT",
7 "PerPkg": "1",
8 "Unit": "iMC"
9 },
10 {
11 "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
12 "Counter": "0,1,2,3",
13 "EventCode": "0x4",
14 "EventName": "UNC_M_CAS_COUNT.RD",
15 "PerPkg": "1",
16 "UMask": "0x3",
17 "Unit": "iMC"
18 },
19 {
20 "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
21 "Counter": "0,1,2,3",
22 "EventCode": "0x4",
23 "EventName": "UNC_M_CAS_COUNT.WR",
24 "PerPkg": "1",
25 "UMask": "0xc",
26 "Unit": "iMC"
27 },
28 {
29 "BriefDescription": "Memory controller clock ticks. Used to get percentages of memory controller cycles events. Derived from unc_m_clockticks",
30 "Counter": "0,1,2,3",
31 "EventName": "UNC_M_CLOCKTICKS",
32 "PerPkg": "1",
33 "Unit": "iMC"
34 },
35 {
36 "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd",
37 "Counter": "0,1,2,3",
38 "EventCode": "0x85",
39 "EventName": "UNC_M_POWER_CHANNEL_PPD",
40 "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
41 "PerPkg": "1",
42 "Unit": "iMC"
43 },
44 {
45 "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
46 "Counter": "0,1,2,3",
47 "EventCode": "0x86",
48 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
49 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
50 "PerPkg": "1",
51 "Unit": "iMC"
52 },
53 {
54 "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
55 "Counter": "0,1,2,3",
56 "EventCode": "0x43",
57 "EventName": "UNC_M_POWER_SELF_REFRESH",
58 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
59 "PerPkg": "1",
60 "Unit": "iMC"
61 },
62 {
63 "BriefDescription": "Memory page conflicts. Derived from unc_m_pre_count.page_miss",
64 "Counter": "0,1,2,3",
65 "EventCode": "0x2",
66 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
67 "PerPkg": "1",
68 "UMask": "0x1",
69 "Unit": "iMC"
70 },
71 {
72 "BriefDescription": "Occupancy counter for memory read queue. Derived from unc_m_rpq_occupancy",
73 "Counter": "0,1,2,3",
74 "EventCode": "0x80",
75 "EventName": "UNC_M_RPQ_OCCUPANCY",
76 "PerPkg": "1",
77 "Unit": "iMC"
78 }
79]
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json b/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
new file mode 100644
index 000000000000..bbe36d547386
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
@@ -0,0 +1,248 @@
1[
2 {
3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
4 "Counter": "0,1,2,3",
5 "EventName": "UNC_P_CLOCKTICKS",
6 "PerPkg": "1",
7 "Unit": "PCU"
8 },
9 {
10 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band0=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band0_cycles",
11 "Counter": "0,1,2,3",
12 "EventCode": "0xb",
13 "EventName": "UNC_P_FREQ_BAND0_CYCLES",
14 "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
15 "PerPkg": "1",
16 "Unit": "PCU"
17 },
18 {
19 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band1=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band1_cycles",
20 "Counter": "0,1,2,3",
21 "EventCode": "0xc",
22 "EventName": "UNC_P_FREQ_BAND1_CYCLES",
23 "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
24 "PerPkg": "1",
25 "Unit": "PCU"
26 },
27 {
28 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band2=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band2_cycles",
29 "Counter": "0,1,2,3",
30 "EventCode": "0xd",
31 "EventName": "UNC_P_FREQ_BAND2_CYCLES",
32 "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
33 "PerPkg": "1",
34 "Unit": "PCU"
35 },
36 {
37 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band3_cycles",
38 "Counter": "0,1,2,3",
39 "EventCode": "0xe",
40 "EventName": "UNC_P_FREQ_BAND3_CYCLES",
41 "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
42 "PerPkg": "1",
43 "Unit": "PCU"
44 },
45 {
46 "BriefDescription": "Counts the number of times that the uncore transitioned a frequency greater than or equal to the frequency that is configured in the filter. (filter_band0=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band0_cycles",
47 "Counter": "0,1,2,3",
48 "EventCode": "0xb",
49 "EventName": "UNC_P_FREQ_BAND0_TRANSITIONS",
50 "Filter": "edge=1",
51 "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
52 "PerPkg": "1",
53 "Unit": "PCU"
54 },
55 {
56 "BriefDescription": "Counts the number of times that the uncore transistioned to a frequency greater than or equal to the frequency that is configured in the filter. (filter_band1=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band1_cycles",
57 "Counter": "0,1,2,3",
58 "EventCode": "0xc",
59 "EventName": "UNC_P_FREQ_BAND1_TRANSITIONS",
60 "Filter": "edge=1",
61 "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
62 "PerPkg": "1",
63 "Unit": "PCU"
64 },
65 {
66 "BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to the frequency that is configured in the filter. (filter_band2=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band2_cycles",
67 "Counter": "0,1,2,3",
68 "EventCode": "0xd",
69 "EventName": "UNC_P_FREQ_BAND2_TRANSITIONS",
70 "Filter": "edge=1",
71 "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
72 "PerPkg": "1",
73 "Unit": "PCU"
74 },
75 {
76 "BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to the frequency that is configured in the filter. (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band3_cycles",
77 "Counter": "0,1,2,3",
78 "EventCode": "0xe",
79 "EventName": "UNC_P_FREQ_BAND3_TRANSITIONS",
80 "Filter": "edge=1",
81 "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
82 "PerPkg": "1",
83 "Unit": "PCU"
84 },
85 {
86 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c0",
87 "Counter": "0,1,2,3",
88 "EventCode": "0x80",
89 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
90 "Filter": "occ_sel=1",
91 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
92 "PerPkg": "1",
93 "Unit": "PCU"
94 },
95 {
96 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c3",
97 "Counter": "0,1,2,3",
98 "EventCode": "0x80",
99 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
100 "Filter": "occ_sel=2",
101 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
102 "PerPkg": "1",
103 "Unit": "PCU"
104 },
105 {
106 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events . Derived from unc_p_power_state_occupancy.cores_c6",
107 "Counter": "0,1,2,3",
108 "EventCode": "0x80",
109 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
110 "Filter": "occ_sel=3",
111 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
112 "PerPkg": "1",
113 "Unit": "PCU"
114 },
115 {
116 "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode. This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip. Derived from unc_p_prochot_external_cycles",
117 "Counter": "0,1,2,3",
118 "EventCode": "0xa",
119 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
120 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
121 "PerPkg": "1",
122 "Unit": "PCU"
123 },
124 {
125 "BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency. Derived from unc_p_freq_max_limit_thermal_cycles",
126 "Counter": "0,1,2,3",
127 "EventCode": "0x4",
128 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
129 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
130 "PerPkg": "1",
131 "Unit": "PCU"
132 },
133 {
134 "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency. Derived from unc_p_freq_max_os_cycles",
135 "Counter": "0,1,2,3",
136 "EventCode": "0x6",
137 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
138 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
139 "PerPkg": "1",
140 "Unit": "PCU"
141 },
142 {
143 "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency. Derived from unc_p_freq_max_power_cycles",
144 "Counter": "0,1,2,3",
145 "EventCode": "0x5",
146 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
147 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
148 "PerPkg": "1",
149 "Unit": "PCU"
150 },
151 {
152 "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency. Derived from unc_p_freq_max_current_cycles",
153 "Counter": "0,1,2,3",
154 "EventCode": "0x7",
155 "EventName": "UNC_P_FREQ_MAX_CURRENT_CYCLES",
156 "MetricExpr": "(UNC_P_FREQ_MAX_CURRENT_CYCLES / UNC_P_CLOCKTICKS) * 100.",
157 "PerPkg": "1",
158 "Unit": "PCU"
159 },
160 {
161 "BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles",
162 "Counter": "0,1,2,3",
163 "EventName": "UNC_P_FREQ_TRANS_CYCLES",
164 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
165 "PerPkg": "1",
166 "Unit": "PCU"
167 },
168 {
169 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 1.2Ghz. Derived from unc_p_freq_band0_cycles",
170 "Counter": "0,1,2,3",
171 "EventCode": "0xb",
172 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES",
173 "Filter": "filter_band0=1200",
174 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
175 "PerPkg": "1",
176 "Unit": "PCU"
177 },
178 {
179 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 2Ghz. Derived from unc_p_freq_band1_cycles",
180 "Counter": "0,1,2,3",
181 "EventCode": "0xc",
182 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES",
183 "Filter": "filter_band1=2000",
184 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
185 "PerPkg": "1",
186 "Unit": "PCU"
187 },
188 {
189 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 3Ghz. Derived from unc_p_freq_band2_cycles",
190 "Counter": "0,1,2,3",
191 "EventCode": "0xd",
192 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES",
193 "Filter": "filter_band2=3000",
194 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
195 "PerPkg": "1",
196 "Unit": "PCU"
197 },
198 {
199 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 4Ghz. Derived from unc_p_freq_band3_cycles",
200 "Counter": "0,1,2,3",
201 "EventCode": "0xe",
202 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES",
203 "Filter": "filter_band3=4000",
204 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
205 "PerPkg": "1",
206 "Unit": "PCU"
207 },
208 {
209 "BriefDescription": "Counts the number of times that the uncore transitioned to a frequency greater than or equal to 1.2Ghz. Derived from unc_p_freq_band0_cycles",
210 "Counter": "0,1,2,3",
211 "EventCode": "0xb",
212 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS",
213 "Filter": "edge=1,filter_band0=1200",
214 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
215 "PerPkg": "1",
216 "Unit": "PCU"
217 },
218 {
219 "BriefDescription": "Counts the number of times that the uncore transitioned to a frequency greater than or equal to 2Ghz. Derived from unc_p_freq_band1_cycles",
220 "Counter": "0,1,2,3",
221 "EventCode": "0xc",
222 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS",
223 "Filter": "edge=1,filter_band1=2000",
224 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
225 "PerPkg": "1",
226 "Unit": "PCU"
227 },
228 {
229 "BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to 3Ghz. Derived from unc_p_freq_band2_cycles",
230 "Counter": "0,1,2,3",
231 "EventCode": "0xd",
232 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS",
233 "Filter": "edge=1,filter_band2=4000",
234 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
235 "PerPkg": "1",
236 "Unit": "PCU"
237 },
238 {
239 "BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to 4Ghz. Derived from unc_p_freq_band3_cycles",
240 "Counter": "0,1,2,3",
241 "EventCode": "0xe",
242 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS",
243 "Filter": "edge=1,filter_band3=4000",
244 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
245 "PerPkg": "1",
246 "Unit": "PCU"
247 }
248]
diff --git a/tools/perf/pmu-events/arch/x86/knightslanding/uncore-memory.json b/tools/perf/pmu-events/arch/x86/knightslanding/uncore-memory.json
new file mode 100644
index 000000000000..e3bcd86c4f56
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/knightslanding/uncore-memory.json
@@ -0,0 +1,42 @@
1[
2 {
3 "BriefDescription": "ddr bandwidth read (CPU traffic only) (MB/sec). ",
4 "Counter": "0,1,2,3",
5 "EventCode": "0x03",
6 "EventName": "UNC_M_CAS_COUNT.RD",
7 "PerPkg": "1",
8 "ScaleUnit": "6.4e-05MiB",
9 "UMask": "0x01",
10 "Unit": "imc"
11 },
12 {
13 "BriefDescription": "ddr bandwidth write (CPU traffic only) (MB/sec). ",
14 "Counter": "0,1,2,3",
15 "EventCode": "0x03",
16 "EventName": "UNC_M_CAS_COUNT.WR",
17 "PerPkg": "1",
18 "ScaleUnit": "6.4e-05MiB",
19 "UMask": "0x02",
20 "Unit": "imc"
21 },
22 {
23 "BriefDescription": "mcdram bandwidth read (CPU traffic only) (MB/sec). ",
24 "Counter": "0,1,2,3",
25 "EventCode": "0x01",
26 "EventName": "UNC_E_RPQ_INSERTS",
27 "PerPkg": "1",
28 "ScaleUnit": "6.4e-05MiB",
29 "UMask": "0x01",
30 "Unit": "edc_eclk"
31 },
32 {
33 "BriefDescription": "mcdram bandwidth write (CPU traffic only) (MB/sec). ",
34 "Counter": "0,1,2,3",
35 "EventCode": "0x02",
36 "EventName": "UNC_E_WPQ_INSERTS",
37 "PerPkg": "1",
38 "ScaleUnit": "6.4e-05MiB",
39 "UMask": "0x01",
40 "Unit": "edc_eclk"
41 }
42]
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
index 41611d7f9873..eed09346a72a 100644
--- a/tools/perf/pmu-events/jevents.c
+++ b/tools/perf/pmu-events/jevents.c
@@ -135,7 +135,6 @@ static struct field {
135 const char *field; 135 const char *field;
136 const char *kernel; 136 const char *kernel;
137} fields[] = { 137} fields[] = {
138 { "EventCode", "event=" },
139 { "UMask", "umask=" }, 138 { "UMask", "umask=" },
140 { "CounterMask", "cmask=" }, 139 { "CounterMask", "cmask=" },
141 { "Invert", "inv=" }, 140 { "Invert", "inv=" },
@@ -189,6 +188,27 @@ static struct msrmap *lookup_msr(char *map, jsmntok_t *val)
189 return NULL; 188 return NULL;
190} 189}
191 190
191static struct map {
192 const char *json;
193 const char *perf;
194} unit_to_pmu[] = {
195 { "CBO", "uncore_cbox" },
196 { "QPI LL", "uncore_qpi" },
197 { "SBO", "uncore_sbox" },
198 {}
199};
200
201static const char *field_to_perf(struct map *table, char *map, jsmntok_t *val)
202{
203 int i;
204
205 for (i = 0; table[i].json; i++) {
206 if (json_streq(map, val, table[i].json))
207 return table[i].perf;
208 }
209 return NULL;
210}
211
192#define EXPECT(e, t, m) do { if (!(e)) { \ 212#define EXPECT(e, t, m) do { if (!(e)) { \
193 jsmntok_t *loc = (t); \ 213 jsmntok_t *loc = (t); \
194 if (!(t)->start && (t) > tokens) \ 214 if (!(t)->start && (t) > tokens) \
@@ -270,7 +290,8 @@ static void print_events_table_prefix(FILE *fp, const char *tblname)
270} 290}
271 291
272static int print_events_table_entry(void *data, char *name, char *event, 292static int print_events_table_entry(void *data, char *name, char *event,
273 char *desc, char *long_desc) 293 char *desc, char *long_desc,
294 char *pmu, char *unit, char *perpkg)
274{ 295{
275 struct perf_entry_data *pd = data; 296 struct perf_entry_data *pd = data;
276 FILE *outfp = pd->outfp; 297 FILE *outfp = pd->outfp;
@@ -288,7 +309,12 @@ static int print_events_table_entry(void *data, char *name, char *event,
288 fprintf(outfp, "\t.topic = \"%s\",\n", topic); 309 fprintf(outfp, "\t.topic = \"%s\",\n", topic);
289 if (long_desc && long_desc[0]) 310 if (long_desc && long_desc[0])
290 fprintf(outfp, "\t.long_desc = \"%s\",\n", long_desc); 311 fprintf(outfp, "\t.long_desc = \"%s\",\n", long_desc);
291 312 if (pmu)
313 fprintf(outfp, "\t.pmu = \"%s\",\n", pmu);
314 if (unit)
315 fprintf(outfp, "\t.unit = \"%s\",\n", unit);
316 if (perpkg)
317 fprintf(outfp, "\t.perpkg = \"%s\",\n", perpkg);
292 fprintf(outfp, "},\n"); 318 fprintf(outfp, "},\n");
293 319
294 return 0; 320 return 0;
@@ -335,7 +361,8 @@ static char *real_event(const char *name, char *event)
335/* Call func with each event in the json file */ 361/* Call func with each event in the json file */
336int json_events(const char *fn, 362int json_events(const char *fn,
337 int (*func)(void *data, char *name, char *event, char *desc, 363 int (*func)(void *data, char *name, char *event, char *desc,
338 char *long_desc), 364 char *long_desc,
365 char *pmu, char *unit, char *perpkg),
339 void *data) 366 void *data)
340{ 367{
341 int err = -EIO; 368 int err = -EIO;
@@ -343,6 +370,7 @@ int json_events(const char *fn,
343 jsmntok_t *tokens, *tok; 370 jsmntok_t *tokens, *tok;
344 int i, j, len; 371 int i, j, len;
345 char *map; 372 char *map;
373 char buf[128];
346 374
347 if (!fn) 375 if (!fn)
348 return -ENOENT; 376 return -ENOENT;
@@ -356,6 +384,11 @@ int json_events(const char *fn,
356 char *event = NULL, *desc = NULL, *name = NULL; 384 char *event = NULL, *desc = NULL, *name = NULL;
357 char *long_desc = NULL; 385 char *long_desc = NULL;
358 char *extra_desc = NULL; 386 char *extra_desc = NULL;
387 char *pmu = NULL;
388 char *filter = NULL;
389 char *perpkg = NULL;
390 char *unit = NULL;
391 unsigned long long eventcode = 0;
359 struct msrmap *msr = NULL; 392 struct msrmap *msr = NULL;
360 jsmntok_t *msrval = NULL; 393 jsmntok_t *msrval = NULL;
361 jsmntok_t *precise = NULL; 394 jsmntok_t *precise = NULL;
@@ -376,6 +409,16 @@ int json_events(const char *fn,
376 nz = !json_streq(map, val, "0"); 409 nz = !json_streq(map, val, "0");
377 if (match_field(map, field, nz, &event, val)) { 410 if (match_field(map, field, nz, &event, val)) {
378 /* ok */ 411 /* ok */
412 } else if (json_streq(map, field, "EventCode")) {
413 char *code = NULL;
414 addfield(map, &code, "", "", val);
415 eventcode |= strtoul(code, NULL, 0);
416 free(code);
417 } else if (json_streq(map, field, "ExtSel")) {
418 char *code = NULL;
419 addfield(map, &code, "", "", val);
420 eventcode |= strtoul(code, NULL, 0) << 21;
421 free(code);
379 } else if (json_streq(map, field, "EventName")) { 422 } else if (json_streq(map, field, "EventName")) {
380 addfield(map, &name, "", "", val); 423 addfield(map, &name, "", "", val);
381 } else if (json_streq(map, field, "BriefDescription")) { 424 } else if (json_streq(map, field, "BriefDescription")) {
@@ -399,6 +442,28 @@ int json_events(const char *fn,
399 addfield(map, &extra_desc, ". ", 442 addfield(map, &extra_desc, ". ",
400 " Supports address when precise", 443 " Supports address when precise",
401 NULL); 444 NULL);
445 } else if (json_streq(map, field, "Unit")) {
446 const char *ppmu;
447 char *s;
448
449 ppmu = field_to_perf(unit_to_pmu, map, val);
450 if (ppmu) {
451 pmu = strdup(ppmu);
452 } else {
453 if (!pmu)
454 pmu = strdup("uncore_");
455 addfield(map, &pmu, "", "", val);
456 for (s = pmu; *s; s++)
457 *s = tolower(*s);
458 }
459 addfield(map, &desc, ". ", "Unit: ", NULL);
460 addfield(map, &desc, "", pmu, NULL);
461 } else if (json_streq(map, field, "Filter")) {
462 addfield(map, &filter, "", "", val);
463 } else if (json_streq(map, field, "ScaleUnit")) {
464 addfield(map, &unit, "", "", val);
465 } else if (json_streq(map, field, "PerPkg")) {
466 addfield(map, &perpkg, "", "", val);
402 } 467 }
403 /* ignore unknown fields */ 468 /* ignore unknown fields */
404 } 469 }
@@ -410,20 +475,29 @@ int json_events(const char *fn,
410 addfield(map, &extra_desc, " ", 475 addfield(map, &extra_desc, " ",
411 "(Precise event)", NULL); 476 "(Precise event)", NULL);
412 } 477 }
478 snprintf(buf, sizeof buf, "event=%#llx", eventcode);
479 addfield(map, &event, ",", buf, NULL);
413 if (desc && extra_desc) 480 if (desc && extra_desc)
414 addfield(map, &desc, " ", extra_desc, NULL); 481 addfield(map, &desc, " ", extra_desc, NULL);
415 if (long_desc && extra_desc) 482 if (long_desc && extra_desc)
416 addfield(map, &long_desc, " ", extra_desc, NULL); 483 addfield(map, &long_desc, " ", extra_desc, NULL);
484 if (filter)
485 addfield(map, &event, ",", filter, NULL);
417 if (msr != NULL) 486 if (msr != NULL)
418 addfield(map, &event, ",", msr->pname, msrval); 487 addfield(map, &event, ",", msr->pname, msrval);
419 fixname(name); 488 fixname(name);
420 489
421 err = func(data, name, real_event(name, event), desc, long_desc); 490 err = func(data, name, real_event(name, event), desc, long_desc,
491 pmu, unit, perpkg);
422 free(event); 492 free(event);
423 free(desc); 493 free(desc);
424 free(name); 494 free(name);
425 free(long_desc); 495 free(long_desc);
426 free(extra_desc); 496 free(extra_desc);
497 free(pmu);
498 free(filter);
499 free(perpkg);
500 free(unit);
427 if (err) 501 if (err)
428 break; 502 break;
429 tok += j; 503 tok += j;
diff --git a/tools/perf/pmu-events/jevents.h b/tools/perf/pmu-events/jevents.h
index b0eb2744b498..71e13de31092 100644
--- a/tools/perf/pmu-events/jevents.h
+++ b/tools/perf/pmu-events/jevents.h
@@ -3,7 +3,9 @@
3 3
4int json_events(const char *fn, 4int json_events(const char *fn,
5 int (*func)(void *data, char *name, char *event, char *desc, 5 int (*func)(void *data, char *name, char *event, char *desc,
6 char *long_desc), 6 char *long_desc,
7 char *pmu,
8 char *unit, char *perpkg),
7 void *data); 9 void *data);
8char *get_cpu_str(void); 10char *get_cpu_str(void);
9 11
diff --git a/tools/perf/pmu-events/json.c b/tools/perf/pmu-events/json.c
index f67bbb0aa36e..0544398d6e2d 100644
--- a/tools/perf/pmu-events/json.c
+++ b/tools/perf/pmu-events/json.c
@@ -49,7 +49,7 @@ static char *mapfile(const char *fn, size_t *size)
49 int err; 49 int err;
50 int fd = open(fn, O_RDONLY); 50 int fd = open(fn, O_RDONLY);
51 51
52 if (fd < 0 && verbose && fn) { 52 if (fd < 0 && verbose > 0 && fn) {
53 pr_err("Error opening events file '%s': %s\n", fn, 53 pr_err("Error opening events file '%s': %s\n", fn,
54 strerror(errno)); 54 strerror(errno));
55 } 55 }
diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h
index 2eaef595d8a0..c669a3cdb9f0 100644
--- a/tools/perf/pmu-events/pmu-events.h
+++ b/tools/perf/pmu-events/pmu-events.h
@@ -10,6 +10,9 @@ struct pmu_event {
10 const char *desc; 10 const char *desc;
11 const char *topic; 11 const char *topic;
12 const char *long_desc; 12 const char *long_desc;
13 const char *pmu;
14 const char *unit;
15 const char *perpkg;
13}; 16};
14 17
15/* 18/*
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 6676c2dd6dcb..1cb3d9b540e9 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -44,6 +44,7 @@ perf-y += is_printable_array.o
44perf-y += bitmap.o 44perf-y += bitmap.o
45perf-y += perf-hooks.o 45perf-y += perf-hooks.o
46perf-y += clang.o 46perf-y += clang.o
47perf-y += unit_number__scnprintf.o
47 48
48$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build 49$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
49 $(call rule_mkdir) 50 $(call rule_mkdir)
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index 28d1605b0338..88dc51f4c27b 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -144,7 +144,7 @@ static int run_dir(const char *d, const char *perf)
144 int vcnt = min(verbose, (int) sizeof(v) - 1); 144 int vcnt = min(verbose, (int) sizeof(v) - 1);
145 char cmd[3*PATH_MAX]; 145 char cmd[3*PATH_MAX];
146 146
147 if (verbose) 147 if (verbose > 0)
148 vcnt++; 148 vcnt++;
149 149
150 snprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s", 150 snprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s",
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index 92343f43e44a..1a04fe77487d 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -5,11 +5,13 @@
5#include <util/evlist.h> 5#include <util/evlist.h>
6#include <linux/bpf.h> 6#include <linux/bpf.h>
7#include <linux/filter.h> 7#include <linux/filter.h>
8#include <api/fs/fs.h>
8#include <bpf/bpf.h> 9#include <bpf/bpf.h>
9#include "tests.h" 10#include "tests.h"
10#include "llvm.h" 11#include "llvm.h"
11#include "debug.h" 12#include "debug.h"
12#define NR_ITERS 111 13#define NR_ITERS 111
14#define PERF_TEST_BPF_PATH "/sys/fs/bpf/perf_test"
13 15
14#ifdef HAVE_LIBBPF_SUPPORT 16#ifdef HAVE_LIBBPF_SUPPORT
15 17
@@ -54,6 +56,7 @@ static struct {
54 const char *msg_load_fail; 56 const char *msg_load_fail;
55 int (*target_func)(void); 57 int (*target_func)(void);
56 int expect_result; 58 int expect_result;
59 bool pin;
57} bpf_testcase_table[] = { 60} bpf_testcase_table[] = {
58 { 61 {
59 LLVM_TESTCASE_BASE, 62 LLVM_TESTCASE_BASE,
@@ -63,6 +66,17 @@ static struct {
63 "load bpf object failed", 66 "load bpf object failed",
64 &epoll_wait_loop, 67 &epoll_wait_loop,
65 (NR_ITERS + 1) / 2, 68 (NR_ITERS + 1) / 2,
69 false,
70 },
71 {
72 LLVM_TESTCASE_BASE,
73 "BPF pinning",
74 "[bpf_pinning]",
75 "fix kbuild first",
76 "check your vmlinux setting?",
77 &epoll_wait_loop,
78 (NR_ITERS + 1) / 2,
79 true,
66 }, 80 },
67#ifdef HAVE_BPF_PROLOGUE 81#ifdef HAVE_BPF_PROLOGUE
68 { 82 {
@@ -73,6 +87,7 @@ static struct {
73 "check your vmlinux setting?", 87 "check your vmlinux setting?",
74 &llseek_loop, 88 &llseek_loop,
75 (NR_ITERS + 1) / 4, 89 (NR_ITERS + 1) / 4,
90 false,
76 }, 91 },
77#endif 92#endif
78 { 93 {
@@ -83,6 +98,7 @@ static struct {
83 "libbpf error when dealing with relocation", 98 "libbpf error when dealing with relocation",
84 NULL, 99 NULL,
85 0, 100 0,
101 false,
86 }, 102 },
87}; 103};
88 104
@@ -226,10 +242,34 @@ static int __test__bpf(int idx)
226 goto out; 242 goto out;
227 } 243 }
228 244
229 if (obj) 245 if (obj) {
230 ret = do_test(obj, 246 ret = do_test(obj,
231 bpf_testcase_table[idx].target_func, 247 bpf_testcase_table[idx].target_func,
232 bpf_testcase_table[idx].expect_result); 248 bpf_testcase_table[idx].expect_result);
249 if (ret != TEST_OK)
250 goto out;
251 if (bpf_testcase_table[idx].pin) {
252 int err;
253
254 if (!bpf_fs__mount()) {
255 pr_debug("BPF filesystem not mounted\n");
256 ret = TEST_FAIL;
257 goto out;
258 }
259 err = mkdir(PERF_TEST_BPF_PATH, 0777);
260 if (err && errno != EEXIST) {
261 pr_debug("Failed to make perf_test dir: %s\n",
262 strerror(errno));
263 ret = TEST_FAIL;
264 goto out;
265 }
266 if (bpf_object__pin(obj, PERF_TEST_BPF_PATH))
267 ret = TEST_FAIL;
268 if (rm_rf(PERF_TEST_BPF_PATH))
269 ret = TEST_FAIL;
270 }
271 }
272
233out: 273out:
234 bpf__clear(); 274 bpf__clear();
235 return ret; 275 return ret;
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index a77dcc0d24e3..83c4669cbc5b 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -247,6 +247,10 @@ static struct test generic_tests[] = {
247 } 247 }
248 }, 248 },
249 { 249 {
250 .desc = "unit_number__scnprintf",
251 .func = test__unit_number__scnprint,
252 },
253 {
250 .func = NULL, 254 .func = NULL,
251 }, 255 },
252}; 256};
@@ -295,7 +299,7 @@ static int run_test(struct test *test, int subtest)
295 if (!dont_fork) { 299 if (!dont_fork) {
296 pr_debug("test child forked, pid %d\n", getpid()); 300 pr_debug("test child forked, pid %d\n", getpid());
297 301
298 if (!verbose) { 302 if (verbose <= 0) {
299 int nullfd = open("/dev/null", O_WRONLY); 303 int nullfd = open("/dev/null", O_WRONLY);
300 304
301 if (nullfd >= 0) { 305 if (nullfd >= 0) {
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index ff5bc6363a79..d1f693041324 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -599,7 +599,7 @@ static int do_test_code_reading(bool try_kcore)
599 continue; 599 continue;
600 } 600 }
601 601
602 if (verbose) { 602 if (verbose > 0) {
603 char errbuf[512]; 603 char errbuf[512];
604 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); 604 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
605 pr_debug("perf_evlist__open() failed!\n%s\n", errbuf); 605 pr_debug("perf_evlist__open() failed!\n%s\n", errbuf);
diff --git a/tools/perf/tests/fdarray.c b/tools/perf/tests/fdarray.c
index a2b5ff9bf83d..bc5982f42dc3 100644
--- a/tools/perf/tests/fdarray.c
+++ b/tools/perf/tests/fdarray.c
@@ -19,7 +19,7 @@ static int fdarray__fprintf_prefix(struct fdarray *fda, const char *prefix, FILE
19{ 19{
20 int printed = 0; 20 int printed = 0;
21 21
22 if (!verbose) 22 if (verbose <= 0)
23 return 0; 23 return 0;
24 24
25 printed += fprintf(fp, "\n%s: ", prefix); 25 printed += fprintf(fp, "\n%s: ", prefix);
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index 02a33ebcd992..482b5365e68d 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -13,7 +13,7 @@ static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
13 struct bpf_object *obj; 13 struct bpf_object *obj;
14 14
15 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL); 15 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL);
16 if (IS_ERR(obj)) 16 if (libbpf_get_error(obj))
17 return TEST_FAIL; 17 return TEST_FAIL;
18 bpf_object__close(obj); 18 bpf_object__close(obj);
19 return TEST_OK; 19 return TEST_OK;
@@ -76,7 +76,7 @@ test_llvm__fetch_bpf_obj(void **p_obj_buf,
76 * Skip this test if user's .perfconfig doesn't set [llvm] section 76 * Skip this test if user's .perfconfig doesn't set [llvm] section
77 * and clang is not found in $PATH, and this is not perf test -v 77 * and clang is not found in $PATH, and this is not perf test -v
78 */ 78 */
79 if (!force && (verbose == 0 && 79 if (!force && (verbose <= 0 &&
80 !llvm_param.user_set_param && 80 !llvm_param.user_set_param &&
81 llvm__search_clang())) { 81 llvm__search_clang())) {
82 pr_debug("No clang and no verbosive, skip this test\n"); 82 pr_debug("No clang and no verbosive, skip this test\n");
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 20c2e641c422..1dc838014422 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -1779,15 +1779,14 @@ static int test_pmu_events(void)
1779 } 1779 }
1780 1780
1781 while (!ret && (ent = readdir(dir))) { 1781 while (!ret && (ent = readdir(dir))) {
1782#define MAX_NAME 100
1783 struct evlist_test e; 1782 struct evlist_test e;
1784 char name[MAX_NAME]; 1783 char name[2 * NAME_MAX + 1 + 12 + 3];
1785 1784
1786 /* Names containing . are special and cannot be used directly */ 1785 /* Names containing . are special and cannot be used directly */
1787 if (strchr(ent->d_name, '.')) 1786 if (strchr(ent->d_name, '.'))
1788 continue; 1787 continue;
1789 1788
1790 snprintf(name, MAX_NAME, "cpu/event=%s/u", ent->d_name); 1789 snprintf(name, sizeof(name), "cpu/event=%s/u", ent->d_name);
1791 1790
1792 e.name = name; 1791 e.name = name;
1793 e.check = test__checkevent_pmu_events; 1792 e.check = test__checkevent_pmu_events;
@@ -1795,11 +1794,10 @@ static int test_pmu_events(void)
1795 ret = test_event(&e); 1794 ret = test_event(&e);
1796 if (ret) 1795 if (ret)
1797 break; 1796 break;
1798 snprintf(name, MAX_NAME, "%s:u,cpu/event=%s/u", ent->d_name, ent->d_name); 1797 snprintf(name, sizeof(name), "%s:u,cpu/event=%s/u", ent->d_name, ent->d_name);
1799 e.name = name; 1798 e.name = name;
1800 e.check = test__checkevent_pmu_events_mix; 1799 e.check = test__checkevent_pmu_events_mix;
1801 ret = test_event(&e); 1800 ret = test_event(&e);
1802#undef MAX_NAME
1803 } 1801 }
1804 1802
1805 closedir(dir); 1803 closedir(dir);
@@ -1810,7 +1808,7 @@ static void debug_warn(const char *warn, va_list params)
1810{ 1808{
1811 char msg[1024]; 1809 char msg[1024];
1812 1810
1813 if (!verbose) 1811 if (verbose <= 0)
1814 return; 1812 return;
1815 1813
1816 vsnprintf(msg, sizeof(msg), warn, params); 1814 vsnprintf(msg, sizeof(msg), warn, params);
diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c
index 81c6eeaca0f5..65dcf48a92fb 100644
--- a/tools/perf/tests/parse-no-sample-id-all.c
+++ b/tools/perf/tests/parse-no-sample-id-all.c
@@ -50,7 +50,8 @@ static int process_events(union perf_event **events, size_t count)
50} 50}
51 51
52struct test_attr_event { 52struct test_attr_event {
53 struct attr_event attr; 53 struct perf_event_header header;
54 struct perf_event_attr attr;
54 u64 id; 55 u64 id;
55}; 56};
56 57
@@ -71,20 +72,16 @@ int test__parse_no_sample_id_all(int subtest __maybe_unused)
71 int err; 72 int err;
72 73
73 struct test_attr_event event1 = { 74 struct test_attr_event event1 = {
74 .attr = { 75 .header = {
75 .header = { 76 .type = PERF_RECORD_HEADER_ATTR,
76 .type = PERF_RECORD_HEADER_ATTR, 77 .size = sizeof(struct test_attr_event),
77 .size = sizeof(struct test_attr_event),
78 },
79 }, 78 },
80 .id = 1, 79 .id = 1,
81 }; 80 };
82 struct test_attr_event event2 = { 81 struct test_attr_event event2 = {
83 .attr = { 82 .header = {
84 .header = { 83 .type = PERF_RECORD_HEADER_ATTR,
85 .type = PERF_RECORD_HEADER_ATTR, 84 .size = sizeof(struct test_attr_event),
86 .size = sizeof(struct test_attr_event),
87 },
88 }, 85 },
89 .id = 2, 86 .id = 2,
90 }; 87 };
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 8f2e1de6d0ea..87893f3ba5f1 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -66,7 +66,7 @@ int test__PERF_RECORD(int subtest __maybe_unused)
66 if (evlist == NULL) /* Fallback for kernels lacking PERF_COUNT_SW_DUMMY */ 66 if (evlist == NULL) /* Fallback for kernels lacking PERF_COUNT_SW_DUMMY */
67 evlist = perf_evlist__new_default(); 67 evlist = perf_evlist__new_default();
68 68
69 if (evlist == NULL || argv == NULL) { 69 if (evlist == NULL) {
70 pr_debug("Not enough memory to create evlist\n"); 70 pr_debug("Not enough memory to create evlist\n");
71 goto out; 71 goto out;
72 } 72 }
@@ -172,13 +172,13 @@ int test__PERF_RECORD(int subtest __maybe_unused)
172 172
173 err = perf_evlist__parse_sample(evlist, event, &sample); 173 err = perf_evlist__parse_sample(evlist, event, &sample);
174 if (err < 0) { 174 if (err < 0) {
175 if (verbose) 175 if (verbose > 0)
176 perf_event__fprintf(event, stderr); 176 perf_event__fprintf(event, stderr);
177 pr_debug("Couldn't parse sample\n"); 177 pr_debug("Couldn't parse sample\n");
178 goto out_delete_evlist; 178 goto out_delete_evlist;
179 } 179 }
180 180
181 if (verbose) { 181 if (verbose > 0) {
182 pr_info("%" PRIu64" %d ", sample.time, sample.cpu); 182 pr_info("%" PRIu64" %d ", sample.time, sample.cpu);
183 perf_event__fprintf(event, stderr); 183 perf_event__fprintf(event, stderr);
184 } 184 }
diff --git a/tools/perf/tests/python-use.c b/tools/perf/tests/python-use.c
index 7a52834ee0d0..fa79509da535 100644
--- a/tools/perf/tests/python-use.c
+++ b/tools/perf/tests/python-use.c
@@ -15,7 +15,7 @@ int test__python_use(int subtest __maybe_unused)
15 int ret; 15 int ret;
16 16
17 if (asprintf(&cmd, "echo \"import sys ; sys.path.append('%s'); import perf\" | %s %s", 17 if (asprintf(&cmd, "echo \"import sys ; sys.path.append('%s'); import perf\" | %s %s",
18 PYTHONPATH, PYTHON, verbose ? "" : "2> /dev/null") < 0) 18 PYTHONPATH, PYTHON, verbose > 0 ? "" : "2> /dev/null") < 0)
19 return -1; 19 return -1;
20 20
21 ret = system(cmd) ? -1 : 0; 21 ret = system(cmd) ? -1 : 0;
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index a512f0c8ff5b..1fa9b9d83aa5 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -96,6 +96,7 @@ int test__perf_hooks(int subtest);
96int test__clang(int subtest); 96int test__clang(int subtest);
97const char *test__clang_subtest_get_desc(int subtest); 97const char *test__clang_subtest_get_desc(int subtest);
98int test__clang_subtest_get_nr(void); 98int test__clang_subtest_get_nr(void);
99int test__unit_number__scnprint(int subtest);
99 100
100#if defined(__arm__) || defined(__aarch64__) 101#if defined(__arm__) || defined(__aarch64__)
101#ifdef HAVE_DWARF_UNWIND_SUPPORT 102#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index a4a4b4625ac3..f2d2e542d0ee 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -109,7 +109,7 @@ int test__thread_map_remove(int subtest __maybe_unused)
109 TEST_ASSERT_VAL("failed to allocate thread_map", 109 TEST_ASSERT_VAL("failed to allocate thread_map",
110 threads); 110 threads);
111 111
112 if (verbose) 112 if (verbose > 0)
113 thread_map__fprintf(threads, stderr); 113 thread_map__fprintf(threads, stderr);
114 114
115 TEST_ASSERT_VAL("failed to remove thread", 115 TEST_ASSERT_VAL("failed to remove thread",
@@ -117,7 +117,7 @@ int test__thread_map_remove(int subtest __maybe_unused)
117 117
118 TEST_ASSERT_VAL("thread_map count != 1", threads->nr == 1); 118 TEST_ASSERT_VAL("thread_map count != 1", threads->nr == 1);
119 119
120 if (verbose) 120 if (verbose > 0)
121 thread_map__fprintf(threads, stderr); 121 thread_map__fprintf(threads, stderr);
122 122
123 TEST_ASSERT_VAL("failed to remove thread", 123 TEST_ASSERT_VAL("failed to remove thread",
@@ -125,7 +125,7 @@ int test__thread_map_remove(int subtest __maybe_unused)
125 125
126 TEST_ASSERT_VAL("thread_map count != 0", threads->nr == 0); 126 TEST_ASSERT_VAL("thread_map count != 0", threads->nr == 0);
127 127
128 if (verbose) 128 if (verbose > 0)
129 thread_map__fprintf(threads, stderr); 129 thread_map__fprintf(threads, stderr);
130 130
131 TEST_ASSERT_VAL("failed to not remove thread", 131 TEST_ASSERT_VAL("failed to not remove thread",
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
index 98fe69ac553c..803f893550d6 100644
--- a/tools/perf/tests/topology.c
+++ b/tools/perf/tests/topology.c
@@ -65,7 +65,9 @@ static int check_cpu_topology(char *path, struct cpu_map *map)
65 session = perf_session__new(&file, false, NULL); 65 session = perf_session__new(&file, false, NULL);
66 TEST_ASSERT_VAL("can't get session", session); 66 TEST_ASSERT_VAL("can't get session", session);
67 67
68 for (i = 0; i < session->header.env.nr_cpus_online; i++) { 68 for (i = 0; i < session->header.env.nr_cpus_avail; i++) {
69 if (!cpu_map__has(map, i))
70 continue;
69 pr_debug("CPU %d, core %d, socket %d\n", i, 71 pr_debug("CPU %d, core %d, socket %d\n", i,
70 session->header.env.cpu[i].core_id, 72 session->header.env.cpu[i].core_id,
71 session->header.env.cpu[i].socket_id); 73 session->header.env.cpu[i].socket_id);
diff --git a/tools/perf/tests/unit_number__scnprintf.c b/tools/perf/tests/unit_number__scnprintf.c
new file mode 100644
index 000000000000..623c2aa53c4a
--- /dev/null
+++ b/tools/perf/tests/unit_number__scnprintf.c
@@ -0,0 +1,37 @@
1#include <linux/compiler.h>
2#include <linux/types.h>
3#include "tests.h"
4#include "util.h"
5#include "debug.h"
6
7int test__unit_number__scnprint(int subtest __maybe_unused)
8{
9 struct {
10 u64 n;
11 const char *str;
12 } test[] = {
13 { 1, "1B" },
14 { 10*1024, "10K" },
15 { 20*1024*1024, "20M" },
16 { 30*1024*1024*1024ULL, "30G" },
17 { 0, "0B" },
18 { 0, NULL },
19 };
20 unsigned i = 0;
21
22 while (test[i].str) {
23 char buf[100];
24
25 unit_number__scnprintf(buf, sizeof(buf), test[i].n);
26
27 pr_debug("n %" PRIu64 ", str '%s', buf '%s'\n",
28 test[i].n, test[i].str, buf);
29
30 if (strcmp(test[i].str, buf))
31 return TEST_FAIL;
32
33 i++;
34 }
35
36 return TEST_OK;
37}
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index a5082331f246..862b043e5924 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -168,7 +168,7 @@ next_pair:
168 err = -1; 168 err = -1;
169 } 169 }
170 170
171 if (!verbose) 171 if (verbose <= 0)
172 goto out; 172 goto out;
173 173
174 header_printed = false; 174 header_printed = false;
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 641b40234a9d..fc4fb669ceee 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -501,8 +501,8 @@ static int hierarchy_set_folding(struct hist_browser *hb, struct hist_entry *he,
501 return n; 501 return n;
502} 502}
503 503
504static void hist_entry__set_folding(struct hist_entry *he, 504static void __hist_entry__set_folding(struct hist_entry *he,
505 struct hist_browser *hb, bool unfold) 505 struct hist_browser *hb, bool unfold)
506{ 506{
507 hist_entry__init_have_children(he); 507 hist_entry__init_have_children(he);
508 he->unfolded = unfold ? he->has_children : false; 508 he->unfolded = unfold ? he->has_children : false;
@@ -520,12 +520,34 @@ static void hist_entry__set_folding(struct hist_entry *he,
520 he->nr_rows = 0; 520 he->nr_rows = 0;
521} 521}
522 522
523static void hist_entry__set_folding(struct hist_entry *he,
524 struct hist_browser *browser, bool unfold)
525{
526 double percent;
527
528 percent = hist_entry__get_percent_limit(he);
529 if (he->filtered || percent < browser->min_pcnt)
530 return;
531
532 __hist_entry__set_folding(he, browser, unfold);
533
534 if (!he->depth || unfold)
535 browser->nr_hierarchy_entries++;
536 if (he->leaf)
537 browser->nr_callchain_rows += he->nr_rows;
538 else if (unfold && !hist_entry__has_hierarchy_children(he, browser->min_pcnt)) {
539 browser->nr_hierarchy_entries++;
540 he->has_no_entry = true;
541 he->nr_rows = 1;
542 } else
543 he->has_no_entry = false;
544}
545
523static void 546static void
524__hist_browser__set_folding(struct hist_browser *browser, bool unfold) 547__hist_browser__set_folding(struct hist_browser *browser, bool unfold)
525{ 548{
526 struct rb_node *nd; 549 struct rb_node *nd;
527 struct hist_entry *he; 550 struct hist_entry *he;
528 double percent;
529 551
530 nd = rb_first(&browser->hists->entries); 552 nd = rb_first(&browser->hists->entries);
531 while (nd) { 553 while (nd) {
@@ -535,21 +557,6 @@ __hist_browser__set_folding(struct hist_browser *browser, bool unfold)
535 nd = __rb_hierarchy_next(nd, HMD_FORCE_CHILD); 557 nd = __rb_hierarchy_next(nd, HMD_FORCE_CHILD);
536 558
537 hist_entry__set_folding(he, browser, unfold); 559 hist_entry__set_folding(he, browser, unfold);
538
539 percent = hist_entry__get_percent_limit(he);
540 if (he->filtered || percent < browser->min_pcnt)
541 continue;
542
543 if (!he->depth || unfold)
544 browser->nr_hierarchy_entries++;
545 if (he->leaf)
546 browser->nr_callchain_rows += he->nr_rows;
547 else if (unfold && !hist_entry__has_hierarchy_children(he, browser->min_pcnt)) {
548 browser->nr_hierarchy_entries++;
549 he->has_no_entry = true;
550 he->nr_rows = 1;
551 } else
552 he->has_no_entry = false;
553 } 560 }
554} 561}
555 562
@@ -564,6 +571,15 @@ static void hist_browser__set_folding(struct hist_browser *browser, bool unfold)
564 ui_browser__reset_index(&browser->b); 571 ui_browser__reset_index(&browser->b);
565} 572}
566 573
574static void hist_browser__set_folding_selected(struct hist_browser *browser, bool unfold)
575{
576 if (!browser->he_selection)
577 return;
578
579 hist_entry__set_folding(browser->he_selection, browser, unfold);
580 browser->b.nr_entries = hist_browser__nr_entries(browser);
581}
582
567static void ui_browser__warn_lost_events(struct ui_browser *browser) 583static void ui_browser__warn_lost_events(struct ui_browser *browser)
568{ 584{
569 ui_browser__warning(browser, 4, 585 ui_browser__warning(browser, 4,
@@ -637,10 +653,18 @@ int hist_browser__run(struct hist_browser *browser, const char *help)
637 /* Collapse the whole world. */ 653 /* Collapse the whole world. */
638 hist_browser__set_folding(browser, false); 654 hist_browser__set_folding(browser, false);
639 break; 655 break;
656 case 'c':
657 /* Collapse the selected entry. */
658 hist_browser__set_folding_selected(browser, false);
659 break;
640 case 'E': 660 case 'E':
641 /* Expand the whole world. */ 661 /* Expand the whole world. */
642 hist_browser__set_folding(browser, true); 662 hist_browser__set_folding(browser, true);
643 break; 663 break;
664 case 'e':
665 /* Expand the selected entry. */
666 hist_browser__set_folding_selected(browser, true);
667 break;
644 case 'H': 668 case 'H':
645 browser->show_headers = !browser->show_headers; 669 browser->show_headers = !browser->show_headers;
646 hist_browser__update_rows(browser); 670 hist_browser__update_rows(browser);
diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c
index 98a34664bb7e..9ce142de536d 100644
--- a/tools/perf/ui/browsers/map.c
+++ b/tools/perf/ui/browsers/map.c
@@ -73,7 +73,7 @@ static int map_browser__run(struct map_browser *browser)
73 73
74 if (ui_browser__show(&browser->b, browser->map->dso->long_name, 74 if (ui_browser__show(&browser->b, browser->map->dso->long_name,
75 "Press ESC to exit, %s / to search", 75 "Press ESC to exit, %s / to search",
76 verbose ? "" : "restart with -v to use") < 0) 76 verbose > 0 ? "" : "restart with -v to use") < 0)
77 return -1; 77 return -1;
78 78
79 while (1) { 79 while (1) {
@@ -81,7 +81,7 @@ static int map_browser__run(struct map_browser *browser)
81 81
82 switch (key) { 82 switch (key) {
83 case '/': 83 case '/':
84 if (verbose) 84 if (verbose > 0)
85 map_browser__search(browser); 85 map_browser__search(browser);
86 default: 86 default:
87 break; 87 break;
@@ -117,7 +117,7 @@ int map__browse(struct map *map)
117 117
118 if (maxaddr < pos->end) 118 if (maxaddr < pos->end)
119 maxaddr = pos->end; 119 maxaddr = pos->end;
120 if (verbose) { 120 if (verbose > 0) {
121 u32 *idx = symbol__browser_index(pos); 121 u32 *idx = symbol__browser_index(pos);
122 *idx = mb.b.nr_entries; 122 *idx = mb.b.nr_entries;
123 } 123 }
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 18cfcdc90356..5d632dca672a 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -648,7 +648,7 @@ unsigned int hists__sort_list_width(struct hists *hists)
648 ret += fmt->width(fmt, &dummy_hpp, hists); 648 ret += fmt->width(fmt, &dummy_hpp, hists);
649 } 649 }
650 650
651 if (verbose && hists__has(hists, sym)) /* Addr + origin */ 651 if (verbose > 0 && hists__has(hists, sym)) /* Addr + origin */
652 ret += 3 + BITS_PER_LONG / 4; 652 ret += 3 + BITS_PER_LONG / 4;
653 653
654 return ret; 654 return ret;
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index 1f6b0994f4f4..50d13e58210f 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -7,6 +7,7 @@
7 7
8pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; 8pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
9void *perf_gtk_handle; 9void *perf_gtk_handle;
10int use_browser = -1;
10 11
11#ifdef HAVE_GTK2_SUPPORT 12#ifdef HAVE_GTK2_SUPPORT
12static int setup_gtk_browser(void) 13static int setup_gtk_browser(void)
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 3840e3a87057..5da376bc1afc 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -162,6 +162,7 @@ CFLAGS_rbtree.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ET
162CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 162CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
163CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 163CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
164CFLAGS_parse-events.o += -Wno-redundant-decls 164CFLAGS_parse-events.o += -Wno-redundant-decls
165CFLAGS_header.o += -include $(OUTPUT)PERF-VERSION-FILE
165 166
166$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE 167$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE
167 $(call rule_mkdir) 168 $(call rule_mkdir)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 06cc04e5806a..273f21fa32b5 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1768,7 +1768,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1768 printf("%-*.*s----\n", 1768 printf("%-*.*s----\n",
1769 graph_dotted_len, graph_dotted_len, graph_dotted_line); 1769 graph_dotted_len, graph_dotted_len, graph_dotted_line);
1770 1770
1771 if (verbose) 1771 if (verbose > 0)
1772 symbol__annotate_hits(sym, evsel); 1772 symbol__annotate_hits(sym, evsel);
1773 1773
1774 list_for_each_entry(pos, &notes->src->source, node) { 1774 list_for_each_entry(pos, &notes->src->source, node) {
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 36c861103291..bc6bc7062eb4 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -670,13 +670,13 @@ int bpf__probe(struct bpf_object *obj)
670 670
671 err = convert_perf_probe_events(pev, 1); 671 err = convert_perf_probe_events(pev, 1);
672 if (err < 0) { 672 if (err < 0) {
673 pr_debug("bpf_probe: failed to convert perf probe events"); 673 pr_debug("bpf_probe: failed to convert perf probe events\n");
674 goto out; 674 goto out;
675 } 675 }
676 676
677 err = apply_perf_probe_events(pev, 1); 677 err = apply_perf_probe_events(pev, 1);
678 if (err < 0) { 678 if (err < 0) {
679 pr_debug("bpf_probe: failed to apply perf probe events"); 679 pr_debug("bpf_probe: failed to apply perf probe events\n");
680 goto out; 680 goto out;
681 } 681 }
682 682
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 8b610dd9e2f6..aba953421a03 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -48,6 +48,8 @@ static int parse_callchain_mode(const char *value)
48 callchain_param.mode = CHAIN_FOLDED; 48 callchain_param.mode = CHAIN_FOLDED;
49 return 0; 49 return 0;
50 } 50 }
51
52 pr_err("Invalid callchain mode: %s\n", value);
51 return -1; 53 return -1;
52} 54}
53 55
@@ -63,6 +65,8 @@ static int parse_callchain_order(const char *value)
63 callchain_param.order_set = true; 65 callchain_param.order_set = true;
64 return 0; 66 return 0;
65 } 67 }
68
69 pr_err("Invalid callchain order: %s\n", value);
66 return -1; 70 return -1;
67} 71}
68 72
@@ -80,6 +84,8 @@ static int parse_callchain_sort_key(const char *value)
80 callchain_param.branch_callstack = 1; 84 callchain_param.branch_callstack = 1;
81 return 0; 85 return 0;
82 } 86 }
87
88 pr_err("Invalid callchain sort key: %s\n", value);
83 return -1; 89 return -1;
84} 90}
85 91
@@ -97,6 +103,8 @@ static int parse_callchain_value(const char *value)
97 callchain_param.value = CCVAL_COUNT; 103 callchain_param.value = CCVAL_COUNT;
98 return 0; 104 return 0;
99 } 105 }
106
107 pr_err("Invalid callchain config key: %s\n", value);
100 return -1; 108 return -1;
101} 109}
102 110
@@ -210,13 +218,17 @@ int perf_callchain_config(const char *var, const char *value)
210 return parse_callchain_sort_key(value); 218 return parse_callchain_sort_key(value);
211 if (!strcmp(var, "threshold")) { 219 if (!strcmp(var, "threshold")) {
212 callchain_param.min_percent = strtod(value, &endptr); 220 callchain_param.min_percent = strtod(value, &endptr);
213 if (value == endptr) 221 if (value == endptr) {
222 pr_err("Invalid callchain threshold: %s\n", value);
214 return -1; 223 return -1;
224 }
215 } 225 }
216 if (!strcmp(var, "print-limit")) { 226 if (!strcmp(var, "print-limit")) {
217 callchain_param.print_limit = strtod(value, &endptr); 227 callchain_param.print_limit = strtod(value, &endptr);
218 if (value == endptr) 228 if (value == endptr) {
229 pr_err("Invalid callchain print limit: %s\n", value);
219 return -1; 230 return -1;
231 }
220 } 232 }
221 233
222 return 0; 234 return 0;
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 8fdee24725a7..eafbf11442b2 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -12,8 +12,8 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
12{ 12{
13 FILE *fp; 13 FILE *fp;
14 char mountpoint[PATH_MAX + 1], tokens[PATH_MAX + 1], type[PATH_MAX + 1]; 14 char mountpoint[PATH_MAX + 1], tokens[PATH_MAX + 1], type[PATH_MAX + 1];
15 char path_v1[PATH_MAX + 1], path_v2[PATH_MAX + 2], *path;
15 char *token, *saved_ptr = NULL; 16 char *token, *saved_ptr = NULL;
16 int found = 0;
17 17
18 fp = fopen("/proc/mounts", "r"); 18 fp = fopen("/proc/mounts", "r");
19 if (!fp) 19 if (!fp)
@@ -24,31 +24,43 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
24 * and inspect every cgroupfs mount point to find one that has 24 * and inspect every cgroupfs mount point to find one that has
25 * perf_event subsystem 25 * perf_event subsystem
26 */ 26 */
27 path_v1[0] = '\0';
28 path_v2[0] = '\0';
29
27 while (fscanf(fp, "%*s %"STR(PATH_MAX)"s %"STR(PATH_MAX)"s %" 30 while (fscanf(fp, "%*s %"STR(PATH_MAX)"s %"STR(PATH_MAX)"s %"
28 STR(PATH_MAX)"s %*d %*d\n", 31 STR(PATH_MAX)"s %*d %*d\n",
29 mountpoint, type, tokens) == 3) { 32 mountpoint, type, tokens) == 3) {
30 33
31 if (!strcmp(type, "cgroup")) { 34 if (!path_v1[0] && !strcmp(type, "cgroup")) {
32 35
33 token = strtok_r(tokens, ",", &saved_ptr); 36 token = strtok_r(tokens, ",", &saved_ptr);
34 37
35 while (token != NULL) { 38 while (token != NULL) {
36 if (!strcmp(token, "perf_event")) { 39 if (!strcmp(token, "perf_event")) {
37 found = 1; 40 strcpy(path_v1, mountpoint);
38 break; 41 break;
39 } 42 }
40 token = strtok_r(NULL, ",", &saved_ptr); 43 token = strtok_r(NULL, ",", &saved_ptr);
41 } 44 }
42 } 45 }
43 if (found) 46
47 if (!path_v2[0] && !strcmp(type, "cgroup2"))
48 strcpy(path_v2, mountpoint);
49
50 if (path_v1[0] && path_v2[0])
44 break; 51 break;
45 } 52 }
46 fclose(fp); 53 fclose(fp);
47 if (!found) 54
55 if (path_v1[0])
56 path = path_v1;
57 else if (path_v2[0])
58 path = path_v2;
59 else
48 return -1; 60 return -1;
49 61
50 if (strlen(mountpoint) < maxlen) { 62 if (strlen(path) < maxlen) {
51 strcpy(buf, mountpoint); 63 strcpy(buf, path);
52 return 0; 64 return 0;
53 } 65 }
54 return -1; 66 return -1;
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 3d906dbbef74..0c7d5a4975cd 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -386,8 +386,10 @@ static int perf_buildid_config(const char *var, const char *value)
386 if (!strcmp(var, "buildid.dir")) { 386 if (!strcmp(var, "buildid.dir")) {
387 const char *dir = perf_config_dirname(var, value); 387 const char *dir = perf_config_dirname(var, value);
388 388
389 if (!dir) 389 if (!dir) {
390 pr_err("Invalid buildid directory!\n");
390 return -1; 391 return -1;
392 }
391 strncpy(buildid_dir, dir, MAXPATHLEN-1); 393 strncpy(buildid_dir, dir, MAXPATHLEN-1);
392 buildid_dir[MAXPATHLEN-1] = '\0'; 394 buildid_dir[MAXPATHLEN-1] = '\0';
393 } 395 }
@@ -405,10 +407,9 @@ static int perf_default_core_config(const char *var __maybe_unused,
405static int perf_ui_config(const char *var, const char *value) 407static int perf_ui_config(const char *var, const char *value)
406{ 408{
407 /* Add other config variables here. */ 409 /* Add other config variables here. */
408 if (!strcmp(var, "ui.show-headers")) { 410 if (!strcmp(var, "ui.show-headers"))
409 symbol_conf.show_hist_headers = perf_config_bool(var, value); 411 symbol_conf.show_hist_headers = perf_config_bool(var, value);
410 return 0; 412
411 }
412 return 0; 413 return 0;
413} 414}
414 415
@@ -646,8 +647,13 @@ static int perf_config_set__init(struct perf_config_set *set)
646 goto out; 647 goto out;
647 } 648 }
648 649
649 if (stat(user_config, &st) < 0) 650 if (stat(user_config, &st) < 0) {
651 if (errno == ENOENT)
652 ret = 0;
650 goto out_free; 653 goto out_free;
654 }
655
656 ret = 0;
651 657
652 if (st.st_uid && (st.st_uid != geteuid())) { 658 if (st.st_uid && (st.st_uid != geteuid())) {
653 warning("File %s not owned by current user or root, " 659 warning("File %s not owned by current user or root, "
@@ -655,11 +661,8 @@ static int perf_config_set__init(struct perf_config_set *set)
655 goto out_free; 661 goto out_free;
656 } 662 }
657 663
658 if (!st.st_size) 664 if (st.st_size)
659 goto out_free; 665 ret = perf_config_from_file(collect_config, user_config, set);
660
661 ret = perf_config_from_file(collect_config, user_config, set);
662
663out_free: 666out_free:
664 free(user_config); 667 free(user_config);
665 } 668 }
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 2c0b52264a46..8c7504939113 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -9,6 +9,7 @@
9#include "asm/bug.h" 9#include "asm/bug.h"
10 10
11static int max_cpu_num; 11static int max_cpu_num;
12static int max_present_cpu_num;
12static int max_node_num; 13static int max_node_num;
13static int *cpunode_map; 14static int *cpunode_map;
14 15
@@ -442,6 +443,7 @@ static void set_max_cpu_num(void)
442 443
443 /* set up default */ 444 /* set up default */
444 max_cpu_num = 4096; 445 max_cpu_num = 4096;
446 max_present_cpu_num = 4096;
445 447
446 mnt = sysfs__mountpoint(); 448 mnt = sysfs__mountpoint();
447 if (!mnt) 449 if (!mnt)
@@ -455,6 +457,17 @@ static void set_max_cpu_num(void)
455 } 457 }
456 458
457 ret = get_max_num(path, &max_cpu_num); 459 ret = get_max_num(path, &max_cpu_num);
460 if (ret)
461 goto out;
462
463 /* get the highest present cpu number for a sparse allocation */
464 ret = snprintf(path, PATH_MAX, "%s/devices/system/cpu/present", mnt);
465 if (ret == PATH_MAX) {
466 pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX);
467 goto out;
468 }
469
470 ret = get_max_num(path, &max_present_cpu_num);
458 471
459out: 472out:
460 if (ret) 473 if (ret)
@@ -505,6 +518,15 @@ int cpu__max_cpu(void)
505 return max_cpu_num; 518 return max_cpu_num;
506} 519}
507 520
521int cpu__max_present_cpu(void)
522{
523 if (unlikely(!max_present_cpu_num))
524 set_max_cpu_num();
525
526 return max_present_cpu_num;
527}
528
529
508int cpu__get_node(int cpu) 530int cpu__get_node(int cpu)
509{ 531{
510 if (unlikely(cpunode_map == NULL)) { 532 if (unlikely(cpunode_map == NULL)) {
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 06bd689f5989..1a0549af8f5c 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -62,6 +62,7 @@ int cpu__setup_cpunode_map(void);
62 62
63int cpu__max_node(void); 63int cpu__max_node(void);
64int cpu__max_cpu(void); 64int cpu__max_cpu(void);
65int cpu__max_present_cpu(void);
65int cpu__get_node(int cpu); 66int cpu__get_node(int cpu);
66 67
67int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, 68int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 7123f4de32cc..4e6cbc99f08e 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -1473,7 +1473,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1473 }, 1473 },
1474 }; 1474 };
1475 struct ctf_writer *cw = &c.writer; 1475 struct ctf_writer *cw = &c.writer;
1476 int err = -1; 1476 int err;
1477 1477
1478 if (opts->all) { 1478 if (opts->all) {
1479 c.tool.comm = process_comm_event; 1479 c.tool.comm = process_comm_event;
@@ -1481,12 +1481,15 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1481 c.tool.fork = process_fork_event; 1481 c.tool.fork = process_fork_event;
1482 } 1482 }
1483 1483
1484 perf_config(convert__config, &c); 1484 err = perf_config(convert__config, &c);
1485 if (err)
1486 return err;
1485 1487
1486 /* CTF writer */ 1488 /* CTF writer */
1487 if (ctf_writer__init(cw, path)) 1489 if (ctf_writer__init(cw, path))
1488 return -1; 1490 return -1;
1489 1491
1492 err = -1;
1490 /* perf.data session */ 1493 /* perf.data session */
1491 session = perf_session__new(&file, 0, &c.tool); 1494 session = perf_session__new(&file, 0, &c.tool);
1492 if (!session) 1495 if (!session)
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index c1838b643108..03eb81f30d0d 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -203,11 +203,28 @@ int perf_debug_option(const char *str)
203 v = (v < 0) || (v > 10) ? 0 : v; 203 v = (v < 0) || (v > 10) ? 0 : v;
204 } 204 }
205 205
206 if (quiet)
207 v = -1;
208
206 *var->ptr = v; 209 *var->ptr = v;
207 free(s); 210 free(s);
208 return 0; 211 return 0;
209} 212}
210 213
214int perf_quiet_option(void)
215{
216 struct debug_variable *var = &debug_variables[0];
217
218 /* disable all debug messages */
219 while (var->name) {
220 *var->ptr = -1;
221 var++;
222 }
223
224 quiet = true;
225 return 0;
226}
227
211#define DEBUG_WRAPPER(__n, __l) \ 228#define DEBUG_WRAPPER(__n, __l) \
212static int pr_ ## __n ## _wrapper(const char *fmt, ...) \ 229static int pr_ ## __n ## _wrapper(const char *fmt, ...) \
213{ \ 230{ \
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index d242adc3d5a2..98832f5531d3 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -54,5 +54,6 @@ int veprintf(int level, int var, const char *fmt, va_list args);
54 54
55int perf_debug_option(const char *str); 55int perf_debug_option(const char *str);
56void perf_debug_setup(void); 56void perf_debug_setup(void);
57int perf_quiet_option(void);
57 58
58#endif /* __PERF_DEBUG_H */ 59#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index d2c6cdd9d42b..d38b62a700ca 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -9,6 +9,13 @@
9#include "debug.h" 9#include "debug.h"
10#include "vdso.h" 10#include "vdso.h"
11 11
12static const char * const debuglink_paths[] = {
13 "%.0s%s",
14 "%s/%s",
15 "%s/.debug/%s",
16 "/usr/lib/debug%s/%s"
17};
18
12char dso__symtab_origin(const struct dso *dso) 19char dso__symtab_origin(const struct dso *dso)
13{ 20{
14 static const char origin[] = { 21 static const char origin[] = {
@@ -44,24 +51,43 @@ int dso__read_binary_type_filename(const struct dso *dso,
44 size_t len; 51 size_t len;
45 52
46 switch (type) { 53 switch (type) {
47 case DSO_BINARY_TYPE__DEBUGLINK: { 54 case DSO_BINARY_TYPE__DEBUGLINK:
48 char *debuglink; 55 {
56 const char *last_slash;
57 char dso_dir[PATH_MAX];
58 char symfile[PATH_MAX];
59 unsigned int i;
49 60
50 len = __symbol__join_symfs(filename, size, dso->long_name); 61 len = __symbol__join_symfs(filename, size, dso->long_name);
51 debuglink = filename + len; 62 last_slash = filename + len;
52 while (debuglink != filename && *debuglink != '/') 63 while (last_slash != filename && *last_slash != '/')
53 debuglink--; 64 last_slash--;
54 if (*debuglink == '/')
55 debuglink++;
56 65
57 ret = -1; 66 strncpy(dso_dir, filename, last_slash - filename);
58 if (!is_regular_file(filename)) 67 dso_dir[last_slash-filename] = '\0';
68
69 if (!is_regular_file(filename)) {
70 ret = -1;
71 break;
72 }
73
74 ret = filename__read_debuglink(filename, symfile, PATH_MAX);
75 if (ret)
59 break; 76 break;
60 77
61 ret = filename__read_debuglink(filename, debuglink, 78 /* Check predefined locations where debug file might reside */
62 size - (debuglink - filename)); 79 ret = -1;
80 for (i = 0; i < ARRAY_SIZE(debuglink_paths); i++) {
81 snprintf(filename, size,
82 debuglink_paths[i], dso_dir, symfile);
83 if (is_regular_file(filename)) {
84 ret = 0;
85 break;
86 }
63 } 87 }
88
64 break; 89 break;
90 }
65 case DSO_BINARY_TYPE__BUILD_ID_CACHE: 91 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
66 if (dso__build_id_filename(dso, filename, size) == NULL) 92 if (dso__build_id_filename(dso, filename, size) == NULL)
67 ret = -1; 93 ret = -1;
@@ -925,7 +951,7 @@ static struct dso *__dso__findlink_by_longname(struct rb_root *root,
925 if (rc == 0) { 951 if (rc == 0) {
926 /* 952 /*
927 * In case the new DSO is a duplicate of an existing 953 * In case the new DSO is a duplicate of an existing
928 * one, print an one-time warning & put the new entry 954 * one, print a one-time warning & put the new entry
929 * at the end of the list of duplicates. 955 * at the end of the list of duplicates.
930 */ 956 */
931 if (!dso || (dso == this)) 957 if (!dso || (dso == this))
@@ -1032,7 +1058,7 @@ int dso__name_len(const struct dso *dso)
1032{ 1058{
1033 if (!dso) 1059 if (!dso)
1034 return strlen("[unknown]"); 1060 return strlen("[unknown]");
1035 if (verbose) 1061 if (verbose > 0)
1036 return dso->long_name_len; 1062 return dso->long_name_len;
1037 1063
1038 return dso->short_name_len; 1064 return dso->short_name_len;
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index bb964e86b09d..075fc77286bf 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -66,7 +66,7 @@ int perf_env__read_cpu_topology_map(struct perf_env *env)
66 return 0; 66 return 0;
67 67
68 if (env->nr_cpus_avail == 0) 68 if (env->nr_cpus_avail == 0)
69 env->nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF); 69 env->nr_cpus_avail = cpu__max_present_cpu();
70 70
71 nr_cpus = env->nr_cpus_avail; 71 nr_cpus = env->nr_cpus_avail;
72 if (nr_cpus == -1) 72 if (nr_cpus == -1)
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 8ab0d7da956b..4ea7ce72ed9c 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,5 +1,5 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */ 2#include <linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
3#include <api/fs/fs.h> 3#include <api/fs/fs.h>
4#include "event.h" 4#include "event.h"
5#include "debug.h" 5#include "debug.h"
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index d92e02006fb8..b601f2814a30 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1184,7 +1184,7 @@ unsigned long perf_event_mlock_kb_in_pages(void)
1184 return pages; 1184 return pages;
1185} 1185}
1186 1186
1187static size_t perf_evlist__mmap_size(unsigned long pages) 1187size_t perf_evlist__mmap_size(unsigned long pages)
1188{ 1188{
1189 if (pages == UINT_MAX) 1189 if (pages == UINT_MAX)
1190 pages = perf_event_mlock_kb_in_pages(); 1190 pages = perf_event_mlock_kb_in_pages();
@@ -1224,12 +1224,16 @@ static long parse_pages_arg(const char *str, unsigned long min,
1224 if (pages == 0 && min == 0) { 1224 if (pages == 0 && min == 0) {
1225 /* leave number of pages at 0 */ 1225 /* leave number of pages at 0 */
1226 } else if (!is_power_of_2(pages)) { 1226 } else if (!is_power_of_2(pages)) {
1227 char buf[100];
1228
1227 /* round pages up to next power of 2 */ 1229 /* round pages up to next power of 2 */
1228 pages = roundup_pow_of_two(pages); 1230 pages = roundup_pow_of_two(pages);
1229 if (!pages) 1231 if (!pages)
1230 return -EINVAL; 1232 return -EINVAL;
1231 pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", 1233
1232 pages * page_size, pages); 1234 unit_number__scnprintf(buf, sizeof(buf), pages * page_size);
1235 pr_info("rounding mmap pages size to %s (%lu pages)\n",
1236 buf, pages);
1233 } 1237 }
1234 1238
1235 if (pages > max) 1239 if (pages > max)
@@ -1797,7 +1801,7 @@ int perf_evlist__start_workload(struct perf_evlist *evlist)
1797 */ 1801 */
1798 ret = write(evlist->workload.cork_fd, &bf, 1); 1802 ret = write(evlist->workload.cork_fd, &bf, 1);
1799 if (ret < 0) 1803 if (ret < 0)
1800 perror("enable to write to pipe"); 1804 perror("unable to write to pipe");
1801 1805
1802 close(evlist->workload.cork_fd); 1806 close(evlist->workload.cork_fd);
1803 return ret; 1807 return ret;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 4fd034f22d2f..389b9ccdf8c7 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -218,6 +218,8 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
218 bool overwrite); 218 bool overwrite);
219void perf_evlist__munmap(struct perf_evlist *evlist); 219void perf_evlist__munmap(struct perf_evlist *evlist);
220 220
221size_t perf_evlist__mmap_size(unsigned long pages);
222
221void perf_evlist__disable(struct perf_evlist *evlist); 223void perf_evlist__disable(struct perf_evlist *evlist);
222void perf_evlist__enable(struct perf_evlist *evlist); 224void perf_evlist__enable(struct perf_evlist *evlist);
223void perf_evlist__toggle_enable(struct perf_evlist *evlist); 225void perf_evlist__toggle_enable(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 04e536ae4d88..ac59710b79e0 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1448,8 +1448,8 @@ static bool ignore_missing_thread(struct perf_evsel *evsel,
1448 return true; 1448 return true;
1449} 1449}
1450 1450
1451static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1451int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1452 struct thread_map *threads) 1452 struct thread_map *threads)
1453{ 1453{
1454 int cpu, thread, nthreads; 1454 int cpu, thread, nthreads;
1455 unsigned long flags = PERF_FLAG_FD_CLOEXEC; 1455 unsigned long flags = PERF_FLAG_FD_CLOEXEC;
@@ -1459,6 +1459,30 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1459 if (perf_missing_features.write_backward && evsel->attr.write_backward) 1459 if (perf_missing_features.write_backward && evsel->attr.write_backward)
1460 return -EINVAL; 1460 return -EINVAL;
1461 1461
1462 if (cpus == NULL) {
1463 static struct cpu_map *empty_cpu_map;
1464
1465 if (empty_cpu_map == NULL) {
1466 empty_cpu_map = cpu_map__dummy_new();
1467 if (empty_cpu_map == NULL)
1468 return -ENOMEM;
1469 }
1470
1471 cpus = empty_cpu_map;
1472 }
1473
1474 if (threads == NULL) {
1475 static struct thread_map *empty_thread_map;
1476
1477 if (empty_thread_map == NULL) {
1478 empty_thread_map = thread_map__new_by_tid(-1);
1479 if (empty_thread_map == NULL)
1480 return -ENOMEM;
1481 }
1482
1483 threads = empty_thread_map;
1484 }
1485
1462 if (evsel->system_wide) 1486 if (evsel->system_wide)
1463 nthreads = 1; 1487 nthreads = 1;
1464 else 1488 else
@@ -1655,46 +1679,16 @@ void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads)
1655 perf_evsel__free_fd(evsel); 1679 perf_evsel__free_fd(evsel);
1656} 1680}
1657 1681
1658static struct {
1659 struct cpu_map map;
1660 int cpus[1];
1661} empty_cpu_map = {
1662 .map.nr = 1,
1663 .cpus = { -1, },
1664};
1665
1666static struct {
1667 struct thread_map map;
1668 int threads[1];
1669} empty_thread_map = {
1670 .map.nr = 1,
1671 .threads = { -1, },
1672};
1673
1674int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1675 struct thread_map *threads)
1676{
1677 if (cpus == NULL) {
1678 /* Work around old compiler warnings about strict aliasing */
1679 cpus = &empty_cpu_map.map;
1680 }
1681
1682 if (threads == NULL)
1683 threads = &empty_thread_map.map;
1684
1685 return __perf_evsel__open(evsel, cpus, threads);
1686}
1687
1688int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 1682int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
1689 struct cpu_map *cpus) 1683 struct cpu_map *cpus)
1690{ 1684{
1691 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map); 1685 return perf_evsel__open(evsel, cpus, NULL);
1692} 1686}
1693 1687
1694int perf_evsel__open_per_thread(struct perf_evsel *evsel, 1688int perf_evsel__open_per_thread(struct perf_evsel *evsel,
1695 struct thread_map *threads) 1689 struct thread_map *threads)
1696{ 1690{
1697 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads); 1691 return perf_evsel__open(evsel, NULL, threads);
1698} 1692}
1699 1693
1700static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel, 1694static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel,
@@ -2469,7 +2463,9 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2469 " -1: Allow use of (almost) all events by all users\n" 2463 " -1: Allow use of (almost) all events by all users\n"
2470 ">= 0: Disallow raw tracepoint access by users without CAP_IOC_LOCK\n" 2464 ">= 0: Disallow raw tracepoint access by users without CAP_IOC_LOCK\n"
2471 ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n" 2465 ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n"
2472 ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN", 2466 ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN\n\n"
2467 "To make this setting permanent, edit /etc/sysctl.conf too, e.g.:\n\n"
2468 " kernel.perf_event_paranoid = -1\n" ,
2473 target->system_wide ? "system-wide " : "", 2469 target->system_wide ? "system-wide " : "",
2474 perf_event_paranoid()); 2470 perf_event_paranoid());
2475 case ENOENT: 2471 case ENOENT:
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 6b2925542c0a..4ef5184819a0 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -168,7 +168,6 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
168 168
169 if (symbol_conf.bt_stop_list && 169 if (symbol_conf.bt_stop_list &&
170 node->sym && 170 node->sym &&
171 node->sym->name &&
172 strlist__has_entry(symbol_conf.bt_stop_list, 171 strlist__has_entry(symbol_conf.bt_stop_list,
173 node->sym->name)) { 172 node->sym->name)) {
174 break; 173 break;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index d89c9c7ef4e5..05714d548584 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -41,6 +41,8 @@ static const u64 __perf_magic2_sw = 0x50455246494c4532ULL;
41 41
42#define PERF_MAGIC __perf_magic2 42#define PERF_MAGIC __perf_magic2
43 43
44const char perf_version_string[] = PERF_VERSION;
45
44struct perf_file_attr { 46struct perf_file_attr {
45 struct perf_event_attr attr; 47 struct perf_event_attr attr;
46 struct perf_file_section ids; 48 struct perf_file_section ids;
@@ -293,11 +295,7 @@ static int write_nrcpus(int fd, struct perf_header *h __maybe_unused,
293 u32 nrc, nra; 295 u32 nrc, nra;
294 int ret; 296 int ret;
295 297
296 nr = sysconf(_SC_NPROCESSORS_CONF); 298 nrc = cpu__max_present_cpu();
297 if (nr < 0)
298 return -1;
299
300 nrc = (u32)(nr & UINT_MAX);
301 299
302 nr = sysconf(_SC_NPROCESSORS_ONLN); 300 nr = sysconf(_SC_NPROCESSORS_ONLN);
303 if (nr < 0) 301 if (nr < 0)
@@ -503,24 +501,29 @@ static void free_cpu_topo(struct cpu_topo *tp)
503 501
504static struct cpu_topo *build_cpu_topology(void) 502static struct cpu_topo *build_cpu_topology(void)
505{ 503{
506 struct cpu_topo *tp; 504 struct cpu_topo *tp = NULL;
507 void *addr; 505 void *addr;
508 u32 nr, i; 506 u32 nr, i;
509 size_t sz; 507 size_t sz;
510 long ncpus; 508 long ncpus;
511 int ret = -1; 509 int ret = -1;
510 struct cpu_map *map;
512 511
513 ncpus = sysconf(_SC_NPROCESSORS_CONF); 512 ncpus = cpu__max_present_cpu();
514 if (ncpus < 0) 513
514 /* build online CPU map */
515 map = cpu_map__new(NULL);
516 if (map == NULL) {
517 pr_debug("failed to get system cpumap\n");
515 return NULL; 518 return NULL;
519 }
516 520
517 nr = (u32)(ncpus & UINT_MAX); 521 nr = (u32)(ncpus & UINT_MAX);
518 522
519 sz = nr * sizeof(char *); 523 sz = nr * sizeof(char *);
520
521 addr = calloc(1, sizeof(*tp) + 2 * sz); 524 addr = calloc(1, sizeof(*tp) + 2 * sz);
522 if (!addr) 525 if (!addr)
523 return NULL; 526 goto out_free;
524 527
525 tp = addr; 528 tp = addr;
526 tp->cpu_nr = nr; 529 tp->cpu_nr = nr;
@@ -530,10 +533,16 @@ static struct cpu_topo *build_cpu_topology(void)
530 tp->thread_siblings = addr; 533 tp->thread_siblings = addr;
531 534
532 for (i = 0; i < nr; i++) { 535 for (i = 0; i < nr; i++) {
536 if (!cpu_map__has(map, i))
537 continue;
538
533 ret = build_cpu_topo(tp, i); 539 ret = build_cpu_topo(tp, i);
534 if (ret < 0) 540 if (ret < 0)
535 break; 541 break;
536 } 542 }
543
544out_free:
545 cpu_map__put(map);
537 if (ret) { 546 if (ret) {
538 free_cpu_topo(tp); 547 free_cpu_topo(tp);
539 tp = NULL; 548 tp = NULL;
@@ -1124,7 +1133,7 @@ static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused,
1124{ 1133{
1125 int nr, i; 1134 int nr, i;
1126 char *str; 1135 char *str;
1127 int cpu_nr = ph->env.nr_cpus_online; 1136 int cpu_nr = ph->env.nr_cpus_avail;
1128 1137
1129 nr = ph->env.nr_sibling_cores; 1138 nr = ph->env.nr_sibling_cores;
1130 str = ph->env.sibling_cores; 1139 str = ph->env.sibling_cores;
@@ -1779,7 +1788,7 @@ static int process_cpu_topology(struct perf_file_section *section,
1779 u32 nr, i; 1788 u32 nr, i;
1780 char *str; 1789 char *str;
1781 struct strbuf sb; 1790 struct strbuf sb;
1782 int cpu_nr = ph->env.nr_cpus_online; 1791 int cpu_nr = ph->env.nr_cpus_avail;
1783 u64 size = 0; 1792 u64 size = 0;
1784 1793
1785 ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu)); 1794 ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu));
@@ -1860,7 +1869,7 @@ static int process_cpu_topology(struct perf_file_section *section,
1860 if (ph->needs_swap) 1869 if (ph->needs_swap)
1861 nr = bswap_32(nr); 1870 nr = bswap_32(nr);
1862 1871
1863 if (nr > (u32)cpu_nr) { 1872 if (nr != (u32)-1 && nr > (u32)cpu_nr) {
1864 pr_debug("socket_id number is too big." 1873 pr_debug("socket_id number is too big."
1865 "You may need to upgrade the perf tool.\n"); 1874 "You may need to upgrade the perf tool.\n");
1866 goto free_cpu; 1875 goto free_cpu;
@@ -2801,8 +2810,10 @@ static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
2801 } 2810 }
2802 2811
2803 event = pevent_find_event(pevent, evsel->attr.config); 2812 event = pevent_find_event(pevent, evsel->attr.config);
2804 if (event == NULL) 2813 if (event == NULL) {
2814 pr_debug("cannot find event format for %d\n", (int)evsel->attr.config);
2805 return -1; 2815 return -1;
2816 }
2806 2817
2807 if (!evsel->name) { 2818 if (!evsel->name) {
2808 snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name); 2819 snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name);
@@ -3201,6 +3212,7 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
3201 case PERF_EVENT_UPDATE__SCALE: 3212 case PERF_EVENT_UPDATE__SCALE:
3202 ev_scale = (struct event_update_event_scale *) ev->data; 3213 ev_scale = (struct event_update_event_scale *) ev->data;
3203 evsel->scale = ev_scale->scale; 3214 evsel->scale = ev_scale->scale;
3215 break;
3204 case PERF_EVENT_UPDATE__CPUS: 3216 case PERF_EVENT_UPDATE__CPUS:
3205 ev_cpus = (struct event_update_event_cpus *) ev->data; 3217 ev_cpus = (struct event_update_event_cpus *) ev->data;
3206 3218
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 7d1b7d33e644..eaf72a938fb4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -69,7 +69,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
69 */ 69 */
70 if (h->ms.sym) { 70 if (h->ms.sym) {
71 symlen = h->ms.sym->namelen + 4; 71 symlen = h->ms.sym->namelen + 4;
72 if (verbose) 72 if (verbose > 0)
73 symlen += BITS_PER_LONG / 4 + 2 + 3; 73 symlen += BITS_PER_LONG / 4 + 2 + 3;
74 hists__new_col_len(hists, HISTC_SYMBOL, symlen); 74 hists__new_col_len(hists, HISTC_SYMBOL, symlen);
75 } else { 75 } else {
@@ -93,7 +93,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
93 if (h->branch_info) { 93 if (h->branch_info) {
94 if (h->branch_info->from.sym) { 94 if (h->branch_info->from.sym) {
95 symlen = (int)h->branch_info->from.sym->namelen + 4; 95 symlen = (int)h->branch_info->from.sym->namelen + 4;
96 if (verbose) 96 if (verbose > 0)
97 symlen += BITS_PER_LONG / 4 + 2 + 3; 97 symlen += BITS_PER_LONG / 4 + 2 + 3;
98 hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen); 98 hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen);
99 99
@@ -107,7 +107,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
107 107
108 if (h->branch_info->to.sym) { 108 if (h->branch_info->to.sym) {
109 symlen = (int)h->branch_info->to.sym->namelen + 4; 109 symlen = (int)h->branch_info->to.sym->namelen + 4;
110 if (verbose) 110 if (verbose > 0)
111 symlen += BITS_PER_LONG / 4 + 2 + 3; 111 symlen += BITS_PER_LONG / 4 + 2 + 3;
112 hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen); 112 hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen);
113 113
@@ -2446,8 +2446,10 @@ int parse_filter_percentage(const struct option *opt __maybe_unused,
2446 symbol_conf.filter_relative = true; 2446 symbol_conf.filter_relative = true;
2447 else if (!strcmp(arg, "absolute")) 2447 else if (!strcmp(arg, "absolute"))
2448 symbol_conf.filter_relative = false; 2448 symbol_conf.filter_relative = false;
2449 else 2449 else {
2450 pr_debug("Invalud percentage: %s\n", arg);
2450 return -1; 2451 return -1;
2452 }
2451 2453
2452 return 0; 2454 return 0;
2453} 2455}
diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build
index 9b742ea8bfe8..7aca5d6d7e1f 100644
--- a/tools/perf/util/intel-pt-decoder/Build
+++ b/tools/perf/util/intel-pt-decoder/Build
@@ -23,4 +23,8 @@ $(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/in
23 $(call rule_mkdir) 23 $(call rule_mkdir)
24 $(call if_changed_dep,cc_o_c) 24 $(call if_changed_dep,cc_o_c)
25 25
26CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder -Wno-override-init 26CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder
27
28ifneq ($(CC), clang)
29 CFLAGS_intel-pt-insn-decoder.o += -Wno-override-init
30endif
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index e4e7dc781d21..7cf7f7aca4d2 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -22,6 +22,7 @@
22#include <errno.h> 22#include <errno.h>
23#include <stdint.h> 23#include <stdint.h>
24#include <inttypes.h> 24#include <inttypes.h>
25#include <linux/compiler.h>
25 26
26#include "../cache.h" 27#include "../cache.h"
27#include "../util.h" 28#include "../util.h"
@@ -1746,6 +1747,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
1746 switch (decoder->packet.type) { 1747 switch (decoder->packet.type) {
1747 case INTEL_PT_TIP_PGD: 1748 case INTEL_PT_TIP_PGD:
1748 decoder->continuous_period = false; 1749 decoder->continuous_period = false;
1750 __fallthrough;
1749 case INTEL_PT_TIP_PGE: 1751 case INTEL_PT_TIP_PGE:
1750 case INTEL_PT_TIP: 1752 case INTEL_PT_TIP:
1751 intel_pt_log("ERROR: Unexpected packet\n"); 1753 intel_pt_log("ERROR: Unexpected packet\n");
@@ -1799,6 +1801,8 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
1799 decoder->pge = false; 1801 decoder->pge = false;
1800 decoder->continuous_period = false; 1802 decoder->continuous_period = false;
1801 intel_pt_clear_tx_flags(decoder); 1803 intel_pt_clear_tx_flags(decoder);
1804 __fallthrough;
1805
1802 case INTEL_PT_TNT: 1806 case INTEL_PT_TNT:
1803 decoder->have_tma = false; 1807 decoder->have_tma = false;
1804 intel_pt_log("ERROR: Unexpected packet\n"); 1808 intel_pt_log("ERROR: Unexpected packet\n");
@@ -1839,6 +1843,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
1839 switch (decoder->packet.type) { 1843 switch (decoder->packet.type) {
1840 case INTEL_PT_TIP_PGD: 1844 case INTEL_PT_TIP_PGD:
1841 decoder->continuous_period = false; 1845 decoder->continuous_period = false;
1846 __fallthrough;
1842 case INTEL_PT_TIP_PGE: 1847 case INTEL_PT_TIP_PGE:
1843 case INTEL_PT_TIP: 1848 case INTEL_PT_TIP:
1844 decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD; 1849 decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
index 4f7b32020487..7528ae4f7e28 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
@@ -17,6 +17,7 @@
17#include <string.h> 17#include <string.h>
18#include <endian.h> 18#include <endian.h>
19#include <byteswap.h> 19#include <byteswap.h>
20#include <linux/compiler.h>
20 21
21#include "intel-pt-pkt-decoder.h" 22#include "intel-pt-pkt-decoder.h"
22 23
@@ -498,6 +499,7 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
498 case INTEL_PT_FUP: 499 case INTEL_PT_FUP:
499 if (!(packet->count)) 500 if (!(packet->count))
500 return snprintf(buf, buf_len, "%s no ip", name); 501 return snprintf(buf, buf_len, "%s no ip", name);
502 __fallthrough;
501 case INTEL_PT_CYC: 503 case INTEL_PT_CYC:
502 case INTEL_PT_VMCS: 504 case INTEL_PT_VMCS:
503 case INTEL_PT_MTC: 505 case INTEL_PT_MTC:
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 85d5eeb66c75..da20cd5612e9 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -2159,7 +2159,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2159 2159
2160 addr_filters__init(&pt->filts); 2160 addr_filters__init(&pt->filts);
2161 2161
2162 perf_config(intel_pt_perf_config, pt); 2162 err = perf_config(intel_pt_perf_config, pt);
2163 if (err)
2164 goto err_free;
2163 2165
2164 err = auxtrace_queues__init(&pt->queues); 2166 err = auxtrace_queues__init(&pt->queues);
2165 if (err) 2167 if (err)
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index b23ff44cf214..824356488ce6 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -48,8 +48,10 @@ int perf_llvm_config(const char *var, const char *value)
48 llvm_param.kbuild_opts = strdup(value); 48 llvm_param.kbuild_opts = strdup(value);
49 else if (!strcmp(var, "dump-obj")) 49 else if (!strcmp(var, "dump-obj"))
50 llvm_param.dump_obj = !!perf_config_bool(var, value); 50 llvm_param.dump_obj = !!perf_config_bool(var, value);
51 else 51 else {
52 pr_debug("Invalid LLVM config option: %s\n", value);
52 return -1; 53 return -1;
54 }
53 llvm_param.user_set_param = true; 55 llvm_param.user_set_param = true;
54 return 0; 56 return 0;
55} 57}
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 9b33bef54581..71c9720d4973 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -87,6 +87,25 @@ out_delete:
87 return NULL; 87 return NULL;
88} 88}
89 89
90struct machine *machine__new_kallsyms(void)
91{
92 struct machine *machine = machine__new_host();
93 /*
94 * FIXME:
95 * 1) MAP__FUNCTION will go away when we stop loading separate maps for
96 * functions and data objects.
97 * 2) We should switch to machine__load_kallsyms(), i.e. not explicitely
98 * ask for not using the kcore parsing code, once this one is fixed
99 * to create a map per module.
100 */
101 if (machine && __machine__load_kallsyms(machine, "/proc/kallsyms", MAP__FUNCTION, true) <= 0) {
102 machine__delete(machine);
103 machine = NULL;
104 }
105
106 return machine;
107}
108
90static void dsos__purge(struct dsos *dsos) 109static void dsos__purge(struct dsos *dsos)
91{ 110{
92 struct dso *pos, *n; 111 struct dso *pos, *n;
@@ -763,7 +782,7 @@ static u64 machine__get_running_kernel_start(struct machine *machine,
763 782
764int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 783int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
765{ 784{
766 enum map_type type; 785 int type;
767 u64 start = machine__get_running_kernel_start(machine, NULL); 786 u64 start = machine__get_running_kernel_start(machine, NULL);
768 787
769 /* In case of renewal the kernel map, destroy previous one */ 788 /* In case of renewal the kernel map, destroy previous one */
@@ -794,7 +813,7 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
794 813
795void machine__destroy_kernel_maps(struct machine *machine) 814void machine__destroy_kernel_maps(struct machine *machine)
796{ 815{
797 enum map_type type; 816 int type;
798 817
799 for (type = 0; type < MAP__NR_TYPES; ++type) { 818 for (type = 0; type < MAP__NR_TYPES; ++type) {
800 struct kmap *kmap; 819 struct kmap *kmap;
@@ -1546,7 +1565,7 @@ int machine__process_event(struct machine *machine, union perf_event *event,
1546 1565
1547static bool symbol__match_regex(struct symbol *sym, regex_t *regex) 1566static bool symbol__match_regex(struct symbol *sym, regex_t *regex)
1548{ 1567{
1549 if (sym->name && !regexec(regex, sym->name, 0, NULL, 0)) 1568 if (!regexec(regex, sym->name, 0, NULL, 0))
1550 return 1; 1569 return 1;
1551 return 0; 1570 return 0;
1552} 1571}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 354de6e56109..a28305029711 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -129,6 +129,7 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
129void machines__set_comm_exec(struct machines *machines, bool comm_exec); 129void machines__set_comm_exec(struct machines *machines, bool comm_exec);
130 130
131struct machine *machine__new_host(void); 131struct machine *machine__new_host(void);
132struct machine *machine__new_kallsyms(void);
132int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 133int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
133void machine__exit(struct machine *machine); 134void machine__exit(struct machine *machine);
134void machine__delete_threads(struct machine *machine); 135void machine__delete_threads(struct machine *machine);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 4f9a71c63026..0a943e7b1ea7 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -387,10 +387,10 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
387{ 387{
388 const char *dsoname = "[unknown]"; 388 const char *dsoname = "[unknown]";
389 389
390 if (map && map->dso && (map->dso->name || map->dso->long_name)) { 390 if (map && map->dso) {
391 if (symbol_conf.show_kernel_path && map->dso->long_name) 391 if (symbol_conf.show_kernel_path && map->dso->long_name)
392 dsoname = map->dso->long_name; 392 dsoname = map->dso->long_name;
393 else if (map->dso->name) 393 else
394 dsoname = map->dso->name; 394 dsoname = map->dso->name;
395 } 395 }
396 396
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 3c876b8ba4de..67a8aebc67ab 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -211,6 +211,8 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
211 closedir(evt_dir); 211 closedir(evt_dir);
212 closedir(sys_dir); 212 closedir(sys_dir);
213 path = zalloc(sizeof(*path)); 213 path = zalloc(sizeof(*path));
214 if (!path)
215 return NULL;
214 path->system = malloc(MAX_EVENT_LENGTH); 216 path->system = malloc(MAX_EVENT_LENGTH);
215 if (!path->system) { 217 if (!path->system) {
216 free(path); 218 free(path);
@@ -252,8 +254,7 @@ struct tracepoint_path *tracepoint_name_to_path(const char *name)
252 if (path->system == NULL || path->name == NULL) { 254 if (path->system == NULL || path->name == NULL) {
253 zfree(&path->system); 255 zfree(&path->system);
254 zfree(&path->name); 256 zfree(&path->name);
255 free(path); 257 zfree(&path);
256 path = NULL;
257 } 258 }
258 259
259 return path; 260 return path;
@@ -310,10 +311,11 @@ __add_event(struct list_head *list, int *idx,
310 311
311 event_attr_init(attr); 312 event_attr_init(attr);
312 313
313 evsel = perf_evsel__new_idx(attr, (*idx)++); 314 evsel = perf_evsel__new_idx(attr, *idx);
314 if (!evsel) 315 if (!evsel)
315 return NULL; 316 return NULL;
316 317
318 (*idx)++;
317 evsel->cpus = cpu_map__get(cpus); 319 evsel->cpus = cpu_map__get(cpus);
318 evsel->own_cpus = cpu_map__get(cpus); 320 evsel->own_cpus = cpu_map__get(cpus);
319 321
@@ -1477,10 +1479,9 @@ static void perf_pmu__parse_cleanup(void)
1477 1479
1478 for (i = 0; i < perf_pmu_events_list_num; i++) { 1480 for (i = 0; i < perf_pmu_events_list_num; i++) {
1479 p = perf_pmu_events_list + i; 1481 p = perf_pmu_events_list + i;
1480 free(p->symbol); 1482 zfree(&p->symbol);
1481 } 1483 }
1482 free(perf_pmu_events_list); 1484 zfree(&perf_pmu_events_list);
1483 perf_pmu_events_list = NULL;
1484 perf_pmu_events_list_num = 0; 1485 perf_pmu_events_list_num = 0;
1485 } 1486 }
1486} 1487}
@@ -1504,35 +1505,41 @@ static void perf_pmu__parse_init(void)
1504 struct perf_pmu_alias *alias; 1505 struct perf_pmu_alias *alias;
1505 int len = 0; 1506 int len = 0;
1506 1507
1507 pmu = perf_pmu__find("cpu"); 1508 pmu = NULL;
1508 if ((pmu == NULL) || list_empty(&pmu->aliases)) { 1509 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
1510 list_for_each_entry(alias, &pmu->aliases, list) {
1511 if (strchr(alias->name, '-'))
1512 len++;
1513 len++;
1514 }
1515 }
1516
1517 if (len == 0) {
1509 perf_pmu_events_list_num = -1; 1518 perf_pmu_events_list_num = -1;
1510 return; 1519 return;
1511 } 1520 }
1512 list_for_each_entry(alias, &pmu->aliases, list) {
1513 if (strchr(alias->name, '-'))
1514 len++;
1515 len++;
1516 }
1517 perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len); 1521 perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len);
1518 if (!perf_pmu_events_list) 1522 if (!perf_pmu_events_list)
1519 return; 1523 return;
1520 perf_pmu_events_list_num = len; 1524 perf_pmu_events_list_num = len;
1521 1525
1522 len = 0; 1526 len = 0;
1523 list_for_each_entry(alias, &pmu->aliases, list) { 1527 pmu = NULL;
1524 struct perf_pmu_event_symbol *p = perf_pmu_events_list + len; 1528 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
1525 char *tmp = strchr(alias->name, '-'); 1529 list_for_each_entry(alias, &pmu->aliases, list) {
1526 1530 struct perf_pmu_event_symbol *p = perf_pmu_events_list + len;
1527 if (tmp != NULL) { 1531 char *tmp = strchr(alias->name, '-');
1528 SET_SYMBOL(strndup(alias->name, tmp - alias->name), 1532
1529 PMU_EVENT_SYMBOL_PREFIX); 1533 if (tmp != NULL) {
1530 p++; 1534 SET_SYMBOL(strndup(alias->name, tmp - alias->name),
1531 SET_SYMBOL(strdup(++tmp), PMU_EVENT_SYMBOL_SUFFIX); 1535 PMU_EVENT_SYMBOL_PREFIX);
1532 len += 2; 1536 p++;
1533 } else { 1537 SET_SYMBOL(strdup(++tmp), PMU_EVENT_SYMBOL_SUFFIX);
1534 SET_SYMBOL(strdup(alias->name), PMU_EVENT_SYMBOL); 1538 len += 2;
1535 len++; 1539 } else {
1540 SET_SYMBOL(strdup(alias->name), PMU_EVENT_SYMBOL);
1541 len++;
1542 }
1536 } 1543 }
1537 } 1544 }
1538 qsort(perf_pmu_events_list, len, 1545 qsort(perf_pmu_events_list, len,
@@ -1563,7 +1570,7 @@ perf_pmu__parse_check(const char *name)
1563 r = bsearch(&p, perf_pmu_events_list, 1570 r = bsearch(&p, perf_pmu_events_list,
1564 (size_t) perf_pmu_events_list_num, 1571 (size_t) perf_pmu_events_list_num,
1565 sizeof(struct perf_pmu_event_symbol), comp_pmu); 1572 sizeof(struct perf_pmu_event_symbol), comp_pmu);
1566 free(p.symbol); 1573 zfree(&p.symbol);
1567 return r ? r->type : PMU_EVENT_SYMBOL_ERR; 1574 return r ? r->type : PMU_EVENT_SYMBOL_ERR;
1568} 1575}
1569 1576
@@ -1710,8 +1717,8 @@ static void parse_events_print_error(struct parse_events_error *err,
1710 fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err->str); 1717 fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err->str);
1711 if (err->help) 1718 if (err->help)
1712 fprintf(stderr, "\n%s\n", err->help); 1719 fprintf(stderr, "\n%s\n", err->help);
1713 free(err->str); 1720 zfree(&err->str);
1714 free(err->help); 1721 zfree(&err->help);
1715 } 1722 }
1716 1723
1717 fprintf(stderr, "Run 'perf list' for a list of valid events\n"); 1724 fprintf(stderr, "Run 'perf list' for a list of valid events\n");
@@ -2013,17 +2020,14 @@ static bool is_event_supported(u8 type, unsigned config)
2013 .config = config, 2020 .config = config,
2014 .disabled = 1, 2021 .disabled = 1,
2015 }; 2022 };
2016 struct { 2023 struct thread_map *tmap = thread_map__new_by_tid(0);
2017 struct thread_map map; 2024
2018 int threads[1]; 2025 if (tmap == NULL)
2019 } tmap = { 2026 return false;
2020 .map.nr = 1,
2021 .threads = { 0 },
2022 };
2023 2027
2024 evsel = perf_evsel__new(&attr); 2028 evsel = perf_evsel__new(&attr);
2025 if (evsel) { 2029 if (evsel) {
2026 open_return = perf_evsel__open(evsel, NULL, &tmap.map); 2030 open_return = perf_evsel__open(evsel, NULL, tmap);
2027 ret = open_return >= 0; 2031 ret = open_return >= 0;
2028 2032
2029 if (open_return == -EACCES) { 2033 if (open_return == -EACCES) {
@@ -2035,7 +2039,7 @@ static bool is_event_supported(u8 type, unsigned config)
2035 * 2039 *
2036 */ 2040 */
2037 evsel->attr.exclude_kernel = 1; 2041 evsel->attr.exclude_kernel = 1;
2038 ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0; 2042 ret = perf_evsel__open(evsel, NULL, tmap) >= 0;
2039 } 2043 }
2040 perf_evsel__delete(evsel); 2044 perf_evsel__delete(evsel);
2041 } 2045 }
@@ -2314,24 +2318,20 @@ int parse_events__is_hardcoded_term(struct parse_events_term *term)
2314 return term->type_term != PARSE_EVENTS__TERM_TYPE_USER; 2318 return term->type_term != PARSE_EVENTS__TERM_TYPE_USER;
2315} 2319}
2316 2320
2317static int new_term(struct parse_events_term **_term, int type_val, 2321static int new_term(struct parse_events_term **_term,
2318 int type_term, char *config, 2322 struct parse_events_term *temp,
2319 char *str, u64 num, int err_term, int err_val) 2323 char *str, u64 num)
2320{ 2324{
2321 struct parse_events_term *term; 2325 struct parse_events_term *term;
2322 2326
2323 term = zalloc(sizeof(*term)); 2327 term = malloc(sizeof(*term));
2324 if (!term) 2328 if (!term)
2325 return -ENOMEM; 2329 return -ENOMEM;
2326 2330
2331 *term = *temp;
2327 INIT_LIST_HEAD(&term->list); 2332 INIT_LIST_HEAD(&term->list);
2328 term->type_val = type_val;
2329 term->type_term = type_term;
2330 term->config = config;
2331 term->err_term = err_term;
2332 term->err_val = err_val;
2333 2333
2334 switch (type_val) { 2334 switch (term->type_val) {
2335 case PARSE_EVENTS__TERM_TYPE_NUM: 2335 case PARSE_EVENTS__TERM_TYPE_NUM:
2336 term->val.num = num; 2336 term->val.num = num;
2337 break; 2337 break;
@@ -2349,15 +2349,22 @@ static int new_term(struct parse_events_term **_term, int type_val,
2349 2349
2350int parse_events_term__num(struct parse_events_term **term, 2350int parse_events_term__num(struct parse_events_term **term,
2351 int type_term, char *config, u64 num, 2351 int type_term, char *config, u64 num,
2352 bool no_value,
2352 void *loc_term_, void *loc_val_) 2353 void *loc_term_, void *loc_val_)
2353{ 2354{
2354 YYLTYPE *loc_term = loc_term_; 2355 YYLTYPE *loc_term = loc_term_;
2355 YYLTYPE *loc_val = loc_val_; 2356 YYLTYPE *loc_val = loc_val_;
2356 2357
2357 return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term, 2358 struct parse_events_term temp = {
2358 config, NULL, num, 2359 .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
2359 loc_term ? loc_term->first_column : 0, 2360 .type_term = type_term,
2360 loc_val ? loc_val->first_column : 0); 2361 .config = config,
2362 .no_value = no_value,
2363 .err_term = loc_term ? loc_term->first_column : 0,
2364 .err_val = loc_val ? loc_val->first_column : 0,
2365 };
2366
2367 return new_term(term, &temp, NULL, num);
2361} 2368}
2362 2369
2363int parse_events_term__str(struct parse_events_term **term, 2370int parse_events_term__str(struct parse_events_term **term,
@@ -2367,37 +2374,45 @@ int parse_events_term__str(struct parse_events_term **term,
2367 YYLTYPE *loc_term = loc_term_; 2374 YYLTYPE *loc_term = loc_term_;
2368 YYLTYPE *loc_val = loc_val_; 2375 YYLTYPE *loc_val = loc_val_;
2369 2376
2370 return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term, 2377 struct parse_events_term temp = {
2371 config, str, 0, 2378 .type_val = PARSE_EVENTS__TERM_TYPE_STR,
2372 loc_term ? loc_term->first_column : 0, 2379 .type_term = type_term,
2373 loc_val ? loc_val->first_column : 0); 2380 .config = config,
2381 .err_term = loc_term ? loc_term->first_column : 0,
2382 .err_val = loc_val ? loc_val->first_column : 0,
2383 };
2384
2385 return new_term(term, &temp, str, 0);
2374} 2386}
2375 2387
2376int parse_events_term__sym_hw(struct parse_events_term **term, 2388int parse_events_term__sym_hw(struct parse_events_term **term,
2377 char *config, unsigned idx) 2389 char *config, unsigned idx)
2378{ 2390{
2379 struct event_symbol *sym; 2391 struct event_symbol *sym;
2392 struct parse_events_term temp = {
2393 .type_val = PARSE_EVENTS__TERM_TYPE_STR,
2394 .type_term = PARSE_EVENTS__TERM_TYPE_USER,
2395 .config = config ?: (char *) "event",
2396 };
2380 2397
2381 BUG_ON(idx >= PERF_COUNT_HW_MAX); 2398 BUG_ON(idx >= PERF_COUNT_HW_MAX);
2382 sym = &event_symbols_hw[idx]; 2399 sym = &event_symbols_hw[idx];
2383 2400
2384 if (config) 2401 return new_term(term, &temp, (char *) sym->symbol, 0);
2385 return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
2386 PARSE_EVENTS__TERM_TYPE_USER, config,
2387 (char *) sym->symbol, 0, 0, 0);
2388 else
2389 return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
2390 PARSE_EVENTS__TERM_TYPE_USER,
2391 (char *) "event", (char *) sym->symbol,
2392 0, 0, 0);
2393} 2402}
2394 2403
2395int parse_events_term__clone(struct parse_events_term **new, 2404int parse_events_term__clone(struct parse_events_term **new,
2396 struct parse_events_term *term) 2405 struct parse_events_term *term)
2397{ 2406{
2398 return new_term(new, term->type_val, term->type_term, term->config, 2407 struct parse_events_term temp = {
2399 term->val.str, term->val.num, 2408 .type_val = term->type_val,
2400 term->err_term, term->err_val); 2409 .type_term = term->type_term,
2410 .config = term->config,
2411 .err_term = term->err_term,
2412 .err_val = term->err_val,
2413 };
2414
2415 return new_term(new, &temp, term->val.str, term->val.num);
2401} 2416}
2402 2417
2403void parse_events_terms__purge(struct list_head *terms) 2418void parse_events_terms__purge(struct list_head *terms)
@@ -2406,7 +2421,7 @@ void parse_events_terms__purge(struct list_head *terms)
2406 2421
2407 list_for_each_entry_safe(term, h, terms, list) { 2422 list_for_each_entry_safe(term, h, terms, list) {
2408 if (term->array.nr_ranges) 2423 if (term->array.nr_ranges)
2409 free(term->array.ranges); 2424 zfree(&term->array.ranges);
2410 list_del_init(&term->list); 2425 list_del_init(&term->list);
2411 free(term); 2426 free(term);
2412 } 2427 }
@@ -2422,7 +2437,7 @@ void parse_events_terms__delete(struct list_head *terms)
2422 2437
2423void parse_events__clear_array(struct parse_events_array *a) 2438void parse_events__clear_array(struct parse_events_array *a)
2424{ 2439{
2425 free(a->ranges); 2440 zfree(&a->ranges);
2426} 2441}
2427 2442
2428void parse_events_evlist_error(struct parse_events_evlist *data, 2443void parse_events_evlist_error(struct parse_events_evlist *data,
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index da246a3ddb69..1af6a267c21b 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -94,6 +94,7 @@ struct parse_events_term {
94 int type_term; 94 int type_term;
95 struct list_head list; 95 struct list_head list;
96 bool used; 96 bool used;
97 bool no_value;
97 98
98 /* error string indexes for within parsed string */ 99 /* error string indexes for within parsed string */
99 int err_term; 100 int err_term;
@@ -122,6 +123,7 @@ void parse_events__shrink_config_terms(void);
122int parse_events__is_hardcoded_term(struct parse_events_term *term); 123int parse_events__is_hardcoded_term(struct parse_events_term *term);
123int parse_events_term__num(struct parse_events_term **term, 124int parse_events_term__num(struct parse_events_term **term,
124 int type_term, char *config, u64 num, 125 int type_term, char *config, u64 num,
126 bool novalue,
125 void *loc_term, void *loc_val); 127 void *loc_term, void *loc_val);
126int parse_events_term__str(struct parse_events_term **term, 128int parse_events_term__str(struct parse_events_term **term,
127 int type_term, char *config, char *str, 129 int type_term, char *config, char *str,
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 879115f93edc..30f018ea1370 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -12,9 +12,13 @@
12#include <linux/list.h> 12#include <linux/list.h>
13#include <linux/types.h> 13#include <linux/types.h>
14#include "util.h" 14#include "util.h"
15#include "pmu.h"
16#include "debug.h"
15#include "parse-events.h" 17#include "parse-events.h"
16#include "parse-events-bison.h" 18#include "parse-events-bison.h"
17 19
20void parse_events_error(YYLTYPE *loc, void *data, void *scanner, char const *msg);
21
18#define ABORT_ON(val) \ 22#define ABORT_ON(val) \
19do { \ 23do { \
20 if (val) \ 24 if (val) \
@@ -236,15 +240,34 @@ PE_KERNEL_PMU_EVENT sep_dc
236 struct list_head *head; 240 struct list_head *head;
237 struct parse_events_term *term; 241 struct parse_events_term *term;
238 struct list_head *list; 242 struct list_head *list;
243 struct perf_pmu *pmu = NULL;
244 int ok = 0;
239 245
240 ALLOC_LIST(head); 246 /* Add it for all PMUs that support the alias */
241 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
242 $1, 1, &@1, NULL));
243 list_add_tail(&term->list, head);
244
245 ALLOC_LIST(list); 247 ALLOC_LIST(list);
246 ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); 248 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
247 parse_events_terms__delete(head); 249 struct perf_pmu_alias *alias;
250
251 list_for_each_entry(alias, &pmu->aliases, list) {
252 if (!strcasecmp(alias->name, $1)) {
253 ALLOC_LIST(head);
254 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
255 $1, 1, false, &@1, NULL));
256 list_add_tail(&term->list, head);
257
258 if (!parse_events_add_pmu(data, list,
259 pmu->name, head)) {
260 pr_debug("%s -> %s/%s/\n", $1,
261 pmu->name, alias->str);
262 ok++;
263 }
264
265 parse_events_terms__delete(head);
266 }
267 }
268 }
269 if (!ok)
270 YYABORT;
248 $$ = list; 271 $$ = list;
249} 272}
250| 273|
@@ -259,7 +282,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
259 282
260 ALLOC_LIST(head); 283 ALLOC_LIST(head);
261 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 284 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
262 &pmu_name, 1, &@1, NULL)); 285 &pmu_name, 1, false, &@1, NULL));
263 list_add_tail(&term->list, head); 286 list_add_tail(&term->list, head);
264 287
265 ALLOC_LIST(list); 288 ALLOC_LIST(list);
@@ -525,7 +548,7 @@ PE_NAME '=' PE_VALUE
525 struct parse_events_term *term; 548 struct parse_events_term *term;
526 549
527 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 550 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
528 $1, $3, &@1, &@3)); 551 $1, $3, false, &@1, &@3));
529 $$ = term; 552 $$ = term;
530} 553}
531| 554|
@@ -543,7 +566,7 @@ PE_NAME
543 struct parse_events_term *term; 566 struct parse_events_term *term;
544 567
545 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 568 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
546 $1, 1, &@1, NULL)); 569 $1, 1, true, &@1, NULL));
547 $$ = term; 570 $$ = term;
548} 571}
549| 572|
@@ -568,7 +591,7 @@ PE_TERM '=' PE_VALUE
568{ 591{
569 struct parse_events_term *term; 592 struct parse_events_term *term;
570 593
571 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, &@1, &@3)); 594 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, false, &@1, &@3));
572 $$ = term; 595 $$ = term;
573} 596}
574| 597|
@@ -576,7 +599,7 @@ PE_TERM
576{ 599{
577 struct parse_events_term *term; 600 struct parse_events_term *term;
578 601
579 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, &@1, NULL)); 602 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, true, &@1, NULL));
580 $$ = term; 603 $$ = term;
581} 604}
582| 605|
@@ -597,7 +620,7 @@ PE_NAME array '=' PE_VALUE
597 struct parse_events_term *term; 620 struct parse_events_term *term;
598 621
599 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 622 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
600 $1, $4, &@1, &@4)); 623 $1, $4, false, &@1, &@4));
601 term->array = $2; 624 term->array = $2;
602 $$ = term; 625 $$ = term;
603} 626}
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index dc6ccaa4e927..12f84dd2ac5d 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -94,32 +94,10 @@ static int pmu_format(const char *name, struct list_head *format)
94 return 0; 94 return 0;
95} 95}
96 96
97static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name) 97static int convert_scale(const char *scale, char **end, double *sval)
98{ 98{
99 struct stat st;
100 ssize_t sret;
101 char scale[128];
102 int fd, ret = -1;
103 char path[PATH_MAX];
104 char *lc; 99 char *lc;
105 100 int ret = 0;
106 snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
107
108 fd = open(path, O_RDONLY);
109 if (fd == -1)
110 return -1;
111
112 if (fstat(fd, &st) < 0)
113 goto error;
114
115 sret = read(fd, scale, sizeof(scale)-1);
116 if (sret < 0)
117 goto error;
118
119 if (scale[sret - 1] == '\n')
120 scale[sret - 1] = '\0';
121 else
122 scale[sret] = '\0';
123 101
124 /* 102 /*
125 * save current locale 103 * save current locale
@@ -134,7 +112,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *
134 lc = strdup(lc); 112 lc = strdup(lc);
135 if (!lc) { 113 if (!lc) {
136 ret = -ENOMEM; 114 ret = -ENOMEM;
137 goto error; 115 goto out;
138 } 116 }
139 117
140 /* 118 /*
@@ -144,14 +122,42 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *
144 */ 122 */
145 setlocale(LC_NUMERIC, "C"); 123 setlocale(LC_NUMERIC, "C");
146 124
147 alias->scale = strtod(scale, NULL); 125 *sval = strtod(scale, end);
148 126
127out:
149 /* restore locale */ 128 /* restore locale */
150 setlocale(LC_NUMERIC, lc); 129 setlocale(LC_NUMERIC, lc);
151
152 free(lc); 130 free(lc);
131 return ret;
132}
133
134static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
135{
136 struct stat st;
137 ssize_t sret;
138 char scale[128];
139 int fd, ret = -1;
140 char path[PATH_MAX];
153 141
154 ret = 0; 142 snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
143
144 fd = open(path, O_RDONLY);
145 if (fd == -1)
146 return -1;
147
148 if (fstat(fd, &st) < 0)
149 goto error;
150
151 sret = read(fd, scale, sizeof(scale)-1);
152 if (sret < 0)
153 goto error;
154
155 if (scale[sret - 1] == '\n')
156 scale[sret - 1] = '\0';
157 else
158 scale[sret] = '\0';
159
160 ret = convert_scale(scale, NULL, &alias->scale);
155error: 161error:
156 close(fd); 162 close(fd);
157 return ret; 163 return ret;
@@ -223,11 +229,13 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
223} 229}
224 230
225static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, 231static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
226 char *desc, char *val, char *long_desc, 232 char *desc, char *val,
227 char *topic) 233 char *long_desc, char *topic,
234 char *unit, char *perpkg)
228{ 235{
229 struct perf_pmu_alias *alias; 236 struct perf_pmu_alias *alias;
230 int ret; 237 int ret;
238 int num;
231 239
232 alias = malloc(sizeof(*alias)); 240 alias = malloc(sizeof(*alias));
233 if (!alias) 241 if (!alias)
@@ -261,6 +269,13 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
261 alias->long_desc = long_desc ? strdup(long_desc) : 269 alias->long_desc = long_desc ? strdup(long_desc) :
262 desc ? strdup(desc) : NULL; 270 desc ? strdup(desc) : NULL;
263 alias->topic = topic ? strdup(topic) : NULL; 271 alias->topic = topic ? strdup(topic) : NULL;
272 if (unit) {
273 if (convert_scale(unit, &unit, &alias->scale) < 0)
274 return -1;
275 snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
276 }
277 alias->per_pkg = perpkg && sscanf(perpkg, "%d", &num) == 1 && num == 1;
278 alias->str = strdup(val);
264 279
265 list_add_tail(&alias->list, list); 280 list_add_tail(&alias->list, list);
266 281
@@ -278,7 +293,8 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
278 293
279 buf[ret] = 0; 294 buf[ret] = 0;
280 295
281 return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL); 296 return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL,
297 NULL);
282} 298}
283 299
284static inline bool pmu_alias_info_file(char *name) 300static inline bool pmu_alias_info_file(char *name)
@@ -498,7 +514,7 @@ char * __weak get_cpuid_str(void)
498 * to the current running CPU. Then, add all PMU events from that table 514 * to the current running CPU. Then, add all PMU events from that table
499 * as aliases. 515 * as aliases.
500 */ 516 */
501static void pmu_add_cpu_aliases(struct list_head *head) 517static void pmu_add_cpu_aliases(struct list_head *head, const char *name)
502{ 518{
503 int i; 519 int i;
504 struct pmu_events_map *map; 520 struct pmu_events_map *map;
@@ -534,14 +550,21 @@ static void pmu_add_cpu_aliases(struct list_head *head)
534 */ 550 */
535 i = 0; 551 i = 0;
536 while (1) { 552 while (1) {
553 const char *pname;
554
537 pe = &map->table[i++]; 555 pe = &map->table[i++];
538 if (!pe->name) 556 if (!pe->name)
539 break; 557 break;
540 558
559 pname = pe->pmu ? pe->pmu : "cpu";
560 if (strncmp(pname, name, strlen(pname)))
561 continue;
562
541 /* need type casts to override 'const' */ 563 /* need type casts to override 'const' */
542 __perf_pmu__new_alias(head, NULL, (char *)pe->name, 564 __perf_pmu__new_alias(head, NULL, (char *)pe->name,
543 (char *)pe->desc, (char *)pe->event, 565 (char *)pe->desc, (char *)pe->event,
544 (char *)pe->long_desc, (char *)pe->topic); 566 (char *)pe->long_desc, (char *)pe->topic,
567 (char *)pe->unit, (char *)pe->perpkg);
545 } 568 }
546 569
547out: 570out:
@@ -569,15 +592,16 @@ static struct perf_pmu *pmu_lookup(const char *name)
569 if (pmu_format(name, &format)) 592 if (pmu_format(name, &format))
570 return NULL; 593 return NULL;
571 594
572 if (pmu_aliases(name, &aliases)) 595 /*
596 * Check the type first to avoid unnecessary work.
597 */
598 if (pmu_type(name, &type))
573 return NULL; 599 return NULL;
574 600
575 if (!strcmp(name, "cpu")) 601 if (pmu_aliases(name, &aliases))
576 pmu_add_cpu_aliases(&aliases);
577
578 if (pmu_type(name, &type))
579 return NULL; 602 return NULL;
580 603
604 pmu_add_cpu_aliases(&aliases, name);
581 pmu = zalloc(sizeof(*pmu)); 605 pmu = zalloc(sizeof(*pmu));
582 if (!pmu) 606 if (!pmu)
583 return NULL; 607 return NULL;
@@ -721,7 +745,7 @@ static int pmu_resolve_param_term(struct parse_events_term *term,
721 } 745 }
722 } 746 }
723 747
724 if (verbose) 748 if (verbose > 0)
725 printf("Required parameter '%s' not specified\n", term->config); 749 printf("Required parameter '%s' not specified\n", term->config);
726 750
727 return -1; 751 return -1;
@@ -779,7 +803,7 @@ static int pmu_config_term(struct list_head *formats,
779 803
780 format = pmu_find_format(formats, term->config); 804 format = pmu_find_format(formats, term->config);
781 if (!format) { 805 if (!format) {
782 if (verbose) 806 if (verbose > 0)
783 printf("Invalid event/parameter '%s'\n", term->config); 807 printf("Invalid event/parameter '%s'\n", term->config);
784 if (err) { 808 if (err) {
785 char *pmu_term = pmu_formats_string(formats); 809 char *pmu_term = pmu_formats_string(formats);
@@ -810,11 +834,20 @@ static int pmu_config_term(struct list_head *formats,
810 * Either directly use a numeric term, or try to translate string terms 834 * Either directly use a numeric term, or try to translate string terms
811 * using event parameters. 835 * using event parameters.
812 */ 836 */
813 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) 837 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
838 if (term->no_value &&
839 bitmap_weight(format->bits, PERF_PMU_FORMAT_BITS) > 1) {
840 if (err) {
841 err->idx = term->err_val;
842 err->str = strdup("no value assigned for term");
843 }
844 return -EINVAL;
845 }
846
814 val = term->val.num; 847 val = term->val.num;
815 else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 848 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
816 if (strcmp(term->val.str, "?")) { 849 if (strcmp(term->val.str, "?")) {
817 if (verbose) { 850 if (verbose > 0) {
818 pr_info("Invalid sysfs entry %s=%s\n", 851 pr_info("Invalid sysfs entry %s=%s\n",
819 term->config, term->val.str); 852 term->config, term->val.str);
820 } 853 }
@@ -921,12 +954,12 @@ static int check_info_data(struct perf_pmu_alias *alias,
921 * define unit, scale and snapshot, fail 954 * define unit, scale and snapshot, fail
922 * if there's more than one. 955 * if there's more than one.
923 */ 956 */
924 if ((info->unit && alias->unit) || 957 if ((info->unit && alias->unit[0]) ||
925 (info->scale && alias->scale) || 958 (info->scale && alias->scale) ||
926 (info->snapshot && alias->snapshot)) 959 (info->snapshot && alias->snapshot))
927 return -EINVAL; 960 return -EINVAL;
928 961
929 if (alias->unit) 962 if (alias->unit[0])
930 info->unit = alias->unit; 963 info->unit = alias->unit;
931 964
932 if (alias->scale) 965 if (alias->scale)
@@ -1065,6 +1098,8 @@ struct sevent {
1065 char *name; 1098 char *name;
1066 char *desc; 1099 char *desc;
1067 char *topic; 1100 char *topic;
1101 char *str;
1102 char *pmu;
1068}; 1103};
1069 1104
1070static int cmp_sevent(const void *a, const void *b) 1105static int cmp_sevent(const void *a, const void *b)
@@ -1161,6 +1196,8 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1161 aliases[j].desc = long_desc ? alias->long_desc : 1196 aliases[j].desc = long_desc ? alias->long_desc :
1162 alias->desc; 1197 alias->desc;
1163 aliases[j].topic = alias->topic; 1198 aliases[j].topic = alias->topic;
1199 aliases[j].str = alias->str;
1200 aliases[j].pmu = pmu->name;
1164 j++; 1201 j++;
1165 } 1202 }
1166 if (pmu->selectable && 1203 if (pmu->selectable &&
@@ -1175,6 +1212,9 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1175 len = j; 1212 len = j;
1176 qsort(aliases, len, sizeof(struct sevent), cmp_sevent); 1213 qsort(aliases, len, sizeof(struct sevent), cmp_sevent);
1177 for (j = 0; j < len; j++) { 1214 for (j = 0; j < len; j++) {
1215 /* Skip duplicates */
1216 if (j > 0 && !strcmp(aliases[j].name, aliases[j - 1].name))
1217 continue;
1178 if (name_only) { 1218 if (name_only) {
1179 printf("%s ", aliases[j].name); 1219 printf("%s ", aliases[j].name);
1180 continue; 1220 continue;
@@ -1192,6 +1232,8 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1192 printf("%*s", 8, "["); 1232 printf("%*s", 8, "[");
1193 wordwrap(aliases[j].desc, 8, columns, 0); 1233 wordwrap(aliases[j].desc, 8, columns, 0);
1194 printf("]\n"); 1234 printf("]\n");
1235 if (verbose > 0)
1236 printf("%*s%s/%s/\n", 8, "", aliases[j].pmu, aliases[j].str);
1195 } else 1237 } else
1196 printf(" %-50s [Kernel PMU event]\n", aliases[j].name); 1238 printf(" %-50s [Kernel PMU event]\n", aliases[j].name);
1197 printed++; 1239 printed++;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 25712034c815..00852ddc7741 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -43,6 +43,7 @@ struct perf_pmu_alias {
43 char *desc; 43 char *desc;
44 char *long_desc; 44 char *long_desc;
45 char *topic; 45 char *topic;
46 char *str;
46 struct list_head terms; /* HEAD struct parse_events_term -> list */ 47 struct list_head terms; /* HEAD struct parse_events_term -> list */
47 struct list_head list; /* ELEM */ 48 struct list_head list; /* ELEM */
48 char unit[UNIT_MAX_LEN+1]; 49 char unit[UNIT_MAX_LEN+1];
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 6a6f44dd594b..28fb62c32678 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -594,7 +594,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
594 pr_debug("try to find information at %" PRIx64 " in %s\n", addr, 594 pr_debug("try to find information at %" PRIx64 " in %s\n", addr,
595 tp->module ? : "kernel"); 595 tp->module ? : "kernel");
596 596
597 dinfo = debuginfo_cache__open(tp->module, verbose == 0); 597 dinfo = debuginfo_cache__open(tp->module, verbose <= 0);
598 if (dinfo) 598 if (dinfo)
599 ret = debuginfo__find_probe_point(dinfo, 599 ret = debuginfo__find_probe_point(dinfo,
600 (unsigned long)addr, pp); 600 (unsigned long)addr, pp);
@@ -2061,7 +2061,7 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
2061 bool is_kprobe) 2061 bool is_kprobe)
2062{ 2062{
2063 struct symbol *sym = NULL; 2063 struct symbol *sym = NULL;
2064 struct map *map; 2064 struct map *map = NULL;
2065 u64 addr = tp->address; 2065 u64 addr = tp->address;
2066 int ret = -ENOENT; 2066 int ret = -ENOENT;
2067 2067
@@ -3023,20 +3023,17 @@ static int try_to_find_absolute_address(struct perf_probe_event *pev,
3023 3023
3024 tev->nargs = pev->nargs; 3024 tev->nargs = pev->nargs;
3025 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 3025 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
3026 if (!tev->args) { 3026 if (!tev->args)
3027 err = -ENOMEM;
3028 goto errout; 3027 goto errout;
3029 } 3028
3030 for (i = 0; i < tev->nargs; i++) 3029 for (i = 0; i < tev->nargs; i++)
3031 copy_to_probe_trace_arg(&tev->args[i], &pev->args[i]); 3030 copy_to_probe_trace_arg(&tev->args[i], &pev->args[i]);
3032 3031
3033 return 1; 3032 return 1;
3034 3033
3035errout: 3034errout:
3036 if (*tevs) { 3035 clear_probe_trace_events(*tevs, 1);
3037 clear_probe_trace_events(*tevs, 1); 3036 *tevs = NULL;
3038 *tevs = NULL;
3039 }
3040 return err; 3037 return err;
3041} 3038}
3042 3039
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 0d9d6e0803b8..57cd268d4275 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -464,7 +464,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
464 /* Verify it is a data structure */ 464 /* Verify it is a data structure */
465 tag = dwarf_tag(&type); 465 tag = dwarf_tag(&type);
466 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) { 466 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
467 pr_warning("%s is not a data structure nor an union.\n", 467 pr_warning("%s is not a data structure nor a union.\n",
468 varname); 468 varname);
469 return -EINVAL; 469 return -EINVAL;
470 } 470 }
@@ -479,7 +479,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
479 } else { 479 } else {
480 /* Verify it is a data structure */ 480 /* Verify it is a data structure */
481 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) { 481 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
482 pr_warning("%s is not a data structure nor an union.\n", 482 pr_warning("%s is not a data structure nor a union.\n",
483 varname); 483 varname);
484 return -EINVAL; 484 return -EINVAL;
485 } 485 }
diff --git a/tools/perf/util/scripting-engines/Build b/tools/perf/util/scripting-engines/Build
index 6516e220c247..82d28c67e0f3 100644
--- a/tools/perf/util/scripting-engines/Build
+++ b/tools/perf/util/scripting-engines/Build
@@ -1,6 +1,6 @@
1libperf-$(CONFIG_LIBPERL) += trace-event-perl.o 1libperf-$(CONFIG_LIBPERL) += trace-event-perl.o
2libperf-$(CONFIG_LIBPYTHON) += trace-event-python.o 2libperf-$(CONFIG_LIBPYTHON) += trace-event-python.o
3 3
4CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default 4CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-nested-externs -Wno-undef -Wno-switch-default
5 5
6CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow 6CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index e55a132f69b7..dff043a29589 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -217,6 +217,7 @@ static void define_event_symbols(struct event_format *event,
217 cur_field_name); 217 cur_field_name);
218 break; 218 break;
219 case PRINT_HEX: 219 case PRINT_HEX:
220 case PRINT_HEX_STR:
220 define_event_symbols(event, ev_name, args->hex.field); 221 define_event_symbols(event, ev_name, args->hex.field);
221 define_event_symbols(event, ev_name, args->hex.size); 222 define_event_symbols(event, ev_name, args->hex.size);
222 break; 223 break;
@@ -309,10 +310,10 @@ static SV *perl_process_callchain(struct perf_sample *sample,
309 if (node->map) { 310 if (node->map) {
310 struct map *map = node->map; 311 struct map *map = node->map;
311 const char *dsoname = "[unknown]"; 312 const char *dsoname = "[unknown]";
312 if (map && map->dso && (map->dso->name || map->dso->long_name)) { 313 if (map && map->dso) {
313 if (symbol_conf.show_kernel_path && map->dso->long_name) 314 if (symbol_conf.show_kernel_path && map->dso->long_name)
314 dsoname = map->dso->long_name; 315 dsoname = map->dso->long_name;
315 else if (map->dso->name) 316 else
316 dsoname = map->dso->name; 317 dsoname = map->dso->name;
317 } 318 }
318 if (!hv_stores(elem, "dso", newSVpv(dsoname,0))) { 319 if (!hv_stores(elem, "dso", newSVpv(dsoname,0))) {
@@ -350,8 +351,10 @@ static void perl_process_tracepoint(struct perf_sample *sample,
350 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 351 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
351 return; 352 return;
352 353
353 if (!event) 354 if (!event) {
354 die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config); 355 pr_debug("ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
356 return;
357 }
355 358
356 pid = raw_field_value(event, "common_pid", data); 359 pid = raw_field_value(event, "common_pid", data);
357 360
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 089438da1f7f..783326cfbaa6 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -236,6 +236,7 @@ static void define_event_symbols(struct event_format *event,
236 cur_field_name); 236 cur_field_name);
237 break; 237 break;
238 case PRINT_HEX: 238 case PRINT_HEX:
239 case PRINT_HEX_STR:
239 define_event_symbols(event, ev_name, args->hex.field); 240 define_event_symbols(event, ev_name, args->hex.field);
240 define_event_symbols(event, ev_name, args->hex.size); 241 define_event_symbols(event, ev_name, args->hex.size);
241 break; 242 break;
@@ -368,10 +369,10 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
368 if (node->map) { 369 if (node->map) {
369 struct map *map = node->map; 370 struct map *map = node->map;
370 const char *dsoname = "[unknown]"; 371 const char *dsoname = "[unknown]";
371 if (map && map->dso && (map->dso->name || map->dso->long_name)) { 372 if (map && map->dso) {
372 if (symbol_conf.show_kernel_path && map->dso->long_name) 373 if (symbol_conf.show_kernel_path && map->dso->long_name)
373 dsoname = map->dso->long_name; 374 dsoname = map->dso->long_name;
374 else if (map->dso->name) 375 else
375 dsoname = map->dso->name; 376 dsoname = map->dso->name;
376 } 377 }
377 pydict_set_item_string_decref(pyelem, "dso", 378 pydict_set_item_string_decref(pyelem, "dso",
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f268201048a0..1dd617d116b5 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -932,7 +932,7 @@ static void branch_stack__printf(struct perf_sample *sample)
932 932
933 printf("..... %2"PRIu64": %016" PRIx64 " -> %016" PRIx64 " %hu cycles %s%s%s%s %x\n", 933 printf("..... %2"PRIu64": %016" PRIx64 " -> %016" PRIx64 " %hu cycles %s%s%s%s %x\n",
934 i, e->from, e->to, 934 i, e->from, e->to,
935 e->flags.cycles, 935 (unsigned short)e->flags.cycles,
936 e->flags.mispred ? "M" : " ", 936 e->flags.mispred ? "M" : " ",
937 e->flags.predicted ? "P" : " ", 937 e->flags.predicted ? "P" : " ",
938 e->flags.abort ? "A" : " ", 938 e->flags.abort ? "A" : " ",
@@ -1191,7 +1191,7 @@ static int
1191 u64 sample_type = evsel->attr.sample_type; 1191 u64 sample_type = evsel->attr.sample_type;
1192 u64 read_format = evsel->attr.read_format; 1192 u64 read_format = evsel->attr.read_format;
1193 1193
1194 /* Standard sample delievery. */ 1194 /* Standard sample delivery. */
1195 if (!(sample_type & PERF_SAMPLE_READ)) 1195 if (!(sample_type & PERF_SAMPLE_READ))
1196 return tool->sample(tool, event, sample, evsel, machine); 1196 return tool->sample(tool, event, sample, evsel, machine);
1197 1197
@@ -1901,7 +1901,7 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
1901 const char *symbol_name, u64 addr) 1901 const char *symbol_name, u64 addr)
1902{ 1902{
1903 char *bracket; 1903 char *bracket;
1904 enum map_type i; 1904 int i;
1905 struct ref_reloc_sym *ref; 1905 struct ref_reloc_sym *ref;
1906 1906
1907 ref = zalloc(sizeof(struct ref_reloc_sym)); 1907 ref = zalloc(sizeof(struct ref_reloc_sym));
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index c8680984d2d6..af415febbc46 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -1,8 +1,15 @@
1#!/usr/bin/python2 1#!/usr/bin/python2
2 2
3from distutils.core import setup, Extension
4from os import getenv 3from os import getenv
5 4
5cc = getenv("CC")
6if cc == "clang":
7 from _sysconfigdata import build_time_vars
8 from re import sub
9 build_time_vars["CFLAGS"] = sub("-specs=[^ ]+", "", build_time_vars["CFLAGS"])
10
11from distutils.core import setup, Extension
12
6from distutils.command.build_ext import build_ext as _build_ext 13from distutils.command.build_ext import build_ext as _build_ext
7from distutils.command.install_lib import install_lib as _install_lib 14from distutils.command.install_lib import install_lib as _install_lib
8 15
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index df622f4e301e..0ff622288d24 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -151,7 +151,7 @@ static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r)
151 if (!dso_l || !dso_r) 151 if (!dso_l || !dso_r)
152 return cmp_null(dso_r, dso_l); 152 return cmp_null(dso_r, dso_l);
153 153
154 if (verbose) { 154 if (verbose > 0) {
155 dso_name_l = dso_l->long_name; 155 dso_name_l = dso_l->long_name;
156 dso_name_r = dso_r->long_name; 156 dso_name_r = dso_r->long_name;
157 } else { 157 } else {
@@ -172,8 +172,8 @@ static int _hist_entry__dso_snprintf(struct map *map, char *bf,
172 size_t size, unsigned int width) 172 size_t size, unsigned int width)
173{ 173{
174 if (map && map->dso) { 174 if (map && map->dso) {
175 const char *dso_name = !verbose ? map->dso->short_name : 175 const char *dso_name = verbose > 0 ? map->dso->long_name :
176 map->dso->long_name; 176 map->dso->short_name;
177 return repsep_snprintf(bf, size, "%-*.*s", width, width, dso_name); 177 return repsep_snprintf(bf, size, "%-*.*s", width, width, dso_name);
178 } 178 }
179 179
@@ -261,7 +261,7 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
261{ 261{
262 size_t ret = 0; 262 size_t ret = 0;
263 263
264 if (verbose) { 264 if (verbose > 0) {
265 char o = map ? dso__symtab_origin(map->dso) : '!'; 265 char o = map ? dso__symtab_origin(map->dso) : '!';
266 ret += repsep_snprintf(bf, size, "%-#*llx %c ", 266 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
267 BITS_PER_LONG / 4 + 2, ip, o); 267 BITS_PER_LONG / 4 + 2, ip, o);
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 7aff317fc7c4..796c847e2f00 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -108,7 +108,7 @@ struct hist_entry {
108 /* 108 /*
109 * Since perf diff only supports the stdio output, TUI 109 * Since perf diff only supports the stdio output, TUI
110 * fields are only accessed from perf report (or perf 110 * fields are only accessed from perf report (or perf
111 * top). So make it an union to reduce memory usage. 111 * top). So make it a union to reduce memory usage.
112 */ 112 */
113 struct hist_entry_diff diff; 113 struct hist_entry_diff diff;
114 struct /* for TUI */ { 114 struct /* for TUI */ {
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 39345c2ddfc2..0d51334a9b46 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -344,7 +344,7 @@ int perf_stat_process_counter(struct perf_stat_config *config,
344 for (i = 0; i < 3; i++) 344 for (i = 0; i < 3; i++)
345 update_stats(&ps->res_stats[i], count[i]); 345 update_stats(&ps->res_stats[i], count[i]);
346 346
347 if (verbose) { 347 if (verbose > 0) {
348 fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 348 fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
349 perf_evsel__name(counter), count[0], count[1], count[2]); 349 perf_evsel__name(counter), count[0], count[1], count[2]);
350 } 350 }
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c
index bcae659b6546..efb53772e0ec 100644
--- a/tools/perf/util/strfilter.c
+++ b/tools/perf/util/strfilter.c
@@ -269,6 +269,7 @@ static int strfilter_node__sprint(struct strfilter_node *node, char *buf)
269 len = strfilter_node__sprint_pt(node->l, buf); 269 len = strfilter_node__sprint_pt(node->l, buf);
270 if (len < 0) 270 if (len < 0)
271 return len; 271 return len;
272 __fallthrough;
272 case '!': 273 case '!':
273 if (buf) { 274 if (buf) {
274 *(buf + len++) = *node->p; 275 *(buf + len++) = *node->p;
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index d8dfaf64b32e..bddca519dd58 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -21,6 +21,8 @@ s64 perf_atoll(const char *str)
21 case 'b': case 'B': 21 case 'b': case 'B':
22 if (*p) 22 if (*p)
23 goto out_err; 23 goto out_err;
24
25 __fallthrough;
24 case '\0': 26 case '\0':
25 return length; 27 return length;
26 default: 28 default:
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index adbc6c02c3aa..4e59ddeb4eda 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -213,7 +213,7 @@ static bool want_demangle(bool is_kernel_sym)
213 213
214static char *demangle_sym(struct dso *dso, int kmodule, const char *elf_name) 214static char *demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
215{ 215{
216 int demangle_flags = verbose ? (DMGL_PARAMS | DMGL_ANSI) : DMGL_NO_OPTS; 216 int demangle_flags = verbose > 0 ? (DMGL_PARAMS | DMGL_ANSI) : DMGL_NO_OPTS;
217 char *demangled = NULL; 217 char *demangled = NULL;
218 218
219 /* 219 /*
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index dc93940de351..70e389bc4af7 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1460,9 +1460,11 @@ int dso__load(struct dso *dso, struct map *map)
1460 * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work 1460 * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work
1461 */ 1461 */
1462 if (!dso->has_build_id && 1462 if (!dso->has_build_id &&
1463 is_regular_file(dso->long_name) && 1463 is_regular_file(dso->long_name)) {
1464 filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0) 1464 __symbol__join_symfs(name, PATH_MAX, dso->long_name);
1465 if (filename__read_build_id(name, build_id, BUILD_ID_SIZE) > 0)
1465 dso__set_build_id(dso, build_id); 1466 dso__set_build_id(dso, build_id);
1467 }
1466 1468
1467 /* 1469 /*
1468 * Iterate over candidate debug images. 1470 * Iterate over candidate debug images.
diff --git a/tools/perf/util/symbol_fprintf.c b/tools/perf/util/symbol_fprintf.c
index 7c6b33e8e2d2..63694e174e5c 100644
--- a/tools/perf/util/symbol_fprintf.c
+++ b/tools/perf/util/symbol_fprintf.c
@@ -21,7 +21,7 @@ size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
21 unsigned long offset; 21 unsigned long offset;
22 size_t length; 22 size_t length;
23 23
24 if (sym && sym->name) { 24 if (sym) {
25 length = fprintf(fp, "%s", sym->name); 25 length = fprintf(fp, "%s", sym->name);
26 if (al && print_offsets) { 26 if (al && print_offsets) {
27 if (al->addr < sym->end) 27 if (al->addr < sym->end)
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index f9eab200fd75..7c3fcc538a70 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -93,7 +93,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
93{ 93{
94 DIR *proc; 94 DIR *proc;
95 int max_threads = 32, items, i; 95 int max_threads = 32, items, i;
96 char path[256]; 96 char path[NAME_MAX + 1 + 6];
97 struct dirent *dirent, **namelist = NULL; 97 struct dirent *dirent, **namelist = NULL;
98 struct thread_map *threads = thread_map__alloc(max_threads); 98 struct thread_map *threads = thread_map__alloc(max_threads);
99 99
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index d995743cb673..e7d60d05596d 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -42,7 +42,7 @@
42#include "evsel.h" 42#include "evsel.h"
43#include "debug.h" 43#include "debug.h"
44 44
45#define VERSION "0.5" 45#define VERSION "0.6"
46 46
47static int output_fd; 47static int output_fd;
48 48
@@ -170,6 +170,12 @@ static bool name_in_tp_list(char *sys, struct tracepoint_path *tps)
170 return false; 170 return false;
171} 171}
172 172
173#define for_each_event(dir, dent, tps) \
174 while ((dent = readdir(dir))) \
175 if (dent->d_type == DT_DIR && \
176 (strcmp(dent->d_name, ".")) && \
177 (strcmp(dent->d_name, ".."))) \
178
173static int copy_event_system(const char *sys, struct tracepoint_path *tps) 179static int copy_event_system(const char *sys, struct tracepoint_path *tps)
174{ 180{
175 struct dirent *dent; 181 struct dirent *dent;
@@ -186,12 +192,10 @@ static int copy_event_system(const char *sys, struct tracepoint_path *tps)
186 return -errno; 192 return -errno;
187 } 193 }
188 194
189 while ((dent = readdir(dir))) { 195 for_each_event(dir, dent, tps) {
190 if (dent->d_type != DT_DIR || 196 if (!name_in_tp_list(dent->d_name, tps))
191 strcmp(dent->d_name, ".") == 0 ||
192 strcmp(dent->d_name, "..") == 0 ||
193 !name_in_tp_list(dent->d_name, tps))
194 continue; 197 continue;
198
195 if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) { 199 if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) {
196 err = -ENOMEM; 200 err = -ENOMEM;
197 goto out; 201 goto out;
@@ -210,12 +214,10 @@ static int copy_event_system(const char *sys, struct tracepoint_path *tps)
210 } 214 }
211 215
212 rewinddir(dir); 216 rewinddir(dir);
213 while ((dent = readdir(dir))) { 217 for_each_event(dir, dent, tps) {
214 if (dent->d_type != DT_DIR || 218 if (!name_in_tp_list(dent->d_name, tps))
215 strcmp(dent->d_name, ".") == 0 ||
216 strcmp(dent->d_name, "..") == 0 ||
217 !name_in_tp_list(dent->d_name, tps))
218 continue; 219 continue;
220
219 if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) { 221 if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) {
220 err = -ENOMEM; 222 err = -ENOMEM;
221 goto out; 223 goto out;
@@ -290,13 +292,11 @@ static int record_event_files(struct tracepoint_path *tps)
290 goto out; 292 goto out;
291 } 293 }
292 294
293 while ((dent = readdir(dir))) { 295 for_each_event(dir, dent, tps) {
294 if (dent->d_type != DT_DIR || 296 if (strcmp(dent->d_name, "ftrace") == 0 ||
295 strcmp(dent->d_name, ".") == 0 ||
296 strcmp(dent->d_name, "..") == 0 ||
297 strcmp(dent->d_name, "ftrace") == 0 ||
298 !system_in_tp_list(dent->d_name, tps)) 297 !system_in_tp_list(dent->d_name, tps))
299 continue; 298 continue;
299
300 count++; 300 count++;
301 } 301 }
302 302
@@ -307,13 +307,11 @@ static int record_event_files(struct tracepoint_path *tps)
307 } 307 }
308 308
309 rewinddir(dir); 309 rewinddir(dir);
310 while ((dent = readdir(dir))) { 310 for_each_event(dir, dent, tps) {
311 if (dent->d_type != DT_DIR || 311 if (strcmp(dent->d_name, "ftrace") == 0 ||
312 strcmp(dent->d_name, ".") == 0 ||
313 strcmp(dent->d_name, "..") == 0 ||
314 strcmp(dent->d_name, "ftrace") == 0 ||
315 !system_in_tp_list(dent->d_name, tps)) 312 !system_in_tp_list(dent->d_name, tps))
316 continue; 313 continue;
314
317 if (asprintf(&sys, "%s/%s", path, dent->d_name) < 0) { 315 if (asprintf(&sys, "%s/%s", path, dent->d_name) < 0) {
318 err = -ENOMEM; 316 err = -ENOMEM;
319 goto out; 317 goto out;
@@ -379,6 +377,34 @@ out:
379 return err; 377 return err;
380} 378}
381 379
380static int record_saved_cmdline(void)
381{
382 unsigned int size;
383 char *path;
384 struct stat st;
385 int ret, err = 0;
386
387 path = get_tracing_file("saved_cmdlines");
388 if (!path) {
389 pr_debug("can't get tracing/saved_cmdline");
390 return -ENOMEM;
391 }
392
393 ret = stat(path, &st);
394 if (ret < 0) {
395 /* not found */
396 size = 0;
397 if (write(output_fd, &size, 8) != 8)
398 err = -EIO;
399 goto out;
400 }
401 err = record_file(path, 8);
402
403out:
404 put_tracing_file(path);
405 return err;
406}
407
382static void 408static void
383put_tracepoints_path(struct tracepoint_path *tps) 409put_tracepoints_path(struct tracepoint_path *tps)
384{ 410{
@@ -539,6 +565,9 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,
539 if (err) 565 if (err)
540 goto out; 566 goto out;
541 err = record_ftrace_printk(); 567 err = record_ftrace_printk();
568 if (err)
569 goto out;
570 err = record_saved_cmdline();
542 571
543out: 572out:
544 /* 573 /*
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 33b52eaa39db..de0078e21408 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -160,6 +160,23 @@ void parse_ftrace_printk(struct pevent *pevent,
160 } 160 }
161} 161}
162 162
163void parse_saved_cmdline(struct pevent *pevent,
164 char *file, unsigned int size __maybe_unused)
165{
166 char *comm;
167 char *line;
168 char *next = NULL;
169 int pid;
170
171 line = strtok_r(file, "\n", &next);
172 while (line) {
173 sscanf(line, "%d %ms", &pid, &comm);
174 pevent_register_comm(pevent, comm, pid);
175 free(comm);
176 line = strtok_r(NULL, "\n", &next);
177 }
178}
179
163int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size) 180int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size)
164{ 181{
165 return pevent_parse_event(pevent, buf, size, "ftrace"); 182 return pevent_parse_event(pevent, buf, size, "ftrace");
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index b67a0ccf5ab9..27420159bf69 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -260,39 +260,53 @@ static int read_header_files(struct pevent *pevent)
260 260
261static int read_ftrace_file(struct pevent *pevent, unsigned long long size) 261static int read_ftrace_file(struct pevent *pevent, unsigned long long size)
262{ 262{
263 int ret;
263 char *buf; 264 char *buf;
264 265
265 buf = malloc(size); 266 buf = malloc(size);
266 if (buf == NULL) 267 if (buf == NULL) {
268 pr_debug("memory allocation failure\n");
267 return -1; 269 return -1;
270 }
268 271
269 if (do_read(buf, size) < 0) { 272 ret = do_read(buf, size);
270 free(buf); 273 if (ret < 0) {
271 return -1; 274 pr_debug("error reading ftrace file.\n");
275 goto out;
272 } 276 }
273 277
274 parse_ftrace_file(pevent, buf, size); 278 ret = parse_ftrace_file(pevent, buf, size);
279 if (ret < 0)
280 pr_debug("error parsing ftrace file.\n");
281out:
275 free(buf); 282 free(buf);
276 return 0; 283 return ret;
277} 284}
278 285
279static int read_event_file(struct pevent *pevent, char *sys, 286static int read_event_file(struct pevent *pevent, char *sys,
280 unsigned long long size) 287 unsigned long long size)
281{ 288{
289 int ret;
282 char *buf; 290 char *buf;
283 291
284 buf = malloc(size); 292 buf = malloc(size);
285 if (buf == NULL) 293 if (buf == NULL) {
294 pr_debug("memory allocation failure\n");
286 return -1; 295 return -1;
296 }
287 297
288 if (do_read(buf, size) < 0) { 298 ret = do_read(buf, size);
299 if (ret < 0) {
289 free(buf); 300 free(buf);
290 return -1; 301 goto out;
291 } 302 }
292 303
293 parse_event_file(pevent, buf, size, sys); 304 ret = parse_event_file(pevent, buf, size, sys);
305 if (ret < 0)
306 pr_debug("error parsing event file.\n");
307out:
294 free(buf); 308 free(buf);
295 return 0; 309 return ret;
296} 310}
297 311
298static int read_ftrace_files(struct pevent *pevent) 312static int read_ftrace_files(struct pevent *pevent)
@@ -341,6 +355,36 @@ static int read_event_files(struct pevent *pevent)
341 return 0; 355 return 0;
342} 356}
343 357
358static int read_saved_cmdline(struct pevent *pevent)
359{
360 unsigned long long size;
361 char *buf;
362 int ret;
363
364 /* it can have 0 size */
365 size = read8(pevent);
366 if (!size)
367 return 0;
368
369 buf = malloc(size + 1);
370 if (buf == NULL) {
371 pr_debug("memory allocation failure\n");
372 return -1;
373 }
374
375 ret = do_read(buf, size);
376 if (ret < 0) {
377 pr_debug("error reading saved cmdlines\n");
378 goto out;
379 }
380
381 parse_saved_cmdline(pevent, buf, size);
382 ret = 0;
383out:
384 free(buf);
385 return ret;
386}
387
344ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe) 388ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
345{ 389{
346 char buf[BUFSIZ]; 390 char buf[BUFSIZ];
@@ -379,10 +423,11 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
379 return -1; 423 return -1;
380 if (show_version) 424 if (show_version)
381 printf("version = %s\n", version); 425 printf("version = %s\n", version);
382 free(version);
383 426
384 if (do_read(buf, 1) < 0) 427 if (do_read(buf, 1) < 0) {
428 free(version);
385 return -1; 429 return -1;
430 }
386 file_bigendian = buf[0]; 431 file_bigendian = buf[0];
387 host_bigendian = bigendian(); 432 host_bigendian = bigendian();
388 433
@@ -423,6 +468,11 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
423 err = read_ftrace_printk(pevent); 468 err = read_ftrace_printk(pevent);
424 if (err) 469 if (err)
425 goto out; 470 goto out;
471 if (atof(version) >= 0.6) {
472 err = read_saved_cmdline(pevent);
473 if (err)
474 goto out;
475 }
426 476
427 size = trace_data_size; 477 size = trace_data_size;
428 repipe = false; 478 repipe = false;
@@ -438,5 +488,6 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
438out: 488out:
439 if (pevent) 489 if (pevent)
440 trace_event__cleanup(tevent); 490 trace_event__cleanup(tevent);
491 free(version);
441 return size; 492 return size;
442} 493}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index b0af9c81bb0d..1fbc044f9eb0 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -42,6 +42,7 @@ raw_field_value(struct event_format *event, const char *name, void *data);
42 42
43void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); 43void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
44void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); 44void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
45void parse_saved_cmdline(struct pevent *pevent, char *file, unsigned int size);
45 46
46ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe); 47ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe);
47 48
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index 6fec84dff3f7..bfb9b7987692 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -35,6 +35,7 @@
35#include "util.h" 35#include "util.h"
36#include "debug.h" 36#include "debug.h"
37#include "asm/bug.h" 37#include "asm/bug.h"
38#include "dso.h"
38 39
39extern int 40extern int
40UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, 41UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
@@ -297,15 +298,58 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
297 int fd; 298 int fd;
298 u64 ofs = dso->data.debug_frame_offset; 299 u64 ofs = dso->data.debug_frame_offset;
299 300
301 /* debug_frame can reside in:
302 * - dso
303 * - debug pointed by symsrc_filename
304 * - gnu_debuglink, which doesn't necessary
305 * has to be pointed by symsrc_filename
306 */
300 if (ofs == 0) { 307 if (ofs == 0) {
301 fd = dso__data_get_fd(dso, machine); 308 fd = dso__data_get_fd(dso, machine);
302 if (fd < 0) 309 if (fd >= 0) {
303 return -EINVAL; 310 ofs = elf_section_offset(fd, ".debug_frame");
311 dso__data_put_fd(dso);
312 }
313
314 if (ofs <= 0) {
315 fd = open(dso->symsrc_filename, O_RDONLY);
316 if (fd >= 0) {
317 ofs = elf_section_offset(fd, ".debug_frame");
318 close(fd);
319 }
320 }
321
322 if (ofs <= 0) {
323 char *debuglink = malloc(PATH_MAX);
324 int ret = 0;
325
326 ret = dso__read_binary_type_filename(
327 dso, DSO_BINARY_TYPE__DEBUGLINK,
328 machine->root_dir, debuglink, PATH_MAX);
329 if (!ret) {
330 fd = open(debuglink, O_RDONLY);
331 if (fd >= 0) {
332 ofs = elf_section_offset(fd,
333 ".debug_frame");
334 close(fd);
335 }
336 }
337 if (ofs > 0) {
338 if (dso->symsrc_filename != NULL) {
339 pr_warning(
340 "%s: overwrite symsrc(%s,%s)\n",
341 __func__,
342 dso->symsrc_filename,
343 debuglink);
344 free(dso->symsrc_filename);
345 }
346 dso->symsrc_filename = debuglink;
347 } else {
348 free(debuglink);
349 }
350 }
304 351
305 /* Check the .debug_frame section for unwinding info */
306 ofs = elf_section_offset(fd, ".debug_frame");
307 dso->data.debug_frame_offset = ofs; 352 dso->data.debug_frame_offset = ofs;
308 dso__data_put_fd(dso);
309 } 353 }
310 354
311 *offset = ofs; 355 *offset = ofs;
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 9ddd98827d12..d8b45cea54d0 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -85,7 +85,7 @@ int mkdir_p(char *path, mode_t mode)
85 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 85 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
86} 86}
87 87
88int rm_rf(char *path) 88int rm_rf(const char *path)
89{ 89{
90 DIR *dir; 90 DIR *dir;
91 int ret = 0; 91 int ret = 0;
@@ -789,3 +789,16 @@ int is_printable_array(char *p, unsigned int len)
789 } 789 }
790 return 1; 790 return 1;
791} 791}
792
793int unit_number__scnprintf(char *buf, size_t size, u64 n)
794{
795 char unit[4] = "BKMG";
796 int i = 0;
797
798 while (((n / 1024) > 1) && (i < 3)) {
799 n /= 1024;
800 i++;
801 }
802
803 return scnprintf(buf, size, "%" PRIu64 "%c", n, unit[i]);
804}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 1d639e38aa82..c74708da8571 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -209,7 +209,7 @@ static inline int sane_case(int x, int high)
209} 209}
210 210
211int mkdir_p(char *path, mode_t mode); 211int mkdir_p(char *path, mode_t mode);
212int rm_rf(char *path); 212int rm_rf(const char *path);
213struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dirent *)); 213struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dirent *));
214bool lsdir_no_dot_filter(const char *name, struct dirent *d); 214bool lsdir_no_dot_filter(const char *name, struct dirent *d);
215int copyfile(const char *from, const char *to); 215int copyfile(const char *from, const char *to);
@@ -363,4 +363,5 @@ int is_printable_array(char *p, unsigned int len);
363 363
364int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz); 364int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz);
365 365
366int unit_number__scnprintf(char *buf, size_t size, u64 n);
366#endif /* GIT_COMPAT_UTIL_H */ 367#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/power/acpi/common/cmfsize.c b/tools/power/acpi/common/cmfsize.c
index bc82596d7354..5b38dc2fec4f 100644
--- a/tools/power/acpi/common/cmfsize.c
+++ b/tools/power/acpi/common/cmfsize.c
@@ -5,7 +5,7 @@
5 *****************************************************************************/ 5 *****************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2016, Intel Corp. 8 * Copyright (C) 2000 - 2017, Intel Corp.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
diff --git a/tools/power/acpi/common/getopt.c b/tools/power/acpi/common/getopt.c
index 3919970f5aea..6e78413bb2cb 100644
--- a/tools/power/acpi/common/getopt.c
+++ b/tools/power/acpi/common/getopt.c
@@ -5,7 +5,7 @@
5 *****************************************************************************/ 5 *****************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2016, Intel Corp. 8 * Copyright (C) 2000 - 2017, Intel Corp.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
diff --git a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
index 546cf4a503b7..82a2ff896a95 100644
--- a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
+++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
@@ -5,7 +5,7 @@
5 *****************************************************************************/ 5 *****************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2016, Intel Corp. 8 * Copyright (C) 2000 - 2017, Intel Corp.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
diff --git a/tools/power/acpi/os_specific/service_layers/osunixdir.c b/tools/power/acpi/os_specific/service_layers/osunixdir.c
index 66c4badf03e5..ea14eaeb268f 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixdir.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixdir.c
@@ -5,7 +5,7 @@
5 *****************************************************************************/ 5 *****************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2016, Intel Corp. 8 * Copyright (C) 2000 - 2017, Intel Corp.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
diff --git a/tools/power/acpi/os_specific/service_layers/osunixmap.c b/tools/power/acpi/os_specific/service_layers/osunixmap.c
index cbfbce18783d..cf9b5a54df92 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixmap.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixmap.c
@@ -5,7 +5,7 @@
5 *****************************************************************************/ 5 *****************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2016, Intel Corp. 8 * Copyright (C) 2000 - 2017, Intel Corp.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c
index 10648aaf6164..c04e8fea2c60 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixxf.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c
@@ -5,7 +5,7 @@
5 *****************************************************************************/ 5 *****************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2016, Intel Corp. 8 * Copyright (C) 2000 - 2017, Intel Corp.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
@@ -318,6 +318,28 @@ acpi_os_physical_table_override(struct acpi_table_header *existing_table,
318 318
319/****************************************************************************** 319/******************************************************************************
320 * 320 *
321 * FUNCTION: acpi_os_enter_sleep
322 *
323 * PARAMETERS: sleep_state - Which sleep state to enter
324 * rega_value - Register A value
325 * regb_value - Register B value
326 *
327 * RETURN: Status
328 *
329 * DESCRIPTION: A hook before writing sleep registers to enter the sleep
330 * state. Return AE_CTRL_TERMINATE to skip further sleep register
331 * writes.
332 *
333 *****************************************************************************/
334
335acpi_status acpi_os_enter_sleep(u8 sleep_state, u32 rega_value, u32 regb_value)
336{
337
338 return (AE_OK);
339}
340
341/******************************************************************************
342 *
321 * FUNCTION: acpi_os_redirect_output 343 * FUNCTION: acpi_os_redirect_output
322 * 344 *
323 * PARAMETERS: destination - An open file handle/pointer 345 * PARAMETERS: destination - An open file handle/pointer
diff --git a/tools/power/acpi/tools/acpidump/acpidump.h b/tools/power/acpi/tools/acpidump/acpidump.h
index 00423fc45e7c..d6aa40fce2b1 100644
--- a/tools/power/acpi/tools/acpidump/acpidump.h
+++ b/tools/power/acpi/tools/acpidump/acpidump.h
@@ -5,7 +5,7 @@
5 *****************************************************************************/ 5 *****************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2016, Intel Corp. 8 * Copyright (C) 2000 - 2017, Intel Corp.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c
index 9031be1afe63..60df1fbd4a77 100644
--- a/tools/power/acpi/tools/acpidump/apdump.c
+++ b/tools/power/acpi/tools/acpidump/apdump.c
@@ -5,7 +5,7 @@
5 *****************************************************************************/ 5 *****************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2016, Intel Corp. 8 * Copyright (C) 2000 - 2017, Intel Corp.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c
index dd5b861dc4a8..31b5a7f74015 100644
--- a/tools/power/acpi/tools/acpidump/apfiles.c
+++ b/tools/power/acpi/tools/acpidump/apfiles.c
@@ -5,7 +5,7 @@
5 *****************************************************************************/ 5 *****************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2016, Intel Corp. 8 * Copyright (C) 2000 - 2017, Intel Corp.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c
index 7ff46be908f0..dd82afa897bd 100644
--- a/tools/power/acpi/tools/acpidump/apmain.c
+++ b/tools/power/acpi/tools/acpidump/apmain.c
@@ -5,7 +5,7 @@
5 *****************************************************************************/ 5 *****************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2016, Intel Corp. 8 * Copyright (C) 2000 - 2017, Intel Corp.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
index 590d12a25f6e..3e701f0e9c14 100644
--- a/tools/power/cpupower/utils/cpufreq-info.c
+++ b/tools/power/cpupower/utils/cpufreq-info.c
@@ -285,20 +285,24 @@ static int get_freq_hardware(unsigned int cpu, unsigned int human)
285 285
286/* --hwlimits / -l */ 286/* --hwlimits / -l */
287 287
288static int get_hardware_limits(unsigned int cpu) 288static int get_hardware_limits(unsigned int cpu, unsigned int human)
289{ 289{
290 unsigned long min, max; 290 unsigned long min, max;
291 291
292 printf(_(" hardware limits: "));
293 if (cpufreq_get_hardware_limits(cpu, &min, &max)) { 292 if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
294 printf(_("Not Available\n")); 293 printf(_("Not Available\n"));
295 return -EINVAL; 294 return -EINVAL;
296 } 295 }
297 296
298 print_speed(min); 297 if (human) {
299 printf(" - "); 298 printf(_(" hardware limits: "));
300 print_speed(max); 299 print_speed(min);
301 printf("\n"); 300 printf(" - ");
301 print_speed(max);
302 printf("\n");
303 } else {
304 printf("%lu %lu\n", min, max);
305 }
302 return 0; 306 return 0;
303} 307}
304 308
@@ -456,7 +460,7 @@ static void debug_output_one(unsigned int cpu)
456 get_related_cpus(cpu); 460 get_related_cpus(cpu);
457 get_affected_cpus(cpu); 461 get_affected_cpus(cpu);
458 get_latency(cpu, 1); 462 get_latency(cpu, 1);
459 get_hardware_limits(cpu); 463 get_hardware_limits(cpu, 1);
460 464
461 freqs = cpufreq_get_available_frequencies(cpu); 465 freqs = cpufreq_get_available_frequencies(cpu);
462 if (freqs) { 466 if (freqs) {
@@ -622,7 +626,7 @@ int cmd_freq_info(int argc, char **argv)
622 ret = get_driver(cpu); 626 ret = get_driver(cpu);
623 break; 627 break;
624 case 'l': 628 case 'l':
625 ret = get_hardware_limits(cpu); 629 ret = get_hardware_limits(cpu, human);
626 break; 630 break;
627 case 'w': 631 case 'w':
628 ret = get_freq_hardware(cpu, human); 632 ret = get_freq_hardware(cpu, human);
@@ -639,7 +643,6 @@ int cmd_freq_info(int argc, char **argv)
639 } 643 }
640 if (ret) 644 if (ret)
641 return ret; 645 return ret;
642 printf("\n");
643 } 646 }
644 return ret; 647 return ret;
645} 648}
diff --git a/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py b/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
new file mode 100755
index 000000000000..fd706ac0f347
--- /dev/null
+++ b/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
@@ -0,0 +1,569 @@
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3#
4""" This utility can be used to debug and tune the performance of the
5intel_pstate driver. This utility can be used in two ways:
6- If there is Linux trace file with pstate_sample events enabled, then
7this utility can parse the trace file and generate performance plots.
8- If user has not specified a trace file as input via command line parameters,
9then this utility enables and collects trace data for a user specified interval
10and generates performance plots.
11
12Prerequisites:
13 Python version 2.7.x
14 gnuplot 5.0 or higher
15 gnuplot-py 1.8
16 (Most of the distributions have these required packages. They may be called
17 gnuplot-py, phython-gnuplot. )
18
19 HWP (Hardware P-States are disabled)
20 Kernel config for Linux trace is enabled
21
22 see print_help(): for Usage and Output details
23
24"""
25from __future__ import print_function
26from datetime import datetime
27import subprocess
28import os
29import time
30import re
31import sys
32import getopt
33import Gnuplot
34from numpy import *
35from decimal import *
36
37__author__ = "Srinivas Pandruvada"
38__copyright__ = " Copyright (c) 2017, Intel Corporation. "
39__license__ = "GPL version 2"
40
41
42MAX_CPUS = 256
43
44# Define the csv file columns
45C_COMM = 18
46C_GHZ = 17
47C_ELAPSED = 16
48C_SAMPLE = 15
49C_DURATION = 14
50C_LOAD = 13
51C_BOOST = 12
52C_FREQ = 11
53C_TSC = 10
54C_APERF = 9
55C_MPERF = 8
56C_TO = 7
57C_FROM = 6
58C_SCALED = 5
59C_CORE = 4
60C_USEC = 3
61C_SEC = 2
62C_CPU = 1
63
64global sample_num, last_sec_cpu, last_usec_cpu, start_time, testname
65
66# 11 digits covers uptime to 115 days
67getcontext().prec = 11
68
69sample_num =0
70last_sec_cpu = [0] * MAX_CPUS
71last_usec_cpu = [0] * MAX_CPUS
72
73def print_help():
74 print('intel_pstate_tracer.py:')
75 print(' Usage:')
76 print(' If the trace file is available, then to simply parse and plot, use (sudo not required):')
77 print(' ./intel_pstate_tracer.py [-c cpus] -t <trace_file> -n <test_name>')
78 print(' Or')
79 print(' ./intel_pstate_tracer.py [--cpu cpus] ---trace_file <trace_file> --name <test_name>')
80 print(' To generate trace file, parse and plot, use (sudo required):')
81 print(' sudo ./intel_pstate_tracer.py [-c cpus] -i <interval> -n <test_name>')
82 print(' Or')
83 print(' sudo ./intel_pstate_tracer.py [--cpu cpus] --interval <interval> --name <test_name>')
84 print(' Optional argument:')
85 print(' cpus: comma separated list of CPUs')
86 print(' Output:')
87 print(' If not already present, creates a "results/test_name" folder in the current working directory with:')
88 print(' cpu.csv - comma seperated values file with trace contents and some additional calculations.')
89 print(' cpu???.csv - comma seperated values file for CPU number ???.')
90 print(' *.png - a variety of PNG format plot files created from the trace contents and the additional calculations.')
91 print(' Notes:')
92 print(' Avoid the use of _ (underscore) in test names, because in gnuplot it is a subscript directive.')
93 print(' Maximum number of CPUs is {0:d}. If there are more the script will abort with an error.'.format(MAX_CPUS))
94 print(' Off-line CPUs cause the script to list some warnings, and create some empty files. Use the CPU mask feature for a clean run.')
95 print(' Empty y range warnings for autoscaled plots can occur and can be ignored.')
96
97def plot_perf_busy_with_sample(cpu_index):
98 """ Plot method to per cpu information """
99
100 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
101 if os.path.exists(file_name):
102 output_png = "cpu%03d_perf_busy_vs_samples.png" % cpu_index
103 g_plot = common_all_gnuplot_settings(output_png)
104 g_plot('set yrange [0:40]')
105 g_plot('set y2range [0:200]')
106 g_plot('set y2tics 0, 10')
107 g_plot('set title "{} : cpu perf busy vs. sample : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
108# Override common
109 g_plot('set xlabel "Samples"')
110 g_plot('set ylabel "P-State"')
111 g_plot('set y2label "Scaled Busy/performance/io-busy(%)"')
112 set_4_plot_linestyles(g_plot)
113 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y2 title "performance",\\'.format(C_SAMPLE, C_CORE))
114 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 2 axis x1y2 title "scaled-busy",\\'.format(C_SAMPLE, C_SCALED))
115 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 3 axis x1y2 title "io-boost",\\'.format(C_SAMPLE, C_BOOST))
116 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 4 axis x1y1 title "P-State"'.format(C_SAMPLE, C_TO))
117
118def plot_perf_busy(cpu_index):
119 """ Plot some per cpu information """
120
121 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
122 if os.path.exists(file_name):
123 output_png = "cpu%03d_perf_busy.png" % cpu_index
124 g_plot = common_all_gnuplot_settings(output_png)
125 g_plot('set yrange [0:40]')
126 g_plot('set y2range [0:200]')
127 g_plot('set y2tics 0, 10')
128 g_plot('set title "{} : perf busy : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
129 g_plot('set ylabel "P-State"')
130 g_plot('set y2label "Scaled Busy/performance/io-busy(%)"')
131 set_4_plot_linestyles(g_plot)
132 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y2 title "performance",\\'.format(C_ELAPSED, C_CORE))
133 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 2 axis x1y2 title "scaled-busy",\\'.format(C_ELAPSED, C_SCALED))
134 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 3 axis x1y2 title "io-boost",\\'.format(C_ELAPSED, C_BOOST))
135 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 4 axis x1y1 title "P-State"'.format(C_ELAPSED, C_TO))
136
137def plot_durations(cpu_index):
138 """ Plot per cpu durations """
139
140 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
141 if os.path.exists(file_name):
142 output_png = "cpu%03d_durations.png" % cpu_index
143 g_plot = common_all_gnuplot_settings(output_png)
144# Should autoscale be used here? Should seconds be used here?
145 g_plot('set yrange [0:5000]')
146 g_plot('set ytics 0, 500')
147 g_plot('set title "{} : durations : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
148 g_plot('set ylabel "Timer Duration (MilliSeconds)"')
149# override common
150 g_plot('set key off')
151 set_4_plot_linestyles(g_plot)
152 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_DURATION))
153
154def plot_loads(cpu_index):
155 """ Plot per cpu loads """
156
157 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
158 if os.path.exists(file_name):
159 output_png = "cpu%03d_loads.png" % cpu_index
160 g_plot = common_all_gnuplot_settings(output_png)
161 g_plot('set yrange [0:100]')
162 g_plot('set ytics 0, 10')
163 g_plot('set title "{} : loads : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
164 g_plot('set ylabel "CPU load (percent)"')
165# override common
166 g_plot('set key off')
167 set_4_plot_linestyles(g_plot)
168 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_LOAD))
169
170def plot_pstate_cpu_with_sample():
171 """ Plot all cpu information """
172
173 if os.path.exists('cpu.csv'):
174 output_png = 'all_cpu_pstates_vs_samples.png'
175 g_plot = common_all_gnuplot_settings(output_png)
176 g_plot('set yrange [0:40]')
177# override common
178 g_plot('set xlabel "Samples"')
179 g_plot('set ylabel "P-State"')
180 g_plot('set title "{} : cpu pstate vs. sample : {:%F %H:%M}"'.format(testname, datetime.now()))
181 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
182 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_SAMPLE, C_TO)
183 g_plot('title_list = "{}"'.format(title_list))
184 g_plot(plot_str)
185
186def plot_pstate_cpu():
187 """ Plot all cpu information from csv files """
188
189 output_png = 'all_cpu_pstates.png'
190 g_plot = common_all_gnuplot_settings(output_png)
191 g_plot('set yrange [0:40]')
192 g_plot('set ylabel "P-State"')
193 g_plot('set title "{} : cpu pstates : {:%F %H:%M}"'.format(testname, datetime.now()))
194
195# the following command is really cool, but doesn't work with the CPU masking option because it aborts on the first missing file.
196# plot_str = 'plot for [i=0:*] file=sprintf("cpu%03d.csv",i) title_s=sprintf("cpu%03d",i) file using 16:7 pt 7 ps 1 title title_s'
197#
198 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
199 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_TO)
200 g_plot('title_list = "{}"'.format(title_list))
201 g_plot(plot_str)
202
203def plot_load_cpu():
204 """ Plot all cpu loads """
205
206 output_png = 'all_cpu_loads.png'
207 g_plot = common_all_gnuplot_settings(output_png)
208 g_plot('set yrange [0:100]')
209 g_plot('set ylabel "CPU load (percent)"')
210 g_plot('set title "{} : cpu loads : {:%F %H:%M}"'.format(testname, datetime.now()))
211
212 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
213 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_LOAD)
214 g_plot('title_list = "{}"'.format(title_list))
215 g_plot(plot_str)
216
217def plot_frequency_cpu():
218 """ Plot all cpu frequencies """
219
220 output_png = 'all_cpu_frequencies.png'
221 g_plot = common_all_gnuplot_settings(output_png)
222 g_plot('set yrange [0:4]')
223 g_plot('set ylabel "CPU Frequency (GHz)"')
224 g_plot('set title "{} : cpu frequencies : {:%F %H:%M}"'.format(testname, datetime.now()))
225
226 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
227 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_FREQ)
228 g_plot('title_list = "{}"'.format(title_list))
229 g_plot(plot_str)
230
231def plot_duration_cpu():
232 """ Plot all cpu durations """
233
234 output_png = 'all_cpu_durations.png'
235 g_plot = common_all_gnuplot_settings(output_png)
236 g_plot('set yrange [0:5000]')
237 g_plot('set ytics 0, 500')
238 g_plot('set ylabel "Timer Duration (MilliSeconds)"')
239 g_plot('set title "{} : cpu durations : {:%F %H:%M}"'.format(testname, datetime.now()))
240
241 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
242 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_DURATION)
243 g_plot('title_list = "{}"'.format(title_list))
244 g_plot(plot_str)
245
246def plot_scaled_cpu():
247 """ Plot all cpu scaled busy """
248
249 output_png = 'all_cpu_scaled.png'
250 g_plot = common_all_gnuplot_settings(output_png)
251# autoscale this one, no set y range
252 g_plot('set ylabel "Scaled Busy (Unitless)"')
253 g_plot('set title "{} : cpu scaled busy : {:%F %H:%M}"'.format(testname, datetime.now()))
254
255 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
256 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_SCALED)
257 g_plot('title_list = "{}"'.format(title_list))
258 g_plot(plot_str)
259
260def plot_boost_cpu():
261 """ Plot all cpu IO Boosts """
262
263 output_png = 'all_cpu_boost.png'
264 g_plot = common_all_gnuplot_settings(output_png)
265 g_plot('set yrange [0:100]')
266 g_plot('set ylabel "CPU IO Boost (percent)"')
267 g_plot('set title "{} : cpu io boost : {:%F %H:%M}"'.format(testname, datetime.now()))
268
269 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
270 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_BOOST)
271 g_plot('title_list = "{}"'.format(title_list))
272 g_plot(plot_str)
273
274def plot_ghz_cpu():
275 """ Plot all cpu tsc ghz """
276
277 output_png = 'all_cpu_ghz.png'
278 g_plot = common_all_gnuplot_settings(output_png)
279# autoscale this one, no set y range
280 g_plot('set ylabel "TSC Frequency (GHz)"')
281 g_plot('set title "{} : cpu TSC Frequencies (Sanity check calculation) : {:%F %H:%M}"'.format(testname, datetime.now()))
282
283 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
284 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_GHZ)
285 g_plot('title_list = "{}"'.format(title_list))
286 g_plot(plot_str)
287
288def common_all_gnuplot_settings(output_png):
289 """ common gnuplot settings for multiple CPUs one one graph. """
290
291 g_plot = common_gnuplot_settings()
292 g_plot('set output "' + output_png + '"')
293 return(g_plot)
294
295def common_gnuplot_settings():
296 """ common gnuplot settings. """
297
298 g_plot = Gnuplot.Gnuplot(persist=1)
299# The following line is for rigor only. It seems to be assumed for .csv files
300 g_plot('set datafile separator \",\"')
301 g_plot('set ytics nomirror')
302 g_plot('set xtics nomirror')
303 g_plot('set xtics font ", 10"')
304 g_plot('set ytics font ", 10"')
305 g_plot('set tics out scale 1.0')
306 g_plot('set grid')
307 g_plot('set key out horiz')
308 g_plot('set key bot center')
309 g_plot('set key samplen 2 spacing .8 font ", 9"')
310 g_plot('set term png size 1200, 600')
311 g_plot('set title font ", 11"')
312 g_plot('set ylabel font ", 10"')
313 g_plot('set xlabel font ", 10"')
314 g_plot('set xlabel offset 0, 0.5')
315 g_plot('set xlabel "Elapsed Time (Seconds)"')
316 return(g_plot)
317
318def set_4_plot_linestyles(g_plot):
319 """ set the linestyles used for 4 plots in 1 graphs. """
320
321 g_plot('set style line 1 linetype 1 linecolor rgb "green" pointtype -1')
322 g_plot('set style line 2 linetype 1 linecolor rgb "red" pointtype -1')
323 g_plot('set style line 3 linetype 1 linecolor rgb "purple" pointtype -1')
324 g_plot('set style line 4 linetype 1 linecolor rgb "blue" pointtype -1')
325
326def store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz):
327 """ Store master csv file information """
328
329 global graph_data_present
330
331 if cpu_mask[cpu_int] == 0:
332 return
333
334 try:
335 f_handle = open('cpu.csv', 'a')
336 string_buffer = "CPU_%03u, %05u, %06u, %u, %u, %u, %u, %u, %u, %u, %.4f, %u, %.2f, %.3f, %u, %.3f, %.3f, %s\n" % (cpu_int, int(time_pre_dec), int(time_post_dec), int(core_busy), int(scaled), int(_from), int(_to), int(mperf), int(aperf), int(tsc), freq_ghz, int(io_boost), load, duration_ms, sample_num, elapsed_time, tsc_ghz, common_comm)
337 f_handle.write(string_buffer);
338 f_handle.close()
339 except:
340 print('IO error cpu.csv')
341 return
342
343 graph_data_present = True;
344
345def split_csv():
346 """ seperate the all csv file into per CPU csv files. """
347
348 global current_max_cpu
349
350 if os.path.exists('cpu.csv'):
351 for index in range(0, current_max_cpu + 1):
352 if cpu_mask[int(index)] != 0:
353 os.system('grep -m 1 common_cpu cpu.csv > cpu{:0>3}.csv'.format(index))
354 os.system('grep CPU_{:0>3} cpu.csv >> cpu{:0>3}.csv'.format(index, index))
355
356def cleanup_data_files():
357 """ clean up existing data files """
358
359 if os.path.exists('cpu.csv'):
360 os.remove('cpu.csv')
361 f_handle = open('cpu.csv', 'a')
362 f_handle.write('common_cpu, common_secs, common_usecs, core_busy, scaled_busy, from, to, mperf, aperf, tsc, freq, boost, load, duration_ms, sample_num, elapsed_time, tsc_ghz, common_comm')
363 f_handle.write('\n')
364 f_handle.close()
365
366def clear_trace_file():
367 """ Clear trace file """
368
369 try:
370 f_handle = open('/sys/kernel/debug/tracing/trace', 'w')
371 f_handle.close()
372 except:
373 print('IO error clearing trace file ')
374 quit()
375
376def enable_trace():
377 """ Enable trace """
378
379 try:
380 open('/sys/kernel/debug/tracing/events/power/pstate_sample/enable'
381 , 'w').write("1")
382 except:
383 print('IO error enabling trace ')
384 quit()
385
386def disable_trace():
387 """ Disable trace """
388
389 try:
390 open('/sys/kernel/debug/tracing/events/power/pstate_sample/enable'
391 , 'w').write("0")
392 except:
393 print('IO error disabling trace ')
394 quit()
395
396def set_trace_buffer_size():
397 """ Set trace buffer size """
398
399 try:
400 open('/sys/kernel/debug/tracing/buffer_size_kb'
401 , 'w').write("10240")
402 except:
403 print('IO error setting trace buffer size ')
404 quit()
405
406def read_trace_data(filename):
407 """ Read and parse trace data """
408
409 global current_max_cpu
410 global sample_num, last_sec_cpu, last_usec_cpu, start_time
411
412 try:
413 data = open(filename, 'r').read()
414 except:
415 print('Error opening ', filename)
416 quit()
417
418 for line in data.splitlines():
419 search_obj = \
420 re.search(r'(^(.*?)\[)((\d+)[^\]])(.*?)(\d+)([.])(\d+)(.*?core_busy=)(\d+)(.*?scaled=)(\d+)(.*?from=)(\d+)(.*?to=)(\d+)(.*?mperf=)(\d+)(.*?aperf=)(\d+)(.*?tsc=)(\d+)(.*?freq=)(\d+)'
421 , line)
422
423 if search_obj:
424 cpu = search_obj.group(3)
425 cpu_int = int(cpu)
426 cpu = str(cpu_int)
427
428 time_pre_dec = search_obj.group(6)
429 time_post_dec = search_obj.group(8)
430 core_busy = search_obj.group(10)
431 scaled = search_obj.group(12)
432 _from = search_obj.group(14)
433 _to = search_obj.group(16)
434 mperf = search_obj.group(18)
435 aperf = search_obj.group(20)
436 tsc = search_obj.group(22)
437 freq = search_obj.group(24)
438 common_comm = search_obj.group(2).replace(' ', '')
439
440 # Not all kernel versions have io_boost field
441 io_boost = '0'
442 search_obj = re.search(r'.*?io_boost=(\d+)', line)
443 if search_obj:
444 io_boost = search_obj.group(1)
445
446 if sample_num == 0 :
447 start_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000)
448 sample_num += 1
449
450 if last_sec_cpu[cpu_int] == 0 :
451 last_sec_cpu[cpu_int] = time_pre_dec
452 last_usec_cpu[cpu_int] = time_post_dec
453 else :
454 duration_us = (int(time_pre_dec) - int(last_sec_cpu[cpu_int])) * 1000000 + (int(time_post_dec) - int(last_usec_cpu[cpu_int]))
455 duration_ms = Decimal(duration_us) / Decimal(1000)
456 last_sec_cpu[cpu_int] = time_pre_dec
457 last_usec_cpu[cpu_int] = time_post_dec
458 elapsed_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000) - start_time
459 load = Decimal(int(mperf)*100)/ Decimal(tsc)
460 freq_ghz = Decimal(freq)/Decimal(1000000)
461# Sanity check calculation, typically anomalies indicate missed samples
462# However, check for 0 (should never occur)
463 tsc_ghz = Decimal(0)
464 if duration_ms != Decimal(0) :
465 tsc_ghz = Decimal(tsc)/duration_ms/Decimal(1000000)
466 store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz)
467
468 if cpu_int > current_max_cpu:
469 current_max_cpu = cpu_int
470# End of for each trace line loop
471# Now seperate the main overall csv file into per CPU csv files.
472 split_csv()
473
474interval = ""
475filename = ""
476cpu_list = ""
477testname = ""
478graph_data_present = False;
479
480valid1 = False
481valid2 = False
482
483cpu_mask = zeros((MAX_CPUS,), dtype=int)
484
485try:
486 opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:",["help","trace_file=","interval=","cpu=","name="])
487except getopt.GetoptError:
488 print_help()
489 sys.exit(2)
490for opt, arg in opts:
491 if opt == '-h':
492 print()
493 sys.exit()
494 elif opt in ("-t", "--trace_file"):
495 valid1 = True
496 location = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
497 filename = os.path.join(location, arg)
498 elif opt in ("-i", "--interval"):
499 valid1 = True
500 interval = arg
501 elif opt in ("-c", "--cpu"):
502 cpu_list = arg
503 elif opt in ("-n", "--name"):
504 valid2 = True
505 testname = arg
506
507if not (valid1 and valid2):
508 print_help()
509 sys.exit()
510
511if cpu_list:
512 for p in re.split("[,]", cpu_list):
513 if int(p) < MAX_CPUS :
514 cpu_mask[int(p)] = 1
515else:
516 for i in range (0, MAX_CPUS):
517 cpu_mask[i] = 1
518
519if not os.path.exists('results'):
520 os.mkdir('results')
521
522os.chdir('results')
523if os.path.exists(testname):
524 print('The test name directory already exists. Please provide a unique test name. Test re-run not supported, yet.')
525 sys.exit()
526os.mkdir(testname)
527os.chdir(testname)
528
529# Temporary (or perhaps not)
530cur_version = sys.version_info
531print('python version (should be >= 2.7):')
532print(cur_version)
533
534# Left as "cleanup" for potential future re-run ability.
535cleanup_data_files()
536
537if interval:
538 filename = "/sys/kernel/debug/tracing/trace"
539 clear_trace_file()
540 set_trace_buffer_size()
541 enable_trace()
542 print('Sleeping for ', interval, 'seconds')
543 time.sleep(int(interval))
544 disable_trace()
545
546current_max_cpu = 0
547
548read_trace_data(filename)
549
550if graph_data_present == False:
551 print('No valid data to plot')
552 sys.exit(2)
553
554for cpu_no in range(0, current_max_cpu + 1):
555 plot_perf_busy_with_sample(cpu_no)
556 plot_perf_busy(cpu_no)
557 plot_durations(cpu_no)
558 plot_loads(cpu_no)
559
560plot_pstate_cpu_with_sample()
561plot_pstate_cpu()
562plot_load_cpu()
563plot_frequency_cpu()
564plot_duration_cpu()
565plot_scaled_cpu()
566plot_boost_cpu()
567plot_ghz_cpu()
568
569os.chdir('../../')
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index 03cb639b292e..fedca3285326 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -16,9 +16,9 @@ idle power-state statistics, temperature and power on X86 processors.
16There are two ways to invoke turbostat. 16There are two ways to invoke turbostat.
17The first method is to supply a 17The first method is to supply a
18\fBcommand\fP, which is forked and statistics are printed 18\fBcommand\fP, which is forked and statistics are printed
19upon its completion. 19in one-shot upon its completion.
20The second method is to omit the command, 20The second method is to omit the command,
21and turbostat displays statistics every 5 seconds. 21and turbostat displays statistics every 5 seconds interval.
22The 5-second interval can be changed using the --interval option. 22The 5-second interval can be changed using the --interval option.
23.PP 23.PP
24Some information is not available on older processors. 24Some information is not available on older processors.
@@ -28,9 +28,10 @@ name as necessary to disambiguate it from others is necessary. Note that option
28.PP 28.PP
29\fB--add attributes\fP add column with counter having specified 'attributes'. The 'location' attribute is required, all others are optional. 29\fB--add attributes\fP add column with counter having specified 'attributes'. The 'location' attribute is required, all others are optional.
30.nf 30.nf
31 location: {\fBmsrDDD\fP | \fBmsr0xXXX\fP} 31 location: {\fBmsrDDD\fP | \fBmsr0xXXX\fP | \fB/sys/path...\fP}
32 msrDDD is a decimal offset, eg. msr16 32 msrDDD is a decimal offset, eg. msr16
33 msr0xXXX is a hex offset, eg. msr0x10 33 msr0xXXX is a hex offset, eg. msr0x10
34 /sys/path... is an absolute path to a sysfs attribute
34 35
35 scope: {\fBcpu\fP | \fBcore\fP | \fBpackage\fP} 36 scope: {\fBcpu\fP | \fBcore\fP | \fBpackage\fP}
36 sample and print the counter for every cpu, core, or package. 37 sample and print the counter for every cpu, core, or package.
@@ -45,12 +46,21 @@ name as necessary to disambiguate it from others is necessary. Note that option
45 'delta' shows the difference in values during the measurement interval. 46 'delta' shows the difference in values during the measurement interval.
46 'percent' shows the delta as a percentage of the cycles elapsed. 47 'percent' shows the delta as a percentage of the cycles elapsed.
47 default: delta 48 default: delta
49
50 name: "name_string"
51 Any string that does not match a key-word above is used
52 as the column header.
48.fi 53.fi
49.PP 54.PP
55\fB--cpu cpu-set\fP limit output to system summary plus the specified cpu-set. If cpu-set is the string "core", then the system summary plus the first CPU in each core are printed -- eg. subsequent HT siblings are not printed. Or if cpu-set is the string "package", then the system summary plus the first CPU in each package is printed. Otherwise, the system summary plus the specified set of CPUs are printed. The cpu-set is ordered from low to high, comma delimited with ".." and "-" permitted to denote a range. eg. 1,2,8,14..17,21-44
56.PP
57\fB--hide column\fP do not show the specified columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--hide sysfs" to hide the sysfs statistics columns as a group.
58.PP
59\fB--show column\fP show only the specified columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--show sysfs" to show the sysfs statistics columns as a group.
60.PP
50\fB--Dump\fP displays the raw counter values. 61\fB--Dump\fP displays the raw counter values.
51.PP 62.PP
52\fB--debug\fP displays additional system configuration information. Invoking this parameter 63\fB--quiet\fP Do not decode and print the system configuration header information.
53more than once may also enable internal turbostat debug information.
54.PP 64.PP
55\fB--interval seconds\fP overrides the default 5.0 second measurement interval. 65\fB--interval seconds\fP overrides the default 5.0 second measurement interval.
56.PP 66.PP
@@ -61,9 +71,7 @@ The file is truncated if it already exists, and it is created if it does not exi
61.PP 71.PP
62\fB--Joules\fP displays energy in Joules, rather than dividing Joules by time to print power in Watts. 72\fB--Joules\fP displays energy in Joules, rather than dividing Joules by time to print power in Watts.
63.PP 73.PP
64\fB--Package\fP limits output to the system summary plus the 1st thread in each Package. 74\fB--list\fP display column header names available for use by --show and --hide, then exit.
65.PP
66\fB--processor\fP limits output to the system summary plus the 1st thread in each processor of each package. Ie. it skips hyper-threaded siblings.
67.PP 75.PP
68\fB--Summary\fP limits output to a 1-line System Summary for each interval. 76\fB--Summary\fP limits output to a 1-line System Summary for each interval.
69.PP 77.PP
@@ -74,24 +82,25 @@ The file is truncated if it already exists, and it is created if it does not exi
74The \fBcommand\fP parameter forks \fBcommand\fP, and upon its exit, 82The \fBcommand\fP parameter forks \fBcommand\fP, and upon its exit,
75displays the statistics gathered since it was forked. 83displays the statistics gathered since it was forked.
76.PP 84.PP
77.SH DEFAULT FIELD DESCRIPTIONS 85.SH ROW DESCRIPTIONS
86The system configuration dump (if --quiet is not used) is followed by statistics. The first row of the statistics labels the content of each column (below). The second row of statistics is the system summary line. The system summary line has a '-' in the columns for the Package, Core, and CPU. The contents of the system summary line depends on the type of column. Columns that count items (eg. IRQ) show the sum across all CPUs in the system. Columns that show a percentage show the average across all CPUs in the system. Columns that dump raw MSR values simply show 0 in the summary. After the system summary row, each row describes a specific Package/Core/CPU. Note that if the --cpu parameter is used to limit which specific CPUs are displayed, turbostat will still collect statistics for all CPUs in the system and will still show the system summary for all CPUs in the system.
87.SH COLUMN DESCRIPTIONS
78.nf 88.nf
89\fBCore\fP processor core number. Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology (HT).
79\fBCPU\fP Linux CPU (logical processor) number. Yes, it is okay that on many systems the CPUs are not listed in numerical order -- for efficiency reasons, turbostat runs in topology order, so HT siblings appear together. 90\fBCPU\fP Linux CPU (logical processor) number. Yes, it is okay that on many systems the CPUs are not listed in numerical order -- for efficiency reasons, turbostat runs in topology order, so HT siblings appear together.
80\fBAVG_MHz\fP number of cycles executed divided by time elapsed. 91\fBPackage\fP processor package number -- not present on systems with a single processor package.
81\fBBusy%\fP percent of the interval that the CPU retired instructions, aka. % of time in "C0" state. 92\fBAvg_MHz\fP number of cycles executed divided by time elapsed. Note that this includes idle-time when 0 instructions are executed.
82\fBBzy_MHz\fP average clock rate while the CPU was busy (in "c0" state). 93\fBBusy%\fP percent of the measurement interval that the CPU executes instructions, aka. % of time in "C0" state.
94\fBBzy_MHz\fP average clock rate while the CPU was not idle (ie. in "c0" state).
83\fBTSC_MHz\fP average MHz that the TSC ran during the entire interval. 95\fBTSC_MHz\fP average MHz that the TSC ran during the entire interval.
84.fi 96\fBIRQ\fP The number of interrupts serviced by that CPU during the measurement interval. The system total line is the sum of interrupts serviced across all CPUs. turbostat parses /proc/interrupts to generate this summary.
85.PP 97\fBSMI\fP The number of System Management Interrupts serviced CPU during the measurement interval. While this counter is actually per-CPU, SMI are triggered on all processors, so the number should be the same for all CPUs.
86.SH DEBUG FIELD DESCRIPTIONS 98\fBC1, C2, C3...\fP The number times Linux requested the C1, C2, C3 idle state during the measurement interval. The system summary line shows the sum for all CPUs. These are C-state names as exported in /sys/devices/system/cpu/cpu*/cpuidle/state*/name. While their names are generic, their attributes are processor specific. They the system description section of output shows what MWAIT sub-states they are mapped to on each system.
87.nf 99\fBC1%, C2%, C3%\fP The residency percentage that Linux requested C1, C2, C3.... The system summary is the average of all CPUs in the system. Note that these are software, reflecting what was requested. The hardware counters reflect what was actually achieved.
88\fBPackage\fP processor package number. 100\fBCPU%c1, CPU%c3, CPU%c6, CPU%c7\fP show the percentage residency in hardware core idle states. These numbers are from hardware residency counters.
89\fBCore\fP processor core number.
90Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology (HT).
91\fBCPU%c1, CPU%c3, CPU%c6, CPU%c7\fP show the percentage residency in hardware core idle states.
92\fBCoreTmp\fP Degrees Celsius reported by the per-core Digital Thermal Sensor. 101\fBCoreTmp\fP Degrees Celsius reported by the per-core Digital Thermal Sensor.
93\fBPkgTtmp\fP Degrees Celsius reported by the per-package Package Thermal Monitor. 102\fBPkgTtmp\fP Degrees Celsius reported by the per-package Package Thermal Monitor.
94\fBPkg%pc2, Pkg%pc3, Pkg%pc6, Pkg%pc7\fP percentage residency in hardware package idle states. 103\fBPkg%pc2, Pkg%pc3, Pkg%pc6, Pkg%pc7\fP percentage residency in hardware package idle states. These numbers are from hardware residency counters.
95\fBPkgWatt\fP Watts consumed by the whole package. 104\fBPkgWatt\fP Watts consumed by the whole package.
96\fBCorWatt\fP Watts consumed by the core part of the package. 105\fBCorWatt\fP Watts consumed by the core part of the package.
97\fBGFXWatt\fP Watts consumed by the Graphics part of the package -- available only on client processors. 106\fBGFXWatt\fP Watts consumed by the Graphics part of the package -- available only on client processors.
@@ -99,51 +108,110 @@ Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading T
99\fBPKG_%\fP percent of the interval that RAPL throttling was active on the Package. 108\fBPKG_%\fP percent of the interval that RAPL throttling was active on the Package.
100\fBRAM_%\fP percent of the interval that RAPL throttling was active on DRAM. 109\fBRAM_%\fP percent of the interval that RAPL throttling was active on DRAM.
101.fi 110.fi
111.SH TOO MUCH INFORMATION EXAMPLE
112By default, turbostat dumps all possible information -- a system configuration header, followed by columns for all counters.
113This is ideal for remote debugging, use the "--out" option to save everything to a text file, and get that file to the expert helping you debug.
102.PP 114.PP
103.SH PERIODIC EXAMPLE 115When you are not interested in all that information, and there are several ways to see only what you want. First the "--quiet" option will skip the configuration information, and turbostat will show only the counter columns. Second, you can reduce the columns with the "--hide" and "--show" options. If you use the "--show" option, then turbostat will show only the columns you list. If you use the "--hide" option, turbostat will show all columns, except the ones you list.
104Without any parameters, turbostat displays statistics ever 5 seconds. 116.PP
105Periodic output goes to stdout, by default, unless --out is used to specify an output file. 117To find out what columns are available for --show and --hide, the "--list" option is available. For convenience, the special strings "sysfs" can be used to refer to all of the sysfs C-state counters at once:
106The 5-second interval can be changed with th "-i sec" option. 118.nf
107Or a command may be specified as in "FORK EXAMPLE" below. 119sudo ./turbostat --show sysfs --quiet sleep 10
12010.003837 sec
121 C1 C1E C3 C6 C7s C1% C1E% C3% C6% C7s%
122 4 21 2 2 459 0.14 0.82 0.00 0.00 98.93
123 1 17 2 2 130 0.00 0.02 0.00 0.00 99.80
124 0 0 0 0 31 0.00 0.00 0.00 0.00 99.95
125 2 1 0 0 52 1.14 6.49 0.00 0.00 92.21
126 1 2 0 0 52 0.00 0.08 0.00 0.00 99.86
127 0 0 0 0 71 0.00 0.00 0.00 0.00 99.89
128 0 0 0 0 25 0.00 0.00 0.00 0.00 99.96
129 0 0 0 0 74 0.00 0.00 0.00 0.00 99.94
130 0 1 0 0 24 0.00 0.00 0.00 0.00 99.84
131.fi
132.PP
133.SH ONE SHOT COMMAND EXAMPLE
134If turbostat is invoked with a command, it will fork that command
135and output the statistics gathered after the command exits.
136In this case, turbostat output goes to stderr, by default.
137Output can instead be saved to a file using the --out option.
138In this example, the "sleep 10" command is forked, and turbostat waits for it to complete before saving all statistics into "ts.out". Note that "sleep 10" is not part of turbostat, but is simply an example of a command that turbostat can fork. The "ts.out" file is what you want to edit in a very wide window, paste into a spreadsheet, or attach to a bugzilla entry.
139
108.nf 140.nf
109[root@hsw]# ./turbostat 141[root@hsw]# ./turbostat -o ts.out sleep 10
110 CPU Avg_MHz Busy% Bzy_MHz TSC_MHz 142[root@hsw]#
111 - 488 12.51 3898 3498 143.fi
112 0 0 0.01 3885 3498
113 4 3897 99.99 3898 3498
114 1 0 0.00 3861 3498
115 5 0 0.00 3882 3498
116 2 1 0.02 3894 3498
117 6 2 0.06 3898 3498
118 3 0 0.00 3849 3498
119 7 0 0.00 3877 3498
120 144
145.SH PERIODIC INTERVAL EXAMPLE
146Without a command to fork, turbostat displays statistics ever 5 seconds.
147Periodic output goes to stdout, by default, unless --out is used to specify an output file.
148The 5-second interval can be changed with the "-i sec" option.
149.nf
150sudo ./turbostat --quiet --hide sysfs,IRQ,SMI,CoreTmp,PkgTmp,GFX%rc6,GFXMHz,PkgWatt,CorWatt,GFXWatt
151 Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c1 CPU%c3 CPU%c6 CPU%c7
152 - - 488 12.52 3900 3498 12.50 0.00 0.00 74.98
153 0 0 5 0.13 3900 3498 99.87 0.00 0.00 0.00
154 0 4 3897 99.99 3900 3498 0.01
155 1 1 0 0.00 3856 3498 0.01 0.00 0.00 99.98
156 1 5 0 0.00 3861 3498 0.01
157 2 2 1 0.02 3889 3498 0.03 0.00 0.00 99.95
158 2 6 0 0.00 3863 3498 0.05
159 3 3 0 0.01 3869 3498 0.02 0.00 0.00 99.97
160 3 7 0 0.00 3878 3498 0.03
161 Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c1 CPU%c3 CPU%c6 CPU%c7
162 - - 491 12.59 3900 3498 12.42 0.00 0.00 74.99
163 0 0 27 0.69 3900 3498 99.31 0.00 0.00 0.00
164 0 4 3898 99.99 3900 3498 0.01
165 1 1 0 0.00 3883 3498 0.01 0.00 0.00 99.99
166 1 5 0 0.00 3898 3498 0.01
167 2 2 0 0.01 3889 3498 0.02 0.00 0.00 99.98
168 2 6 0 0.00 3889 3498 0.02
169 3 3 0 0.00 3856 3498 0.01 0.00 0.00 99.99
170 3 7 0 0.00 3897 3498 0.01
121.fi 171.fi
122.SH DEBUG EXAMPLE 172This example also shows the use of the --hide option to skip columns that are not wanted.
123The "--debug" option prints additional system information before measurements: 173Note that cpu4 in this example is 99.99% busy, while the other CPUs are all under 1% busy.
174Notice that cpu4's HT sibling is cpu0, which is under 1% busy, but can get into CPU%c1 only,
175because its cpu4's activity on shared hardware keeps it from entering a deeper C-state.
124 176
125The first row of statistics is a summary for the entire system. 177.SH SYSTEM CONFIGURATION INFORMATION EXAMPLE
126For residency % columns, the summary is a weighted average. 178
127For Temperature columns, the summary is the column maximum. 179By default, turbostat always dumps system configuration information
128For Watts columns, the summary is a system total. 180before taking measurements. In the example above, "--quiet" is used
129Subsequent rows show per-CPU statistics. 181to suppress that output. Here is an example of the configuration information:
130.nf 182.nf
131turbostat version 4.1 10-Feb, 2015 - Len Brown <lenb@kernel.org> 183turbostat version 2017.02.15 - Len Brown <lenb@kernel.org>
132CPUID(0): GenuineIntel 13 CPUID levels; family:model:stepping 0x6:3c:3 (6:60:3) 184CPUID(0): GenuineIntel 13 CPUID levels; family:model:stepping 0x6:3c:3 (6:60:3)
133CPUID(6): APERF, DTS, PTM, EPB 185CPUID(1): SSE3 MONITOR - EIST TM2 TSC MSR ACPI-TM TM
186CPUID(6): APERF, TURBO, DTS, PTM, No-HWP, No-HWPnotify, No-HWPwindow, No-HWPepp, No-HWPpkg, EPB
187cpu4: MSR_IA32_MISC_ENABLE: 0x00850089 (TCC EIST No-MWAIT PREFETCH TURBO)
188CPUID(7): No-SGX
189cpu4: MSR_MISC_PWR_MGMT: 0x00400000 (ENable-EIST_Coordination DISable-EPB DISable-OOB)
134RAPL: 3121 sec. Joule Counter Range, at 84 Watts 190RAPL: 3121 sec. Joule Counter Range, at 84 Watts
135cpu0: MSR_NHM_PLATFORM_INFO: 0x80838f3012300 191cpu4: MSR_PLATFORM_INFO: 0x80838f3012300
1368 * 100 = 800 MHz max efficiency 1928 * 100.0 = 800.0 MHz max efficiency frequency
13735 * 100 = 3500 MHz TSC frequency 19335 * 100.0 = 3500.0 MHz base frequency
138cpu0: MSR_IA32_POWER_CTL: 0x0004005d (C1E auto-promotion: DISabled) 194cpu4: MSR_IA32_POWER_CTL: 0x0004005d (C1E auto-promotion: DISabled)
139cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x1e000400 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, UNlocked: pkg-cstate-limit=0: pc0) 195cpu4: MSR_TURBO_RATIO_LIMIT: 0x25262727
140cpu0: MSR_TURBO_RATIO_LIMIT: 0x25262727 19637 * 100.0 = 3700.0 MHz max turbo 4 active cores
14137 * 100 = 3700 MHz max turbo 4 active cores 19738 * 100.0 = 3800.0 MHz max turbo 3 active cores
14238 * 100 = 3800 MHz max turbo 3 active cores 19839 * 100.0 = 3900.0 MHz max turbo 2 active cores
14339 * 100 = 3900 MHz max turbo 2 active cores 19939 * 100.0 = 3900.0 MHz max turbo 1 active cores
14439 * 100 = 3900 MHz max turbo 1 active cores 200cpu4: MSR_CONFIG_TDP_NOMINAL: 0x00000023 (base_ratio=35)
201cpu4: MSR_CONFIG_TDP_LEVEL_1: 0x00000000 ()
202cpu4: MSR_CONFIG_TDP_LEVEL_2: 0x00000000 ()
203cpu4: MSR_CONFIG_TDP_CONTROL: 0x80000000 ( lock=1)
204cpu4: MSR_TURBO_ACTIVATION_RATIO: 0x00000000 (MAX_NON_TURBO_RATIO=0 lock=0)
205cpu4: MSR_PKG_CST_CONFIG_CONTROL: 0x1e000400 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, UNlocked: pkg-cstate-limit=0: pc0)
206cpu4: POLL: CPUIDLE CORE POLL IDLE
207cpu4: C1: MWAIT 0x00
208cpu4: C1E: MWAIT 0x01
209cpu4: C3: MWAIT 0x10
210cpu4: C6: MWAIT 0x20
211cpu4: C7s: MWAIT 0x32
212cpu4: MSR_MISC_FEATURE_CONTROL: 0x00000000 (L2-Prefetch L2-Prefetch-pair L1-Prefetch L1-IP-Prefetch)
145cpu0: MSR_IA32_ENERGY_PERF_BIAS: 0x00000006 (balanced) 213cpu0: MSR_IA32_ENERGY_PERF_BIAS: 0x00000006 (balanced)
146cpu0: MSR_CORE_PERF_LIMIT_REASONS, 0x31200000 (Active: ) (Logged: Auto-HWP, Amps, MultiCoreTurbo, Transitions, ) 214cpu0: MSR_CORE_PERF_LIMIT_REASONS, 0x31200000 (Active: ) (Logged: Transitions, MultiCoreTurbo, Amps, Auto-HWP, )
147cpu0: MSR_GFX_PERF_LIMIT_REASONS, 0x00000000 (Active: ) (Logged: ) 215cpu0: MSR_GFX_PERF_LIMIT_REASONS, 0x00000000 (Active: ) (Logged: )
148cpu0: MSR_RING_PERF_LIMIT_REASONS, 0x0d000000 (Active: ) (Logged: Amps, PkgPwrL1, PkgPwrL2, ) 216cpu0: MSR_RING_PERF_LIMIT_REASONS, 0x0d000000 (Active: ) (Logged: Amps, PkgPwrL1, PkgPwrL2, )
149cpu0: MSR_RAPL_POWER_UNIT: 0x000a0e03 (0.125000 Watts, 0.000061 Joules, 0.000977 sec.) 217cpu0: MSR_RAPL_POWER_UNIT: 0x000a0e03 (0.125000 Watts, 0.000061 Joules, 0.000977 sec.)
@@ -158,23 +226,14 @@ cpu0: MSR_PP1_POLICY: 0
158cpu0: MSR_PP1_POWER_LIMIT: 0x00000000 (UNlocked) 226cpu0: MSR_PP1_POWER_LIMIT: 0x00000000 (UNlocked)
159cpu0: GFX Limit: DISabled (0.000000 Watts, 0.000977 sec, clamp DISabled) 227cpu0: GFX Limit: DISabled (0.000000 Watts, 0.000977 sec, clamp DISabled)
160cpu0: MSR_IA32_TEMPERATURE_TARGET: 0x00641400 (100 C) 228cpu0: MSR_IA32_TEMPERATURE_TARGET: 0x00641400 (100 C)
161cpu0: MSR_IA32_PACKAGE_THERM_STATUS: 0x88340800 (48 C) 229cpu0: MSR_IA32_PACKAGE_THERM_STATUS: 0x884c0800 (24 C)
162cpu0: MSR_IA32_THERM_STATUS: 0x88340000 (48 C +/- 1) 230cpu0: MSR_IA32_THERM_STATUS: 0x884c0000 (24 C +/- 1)
163cpu1: MSR_IA32_THERM_STATUS: 0x88440000 (32 C +/- 1) 231cpu1: MSR_IA32_THERM_STATUS: 0x88510000 (19 C +/- 1)
164cpu2: MSR_IA32_THERM_STATUS: 0x88450000 (31 C +/- 1) 232cpu2: MSR_IA32_THERM_STATUS: 0x884e0000 (22 C +/- 1)
165cpu3: MSR_IA32_THERM_STATUS: 0x88490000 (27 C +/- 1) 233cpu3: MSR_IA32_THERM_STATUS: 0x88510000 (19 C +/- 1)
166 Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp PkgWatt CorWatt GFXWatt 234cpu4: MSR_PKGC3_IRTL: 0x00008842 (valid, 67584 ns)
167 - - 493 12.64 3898 3498 0 12.64 0.00 0.00 74.72 47 47 21.62 13.74 0.00 235cpu4: MSR_PKGC6_IRTL: 0x00008873 (valid, 117760 ns)
168 0 0 4 0.11 3894 3498 0 99.89 0.00 0.00 0.00 47 47 21.62 13.74 0.00 236cpu4: MSR_PKGC7_IRTL: 0x00008891 (valid, 148480 ns)
169 0 4 3897 99.98 3898 3498 0 0.02
170 1 1 7 0.17 3887 3498 0 0.04 0.00 0.00 99.79 32
171 1 5 0 0.00 3885 3498 0 0.21
172 2 2 29 0.76 3895 3498 0 0.10 0.01 0.01 99.13 32
173 2 6 2 0.06 3896 3498 0 0.80
174 3 3 1 0.02 3832 3498 0 0.03 0.00 0.00 99.95 28
175 3 7 0 0.00 3879 3498 0 0.04
176^C
177
178.fi 237.fi
179The \fBmax efficiency\fP frequency, a.k.a. Low Frequency Mode, is the frequency 238The \fBmax efficiency\fP frequency, a.k.a. Low Frequency Mode, is the frequency
180available at the minimum package voltage. The \fBTSC frequency\fP is the base 239available at the minimum package voltage. The \fBTSC frequency\fP is the base
@@ -184,42 +243,22 @@ should be sustainable on all CPUs indefinitely, given nominal power and cooling.
184The remaining rows show what maximum turbo frequency is possible 243The remaining rows show what maximum turbo frequency is possible
185depending on the number of idle cores. Note that not all information is 244depending on the number of idle cores. Note that not all information is
186available on all processors. 245available on all processors.
187.PP 246.SH ADD COUNTER EXAMPLE
188The --debug option adds additional columns to the measurement ouput, including CPU idle power-state residency processor temperature sensor readinds. 247Here we limit turbostat to showing just the CPU number for cpu0 - cpu3.
189See the field definitions above. 248We add a counter showing the 32-bit raw value of MSR 0x199 (MSR_IA32_PERF_CTL),
190.SH FORK EXAMPLE 249labeling it with the column header, "PRF_CTRL", and display it only once,
191If turbostat is invoked with a command, it will fork that command 250afte the conclusion of a 0.1 second sleep.
192and output the statistics gathered after the command exits.
193In this case, turbostat output goes to stderr, by default.
194Output can instead be saved to a file using the --out option.
195eg. Here a cycle soaker is run on 1 CPU (see %c0) for a few seconds
196until ^C while the other CPUs are mostly idle:
197
198.nf 251.nf
199root@hsw: turbostat cat /dev/zero > /dev/null 252sudo ./turbostat --quiet --cpu 0-3 --show CPU --add msr0x199,u32,raw,PRF_CTRL sleep .1
200^C 2530.101604 sec
201 CPU Avg_MHz Busy% Bzy_MHz TSC_MHz 254CPU PRF_CTRL
202 - 482 12.51 3854 3498 255- 0x00000000
203 0 0 0.01 1960 3498 2560 0x00000c00
204 4 0 0.00 2128 3498 2571 0x00000800
205 1 0 0.00 3003 3498 2582 0x00000a00
206 5 3854 99.98 3855 3498 2593 0x00000800
207 2 0 0.01 3504 3498
208 6 3 0.08 3884 3498
209 3 0 0.00 2553 3498
210 7 0 0.00 2126 3498
21110.783983 sec
212 260
213.fi 261.fi
214Above the cycle soaker drives cpu5 up its 3.9 GHz turbo limit.
215The first row shows the average MHz and Busy% across all the processors in the system.
216
217Note that the Avg_MHz column reflects the total number of cycles executed
218divided by the measurement interval. If the Busy% column is 100%,
219then the processor was running at that speed the entire interval.
220The Avg_MHz multiplied by the Busy% results in the Bzy_MHz --
221which is the average frequency while the processor was executing --
222not including any non-busy idle time.
223 262
224.SH NOTES 263.SH NOTES
225 264
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index f13f61b065c6..828dccd3f01e 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -49,17 +49,14 @@ FILE *outf;
49int *fd_percpu; 49int *fd_percpu;
50struct timespec interval_ts = {5, 0}; 50struct timespec interval_ts = {5, 0};
51unsigned int debug; 51unsigned int debug;
52unsigned int quiet;
53unsigned int sums_need_wide_columns;
52unsigned int rapl_joules; 54unsigned int rapl_joules;
53unsigned int summary_only; 55unsigned int summary_only;
56unsigned int list_header_only;
54unsigned int dump_only; 57unsigned int dump_only;
55unsigned int do_nhm_cstates;
56unsigned int do_snb_cstates; 58unsigned int do_snb_cstates;
57unsigned int do_knl_cstates; 59unsigned int do_knl_cstates;
58unsigned int do_pc2;
59unsigned int do_pc3;
60unsigned int do_pc6;
61unsigned int do_pc7;
62unsigned int do_c8_c9_c10;
63unsigned int do_skl_residency; 60unsigned int do_skl_residency;
64unsigned int do_slm_cstates; 61unsigned int do_slm_cstates;
65unsigned int use_c1_residency_msr; 62unsigned int use_c1_residency_msr;
@@ -71,25 +68,19 @@ unsigned int units = 1000000; /* MHz etc */
71unsigned int genuine_intel; 68unsigned int genuine_intel;
72unsigned int has_invariant_tsc; 69unsigned int has_invariant_tsc;
73unsigned int do_nhm_platform_info; 70unsigned int do_nhm_platform_info;
71unsigned int no_MSR_MISC_PWR_MGMT;
74unsigned int aperf_mperf_multiplier = 1; 72unsigned int aperf_mperf_multiplier = 1;
75int do_irq = 1;
76int do_smi;
77double bclk; 73double bclk;
78double base_hz; 74double base_hz;
79unsigned int has_base_hz; 75unsigned int has_base_hz;
80double tsc_tweak = 1.0; 76double tsc_tweak = 1.0;
81unsigned int show_pkg;
82unsigned int show_core;
83unsigned int show_cpu;
84unsigned int show_pkg_only; 77unsigned int show_pkg_only;
85unsigned int show_core_only; 78unsigned int show_core_only;
86char *output_buffer, *outp; 79char *output_buffer, *outp;
87unsigned int do_rapl; 80unsigned int do_rapl;
88unsigned int do_dts; 81unsigned int do_dts;
89unsigned int do_ptm; 82unsigned int do_ptm;
90unsigned int do_gfx_rc6_ms;
91unsigned long long gfx_cur_rc6_ms; 83unsigned long long gfx_cur_rc6_ms;
92unsigned int do_gfx_mhz;
93unsigned int gfx_cur_mhz; 84unsigned int gfx_cur_mhz;
94unsigned int tcc_activation_temp; 85unsigned int tcc_activation_temp;
95unsigned int tcc_activation_temp_override; 86unsigned int tcc_activation_temp_override;
@@ -109,6 +100,7 @@ unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */
109unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */ 100unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */
110unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */ 101unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */
111unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */ 102unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */
103unsigned int has_misc_feature_control;
112 104
113#define RAPL_PKG (1 << 0) 105#define RAPL_PKG (1 << 0)
114 /* 0x610 MSR_PKG_POWER_LIMIT */ 106 /* 0x610 MSR_PKG_POWER_LIMIT */
@@ -148,34 +140,38 @@ unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */
148 * Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters 140 * Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters
149 */ 141 */
150#define NAME_BYTES 20 142#define NAME_BYTES 20
143#define PATH_BYTES 128
151 144
152int backwards_count; 145int backwards_count;
153char *progname; 146char *progname;
154 147
155cpu_set_t *cpu_present_set, *cpu_affinity_set; 148#define CPU_SUBSET_MAXCPUS 1024 /* need to use before probe... */
156size_t cpu_present_setsize, cpu_affinity_setsize; 149cpu_set_t *cpu_present_set, *cpu_affinity_set, *cpu_subset;
150size_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size;
151#define MAX_ADDED_COUNTERS 16
157 152
158struct thread_data { 153struct thread_data {
159 unsigned long long tsc; 154 unsigned long long tsc;
160 unsigned long long aperf; 155 unsigned long long aperf;
161 unsigned long long mperf; 156 unsigned long long mperf;
162 unsigned long long c1; 157 unsigned long long c1;
163 unsigned int irq_count; 158 unsigned long long irq_count;
164 unsigned int smi_count; 159 unsigned int smi_count;
165 unsigned int cpu_id; 160 unsigned int cpu_id;
166 unsigned int flags; 161 unsigned int flags;
167#define CPU_IS_FIRST_THREAD_IN_CORE 0x2 162#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
168#define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4 163#define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4
169 unsigned long long counter[1]; 164 unsigned long long counter[MAX_ADDED_COUNTERS];
170} *thread_even, *thread_odd; 165} *thread_even, *thread_odd;
171 166
172struct core_data { 167struct core_data {
173 unsigned long long c3; 168 unsigned long long c3;
174 unsigned long long c6; 169 unsigned long long c6;
175 unsigned long long c7; 170 unsigned long long c7;
171 unsigned long long mc6_us; /* duplicate as per-core for now, even though per module */
176 unsigned int core_temp_c; 172 unsigned int core_temp_c;
177 unsigned int core_id; 173 unsigned int core_id;
178 unsigned long long counter[1]; 174 unsigned long long counter[MAX_ADDED_COUNTERS];
179} *core_even, *core_odd; 175} *core_even, *core_odd;
180 176
181struct pkg_data { 177struct pkg_data {
@@ -200,7 +196,7 @@ struct pkg_data {
200 unsigned int rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */ 196 unsigned int rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */
201 unsigned int rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */ 197 unsigned int rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */
202 unsigned int pkg_temp_c; 198 unsigned int pkg_temp_c;
203 unsigned long long counter[1]; 199 unsigned long long counter[MAX_ADDED_COUNTERS];
204} *package_even, *package_odd; 200} *package_even, *package_odd;
205 201
206#define ODD_COUNTERS thread_odd, core_odd, package_odd 202#define ODD_COUNTERS thread_odd, core_odd, package_odd
@@ -215,22 +211,27 @@ struct pkg_data {
215#define GET_PKG(pkg_base, pkg_no) (pkg_base + pkg_no) 211#define GET_PKG(pkg_base, pkg_no) (pkg_base + pkg_no)
216 212
217enum counter_scope {SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE}; 213enum counter_scope {SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE};
218enum counter_type {COUNTER_CYCLES, COUNTER_SECONDS}; 214enum counter_type {COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC};
219enum counter_format {FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT}; 215enum counter_format {FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT};
220 216
221struct msr_counter { 217struct msr_counter {
222 unsigned int msr_num; 218 unsigned int msr_num;
223 char name[NAME_BYTES]; 219 char name[NAME_BYTES];
220 char path[PATH_BYTES];
224 unsigned int width; 221 unsigned int width;
225 enum counter_type type; 222 enum counter_type type;
226 enum counter_format format; 223 enum counter_format format;
227 struct msr_counter *next; 224 struct msr_counter *next;
225 unsigned int flags;
226#define FLAGS_HIDE (1 << 0)
227#define FLAGS_SHOW (1 << 1)
228#define SYSFS_PERCPU (1 << 1)
228}; 229};
229 230
230struct sys_counters { 231struct sys_counters {
231 unsigned int thread_counter_bytes; 232 unsigned int added_thread_counters;
232 unsigned int core_counter_bytes; 233 unsigned int added_core_counters;
233 unsigned int package_counter_bytes; 234 unsigned int added_package_counters;
234 struct msr_counter *tp; 235 struct msr_counter *tp;
235 struct msr_counter *cp; 236 struct msr_counter *cp;
236 struct msr_counter *pp; 237 struct msr_counter *pp;
@@ -334,147 +335,333 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
334 retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset); 335 retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset);
335 336
336 if (retval != sizeof *msr) 337 if (retval != sizeof *msr)
337 err(-1, "msr %d offset 0x%llx read failed", cpu, (unsigned long long)offset); 338 err(-1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset);
338 339
339 return 0; 340 return 0;
340} 341}
341 342
342/* 343/*
343 * Example Format w/ field column widths: 344 * Each string in this array is compared in --show and --hide cmdline.
344 * 345 * Thus, strings that are proper sub-sets must follow their more specific peers.
345 * Package Core CPU Avg_MHz Bzy_MHz TSC_MHz IRQ SMI Busy% CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 ThreadC CoreTmp CoreCnt PkgTmp GFXMHz Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt PkgCnt 346 */
346 * 12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678 347struct msr_counter bic[] = {
348 { 0x0, "Package" },
349 { 0x0, "Avg_MHz" },
350 { 0x0, "Bzy_MHz" },
351 { 0x0, "TSC_MHz" },
352 { 0x0, "IRQ" },
353 { 0x0, "SMI", "", 32, 0, FORMAT_DELTA, NULL},
354 { 0x0, "Busy%" },
355 { 0x0, "CPU%c1" },
356 { 0x0, "CPU%c3" },
357 { 0x0, "CPU%c6" },
358 { 0x0, "CPU%c7" },
359 { 0x0, "ThreadC" },
360 { 0x0, "CoreTmp" },
361 { 0x0, "CoreCnt" },
362 { 0x0, "PkgTmp" },
363 { 0x0, "GFX%rc6" },
364 { 0x0, "GFXMHz" },
365 { 0x0, "Pkg%pc2" },
366 { 0x0, "Pkg%pc3" },
367 { 0x0, "Pkg%pc6" },
368 { 0x0, "Pkg%pc7" },
369 { 0x0, "Pkg%pc8" },
370 { 0x0, "Pkg%pc9" },
371 { 0x0, "Pkg%pc10" },
372 { 0x0, "PkgWatt" },
373 { 0x0, "CorWatt" },
374 { 0x0, "GFXWatt" },
375 { 0x0, "PkgCnt" },
376 { 0x0, "RAMWatt" },
377 { 0x0, "PKG_%" },
378 { 0x0, "RAM_%" },
379 { 0x0, "Pkg_J" },
380 { 0x0, "Cor_J" },
381 { 0x0, "GFX_J" },
382 { 0x0, "RAM_J" },
383 { 0x0, "Core" },
384 { 0x0, "CPU" },
385 { 0x0, "Mod%c6" },
386 { 0x0, "sysfs" },
387};
388
389#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
390#define BIC_Package (1ULL << 0)
391#define BIC_Avg_MHz (1ULL << 1)
392#define BIC_Bzy_MHz (1ULL << 2)
393#define BIC_TSC_MHz (1ULL << 3)
394#define BIC_IRQ (1ULL << 4)
395#define BIC_SMI (1ULL << 5)
396#define BIC_Busy (1ULL << 6)
397#define BIC_CPU_c1 (1ULL << 7)
398#define BIC_CPU_c3 (1ULL << 8)
399#define BIC_CPU_c6 (1ULL << 9)
400#define BIC_CPU_c7 (1ULL << 10)
401#define BIC_ThreadC (1ULL << 11)
402#define BIC_CoreTmp (1ULL << 12)
403#define BIC_CoreCnt (1ULL << 13)
404#define BIC_PkgTmp (1ULL << 14)
405#define BIC_GFX_rc6 (1ULL << 15)
406#define BIC_GFXMHz (1ULL << 16)
407#define BIC_Pkgpc2 (1ULL << 17)
408#define BIC_Pkgpc3 (1ULL << 18)
409#define BIC_Pkgpc6 (1ULL << 19)
410#define BIC_Pkgpc7 (1ULL << 20)
411#define BIC_Pkgpc8 (1ULL << 21)
412#define BIC_Pkgpc9 (1ULL << 22)
413#define BIC_Pkgpc10 (1ULL << 23)
414#define BIC_PkgWatt (1ULL << 24)
415#define BIC_CorWatt (1ULL << 25)
416#define BIC_GFXWatt (1ULL << 26)
417#define BIC_PkgCnt (1ULL << 27)
418#define BIC_RAMWatt (1ULL << 28)
419#define BIC_PKG__ (1ULL << 29)
420#define BIC_RAM__ (1ULL << 30)
421#define BIC_Pkg_J (1ULL << 31)
422#define BIC_Cor_J (1ULL << 32)
423#define BIC_GFX_J (1ULL << 33)
424#define BIC_RAM_J (1ULL << 34)
425#define BIC_Core (1ULL << 35)
426#define BIC_CPU (1ULL << 36)
427#define BIC_Mod_c6 (1ULL << 37)
428#define BIC_sysfs (1ULL << 38)
429
430unsigned long long bic_enabled = 0xFFFFFFFFFFFFFFFFULL;
431unsigned long long bic_present = BIC_sysfs;
432
433#define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
434#define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT)
435#define BIC_NOT_PRESENT(COUNTER_BIT) (bic_present &= ~COUNTER_BIT)
436
437#define MAX_DEFERRED 16
438char *deferred_skip_names[MAX_DEFERRED];
439int deferred_skip_index;
440
441/*
442 * HIDE_LIST - hide this list of counters, show the rest [default]
443 * SHOW_LIST - show this list of counters, hide the rest
347 */ 444 */
445enum show_hide_mode { SHOW_LIST, HIDE_LIST } global_show_hide_mode = HIDE_LIST;
348 446
349void print_header(void) 447void help(void)
350{ 448{
351 struct msr_counter *mp; 449 fprintf(outf,
450 "Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n"
451 "\n"
452 "Turbostat forks the specified COMMAND and prints statistics\n"
453 "when COMMAND completes.\n"
454 "If no COMMAND is specified, turbostat wakes every 5-seconds\n"
455 "to print statistics, until interrupted.\n"
456 "--add add a counter\n"
457 " eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
458 "--cpu cpu-set limit output to summary plus cpu-set:\n"
459 " {core | package | j,k,l..m,n-p }\n"
460 "--quiet skip decoding system configuration header\n"
461 "--interval sec Override default 5-second measurement interval\n"
462 "--help print this help message\n"
463 "--list list column headers only\n"
464 "--out file create or truncate \"file\" for all output\n"
465 "--version print version information\n"
466 "\n"
467 "For more help, run \"man turbostat\"\n");
468}
352 469
353 if (show_pkg) 470/*
354 outp += sprintf(outp, "\tPackage"); 471 * bic_lookup
355 if (show_core) 472 * for all the strings in comma separate name_list,
356 outp += sprintf(outp, "\tCore"); 473 * set the approprate bit in return value.
357 if (show_cpu) 474 */
358 outp += sprintf(outp, "\tCPU"); 475unsigned long long bic_lookup(char *name_list, enum show_hide_mode mode)
359 if (has_aperf) 476{
360 outp += sprintf(outp, "\tAvg_MHz"); 477 int i;
361 if (has_aperf) 478 unsigned long long retval = 0;
362 outp += sprintf(outp, "\tBusy%%");
363 if (has_aperf)
364 outp += sprintf(outp, "\tBzy_MHz");
365 outp += sprintf(outp, "\tTSC_MHz");
366 479
367 if (!debug) 480 while (name_list) {
368 goto done; 481 char *comma;
369 482
370 if (do_irq) 483 comma = strchr(name_list, ',');
371 outp += sprintf(outp, "\tIRQ"); 484
372 if (do_smi) 485 if (comma)
373 outp += sprintf(outp, "\tSMI"); 486 *comma = '\0';
374 487
375 if (do_nhm_cstates) 488 for (i = 0; i < MAX_BIC; ++i) {
376 outp += sprintf(outp, "\tCPU%%c1"); 489 if (!strcmp(name_list, bic[i].name)) {
377 if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates) 490 retval |= (1ULL << i);
378 outp += sprintf(outp, "\tCPU%%c3"); 491 break;
379 if (do_nhm_cstates) 492 }
380 outp += sprintf(outp, "\tCPU%%c6"); 493 }
381 if (do_snb_cstates) 494 if (i == MAX_BIC) {
382 outp += sprintf(outp, "\tCPU%%c7"); 495 if (mode == SHOW_LIST) {
496 fprintf(stderr, "Invalid counter name: %s\n", name_list);
497 exit(-1);
498 }
499 deferred_skip_names[deferred_skip_index++] = name_list;
500 if (debug)
501 fprintf(stderr, "deferred \"%s\"\n", name_list);
502 if (deferred_skip_index >= MAX_DEFERRED) {
503 fprintf(stderr, "More than max %d un-recognized --skip options '%s'\n",
504 MAX_DEFERRED, name_list);
505 help();
506 exit(1);
507 }
508 }
509
510 name_list = comma;
511 if (name_list)
512 name_list++;
513
514 }
515 return retval;
516}
517
518
519void print_header(char *delim)
520{
521 struct msr_counter *mp;
522 int printed = 0;
523
524 if (DO_BIC(BIC_Package))
525 outp += sprintf(outp, "%sPackage", (printed++ ? delim : ""));
526 if (DO_BIC(BIC_Core))
527 outp += sprintf(outp, "%sCore", (printed++ ? delim : ""));
528 if (DO_BIC(BIC_CPU))
529 outp += sprintf(outp, "%sCPU", (printed++ ? delim : ""));
530 if (DO_BIC(BIC_Avg_MHz))
531 outp += sprintf(outp, "%sAvg_MHz", (printed++ ? delim : ""));
532 if (DO_BIC(BIC_Busy))
533 outp += sprintf(outp, "%sBusy%%", (printed++ ? delim : ""));
534 if (DO_BIC(BIC_Bzy_MHz))
535 outp += sprintf(outp, "%sBzy_MHz", (printed++ ? delim : ""));
536 if (DO_BIC(BIC_TSC_MHz))
537 outp += sprintf(outp, "%sTSC_MHz", (printed++ ? delim : ""));
538
539 if (DO_BIC(BIC_IRQ)) {
540 if (sums_need_wide_columns)
541 outp += sprintf(outp, "%s IRQ", (printed++ ? delim : ""));
542 else
543 outp += sprintf(outp, "%sIRQ", (printed++ ? delim : ""));
544 }
545
546 if (DO_BIC(BIC_SMI))
547 outp += sprintf(outp, "%sSMI", (printed++ ? delim : ""));
383 548
384 for (mp = sys.tp; mp; mp = mp->next) { 549 for (mp = sys.tp; mp; mp = mp->next) {
550
385 if (mp->format == FORMAT_RAW) { 551 if (mp->format == FORMAT_RAW) {
386 if (mp->width == 64) 552 if (mp->width == 64)
387 outp += sprintf(outp, "\t%18.18s", mp->name); 553 outp += sprintf(outp, "%s%18.18s", (printed++ ? delim : ""), mp->name);
388 else 554 else
389 outp += sprintf(outp, "\t%10.10s", mp->name); 555 outp += sprintf(outp, "%s%10.10s", (printed++ ? delim : ""), mp->name);
390 } else { 556 } else {
391 outp += sprintf(outp, "\t%-7.7s", mp->name); 557 if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
558 outp += sprintf(outp, "%s%8s", (printed++ ? delim : ""), mp->name);
559 else
560 outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), mp->name);
392 } 561 }
393 } 562 }
394 563
395 if (do_dts) 564 if (DO_BIC(BIC_CPU_c1))
396 outp += sprintf(outp, "\tCoreTmp"); 565 outp += sprintf(outp, "%sCPU%%c1", (printed++ ? delim : ""));
566 if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates)
567 outp += sprintf(outp, "%sCPU%%c3", (printed++ ? delim : ""));
568 if (DO_BIC(BIC_CPU_c6))
569 outp += sprintf(outp, "%sCPU%%c6", (printed++ ? delim : ""));
570 if (DO_BIC(BIC_CPU_c7))
571 outp += sprintf(outp, "%sCPU%%c7", (printed++ ? delim : ""));
572
573 if (DO_BIC(BIC_Mod_c6))
574 outp += sprintf(outp, "%sMod%%c6", (printed++ ? delim : ""));
575
576 if (DO_BIC(BIC_CoreTmp))
577 outp += sprintf(outp, "%sCoreTmp", (printed++ ? delim : ""));
397 578
398 for (mp = sys.cp; mp; mp = mp->next) { 579 for (mp = sys.cp; mp; mp = mp->next) {
399 if (mp->format == FORMAT_RAW) { 580 if (mp->format == FORMAT_RAW) {
400 if (mp->width == 64) 581 if (mp->width == 64)
401 outp += sprintf(outp, "\t%18.18s", mp->name); 582 outp += sprintf(outp, "%s%18.18s", delim, mp->name);
402 else 583 else
403 outp += sprintf(outp, "\t%10.10s", mp->name); 584 outp += sprintf(outp, "%s%10.10s", delim, mp->name);
404 } else { 585 } else {
405 outp += sprintf(outp, "\t%-7.7s", mp->name); 586 if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
587 outp += sprintf(outp, "%s%8s", delim, mp->name);
588 else
589 outp += sprintf(outp, "%s%s", delim, mp->name);
406 } 590 }
407 } 591 }
408 592
409 if (do_ptm) 593 if (DO_BIC(BIC_PkgTmp))
410 outp += sprintf(outp, "\tPkgTmp"); 594 outp += sprintf(outp, "%sPkgTmp", (printed++ ? delim : ""));
411 595
412 if (do_gfx_rc6_ms) 596 if (DO_BIC(BIC_GFX_rc6))
413 outp += sprintf(outp, "\tGFX%%rc6"); 597 outp += sprintf(outp, "%sGFX%%rc6", (printed++ ? delim : ""));
414 598
415 if (do_gfx_mhz) 599 if (DO_BIC(BIC_GFXMHz))
416 outp += sprintf(outp, "\tGFXMHz"); 600 outp += sprintf(outp, "%sGFXMHz", (printed++ ? delim : ""));
417 601
418 if (do_skl_residency) { 602 if (do_skl_residency) {
419 outp += sprintf(outp, "\tTotl%%C0"); 603 outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : ""));
420 outp += sprintf(outp, "\tAny%%C0"); 604 outp += sprintf(outp, "%sAny%%C0", (printed++ ? delim : ""));
421 outp += sprintf(outp, "\tGFX%%C0"); 605 outp += sprintf(outp, "%sGFX%%C0", (printed++ ? delim : ""));
422 outp += sprintf(outp, "\tCPUGFX%%"); 606 outp += sprintf(outp, "%sCPUGFX%%", (printed++ ? delim : ""));
423 }
424
425 if (do_pc2)
426 outp += sprintf(outp, "\tPkg%%pc2");
427 if (do_pc3)
428 outp += sprintf(outp, "\tPkg%%pc3");
429 if (do_pc6)
430 outp += sprintf(outp, "\tPkg%%pc6");
431 if (do_pc7)
432 outp += sprintf(outp, "\tPkg%%pc7");
433 if (do_c8_c9_c10) {
434 outp += sprintf(outp, "\tPkg%%pc8");
435 outp += sprintf(outp, "\tPkg%%pc9");
436 outp += sprintf(outp, "\tPk%%pc10");
437 } 607 }
438 608
609 if (DO_BIC(BIC_Pkgpc2))
610 outp += sprintf(outp, "%sPkg%%pc2", (printed++ ? delim : ""));
611 if (DO_BIC(BIC_Pkgpc3))
612 outp += sprintf(outp, "%sPkg%%pc3", (printed++ ? delim : ""));
613 if (DO_BIC(BIC_Pkgpc6))
614 outp += sprintf(outp, "%sPkg%%pc6", (printed++ ? delim : ""));
615 if (DO_BIC(BIC_Pkgpc7))
616 outp += sprintf(outp, "%sPkg%%pc7", (printed++ ? delim : ""));
617 if (DO_BIC(BIC_Pkgpc8))
618 outp += sprintf(outp, "%sPkg%%pc8", (printed++ ? delim : ""));
619 if (DO_BIC(BIC_Pkgpc9))
620 outp += sprintf(outp, "%sPkg%%pc9", (printed++ ? delim : ""));
621 if (DO_BIC(BIC_Pkgpc10))
622 outp += sprintf(outp, "%sPk%%pc10", (printed++ ? delim : ""));
623
439 if (do_rapl && !rapl_joules) { 624 if (do_rapl && !rapl_joules) {
440 if (do_rapl & RAPL_PKG) 625 if (DO_BIC(BIC_PkgWatt))
441 outp += sprintf(outp, "\tPkgWatt"); 626 outp += sprintf(outp, "%sPkgWatt", (printed++ ? delim : ""));
442 if (do_rapl & RAPL_CORES_ENERGY_STATUS) 627 if (DO_BIC(BIC_CorWatt))
443 outp += sprintf(outp, "\tCorWatt"); 628 outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : ""));
444 if (do_rapl & RAPL_GFX) 629 if (DO_BIC(BIC_GFXWatt))
445 outp += sprintf(outp, "\tGFXWatt"); 630 outp += sprintf(outp, "%sGFXWatt", (printed++ ? delim : ""));
446 if (do_rapl & RAPL_DRAM) 631 if (DO_BIC(BIC_RAMWatt))
447 outp += sprintf(outp, "\tRAMWatt"); 632 outp += sprintf(outp, "%sRAMWatt", (printed++ ? delim : ""));
448 if (do_rapl & RAPL_PKG_PERF_STATUS) 633 if (DO_BIC(BIC_PKG__))
449 outp += sprintf(outp, "\tPKG_%%"); 634 outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));
450 if (do_rapl & RAPL_DRAM_PERF_STATUS) 635 if (DO_BIC(BIC_RAM__))
451 outp += sprintf(outp, "\tRAM_%%"); 636 outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));
452 } else if (do_rapl && rapl_joules) { 637 } else if (do_rapl && rapl_joules) {
453 if (do_rapl & RAPL_PKG) 638 if (DO_BIC(BIC_Pkg_J))
454 outp += sprintf(outp, "\tPkg_J"); 639 outp += sprintf(outp, "%sPkg_J", (printed++ ? delim : ""));
455 if (do_rapl & RAPL_CORES_ENERGY_STATUS) 640 if (DO_BIC(BIC_Cor_J))
456 outp += sprintf(outp, "\tCor_J"); 641 outp += sprintf(outp, "%sCor_J", (printed++ ? delim : ""));
457 if (do_rapl & RAPL_GFX) 642 if (DO_BIC(BIC_GFX_J))
458 outp += sprintf(outp, "\tGFX_J"); 643 outp += sprintf(outp, "%sGFX_J", (printed++ ? delim : ""));
459 if (do_rapl & RAPL_DRAM) 644 if (DO_BIC(BIC_RAM_J))
460 outp += sprintf(outp, "\tRAM_J"); 645 outp += sprintf(outp, "%sRAM_J", (printed++ ? delim : ""));
461 if (do_rapl & RAPL_PKG_PERF_STATUS) 646 if (DO_BIC(BIC_PKG__))
462 outp += sprintf(outp, "\tPKG_%%"); 647 outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));
463 if (do_rapl & RAPL_DRAM_PERF_STATUS) 648 if (DO_BIC(BIC_RAM__))
464 outp += sprintf(outp, "\tRAM_%%"); 649 outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));
465 } 650 }
466 for (mp = sys.pp; mp; mp = mp->next) { 651 for (mp = sys.pp; mp; mp = mp->next) {
467 if (mp->format == FORMAT_RAW) { 652 if (mp->format == FORMAT_RAW) {
468 if (mp->width == 64) 653 if (mp->width == 64)
469 outp += sprintf(outp, "\t%18.18s", mp->name); 654 outp += sprintf(outp, "%s%18.18s", delim, mp->name);
470 else 655 else
471 outp += sprintf(outp, "\t%10.10s", mp->name); 656 outp += sprintf(outp, "%s%10.10s", delim, mp->name);
472 } else { 657 } else {
473 outp += sprintf(outp, "\t%-7.7s", mp->name); 658 if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
659 outp += sprintf(outp, "%s%8s", delim, mp->name);
660 else
661 outp += sprintf(outp, "%s%s", delim, mp->name);
474 } 662 }
475 } 663 }
476 664
477done:
478 outp += sprintf(outp, "\n"); 665 outp += sprintf(outp, "\n");
479} 666}
480 667
@@ -494,10 +681,10 @@ int dump_counters(struct thread_data *t, struct core_data *c,
494 outp += sprintf(outp, "mperf: %016llX\n", t->mperf); 681 outp += sprintf(outp, "mperf: %016llX\n", t->mperf);
495 outp += sprintf(outp, "c1: %016llX\n", t->c1); 682 outp += sprintf(outp, "c1: %016llX\n", t->c1);
496 683
497 if (do_irq) 684 if (DO_BIC(BIC_IRQ))
498 outp += sprintf(outp, "IRQ: %08X\n", t->irq_count); 685 outp += sprintf(outp, "IRQ: %lld\n", t->irq_count);
499 if (do_smi) 686 if (DO_BIC(BIC_SMI))
500 outp += sprintf(outp, "SMI: %08X\n", t->smi_count); 687 outp += sprintf(outp, "SMI: %d\n", t->smi_count);
501 688
502 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 689 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
503 outp += sprintf(outp, "tADDED [%d] msr0x%x: %08llX\n", 690 outp += sprintf(outp, "tADDED [%d] msr0x%x: %08llX\n",
@@ -516,6 +703,7 @@ int dump_counters(struct thread_data *t, struct core_data *c,
516 outp += sprintf(outp, "cADDED [%d] msr0x%x: %08llX\n", 703 outp += sprintf(outp, "cADDED [%d] msr0x%x: %08llX\n",
517 i, mp->msr_num, c->counter[i]); 704 i, mp->msr_num, c->counter[i]);
518 } 705 }
706 outp += sprintf(outp, "mc6_us: %016llX\n", c->mc6_us);
519 } 707 }
520 708
521 if (p) { 709 if (p) {
@@ -527,11 +715,11 @@ int dump_counters(struct thread_data *t, struct core_data *c,
527 outp += sprintf(outp, "CPU + GFX: %016llX\n", p->pkg_both_core_gfxe_c0); 715 outp += sprintf(outp, "CPU + GFX: %016llX\n", p->pkg_both_core_gfxe_c0);
528 716
529 outp += sprintf(outp, "pc2: %016llX\n", p->pc2); 717 outp += sprintf(outp, "pc2: %016llX\n", p->pc2);
530 if (do_pc3) 718 if (DO_BIC(BIC_Pkgpc3))
531 outp += sprintf(outp, "pc3: %016llX\n", p->pc3); 719 outp += sprintf(outp, "pc3: %016llX\n", p->pc3);
532 if (do_pc6) 720 if (DO_BIC(BIC_Pkgpc6))
533 outp += sprintf(outp, "pc6: %016llX\n", p->pc6); 721 outp += sprintf(outp, "pc6: %016llX\n", p->pc6);
534 if (do_pc7) 722 if (DO_BIC(BIC_Pkgpc7))
535 outp += sprintf(outp, "pc7: %016llX\n", p->pc7); 723 outp += sprintf(outp, "pc7: %016llX\n", p->pc7);
536 outp += sprintf(outp, "pc8: %016llX\n", p->pc8); 724 outp += sprintf(outp, "pc8: %016llX\n", p->pc8);
537 outp += sprintf(outp, "pc9: %016llX\n", p->pc9); 725 outp += sprintf(outp, "pc9: %016llX\n", p->pc9);
@@ -563,10 +751,12 @@ int dump_counters(struct thread_data *t, struct core_data *c,
563int format_counters(struct thread_data *t, struct core_data *c, 751int format_counters(struct thread_data *t, struct core_data *c,
564 struct pkg_data *p) 752 struct pkg_data *p)
565{ 753{
566 double interval_float; 754 double interval_float, tsc;
567 char *fmt8; 755 char *fmt8;
568 int i; 756 int i;
569 struct msr_counter *mp; 757 struct msr_counter *mp;
758 char *delim = "\t";
759 int printed = 0;
570 760
571 /* if showing only 1st thread in core and this isn't one, bail out */ 761 /* if showing only 1st thread in core and this isn't one, bail out */
572 if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 762 if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
@@ -576,106 +766,126 @@ int format_counters(struct thread_data *t, struct core_data *c,
576 if (show_pkg_only && !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 766 if (show_pkg_only && !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
577 return 0; 767 return 0;
578 768
769 /*if not summary line and --cpu is used */
770 if ((t != &average.threads) &&
771 (cpu_subset && !CPU_ISSET_S(t->cpu_id, cpu_subset_size, cpu_subset)))
772 return 0;
773
579 interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0; 774 interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0;
580 775
776 tsc = t->tsc * tsc_tweak;
777
581 /* topo columns, print blanks on 1st (average) line */ 778 /* topo columns, print blanks on 1st (average) line */
582 if (t == &average.threads) { 779 if (t == &average.threads) {
583 if (show_pkg) 780 if (DO_BIC(BIC_Package))
584 outp += sprintf(outp, "\t-"); 781 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
585 if (show_core) 782 if (DO_BIC(BIC_Core))
586 outp += sprintf(outp, "\t-"); 783 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
587 if (show_cpu) 784 if (DO_BIC(BIC_CPU))
588 outp += sprintf(outp, "\t-"); 785 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
589 } else { 786 } else {
590 if (show_pkg) { 787 if (DO_BIC(BIC_Package)) {
591 if (p) 788 if (p)
592 outp += sprintf(outp, "\t%d", p->package_id); 789 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->package_id);
593 else 790 else
594 outp += sprintf(outp, "\t-"); 791 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
595 } 792 }
596 if (show_core) { 793 if (DO_BIC(BIC_Core)) {
597 if (c) 794 if (c)
598 outp += sprintf(outp, "\t%d", c->core_id); 795 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_id);
599 else 796 else
600 outp += sprintf(outp, "\t-"); 797 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
601 } 798 }
602 if (show_cpu) 799 if (DO_BIC(BIC_CPU))
603 outp += sprintf(outp, "\t%d", t->cpu_id); 800 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->cpu_id);
604 } 801 }
605 802
606 /* Avg_MHz */ 803 if (DO_BIC(BIC_Avg_MHz))
607 if (has_aperf) 804 outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""),
608 outp += sprintf(outp, "\t%.0f",
609 1.0 / units * t->aperf / interval_float); 805 1.0 / units * t->aperf / interval_float);
610 806
611 /* Busy% */ 807 if (DO_BIC(BIC_Busy))
612 if (has_aperf) 808 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->mperf/tsc);
613 outp += sprintf(outp, "\t%.2f", 100.0 * t->mperf/t->tsc/tsc_tweak);
614 809
615 /* Bzy_MHz */ 810 if (DO_BIC(BIC_Bzy_MHz)) {
616 if (has_aperf) {
617 if (has_base_hz) 811 if (has_base_hz)
618 outp += sprintf(outp, "\t%.0f", base_hz / units * t->aperf / t->mperf); 812 outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), base_hz / units * t->aperf / t->mperf);
619 else 813 else
620 outp += sprintf(outp, "\t%.0f", 814 outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""),
621 1.0 * t->tsc / units * t->aperf / t->mperf / interval_float); 815 tsc / units * t->aperf / t->mperf / interval_float);
622 } 816 }
623 817
624 /* TSC_MHz */ 818 if (DO_BIC(BIC_TSC_MHz))
625 outp += sprintf(outp, "\t%.0f", 1.0 * t->tsc/units/interval_float); 819 outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 * t->tsc/units/interval_float);
626
627 if (!debug)
628 goto done;
629 820
630 /* IRQ */ 821 /* IRQ */
631 if (do_irq) 822 if (DO_BIC(BIC_IRQ)) {
632 outp += sprintf(outp, "\t%d", t->irq_count); 823 if (sums_need_wide_columns)
824 outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->irq_count);
825 else
826 outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->irq_count);
827 }
633 828
634 /* SMI */ 829 /* SMI */
635 if (do_smi) 830 if (DO_BIC(BIC_SMI))
636 outp += sprintf(outp, "\t%d", t->smi_count); 831 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->smi_count);
637
638 if (do_nhm_cstates)
639 outp += sprintf(outp, "\t%.2f", 100.0 * t->c1/t->tsc);
640
641 /* print per-core data only for 1st thread in core */
642 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
643 goto done;
644
645 if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates)
646 outp += sprintf(outp, "\t%.2f", 100.0 * c->c3/t->tsc);
647 if (do_nhm_cstates)
648 outp += sprintf(outp, "\t%.2f", 100.0 * c->c6/t->tsc);
649 if (do_snb_cstates)
650 outp += sprintf(outp, "\t%.2f", 100.0 * c->c7/t->tsc);
651 832
833 /* Added counters */
652 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 834 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
653 if (mp->format == FORMAT_RAW) { 835 if (mp->format == FORMAT_RAW) {
654 if (mp->width == 32) 836 if (mp->width == 32)
655 outp += sprintf(outp, "\t0x%08lx", (unsigned long) t->counter[i]); 837 outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) t->counter[i]);
656 else 838 else
657 outp += sprintf(outp, "\t0x%016llx", t->counter[i]); 839 outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), t->counter[i]);
658 } else if (mp->format == FORMAT_DELTA) { 840 } else if (mp->format == FORMAT_DELTA) {
659 outp += sprintf(outp, "\t%8lld", t->counter[i]); 841 if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
842 outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->counter[i]);
843 else
844 outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->counter[i]);
660 } else if (mp->format == FORMAT_PERCENT) { 845 } else if (mp->format == FORMAT_PERCENT) {
661 outp += sprintf(outp, "\t%.2f", 100.0 * t->counter[i]/t->tsc); 846 if (mp->type == COUNTER_USEC)
847 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), t->counter[i]/interval_float/10000);
848 else
849 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->counter[i]/tsc);
662 } 850 }
663 } 851 }
664 852
853 /* C1 */
854 if (DO_BIC(BIC_CPU_c1))
855 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->c1/tsc);
665 856
666 if (do_dts) 857
667 outp += sprintf(outp, "\t%d", c->core_temp_c); 858 /* print per-core data only for 1st thread in core */
859 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
860 goto done;
861
862 if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates)
863 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c3/tsc);
864 if (DO_BIC(BIC_CPU_c6))
865 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c6/tsc);
866 if (DO_BIC(BIC_CPU_c7))
867 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c7/tsc);
868
869 /* Mod%c6 */
870 if (DO_BIC(BIC_Mod_c6))
871 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->mc6_us / tsc);
872
873 if (DO_BIC(BIC_CoreTmp))
874 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_temp_c);
668 875
669 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 876 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
670 if (mp->format == FORMAT_RAW) { 877 if (mp->format == FORMAT_RAW) {
671 if (mp->width == 32) 878 if (mp->width == 32)
672 outp += sprintf(outp, "\t0x%08lx", (unsigned long) c->counter[i]); 879 outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) c->counter[i]);
673 else 880 else
674 outp += sprintf(outp, "\t0x%016llx", c->counter[i]); 881 outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), c->counter[i]);
675 } else if (mp->format == FORMAT_DELTA) { 882 } else if (mp->format == FORMAT_DELTA) {
676 outp += sprintf(outp, "\t%8lld", c->counter[i]); 883 if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
884 outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), c->counter[i]);
885 else
886 outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), c->counter[i]);
677 } else if (mp->format == FORMAT_PERCENT) { 887 } else if (mp->format == FORMAT_PERCENT) {
678 outp += sprintf(outp, "\t%.2f", 100.0 * c->counter[i]/t->tsc); 888 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->counter[i]/tsc);
679 } 889 }
680 } 890 }
681 891
@@ -684,95 +894,89 @@ int format_counters(struct thread_data *t, struct core_data *c,
684 goto done; 894 goto done;
685 895
686 /* PkgTmp */ 896 /* PkgTmp */
687 if (do_ptm) 897 if (DO_BIC(BIC_PkgTmp))
688 outp += sprintf(outp, "\t%d", p->pkg_temp_c); 898 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->pkg_temp_c);
689 899
690 /* GFXrc6 */ 900 /* GFXrc6 */
691 if (do_gfx_rc6_ms) { 901 if (DO_BIC(BIC_GFX_rc6)) {
692 if (p->gfx_rc6_ms == -1) { /* detect GFX counter reset */ 902 if (p->gfx_rc6_ms == -1) { /* detect GFX counter reset */
693 outp += sprintf(outp, "\t**.**"); 903 outp += sprintf(outp, "%s**.**", (printed++ ? delim : ""));
694 } else { 904 } else {
695 outp += sprintf(outp, "\t%.2f", 905 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""),
696 p->gfx_rc6_ms / 10.0 / interval_float); 906 p->gfx_rc6_ms / 10.0 / interval_float);
697 } 907 }
698 } 908 }
699 909
700 /* GFXMHz */ 910 /* GFXMHz */
701 if (do_gfx_mhz) 911 if (DO_BIC(BIC_GFXMHz))
702 outp += sprintf(outp, "\t%d", p->gfx_mhz); 912 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_mhz);
703 913
704 /* Totl%C0, Any%C0 GFX%C0 CPUGFX% */ 914 /* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
705 if (do_skl_residency) { 915 if (do_skl_residency) {
706 outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_wtd_core_c0/t->tsc); 916 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_wtd_core_c0/tsc);
707 outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_any_core_c0/t->tsc); 917 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_core_c0/tsc);
708 outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_any_gfxe_c0/t->tsc); 918 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_gfxe_c0/tsc);
709 outp += sprintf(outp, "\t%.2f", 100.0 * p->pkg_both_core_gfxe_c0/t->tsc); 919 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_both_core_gfxe_c0/tsc);
710 }
711
712 if (do_pc2)
713 outp += sprintf(outp, "\t%.2f", 100.0 * p->pc2/t->tsc);
714 if (do_pc3)
715 outp += sprintf(outp, "\t%.2f", 100.0 * p->pc3/t->tsc);
716 if (do_pc6)
717 outp += sprintf(outp, "\t%.2f", 100.0 * p->pc6/t->tsc);
718 if (do_pc7)
719 outp += sprintf(outp, "\t%.2f", 100.0 * p->pc7/t->tsc);
720 if (do_c8_c9_c10) {
721 outp += sprintf(outp, "\t%.2f", 100.0 * p->pc8/t->tsc);
722 outp += sprintf(outp, "\t%.2f", 100.0 * p->pc9/t->tsc);
723 outp += sprintf(outp, "\t%.2f", 100.0 * p->pc10/t->tsc);
724 } 920 }
725 921
922 if (DO_BIC(BIC_Pkgpc2))
923 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc2/tsc);
924 if (DO_BIC(BIC_Pkgpc3))
925 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc3/tsc);
926 if (DO_BIC(BIC_Pkgpc6))
927 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc6/tsc);
928 if (DO_BIC(BIC_Pkgpc7))
929 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc7/tsc);
930 if (DO_BIC(BIC_Pkgpc8))
931 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc8/tsc);
932 if (DO_BIC(BIC_Pkgpc9))
933 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc9/tsc);
934 if (DO_BIC(BIC_Pkgpc10))
935 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc10/tsc);
936
726 /* 937 /*
727 * If measurement interval exceeds minimum RAPL Joule Counter range, 938 * If measurement interval exceeds minimum RAPL Joule Counter range,
728 * indicate that results are suspect by printing "**" in fraction place. 939 * indicate that results are suspect by printing "**" in fraction place.
729 */ 940 */
730 if (interval_float < rapl_joule_counter_range) 941 if (interval_float < rapl_joule_counter_range)
731 fmt8 = "\t%.2f"; 942 fmt8 = "%s%.2f";
732 else 943 else
733 fmt8 = "%6.0f**"; 944 fmt8 = "%6.0f**";
734 945
735 if (do_rapl && !rapl_joules) { 946 if (DO_BIC(BIC_PkgWatt))
736 if (do_rapl & RAPL_PKG) 947 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units / interval_float);
737 outp += sprintf(outp, fmt8, p->energy_pkg * rapl_energy_units / interval_float); 948 if (DO_BIC(BIC_CorWatt))
738 if (do_rapl & RAPL_CORES_ENERGY_STATUS) 949 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units / interval_float);
739 outp += sprintf(outp, fmt8, p->energy_cores * rapl_energy_units / interval_float); 950 if (DO_BIC(BIC_GFXWatt))
740 if (do_rapl & RAPL_GFX) 951 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units / interval_float);
741 outp += sprintf(outp, fmt8, p->energy_gfx * rapl_energy_units / interval_float); 952 if (DO_BIC(BIC_RAMWatt))
742 if (do_rapl & RAPL_DRAM) 953 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_dram * rapl_dram_energy_units / interval_float);
743 outp += sprintf(outp, fmt8, p->energy_dram * rapl_dram_energy_units / interval_float); 954 if (DO_BIC(BIC_Pkg_J))
744 if (do_rapl & RAPL_PKG_PERF_STATUS) 955 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units);
745 outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); 956 if (DO_BIC(BIC_Cor_J))
746 if (do_rapl & RAPL_DRAM_PERF_STATUS) 957 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units);
747 outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); 958 if (DO_BIC(BIC_GFX_J))
748 } else if (do_rapl && rapl_joules) { 959 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units);
749 if (do_rapl & RAPL_PKG) 960 if (DO_BIC(BIC_RAM_J))
750 outp += sprintf(outp, fmt8, 961 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_dram * rapl_dram_energy_units);
751 p->energy_pkg * rapl_energy_units); 962 if (DO_BIC(BIC_PKG__))
752 if (do_rapl & RAPL_CORES) 963 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
753 outp += sprintf(outp, fmt8, 964 if (DO_BIC(BIC_RAM__))
754 p->energy_cores * rapl_energy_units); 965 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
755 if (do_rapl & RAPL_GFX) 966
756 outp += sprintf(outp, fmt8,
757 p->energy_gfx * rapl_energy_units);
758 if (do_rapl & RAPL_DRAM)
759 outp += sprintf(outp, fmt8,
760 p->energy_dram * rapl_dram_energy_units);
761 if (do_rapl & RAPL_PKG_PERF_STATUS)
762 outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
763 if (do_rapl & RAPL_DRAM_PERF_STATUS)
764 outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
765 }
766 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 967 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
767 if (mp->format == FORMAT_RAW) { 968 if (mp->format == FORMAT_RAW) {
768 if (mp->width == 32) 969 if (mp->width == 32)
769 outp += sprintf(outp, "\t0x%08lx", (unsigned long) p->counter[i]); 970 outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) p->counter[i]);
770 else 971 else
771 outp += sprintf(outp, "\t0x%016llx", p->counter[i]); 972 outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), p->counter[i]);
772 } else if (mp->format == FORMAT_DELTA) { 973 } else if (mp->format == FORMAT_DELTA) {
773 outp += sprintf(outp, "\t%8lld", p->counter[i]); 974 if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
975 outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), p->counter[i]);
976 else
977 outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), p->counter[i]);
774 } else if (mp->format == FORMAT_PERCENT) { 978 } else if (mp->format == FORMAT_PERCENT) {
775 outp += sprintf(outp, "\t%.2f", 100.0 * p->counter[i]/t->tsc); 979 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->counter[i]/tsc);
776 } 980 }
777 } 981 }
778 982
@@ -807,7 +1011,7 @@ void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_
807 static int printed; 1011 static int printed;
808 1012
809 if (!printed || !summary_only) 1013 if (!printed || !summary_only)
810 print_header(); 1014 print_header("\t");
811 1015
812 if (topo.num_cpus > 1) 1016 if (topo.num_cpus > 1)
813 format_counters(&average.threads, &average.cores, 1017 format_counters(&average.threads, &average.cores,
@@ -841,11 +1045,11 @@ delta_package(struct pkg_data *new, struct pkg_data *old)
841 old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0; 1045 old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0;
842 } 1046 }
843 old->pc2 = new->pc2 - old->pc2; 1047 old->pc2 = new->pc2 - old->pc2;
844 if (do_pc3) 1048 if (DO_BIC(BIC_Pkgpc3))
845 old->pc3 = new->pc3 - old->pc3; 1049 old->pc3 = new->pc3 - old->pc3;
846 if (do_pc6) 1050 if (DO_BIC(BIC_Pkgpc6))
847 old->pc6 = new->pc6 - old->pc6; 1051 old->pc6 = new->pc6 - old->pc6;
848 if (do_pc7) 1052 if (DO_BIC(BIC_Pkgpc7))
849 old->pc7 = new->pc7 - old->pc7; 1053 old->pc7 = new->pc7 - old->pc7;
850 old->pc8 = new->pc8 - old->pc8; 1054 old->pc8 = new->pc8 - old->pc8;
851 old->pc9 = new->pc9 - old->pc9; 1055 old->pc9 = new->pc9 - old->pc9;
@@ -887,6 +1091,7 @@ delta_core(struct core_data *new, struct core_data *old)
887 old->c6 = new->c6 - old->c6; 1091 old->c6 = new->c6 - old->c6;
888 old->c7 = new->c7 - old->c7; 1092 old->c7 = new->c7 - old->c7;
889 old->core_temp_c = new->core_temp_c; 1093 old->core_temp_c = new->core_temp_c;
1094 old->mc6_us = new->mc6_us - old->mc6_us;
890 1095
891 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 1096 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
892 if (mp->format == FORMAT_RAW) 1097 if (mp->format == FORMAT_RAW)
@@ -916,7 +1121,7 @@ delta_thread(struct thread_data *new, struct thread_data *old,
916 1121
917 old->c1 = new->c1 - old->c1; 1122 old->c1 = new->c1 - old->c1;
918 1123
919 if (has_aperf) { 1124 if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz)) {
920 if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) { 1125 if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {
921 old->aperf = new->aperf - old->aperf; 1126 old->aperf = new->aperf - old->aperf;
922 old->mperf = new->mperf - old->mperf; 1127 old->mperf = new->mperf - old->mperf;
@@ -941,7 +1146,7 @@ delta_thread(struct thread_data *new, struct thread_data *old,
941 old->c1 = 0; 1146 old->c1 = 0;
942 else { 1147 else {
943 /* normal case, derive c1 */ 1148 /* normal case, derive c1 */
944 old->c1 = old->tsc - old->mperf - core_delta->c3 1149 old->c1 = (old->tsc * tsc_tweak) - old->mperf - core_delta->c3
945 - core_delta->c6 - core_delta->c7; 1150 - core_delta->c6 - core_delta->c7;
946 } 1151 }
947 } 1152 }
@@ -952,10 +1157,10 @@ delta_thread(struct thread_data *new, struct thread_data *old,
952 old->mperf = 1; /* divide by 0 protection */ 1157 old->mperf = 1; /* divide by 0 protection */
953 } 1158 }
954 1159
955 if (do_irq) 1160 if (DO_BIC(BIC_IRQ))
956 old->irq_count = new->irq_count - old->irq_count; 1161 old->irq_count = new->irq_count - old->irq_count;
957 1162
958 if (do_smi) 1163 if (DO_BIC(BIC_SMI))
959 old->smi_count = new->smi_count - old->smi_count; 1164 old->smi_count = new->smi_count - old->smi_count;
960 1165
961 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 1166 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
@@ -1008,6 +1213,7 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
1008 c->c3 = 0; 1213 c->c3 = 0;
1009 c->c6 = 0; 1214 c->c6 = 0;
1010 c->c7 = 0; 1215 c->c7 = 0;
1216 c->mc6_us = 0;
1011 c->core_temp_c = 0; 1217 c->core_temp_c = 0;
1012 1218
1013 p->pkg_wtd_core_c0 = 0; 1219 p->pkg_wtd_core_c0 = 0;
@@ -1016,11 +1222,11 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
1016 p->pkg_both_core_gfxe_c0 = 0; 1222 p->pkg_both_core_gfxe_c0 = 0;
1017 1223
1018 p->pc2 = 0; 1224 p->pc2 = 0;
1019 if (do_pc3) 1225 if (DO_BIC(BIC_Pkgpc3))
1020 p->pc3 = 0; 1226 p->pc3 = 0;
1021 if (do_pc6) 1227 if (DO_BIC(BIC_Pkgpc6))
1022 p->pc6 = 0; 1228 p->pc6 = 0;
1023 if (do_pc7) 1229 if (DO_BIC(BIC_Pkgpc7))
1024 p->pc7 = 0; 1230 p->pc7 = 0;
1025 p->pc8 = 0; 1231 p->pc8 = 0;
1026 p->pc9 = 0; 1232 p->pc9 = 0;
@@ -1036,7 +1242,6 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
1036 1242
1037 p->gfx_rc6_ms = 0; 1243 p->gfx_rc6_ms = 0;
1038 p->gfx_mhz = 0; 1244 p->gfx_mhz = 0;
1039
1040 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) 1245 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next)
1041 t->counter[i] = 0; 1246 t->counter[i] = 0;
1042 1247
@@ -1073,6 +1278,7 @@ int sum_counters(struct thread_data *t, struct core_data *c,
1073 average.cores.c3 += c->c3; 1278 average.cores.c3 += c->c3;
1074 average.cores.c6 += c->c6; 1279 average.cores.c6 += c->c6;
1075 average.cores.c7 += c->c7; 1280 average.cores.c7 += c->c7;
1281 average.cores.mc6_us += c->mc6_us;
1076 1282
1077 average.cores.core_temp_c = MAX(average.cores.core_temp_c, c->core_temp_c); 1283 average.cores.core_temp_c = MAX(average.cores.core_temp_c, c->core_temp_c);
1078 1284
@@ -1094,11 +1300,11 @@ int sum_counters(struct thread_data *t, struct core_data *c,
1094 } 1300 }
1095 1301
1096 average.packages.pc2 += p->pc2; 1302 average.packages.pc2 += p->pc2;
1097 if (do_pc3) 1303 if (DO_BIC(BIC_Pkgpc3))
1098 average.packages.pc3 += p->pc3; 1304 average.packages.pc3 += p->pc3;
1099 if (do_pc6) 1305 if (DO_BIC(BIC_Pkgpc6))
1100 average.packages.pc6 += p->pc6; 1306 average.packages.pc6 += p->pc6;
1101 if (do_pc7) 1307 if (DO_BIC(BIC_Pkgpc7))
1102 average.packages.pc7 += p->pc7; 1308 average.packages.pc7 += p->pc7;
1103 average.packages.pc8 += p->pc8; 1309 average.packages.pc8 += p->pc8;
1104 average.packages.pc9 += p->pc9; 1310 average.packages.pc9 += p->pc9;
@@ -1143,9 +1349,13 @@ void compute_average(struct thread_data *t, struct core_data *c,
1143 average.threads.mperf /= topo.num_cpus; 1349 average.threads.mperf /= topo.num_cpus;
1144 average.threads.c1 /= topo.num_cpus; 1350 average.threads.c1 /= topo.num_cpus;
1145 1351
1352 if (average.threads.irq_count > 9999999)
1353 sums_need_wide_columns = 1;
1354
1146 average.cores.c3 /= topo.num_cores; 1355 average.cores.c3 /= topo.num_cores;
1147 average.cores.c6 /= topo.num_cores; 1356 average.cores.c6 /= topo.num_cores;
1148 average.cores.c7 /= topo.num_cores; 1357 average.cores.c7 /= topo.num_cores;
1358 average.cores.mc6_us /= topo.num_cores;
1149 1359
1150 if (do_skl_residency) { 1360 if (do_skl_residency) {
1151 average.packages.pkg_wtd_core_c0 /= topo.num_packages; 1361 average.packages.pkg_wtd_core_c0 /= topo.num_packages;
@@ -1155,11 +1365,11 @@ void compute_average(struct thread_data *t, struct core_data *c,
1155 } 1365 }
1156 1366
1157 average.packages.pc2 /= topo.num_packages; 1367 average.packages.pc2 /= topo.num_packages;
1158 if (do_pc3) 1368 if (DO_BIC(BIC_Pkgpc3))
1159 average.packages.pc3 /= topo.num_packages; 1369 average.packages.pc3 /= topo.num_packages;
1160 if (do_pc6) 1370 if (DO_BIC(BIC_Pkgpc6))
1161 average.packages.pc6 /= topo.num_packages; 1371 average.packages.pc6 /= topo.num_packages;
1162 if (do_pc7) 1372 if (DO_BIC(BIC_Pkgpc7))
1163 average.packages.pc7 /= topo.num_packages; 1373 average.packages.pc7 /= topo.num_packages;
1164 1374
1165 average.packages.pc8 /= topo.num_packages; 1375 average.packages.pc8 /= topo.num_packages;
@@ -1169,16 +1379,29 @@ void compute_average(struct thread_data *t, struct core_data *c,
1169 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 1379 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
1170 if (mp->format == FORMAT_RAW) 1380 if (mp->format == FORMAT_RAW)
1171 continue; 1381 continue;
1382 if (mp->type == COUNTER_ITEMS) {
1383 if (average.threads.counter[i] > 9999999)
1384 sums_need_wide_columns = 1;
1385 continue;
1386 }
1172 average.threads.counter[i] /= topo.num_cpus; 1387 average.threads.counter[i] /= topo.num_cpus;
1173 } 1388 }
1174 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 1389 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
1175 if (mp->format == FORMAT_RAW) 1390 if (mp->format == FORMAT_RAW)
1176 continue; 1391 continue;
1392 if (mp->type == COUNTER_ITEMS) {
1393 if (average.cores.counter[i] > 9999999)
1394 sums_need_wide_columns = 1;
1395 }
1177 average.cores.counter[i] /= topo.num_cores; 1396 average.cores.counter[i] /= topo.num_cores;
1178 } 1397 }
1179 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 1398 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
1180 if (mp->format == FORMAT_RAW) 1399 if (mp->format == FORMAT_RAW)
1181 continue; 1400 continue;
1401 if (mp->type == COUNTER_ITEMS) {
1402 if (average.packages.counter[i] > 9999999)
1403 sums_need_wide_columns = 1;
1404 }
1182 average.packages.counter[i] /= topo.num_packages; 1405 average.packages.counter[i] /= topo.num_packages;
1183 } 1406 }
1184} 1407}
@@ -1193,6 +1416,60 @@ static unsigned long long rdtsc(void)
1193} 1416}
1194 1417
1195/* 1418/*
1419 * Open a file, and exit on failure
1420 */
1421FILE *fopen_or_die(const char *path, const char *mode)
1422{
1423 FILE *filep = fopen(path, mode);
1424
1425 if (!filep)
1426 err(1, "%s: open failed", path);
1427 return filep;
1428}
1429/*
1430 * snapshot_sysfs_counter()
1431 *
1432 * return snapshot of given counter
1433 */
1434unsigned long long snapshot_sysfs_counter(char *path)
1435{
1436 FILE *fp;
1437 int retval;
1438 unsigned long long counter;
1439
1440 fp = fopen_or_die(path, "r");
1441
1442 retval = fscanf(fp, "%lld", &counter);
1443 if (retval != 1)
1444 err(1, "snapshot_sysfs_counter(%s)", path);
1445
1446 fclose(fp);
1447
1448 return counter;
1449}
1450
1451int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp)
1452{
1453 if (mp->msr_num != 0) {
1454 if (get_msr(cpu, mp->msr_num, counterp))
1455 return -1;
1456 } else {
1457 char path[128];
1458
1459 if (mp->flags & SYSFS_PERCPU) {
1460 sprintf(path, "/sys/devices/system/cpu/cpu%d/%s",
1461 cpu, mp->path);
1462
1463 *counterp = snapshot_sysfs_counter(path);
1464 } else {
1465 *counterp = snapshot_sysfs_counter(mp->path);
1466 }
1467 }
1468
1469 return 0;
1470}
1471
1472/*
1196 * get_counters(...) 1473 * get_counters(...)
1197 * migrate to cpu 1474 * migrate to cpu
1198 * acquire and record local counters for that cpu 1475 * acquire and record local counters for that cpu
@@ -1213,7 +1490,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1213retry: 1490retry:
1214 t->tsc = rdtsc(); /* we are running on local CPU of interest */ 1491 t->tsc = rdtsc(); /* we are running on local CPU of interest */
1215 1492
1216 if (has_aperf) { 1493 if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz)) {
1217 unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time; 1494 unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time;
1218 1495
1219 /* 1496 /*
@@ -1269,35 +1546,33 @@ retry:
1269 t->mperf = t->mperf * aperf_mperf_multiplier; 1546 t->mperf = t->mperf * aperf_mperf_multiplier;
1270 } 1547 }
1271 1548
1272 if (do_irq) 1549 if (DO_BIC(BIC_IRQ))
1273 t->irq_count = irqs_per_cpu[cpu]; 1550 t->irq_count = irqs_per_cpu[cpu];
1274 if (do_smi) { 1551 if (DO_BIC(BIC_SMI)) {
1275 if (get_msr(cpu, MSR_SMI_COUNT, &msr)) 1552 if (get_msr(cpu, MSR_SMI_COUNT, &msr))
1276 return -5; 1553 return -5;
1277 t->smi_count = msr & 0xFFFFFFFF; 1554 t->smi_count = msr & 0xFFFFFFFF;
1278 } 1555 }
1279 1556 if (DO_BIC(BIC_CPU_c1) && use_c1_residency_msr) {
1280 if (use_c1_residency_msr) {
1281 if (get_msr(cpu, MSR_CORE_C1_RES, &t->c1)) 1557 if (get_msr(cpu, MSR_CORE_C1_RES, &t->c1))
1282 return -6; 1558 return -6;
1283 } 1559 }
1284 1560
1285 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { 1561 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
1286 if (get_msr(cpu, mp->msr_num, &t->counter[i])) 1562 if (get_mp(cpu, mp, &t->counter[i]))
1287 return -10; 1563 return -10;
1288 } 1564 }
1289 1565
1290
1291 /* collect core counters only for 1st thread in core */ 1566 /* collect core counters only for 1st thread in core */
1292 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 1567 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
1293 return 0; 1568 return 0;
1294 1569
1295 if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates) { 1570 if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates) {
1296 if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3)) 1571 if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3))
1297 return -6; 1572 return -6;
1298 } 1573 }
1299 1574
1300 if (do_nhm_cstates && !do_knl_cstates) { 1575 if (DO_BIC(BIC_CPU_c6) && !do_knl_cstates) {
1301 if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6)) 1576 if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6))
1302 return -7; 1577 return -7;
1303 } else if (do_knl_cstates) { 1578 } else if (do_knl_cstates) {
@@ -1305,18 +1580,22 @@ retry:
1305 return -7; 1580 return -7;
1306 } 1581 }
1307 1582
1308 if (do_snb_cstates) 1583 if (DO_BIC(BIC_CPU_c7))
1309 if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7)) 1584 if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7))
1310 return -8; 1585 return -8;
1311 1586
1312 if (do_dts) { 1587 if (DO_BIC(BIC_Mod_c6))
1588 if (get_msr(cpu, MSR_MODULE_C6_RES_MS, &c->mc6_us))
1589 return -8;
1590
1591 if (DO_BIC(BIC_CoreTmp)) {
1313 if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr)) 1592 if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))
1314 return -9; 1593 return -9;
1315 c->core_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F); 1594 c->core_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F);
1316 } 1595 }
1317 1596
1318 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { 1597 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
1319 if (get_msr(cpu, mp->msr_num, &c->counter[i])) 1598 if (get_mp(cpu, mp, &c->counter[i]))
1320 return -10; 1599 return -10;
1321 } 1600 }
1322 1601
@@ -1334,26 +1613,35 @@ retry:
1334 if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0)) 1613 if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0))
1335 return -13; 1614 return -13;
1336 } 1615 }
1337 if (do_pc3) 1616 if (DO_BIC(BIC_Pkgpc3))
1338 if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3)) 1617 if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3))
1339 return -9; 1618 return -9;
1340 if (do_pc6) 1619 if (DO_BIC(BIC_Pkgpc6)) {
1341 if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6)) 1620 if (do_slm_cstates) {
1342 return -10; 1621 if (get_msr(cpu, MSR_ATOM_PKG_C6_RESIDENCY, &p->pc6))
1343 if (do_pc2) 1622 return -10;
1623 } else {
1624 if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6))
1625 return -10;
1626 }
1627 }
1628
1629 if (DO_BIC(BIC_Pkgpc2))
1344 if (get_msr(cpu, MSR_PKG_C2_RESIDENCY, &p->pc2)) 1630 if (get_msr(cpu, MSR_PKG_C2_RESIDENCY, &p->pc2))
1345 return -11; 1631 return -11;
1346 if (do_pc7) 1632 if (DO_BIC(BIC_Pkgpc7))
1347 if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7)) 1633 if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7))
1348 return -12; 1634 return -12;
1349 if (do_c8_c9_c10) { 1635 if (DO_BIC(BIC_Pkgpc8))
1350 if (get_msr(cpu, MSR_PKG_C8_RESIDENCY, &p->pc8)) 1636 if (get_msr(cpu, MSR_PKG_C8_RESIDENCY, &p->pc8))
1351 return -13; 1637 return -13;
1638 if (DO_BIC(BIC_Pkgpc9))
1352 if (get_msr(cpu, MSR_PKG_C9_RESIDENCY, &p->pc9)) 1639 if (get_msr(cpu, MSR_PKG_C9_RESIDENCY, &p->pc9))
1353 return -13; 1640 return -13;
1641 if (DO_BIC(BIC_Pkgpc10))
1354 if (get_msr(cpu, MSR_PKG_C10_RESIDENCY, &p->pc10)) 1642 if (get_msr(cpu, MSR_PKG_C10_RESIDENCY, &p->pc10))
1355 return -13; 1643 return -13;
1356 } 1644
1357 if (do_rapl & RAPL_PKG) { 1645 if (do_rapl & RAPL_PKG) {
1358 if (get_msr(cpu, MSR_PKG_ENERGY_STATUS, &msr)) 1646 if (get_msr(cpu, MSR_PKG_ENERGY_STATUS, &msr))
1359 return -13; 1647 return -13;
@@ -1384,20 +1672,20 @@ retry:
1384 return -16; 1672 return -16;
1385 p->rapl_dram_perf_status = msr & 0xFFFFFFFF; 1673 p->rapl_dram_perf_status = msr & 0xFFFFFFFF;
1386 } 1674 }
1387 if (do_ptm) { 1675 if (DO_BIC(BIC_PkgTmp)) {
1388 if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr)) 1676 if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))
1389 return -17; 1677 return -17;
1390 p->pkg_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F); 1678 p->pkg_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F);
1391 } 1679 }
1392 1680
1393 if (do_gfx_rc6_ms) 1681 if (DO_BIC(BIC_GFX_rc6))
1394 p->gfx_rc6_ms = gfx_cur_rc6_ms; 1682 p->gfx_rc6_ms = gfx_cur_rc6_ms;
1395 1683
1396 if (do_gfx_mhz) 1684 if (DO_BIC(BIC_GFXMHz))
1397 p->gfx_mhz = gfx_cur_mhz; 1685 p->gfx_mhz = gfx_cur_mhz;
1398 1686
1399 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { 1687 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
1400 if (get_msr(cpu, mp->msr_num, &p->counter[i])) 1688 if (get_mp(cpu, mp, &p->counter[i]))
1401 return -10; 1689 return -10;
1402 } 1690 }
1403 1691
@@ -1433,8 +1721,8 @@ char *pkg_cstate_limit_strings[] = { "reserved", "unknown", "pc0", "pc1", "pc2",
1433int nhm_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1721int nhm_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
1434int snb_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1722int snb_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
1435int hsw_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1723int hsw_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
1436int slv_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1724int slv_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7};
1437int amt_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1725int amt_pkg_cstate_limits[16] = {PCLUNL, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
1438int phi_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1726int phi_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
1439int bxt_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1727int bxt_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
1440int skx_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV}; 1728int skx_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
@@ -1457,11 +1745,11 @@ dump_nhm_platform_info(void)
1457 fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr); 1745 fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr);
1458 1746
1459 ratio = (msr >> 40) & 0xFF; 1747 ratio = (msr >> 40) & 0xFF;
1460 fprintf(outf, "%d * %.0f = %.0f MHz max efficiency frequency\n", 1748 fprintf(outf, "%d * %.1f = %.1f MHz max efficiency frequency\n",
1461 ratio, bclk, ratio * bclk); 1749 ratio, bclk, ratio * bclk);
1462 1750
1463 ratio = (msr >> 8) & 0xFF; 1751 ratio = (msr >> 8) & 0xFF;
1464 fprintf(outf, "%d * %.0f = %.0f MHz base frequency\n", 1752 fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n",
1465 ratio, bclk, ratio * bclk); 1753 ratio, bclk, ratio * bclk);
1466 1754
1467 get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr); 1755 get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr);
@@ -1483,12 +1771,12 @@ dump_hsw_turbo_ratio_limits(void)
1483 1771
1484 ratio = (msr >> 8) & 0xFF; 1772 ratio = (msr >> 8) & 0xFF;
1485 if (ratio) 1773 if (ratio)
1486 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 18 active cores\n", 1774 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 18 active cores\n",
1487 ratio, bclk, ratio * bclk); 1775 ratio, bclk, ratio * bclk);
1488 1776
1489 ratio = (msr >> 0) & 0xFF; 1777 ratio = (msr >> 0) & 0xFF;
1490 if (ratio) 1778 if (ratio)
1491 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 17 active cores\n", 1779 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 17 active cores\n",
1492 ratio, bclk, ratio * bclk); 1780 ratio, bclk, ratio * bclk);
1493 return; 1781 return;
1494} 1782}
@@ -1505,99 +1793,175 @@ dump_ivt_turbo_ratio_limits(void)
1505 1793
1506 ratio = (msr >> 56) & 0xFF; 1794 ratio = (msr >> 56) & 0xFF;
1507 if (ratio) 1795 if (ratio)
1508 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 16 active cores\n", 1796 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 16 active cores\n",
1509 ratio, bclk, ratio * bclk); 1797 ratio, bclk, ratio * bclk);
1510 1798
1511 ratio = (msr >> 48) & 0xFF; 1799 ratio = (msr >> 48) & 0xFF;
1512 if (ratio) 1800 if (ratio)
1513 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 15 active cores\n", 1801 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 15 active cores\n",
1514 ratio, bclk, ratio * bclk); 1802 ratio, bclk, ratio * bclk);
1515 1803
1516 ratio = (msr >> 40) & 0xFF; 1804 ratio = (msr >> 40) & 0xFF;
1517 if (ratio) 1805 if (ratio)
1518 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 14 active cores\n", 1806 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 14 active cores\n",
1519 ratio, bclk, ratio * bclk); 1807 ratio, bclk, ratio * bclk);
1520 1808
1521 ratio = (msr >> 32) & 0xFF; 1809 ratio = (msr >> 32) & 0xFF;
1522 if (ratio) 1810 if (ratio)
1523 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 13 active cores\n", 1811 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 13 active cores\n",
1524 ratio, bclk, ratio * bclk); 1812 ratio, bclk, ratio * bclk);
1525 1813
1526 ratio = (msr >> 24) & 0xFF; 1814 ratio = (msr >> 24) & 0xFF;
1527 if (ratio) 1815 if (ratio)
1528 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 12 active cores\n", 1816 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 12 active cores\n",
1529 ratio, bclk, ratio * bclk); 1817 ratio, bclk, ratio * bclk);
1530 1818
1531 ratio = (msr >> 16) & 0xFF; 1819 ratio = (msr >> 16) & 0xFF;
1532 if (ratio) 1820 if (ratio)
1533 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 11 active cores\n", 1821 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 11 active cores\n",
1534 ratio, bclk, ratio * bclk); 1822 ratio, bclk, ratio * bclk);
1535 1823
1536 ratio = (msr >> 8) & 0xFF; 1824 ratio = (msr >> 8) & 0xFF;
1537 if (ratio) 1825 if (ratio)
1538 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 10 active cores\n", 1826 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 10 active cores\n",
1539 ratio, bclk, ratio * bclk); 1827 ratio, bclk, ratio * bclk);
1540 1828
1541 ratio = (msr >> 0) & 0xFF; 1829 ratio = (msr >> 0) & 0xFF;
1542 if (ratio) 1830 if (ratio)
1543 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 9 active cores\n", 1831 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 9 active cores\n",
1544 ratio, bclk, ratio * bclk); 1832 ratio, bclk, ratio * bclk);
1545 return; 1833 return;
1546} 1834}
1835int has_turbo_ratio_group_limits(int family, int model)
1836{
1837
1838 if (!genuine_intel)
1839 return 0;
1840
1841 switch (model) {
1842 case INTEL_FAM6_ATOM_GOLDMONT:
1843 case INTEL_FAM6_SKYLAKE_X:
1844 case INTEL_FAM6_ATOM_DENVERTON:
1845 return 1;
1846 }
1847 return 0;
1848}
1547 1849
1548static void 1850static void
1549dump_nhm_turbo_ratio_limits(void) 1851dump_turbo_ratio_limits(int family, int model)
1550{ 1852{
1551 unsigned long long msr; 1853 unsigned long long msr, core_counts;
1552 unsigned int ratio; 1854 unsigned int ratio, group_size;
1553 1855
1554 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr); 1856 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
1555
1556 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr); 1857 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr);
1557 1858
1859 if (has_turbo_ratio_group_limits(family, model)) {
1860 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &core_counts);
1861 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, core_counts);
1862 } else {
1863 core_counts = 0x0807060504030201;
1864 }
1865
1558 ratio = (msr >> 56) & 0xFF; 1866 ratio = (msr >> 56) & 0xFF;
1867 group_size = (core_counts >> 56) & 0xFF;
1559 if (ratio) 1868 if (ratio)
1560 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 8 active cores\n", 1869 fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
1561 ratio, bclk, ratio * bclk); 1870 ratio, bclk, ratio * bclk, group_size);
1562 1871
1563 ratio = (msr >> 48) & 0xFF; 1872 ratio = (msr >> 48) & 0xFF;
1873 group_size = (core_counts >> 48) & 0xFF;
1564 if (ratio) 1874 if (ratio)
1565 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 7 active cores\n", 1875 fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
1566 ratio, bclk, ratio * bclk); 1876 ratio, bclk, ratio * bclk, group_size);
1567 1877
1568 ratio = (msr >> 40) & 0xFF; 1878 ratio = (msr >> 40) & 0xFF;
1879 group_size = (core_counts >> 40) & 0xFF;
1569 if (ratio) 1880 if (ratio)
1570 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 6 active cores\n", 1881 fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
1571 ratio, bclk, ratio * bclk); 1882 ratio, bclk, ratio * bclk, group_size);
1572 1883
1573 ratio = (msr >> 32) & 0xFF; 1884 ratio = (msr >> 32) & 0xFF;
1885 group_size = (core_counts >> 32) & 0xFF;
1574 if (ratio) 1886 if (ratio)
1575 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 5 active cores\n", 1887 fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
1576 ratio, bclk, ratio * bclk); 1888 ratio, bclk, ratio * bclk, group_size);
1577 1889
1578 ratio = (msr >> 24) & 0xFF; 1890 ratio = (msr >> 24) & 0xFF;
1891 group_size = (core_counts >> 24) & 0xFF;
1579 if (ratio) 1892 if (ratio)
1580 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 4 active cores\n", 1893 fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
1581 ratio, bclk, ratio * bclk); 1894 ratio, bclk, ratio * bclk, group_size);
1582 1895
1583 ratio = (msr >> 16) & 0xFF; 1896 ratio = (msr >> 16) & 0xFF;
1897 group_size = (core_counts >> 16) & 0xFF;
1584 if (ratio) 1898 if (ratio)
1585 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 3 active cores\n", 1899 fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
1586 ratio, bclk, ratio * bclk); 1900 ratio, bclk, ratio * bclk, group_size);
1587 1901
1588 ratio = (msr >> 8) & 0xFF; 1902 ratio = (msr >> 8) & 0xFF;
1903 group_size = (core_counts >> 8) & 0xFF;
1589 if (ratio) 1904 if (ratio)
1590 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 2 active cores\n", 1905 fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
1591 ratio, bclk, ratio * bclk); 1906 ratio, bclk, ratio * bclk, group_size);
1592 1907
1593 ratio = (msr >> 0) & 0xFF; 1908 ratio = (msr >> 0) & 0xFF;
1909 group_size = (core_counts >> 0) & 0xFF;
1594 if (ratio) 1910 if (ratio)
1595 fprintf(outf, "%d * %.0f = %.0f MHz max turbo 1 active cores\n", 1911 fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
1596 ratio, bclk, ratio * bclk); 1912 ratio, bclk, ratio * bclk, group_size);
1597 return; 1913 return;
1598} 1914}
1599 1915
1600static void 1916static void
1917dump_atom_turbo_ratio_limits(void)
1918{
1919 unsigned long long msr;
1920 unsigned int ratio;
1921
1922 get_msr(base_cpu, MSR_ATOM_CORE_RATIOS, &msr);
1923 fprintf(outf, "cpu%d: MSR_ATOM_CORE_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);
1924
1925 ratio = (msr >> 0) & 0x3F;
1926 if (ratio)
1927 fprintf(outf, "%d * %.1f = %.1f MHz minimum operating frequency\n",
1928 ratio, bclk, ratio * bclk);
1929
1930 ratio = (msr >> 8) & 0x3F;
1931 if (ratio)
1932 fprintf(outf, "%d * %.1f = %.1f MHz low frequency mode (LFM)\n",
1933 ratio, bclk, ratio * bclk);
1934
1935 ratio = (msr >> 16) & 0x3F;
1936 if (ratio)
1937 fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n",
1938 ratio, bclk, ratio * bclk);
1939
1940 get_msr(base_cpu, MSR_ATOM_CORE_TURBO_RATIOS, &msr);
1941 fprintf(outf, "cpu%d: MSR_ATOM_CORE_TURBO_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);
1942
1943 ratio = (msr >> 24) & 0x3F;
1944 if (ratio)
1945 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 4 active cores\n",
1946 ratio, bclk, ratio * bclk);
1947
1948 ratio = (msr >> 16) & 0x3F;
1949 if (ratio)
1950 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 3 active cores\n",
1951 ratio, bclk, ratio * bclk);
1952
1953 ratio = (msr >> 8) & 0x3F;
1954 if (ratio)
1955 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 2 active cores\n",
1956 ratio, bclk, ratio * bclk);
1957
1958 ratio = (msr >> 0) & 0x3F;
1959 if (ratio)
1960 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 1 active core\n",
1961 ratio, bclk, ratio * bclk);
1962}
1963
1964static void
1601dump_knl_turbo_ratio_limits(void) 1965dump_knl_turbo_ratio_limits(void)
1602{ 1966{
1603 const unsigned int buckets_no = 7; 1967 const unsigned int buckets_no = 7;
@@ -1652,7 +2016,7 @@ dump_knl_turbo_ratio_limits(void)
1652 for (i = buckets_no - 1; i >= 0; i--) 2016 for (i = buckets_no - 1; i >= 0; i--)
1653 if (i > 0 ? ratio[i] != ratio[i - 1] : 1) 2017 if (i > 0 ? ratio[i] != ratio[i - 1] : 1)
1654 fprintf(outf, 2018 fprintf(outf,
1655 "%d * %.0f = %.0f MHz max turbo %d active cores\n", 2019 "%d * %.1f = %.1f MHz max turbo %d active cores\n",
1656 ratio[i], bclk, ratio[i] * bclk, cores[i]); 2020 ratio[i], bclk, ratio[i] * bclk, cores[i]);
1657} 2021}
1658 2022
@@ -1661,12 +2025,12 @@ dump_nhm_cst_cfg(void)
1661{ 2025{
1662 unsigned long long msr; 2026 unsigned long long msr;
1663 2027
1664 get_msr(base_cpu, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr); 2028 get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);
1665 2029
1666#define SNB_C1_AUTO_UNDEMOTE (1UL << 27) 2030#define SNB_C1_AUTO_UNDEMOTE (1UL << 27)
1667#define SNB_C3_AUTO_UNDEMOTE (1UL << 28) 2031#define SNB_C3_AUTO_UNDEMOTE (1UL << 28)
1668 2032
1669 fprintf(outf, "cpu%d: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x%08llx", base_cpu, msr); 2033 fprintf(outf, "cpu%d: MSR_PKG_CST_CONFIG_CONTROL: 0x%08llx", base_cpu, msr);
1670 2034
1671 fprintf(outf, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: %s)\n", 2035 fprintf(outf, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: %s)\n",
1672 (msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "", 2036 (msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "",
@@ -1810,16 +2174,6 @@ void free_all_buffers(void)
1810 free(irqs_per_cpu); 2174 free(irqs_per_cpu);
1811} 2175}
1812 2176
1813/*
1814 * Open a file, and exit on failure
1815 */
1816FILE *fopen_or_die(const char *path, const char *mode)
1817{
1818 FILE *filep = fopen(path, mode);
1819 if (!filep)
1820 err(1, "%s: open failed", path);
1821 return filep;
1822}
1823 2177
1824/* 2178/*
1825 * Parse a file containing a single int. 2179 * Parse a file containing a single int.
@@ -2148,13 +2502,14 @@ int snapshot_gfx_mhz(void)
2148 */ 2502 */
2149int snapshot_proc_sysfs_files(void) 2503int snapshot_proc_sysfs_files(void)
2150{ 2504{
2151 if (snapshot_proc_interrupts()) 2505 if (DO_BIC(BIC_IRQ))
2152 return 1; 2506 if (snapshot_proc_interrupts())
2507 return 1;
2153 2508
2154 if (do_gfx_rc6_ms) 2509 if (DO_BIC(BIC_GFX_rc6))
2155 snapshot_gfx_rc6_ms(); 2510 snapshot_gfx_rc6_ms();
2156 2511
2157 if (do_gfx_mhz) 2512 if (DO_BIC(BIC_GFXMHz))
2158 snapshot_gfx_mhz(); 2513 snapshot_gfx_mhz();
2159 2514
2160 return 0; 2515 return 0;
@@ -2283,7 +2638,9 @@ void check_permissions()
2283 * MSR_SMI_COUNT 0x00000034 2638 * MSR_SMI_COUNT 0x00000034
2284 * 2639 *
2285 * MSR_PLATFORM_INFO 0x000000ce 2640 * MSR_PLATFORM_INFO 0x000000ce
2286 * MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2 2641 * MSR_PKG_CST_CONFIG_CONTROL 0x000000e2
2642 *
2643 * MSR_MISC_PWR_MGMT 0x000001aa
2287 * 2644 *
2288 * MSR_PKG_C3_RESIDENCY 0x000003f8 2645 * MSR_PKG_C3_RESIDENCY 0x000003f8
2289 * MSR_PKG_C6_RESIDENCY 0x000003f9 2646 * MSR_PKG_C6_RESIDENCY 0x000003f9
@@ -2291,7 +2648,8 @@ void check_permissions()
2291 * MSR_CORE_C6_RESIDENCY 0x000003fd 2648 * MSR_CORE_C6_RESIDENCY 0x000003fd
2292 * 2649 *
2293 * Side effect: 2650 * Side effect:
2294 * sets global pkg_cstate_limit to decode MSR_NHM_SNB_PKG_CST_CFG_CTL 2651 * sets global pkg_cstate_limit to decode MSR_PKG_CST_CONFIG_CONTROL
2652 * sets has_misc_feature_control
2295 */ 2653 */
2296int probe_nhm_msrs(unsigned int family, unsigned int model) 2654int probe_nhm_msrs(unsigned int family, unsigned int model)
2297{ 2655{
@@ -2322,6 +2680,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
2322 case INTEL_FAM6_IVYBRIDGE: /* IVB */ 2680 case INTEL_FAM6_IVYBRIDGE: /* IVB */
2323 case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ 2681 case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */
2324 pkg_cstate_limits = snb_pkg_cstate_limits; 2682 pkg_cstate_limits = snb_pkg_cstate_limits;
2683 has_misc_feature_control = 1;
2325 break; 2684 break;
2326 case INTEL_FAM6_HASWELL_CORE: /* HSW */ 2685 case INTEL_FAM6_HASWELL_CORE: /* HSW */
2327 case INTEL_FAM6_HASWELL_X: /* HSX */ 2686 case INTEL_FAM6_HASWELL_X: /* HSX */
@@ -2336,29 +2695,34 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
2336 case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 2695 case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */
2337 case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 2696 case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */
2338 pkg_cstate_limits = hsw_pkg_cstate_limits; 2697 pkg_cstate_limits = hsw_pkg_cstate_limits;
2698 has_misc_feature_control = 1;
2339 break; 2699 break;
2340 case INTEL_FAM6_SKYLAKE_X: /* SKX */ 2700 case INTEL_FAM6_SKYLAKE_X: /* SKX */
2341 pkg_cstate_limits = skx_pkg_cstate_limits; 2701 pkg_cstate_limits = skx_pkg_cstate_limits;
2702 has_misc_feature_control = 1;
2342 break; 2703 break;
2343 case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ 2704 case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */
2705 no_MSR_MISC_PWR_MGMT = 1;
2344 case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ 2706 case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */
2345 pkg_cstate_limits = slv_pkg_cstate_limits; 2707 pkg_cstate_limits = slv_pkg_cstate_limits;
2346 break; 2708 break;
2347 case INTEL_FAM6_ATOM_AIRMONT: /* AMT */ 2709 case INTEL_FAM6_ATOM_AIRMONT: /* AMT */
2348 pkg_cstate_limits = amt_pkg_cstate_limits; 2710 pkg_cstate_limits = amt_pkg_cstate_limits;
2711 no_MSR_MISC_PWR_MGMT = 1;
2349 break; 2712 break;
2350 case INTEL_FAM6_XEON_PHI_KNL: /* PHI */ 2713 case INTEL_FAM6_XEON_PHI_KNL: /* PHI */
2351 case INTEL_FAM6_XEON_PHI_KNM: 2714 case INTEL_FAM6_XEON_PHI_KNM:
2352 pkg_cstate_limits = phi_pkg_cstate_limits; 2715 pkg_cstate_limits = phi_pkg_cstate_limits;
2353 break; 2716 break;
2354 case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 2717 case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
2718 case INTEL_FAM6_ATOM_GEMINI_LAKE:
2355 case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ 2719 case INTEL_FAM6_ATOM_DENVERTON: /* DNV */
2356 pkg_cstate_limits = bxt_pkg_cstate_limits; 2720 pkg_cstate_limits = bxt_pkg_cstate_limits;
2357 break; 2721 break;
2358 default: 2722 default:
2359 return 0; 2723 return 0;
2360 } 2724 }
2361 get_msr(base_cpu, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr); 2725 get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);
2362 pkg_cstate_limit = pkg_cstate_limits[msr & 0xF]; 2726 pkg_cstate_limit = pkg_cstate_limits[msr & 0xF];
2363 2727
2364 get_msr(base_cpu, MSR_PLATFORM_INFO, &msr); 2728 get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);
@@ -2368,8 +2732,69 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
2368 has_base_hz = 1; 2732 has_base_hz = 1;
2369 return 1; 2733 return 1;
2370} 2734}
2371int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model) 2735/*
2736 * SLV client has support for unique MSRs:
2737 *
2738 * MSR_CC6_DEMOTION_POLICY_CONFIG
2739 * MSR_MC6_DEMOTION_POLICY_CONFIG
2740 */
2741
2742int has_slv_msrs(unsigned int family, unsigned int model)
2372{ 2743{
2744 if (!genuine_intel)
2745 return 0;
2746
2747 switch (model) {
2748 case INTEL_FAM6_ATOM_SILVERMONT1:
2749 case INTEL_FAM6_ATOM_MERRIFIELD:
2750 case INTEL_FAM6_ATOM_MOOREFIELD:
2751 return 1;
2752 }
2753 return 0;
2754}
2755int is_dnv(unsigned int family, unsigned int model)
2756{
2757
2758 if (!genuine_intel)
2759 return 0;
2760
2761 switch (model) {
2762 case INTEL_FAM6_ATOM_DENVERTON:
2763 return 1;
2764 }
2765 return 0;
2766}
2767int is_bdx(unsigned int family, unsigned int model)
2768{
2769
2770 if (!genuine_intel)
2771 return 0;
2772
2773 switch (model) {
2774 case INTEL_FAM6_BROADWELL_X:
2775 case INTEL_FAM6_BROADWELL_XEON_D:
2776 return 1;
2777 }
2778 return 0;
2779}
2780int is_skx(unsigned int family, unsigned int model)
2781{
2782
2783 if (!genuine_intel)
2784 return 0;
2785
2786 switch (model) {
2787 case INTEL_FAM6_SKYLAKE_X:
2788 return 1;
2789 }
2790 return 0;
2791}
2792
2793int has_turbo_ratio_limit(unsigned int family, unsigned int model)
2794{
2795 if (has_slv_msrs(family, model))
2796 return 0;
2797
2373 switch (model) { 2798 switch (model) {
2374 /* Nehalem compatible, but do not include turbo-ratio limit support */ 2799 /* Nehalem compatible, but do not include turbo-ratio limit support */
2375 case INTEL_FAM6_NEHALEM_EX: /* Nehalem-EX Xeon - Beckton */ 2800 case INTEL_FAM6_NEHALEM_EX: /* Nehalem-EX Xeon - Beckton */
@@ -2381,6 +2806,13 @@ int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model)
2381 return 1; 2806 return 1;
2382 } 2807 }
2383} 2808}
2809int has_atom_turbo_ratio_limit(unsigned int family, unsigned int model)
2810{
2811 if (has_slv_msrs(family, model))
2812 return 1;
2813
2814 return 0;
2815}
2384int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model) 2816int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
2385{ 2817{
2386 if (!genuine_intel) 2818 if (!genuine_intel)
@@ -2429,6 +2861,22 @@ int has_knl_turbo_ratio_limit(unsigned int family, unsigned int model)
2429 return 0; 2861 return 0;
2430 } 2862 }
2431} 2863}
2864int has_glm_turbo_ratio_limit(unsigned int family, unsigned int model)
2865{
2866 if (!genuine_intel)
2867 return 0;
2868
2869 if (family != 6)
2870 return 0;
2871
2872 switch (model) {
2873 case INTEL_FAM6_ATOM_GOLDMONT:
2874 case INTEL_FAM6_SKYLAKE_X:
2875 return 1;
2876 default:
2877 return 0;
2878 }
2879}
2432int has_config_tdp(unsigned int family, unsigned int model) 2880int has_config_tdp(unsigned int family, unsigned int model)
2433{ 2881{
2434 if (!genuine_intel) 2882 if (!genuine_intel)
@@ -2475,8 +2923,11 @@ dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
2475 if (has_ivt_turbo_ratio_limit(family, model)) 2923 if (has_ivt_turbo_ratio_limit(family, model))
2476 dump_ivt_turbo_ratio_limits(); 2924 dump_ivt_turbo_ratio_limits();
2477 2925
2478 if (has_nhm_turbo_ratio_limit(family, model)) 2926 if (has_turbo_ratio_limit(family, model))
2479 dump_nhm_turbo_ratio_limits(); 2927 dump_turbo_ratio_limits(family, model);
2928
2929 if (has_atom_turbo_ratio_limit(family, model))
2930 dump_atom_turbo_ratio_limits();
2480 2931
2481 if (has_knl_turbo_ratio_limit(family, model)) 2932 if (has_knl_turbo_ratio_limit(family, model))
2482 dump_knl_turbo_ratio_limits(); 2933 dump_knl_turbo_ratio_limits();
@@ -2487,6 +2938,96 @@ dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
2487 dump_nhm_cst_cfg(); 2938 dump_nhm_cst_cfg();
2488} 2939}
2489 2940
2941static void
2942dump_sysfs_cstate_config(void)
2943{
2944 char path[64];
2945 char name_buf[16];
2946 char desc[64];
2947 FILE *input;
2948 int state;
2949 char *sp;
2950
2951 if (!DO_BIC(BIC_sysfs))
2952 return;
2953
2954 for (state = 0; state < 10; ++state) {
2955
2956 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
2957 base_cpu, state);
2958 input = fopen(path, "r");
2959 if (input == NULL)
2960 continue;
2961 fgets(name_buf, sizeof(name_buf), input);
2962
2963 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
2964 sp = strchr(name_buf, '-');
2965 if (!sp)
2966 sp = strchrnul(name_buf, '\n');
2967 *sp = '\0';
2968
2969 fclose(input);
2970
2971 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/desc",
2972 base_cpu, state);
2973 input = fopen(path, "r");
2974 if (input == NULL)
2975 continue;
2976 fgets(desc, sizeof(desc), input);
2977
2978 fprintf(outf, "cpu%d: %s: %s", base_cpu, name_buf, desc);
2979 fclose(input);
2980 }
2981}
2982static void
2983dump_sysfs_pstate_config(void)
2984{
2985 char path[64];
2986 char driver_buf[64];
2987 char governor_buf[64];
2988 FILE *input;
2989 int turbo;
2990
2991 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_driver",
2992 base_cpu);
2993 input = fopen(path, "r");
2994 if (input == NULL) {
2995 fprintf(stderr, "NSFOD %s\n", path);
2996 return;
2997 }
2998 fgets(driver_buf, sizeof(driver_buf), input);
2999 fclose(input);
3000
3001 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor",
3002 base_cpu);
3003 input = fopen(path, "r");
3004 if (input == NULL) {
3005 fprintf(stderr, "NSFOD %s\n", path);
3006 return;
3007 }
3008 fgets(governor_buf, sizeof(governor_buf), input);
3009 fclose(input);
3010
3011 fprintf(outf, "cpu%d: cpufreq driver: %s", base_cpu, driver_buf);
3012 fprintf(outf, "cpu%d: cpufreq governor: %s", base_cpu, governor_buf);
3013
3014 sprintf(path, "/sys/devices/system/cpu/cpufreq/boost");
3015 input = fopen(path, "r");
3016 if (input != NULL) {
3017 fscanf(input, "%d", &turbo);
3018 fprintf(outf, "cpufreq boost: %d\n", turbo);
3019 fclose(input);
3020 }
3021
3022 sprintf(path, "/sys/devices/system/cpu/intel_pstate/no_turbo");
3023 input = fopen(path, "r");
3024 if (input != NULL) {
3025 fscanf(input, "%d", &turbo);
3026 fprintf(outf, "cpufreq intel_pstate no_turbo: %d\n", turbo);
3027 fclose(input);
3028 }
3029}
3030
2490 3031
2491/* 3032/*
2492 * print_epb() 3033 * print_epb()
@@ -2790,15 +3331,40 @@ void rapl_probe(unsigned int family, unsigned int model)
2790 case INTEL_FAM6_BROADWELL_CORE: /* BDW */ 3331 case INTEL_FAM6_BROADWELL_CORE: /* BDW */
2791 case INTEL_FAM6_BROADWELL_GT3E: /* BDW */ 3332 case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
2792 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO; 3333 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO;
3334 if (rapl_joules) {
3335 BIC_PRESENT(BIC_Pkg_J);
3336 BIC_PRESENT(BIC_Cor_J);
3337 BIC_PRESENT(BIC_GFX_J);
3338 } else {
3339 BIC_PRESENT(BIC_PkgWatt);
3340 BIC_PRESENT(BIC_CorWatt);
3341 BIC_PRESENT(BIC_GFXWatt);
3342 }
2793 break; 3343 break;
2794 case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 3344 case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
3345 case INTEL_FAM6_ATOM_GEMINI_LAKE:
2795 do_rapl = RAPL_PKG | RAPL_PKG_POWER_INFO; 3346 do_rapl = RAPL_PKG | RAPL_PKG_POWER_INFO;
3347 if (rapl_joules)
3348 BIC_PRESENT(BIC_Pkg_J);
3349 else
3350 BIC_PRESENT(BIC_PkgWatt);
2796 break; 3351 break;
2797 case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */ 3352 case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
2798 case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */ 3353 case INTEL_FAM6_SKYLAKE_DESKTOP: /* SKL */
2799 case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 3354 case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */
2800 case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 3355 case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */
2801 do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO; 3356 do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
3357 BIC_PRESENT(BIC_PKG__);
3358 BIC_PRESENT(BIC_RAM__);
3359 if (rapl_joules) {
3360 BIC_PRESENT(BIC_Pkg_J);
3361 BIC_PRESENT(BIC_Cor_J);
3362 BIC_PRESENT(BIC_RAM_J);
3363 } else {
3364 BIC_PRESENT(BIC_PkgWatt);
3365 BIC_PRESENT(BIC_CorWatt);
3366 BIC_PRESENT(BIC_RAMWatt);
3367 }
2802 break; 3368 break;
2803 case INTEL_FAM6_HASWELL_X: /* HSX */ 3369 case INTEL_FAM6_HASWELL_X: /* HSX */
2804 case INTEL_FAM6_BROADWELL_X: /* BDX */ 3370 case INTEL_FAM6_BROADWELL_X: /* BDX */
@@ -2807,17 +3373,55 @@ void rapl_probe(unsigned int family, unsigned int model)
2807 case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ 3373 case INTEL_FAM6_XEON_PHI_KNL: /* KNL */
2808 case INTEL_FAM6_XEON_PHI_KNM: 3374 case INTEL_FAM6_XEON_PHI_KNM:
2809 do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO; 3375 do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
3376 BIC_PRESENT(BIC_PKG__);
3377 BIC_PRESENT(BIC_RAM__);
3378 if (rapl_joules) {
3379 BIC_PRESENT(BIC_Pkg_J);
3380 BIC_PRESENT(BIC_RAM_J);
3381 } else {
3382 BIC_PRESENT(BIC_PkgWatt);
3383 BIC_PRESENT(BIC_RAMWatt);
3384 }
2810 break; 3385 break;
2811 case INTEL_FAM6_SANDYBRIDGE_X: 3386 case INTEL_FAM6_SANDYBRIDGE_X:
2812 case INTEL_FAM6_IVYBRIDGE_X: 3387 case INTEL_FAM6_IVYBRIDGE_X:
2813 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO; 3388 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO;
3389 BIC_PRESENT(BIC_PKG__);
3390 BIC_PRESENT(BIC_RAM__);
3391 if (rapl_joules) {
3392 BIC_PRESENT(BIC_Pkg_J);
3393 BIC_PRESENT(BIC_Cor_J);
3394 BIC_PRESENT(BIC_RAM_J);
3395 } else {
3396 BIC_PRESENT(BIC_PkgWatt);
3397 BIC_PRESENT(BIC_CorWatt);
3398 BIC_PRESENT(BIC_RAMWatt);
3399 }
2814 break; 3400 break;
2815 case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */ 3401 case INTEL_FAM6_ATOM_SILVERMONT1: /* BYT */
2816 case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */ 3402 case INTEL_FAM6_ATOM_SILVERMONT2: /* AVN */
2817 do_rapl = RAPL_PKG | RAPL_CORES; 3403 do_rapl = RAPL_PKG | RAPL_CORES;
3404 if (rapl_joules) {
3405 BIC_PRESENT(BIC_Pkg_J);
3406 BIC_PRESENT(BIC_Cor_J);
3407 } else {
3408 BIC_PRESENT(BIC_PkgWatt);
3409 BIC_PRESENT(BIC_CorWatt);
3410 }
2818 break; 3411 break;
2819 case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ 3412 case INTEL_FAM6_ATOM_DENVERTON: /* DNV */
2820 do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO | RAPL_CORES_ENERGY_STATUS; 3413 do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO | RAPL_CORES_ENERGY_STATUS;
3414 BIC_PRESENT(BIC_PKG__);
3415 BIC_PRESENT(BIC_RAM__);
3416 if (rapl_joules) {
3417 BIC_PRESENT(BIC_Pkg_J);
3418 BIC_PRESENT(BIC_Cor_J);
3419 BIC_PRESENT(BIC_RAM_J);
3420 } else {
3421 BIC_PRESENT(BIC_PkgWatt);
3422 BIC_PRESENT(BIC_CorWatt);
3423 BIC_PRESENT(BIC_RAMWatt);
3424 }
2821 break; 3425 break;
2822 default: 3426 default:
2823 return; 3427 return;
@@ -2844,7 +3448,7 @@ void rapl_probe(unsigned int family, unsigned int model)
2844 tdp = get_tdp(model); 3448 tdp = get_tdp(model);
2845 3449
2846 rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp; 3450 rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
2847 if (debug) 3451 if (!quiet)
2848 fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp); 3452 fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
2849 3453
2850 return; 3454 return;
@@ -2969,11 +3573,9 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
2969 if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr)) 3573 if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr))
2970 return -1; 3574 return -1;
2971 3575
2972 if (debug) { 3576 fprintf(outf, "cpu%d: MSR_RAPL_POWER_UNIT: 0x%08llx (%f Watts, %f Joules, %f sec.)\n", cpu, msr,
2973 fprintf(outf, "cpu%d: MSR_RAPL_POWER_UNIT: 0x%08llx " 3577 rapl_power_units, rapl_energy_units, rapl_time_units);
2974 "(%f Watts, %f Joules, %f sec.)\n", cpu, msr, 3578
2975 rapl_power_units, rapl_energy_units, rapl_time_units);
2976 }
2977 if (do_rapl & RAPL_PKG_POWER_INFO) { 3579 if (do_rapl & RAPL_PKG_POWER_INFO) {
2978 3580
2979 if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr)) 3581 if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr))
@@ -2994,7 +3596,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
2994 return -9; 3596 return -9;
2995 3597
2996 fprintf(outf, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n", 3598 fprintf(outf, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n",
2997 cpu, msr, (msr >> 63) & 1 ? "": "UN"); 3599 cpu, msr, (msr >> 63) & 1 ? "" : "UN");
2998 3600
2999 print_power_limit_msr(cpu, msr, "PKG Limit #1"); 3601 print_power_limit_msr(cpu, msr, "PKG Limit #1");
3000 fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%f Watts, %f* sec, clamp %sabled)\n", 3602 fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%f Watts, %f* sec, clamp %sabled)\n",
@@ -3020,40 +3622,34 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
3020 if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr)) 3622 if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr))
3021 return -9; 3623 return -9;
3022 fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n", 3624 fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n",
3023 cpu, msr, (msr >> 31) & 1 ? "": "UN"); 3625 cpu, msr, (msr >> 31) & 1 ? "" : "UN");
3024 3626
3025 print_power_limit_msr(cpu, msr, "DRAM Limit"); 3627 print_power_limit_msr(cpu, msr, "DRAM Limit");
3026 } 3628 }
3027 if (do_rapl & RAPL_CORE_POLICY) { 3629 if (do_rapl & RAPL_CORE_POLICY) {
3028 if (debug) { 3630 if (get_msr(cpu, MSR_PP0_POLICY, &msr))
3029 if (get_msr(cpu, MSR_PP0_POLICY, &msr)) 3631 return -7;
3030 return -7;
3031 3632
3032 fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF); 3633 fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF);
3033 }
3034 } 3634 }
3035 if (do_rapl & RAPL_CORES_POWER_LIMIT) { 3635 if (do_rapl & RAPL_CORES_POWER_LIMIT) {
3036 if (debug) { 3636 if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr))
3037 if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr)) 3637 return -9;
3038 return -9; 3638 fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n",
3039 fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n", 3639 cpu, msr, (msr >> 31) & 1 ? "" : "UN");
3040 cpu, msr, (msr >> 31) & 1 ? "": "UN"); 3640 print_power_limit_msr(cpu, msr, "Cores Limit");
3041 print_power_limit_msr(cpu, msr, "Cores Limit");
3042 }
3043 } 3641 }
3044 if (do_rapl & RAPL_GFX) { 3642 if (do_rapl & RAPL_GFX) {
3045 if (debug) { 3643 if (get_msr(cpu, MSR_PP1_POLICY, &msr))
3046 if (get_msr(cpu, MSR_PP1_POLICY, &msr)) 3644 return -8;
3047 return -8;
3048 3645
3049 fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF); 3646 fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF);
3050 3647
3051 if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr)) 3648 if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr))
3052 return -9; 3649 return -9;
3053 fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n", 3650 fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n",
3054 cpu, msr, (msr >> 31) & 1 ? "": "UN"); 3651 cpu, msr, (msr >> 31) & 1 ? "" : "UN");
3055 print_power_limit_msr(cpu, msr, "GFX Limit"); 3652 print_power_limit_msr(cpu, msr, "GFX Limit");
3056 }
3057 } 3653 }
3058 return 0; 3654 return 0;
3059} 3655}
@@ -3090,6 +3686,7 @@ int has_snb_msrs(unsigned int family, unsigned int model)
3090 case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 3686 case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */
3091 case INTEL_FAM6_SKYLAKE_X: /* SKX */ 3687 case INTEL_FAM6_SKYLAKE_X: /* SKX */
3092 case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 3688 case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
3689 case INTEL_FAM6_ATOM_GEMINI_LAKE:
3093 case INTEL_FAM6_ATOM_DENVERTON: /* DNV */ 3690 case INTEL_FAM6_ATOM_DENVERTON: /* DNV */
3094 return 1; 3691 return 1;
3095 } 3692 }
@@ -3121,6 +3718,7 @@ int has_hsw_msrs(unsigned int family, unsigned int model)
3121 case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */ 3718 case INTEL_FAM6_KABYLAKE_MOBILE: /* KBL */
3122 case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */ 3719 case INTEL_FAM6_KABYLAKE_DESKTOP: /* KBL */
3123 case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 3720 case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
3721 case INTEL_FAM6_ATOM_GEMINI_LAKE:
3124 return 1; 3722 return 1;
3125 } 3723 }
3126 return 0; 3724 return 0;
@@ -3149,8 +3747,6 @@ int has_skl_msrs(unsigned int family, unsigned int model)
3149 return 0; 3747 return 0;
3150} 3748}
3151 3749
3152
3153
3154int is_slm(unsigned int family, unsigned int model) 3750int is_slm(unsigned int family, unsigned int model)
3155{ 3751{
3156 if (!genuine_intel) 3752 if (!genuine_intel)
@@ -3201,7 +3797,8 @@ double slm_bclk(void)
3201 } 3797 }
3202 freq = slm_freq_table[i]; 3798 freq = slm_freq_table[i];
3203 3799
3204 fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq); 3800 if (!quiet)
3801 fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq);
3205 3802
3206 return freq; 3803 return freq;
3207} 3804}
@@ -3264,7 +3861,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
3264 3861
3265 target_c_local = (msr >> 16) & 0xFF; 3862 target_c_local = (msr >> 16) & 0xFF;
3266 3863
3267 if (debug) 3864 if (!quiet)
3268 fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", 3865 fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n",
3269 cpu, msr, target_c_local); 3866 cpu, msr, target_c_local);
3270 3867
@@ -3299,13 +3896,30 @@ void decode_misc_enable_msr(void)
3299 unsigned long long msr; 3896 unsigned long long msr;
3300 3897
3301 if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr)) 3898 if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr))
3302 fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%s %s %s)\n", 3899 fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%sTCC %sEIST %sMWAIT %sPREFETCH %sTURBO)\n",
3303 base_cpu, msr, 3900 base_cpu, msr,
3304 msr & (1 << 3) ? "TCC" : "", 3901 msr & MSR_IA32_MISC_ENABLE_TM1 ? "" : "No-",
3305 msr & (1 << 16) ? "EIST" : "", 3902 msr & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP ? "" : "No-",
3306 msr & (1 << 18) ? "MONITOR" : ""); 3903 msr & MSR_IA32_MISC_ENABLE_MWAIT ? "No-" : "",
3904 msr & MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE ? "No-" : "",
3905 msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ? "No-" : "");
3307} 3906}
3308 3907
3908void decode_misc_feature_control(void)
3909{
3910 unsigned long long msr;
3911
3912 if (!has_misc_feature_control)
3913 return;
3914
3915 if (!get_msr(base_cpu, MSR_MISC_FEATURE_CONTROL, &msr))
3916 fprintf(outf, "cpu%d: MSR_MISC_FEATURE_CONTROL: 0x%08llx (%sL2-Prefetch %sL2-Prefetch-pair %sL1-Prefetch %sL1-IP-Prefetch)\n",
3917 base_cpu, msr,
3918 msr & (0 << 0) ? "No-" : "",
3919 msr & (1 << 0) ? "No-" : "",
3920 msr & (2 << 0) ? "No-" : "",
3921 msr & (3 << 0) ? "No-" : "");
3922}
3309/* 3923/*
3310 * Decode MSR_MISC_PWR_MGMT 3924 * Decode MSR_MISC_PWR_MGMT
3311 * 3925 *
@@ -3320,6 +3934,9 @@ void decode_misc_pwr_mgmt_msr(void)
3320 if (!do_nhm_platform_info) 3934 if (!do_nhm_platform_info)
3321 return; 3935 return;
3322 3936
3937 if (no_MSR_MISC_PWR_MGMT)
3938 return;
3939
3323 if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr)) 3940 if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr))
3324 fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n", 3941 fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n",
3325 base_cpu, msr, 3942 base_cpu, msr,
@@ -3327,11 +3944,30 @@ void decode_misc_pwr_mgmt_msr(void)
3327 msr & (1 << 1) ? "EN" : "DIS", 3944 msr & (1 << 1) ? "EN" : "DIS",
3328 msr & (1 << 8) ? "EN" : "DIS"); 3945 msr & (1 << 8) ? "EN" : "DIS");
3329} 3946}
3947/*
3948 * Decode MSR_CC6_DEMOTION_POLICY_CONFIG, MSR_MC6_DEMOTION_POLICY_CONFIG
3949 *
3950 * This MSRs are present on Silvermont processors,
3951 * Intel Atom processor E3000 series (Baytrail), and friends.
3952 */
3953void decode_c6_demotion_policy_msr(void)
3954{
3955 unsigned long long msr;
3956
3957 if (!get_msr(base_cpu, MSR_CC6_DEMOTION_POLICY_CONFIG, &msr))
3958 fprintf(outf, "cpu%d: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-CC6-Demotion)\n",
3959 base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");
3960
3961 if (!get_msr(base_cpu, MSR_MC6_DEMOTION_POLICY_CONFIG, &msr))
3962 fprintf(outf, "cpu%d: MSR_MC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-MC6-Demotion)\n",
3963 base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");
3964}
3330 3965
3331void process_cpuid() 3966void process_cpuid()
3332{ 3967{
3333 unsigned int eax, ebx, ecx, edx, max_level, max_extended_level; 3968 unsigned int eax, ebx, ecx, edx, max_level, max_extended_level;
3334 unsigned int fms, family, model, stepping; 3969 unsigned int fms, family, model, stepping;
3970 unsigned int has_turbo;
3335 3971
3336 eax = ebx = ecx = edx = 0; 3972 eax = ebx = ecx = edx = 0;
3337 3973
@@ -3340,7 +3976,7 @@ void process_cpuid()
3340 if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e) 3976 if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
3341 genuine_intel = 1; 3977 genuine_intel = 1;
3342 3978
3343 if (debug) 3979 if (!quiet)
3344 fprintf(outf, "CPUID(0): %.4s%.4s%.4s ", 3980 fprintf(outf, "CPUID(0): %.4s%.4s%.4s ",
3345 (char *)&ebx, (char *)&edx, (char *)&ecx); 3981 (char *)&ebx, (char *)&edx, (char *)&ecx);
3346 3982
@@ -3351,7 +3987,7 @@ void process_cpuid()
3351 if (family == 6 || family == 0xf) 3987 if (family == 6 || family == 0xf)
3352 model += ((fms >> 16) & 0xf) << 4; 3988 model += ((fms >> 16) & 0xf) << 4;
3353 3989
3354 if (debug) { 3990 if (!quiet) {
3355 fprintf(outf, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", 3991 fprintf(outf, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
3356 max_level, family, model, stepping, family, model, stepping); 3992 max_level, family, model, stepping, family, model, stepping);
3357 fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s\n", 3993 fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s\n",
@@ -3394,8 +4030,18 @@ void process_cpuid()
3394 4030
3395 __cpuid(0x6, eax, ebx, ecx, edx); 4031 __cpuid(0x6, eax, ebx, ecx, edx);
3396 has_aperf = ecx & (1 << 0); 4032 has_aperf = ecx & (1 << 0);
4033 if (has_aperf) {
4034 BIC_PRESENT(BIC_Avg_MHz);
4035 BIC_PRESENT(BIC_Busy);
4036 BIC_PRESENT(BIC_Bzy_MHz);
4037 }
3397 do_dts = eax & (1 << 0); 4038 do_dts = eax & (1 << 0);
4039 if (do_dts)
4040 BIC_PRESENT(BIC_CoreTmp);
4041 has_turbo = eax & (1 << 1);
3398 do_ptm = eax & (1 << 6); 4042 do_ptm = eax & (1 << 6);
4043 if (do_ptm)
4044 BIC_PRESENT(BIC_PkgTmp);
3399 has_hwp = eax & (1 << 7); 4045 has_hwp = eax & (1 << 7);
3400 has_hwp_notify = eax & (1 << 8); 4046 has_hwp_notify = eax & (1 << 8);
3401 has_hwp_activity_window = eax & (1 << 9); 4047 has_hwp_activity_window = eax & (1 << 9);
@@ -3403,10 +4049,11 @@ void process_cpuid()
3403 has_hwp_pkg = eax & (1 << 11); 4049 has_hwp_pkg = eax & (1 << 11);
3404 has_epb = ecx & (1 << 3); 4050 has_epb = ecx & (1 << 3);
3405 4051
3406 if (debug) 4052 if (!quiet)
3407 fprintf(outf, "CPUID(6): %sAPERF, %sDTS, %sPTM, %sHWP, " 4053 fprintf(outf, "CPUID(6): %sAPERF, %sTURBO, %sDTS, %sPTM, %sHWP, "
3408 "%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n", 4054 "%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",
3409 has_aperf ? "" : "No-", 4055 has_aperf ? "" : "No-",
4056 has_turbo ? "" : "No-",
3410 do_dts ? "" : "No-", 4057 do_dts ? "" : "No-",
3411 do_ptm ? "" : "No-", 4058 do_ptm ? "" : "No-",
3412 has_hwp ? "" : "No-", 4059 has_hwp ? "" : "No-",
@@ -3416,10 +4063,11 @@ void process_cpuid()
3416 has_hwp_pkg ? "" : "No-", 4063 has_hwp_pkg ? "" : "No-",
3417 has_epb ? "" : "No-"); 4064 has_epb ? "" : "No-");
3418 4065
3419 if (debug) 4066 if (!quiet)
3420 decode_misc_enable_msr(); 4067 decode_misc_enable_msr();
3421 4068
3422 if (max_level >= 0x7 && debug) { 4069
4070 if (max_level >= 0x7 && !quiet) {
3423 int has_sgx; 4071 int has_sgx;
3424 4072
3425 ecx = 0; 4073 ecx = 0;
@@ -3445,7 +4093,7 @@ void process_cpuid()
3445 4093
3446 if (ebx_tsc != 0) { 4094 if (ebx_tsc != 0) {
3447 4095
3448 if (debug && (ebx != 0)) 4096 if (!quiet && (ebx != 0))
3449 fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n", 4097 fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n",
3450 eax_crystal, ebx_tsc, crystal_hz); 4098 eax_crystal, ebx_tsc, crystal_hz);
3451 4099
@@ -3462,6 +4110,7 @@ void process_cpuid()
3462 crystal_hz = 25000000; /* 25.0 MHz */ 4110 crystal_hz = 25000000; /* 25.0 MHz */
3463 break; 4111 break;
3464 case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ 4112 case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
4113 case INTEL_FAM6_ATOM_GEMINI_LAKE:
3465 crystal_hz = 19200000; /* 19.2 MHz */ 4114 crystal_hz = 19200000; /* 19.2 MHz */
3466 break; 4115 break;
3467 default: 4116 default:
@@ -3470,7 +4119,7 @@ void process_cpuid()
3470 4119
3471 if (crystal_hz) { 4120 if (crystal_hz) {
3472 tsc_hz = (unsigned long long) crystal_hz * ebx_tsc / eax_crystal; 4121 tsc_hz = (unsigned long long) crystal_hz * ebx_tsc / eax_crystal;
3473 if (debug) 4122 if (!quiet)
3474 fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n", 4123 fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n",
3475 tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal); 4124 tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal);
3476 } 4125 }
@@ -3485,7 +4134,7 @@ void process_cpuid()
3485 base_mhz = max_mhz = bus_mhz = edx = 0; 4134 base_mhz = max_mhz = bus_mhz = edx = 0;
3486 4135
3487 __cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx); 4136 __cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx);
3488 if (debug) 4137 if (!quiet)
3489 fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n", 4138 fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n",
3490 base_mhz, max_mhz, bus_mhz); 4139 base_mhz, max_mhz, bus_mhz);
3491 } 4140 }
@@ -3493,56 +4142,96 @@ void process_cpuid()
3493 if (has_aperf) 4142 if (has_aperf)
3494 aperf_mperf_multiplier = get_aperf_mperf_multiplier(family, model); 4143 aperf_mperf_multiplier = get_aperf_mperf_multiplier(family, model);
3495 4144
3496 do_nhm_platform_info = do_nhm_cstates = do_smi = probe_nhm_msrs(family, model); 4145 BIC_PRESENT(BIC_IRQ);
4146 BIC_PRESENT(BIC_TSC_MHz);
4147
4148 if (probe_nhm_msrs(family, model)) {
4149 do_nhm_platform_info = 1;
4150 BIC_PRESENT(BIC_CPU_c1);
4151 BIC_PRESENT(BIC_CPU_c3);
4152 BIC_PRESENT(BIC_CPU_c6);
4153 BIC_PRESENT(BIC_SMI);
4154 }
3497 do_snb_cstates = has_snb_msrs(family, model); 4155 do_snb_cstates = has_snb_msrs(family, model);
4156
4157 if (do_snb_cstates)
4158 BIC_PRESENT(BIC_CPU_c7);
4159
3498 do_irtl_snb = has_snb_msrs(family, model); 4160 do_irtl_snb = has_snb_msrs(family, model);
3499 do_pc2 = do_snb_cstates && (pkg_cstate_limit >= PCL__2); 4161 if (do_snb_cstates && (pkg_cstate_limit >= PCL__2))
3500 do_pc3 = (pkg_cstate_limit >= PCL__3); 4162 BIC_PRESENT(BIC_Pkgpc2);
3501 do_pc6 = (pkg_cstate_limit >= PCL__6); 4163 if (pkg_cstate_limit >= PCL__3)
3502 do_pc7 = do_snb_cstates && (pkg_cstate_limit >= PCL__7); 4164 BIC_PRESENT(BIC_Pkgpc3);
3503 do_c8_c9_c10 = has_hsw_msrs(family, model); 4165 if (pkg_cstate_limit >= PCL__6)
4166 BIC_PRESENT(BIC_Pkgpc6);
4167 if (do_snb_cstates && (pkg_cstate_limit >= PCL__7))
4168 BIC_PRESENT(BIC_Pkgpc7);
4169 if (has_slv_msrs(family, model)) {
4170 BIC_NOT_PRESENT(BIC_Pkgpc2);
4171 BIC_NOT_PRESENT(BIC_Pkgpc3);
4172 BIC_PRESENT(BIC_Pkgpc6);
4173 BIC_NOT_PRESENT(BIC_Pkgpc7);
4174 BIC_PRESENT(BIC_Mod_c6);
4175 use_c1_residency_msr = 1;
4176 }
4177 if (is_dnv(family, model)) {
4178 BIC_PRESENT(BIC_CPU_c1);
4179 BIC_NOT_PRESENT(BIC_CPU_c3);
4180 BIC_NOT_PRESENT(BIC_Pkgpc3);
4181 BIC_NOT_PRESENT(BIC_CPU_c7);
4182 BIC_NOT_PRESENT(BIC_Pkgpc7);
4183 use_c1_residency_msr = 1;
4184 }
4185 if (is_skx(family, model)) {
4186 BIC_NOT_PRESENT(BIC_CPU_c3);
4187 BIC_NOT_PRESENT(BIC_Pkgpc3);
4188 BIC_NOT_PRESENT(BIC_CPU_c7);
4189 BIC_NOT_PRESENT(BIC_Pkgpc7);
4190 }
4191 if (is_bdx(family, model)) {
4192 BIC_NOT_PRESENT(BIC_CPU_c7);
4193 BIC_NOT_PRESENT(BIC_Pkgpc7);
4194 }
4195 if (has_hsw_msrs(family, model)) {
4196 BIC_PRESENT(BIC_Pkgpc8);
4197 BIC_PRESENT(BIC_Pkgpc9);
4198 BIC_PRESENT(BIC_Pkgpc10);
4199 }
3504 do_irtl_hsw = has_hsw_msrs(family, model); 4200 do_irtl_hsw = has_hsw_msrs(family, model);
3505 do_skl_residency = has_skl_msrs(family, model); 4201 do_skl_residency = has_skl_msrs(family, model);
3506 do_slm_cstates = is_slm(family, model); 4202 do_slm_cstates = is_slm(family, model);
3507 do_knl_cstates = is_knl(family, model); 4203 do_knl_cstates = is_knl(family, model);
3508 4204
3509 if (debug) 4205 if (!quiet)
3510 decode_misc_pwr_mgmt_msr(); 4206 decode_misc_pwr_mgmt_msr();
3511 4207
4208 if (!quiet && has_slv_msrs(family, model))
4209 decode_c6_demotion_policy_msr();
4210
3512 rapl_probe(family, model); 4211 rapl_probe(family, model);
3513 perf_limit_reasons_probe(family, model); 4212 perf_limit_reasons_probe(family, model);
3514 4213
3515 if (debug) 4214 if (!quiet)
3516 dump_cstate_pstate_config_info(family, model); 4215 dump_cstate_pstate_config_info(family, model);
3517 4216
4217 if (!quiet)
4218 dump_sysfs_cstate_config();
4219 if (!quiet)
4220 dump_sysfs_pstate_config();
4221
3518 if (has_skl_msrs(family, model)) 4222 if (has_skl_msrs(family, model))
3519 calculate_tsc_tweak(); 4223 calculate_tsc_tweak();
3520 4224
3521 do_gfx_rc6_ms = !access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK); 4225 if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK))
4226 BIC_PRESENT(BIC_GFX_rc6);
3522 4227
3523 do_gfx_mhz = !access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK); 4228 if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK))
4229 BIC_PRESENT(BIC_GFXMHz);
3524 4230
3525 return; 4231 if (!quiet)
3526} 4232 decode_misc_feature_control();
3527 4233
3528void help() 4234 return;
3529{
3530 fprintf(outf,
3531 "Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n"
3532 "\n"
3533 "Turbostat forks the specified COMMAND and prints statistics\n"
3534 "when COMMAND completes.\n"
3535 "If no COMMAND is specified, turbostat wakes every 5-seconds\n"
3536 "to print statistics, until interrupted.\n"
3537 "--add add a counter\n"
3538 " eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
3539 "--debug run in \"debug\" mode\n"
3540 "--interval sec Override default 5-second measurement interval\n"
3541 "--help print this help message\n"
3542 "--out file create or truncate \"file\" for all output\n"
3543 "--version print version information\n"
3544 "\n"
3545 "For more help, run \"man turbostat\"\n");
3546} 4235}
3547 4236
3548 4237
@@ -3579,7 +4268,7 @@ void topology_probe()
3579 topo.max_cpu_num = 0; 4268 topo.max_cpu_num = 0;
3580 for_all_proc_cpus(count_cpus); 4269 for_all_proc_cpus(count_cpus);
3581 if (!summary_only && topo.num_cpus > 1) 4270 if (!summary_only && topo.num_cpus > 1)
3582 show_cpu = 1; 4271 BIC_PRESENT(BIC_CPU);
3583 4272
3584 if (debug > 1) 4273 if (debug > 1)
3585 fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num); 4274 fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num);
@@ -3599,6 +4288,15 @@ void topology_probe()
3599 for_all_proc_cpus(mark_cpu_present); 4288 for_all_proc_cpus(mark_cpu_present);
3600 4289
3601 /* 4290 /*
4291 * Validate that all cpus in cpu_subset are also in cpu_present_set
4292 */
4293 for (i = 0; i < CPU_SUBSET_MAXCPUS; ++i) {
4294 if (CPU_ISSET_S(i, cpu_subset_size, cpu_subset))
4295 if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set))
4296 err(1, "cpu%d not present", i);
4297 }
4298
4299 /*
3602 * Allocate and initialize cpu_affinity_set 4300 * Allocate and initialize cpu_affinity_set
3603 */ 4301 */
3604 cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1)); 4302 cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1));
@@ -3639,15 +4337,15 @@ void topology_probe()
3639 if (debug > 1) 4337 if (debug > 1)
3640 fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", 4338 fprintf(outf, "max_core_id %d, sizing for %d cores per package\n",
3641 max_core_id, topo.num_cores_per_pkg); 4339 max_core_id, topo.num_cores_per_pkg);
3642 if (debug && !summary_only && topo.num_cores_per_pkg > 1) 4340 if (!summary_only && topo.num_cores_per_pkg > 1)
3643 show_core = 1; 4341 BIC_PRESENT(BIC_Core);
3644 4342
3645 topo.num_packages = max_package_id + 1; 4343 topo.num_packages = max_package_id + 1;
3646 if (debug > 1) 4344 if (debug > 1)
3647 fprintf(outf, "max_package_id %d, sizing for %d packages\n", 4345 fprintf(outf, "max_package_id %d, sizing for %d packages\n",
3648 max_package_id, topo.num_packages); 4346 max_package_id, topo.num_packages);
3649 if (debug && !summary_only && topo.num_packages > 1) 4347 if (!summary_only && topo.num_packages > 1)
3650 show_pkg = 1; 4348 BIC_PRESENT(BIC_Package);
3651 4349
3652 topo.num_threads_per_core = max_siblings; 4350 topo.num_threads_per_core = max_siblings;
3653 if (debug > 1) 4351 if (debug > 1)
@@ -3662,7 +4360,7 @@ allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data
3662 int i; 4360 int i;
3663 4361
3664 *t = calloc(topo.num_threads_per_core * topo.num_cores_per_pkg * 4362 *t = calloc(topo.num_threads_per_core * topo.num_cores_per_pkg *
3665 topo.num_packages, sizeof(struct thread_data) + sys.thread_counter_bytes); 4363 topo.num_packages, sizeof(struct thread_data));
3666 if (*t == NULL) 4364 if (*t == NULL)
3667 goto error; 4365 goto error;
3668 4366
@@ -3671,14 +4369,14 @@ allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data
3671 (*t)[i].cpu_id = -1; 4369 (*t)[i].cpu_id = -1;
3672 4370
3673 *c = calloc(topo.num_cores_per_pkg * topo.num_packages, 4371 *c = calloc(topo.num_cores_per_pkg * topo.num_packages,
3674 sizeof(struct core_data) + sys.core_counter_bytes); 4372 sizeof(struct core_data));
3675 if (*c == NULL) 4373 if (*c == NULL)
3676 goto error; 4374 goto error;
3677 4375
3678 for (i = 0; i < topo.num_cores_per_pkg * topo.num_packages; i++) 4376 for (i = 0; i < topo.num_cores_per_pkg * topo.num_packages; i++)
3679 (*c)[i].core_id = -1; 4377 (*c)[i].core_id = -1;
3680 4378
3681 *p = calloc(topo.num_packages, sizeof(struct pkg_data) + sys.package_counter_bytes); 4379 *p = calloc(topo.num_packages, sizeof(struct pkg_data));
3682 if (*p == NULL) 4380 if (*p == NULL)
3683 goto error; 4381 goto error;
3684 4382
@@ -3789,24 +4487,24 @@ void turbostat_init()
3789 process_cpuid(); 4487 process_cpuid();
3790 4488
3791 4489
3792 if (debug) 4490 if (!quiet)
3793 for_all_cpus(print_hwp, ODD_COUNTERS); 4491 for_all_cpus(print_hwp, ODD_COUNTERS);
3794 4492
3795 if (debug) 4493 if (!quiet)
3796 for_all_cpus(print_epb, ODD_COUNTERS); 4494 for_all_cpus(print_epb, ODD_COUNTERS);
3797 4495
3798 if (debug) 4496 if (!quiet)
3799 for_all_cpus(print_perf_limit, ODD_COUNTERS); 4497 for_all_cpus(print_perf_limit, ODD_COUNTERS);
3800 4498
3801 if (debug) 4499 if (!quiet)
3802 for_all_cpus(print_rapl, ODD_COUNTERS); 4500 for_all_cpus(print_rapl, ODD_COUNTERS);
3803 4501
3804 for_all_cpus(set_temperature_target, ODD_COUNTERS); 4502 for_all_cpus(set_temperature_target, ODD_COUNTERS);
3805 4503
3806 if (debug) 4504 if (!quiet)
3807 for_all_cpus(print_thermal, ODD_COUNTERS); 4505 for_all_cpus(print_thermal, ODD_COUNTERS);
3808 4506
3809 if (debug && do_irtl_snb) 4507 if (!quiet && do_irtl_snb)
3810 print_irtl(); 4508 print_irtl();
3811} 4509}
3812 4510
@@ -3815,6 +4513,7 @@ int fork_it(char **argv)
3815 pid_t child_pid; 4513 pid_t child_pid;
3816 int status; 4514 int status;
3817 4515
4516 snapshot_proc_sysfs_files();
3818 status = for_all_cpus(get_counters, EVEN_COUNTERS); 4517 status = for_all_cpus(get_counters, EVEN_COUNTERS);
3819 if (status) 4518 if (status)
3820 exit(status); 4519 exit(status);
@@ -3826,6 +4525,7 @@ int fork_it(char **argv)
3826 if (!child_pid) { 4525 if (!child_pid) {
3827 /* child */ 4526 /* child */
3828 execvp(argv[0], argv); 4527 execvp(argv[0], argv);
4528 err(errno, "exec %s", argv[0]);
3829 } else { 4529 } else {
3830 4530
3831 /* parent */ 4531 /* parent */
@@ -3841,6 +4541,7 @@ int fork_it(char **argv)
3841 * n.b. fork_it() does not check for errors from for_all_cpus() 4541 * n.b. fork_it() does not check for errors from for_all_cpus()
3842 * because re-starting is problematic when forking 4542 * because re-starting is problematic when forking
3843 */ 4543 */
4544 snapshot_proc_sysfs_files();
3844 for_all_cpus(get_counters, ODD_COUNTERS); 4545 for_all_cpus(get_counters, ODD_COUNTERS);
3845 gettimeofday(&tv_odd, (struct timezone *)NULL); 4546 gettimeofday(&tv_odd, (struct timezone *)NULL);
3846 timersub(&tv_odd, &tv_even, &tv_delta); 4547 timersub(&tv_odd, &tv_even, &tv_delta);
@@ -3862,6 +4563,7 @@ int get_and_dump_counters(void)
3862{ 4563{
3863 int status; 4564 int status;
3864 4565
4566 snapshot_proc_sysfs_files();
3865 status = for_all_cpus(get_counters, ODD_COUNTERS); 4567 status = for_all_cpus(get_counters, ODD_COUNTERS);
3866 if (status) 4568 if (status)
3867 return status; 4569 return status;
@@ -3876,13 +4578,13 @@ int get_and_dump_counters(void)
3876} 4578}
3877 4579
3878void print_version() { 4580void print_version() {
3879 fprintf(outf, "turbostat version 4.16 24 Dec 2016" 4581 fprintf(outf, "turbostat version 17.02.24"
3880 " - Len Brown <lenb@kernel.org>\n"); 4582 " - Len Brown <lenb@kernel.org>\n");
3881} 4583}
3882 4584
3883int add_counter(unsigned int msr_num, char *name, unsigned int width, 4585int add_counter(unsigned int msr_num, char *path, char *name,
3884 enum counter_scope scope, enum counter_type type, 4586 unsigned int width, enum counter_scope scope,
3885 enum counter_format format) 4587 enum counter_type type, enum counter_format format, int flags)
3886{ 4588{
3887 struct msr_counter *msrp; 4589 struct msr_counter *msrp;
3888 4590
@@ -3894,31 +4596,46 @@ int add_counter(unsigned int msr_num, char *name, unsigned int width,
3894 4596
3895 msrp->msr_num = msr_num; 4597 msrp->msr_num = msr_num;
3896 strncpy(msrp->name, name, NAME_BYTES); 4598 strncpy(msrp->name, name, NAME_BYTES);
4599 if (path)
4600 strncpy(msrp->path, path, PATH_BYTES);
3897 msrp->width = width; 4601 msrp->width = width;
3898 msrp->type = type; 4602 msrp->type = type;
3899 msrp->format = format; 4603 msrp->format = format;
4604 msrp->flags = flags;
3900 4605
3901 switch (scope) { 4606 switch (scope) {
3902 4607
3903 case SCOPE_CPU: 4608 case SCOPE_CPU:
3904 sys.thread_counter_bytes += 64;
3905 msrp->next = sys.tp; 4609 msrp->next = sys.tp;
3906 sys.tp = msrp; 4610 sys.tp = msrp;
3907 sys.thread_counter_bytes += sizeof(unsigned long long); 4611 sys.added_thread_counters++;
4612 if (sys.added_thread_counters > MAX_ADDED_COUNTERS) {
4613 fprintf(stderr, "exceeded max %d added thread counters\n",
4614 MAX_ADDED_COUNTERS);
4615 exit(-1);
4616 }
3908 break; 4617 break;
3909 4618
3910 case SCOPE_CORE: 4619 case SCOPE_CORE:
3911 sys.core_counter_bytes += 64;
3912 msrp->next = sys.cp; 4620 msrp->next = sys.cp;
3913 sys.cp = msrp; 4621 sys.cp = msrp;
3914 sys.core_counter_bytes += sizeof(unsigned long long); 4622 sys.added_core_counters++;
4623 if (sys.added_core_counters > MAX_ADDED_COUNTERS) {
4624 fprintf(stderr, "exceeded max %d added core counters\n",
4625 MAX_ADDED_COUNTERS);
4626 exit(-1);
4627 }
3915 break; 4628 break;
3916 4629
3917 case SCOPE_PACKAGE: 4630 case SCOPE_PACKAGE:
3918 sys.package_counter_bytes += 64;
3919 msrp->next = sys.pp; 4631 msrp->next = sys.pp;
3920 sys.pp = msrp; 4632 sys.pp = msrp;
3921 sys.package_counter_bytes += sizeof(unsigned long long); 4633 sys.added_package_counters++;
4634 if (sys.added_package_counters > MAX_ADDED_COUNTERS) {
4635 fprintf(stderr, "exceeded max %d added package counters\n",
4636 MAX_ADDED_COUNTERS);
4637 exit(-1);
4638 }
3922 break; 4639 break;
3923 } 4640 }
3924 4641
@@ -3928,7 +4645,8 @@ int add_counter(unsigned int msr_num, char *name, unsigned int width,
3928void parse_add_command(char *add_command) 4645void parse_add_command(char *add_command)
3929{ 4646{
3930 int msr_num = 0; 4647 int msr_num = 0;
3931 char name_buffer[NAME_BYTES]; 4648 char *path = NULL;
4649 char name_buffer[NAME_BYTES] = "";
3932 int width = 64; 4650 int width = 64;
3933 int fail = 0; 4651 int fail = 0;
3934 enum counter_scope scope = SCOPE_CPU; 4652 enum counter_scope scope = SCOPE_CPU;
@@ -3943,6 +4661,11 @@ void parse_add_command(char *add_command)
3943 if (sscanf(add_command, "msr%d", &msr_num) == 1) 4661 if (sscanf(add_command, "msr%d", &msr_num) == 1)
3944 goto next; 4662 goto next;
3945 4663
4664 if (*add_command == '/') {
4665 path = add_command;
4666 goto next;
4667 }
4668
3946 if (sscanf(add_command, "u%d", &width) == 1) { 4669 if (sscanf(add_command, "u%d", &width) == 1) {
3947 if ((width == 32) || (width == 64)) 4670 if ((width == 32) || (width == 64))
3948 goto next; 4671 goto next;
@@ -3968,6 +4691,10 @@ void parse_add_command(char *add_command)
3968 type = COUNTER_SECONDS; 4691 type = COUNTER_SECONDS;
3969 goto next; 4692 goto next;
3970 } 4693 }
4694 if (!strncmp(add_command, "usec", strlen("usec"))) {
4695 type = COUNTER_USEC;
4696 goto next;
4697 }
3971 if (!strncmp(add_command, "raw", strlen("raw"))) { 4698 if (!strncmp(add_command, "raw", strlen("raw"))) {
3972 format = FORMAT_RAW; 4699 format = FORMAT_RAW;
3973 goto next; 4700 goto next;
@@ -3992,36 +4719,26 @@ void parse_add_command(char *add_command)
3992 4719
3993next: 4720next:
3994 add_command = strchr(add_command, ','); 4721 add_command = strchr(add_command, ',');
3995 if (add_command) 4722 if (add_command) {
4723 *add_command = '\0';
3996 add_command++; 4724 add_command++;
4725 }
3997 4726
3998 } 4727 }
3999 if (msr_num == 0) { 4728 if ((msr_num == 0) && (path == NULL)) {
4000 fprintf(stderr, "--add: (msrDDD | msr0xXXX) required\n"); 4729 fprintf(stderr, "--add: (msrDDD | msr0xXXX | /path_to_counter ) required\n");
4001 fail++; 4730 fail++;
4002 } 4731 }
4003 4732
4004 /* generate default column header */ 4733 /* generate default column header */
4005 if (*name_buffer == '\0') { 4734 if (*name_buffer == '\0') {
4006 if (format == FORMAT_RAW) { 4735 if (width == 32)
4007 if (width == 32) 4736 sprintf(name_buffer, "M0x%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");
4008 sprintf(name_buffer, "msr%d", msr_num); 4737 else
4009 else 4738 sprintf(name_buffer, "M0X%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");
4010 sprintf(name_buffer, "MSR%d", msr_num);
4011 } else if (format == FORMAT_DELTA) {
4012 if (width == 32)
4013 sprintf(name_buffer, "cnt%d", msr_num);
4014 else
4015 sprintf(name_buffer, "CNT%d", msr_num);
4016 } else if (format == FORMAT_PERCENT) {
4017 if (width == 32)
4018 sprintf(name_buffer, "msr%d%%", msr_num);
4019 else
4020 sprintf(name_buffer, "MSR%d%%", msr_num);
4021 }
4022 } 4739 }
4023 4740
4024 if (add_counter(msr_num, name_buffer, width, scope, type, format)) 4741 if (add_counter(msr_num, path, name_buffer, width, scope, type, format, 0))
4025 fail++; 4742 fail++;
4026 4743
4027 if (fail) { 4744 if (fail) {
@@ -4029,20 +4746,214 @@ next:
4029 exit(1); 4746 exit(1);
4030 } 4747 }
4031} 4748}
4749
4750int is_deferred_skip(char *name)
4751{
4752 int i;
4753
4754 for (i = 0; i < deferred_skip_index; ++i)
4755 if (!strcmp(name, deferred_skip_names[i]))
4756 return 1;
4757 return 0;
4758}
4759
4760void probe_sysfs(void)
4761{
4762 char path[64];
4763 char name_buf[16];
4764 FILE *input;
4765 int state;
4766 char *sp;
4767
4768 if (!DO_BIC(BIC_sysfs))
4769 return;
4770
4771 for (state = 10; state > 0; --state) {
4772
4773 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
4774 base_cpu, state);
4775 input = fopen(path, "r");
4776 if (input == NULL)
4777 continue;
4778 fgets(name_buf, sizeof(name_buf), input);
4779
4780 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
4781 sp = strchr(name_buf, '-');
4782 if (!sp)
4783 sp = strchrnul(name_buf, '\n');
4784 *sp = '%';
4785 *(sp + 1) = '\0';
4786
4787 fclose(input);
4788
4789 sprintf(path, "cpuidle/state%d/time", state);
4790
4791 if (is_deferred_skip(name_buf))
4792 continue;
4793
4794 add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_USEC,
4795 FORMAT_PERCENT, SYSFS_PERCPU);
4796 }
4797
4798 for (state = 10; state > 0; --state) {
4799
4800 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
4801 base_cpu, state);
4802 input = fopen(path, "r");
4803 if (input == NULL)
4804 continue;
4805 fgets(name_buf, sizeof(name_buf), input);
4806 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
4807 sp = strchr(name_buf, '-');
4808 if (!sp)
4809 sp = strchrnul(name_buf, '\n');
4810 *sp = '\0';
4811 fclose(input);
4812
4813 sprintf(path, "cpuidle/state%d/usage", state);
4814
4815 if (is_deferred_skip(name_buf))
4816 continue;
4817
4818 add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS,
4819 FORMAT_DELTA, SYSFS_PERCPU);
4820 }
4821
4822}
4823
4824
4825/*
4826 * parse cpuset with following syntax
4827 * 1,2,4..6,8-10 and set bits in cpu_subset
4828 */
4829void parse_cpu_command(char *optarg)
4830{
4831 unsigned int start, end;
4832 char *next;
4833
4834 if (!strcmp(optarg, "core")) {
4835 if (cpu_subset)
4836 goto error;
4837 show_core_only++;
4838 return;
4839 }
4840 if (!strcmp(optarg, "package")) {
4841 if (cpu_subset)
4842 goto error;
4843 show_pkg_only++;
4844 return;
4845 }
4846 if (show_core_only || show_pkg_only)
4847 goto error;
4848
4849 cpu_subset = CPU_ALLOC(CPU_SUBSET_MAXCPUS);
4850 if (cpu_subset == NULL)
4851 err(3, "CPU_ALLOC");
4852 cpu_subset_size = CPU_ALLOC_SIZE(CPU_SUBSET_MAXCPUS);
4853
4854 CPU_ZERO_S(cpu_subset_size, cpu_subset);
4855
4856 next = optarg;
4857
4858 while (next && *next) {
4859
4860 if (*next == '-') /* no negative cpu numbers */
4861 goto error;
4862
4863 start = strtoul(next, &next, 10);
4864
4865 if (start >= CPU_SUBSET_MAXCPUS)
4866 goto error;
4867 CPU_SET_S(start, cpu_subset_size, cpu_subset);
4868
4869 if (*next == '\0')
4870 break;
4871
4872 if (*next == ',') {
4873 next += 1;
4874 continue;
4875 }
4876
4877 if (*next == '-') {
4878 next += 1; /* start range */
4879 } else if (*next == '.') {
4880 next += 1;
4881 if (*next == '.')
4882 next += 1; /* start range */
4883 else
4884 goto error;
4885 }
4886
4887 end = strtoul(next, &next, 10);
4888 if (end <= start)
4889 goto error;
4890
4891 while (++start <= end) {
4892 if (start >= CPU_SUBSET_MAXCPUS)
4893 goto error;
4894 CPU_SET_S(start, cpu_subset_size, cpu_subset);
4895 }
4896
4897 if (*next == ',')
4898 next += 1;
4899 else if (*next != '\0')
4900 goto error;
4901 }
4902
4903 return;
4904
4905error:
4906 fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);
4907 help();
4908 exit(-1);
4909}
4910
4911int shown;
4912/*
4913 * parse_show_hide() - process cmdline to set default counter action
4914 */
4915void parse_show_hide(char *optarg, enum show_hide_mode new_mode)
4916{
4917 /*
4918 * --show: show only those specified
4919 * The 1st invocation will clear and replace the enabled mask
4920 * subsequent invocations can add to it.
4921 */
4922 if (new_mode == SHOW_LIST) {
4923 if (shown == 0)
4924 bic_enabled = bic_lookup(optarg, new_mode);
4925 else
4926 bic_enabled |= bic_lookup(optarg, new_mode);
4927 shown = 1;
4928
4929 return;
4930 }
4931
4932 /*
4933 * --hide: do not show those specified
4934 * multiple invocations simply clear more bits in enabled mask
4935 */
4936 bic_enabled &= ~bic_lookup(optarg, new_mode);
4937
4938}
4939
4032void cmdline(int argc, char **argv) 4940void cmdline(int argc, char **argv)
4033{ 4941{
4034 int opt; 4942 int opt;
4035 int option_index = 0; 4943 int option_index = 0;
4036 static struct option long_options[] = { 4944 static struct option long_options[] = {
4037 {"add", required_argument, 0, 'a'}, 4945 {"add", required_argument, 0, 'a'},
4946 {"cpu", required_argument, 0, 'c'},
4038 {"Dump", no_argument, 0, 'D'}, 4947 {"Dump", no_argument, 0, 'D'},
4039 {"debug", no_argument, 0, 'd'}, 4948 {"debug", no_argument, 0, 'd'}, /* internal, not documented */
4040 {"interval", required_argument, 0, 'i'}, 4949 {"interval", required_argument, 0, 'i'},
4041 {"help", no_argument, 0, 'h'}, 4950 {"help", no_argument, 0, 'h'},
4951 {"hide", required_argument, 0, 'H'}, // meh, -h taken by --help
4042 {"Joules", no_argument, 0, 'J'}, 4952 {"Joules", no_argument, 0, 'J'},
4953 {"list", no_argument, 0, 'l'},
4043 {"out", required_argument, 0, 'o'}, 4954 {"out", required_argument, 0, 'o'},
4044 {"Package", no_argument, 0, 'p'}, 4955 {"quiet", no_argument, 0, 'q'},
4045 {"processor", no_argument, 0, 'p'}, 4956 {"show", required_argument, 0, 's'},
4046 {"Summary", no_argument, 0, 'S'}, 4957 {"Summary", no_argument, 0, 'S'},
4047 {"TCC", required_argument, 0, 'T'}, 4958 {"TCC", required_argument, 0, 'T'},
4048 {"version", no_argument, 0, 'v' }, 4959 {"version", no_argument, 0, 'v' },
@@ -4051,18 +4962,24 @@ void cmdline(int argc, char **argv)
4051 4962
4052 progname = argv[0]; 4963 progname = argv[0];
4053 4964
4054 while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:o:PpST:v", 4965 while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:o:qST:v",
4055 long_options, &option_index)) != -1) { 4966 long_options, &option_index)) != -1) {
4056 switch (opt) { 4967 switch (opt) {
4057 case 'a': 4968 case 'a':
4058 parse_add_command(optarg); 4969 parse_add_command(optarg);
4059 break; 4970 break;
4971 case 'c':
4972 parse_cpu_command(optarg);
4973 break;
4060 case 'D': 4974 case 'D':
4061 dump_only++; 4975 dump_only++;
4062 break; 4976 break;
4063 case 'd': 4977 case 'd':
4064 debug++; 4978 debug++;
4065 break; 4979 break;
4980 case 'H':
4981 parse_show_hide(optarg, HIDE_LIST);
4982 break;
4066 case 'h': 4983 case 'h':
4067 default: 4984 default:
4068 help(); 4985 help();
@@ -4084,14 +5001,18 @@ void cmdline(int argc, char **argv)
4084 case 'J': 5001 case 'J':
4085 rapl_joules++; 5002 rapl_joules++;
4086 break; 5003 break;
5004 case 'l':
5005 list_header_only++;
5006 quiet++;
5007 break;
4087 case 'o': 5008 case 'o':
4088 outf = fopen_or_die(optarg, "w"); 5009 outf = fopen_or_die(optarg, "w");
4089 break; 5010 break;
4090 case 'P': 5011 case 'q':
4091 show_pkg_only++; 5012 quiet = 1;
4092 break; 5013 break;
4093 case 'p': 5014 case 's':
4094 show_core_only++; 5015 parse_show_hide(optarg, SHOW_LIST);
4095 break; 5016 break;
4096 case 'S': 5017 case 'S':
4097 summary_only++; 5018 summary_only++;
@@ -4113,15 +5034,24 @@ int main(int argc, char **argv)
4113 5034
4114 cmdline(argc, argv); 5035 cmdline(argc, argv);
4115 5036
4116 if (debug) 5037 if (!quiet)
4117 print_version(); 5038 print_version();
4118 5039
5040 probe_sysfs();
5041
4119 turbostat_init(); 5042 turbostat_init();
4120 5043
4121 /* dump counters and exit */ 5044 /* dump counters and exit */
4122 if (dump_only) 5045 if (dump_only)
4123 return get_and_dump_counters(); 5046 return get_and_dump_counters();
4124 5047
5048 /* list header and exit */
5049 if (list_header_only) {
5050 print_header(",");
5051 flush_output_stdout();
5052 return 0;
5053 }
5054
4125 /* 5055 /*
4126 * if any params left, it must be a command to fork 5056 * if any params left, it must be a command to fork
4127 */ 5057 */
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 8abbef164b4e..621578aa12d6 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -32,7 +32,6 @@ EXTRA_WARNINGS += -Wold-style-definition
32EXTRA_WARNINGS += -Wpacked 32EXTRA_WARNINGS += -Wpacked
33EXTRA_WARNINGS += -Wredundant-decls 33EXTRA_WARNINGS += -Wredundant-decls
34EXTRA_WARNINGS += -Wshadow 34EXTRA_WARNINGS += -Wshadow
35EXTRA_WARNINGS += -Wstrict-aliasing=3
36EXTRA_WARNINGS += -Wstrict-prototypes 35EXTRA_WARNINGS += -Wstrict-prototypes
37EXTRA_WARNINGS += -Wswitch-default 36EXTRA_WARNINGS += -Wswitch-default
38EXTRA_WARNINGS += -Wswitch-enum 37EXTRA_WARNINGS += -Wswitch-enum
@@ -40,12 +39,26 @@ EXTRA_WARNINGS += -Wundef
40EXTRA_WARNINGS += -Wwrite-strings 39EXTRA_WARNINGS += -Wwrite-strings
41EXTRA_WARNINGS += -Wformat 40EXTRA_WARNINGS += -Wformat
42 41
42ifneq ($(CC), clang)
43EXTRA_WARNINGS += -Wstrict-aliasing=3
44endif
45
43ifneq ($(findstring $(MAKEFLAGS), w),w) 46ifneq ($(findstring $(MAKEFLAGS), w),w)
44PRINT_DIR = --no-print-directory 47PRINT_DIR = --no-print-directory
45else 48else
46NO_SUBDIR = : 49NO_SUBDIR = :
47endif 50endif
48 51
52ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4
53ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)
54 silent=1
55endif
56else # make-3.8x
57ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
58 silent=1
59endif
60endif
61
49# 62#
50# Define a callable command for descending to a new directory 63# Define a callable command for descending to a new directory
51# 64#
@@ -58,7 +71,7 @@ descend = \
58QUIET_SUBDIR0 = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir 71QUIET_SUBDIR0 = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir
59QUIET_SUBDIR1 = 72QUIET_SUBDIR1 =
60 73
61ifneq ($(findstring $(MAKEFLAGS),s),s) 74ifneq ($(silent),1)
62 ifneq ($(V),1) 75 ifneq ($(V),1)
63 QUIET_CC = @echo ' CC '$@; 76 QUIET_CC = @echo ' CC '$@;
64 QUIET_CC_FPIC = @echo ' CC FPIC '$@; 77 QUIET_CC_FPIC = @echo ' CC FPIC '$@;
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index be93ab02b490..6e4eb2fc2d1e 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -179,6 +179,7 @@ my $localversion;
179my $iteration = 0; 179my $iteration = 0;
180my $successes = 0; 180my $successes = 0;
181my $stty_orig; 181my $stty_orig;
182my $run_command_status = 0;
182 183
183my $bisect_good; 184my $bisect_good;
184my $bisect_bad; 185my $bisect_bad;
@@ -1325,26 +1326,44 @@ sub wait_for_monitor;
1325 1326
1326sub reboot { 1327sub reboot {
1327 my ($time) = @_; 1328 my ($time) = @_;
1329 my $powercycle = 0;
1328 1330
1329 # Make sure everything has been written to disk 1331 # test if the machine can be connected to within 5 seconds
1330 run_ssh("sync"); 1332 my $stat = run_ssh("echo check machine status", 5);
1333 if (!$stat) {
1334 doprint("power cycle\n");
1335 $powercycle = 1;
1336 }
1337
1338 if ($powercycle) {
1339 run_command "$power_cycle";
1331 1340
1332 if (defined($time)) {
1333 start_monitor; 1341 start_monitor;
1334 # flush out current monitor 1342 # flush out current monitor
1335 # May contain the reboot success line 1343 # May contain the reboot success line
1336 wait_for_monitor 1; 1344 wait_for_monitor 1;
1337 }
1338 1345
1339 # try to reboot normally 1346 } else {
1340 if (run_command $reboot) { 1347 # Make sure everything has been written to disk
1341 if (defined($powercycle_after_reboot)) { 1348 run_ssh("sync");
1342 sleep $powercycle_after_reboot; 1349
1350 if (defined($time)) {
1351 start_monitor;
1352 # flush out current monitor
1353 # May contain the reboot success line
1354 wait_for_monitor 1;
1355 }
1356
1357 # try to reboot normally
1358 if (run_command $reboot) {
1359 if (defined($powercycle_after_reboot)) {
1360 sleep $powercycle_after_reboot;
1361 run_command "$power_cycle";
1362 }
1363 } else {
1364 # nope? power cycle it.
1343 run_command "$power_cycle"; 1365 run_command "$power_cycle";
1344 } 1366 }
1345 } else {
1346 # nope? power cycle it.
1347 run_command "$power_cycle";
1348 } 1367 }
1349 1368
1350 if (defined($time)) { 1369 if (defined($time)) {
@@ -1412,6 +1431,10 @@ sub dodie {
1412 system("stty $stty_orig"); 1431 system("stty $stty_orig");
1413 } 1432 }
1414 1433
1434 if (defined($post_test)) {
1435 run_command $post_test;
1436 }
1437
1415 die @_, "\n"; 1438 die @_, "\n";
1416} 1439}
1417 1440
@@ -1624,10 +1647,6 @@ sub save_logs {
1624 1647
1625sub fail { 1648sub fail {
1626 1649
1627 if (defined($post_test)) {
1628 run_command $post_test;
1629 }
1630
1631 if ($die_on_failure) { 1650 if ($die_on_failure) {
1632 dodie @_; 1651 dodie @_;
1633 } 1652 }
@@ -1660,23 +1679,26 @@ sub fail {
1660 save_logs "fail", $store_failures; 1679 save_logs "fail", $store_failures;
1661 } 1680 }
1662 1681
1682 if (defined($post_test)) {
1683 run_command $post_test;
1684 }
1685
1663 return 1; 1686 return 1;
1664} 1687}
1665 1688
1666sub run_command { 1689sub run_command {
1667 my ($command, $redirect) = @_; 1690 my ($command, $redirect, $timeout) = @_;
1668 my $start_time; 1691 my $start_time;
1669 my $end_time; 1692 my $end_time;
1670 my $dolog = 0; 1693 my $dolog = 0;
1671 my $dord = 0; 1694 my $dord = 0;
1672 my $pid; 1695 my $pid;
1673 1696
1674 $start_time = time;
1675
1676 $command =~ s/\$SSH_USER/$ssh_user/g; 1697 $command =~ s/\$SSH_USER/$ssh_user/g;
1677 $command =~ s/\$MACHINE/$machine/g; 1698 $command =~ s/\$MACHINE/$machine/g;
1678 1699
1679 doprint("$command ... "); 1700 doprint("$command ... ");
1701 $start_time = time;
1680 1702
1681 $pid = open(CMD, "$command 2>&1 |") or 1703 $pid = open(CMD, "$command 2>&1 |") or
1682 (fail "unable to exec $command" and return 0); 1704 (fail "unable to exec $command" and return 0);
@@ -1693,13 +1715,30 @@ sub run_command {
1693 $dord = 1; 1715 $dord = 1;
1694 } 1716 }
1695 1717
1696 while (<CMD>) { 1718 my $hit_timeout = 0;
1697 print LOG if ($dolog); 1719
1698 print RD if ($dord); 1720 while (1) {
1721 my $fp = \*CMD;
1722 if (defined($timeout)) {
1723 doprint "timeout = $timeout\n";
1724 }
1725 my $line = wait_for_input($fp, $timeout);
1726 if (!defined($line)) {
1727 my $now = time;
1728 if (defined($timeout) && (($now - $start_time) >= $timeout)) {
1729 doprint "Hit timeout of $timeout, killing process\n";
1730 $hit_timeout = 1;
1731 kill 9, $pid;
1732 }
1733 last;
1734 }
1735 print LOG $line if ($dolog);
1736 print RD $line if ($dord);
1699 } 1737 }
1700 1738
1701 waitpid($pid, 0); 1739 waitpid($pid, 0);
1702 my $failed = $?; 1740 # shift 8 for real exit status
1741 $run_command_status = $? >> 8;
1703 1742
1704 close(CMD); 1743 close(CMD);
1705 close(LOG) if ($dolog); 1744 close(LOG) if ($dolog);
@@ -1714,21 +1753,25 @@ sub run_command {
1714 doprint "[$delta seconds] "; 1753 doprint "[$delta seconds] ";
1715 } 1754 }
1716 1755
1717 if ($failed) { 1756 if ($hit_timeout) {
1757 $run_command_status = 1;
1758 }
1759
1760 if ($run_command_status) {
1718 doprint "FAILED!\n"; 1761 doprint "FAILED!\n";
1719 } else { 1762 } else {
1720 doprint "SUCCESS\n"; 1763 doprint "SUCCESS\n";
1721 } 1764 }
1722 1765
1723 return !$failed; 1766 return !$run_command_status;
1724} 1767}
1725 1768
1726sub run_ssh { 1769sub run_ssh {
1727 my ($cmd) = @_; 1770 my ($cmd, $timeout) = @_;
1728 my $cp_exec = $ssh_exec; 1771 my $cp_exec = $ssh_exec;
1729 1772
1730 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 1773 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1731 return run_command "$cp_exec"; 1774 return run_command "$cp_exec", undef , $timeout;
1732} 1775}
1733 1776
1734sub run_scp { 1777sub run_scp {
@@ -2489,10 +2532,6 @@ sub halt {
2489sub success { 2532sub success {
2490 my ($i) = @_; 2533 my ($i) = @_;
2491 2534
2492 if (defined($post_test)) {
2493 run_command $post_test;
2494 }
2495
2496 $successes++; 2535 $successes++;
2497 2536
2498 my $name = ""; 2537 my $name = "";
@@ -2517,6 +2556,10 @@ sub success {
2517 doprint "Reboot and wait $sleep_time seconds\n"; 2556 doprint "Reboot and wait $sleep_time seconds\n";
2518 reboot_to_good $sleep_time; 2557 reboot_to_good $sleep_time;
2519 } 2558 }
2559
2560 if (defined($post_test)) {
2561 run_command $post_test;
2562 }
2520} 2563}
2521 2564
2522sub answer_bisect { 2565sub answer_bisect {
@@ -2537,16 +2580,15 @@ sub answer_bisect {
2537} 2580}
2538 2581
2539sub child_run_test { 2582sub child_run_test {
2540 my $failed = 0;
2541 2583
2542 # child should have no power 2584 # child should have no power
2543 $reboot_on_error = 0; 2585 $reboot_on_error = 0;
2544 $poweroff_on_error = 0; 2586 $poweroff_on_error = 0;
2545 $die_on_failure = 1; 2587 $die_on_failure = 1;
2546 2588
2547 run_command $run_test, $testlog or $failed = 1; 2589 run_command $run_test, $testlog;
2548 2590
2549 exit $failed; 2591 exit $run_command_status;
2550} 2592}
2551 2593
2552my $child_done; 2594my $child_done;
@@ -2629,7 +2671,7 @@ sub do_run_test {
2629 } 2671 }
2630 2672
2631 waitpid $child_pid, 0; 2673 waitpid $child_pid, 0;
2632 $child_exit = $?; 2674 $child_exit = $? >> 8;
2633 2675
2634 my $end_time = time; 2676 my $end_time = time;
2635 $test_time = $end_time - $start_time; 2677 $test_time = $end_time - $start_time;
@@ -3330,7 +3372,6 @@ sub config_bisect {
3330 save_config \%good_configs, $good_config; 3372 save_config \%good_configs, $good_config;
3331 save_config \%bad_configs, $bad_config; 3373 save_config \%bad_configs, $bad_config;
3332 3374
3333
3334 if (defined($config_bisect_check) && $config_bisect_check ne "0") { 3375 if (defined($config_bisect_check) && $config_bisect_check ne "0") {
3335 if ($config_bisect_check ne "good") { 3376 if ($config_bisect_check ne "good") {
3336 doprint "Testing bad config\n"; 3377 doprint "Testing bad config\n";
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 45be8b55a663..798f17655433 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -887,7 +887,7 @@ static void nfit_test0_setup(struct nfit_test *t)
887 memdev->range_index = 0+1; 887 memdev->range_index = 0+1;
888 memdev->region_index = 4+1; 888 memdev->region_index = 4+1;
889 memdev->region_size = SPA0_SIZE/2; 889 memdev->region_size = SPA0_SIZE/2;
890 memdev->region_offset = t->spa_set_dma[0]; 890 memdev->region_offset = 1;
891 memdev->address = 0; 891 memdev->address = 0;
892 memdev->interleave_index = 0; 892 memdev->interleave_index = 0;
893 memdev->interleave_ways = 2; 893 memdev->interleave_ways = 2;
@@ -902,7 +902,7 @@ static void nfit_test0_setup(struct nfit_test *t)
902 memdev->range_index = 0+1; 902 memdev->range_index = 0+1;
903 memdev->region_index = 5+1; 903 memdev->region_index = 5+1;
904 memdev->region_size = SPA0_SIZE/2; 904 memdev->region_size = SPA0_SIZE/2;
905 memdev->region_offset = t->spa_set_dma[0] + SPA0_SIZE/2; 905 memdev->region_offset = (1 << 8);
906 memdev->address = 0; 906 memdev->address = 0;
907 memdev->interleave_index = 0; 907 memdev->interleave_index = 0;
908 memdev->interleave_ways = 2; 908 memdev->interleave_ways = 2;
@@ -917,7 +917,7 @@ static void nfit_test0_setup(struct nfit_test *t)
917 memdev->range_index = 1+1; 917 memdev->range_index = 1+1;
918 memdev->region_index = 4+1; 918 memdev->region_index = 4+1;
919 memdev->region_size = SPA1_SIZE/4; 919 memdev->region_size = SPA1_SIZE/4;
920 memdev->region_offset = t->spa_set_dma[1]; 920 memdev->region_offset = (1 << 16);
921 memdev->address = SPA0_SIZE/2; 921 memdev->address = SPA0_SIZE/2;
922 memdev->interleave_index = 0; 922 memdev->interleave_index = 0;
923 memdev->interleave_ways = 4; 923 memdev->interleave_ways = 4;
@@ -932,7 +932,7 @@ static void nfit_test0_setup(struct nfit_test *t)
932 memdev->range_index = 1+1; 932 memdev->range_index = 1+1;
933 memdev->region_index = 5+1; 933 memdev->region_index = 5+1;
934 memdev->region_size = SPA1_SIZE/4; 934 memdev->region_size = SPA1_SIZE/4;
935 memdev->region_offset = t->spa_set_dma[1] + SPA1_SIZE/4; 935 memdev->region_offset = (1 << 24);
936 memdev->address = SPA0_SIZE/2; 936 memdev->address = SPA0_SIZE/2;
937 memdev->interleave_index = 0; 937 memdev->interleave_index = 0;
938 memdev->interleave_ways = 4; 938 memdev->interleave_ways = 4;
@@ -947,7 +947,7 @@ static void nfit_test0_setup(struct nfit_test *t)
947 memdev->range_index = 1+1; 947 memdev->range_index = 1+1;
948 memdev->region_index = 6+1; 948 memdev->region_index = 6+1;
949 memdev->region_size = SPA1_SIZE/4; 949 memdev->region_size = SPA1_SIZE/4;
950 memdev->region_offset = t->spa_set_dma[1] + 2*SPA1_SIZE/4; 950 memdev->region_offset = (1ULL << 32);
951 memdev->address = SPA0_SIZE/2; 951 memdev->address = SPA0_SIZE/2;
952 memdev->interleave_index = 0; 952 memdev->interleave_index = 0;
953 memdev->interleave_ways = 4; 953 memdev->interleave_ways = 4;
@@ -962,7 +962,7 @@ static void nfit_test0_setup(struct nfit_test *t)
962 memdev->range_index = 1+1; 962 memdev->range_index = 1+1;
963 memdev->region_index = 7+1; 963 memdev->region_index = 7+1;
964 memdev->region_size = SPA1_SIZE/4; 964 memdev->region_size = SPA1_SIZE/4;
965 memdev->region_offset = t->spa_set_dma[1] + 3*SPA1_SIZE/4; 965 memdev->region_offset = (1ULL << 40);
966 memdev->address = SPA0_SIZE/2; 966 memdev->address = SPA0_SIZE/2;
967 memdev->interleave_index = 0; 967 memdev->interleave_index = 0;
968 memdev->interleave_ways = 4; 968 memdev->interleave_ways = 4;
@@ -1380,7 +1380,7 @@ static void nfit_test0_setup(struct nfit_test *t)
1380 memdev->range_index = 11+1; 1380 memdev->range_index = 11+1;
1381 memdev->region_index = 9+1; 1381 memdev->region_index = 9+1;
1382 memdev->region_size = SPA0_SIZE; 1382 memdev->region_size = SPA0_SIZE;
1383 memdev->region_offset = t->spa_set_dma[2]; 1383 memdev->region_offset = (1ULL << 48);
1384 memdev->address = 0; 1384 memdev->address = 0;
1385 memdev->interleave_index = 0; 1385 memdev->interleave_index = 0;
1386 memdev->interleave_ways = 1; 1386 memdev->interleave_ways = 1;
diff --git a/tools/testing/radix-tree/.gitignore b/tools/testing/radix-tree/.gitignore
index 11d888ca6a92..d4706c0ffceb 100644
--- a/tools/testing/radix-tree/.gitignore
+++ b/tools/testing/radix-tree/.gitignore
@@ -1,2 +1,6 @@
1generated/map-shift.h
2idr.c
3idr-test
1main 4main
5multiorder
2radix-tree.c 6radix-tree.c
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index 3635e4d3eca7..f11315bedefc 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -1,29 +1,47 @@
1 1
2CFLAGS += -I. -I../../include -g -O2 -Wall -D_LGPL_SOURCE 2CFLAGS += -I. -I../../include -g -O2 -Wall -D_LGPL_SOURCE -fsanitize=address
3LDFLAGS += -lpthread -lurcu 3LDFLAGS += -lpthread -lurcu
4TARGETS = main 4TARGETS = main idr-test multiorder
5OFILES = main.o radix-tree.o linux.o test.o tag_check.o find_next_bit.o \ 5CORE_OFILES := radix-tree.o idr.o linux.o test.o find_bit.o
6 regression1.o regression2.o regression3.o multiorder.o \ 6OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \
7 iteration_check.o benchmark.o 7 tag_check.o multiorder.o idr-test.o iteration_check.o benchmark.o
8 8
9ifdef BENCHMARK 9ifndef SHIFT
10 CFLAGS += -DBENCHMARK=1 10 SHIFT=3
11endif 11endif
12 12
13targets: $(TARGETS) 13targets: mapshift $(TARGETS)
14 14
15main: $(OFILES) 15main: $(OFILES)
16 $(CC) $(CFLAGS) $(LDFLAGS) $(OFILES) -o main 16 $(CC) $(CFLAGS) $(LDFLAGS) $^ -o main
17
18idr-test: idr-test.o $(CORE_OFILES)
19 $(CC) $(CFLAGS) $(LDFLAGS) $^ -o idr-test
20
21multiorder: multiorder.o $(CORE_OFILES)
22 $(CC) $(CFLAGS) $(LDFLAGS) $^ -o multiorder
17 23
18clean: 24clean:
19 $(RM) -f $(TARGETS) *.o radix-tree.c 25 $(RM) $(TARGETS) *.o radix-tree.c idr.c generated/map-shift.h
20 26
21find_next_bit.o: ../../lib/find_bit.c 27vpath %.c ../../lib
22 $(CC) $(CFLAGS) -c -o $@ $<
23 28
24$(OFILES): *.h */*.h \ 29$(OFILES): *.h */*.h generated/map-shift.h \
25 ../../include/linux/*.h \ 30 ../../include/linux/*.h \
26 ../../../include/linux/radix-tree.h 31 ../../include/asm/*.h \
32 ../../../include/linux/radix-tree.h \
33 ../../../include/linux/idr.h
27 34
28radix-tree.c: ../../../lib/radix-tree.c 35radix-tree.c: ../../../lib/radix-tree.c
29 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@ 36 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@
37
38idr.c: ../../../lib/idr.c
39 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@
40
41.PHONY: mapshift
42
43mapshift:
44 @if ! grep -qw $(SHIFT) generated/map-shift.h; then \
45 echo "#define RADIX_TREE_MAP_SHIFT $(SHIFT)" > \
46 generated/map-shift.h; \
47 fi
diff --git a/tools/testing/radix-tree/benchmark.c b/tools/testing/radix-tree/benchmark.c
index 215ca86c7605..9b09ddfe462f 100644
--- a/tools/testing/radix-tree/benchmark.c
+++ b/tools/testing/radix-tree/benchmark.c
@@ -71,7 +71,7 @@ static void benchmark_size(unsigned long size, unsigned long step, int order)
71 tagged = benchmark_iter(&tree, true); 71 tagged = benchmark_iter(&tree, true);
72 normal = benchmark_iter(&tree, false); 72 normal = benchmark_iter(&tree, false);
73 73
74 printf("Size %ld, step %6ld, order %d tagged %10lld ns, normal %10lld ns\n", 74 printv(2, "Size %ld, step %6ld, order %d tagged %10lld ns, normal %10lld ns\n",
75 size, step, order, tagged, normal); 75 size, step, order, tagged, normal);
76 76
77 item_kill_tree(&tree); 77 item_kill_tree(&tree);
@@ -85,8 +85,8 @@ void benchmark(void)
85 128, 256, 512, 12345, 0}; 85 128, 256, 512, 12345, 0};
86 int c, s; 86 int c, s;
87 87
88 printf("starting benchmarks\n"); 88 printv(1, "starting benchmarks\n");
89 printf("RADIX_TREE_MAP_SHIFT = %d\n", RADIX_TREE_MAP_SHIFT); 89 printv(1, "RADIX_TREE_MAP_SHIFT = %d\n", RADIX_TREE_MAP_SHIFT);
90 90
91 for (c = 0; size[c]; c++) 91 for (c = 0; size[c]; c++)
92 for (s = 0; step[s]; s++) 92 for (s = 0; step[s]; s++)
diff --git a/tools/testing/radix-tree/generated/autoconf.h b/tools/testing/radix-tree/generated/autoconf.h
index ad18cf5a2a3a..cf88dc5b8832 100644
--- a/tools/testing/radix-tree/generated/autoconf.h
+++ b/tools/testing/radix-tree/generated/autoconf.h
@@ -1,3 +1 @@
1#define CONFIG_RADIX_TREE_MULTIORDER 1 #define CONFIG_RADIX_TREE_MULTIORDER 1
2#define CONFIG_SHMEM 1
3#define CONFIG_SWAP 1
diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c
new file mode 100644
index 000000000000..a26098c6123d
--- /dev/null
+++ b/tools/testing/radix-tree/idr-test.c
@@ -0,0 +1,444 @@
1/*
2 * idr-test.c: Test the IDR API
3 * Copyright (c) 2016 Matthew Wilcox <willy@infradead.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 */
14#include <linux/bitmap.h>
15#include <linux/idr.h>
16#include <linux/slab.h>
17#include <linux/kernel.h>
18#include <linux/errno.h>
19
20#include "test.h"
21
22#define DUMMY_PTR ((void *)0x12)
23
24int item_idr_free(int id, void *p, void *data)
25{
26 struct item *item = p;
27 assert(item->index == id);
28 free(p);
29
30 return 0;
31}
32
33void item_idr_remove(struct idr *idr, int id)
34{
35 struct item *item = idr_find(idr, id);
36 assert(item->index == id);
37 idr_remove(idr, id);
38 free(item);
39}
40
41void idr_alloc_test(void)
42{
43 unsigned long i;
44 DEFINE_IDR(idr);
45
46 assert(idr_alloc_cyclic(&idr, DUMMY_PTR, 0, 0x4000, GFP_KERNEL) == 0);
47 assert(idr_alloc_cyclic(&idr, DUMMY_PTR, 0x3ffd, 0x4000, GFP_KERNEL) == 0x3ffd);
48 idr_remove(&idr, 0x3ffd);
49 idr_remove(&idr, 0);
50
51 for (i = 0x3ffe; i < 0x4003; i++) {
52 int id;
53 struct item *item;
54
55 if (i < 0x4000)
56 item = item_create(i, 0);
57 else
58 item = item_create(i - 0x3fff, 0);
59
60 id = idr_alloc_cyclic(&idr, item, 1, 0x4000, GFP_KERNEL);
61 assert(id == item->index);
62 }
63
64 idr_for_each(&idr, item_idr_free, &idr);
65 idr_destroy(&idr);
66}
67
68void idr_replace_test(void)
69{
70 DEFINE_IDR(idr);
71
72 idr_alloc(&idr, (void *)-1, 10, 11, GFP_KERNEL);
73 idr_replace(&idr, &idr, 10);
74
75 idr_destroy(&idr);
76}
77
78/*
79 * Unlike the radix tree, you can put a NULL pointer -- with care -- into
80 * the IDR. Some interfaces, like idr_find() do not distinguish between
81 * "present, value is NULL" and "not present", but that's exactly what some
82 * users want.
83 */
84void idr_null_test(void)
85{
86 int i;
87 DEFINE_IDR(idr);
88
89 assert(idr_is_empty(&idr));
90
91 assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == 0);
92 assert(!idr_is_empty(&idr));
93 idr_remove(&idr, 0);
94 assert(idr_is_empty(&idr));
95
96 assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == 0);
97 assert(!idr_is_empty(&idr));
98 idr_destroy(&idr);
99 assert(idr_is_empty(&idr));
100
101 for (i = 0; i < 10; i++) {
102 assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == i);
103 }
104
105 assert(idr_replace(&idr, DUMMY_PTR, 3) == NULL);
106 assert(idr_replace(&idr, DUMMY_PTR, 4) == NULL);
107 assert(idr_replace(&idr, NULL, 4) == DUMMY_PTR);
108 assert(idr_replace(&idr, DUMMY_PTR, 11) == ERR_PTR(-ENOENT));
109 idr_remove(&idr, 5);
110 assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == 5);
111 idr_remove(&idr, 5);
112
113 for (i = 0; i < 9; i++) {
114 idr_remove(&idr, i);
115 assert(!idr_is_empty(&idr));
116 }
117 idr_remove(&idr, 8);
118 assert(!idr_is_empty(&idr));
119 idr_remove(&idr, 9);
120 assert(idr_is_empty(&idr));
121
122 assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == 0);
123 assert(idr_replace(&idr, DUMMY_PTR, 3) == ERR_PTR(-ENOENT));
124 assert(idr_replace(&idr, DUMMY_PTR, 0) == NULL);
125 assert(idr_replace(&idr, NULL, 0) == DUMMY_PTR);
126
127 idr_destroy(&idr);
128 assert(idr_is_empty(&idr));
129
130 for (i = 1; i < 10; i++) {
131 assert(idr_alloc(&idr, NULL, 1, 0, GFP_KERNEL) == i);
132 }
133
134 idr_destroy(&idr);
135 assert(idr_is_empty(&idr));
136}
137
138void idr_nowait_test(void)
139{
140 unsigned int i;
141 DEFINE_IDR(idr);
142
143 idr_preload(GFP_KERNEL);
144
145 for (i = 0; i < 3; i++) {
146 struct item *item = item_create(i, 0);
147 assert(idr_alloc(&idr, item, i, i + 1, GFP_NOWAIT) == i);
148 }
149
150 idr_preload_end();
151
152 idr_for_each(&idr, item_idr_free, &idr);
153 idr_destroy(&idr);
154}
155
156void idr_checks(void)
157{
158 unsigned long i;
159 DEFINE_IDR(idr);
160
161 for (i = 0; i < 10000; i++) {
162 struct item *item = item_create(i, 0);
163 assert(idr_alloc(&idr, item, 0, 20000, GFP_KERNEL) == i);
164 }
165
166 assert(idr_alloc(&idr, DUMMY_PTR, 5, 30, GFP_KERNEL) < 0);
167
168 for (i = 0; i < 5000; i++)
169 item_idr_remove(&idr, i);
170
171 idr_remove(&idr, 3);
172
173 idr_for_each(&idr, item_idr_free, &idr);
174 idr_destroy(&idr);
175
176 assert(idr_is_empty(&idr));
177
178 idr_remove(&idr, 3);
179 idr_remove(&idr, 0);
180
181 for (i = INT_MAX - 3UL; i < INT_MAX + 1UL; i++) {
182 struct item *item = item_create(i, 0);
183 assert(idr_alloc(&idr, item, i, i + 10, GFP_KERNEL) == i);
184 }
185 assert(idr_alloc(&idr, DUMMY_PTR, i - 2, i, GFP_KERNEL) == -ENOSPC);
186
187 idr_for_each(&idr, item_idr_free, &idr);
188 idr_destroy(&idr);
189 idr_destroy(&idr);
190
191 assert(idr_is_empty(&idr));
192
193 for (i = 1; i < 10000; i++) {
194 struct item *item = item_create(i, 0);
195 assert(idr_alloc(&idr, item, 1, 20000, GFP_KERNEL) == i);
196 }
197
198 idr_for_each(&idr, item_idr_free, &idr);
199 idr_destroy(&idr);
200
201 idr_replace_test();
202 idr_alloc_test();
203 idr_null_test();
204 idr_nowait_test();
205}
206
207/*
208 * Check that we get the correct error when we run out of memory doing
209 * allocations. To ensure we run out of memory, just "forget" to preload.
210 * The first test is for not having a bitmap available, and the second test
211 * is for not being able to allocate a level of the radix tree.
212 */
213void ida_check_nomem(void)
214{
215 DEFINE_IDA(ida);
216 int id, err;
217
218 err = ida_get_new_above(&ida, 256, &id);
219 assert(err == -EAGAIN);
220 err = ida_get_new_above(&ida, 1UL << 30, &id);
221 assert(err == -EAGAIN);
222}
223
224/*
225 * Check what happens when we fill a leaf and then delete it. This may
226 * discover mishandling of IDR_FREE.
227 */
228void ida_check_leaf(void)
229{
230 DEFINE_IDA(ida);
231 int id;
232 unsigned long i;
233
234 for (i = 0; i < IDA_BITMAP_BITS; i++) {
235 assert(ida_pre_get(&ida, GFP_KERNEL));
236 assert(!ida_get_new(&ida, &id));
237 assert(id == i);
238 }
239
240 ida_destroy(&ida);
241 assert(ida_is_empty(&ida));
242
243 assert(ida_pre_get(&ida, GFP_KERNEL));
244 assert(!ida_get_new(&ida, &id));
245 assert(id == 0);
246 ida_destroy(&ida);
247 assert(ida_is_empty(&ida));
248}
249
250/*
251 * Check handling of conversions between exceptional entries and full bitmaps.
252 */
253void ida_check_conv(void)
254{
255 DEFINE_IDA(ida);
256 int id;
257 unsigned long i;
258
259 for (i = 0; i < IDA_BITMAP_BITS * 2; i += IDA_BITMAP_BITS) {
260 assert(ida_pre_get(&ida, GFP_KERNEL));
261 assert(!ida_get_new_above(&ida, i + 1, &id));
262 assert(id == i + 1);
263 assert(!ida_get_new_above(&ida, i + BITS_PER_LONG, &id));
264 assert(id == i + BITS_PER_LONG);
265 ida_remove(&ida, i + 1);
266 ida_remove(&ida, i + BITS_PER_LONG);
267 assert(ida_is_empty(&ida));
268 }
269
270 assert(ida_pre_get(&ida, GFP_KERNEL));
271
272 for (i = 0; i < IDA_BITMAP_BITS * 2; i++) {
273 assert(ida_pre_get(&ida, GFP_KERNEL));
274 assert(!ida_get_new(&ida, &id));
275 assert(id == i);
276 }
277
278 for (i = IDA_BITMAP_BITS * 2; i > 0; i--) {
279 ida_remove(&ida, i - 1);
280 }
281 assert(ida_is_empty(&ida));
282
283 for (i = 0; i < IDA_BITMAP_BITS + BITS_PER_LONG - 4; i++) {
284 assert(ida_pre_get(&ida, GFP_KERNEL));
285 assert(!ida_get_new(&ida, &id));
286 assert(id == i);
287 }
288
289 for (i = IDA_BITMAP_BITS + BITS_PER_LONG - 4; i > 0; i--) {
290 ida_remove(&ida, i - 1);
291 }
292 assert(ida_is_empty(&ida));
293
294 radix_tree_cpu_dead(1);
295 for (i = 0; i < 1000000; i++) {
296 int err = ida_get_new(&ida, &id);
297 if (err == -EAGAIN) {
298 assert((i % IDA_BITMAP_BITS) == (BITS_PER_LONG - 2));
299 assert(ida_pre_get(&ida, GFP_KERNEL));
300 err = ida_get_new(&ida, &id);
301 } else {
302 assert((i % IDA_BITMAP_BITS) != (BITS_PER_LONG - 2));
303 }
304 assert(!err);
305 assert(id == i);
306 }
307 ida_destroy(&ida);
308}
309
310/*
311 * Check allocations up to and slightly above the maximum allowed (2^31-1) ID.
312 * Allocating up to 2^31-1 should succeed, and then allocating the next one
313 * should fail.
314 */
315void ida_check_max(void)
316{
317 DEFINE_IDA(ida);
318 int id, err;
319 unsigned long i, j;
320
321 for (j = 1; j < 65537; j *= 2) {
322 unsigned long base = (1UL << 31) - j;
323 for (i = 0; i < j; i++) {
324 assert(ida_pre_get(&ida, GFP_KERNEL));
325 assert(!ida_get_new_above(&ida, base, &id));
326 assert(id == base + i);
327 }
328 assert(ida_pre_get(&ida, GFP_KERNEL));
329 err = ida_get_new_above(&ida, base, &id);
330 assert(err == -ENOSPC);
331 ida_destroy(&ida);
332 assert(ida_is_empty(&ida));
333 rcu_barrier();
334 }
335}
336
337void ida_check_random(void)
338{
339 DEFINE_IDA(ida);
340 DECLARE_BITMAP(bitmap, 2048);
341 int id;
342 unsigned int i;
343 time_t s = time(NULL);
344
345 repeat:
346 memset(bitmap, 0, sizeof(bitmap));
347 for (i = 0; i < 100000; i++) {
348 int i = rand();
349 int bit = i & 2047;
350 if (test_bit(bit, bitmap)) {
351 __clear_bit(bit, bitmap);
352 ida_remove(&ida, bit);
353 } else {
354 __set_bit(bit, bitmap);
355 ida_pre_get(&ida, GFP_KERNEL);
356 assert(!ida_get_new_above(&ida, bit, &id));
357 assert(id == bit);
358 }
359 }
360 ida_destroy(&ida);
361 if (time(NULL) < s + 10)
362 goto repeat;
363}
364
365void ida_checks(void)
366{
367 DEFINE_IDA(ida);
368 int id;
369 unsigned long i;
370
371 radix_tree_cpu_dead(1);
372 ida_check_nomem();
373
374 for (i = 0; i < 10000; i++) {
375 assert(ida_pre_get(&ida, GFP_KERNEL));
376 assert(!ida_get_new(&ida, &id));
377 assert(id == i);
378 }
379
380 ida_remove(&ida, 20);
381 ida_remove(&ida, 21);
382 for (i = 0; i < 3; i++) {
383 assert(ida_pre_get(&ida, GFP_KERNEL));
384 assert(!ida_get_new(&ida, &id));
385 if (i == 2)
386 assert(id == 10000);
387 }
388
389 for (i = 0; i < 5000; i++)
390 ida_remove(&ida, i);
391
392 assert(ida_pre_get(&ida, GFP_KERNEL));
393 assert(!ida_get_new_above(&ida, 5000, &id));
394 assert(id == 10001);
395
396 ida_destroy(&ida);
397
398 assert(ida_is_empty(&ida));
399
400 assert(ida_pre_get(&ida, GFP_KERNEL));
401 assert(!ida_get_new_above(&ida, 1, &id));
402 assert(id == 1);
403
404 ida_remove(&ida, id);
405 assert(ida_is_empty(&ida));
406 ida_destroy(&ida);
407 assert(ida_is_empty(&ida));
408
409 assert(ida_pre_get(&ida, GFP_KERNEL));
410 assert(!ida_get_new_above(&ida, 1, &id));
411 ida_destroy(&ida);
412 assert(ida_is_empty(&ida));
413
414 assert(ida_pre_get(&ida, GFP_KERNEL));
415 assert(!ida_get_new_above(&ida, 1, &id));
416 assert(id == 1);
417 assert(ida_pre_get(&ida, GFP_KERNEL));
418 assert(!ida_get_new_above(&ida, 1025, &id));
419 assert(id == 1025);
420 assert(ida_pre_get(&ida, GFP_KERNEL));
421 assert(!ida_get_new_above(&ida, 10000, &id));
422 assert(id == 10000);
423 ida_remove(&ida, 1025);
424 ida_destroy(&ida);
425 assert(ida_is_empty(&ida));
426
427 ida_check_leaf();
428 ida_check_max();
429 ida_check_conv();
430 ida_check_random();
431
432 radix_tree_cpu_dead(1);
433}
434
435int __weak main(void)
436{
437 radix_tree_init();
438 idr_checks();
439 ida_checks();
440 rcu_barrier();
441 if (nr_allocated)
442 printf("nr_allocated = %d\n", nr_allocated);
443 return 0;
444}
diff --git a/tools/testing/radix-tree/iteration_check.c b/tools/testing/radix-tree/iteration_check.c
index 7572b7ed930e..a92bab513701 100644
--- a/tools/testing/radix-tree/iteration_check.c
+++ b/tools/testing/radix-tree/iteration_check.c
@@ -177,7 +177,7 @@ void iteration_test(unsigned order, unsigned test_duration)
177{ 177{
178 int i; 178 int i;
179 179
180 printf("Running %siteration tests for %d seconds\n", 180 printv(1, "Running %siteration tests for %d seconds\n",
181 order > 0 ? "multiorder " : "", test_duration); 181 order > 0 ? "multiorder " : "", test_duration);
182 182
183 max_order = order; 183 max_order = order;
diff --git a/tools/testing/radix-tree/linux.c b/tools/testing/radix-tree/linux.c
index d31ea7c9abec..cf48c8473f48 100644
--- a/tools/testing/radix-tree/linux.c
+++ b/tools/testing/radix-tree/linux.c
@@ -5,7 +5,7 @@
5#include <unistd.h> 5#include <unistd.h>
6#include <assert.h> 6#include <assert.h>
7 7
8#include <linux/mempool.h> 8#include <linux/gfp.h>
9#include <linux/poison.h> 9#include <linux/poison.h>
10#include <linux/slab.h> 10#include <linux/slab.h>
11#include <linux/radix-tree.h> 11#include <linux/radix-tree.h>
@@ -13,6 +13,8 @@
13 13
14int nr_allocated; 14int nr_allocated;
15int preempt_count; 15int preempt_count;
16int kmalloc_verbose;
17int test_verbose;
16 18
17struct kmem_cache { 19struct kmem_cache {
18 pthread_mutex_t lock; 20 pthread_mutex_t lock;
@@ -22,27 +24,6 @@ struct kmem_cache {
22 void (*ctor)(void *); 24 void (*ctor)(void *);
23}; 25};
24 26
25void *mempool_alloc(mempool_t *pool, int gfp_mask)
26{
27 return pool->alloc(gfp_mask, pool->data);
28}
29
30void mempool_free(void *element, mempool_t *pool)
31{
32 pool->free(element, pool->data);
33}
34
35mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
36 mempool_free_t *free_fn, void *pool_data)
37{
38 mempool_t *ret = malloc(sizeof(*ret));
39
40 ret->alloc = alloc_fn;
41 ret->free = free_fn;
42 ret->data = pool_data;
43 return ret;
44}
45
46void *kmem_cache_alloc(struct kmem_cache *cachep, int flags) 27void *kmem_cache_alloc(struct kmem_cache *cachep, int flags)
47{ 28{
48 struct radix_tree_node *node; 29 struct radix_tree_node *node;
@@ -54,9 +35,9 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, int flags)
54 if (cachep->nr_objs) { 35 if (cachep->nr_objs) {
55 cachep->nr_objs--; 36 cachep->nr_objs--;
56 node = cachep->objs; 37 node = cachep->objs;
57 cachep->objs = node->private_data; 38 cachep->objs = node->parent;
58 pthread_mutex_unlock(&cachep->lock); 39 pthread_mutex_unlock(&cachep->lock);
59 node->private_data = NULL; 40 node->parent = NULL;
60 } else { 41 } else {
61 pthread_mutex_unlock(&cachep->lock); 42 pthread_mutex_unlock(&cachep->lock);
62 node = malloc(cachep->size); 43 node = malloc(cachep->size);
@@ -65,6 +46,8 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, int flags)
65 } 46 }
66 47
67 uatomic_inc(&nr_allocated); 48 uatomic_inc(&nr_allocated);
49 if (kmalloc_verbose)
50 printf("Allocating %p from slab\n", node);
68 return node; 51 return node;
69} 52}
70 53
@@ -72,6 +55,8 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp)
72{ 55{
73 assert(objp); 56 assert(objp);
74 uatomic_dec(&nr_allocated); 57 uatomic_dec(&nr_allocated);
58 if (kmalloc_verbose)
59 printf("Freeing %p to slab\n", objp);
75 pthread_mutex_lock(&cachep->lock); 60 pthread_mutex_lock(&cachep->lock);
76 if (cachep->nr_objs > 10) { 61 if (cachep->nr_objs > 10) {
77 memset(objp, POISON_FREE, cachep->size); 62 memset(objp, POISON_FREE, cachep->size);
@@ -79,7 +64,7 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp)
79 } else { 64 } else {
80 struct radix_tree_node *node = objp; 65 struct radix_tree_node *node = objp;
81 cachep->nr_objs++; 66 cachep->nr_objs++;
82 node->private_data = cachep->objs; 67 node->parent = cachep->objs;
83 cachep->objs = node; 68 cachep->objs = node;
84 } 69 }
85 pthread_mutex_unlock(&cachep->lock); 70 pthread_mutex_unlock(&cachep->lock);
@@ -89,6 +74,8 @@ void *kmalloc(size_t size, gfp_t gfp)
89{ 74{
90 void *ret = malloc(size); 75 void *ret = malloc(size);
91 uatomic_inc(&nr_allocated); 76 uatomic_inc(&nr_allocated);
77 if (kmalloc_verbose)
78 printf("Allocating %p from malloc\n", ret);
92 return ret; 79 return ret;
93} 80}
94 81
@@ -97,6 +84,8 @@ void kfree(void *p)
97 if (!p) 84 if (!p)
98 return; 85 return;
99 uatomic_dec(&nr_allocated); 86 uatomic_dec(&nr_allocated);
87 if (kmalloc_verbose)
88 printf("Freeing %p to malloc\n", p);
100 free(p); 89 free(p);
101} 90}
102 91
diff --git a/tools/testing/radix-tree/linux/bitops.h b/tools/testing/radix-tree/linux/bitops.h
deleted file mode 100644
index a13e9bc76eec..000000000000
--- a/tools/testing/radix-tree/linux/bitops.h
+++ /dev/null
@@ -1,160 +0,0 @@
1#ifndef _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
2#define _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
3
4#include <linux/types.h>
5#include <linux/bitops/find.h>
6#include <linux/bitops/hweight.h>
7#include <linux/kernel.h>
8
9#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
10#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
11#define BITS_PER_BYTE 8
12#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
13
14/**
15 * __set_bit - Set a bit in memory
16 * @nr: the bit to set
17 * @addr: the address to start counting from
18 *
19 * Unlike set_bit(), this function is non-atomic and may be reordered.
20 * If it's called on the same region of memory simultaneously, the effect
21 * may be that only one operation succeeds.
22 */
23static inline void __set_bit(int nr, volatile unsigned long *addr)
24{
25 unsigned long mask = BIT_MASK(nr);
26 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
27
28 *p |= mask;
29}
30
31static inline void __clear_bit(int nr, volatile unsigned long *addr)
32{
33 unsigned long mask = BIT_MASK(nr);
34 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
35
36 *p &= ~mask;
37}
38
39/**
40 * __change_bit - Toggle a bit in memory
41 * @nr: the bit to change
42 * @addr: the address to start counting from
43 *
44 * Unlike change_bit(), this function is non-atomic and may be reordered.
45 * If it's called on the same region of memory simultaneously, the effect
46 * may be that only one operation succeeds.
47 */
48static inline void __change_bit(int nr, volatile unsigned long *addr)
49{
50 unsigned long mask = BIT_MASK(nr);
51 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
52
53 *p ^= mask;
54}
55
56/**
57 * __test_and_set_bit - Set a bit and return its old value
58 * @nr: Bit to set
59 * @addr: Address to count from
60 *
61 * This operation is non-atomic and can be reordered.
62 * If two examples of this operation race, one can appear to succeed
63 * but actually fail. You must protect multiple accesses with a lock.
64 */
65static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
66{
67 unsigned long mask = BIT_MASK(nr);
68 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
69 unsigned long old = *p;
70
71 *p = old | mask;
72 return (old & mask) != 0;
73}
74
75/**
76 * __test_and_clear_bit - Clear a bit and return its old value
77 * @nr: Bit to clear
78 * @addr: Address to count from
79 *
80 * This operation is non-atomic and can be reordered.
81 * If two examples of this operation race, one can appear to succeed
82 * but actually fail. You must protect multiple accesses with a lock.
83 */
84static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
85{
86 unsigned long mask = BIT_MASK(nr);
87 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
88 unsigned long old = *p;
89
90 *p = old & ~mask;
91 return (old & mask) != 0;
92}
93
94/* WARNING: non atomic and it can be reordered! */
95static inline int __test_and_change_bit(int nr,
96 volatile unsigned long *addr)
97{
98 unsigned long mask = BIT_MASK(nr);
99 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
100 unsigned long old = *p;
101
102 *p = old ^ mask;
103 return (old & mask) != 0;
104}
105
106/**
107 * test_bit - Determine whether a bit is set
108 * @nr: bit number to test
109 * @addr: Address to start counting from
110 */
111static inline int test_bit(int nr, const volatile unsigned long *addr)
112{
113 return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
114}
115
116/**
117 * __ffs - find first bit in word.
118 * @word: The word to search
119 *
120 * Undefined if no bit exists, so code should check against 0 first.
121 */
122static inline unsigned long __ffs(unsigned long word)
123{
124 int num = 0;
125
126 if ((word & 0xffffffff) == 0) {
127 num += 32;
128 word >>= 32;
129 }
130 if ((word & 0xffff) == 0) {
131 num += 16;
132 word >>= 16;
133 }
134 if ((word & 0xff) == 0) {
135 num += 8;
136 word >>= 8;
137 }
138 if ((word & 0xf) == 0) {
139 num += 4;
140 word >>= 4;
141 }
142 if ((word & 0x3) == 0) {
143 num += 2;
144 word >>= 2;
145 }
146 if ((word & 0x1) == 0)
147 num += 1;
148 return num;
149}
150
151unsigned long find_next_bit(const unsigned long *addr,
152 unsigned long size,
153 unsigned long offset);
154
155static inline unsigned long hweight_long(unsigned long w)
156{
157 return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
158}
159
160#endif /* _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ */
diff --git a/tools/testing/radix-tree/linux/bitops/__ffs.h b/tools/testing/radix-tree/linux/bitops/__ffs.h
deleted file mode 100644
index 9a3274aecf83..000000000000
--- a/tools/testing/radix-tree/linux/bitops/__ffs.h
+++ /dev/null
@@ -1,43 +0,0 @@
1#ifndef _ASM_GENERIC_BITOPS___FFS_H_
2#define _ASM_GENERIC_BITOPS___FFS_H_
3
4#include <asm/types.h>
5
6/**
7 * __ffs - find first bit in word.
8 * @word: The word to search
9 *
10 * Undefined if no bit exists, so code should check against 0 first.
11 */
12static inline unsigned long __ffs(unsigned long word)
13{
14 int num = 0;
15
16#if BITS_PER_LONG == 64
17 if ((word & 0xffffffff) == 0) {
18 num += 32;
19 word >>= 32;
20 }
21#endif
22 if ((word & 0xffff) == 0) {
23 num += 16;
24 word >>= 16;
25 }
26 if ((word & 0xff) == 0) {
27 num += 8;
28 word >>= 8;
29 }
30 if ((word & 0xf) == 0) {
31 num += 4;
32 word >>= 4;
33 }
34 if ((word & 0x3) == 0) {
35 num += 2;
36 word >>= 2;
37 }
38 if ((word & 0x1) == 0)
39 num += 1;
40 return num;
41}
42
43#endif /* _ASM_GENERIC_BITOPS___FFS_H_ */
diff --git a/tools/testing/radix-tree/linux/bitops/ffs.h b/tools/testing/radix-tree/linux/bitops/ffs.h
deleted file mode 100644
index fbbb43af7dc0..000000000000
--- a/tools/testing/radix-tree/linux/bitops/ffs.h
+++ /dev/null
@@ -1,41 +0,0 @@
1#ifndef _ASM_GENERIC_BITOPS_FFS_H_
2#define _ASM_GENERIC_BITOPS_FFS_H_
3
4/**
5 * ffs - find first bit set
6 * @x: the word to search
7 *
8 * This is defined the same way as
9 * the libc and compiler builtin ffs routines, therefore
10 * differs in spirit from the above ffz (man ffs).
11 */
12static inline int ffs(int x)
13{
14 int r = 1;
15
16 if (!x)
17 return 0;
18 if (!(x & 0xffff)) {
19 x >>= 16;
20 r += 16;
21 }
22 if (!(x & 0xff)) {
23 x >>= 8;
24 r += 8;
25 }
26 if (!(x & 0xf)) {
27 x >>= 4;
28 r += 4;
29 }
30 if (!(x & 3)) {
31 x >>= 2;
32 r += 2;
33 }
34 if (!(x & 1)) {
35 x >>= 1;
36 r += 1;
37 }
38 return r;
39}
40
41#endif /* _ASM_GENERIC_BITOPS_FFS_H_ */
diff --git a/tools/testing/radix-tree/linux/bitops/ffz.h b/tools/testing/radix-tree/linux/bitops/ffz.h
deleted file mode 100644
index 6744bd4cdf46..000000000000
--- a/tools/testing/radix-tree/linux/bitops/ffz.h
+++ /dev/null
@@ -1,12 +0,0 @@
1#ifndef _ASM_GENERIC_BITOPS_FFZ_H_
2#define _ASM_GENERIC_BITOPS_FFZ_H_
3
4/*
5 * ffz - find first zero in word.
6 * @word: The word to search
7 *
8 * Undefined if no zero exists, so code should check against ~0UL first.
9 */
10#define ffz(x) __ffs(~(x))
11
12#endif /* _ASM_GENERIC_BITOPS_FFZ_H_ */
diff --git a/tools/testing/radix-tree/linux/bitops/find.h b/tools/testing/radix-tree/linux/bitops/find.h
deleted file mode 100644
index 72a51e5a12ef..000000000000
--- a/tools/testing/radix-tree/linux/bitops/find.h
+++ /dev/null
@@ -1,13 +0,0 @@
1#ifndef _ASM_GENERIC_BITOPS_FIND_H_
2#define _ASM_GENERIC_BITOPS_FIND_H_
3
4extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
5 size, unsigned long offset);
6
7extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned
8 long size, unsigned long offset);
9
10#define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
11#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
12
13#endif /*_ASM_GENERIC_BITOPS_FIND_H_ */
diff --git a/tools/testing/radix-tree/linux/bitops/fls.h b/tools/testing/radix-tree/linux/bitops/fls.h
deleted file mode 100644
index 850859bc5069..000000000000
--- a/tools/testing/radix-tree/linux/bitops/fls.h
+++ /dev/null
@@ -1,41 +0,0 @@
1#ifndef _ASM_GENERIC_BITOPS_FLS_H_
2#define _ASM_GENERIC_BITOPS_FLS_H_
3
4/**
5 * fls - find last (most-significant) bit set
6 * @x: the word to search
7 *
8 * This is defined the same way as ffs.
9 * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
10 */
11
12static inline int fls(int x)
13{
14 int r = 32;
15
16 if (!x)
17 return 0;
18 if (!(x & 0xffff0000u)) {
19 x <<= 16;
20 r -= 16;
21 }
22 if (!(x & 0xff000000u)) {
23 x <<= 8;
24 r -= 8;
25 }
26 if (!(x & 0xf0000000u)) {
27 x <<= 4;
28 r -= 4;
29 }
30 if (!(x & 0xc0000000u)) {
31 x <<= 2;
32 r -= 2;
33 }
34 if (!(x & 0x80000000u)) {
35 x <<= 1;
36 r -= 1;
37 }
38 return r;
39}
40
41#endif /* _ASM_GENERIC_BITOPS_FLS_H_ */
diff --git a/tools/testing/radix-tree/linux/bitops/fls64.h b/tools/testing/radix-tree/linux/bitops/fls64.h
deleted file mode 100644
index 1b6b17ce2428..000000000000
--- a/tools/testing/radix-tree/linux/bitops/fls64.h
+++ /dev/null
@@ -1,14 +0,0 @@
1#ifndef _ASM_GENERIC_BITOPS_FLS64_H_
2#define _ASM_GENERIC_BITOPS_FLS64_H_
3
4#include <asm/types.h>
5
6static inline int fls64(__u64 x)
7{
8 __u32 h = x >> 32;
9 if (h)
10 return fls(h) + 32;
11 return fls(x);
12}
13
14#endif /* _ASM_GENERIC_BITOPS_FLS64_H_ */
diff --git a/tools/testing/radix-tree/linux/bitops/hweight.h b/tools/testing/radix-tree/linux/bitops/hweight.h
deleted file mode 100644
index fbbc383771da..000000000000
--- a/tools/testing/radix-tree/linux/bitops/hweight.h
+++ /dev/null
@@ -1,11 +0,0 @@
1#ifndef _ASM_GENERIC_BITOPS_HWEIGHT_H_
2#define _ASM_GENERIC_BITOPS_HWEIGHT_H_
3
4#include <asm/types.h>
5
6extern unsigned int hweight32(unsigned int w);
7extern unsigned int hweight16(unsigned int w);
8extern unsigned int hweight8(unsigned int w);
9extern unsigned long hweight64(__u64 w);
10
11#endif /* _ASM_GENERIC_BITOPS_HWEIGHT_H_ */
diff --git a/tools/testing/radix-tree/linux/bitops/le.h b/tools/testing/radix-tree/linux/bitops/le.h
deleted file mode 100644
index b9c7e5d2d2ad..000000000000
--- a/tools/testing/radix-tree/linux/bitops/le.h
+++ /dev/null
@@ -1,53 +0,0 @@
1#ifndef _ASM_GENERIC_BITOPS_LE_H_
2#define _ASM_GENERIC_BITOPS_LE_H_
3
4#include <asm/types.h>
5#include <asm/byteorder.h>
6
7#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
8#define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7)
9
10#if defined(__LITTLE_ENDIAN)
11
12#define generic_test_le_bit(nr, addr) test_bit(nr, addr)
13#define generic___set_le_bit(nr, addr) __set_bit(nr, addr)
14#define generic___clear_le_bit(nr, addr) __clear_bit(nr, addr)
15
16#define generic_test_and_set_le_bit(nr, addr) test_and_set_bit(nr, addr)
17#define generic_test_and_clear_le_bit(nr, addr) test_and_clear_bit(nr, addr)
18
19#define generic___test_and_set_le_bit(nr, addr) __test_and_set_bit(nr, addr)
20#define generic___test_and_clear_le_bit(nr, addr) __test_and_clear_bit(nr, addr)
21
22#define generic_find_next_zero_le_bit(addr, size, offset) find_next_zero_bit(addr, size, offset)
23
24#elif defined(__BIG_ENDIAN)
25
26#define generic_test_le_bit(nr, addr) \
27 test_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
28#define generic___set_le_bit(nr, addr) \
29 __set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
30#define generic___clear_le_bit(nr, addr) \
31 __clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
32
33#define generic_test_and_set_le_bit(nr, addr) \
34 test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
35#define generic_test_and_clear_le_bit(nr, addr) \
36 test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
37
38#define generic___test_and_set_le_bit(nr, addr) \
39 __test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
40#define generic___test_and_clear_le_bit(nr, addr) \
41 __test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
42
43extern unsigned long generic_find_next_zero_le_bit(const unsigned long *addr,
44 unsigned long size, unsigned long offset);
45
46#else
47#error "Please fix <asm/byteorder.h>"
48#endif
49
50#define generic_find_first_zero_le_bit(addr, size) \
51 generic_find_next_zero_le_bit((addr), (size), 0)
52
53#endif /* _ASM_GENERIC_BITOPS_LE_H_ */
diff --git a/tools/testing/radix-tree/linux/bitops/non-atomic.h b/tools/testing/radix-tree/linux/bitops/non-atomic.h
deleted file mode 100644
index 6a1bcb9d2c4a..000000000000
--- a/tools/testing/radix-tree/linux/bitops/non-atomic.h
+++ /dev/null
@@ -1,110 +0,0 @@
1#ifndef _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
2#define _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
3
4#include <asm/types.h>
5
6#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
7
8/**
9 * __set_bit - Set a bit in memory
10 * @nr: the bit to set
11 * @addr: the address to start counting from
12 *
13 * Unlike set_bit(), this function is non-atomic and may be reordered.
14 * If it's called on the same region of memory simultaneously, the effect
15 * may be that only one operation succeeds.
16 */
17static inline void __set_bit(int nr, volatile unsigned long *addr)
18{
19 unsigned long mask = BIT_MASK(nr);
20 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
21
22 *p |= mask;
23}
24
25static inline void __clear_bit(int nr, volatile unsigned long *addr)
26{
27 unsigned long mask = BIT_MASK(nr);
28 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
29
30 *p &= ~mask;
31}
32
33/**
34 * __change_bit - Toggle a bit in memory
35 * @nr: the bit to change
36 * @addr: the address to start counting from
37 *
38 * Unlike change_bit(), this function is non-atomic and may be reordered.
39 * If it's called on the same region of memory simultaneously, the effect
40 * may be that only one operation succeeds.
41 */
42static inline void __change_bit(int nr, volatile unsigned long *addr)
43{
44 unsigned long mask = BIT_MASK(nr);
45 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
46
47 *p ^= mask;
48}
49
50/**
51 * __test_and_set_bit - Set a bit and return its old value
52 * @nr: Bit to set
53 * @addr: Address to count from
54 *
55 * This operation is non-atomic and can be reordered.
56 * If two examples of this operation race, one can appear to succeed
57 * but actually fail. You must protect multiple accesses with a lock.
58 */
59static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
60{
61 unsigned long mask = BIT_MASK(nr);
62 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
63 unsigned long old = *p;
64
65 *p = old | mask;
66 return (old & mask) != 0;
67}
68
69/**
70 * __test_and_clear_bit - Clear a bit and return its old value
71 * @nr: Bit to clear
72 * @addr: Address to count from
73 *
74 * This operation is non-atomic and can be reordered.
75 * If two examples of this operation race, one can appear to succeed
76 * but actually fail. You must protect multiple accesses with a lock.
77 */
78static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
79{
80 unsigned long mask = BIT_MASK(nr);
81 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
82 unsigned long old = *p;
83
84 *p = old & ~mask;
85 return (old & mask) != 0;
86}
87
88/* WARNING: non atomic and it can be reordered! */
89static inline int __test_and_change_bit(int nr,
90 volatile unsigned long *addr)
91{
92 unsigned long mask = BIT_MASK(nr);
93 unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
94 unsigned long old = *p;
95
96 *p = old ^ mask;
97 return (old & mask) != 0;
98}
99
100/**
101 * test_bit - Determine whether a bit is set
102 * @nr: bit number to test
103 * @addr: Address to start counting from
104 */
105static inline int test_bit(int nr, const volatile unsigned long *addr)
106{
107 return 1UL & (addr[BITOP_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
108}
109
110#endif /* _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ */
diff --git a/tools/testing/radix-tree/linux/export.h b/tools/testing/radix-tree/linux/export.h
deleted file mode 100644
index b6afd131998d..000000000000
--- a/tools/testing/radix-tree/linux/export.h
+++ /dev/null
@@ -1,2 +0,0 @@
1
2#define EXPORT_SYMBOL(sym)
diff --git a/tools/testing/radix-tree/linux/gfp.h b/tools/testing/radix-tree/linux/gfp.h
index 5b09b2ce6c33..39a0dcb9475a 100644
--- a/tools/testing/radix-tree/linux/gfp.h
+++ b/tools/testing/radix-tree/linux/gfp.h
@@ -1,6 +1,8 @@
1#ifndef _GFP_H 1#ifndef _GFP_H
2#define _GFP_H 2#define _GFP_H
3 3
4#include <linux/types.h>
5
4#define __GFP_BITS_SHIFT 26 6#define __GFP_BITS_SHIFT 26
5#define __GFP_BITS_MASK ((gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) 7#define __GFP_BITS_MASK ((gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
6 8
@@ -13,10 +15,12 @@
13#define __GFP_DIRECT_RECLAIM 0x400000u 15#define __GFP_DIRECT_RECLAIM 0x400000u
14#define __GFP_KSWAPD_RECLAIM 0x2000000u 16#define __GFP_KSWAPD_RECLAIM 0x2000000u
15 17
16#define __GFP_RECLAIM (__GFP_DIRECT_RECLAIM|__GFP_KSWAPD_RECLAIM) 18#define __GFP_RECLAIM (__GFP_DIRECT_RECLAIM|__GFP_KSWAPD_RECLAIM)
19
20#define GFP_ATOMIC (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)
21#define GFP_KERNEL (__GFP_RECLAIM | __GFP_IO | __GFP_FS)
22#define GFP_NOWAIT (__GFP_KSWAPD_RECLAIM)
17 23
18#define GFP_ATOMIC (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)
19#define GFP_KERNEL (__GFP_RECLAIM | __GFP_IO | __GFP_FS)
20 24
21static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags) 25static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags)
22{ 26{
diff --git a/tools/testing/radix-tree/linux/idr.h b/tools/testing/radix-tree/linux/idr.h
new file mode 100644
index 000000000000..4e342f2e37cf
--- /dev/null
+++ b/tools/testing/radix-tree/linux/idr.h
@@ -0,0 +1 @@
#include "../../../../include/linux/idr.h"
diff --git a/tools/testing/radix-tree/linux/init.h b/tools/testing/radix-tree/linux/init.h
index 360cabb3c4e7..1bb0afc21309 100644
--- a/tools/testing/radix-tree/linux/init.h
+++ b/tools/testing/radix-tree/linux/init.h
@@ -1 +1 @@
/* An empty file stub that allows radix-tree.c to compile. */ #define __init
diff --git a/tools/testing/radix-tree/linux/kernel.h b/tools/testing/radix-tree/linux/kernel.h
index 9b43b4975d83..b21a77fddcf7 100644
--- a/tools/testing/radix-tree/linux/kernel.h
+++ b/tools/testing/radix-tree/linux/kernel.h
@@ -1,64 +1,21 @@
1#ifndef _KERNEL_H 1#ifndef _KERNEL_H
2#define _KERNEL_H 2#define _KERNEL_H
3 3
4#include <assert.h> 4#include "../../include/linux/kernel.h"
5#include <string.h> 5#include <string.h>
6#include <stdio.h> 6#include <stdio.h>
7#include <stddef.h>
8#include <limits.h> 7#include <limits.h>
9 8
10#include "../../include/linux/compiler.h" 9#include <linux/compiler.h>
11#include "../../include/linux/err.h" 10#include <linux/err.h>
11#include <linux/bitops.h>
12#include <linux/log2.h>
12#include "../../../include/linux/kconfig.h" 13#include "../../../include/linux/kconfig.h"
13 14
14#ifdef BENCHMARK
15#define RADIX_TREE_MAP_SHIFT 6
16#else
17#define RADIX_TREE_MAP_SHIFT 3
18#endif
19
20#ifndef NULL
21#define NULL 0
22#endif
23
24#define BUG_ON(expr) assert(!(expr))
25#define WARN_ON(expr) assert(!(expr))
26#define __init
27#define __must_check
28#define panic(expr)
29#define printk printf 15#define printk printf
30#define __force
31#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
32#define pr_debug printk 16#define pr_debug printk
33 17#define pr_cont printk
34#define smp_rmb() barrier()
35#define smp_wmb() barrier()
36#define cpu_relax() barrier()
37 18
38#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 19#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
39 20
40#define container_of(ptr, type, member) ({ \
41 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
42 (type *)( (char *)__mptr - offsetof(type, member) );})
43#define min(a, b) ((a) < (b) ? (a) : (b))
44
45#define cond_resched() sched_yield()
46
47static inline int in_interrupt(void)
48{
49 return 0;
50}
51
52/*
53 * This looks more complex than it should be. But we need to
54 * get the type for the ~ right in round_down (it needs to be
55 * as wide as the result!), and we want to evaluate the macro
56 * arguments just once each.
57 */
58#define __round_mask(x, y) ((__typeof__(x))((y)-1))
59#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
60#define round_down(x, y) ((x) & ~__round_mask(x, y))
61
62#define xchg(ptr, x) uatomic_xchg(ptr, x)
63
64#endif /* _KERNEL_H */ 21#endif /* _KERNEL_H */
diff --git a/tools/testing/radix-tree/linux/mempool.h b/tools/testing/radix-tree/linux/mempool.h
deleted file mode 100644
index 6a2dc55b41d6..000000000000
--- a/tools/testing/radix-tree/linux/mempool.h
+++ /dev/null
@@ -1,16 +0,0 @@
1
2#include <linux/slab.h>
3
4typedef void *(mempool_alloc_t)(int gfp_mask, void *pool_data);
5typedef void (mempool_free_t)(void *element, void *pool_data);
6
7typedef struct {
8 mempool_alloc_t *alloc;
9 mempool_free_t *free;
10 void *data;
11} mempool_t;
12
13void *mempool_alloc(mempool_t *pool, int gfp_mask);
14void mempool_free(void *element, mempool_t *pool);
15mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
16 mempool_free_t *free_fn, void *pool_data);
diff --git a/tools/testing/radix-tree/linux/percpu.h b/tools/testing/radix-tree/linux/percpu.h
index 5837f1d56f17..3ea01a1a88c2 100644
--- a/tools/testing/radix-tree/linux/percpu.h
+++ b/tools/testing/radix-tree/linux/percpu.h
@@ -1,7 +1,10 @@
1 1#define DECLARE_PER_CPU(type, val) extern type val
2#define DEFINE_PER_CPU(type, val) type val 2#define DEFINE_PER_CPU(type, val) type val
3 3
4#define __get_cpu_var(var) var 4#define __get_cpu_var(var) var
5#define this_cpu_ptr(var) var 5#define this_cpu_ptr(var) var
6#define this_cpu_read(var) var
7#define this_cpu_xchg(var, val) uatomic_xchg(&var, val)
8#define this_cpu_cmpxchg(var, old, new) uatomic_cmpxchg(&var, old, new)
6#define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); }) 9#define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); })
7#define per_cpu(var, cpu) (*per_cpu_ptr(&(var), cpu)) 10#define per_cpu(var, cpu) (*per_cpu_ptr(&(var), cpu))
diff --git a/tools/testing/radix-tree/linux/preempt.h b/tools/testing/radix-tree/linux/preempt.h
index 65c04c226965..35c5ac81529f 100644
--- a/tools/testing/radix-tree/linux/preempt.h
+++ b/tools/testing/radix-tree/linux/preempt.h
@@ -1,4 +1,14 @@
1#ifndef __LINUX_PREEMPT_H
2#define __LINUX_PREEMPT_H
3
1extern int preempt_count; 4extern int preempt_count;
2 5
3#define preempt_disable() uatomic_inc(&preempt_count) 6#define preempt_disable() uatomic_inc(&preempt_count)
4#define preempt_enable() uatomic_dec(&preempt_count) 7#define preempt_enable() uatomic_dec(&preempt_count)
8
9static inline int in_interrupt(void)
10{
11 return 0;
12}
13
14#endif /* __LINUX_PREEMPT_H */
diff --git a/tools/testing/radix-tree/linux/radix-tree.h b/tools/testing/radix-tree/linux/radix-tree.h
index ce694ddd4aea..bf1bb231f9b5 100644
--- a/tools/testing/radix-tree/linux/radix-tree.h
+++ b/tools/testing/radix-tree/linux/radix-tree.h
@@ -1 +1,26 @@
1#ifndef _TEST_RADIX_TREE_H
2#define _TEST_RADIX_TREE_H
3
4#include "generated/map-shift.h"
1#include "../../../../include/linux/radix-tree.h" 5#include "../../../../include/linux/radix-tree.h"
6
7extern int kmalloc_verbose;
8extern int test_verbose;
9
10static inline void trace_call_rcu(struct rcu_head *head,
11 void (*func)(struct rcu_head *head))
12{
13 if (kmalloc_verbose)
14 printf("Delaying free of %p to slab\n", (char *)head -
15 offsetof(struct radix_tree_node, rcu_head));
16 call_rcu(head, func);
17}
18
19#define printv(verbosity_level, fmt, ...) \
20 if(test_verbose >= verbosity_level) \
21 printf(fmt, ##__VA_ARGS__)
22
23#undef call_rcu
24#define call_rcu(x, y) trace_call_rcu(x, y)
25
26#endif /* _TEST_RADIX_TREE_H */
diff --git a/tools/testing/radix-tree/linux/types.h b/tools/testing/radix-tree/linux/types.h
deleted file mode 100644
index 8491d89873bb..000000000000
--- a/tools/testing/radix-tree/linux/types.h
+++ /dev/null
@@ -1,23 +0,0 @@
1#ifndef _TYPES_H
2#define _TYPES_H
3
4#include "../../include/linux/types.h"
5
6#define __rcu
7#define __read_mostly
8
9static inline void INIT_LIST_HEAD(struct list_head *list)
10{
11 list->next = list;
12 list->prev = list;
13}
14
15typedef struct {
16 unsigned int x;
17} spinlock_t;
18
19#define uninitialized_var(x) x = x
20
21#include <linux/gfp.h>
22
23#endif
diff --git a/tools/testing/radix-tree/main.c b/tools/testing/radix-tree/main.c
index f7e9801a6754..b829127d5670 100644
--- a/tools/testing/radix-tree/main.c
+++ b/tools/testing/radix-tree/main.c
@@ -3,6 +3,7 @@
3#include <unistd.h> 3#include <unistd.h>
4#include <time.h> 4#include <time.h>
5#include <assert.h> 5#include <assert.h>
6#include <limits.h>
6 7
7#include <linux/slab.h> 8#include <linux/slab.h>
8#include <linux/radix-tree.h> 9#include <linux/radix-tree.h>
@@ -67,7 +68,7 @@ void big_gang_check(bool long_run)
67 68
68 for (i = 0; i < (long_run ? 1000 : 3); i++) { 69 for (i = 0; i < (long_run ? 1000 : 3); i++) {
69 __big_gang_check(); 70 __big_gang_check();
70 printf("%d ", i); 71 printv(2, "%d ", i);
71 fflush(stdout); 72 fflush(stdout);
72 } 73 }
73} 74}
@@ -128,14 +129,19 @@ void check_copied_tags(struct radix_tree_root *tree, unsigned long start, unsign
128 putchar('.'); */ 129 putchar('.'); */
129 if (idx[i] < start || idx[i] > end) { 130 if (idx[i] < start || idx[i] > end) {
130 if (item_tag_get(tree, idx[i], totag)) { 131 if (item_tag_get(tree, idx[i], totag)) {
131 printf("%lu-%lu: %lu, tags %d-%d\n", start, end, idx[i], item_tag_get(tree, idx[i], fromtag), item_tag_get(tree, idx[i], totag)); 132 printv(2, "%lu-%lu: %lu, tags %d-%d\n", start,
133 end, idx[i], item_tag_get(tree, idx[i],
134 fromtag),
135 item_tag_get(tree, idx[i], totag));
132 } 136 }
133 assert(!item_tag_get(tree, idx[i], totag)); 137 assert(!item_tag_get(tree, idx[i], totag));
134 continue; 138 continue;
135 } 139 }
136 if (item_tag_get(tree, idx[i], fromtag) ^ 140 if (item_tag_get(tree, idx[i], fromtag) ^
137 item_tag_get(tree, idx[i], totag)) { 141 item_tag_get(tree, idx[i], totag)) {
138 printf("%lu-%lu: %lu, tags %d-%d\n", start, end, idx[i], item_tag_get(tree, idx[i], fromtag), item_tag_get(tree, idx[i], totag)); 142 printv(2, "%lu-%lu: %lu, tags %d-%d\n", start, end,
143 idx[i], item_tag_get(tree, idx[i], fromtag),
144 item_tag_get(tree, idx[i], totag));
139 } 145 }
140 assert(!(item_tag_get(tree, idx[i], fromtag) ^ 146 assert(!(item_tag_get(tree, idx[i], fromtag) ^
141 item_tag_get(tree, idx[i], totag))); 147 item_tag_get(tree, idx[i], totag)));
@@ -237,7 +243,7 @@ static void __locate_check(struct radix_tree_root *tree, unsigned long index,
237 item = item_lookup(tree, index); 243 item = item_lookup(tree, index);
238 index2 = find_item(tree, item); 244 index2 = find_item(tree, item);
239 if (index != index2) { 245 if (index != index2) {
240 printf("index %ld order %d inserted; found %ld\n", 246 printv(2, "index %ld order %d inserted; found %ld\n",
241 index, order, index2); 247 index, order, index2);
242 abort(); 248 abort();
243 } 249 }
@@ -288,43 +294,48 @@ static void single_thread_tests(bool long_run)
288{ 294{
289 int i; 295 int i;
290 296
291 printf("starting single_thread_tests: %d allocated, preempt %d\n", 297 printv(1, "starting single_thread_tests: %d allocated, preempt %d\n",
292 nr_allocated, preempt_count); 298 nr_allocated, preempt_count);
293 multiorder_checks(); 299 multiorder_checks();
294 rcu_barrier(); 300 rcu_barrier();
295 printf("after multiorder_check: %d allocated, preempt %d\n", 301 printv(2, "after multiorder_check: %d allocated, preempt %d\n",
296 nr_allocated, preempt_count); 302 nr_allocated, preempt_count);
297 locate_check(); 303 locate_check();
298 rcu_barrier(); 304 rcu_barrier();
299 printf("after locate_check: %d allocated, preempt %d\n", 305 printv(2, "after locate_check: %d allocated, preempt %d\n",
300 nr_allocated, preempt_count); 306 nr_allocated, preempt_count);
301 tag_check(); 307 tag_check();
302 rcu_barrier(); 308 rcu_barrier();
303 printf("after tag_check: %d allocated, preempt %d\n", 309 printv(2, "after tag_check: %d allocated, preempt %d\n",
304 nr_allocated, preempt_count); 310 nr_allocated, preempt_count);
305 gang_check(); 311 gang_check();
306 rcu_barrier(); 312 rcu_barrier();
307 printf("after gang_check: %d allocated, preempt %d\n", 313 printv(2, "after gang_check: %d allocated, preempt %d\n",
308 nr_allocated, preempt_count); 314 nr_allocated, preempt_count);
309 add_and_check(); 315 add_and_check();
310 rcu_barrier(); 316 rcu_barrier();
311 printf("after add_and_check: %d allocated, preempt %d\n", 317 printv(2, "after add_and_check: %d allocated, preempt %d\n",
312 nr_allocated, preempt_count); 318 nr_allocated, preempt_count);
313 dynamic_height_check(); 319 dynamic_height_check();
314 rcu_barrier(); 320 rcu_barrier();
315 printf("after dynamic_height_check: %d allocated, preempt %d\n", 321 printv(2, "after dynamic_height_check: %d allocated, preempt %d\n",
322 nr_allocated, preempt_count);
323 idr_checks();
324 ida_checks();
325 rcu_barrier();
326 printv(2, "after idr_checks: %d allocated, preempt %d\n",
316 nr_allocated, preempt_count); 327 nr_allocated, preempt_count);
317 big_gang_check(long_run); 328 big_gang_check(long_run);
318 rcu_barrier(); 329 rcu_barrier();
319 printf("after big_gang_check: %d allocated, preempt %d\n", 330 printv(2, "after big_gang_check: %d allocated, preempt %d\n",
320 nr_allocated, preempt_count); 331 nr_allocated, preempt_count);
321 for (i = 0; i < (long_run ? 2000 : 3); i++) { 332 for (i = 0; i < (long_run ? 2000 : 3); i++) {
322 copy_tag_check(); 333 copy_tag_check();
323 printf("%d ", i); 334 printv(2, "%d ", i);
324 fflush(stdout); 335 fflush(stdout);
325 } 336 }
326 rcu_barrier(); 337 rcu_barrier();
327 printf("after copy_tag_check: %d allocated, preempt %d\n", 338 printv(2, "after copy_tag_check: %d allocated, preempt %d\n",
328 nr_allocated, preempt_count); 339 nr_allocated, preempt_count);
329} 340}
330 341
@@ -334,24 +345,28 @@ int main(int argc, char **argv)
334 int opt; 345 int opt;
335 unsigned int seed = time(NULL); 346 unsigned int seed = time(NULL);
336 347
337 while ((opt = getopt(argc, argv, "ls:")) != -1) { 348 while ((opt = getopt(argc, argv, "ls:v")) != -1) {
338 if (opt == 'l') 349 if (opt == 'l')
339 long_run = true; 350 long_run = true;
340 else if (opt == 's') 351 else if (opt == 's')
341 seed = strtoul(optarg, NULL, 0); 352 seed = strtoul(optarg, NULL, 0);
353 else if (opt == 'v')
354 test_verbose++;
342 } 355 }
343 356
344 printf("random seed %u\n", seed); 357 printf("random seed %u\n", seed);
345 srand(seed); 358 srand(seed);
346 359
360 printf("running tests\n");
361
347 rcu_register_thread(); 362 rcu_register_thread();
348 radix_tree_init(); 363 radix_tree_init();
349 364
350 regression1_test(); 365 regression1_test();
351 regression2_test(); 366 regression2_test();
352 regression3_test(); 367 regression3_test();
353 iteration_test(0, 10); 368 iteration_test(0, 10 + 90 * long_run);
354 iteration_test(7, 20); 369 iteration_test(7, 10 + 90 * long_run);
355 single_thread_tests(long_run); 370 single_thread_tests(long_run);
356 371
357 /* Free any remaining preallocated nodes */ 372 /* Free any remaining preallocated nodes */
@@ -360,9 +375,11 @@ int main(int argc, char **argv)
360 benchmark(); 375 benchmark();
361 376
362 rcu_barrier(); 377 rcu_barrier();
363 printf("after rcu_barrier: %d allocated, preempt %d\n", 378 printv(2, "after rcu_barrier: %d allocated, preempt %d\n",
364 nr_allocated, preempt_count); 379 nr_allocated, preempt_count);
365 rcu_unregister_thread(); 380 rcu_unregister_thread();
366 381
382 printf("tests completed\n");
383
367 exit(0); 384 exit(0);
368} 385}
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c
index f79812a5e070..06c71178d07d 100644
--- a/tools/testing/radix-tree/multiorder.c
+++ b/tools/testing/radix-tree/multiorder.c
@@ -30,7 +30,7 @@ static void __multiorder_tag_test(int index, int order)
30 /* our canonical entry */ 30 /* our canonical entry */
31 base = index & ~((1 << order) - 1); 31 base = index & ~((1 << order) - 1);
32 32
33 printf("Multiorder tag test with index %d, canonical entry %d\n", 33 printv(2, "Multiorder tag test with index %d, canonical entry %d\n",
34 index, base); 34 index, base);
35 35
36 err = item_insert_order(&tree, index, order); 36 err = item_insert_order(&tree, index, order);
@@ -150,7 +150,7 @@ static void multiorder_check(unsigned long index, int order)
150 struct item *item2 = item_create(min, order); 150 struct item *item2 = item_create(min, order);
151 RADIX_TREE(tree, GFP_KERNEL); 151 RADIX_TREE(tree, GFP_KERNEL);
152 152
153 printf("Multiorder index %ld, order %d\n", index, order); 153 printv(2, "Multiorder index %ld, order %d\n", index, order);
154 154
155 assert(item_insert_order(&tree, index, order) == 0); 155 assert(item_insert_order(&tree, index, order) == 0);
156 156
@@ -188,7 +188,7 @@ static void multiorder_shrink(unsigned long index, int order)
188 RADIX_TREE(tree, GFP_KERNEL); 188 RADIX_TREE(tree, GFP_KERNEL);
189 struct radix_tree_node *node; 189 struct radix_tree_node *node;
190 190
191 printf("Multiorder shrink index %ld, order %d\n", index, order); 191 printv(2, "Multiorder shrink index %ld, order %d\n", index, order);
192 192
193 assert(item_insert_order(&tree, 0, order) == 0); 193 assert(item_insert_order(&tree, 0, order) == 0);
194 194
@@ -209,7 +209,8 @@ static void multiorder_shrink(unsigned long index, int order)
209 item_check_absent(&tree, i); 209 item_check_absent(&tree, i);
210 210
211 if (!item_delete(&tree, 0)) { 211 if (!item_delete(&tree, 0)) {
212 printf("failed to delete index %ld (order %d)\n", index, order); abort(); 212 printv(2, "failed to delete index %ld (order %d)\n", index, order);
213 abort();
213 } 214 }
214 215
215 for (i = 0; i < 2*max; i++) 216 for (i = 0; i < 2*max; i++)
@@ -234,7 +235,7 @@ void multiorder_iteration(void)
234 void **slot; 235 void **slot;
235 int i, j, err; 236 int i, j, err;
236 237
237 printf("Multiorder iteration test\n"); 238 printv(1, "Multiorder iteration test\n");
238 239
239#define NUM_ENTRIES 11 240#define NUM_ENTRIES 11
240 int index[NUM_ENTRIES] = {0, 2, 4, 8, 16, 32, 34, 36, 64, 72, 128}; 241 int index[NUM_ENTRIES] = {0, 2, 4, 8, 16, 32, 34, 36, 64, 72, 128};
@@ -275,7 +276,7 @@ void multiorder_tagged_iteration(void)
275 void **slot; 276 void **slot;
276 int i, j; 277 int i, j;
277 278
278 printf("Multiorder tagged iteration test\n"); 279 printv(1, "Multiorder tagged iteration test\n");
279 280
280#define MT_NUM_ENTRIES 9 281#define MT_NUM_ENTRIES 9
281 int index[MT_NUM_ENTRIES] = {0, 2, 4, 16, 32, 40, 64, 72, 128}; 282 int index[MT_NUM_ENTRIES] = {0, 2, 4, 16, 32, 40, 64, 72, 128};
@@ -355,6 +356,10 @@ void multiorder_tagged_iteration(void)
355 item_kill_tree(&tree); 356 item_kill_tree(&tree);
356} 357}
357 358
359/*
360 * Basic join checks: make sure we can't find an entry in the tree after
361 * a larger entry has replaced it
362 */
358static void multiorder_join1(unsigned long index, 363static void multiorder_join1(unsigned long index,
359 unsigned order1, unsigned order2) 364 unsigned order1, unsigned order2)
360{ 365{
@@ -373,6 +378,10 @@ static void multiorder_join1(unsigned long index,
373 item_kill_tree(&tree); 378 item_kill_tree(&tree);
374} 379}
375 380
381/*
382 * Check that the accounting of exceptional entries is handled correctly
383 * by joining an exceptional entry to a normal pointer.
384 */
376static void multiorder_join2(unsigned order1, unsigned order2) 385static void multiorder_join2(unsigned order1, unsigned order2)
377{ 386{
378 RADIX_TREE(tree, GFP_KERNEL); 387 RADIX_TREE(tree, GFP_KERNEL);
@@ -386,6 +395,9 @@ static void multiorder_join2(unsigned order1, unsigned order2)
386 assert(item2 == (void *)0x12UL); 395 assert(item2 == (void *)0x12UL);
387 assert(node->exceptional == 1); 396 assert(node->exceptional == 1);
388 397
398 item2 = radix_tree_lookup(&tree, 0);
399 free(item2);
400
389 radix_tree_join(&tree, 0, order1, item1); 401 radix_tree_join(&tree, 0, order1, item1);
390 item2 = __radix_tree_lookup(&tree, 1 << order2, &node, NULL); 402 item2 = __radix_tree_lookup(&tree, 1 << order2, &node, NULL);
391 assert(item2 == item1); 403 assert(item2 == item1);
@@ -453,7 +465,7 @@ static void check_mem(unsigned old_order, unsigned new_order, unsigned alloc)
453{ 465{
454 struct radix_tree_preload *rtp = &radix_tree_preloads; 466 struct radix_tree_preload *rtp = &radix_tree_preloads;
455 if (rtp->nr != 0) 467 if (rtp->nr != 0)
456 printf("split(%u %u) remaining %u\n", old_order, new_order, 468 printv(2, "split(%u %u) remaining %u\n", old_order, new_order,
457 rtp->nr); 469 rtp->nr);
458 /* 470 /*
459 * Can't check for equality here as some nodes may have been 471 * Can't check for equality here as some nodes may have been
@@ -461,7 +473,7 @@ static void check_mem(unsigned old_order, unsigned new_order, unsigned alloc)
461 * nodes allocated since they should have all been preloaded. 473 * nodes allocated since they should have all been preloaded.
462 */ 474 */
463 if (nr_allocated > alloc) 475 if (nr_allocated > alloc)
464 printf("split(%u %u) allocated %u %u\n", old_order, new_order, 476 printv(2, "split(%u %u) allocated %u %u\n", old_order, new_order,
465 alloc, nr_allocated); 477 alloc, nr_allocated);
466} 478}
467 479
@@ -471,6 +483,7 @@ static void __multiorder_split(int old_order, int new_order)
471 void **slot; 483 void **slot;
472 struct radix_tree_iter iter; 484 struct radix_tree_iter iter;
473 unsigned alloc; 485 unsigned alloc;
486 struct item *item;
474 487
475 radix_tree_preload(GFP_KERNEL); 488 radix_tree_preload(GFP_KERNEL);
476 assert(item_insert_order(&tree, 0, old_order) == 0); 489 assert(item_insert_order(&tree, 0, old_order) == 0);
@@ -479,7 +492,7 @@ static void __multiorder_split(int old_order, int new_order)
479 /* Wipe out the preloaded cache or it'll confuse check_mem() */ 492 /* Wipe out the preloaded cache or it'll confuse check_mem() */
480 radix_tree_cpu_dead(0); 493 radix_tree_cpu_dead(0);
481 494
482 radix_tree_tag_set(&tree, 0, 2); 495 item = radix_tree_tag_set(&tree, 0, 2);
483 496
484 radix_tree_split_preload(old_order, new_order, GFP_KERNEL); 497 radix_tree_split_preload(old_order, new_order, GFP_KERNEL);
485 alloc = nr_allocated; 498 alloc = nr_allocated;
@@ -492,6 +505,7 @@ static void __multiorder_split(int old_order, int new_order)
492 radix_tree_preload_end(); 505 radix_tree_preload_end();
493 506
494 item_kill_tree(&tree); 507 item_kill_tree(&tree);
508 free(item);
495} 509}
496 510
497static void __multiorder_split2(int old_order, int new_order) 511static void __multiorder_split2(int old_order, int new_order)
@@ -633,3 +647,10 @@ void multiorder_checks(void)
633 647
634 radix_tree_cpu_dead(0); 648 radix_tree_cpu_dead(0);
635} 649}
650
651int __weak main(void)
652{
653 radix_tree_init();
654 multiorder_checks();
655 return 0;
656}
diff --git a/tools/testing/radix-tree/regression1.c b/tools/testing/radix-tree/regression1.c
index 0d6813a61b37..bf97742fc18c 100644
--- a/tools/testing/radix-tree/regression1.c
+++ b/tools/testing/radix-tree/regression1.c
@@ -193,7 +193,7 @@ void regression1_test(void)
193 long arg; 193 long arg;
194 194
195 /* Regression #1 */ 195 /* Regression #1 */
196 printf("running regression test 1, should finish in under a minute\n"); 196 printv(1, "running regression test 1, should finish in under a minute\n");
197 nr_threads = 2; 197 nr_threads = 2;
198 pthread_barrier_init(&worker_barrier, NULL, nr_threads); 198 pthread_barrier_init(&worker_barrier, NULL, nr_threads);
199 199
@@ -216,5 +216,5 @@ void regression1_test(void)
216 216
217 free(threads); 217 free(threads);
218 218
219 printf("regression test 1, done\n"); 219 printv(1, "regression test 1, done\n");
220} 220}
diff --git a/tools/testing/radix-tree/regression2.c b/tools/testing/radix-tree/regression2.c
index a41325d7a170..42dd2a33ed24 100644
--- a/tools/testing/radix-tree/regression2.c
+++ b/tools/testing/radix-tree/regression2.c
@@ -80,7 +80,7 @@ void regression2_test(void)
80 unsigned long int start, end; 80 unsigned long int start, end;
81 struct page *pages[1]; 81 struct page *pages[1];
82 82
83 printf("running regression test 2 (should take milliseconds)\n"); 83 printv(1, "running regression test 2 (should take milliseconds)\n");
84 /* 0. */ 84 /* 0. */
85 for (i = 0; i <= max_slots - 1; i++) { 85 for (i = 0; i <= max_slots - 1; i++) {
86 p = page_alloc(); 86 p = page_alloc();
@@ -103,7 +103,7 @@ void regression2_test(void)
103 103
104 /* 4. */ 104 /* 4. */
105 for (i = max_slots - 1; i >= 0; i--) 105 for (i = max_slots - 1; i >= 0; i--)
106 radix_tree_delete(&mt_tree, i); 106 free(radix_tree_delete(&mt_tree, i));
107 107
108 /* 5. */ 108 /* 5. */
109 // NOTE: start should not be 0 because radix_tree_gang_lookup_tag_slot 109 // NOTE: start should not be 0 because radix_tree_gang_lookup_tag_slot
@@ -114,7 +114,9 @@ void regression2_test(void)
114 PAGECACHE_TAG_TOWRITE); 114 PAGECACHE_TAG_TOWRITE);
115 115
116 /* We remove all the remained nodes */ 116 /* We remove all the remained nodes */
117 radix_tree_delete(&mt_tree, max_slots); 117 free(radix_tree_delete(&mt_tree, max_slots));
118 118
119 printf("regression test 2, done\n"); 119 BUG_ON(!radix_tree_empty(&mt_tree));
120
121 printv(1, "regression test 2, done\n");
120} 122}
diff --git a/tools/testing/radix-tree/regression3.c b/tools/testing/radix-tree/regression3.c
index b594841fae85..670c3d2ae7b1 100644
--- a/tools/testing/radix-tree/regression3.c
+++ b/tools/testing/radix-tree/regression3.c
@@ -34,21 +34,21 @@ void regression3_test(void)
34 void **slot; 34 void **slot;
35 bool first; 35 bool first;
36 36
37 printf("running regression test 3 (should take milliseconds)\n"); 37 printv(1, "running regression test 3 (should take milliseconds)\n");
38 38
39 radix_tree_insert(&root, 0, ptr0); 39 radix_tree_insert(&root, 0, ptr0);
40 radix_tree_tag_set(&root, 0, 0); 40 radix_tree_tag_set(&root, 0, 0);
41 41
42 first = true; 42 first = true;
43 radix_tree_for_each_tagged(slot, &root, &iter, 0, 0) { 43 radix_tree_for_each_tagged(slot, &root, &iter, 0, 0) {
44 printf("tagged %ld %p\n", iter.index, *slot); 44 printv(2, "tagged %ld %p\n", iter.index, *slot);
45 if (first) { 45 if (first) {
46 radix_tree_insert(&root, 1, ptr); 46 radix_tree_insert(&root, 1, ptr);
47 radix_tree_tag_set(&root, 1, 0); 47 radix_tree_tag_set(&root, 1, 0);
48 first = false; 48 first = false;
49 } 49 }
50 if (radix_tree_deref_retry(*slot)) { 50 if (radix_tree_deref_retry(*slot)) {
51 printf("retry at %ld\n", iter.index); 51 printv(2, "retry at %ld\n", iter.index);
52 slot = radix_tree_iter_retry(&iter); 52 slot = radix_tree_iter_retry(&iter);
53 continue; 53 continue;
54 } 54 }
@@ -57,13 +57,13 @@ void regression3_test(void)
57 57
58 first = true; 58 first = true;
59 radix_tree_for_each_slot(slot, &root, &iter, 0) { 59 radix_tree_for_each_slot(slot, &root, &iter, 0) {
60 printf("slot %ld %p\n", iter.index, *slot); 60 printv(2, "slot %ld %p\n", iter.index, *slot);
61 if (first) { 61 if (first) {
62 radix_tree_insert(&root, 1, ptr); 62 radix_tree_insert(&root, 1, ptr);
63 first = false; 63 first = false;
64 } 64 }
65 if (radix_tree_deref_retry(*slot)) { 65 if (radix_tree_deref_retry(*slot)) {
66 printk("retry at %ld\n", iter.index); 66 printv(2, "retry at %ld\n", iter.index);
67 slot = radix_tree_iter_retry(&iter); 67 slot = radix_tree_iter_retry(&iter);
68 continue; 68 continue;
69 } 69 }
@@ -72,30 +72,30 @@ void regression3_test(void)
72 72
73 first = true; 73 first = true;
74 radix_tree_for_each_contig(slot, &root, &iter, 0) { 74 radix_tree_for_each_contig(slot, &root, &iter, 0) {
75 printk("contig %ld %p\n", iter.index, *slot); 75 printv(2, "contig %ld %p\n", iter.index, *slot);
76 if (first) { 76 if (first) {
77 radix_tree_insert(&root, 1, ptr); 77 radix_tree_insert(&root, 1, ptr);
78 first = false; 78 first = false;
79 } 79 }
80 if (radix_tree_deref_retry(*slot)) { 80 if (radix_tree_deref_retry(*slot)) {
81 printk("retry at %ld\n", iter.index); 81 printv(2, "retry at %ld\n", iter.index);
82 slot = radix_tree_iter_retry(&iter); 82 slot = radix_tree_iter_retry(&iter);
83 continue; 83 continue;
84 } 84 }
85 } 85 }
86 86
87 radix_tree_for_each_slot(slot, &root, &iter, 0) { 87 radix_tree_for_each_slot(slot, &root, &iter, 0) {
88 printf("slot %ld %p\n", iter.index, *slot); 88 printv(2, "slot %ld %p\n", iter.index, *slot);
89 if (!iter.index) { 89 if (!iter.index) {
90 printf("next at %ld\n", iter.index); 90 printv(2, "next at %ld\n", iter.index);
91 slot = radix_tree_iter_resume(slot, &iter); 91 slot = radix_tree_iter_resume(slot, &iter);
92 } 92 }
93 } 93 }
94 94
95 radix_tree_for_each_contig(slot, &root, &iter, 0) { 95 radix_tree_for_each_contig(slot, &root, &iter, 0) {
96 printf("contig %ld %p\n", iter.index, *slot); 96 printv(2, "contig %ld %p\n", iter.index, *slot);
97 if (!iter.index) { 97 if (!iter.index) {
98 printf("next at %ld\n", iter.index); 98 printv(2, "next at %ld\n", iter.index);
99 slot = radix_tree_iter_resume(slot, &iter); 99 slot = radix_tree_iter_resume(slot, &iter);
100 } 100 }
101 } 101 }
@@ -103,9 +103,9 @@ void regression3_test(void)
103 radix_tree_tag_set(&root, 0, 0); 103 radix_tree_tag_set(&root, 0, 0);
104 radix_tree_tag_set(&root, 1, 0); 104 radix_tree_tag_set(&root, 1, 0);
105 radix_tree_for_each_tagged(slot, &root, &iter, 0, 0) { 105 radix_tree_for_each_tagged(slot, &root, &iter, 0, 0) {
106 printf("tagged %ld %p\n", iter.index, *slot); 106 printv(2, "tagged %ld %p\n", iter.index, *slot);
107 if (!iter.index) { 107 if (!iter.index) {
108 printf("next at %ld\n", iter.index); 108 printv(2, "next at %ld\n", iter.index);
109 slot = radix_tree_iter_resume(slot, &iter); 109 slot = radix_tree_iter_resume(slot, &iter);
110 } 110 }
111 } 111 }
@@ -113,5 +113,5 @@ void regression3_test(void)
113 radix_tree_delete(&root, 0); 113 radix_tree_delete(&root, 0);
114 radix_tree_delete(&root, 1); 114 radix_tree_delete(&root, 1);
115 115
116 printf("regression test 3 passed\n"); 116 printv(1, "regression test 3 passed\n");
117} 117}
diff --git a/tools/testing/radix-tree/tag_check.c b/tools/testing/radix-tree/tag_check.c
index fd98c132207a..d4ff00989245 100644
--- a/tools/testing/radix-tree/tag_check.c
+++ b/tools/testing/radix-tree/tag_check.c
@@ -49,10 +49,10 @@ void simple_checks(void)
49 } 49 }
50 verify_tag_consistency(&tree, 0); 50 verify_tag_consistency(&tree, 0);
51 verify_tag_consistency(&tree, 1); 51 verify_tag_consistency(&tree, 1);
52 printf("before item_kill_tree: %d allocated\n", nr_allocated); 52 printv(2, "before item_kill_tree: %d allocated\n", nr_allocated);
53 item_kill_tree(&tree); 53 item_kill_tree(&tree);
54 rcu_barrier(); 54 rcu_barrier();
55 printf("after item_kill_tree: %d allocated\n", nr_allocated); 55 printv(2, "after item_kill_tree: %d allocated\n", nr_allocated);
56} 56}
57 57
58/* 58/*
@@ -257,7 +257,7 @@ static void do_thrash(struct radix_tree_root *tree, char *thrash_state, int tag)
257 257
258 gang_check(tree, thrash_state, tag); 258 gang_check(tree, thrash_state, tag);
259 259
260 printf("%d(%d) %d(%d) %d(%d) %d(%d) / " 260 printv(2, "%d(%d) %d(%d) %d(%d) %d(%d) / "
261 "%d(%d) present, %d(%d) tagged\n", 261 "%d(%d) present, %d(%d) tagged\n",
262 insert_chunk, nr_inserted, 262 insert_chunk, nr_inserted,
263 delete_chunk, nr_deleted, 263 delete_chunk, nr_deleted,
@@ -296,13 +296,13 @@ static void __leak_check(void)
296{ 296{
297 RADIX_TREE(tree, GFP_KERNEL); 297 RADIX_TREE(tree, GFP_KERNEL);
298 298
299 printf("%d: nr_allocated=%d\n", __LINE__, nr_allocated); 299 printv(2, "%d: nr_allocated=%d\n", __LINE__, nr_allocated);
300 item_insert(&tree, 1000000); 300 item_insert(&tree, 1000000);
301 printf("%d: nr_allocated=%d\n", __LINE__, nr_allocated); 301 printv(2, "%d: nr_allocated=%d\n", __LINE__, nr_allocated);
302 item_delete(&tree, 1000000); 302 item_delete(&tree, 1000000);
303 printf("%d: nr_allocated=%d\n", __LINE__, nr_allocated); 303 printv(2, "%d: nr_allocated=%d\n", __LINE__, nr_allocated);
304 item_kill_tree(&tree); 304 item_kill_tree(&tree);
305 printf("%d: nr_allocated=%d\n", __LINE__, nr_allocated); 305 printv(2, "%d: nr_allocated=%d\n", __LINE__, nr_allocated);
306} 306}
307 307
308static void single_check(void) 308static void single_check(void)
@@ -336,15 +336,15 @@ void tag_check(void)
336 extend_checks(); 336 extend_checks();
337 contract_checks(); 337 contract_checks();
338 rcu_barrier(); 338 rcu_barrier();
339 printf("after extend_checks: %d allocated\n", nr_allocated); 339 printv(2, "after extend_checks: %d allocated\n", nr_allocated);
340 __leak_check(); 340 __leak_check();
341 leak_check(); 341 leak_check();
342 rcu_barrier(); 342 rcu_barrier();
343 printf("after leak_check: %d allocated\n", nr_allocated); 343 printv(2, "after leak_check: %d allocated\n", nr_allocated);
344 simple_checks(); 344 simple_checks();
345 rcu_barrier(); 345 rcu_barrier();
346 printf("after simple_checks: %d allocated\n", nr_allocated); 346 printv(2, "after simple_checks: %d allocated\n", nr_allocated);
347 thrash_tags(); 347 thrash_tags();
348 rcu_barrier(); 348 rcu_barrier();
349 printf("after thrash_tags: %d allocated\n", nr_allocated); 349 printv(2, "after thrash_tags: %d allocated\n", nr_allocated);
350} 350}
diff --git a/tools/testing/radix-tree/test.c b/tools/testing/radix-tree/test.c
index e5726e373646..1a257d738a1e 100644
--- a/tools/testing/radix-tree/test.c
+++ b/tools/testing/radix-tree/test.c
@@ -29,15 +29,28 @@ int __item_insert(struct radix_tree_root *root, struct item *item)
29 return __radix_tree_insert(root, item->index, item->order, item); 29 return __radix_tree_insert(root, item->index, item->order, item);
30} 30}
31 31
32int item_insert(struct radix_tree_root *root, unsigned long index) 32struct item *item_create(unsigned long index, unsigned int order)
33{ 33{
34 return __item_insert(root, item_create(index, 0)); 34 struct item *ret = malloc(sizeof(*ret));
35
36 ret->index = index;
37 ret->order = order;
38 return ret;
35} 39}
36 40
37int item_insert_order(struct radix_tree_root *root, unsigned long index, 41int item_insert_order(struct radix_tree_root *root, unsigned long index,
38 unsigned order) 42 unsigned order)
39{ 43{
40 return __item_insert(root, item_create(index, order)); 44 struct item *item = item_create(index, order);
45 int err = __item_insert(root, item);
46 if (err)
47 free(item);
48 return err;
49}
50
51int item_insert(struct radix_tree_root *root, unsigned long index)
52{
53 return item_insert_order(root, index, 0);
41} 54}
42 55
43void item_sanity(struct item *item, unsigned long index) 56void item_sanity(struct item *item, unsigned long index)
@@ -61,15 +74,6 @@ int item_delete(struct radix_tree_root *root, unsigned long index)
61 return 0; 74 return 0;
62} 75}
63 76
64struct item *item_create(unsigned long index, unsigned int order)
65{
66 struct item *ret = malloc(sizeof(*ret));
67
68 ret->index = index;
69 ret->order = order;
70 return ret;
71}
72
73void item_check_present(struct radix_tree_root *root, unsigned long index) 77void item_check_present(struct radix_tree_root *root, unsigned long index)
74{ 78{
75 struct item *item; 79 struct item *item;
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h
index 056a23b56467..b30e11d9d271 100644
--- a/tools/testing/radix-tree/test.h
+++ b/tools/testing/radix-tree/test.h
@@ -34,6 +34,8 @@ void tag_check(void);
34void multiorder_checks(void); 34void multiorder_checks(void);
35void iteration_test(unsigned order, unsigned duration); 35void iteration_test(unsigned order, unsigned duration);
36void benchmark(void); 36void benchmark(void);
37void idr_checks(void);
38void ida_checks(void);
37 39
38struct item * 40struct item *
39item_tag_set(struct radix_tree_root *root, unsigned long index, int tag); 41item_tag_set(struct radix_tree_root *root, unsigned long index, int tag);
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 831022b12848..d8593f1251ec 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -1,6 +1,7 @@
1TARGETS = bpf 1TARGETS = bpf
2TARGETS += breakpoints 2TARGETS += breakpoints
3TARGETS += capabilities 3TARGETS += capabilities
4TARGETS += cpufreq
4TARGETS += cpu-hotplug 5TARGETS += cpu-hotplug
5TARGETS += efivarfs 6TARGETS += efivarfs
6TARGETS += exec 7TARGETS += exec
@@ -8,6 +9,7 @@ TARGETS += firmware
8TARGETS += ftrace 9TARGETS += ftrace
9TARGETS += futex 10TARGETS += futex
10TARGETS += gpio 11TARGETS += gpio
12TARGETS += intel_pstate
11TARGETS += ipc 13TARGETS += ipc
12TARGETS += kcmp 14TARGETS += kcmp
13TARGETS += lib 15TARGETS += lib
@@ -24,6 +26,7 @@ TARGETS += ptrace
24TARGETS += seccomp 26TARGETS += seccomp
25TARGETS += sigaltstack 27TARGETS += sigaltstack
26TARGETS += size 28TARGETS += size
29TARGETS += splice
27TARGETS += static_keys 30TARGETS += static_keys
28TARGETS += sync 31TARGETS += sync
29TARGETS += sysctl 32TARGETS += sysctl
@@ -49,29 +52,44 @@ override LDFLAGS =
49override MAKEFLAGS = 52override MAKEFLAGS =
50endif 53endif
51 54
55BUILD := $(O)
56ifndef BUILD
57 BUILD := $(KBUILD_OUTPUT)
58endif
59ifndef BUILD
60 BUILD := $(shell pwd)
61endif
62
63export BUILD
52all: 64all:
53 for TARGET in $(TARGETS); do \ 65 for TARGET in $(TARGETS); do \
54 make -C $$TARGET; \ 66 BUILD_TARGET=$$BUILD/$$TARGET; \
67 mkdir $$BUILD_TARGET -p; \
68 make OUTPUT=$$BUILD_TARGET -C $$TARGET;\
55 done; 69 done;
56 70
57run_tests: all 71run_tests: all
58 for TARGET in $(TARGETS); do \ 72 for TARGET in $(TARGETS); do \
59 make -C $$TARGET run_tests; \ 73 BUILD_TARGET=$$BUILD/$$TARGET; \
74 make OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests;\
60 done; 75 done;
61 76
62hotplug: 77hotplug:
63 for TARGET in $(TARGETS_HOTPLUG); do \ 78 for TARGET in $(TARGETS_HOTPLUG); do \
64 make -C $$TARGET; \ 79 BUILD_TARGET=$$BUILD/$$TARGET; \
80 make OUTPUT=$$BUILD_TARGET -C $$TARGET;\
65 done; 81 done;
66 82
67run_hotplug: hotplug 83run_hotplug: hotplug
68 for TARGET in $(TARGETS_HOTPLUG); do \ 84 for TARGET in $(TARGETS_HOTPLUG); do \
69 make -C $$TARGET run_full_test; \ 85 BUILD_TARGET=$$BUILD/$$TARGET; \
86 make OUTPUT=$$BUILD_TARGET -C $$TARGET run_full_test;\
70 done; 87 done;
71 88
72clean_hotplug: 89clean_hotplug:
73 for TARGET in $(TARGETS_HOTPLUG); do \ 90 for TARGET in $(TARGETS_HOTPLUG); do \
74 make -C $$TARGET clean; \ 91 BUILD_TARGET=$$BUILD/$$TARGET; \
92 make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\
75 done; 93 done;
76 94
77run_pstore_crash: 95run_pstore_crash:
@@ -86,7 +104,8 @@ ifdef INSTALL_PATH
86 @# Ask all targets to install their files 104 @# Ask all targets to install their files
87 mkdir -p $(INSTALL_PATH) 105 mkdir -p $(INSTALL_PATH)
88 for TARGET in $(TARGETS); do \ 106 for TARGET in $(TARGETS); do \
89 make -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \ 107 BUILD_TARGET=$$BUILD/$$TARGET; \
108 make OUTPUT=$$BUILD_TARGET -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \
90 done; 109 done;
91 110
92 @# Ask all targets to emit their test scripts 111 @# Ask all targets to emit their test scripts
@@ -95,10 +114,11 @@ ifdef INSTALL_PATH
95 echo "ROOT=\$$PWD" >> $(ALL_SCRIPT) 114 echo "ROOT=\$$PWD" >> $(ALL_SCRIPT)
96 115
97 for TARGET in $(TARGETS); do \ 116 for TARGET in $(TARGETS); do \
117 BUILD_TARGET=$$BUILD/$$TARGET; \
98 echo "echo ; echo Running tests in $$TARGET" >> $(ALL_SCRIPT); \ 118 echo "echo ; echo Running tests in $$TARGET" >> $(ALL_SCRIPT); \
99 echo "echo ========================================" >> $(ALL_SCRIPT); \ 119 echo "echo ========================================" >> $(ALL_SCRIPT); \
100 echo "cd $$TARGET" >> $(ALL_SCRIPT); \ 120 echo "cd $$TARGET" >> $(ALL_SCRIPT); \
101 make -s --no-print-directory -C $$TARGET emit_tests >> $(ALL_SCRIPT); \ 121 make -s --no-print-directory OUTPUT=$$BUILD_TARGET -C $$TARGET emit_tests >> $(ALL_SCRIPT); \
102 echo "cd \$$ROOT" >> $(ALL_SCRIPT); \ 122 echo "cd \$$ROOT" >> $(ALL_SCRIPT); \
103 done; 123 done;
104 124
@@ -109,7 +129,8 @@ endif
109 129
110clean: 130clean:
111 for TARGET in $(TARGETS); do \ 131 for TARGET in $(TARGETS); do \
112 make -C $$TARGET clean; \ 132 BUILD_TARGET=$$BUILD/$$TARGET; \
133 make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\
113 done; 134 done;
114 135
115.PHONY: install 136.PHONY: install
diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore
index 071431bedde8..541d9d7fad5a 100644
--- a/tools/testing/selftests/bpf/.gitignore
+++ b/tools/testing/selftests/bpf/.gitignore
@@ -1,3 +1,5 @@
1test_verifier 1test_verifier
2test_maps 2test_maps
3test_lru_map 3test_lru_map
4test_lpm_map
5test_tag
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 7a5f24543a5f..4b498265dae6 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -1,13 +1,20 @@
1CFLAGS += -Wall -O2 -I../../../../usr/include 1LIBDIR := ../../../lib
2BPFOBJ := $(LIBDIR)/bpf/bpf.o
2 3
3test_objs = test_verifier test_maps test_lru_map 4CFLAGS += -Wall -O2 -lcap -I../../../include/uapi -I$(LIBDIR)
4 5
5TEST_PROGS := test_verifier test_maps test_lru_map test_kmod.sh 6TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map
6TEST_FILES := $(test_objs)
7 7
8all: $(test_objs) 8TEST_PROGS := test_kmod.sh
9 9
10include ../lib.mk 10.PHONY: all clean force
11
12# force a rebuild of BPFOBJ when its dependencies are updated
13force:
14
15$(BPFOBJ): force
16 $(MAKE) -C $(dir $(BPFOBJ))
11 17
12clean: 18$(test_objs): $(BPFOBJ)
13 $(RM) $(test_objs) 19
20include ../lib.mk
diff --git a/tools/testing/selftests/bpf/bpf_sys.h b/tools/testing/selftests/bpf/bpf_sys.h
deleted file mode 100644
index 6b4565f2a3f2..000000000000
--- a/tools/testing/selftests/bpf/bpf_sys.h
+++ /dev/null
@@ -1,108 +0,0 @@
1#ifndef __BPF_SYS__
2#define __BPF_SYS__
3
4#include <stdint.h>
5#include <stdlib.h>
6
7#include <sys/syscall.h>
8
9#include <linux/bpf.h>
10
11static inline __u64 bpf_ptr_to_u64(const void *ptr)
12{
13 return (__u64)(unsigned long) ptr;
14}
15
16static inline int bpf(int cmd, union bpf_attr *attr, unsigned int size)
17{
18#ifdef __NR_bpf
19 return syscall(__NR_bpf, cmd, attr, size);
20#else
21 fprintf(stderr, "No bpf syscall, kernel headers too old?\n");
22 errno = ENOSYS;
23 return -1;
24#endif
25}
26
27static inline int bpf_map_lookup(int fd, const void *key, void *value)
28{
29 union bpf_attr attr = {};
30
31 attr.map_fd = fd;
32 attr.key = bpf_ptr_to_u64(key);
33 attr.value = bpf_ptr_to_u64(value);
34
35 return bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
36}
37
38static inline int bpf_map_update(int fd, const void *key, const void *value,
39 uint64_t flags)
40{
41 union bpf_attr attr = {};
42
43 attr.map_fd = fd;
44 attr.key = bpf_ptr_to_u64(key);
45 attr.value = bpf_ptr_to_u64(value);
46 attr.flags = flags;
47
48 return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
49}
50
51static inline int bpf_map_delete(int fd, const void *key)
52{
53 union bpf_attr attr = {};
54
55 attr.map_fd = fd;
56 attr.key = bpf_ptr_to_u64(key);
57
58 return bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
59}
60
61static inline int bpf_map_next_key(int fd, const void *key, void *next_key)
62{
63 union bpf_attr attr = {};
64
65 attr.map_fd = fd;
66 attr.key = bpf_ptr_to_u64(key);
67 attr.next_key = bpf_ptr_to_u64(next_key);
68
69 return bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
70}
71
72static inline int bpf_map_create(enum bpf_map_type type, uint32_t size_key,
73 uint32_t size_value, uint32_t max_elem,
74 uint32_t flags)
75{
76 union bpf_attr attr = {};
77
78 attr.map_type = type;
79 attr.key_size = size_key;
80 attr.value_size = size_value;
81 attr.max_entries = max_elem;
82 attr.map_flags = flags;
83
84 return bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
85}
86
87static inline int bpf_prog_load(enum bpf_prog_type type,
88 const struct bpf_insn *insns, size_t size_insns,
89 const char *license, char *log, size_t size_log)
90{
91 union bpf_attr attr = {};
92
93 attr.prog_type = type;
94 attr.insns = bpf_ptr_to_u64(insns);
95 attr.insn_cnt = size_insns / sizeof(struct bpf_insn);
96 attr.license = bpf_ptr_to_u64(license);
97
98 if (size_log > 0) {
99 attr.log_buf = bpf_ptr_to_u64(log);
100 attr.log_size = size_log;
101 attr.log_level = 1;
102 log[0] = 0;
103 }
104
105 return bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
106}
107
108#endif /* __BPF_SYS__ */
diff --git a/tools/testing/selftests/bpf/test_lpm_map.c b/tools/testing/selftests/bpf/test_lpm_map.c
new file mode 100644
index 000000000000..e97565243d59
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_lpm_map.c
@@ -0,0 +1,358 @@
1/*
2 * Randomized tests for eBPF longest-prefix-match maps
3 *
4 * This program runs randomized tests against the lpm-bpf-map. It implements a
5 * "Trivial Longest Prefix Match" (tlpm) based on simple, linear, singly linked
6 * lists. The implementation should be pretty straightforward.
7 *
8 * Based on tlpm, this inserts randomized data into bpf-lpm-maps and verifies
9 * the trie-based bpf-map implementation behaves the same way as tlpm.
10 */
11
12#include <assert.h>
13#include <errno.h>
14#include <inttypes.h>
15#include <linux/bpf.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <time.h>
20#include <unistd.h>
21#include <arpa/inet.h>
22#include <sys/time.h>
23#include <sys/resource.h>
24
25#include <bpf/bpf.h>
26#include "bpf_util.h"
27
28struct tlpm_node {
29 struct tlpm_node *next;
30 size_t n_bits;
31 uint8_t key[];
32};
33
34static struct tlpm_node *tlpm_add(struct tlpm_node *list,
35 const uint8_t *key,
36 size_t n_bits)
37{
38 struct tlpm_node *node;
39 size_t n;
40
41 /* add new entry with @key/@n_bits to @list and return new head */
42
43 n = (n_bits + 7) / 8;
44 node = malloc(sizeof(*node) + n);
45 assert(node);
46
47 node->next = list;
48 node->n_bits = n_bits;
49 memcpy(node->key, key, n);
50
51 return node;
52}
53
54static void tlpm_clear(struct tlpm_node *list)
55{
56 struct tlpm_node *node;
57
58 /* free all entries in @list */
59
60 while ((node = list)) {
61 list = list->next;
62 free(node);
63 }
64}
65
66static struct tlpm_node *tlpm_match(struct tlpm_node *list,
67 const uint8_t *key,
68 size_t n_bits)
69{
70 struct tlpm_node *best = NULL;
71 size_t i;
72
73 /* Perform longest prefix-match on @key/@n_bits. That is, iterate all
74 * entries and match each prefix against @key. Remember the "best"
75 * entry we find (i.e., the longest prefix that matches) and return it
76 * to the caller when done.
77 */
78
79 for ( ; list; list = list->next) {
80 for (i = 0; i < n_bits && i < list->n_bits; ++i) {
81 if ((key[i / 8] & (1 << (7 - i % 8))) !=
82 (list->key[i / 8] & (1 << (7 - i % 8))))
83 break;
84 }
85
86 if (i >= list->n_bits) {
87 if (!best || i > best->n_bits)
88 best = list;
89 }
90 }
91
92 return best;
93}
94
95static void test_lpm_basic(void)
96{
97 struct tlpm_node *list = NULL, *t1, *t2;
98
99 /* very basic, static tests to verify tlpm works as expected */
100
101 assert(!tlpm_match(list, (uint8_t[]){ 0xff }, 8));
102
103 t1 = list = tlpm_add(list, (uint8_t[]){ 0xff }, 8);
104 assert(t1 == tlpm_match(list, (uint8_t[]){ 0xff }, 8));
105 assert(t1 == tlpm_match(list, (uint8_t[]){ 0xff, 0xff }, 16));
106 assert(t1 == tlpm_match(list, (uint8_t[]){ 0xff, 0x00 }, 16));
107 assert(!tlpm_match(list, (uint8_t[]){ 0x7f }, 8));
108 assert(!tlpm_match(list, (uint8_t[]){ 0xfe }, 8));
109 assert(!tlpm_match(list, (uint8_t[]){ 0xff }, 7));
110
111 t2 = list = tlpm_add(list, (uint8_t[]){ 0xff, 0xff }, 16);
112 assert(t1 == tlpm_match(list, (uint8_t[]){ 0xff }, 8));
113 assert(t2 == tlpm_match(list, (uint8_t[]){ 0xff, 0xff }, 16));
114 assert(t1 == tlpm_match(list, (uint8_t[]){ 0xff, 0xff }, 15));
115 assert(!tlpm_match(list, (uint8_t[]){ 0x7f, 0xff }, 16));
116
117 tlpm_clear(list);
118}
119
120static void test_lpm_order(void)
121{
122 struct tlpm_node *t1, *t2, *l1 = NULL, *l2 = NULL;
123 size_t i, j;
124
125 /* Verify the tlpm implementation works correctly regardless of the
126 * order of entries. Insert a random set of entries into @l1, and copy
127 * the same data in reverse order into @l2. Then verify a lookup of
128 * random keys will yield the same result in both sets.
129 */
130
131 for (i = 0; i < (1 << 12); ++i)
132 l1 = tlpm_add(l1, (uint8_t[]){
133 rand() % 0xff,
134 rand() % 0xff,
135 }, rand() % 16 + 1);
136
137 for (t1 = l1; t1; t1 = t1->next)
138 l2 = tlpm_add(l2, t1->key, t1->n_bits);
139
140 for (i = 0; i < (1 << 8); ++i) {
141 uint8_t key[] = { rand() % 0xff, rand() % 0xff };
142
143 t1 = tlpm_match(l1, key, 16);
144 t2 = tlpm_match(l2, key, 16);
145
146 assert(!t1 == !t2);
147 if (t1) {
148 assert(t1->n_bits == t2->n_bits);
149 for (j = 0; j < t1->n_bits; ++j)
150 assert((t1->key[j / 8] & (1 << (7 - j % 8))) ==
151 (t2->key[j / 8] & (1 << (7 - j % 8))));
152 }
153 }
154
155 tlpm_clear(l1);
156 tlpm_clear(l2);
157}
158
159static void test_lpm_map(int keysize)
160{
161 size_t i, j, n_matches, n_nodes, n_lookups;
162 struct tlpm_node *t, *list = NULL;
163 struct bpf_lpm_trie_key *key;
164 uint8_t *data, *value;
165 int r, map;
166
167 /* Compare behavior of tlpm vs. bpf-lpm. Create a randomized set of
168 * prefixes and insert it into both tlpm and bpf-lpm. Then run some
169 * randomized lookups and verify both maps return the same result.
170 */
171
172 n_matches = 0;
173 n_nodes = 1 << 8;
174 n_lookups = 1 << 16;
175
176 data = alloca(keysize);
177 memset(data, 0, keysize);
178
179 value = alloca(keysize + 1);
180 memset(value, 0, keysize + 1);
181
182 key = alloca(sizeof(*key) + keysize);
183 memset(key, 0, sizeof(*key) + keysize);
184
185 map = bpf_create_map(BPF_MAP_TYPE_LPM_TRIE,
186 sizeof(*key) + keysize,
187 keysize + 1,
188 4096,
189 BPF_F_NO_PREALLOC);
190 assert(map >= 0);
191
192 for (i = 0; i < n_nodes; ++i) {
193 for (j = 0; j < keysize; ++j)
194 value[j] = rand() & 0xff;
195 value[keysize] = rand() % (8 * keysize + 1);
196
197 list = tlpm_add(list, value, value[keysize]);
198
199 key->prefixlen = value[keysize];
200 memcpy(key->data, value, keysize);
201 r = bpf_map_update_elem(map, key, value, 0);
202 assert(!r);
203 }
204
205 for (i = 0; i < n_lookups; ++i) {
206 for (j = 0; j < keysize; ++j)
207 data[j] = rand() & 0xff;
208
209 t = tlpm_match(list, data, 8 * keysize);
210
211 key->prefixlen = 8 * keysize;
212 memcpy(key->data, data, keysize);
213 r = bpf_map_lookup_elem(map, key, value);
214 assert(!r || errno == ENOENT);
215 assert(!t == !!r);
216
217 if (t) {
218 ++n_matches;
219 assert(t->n_bits == value[keysize]);
220 for (j = 0; j < t->n_bits; ++j)
221 assert((t->key[j / 8] & (1 << (7 - j % 8))) ==
222 (value[j / 8] & (1 << (7 - j % 8))));
223 }
224 }
225
226 close(map);
227 tlpm_clear(list);
228
229 /* With 255 random nodes in the map, we are pretty likely to match
230 * something on every lookup. For statistics, use this:
231 *
232 * printf(" nodes: %zu\n"
233 * "lookups: %zu\n"
234 * "matches: %zu\n", n_nodes, n_lookups, n_matches);
235 */
236}
237
238/* Test the implementation with some 'real world' examples */
239
240static void test_lpm_ipaddr(void)
241{
242 struct bpf_lpm_trie_key *key_ipv4;
243 struct bpf_lpm_trie_key *key_ipv6;
244 size_t key_size_ipv4;
245 size_t key_size_ipv6;
246 int map_fd_ipv4;
247 int map_fd_ipv6;
248 __u64 value;
249
250 key_size_ipv4 = sizeof(*key_ipv4) + sizeof(__u32);
251 key_size_ipv6 = sizeof(*key_ipv6) + sizeof(__u32) * 4;
252 key_ipv4 = alloca(key_size_ipv4);
253 key_ipv6 = alloca(key_size_ipv6);
254
255 map_fd_ipv4 = bpf_create_map(BPF_MAP_TYPE_LPM_TRIE,
256 key_size_ipv4, sizeof(value),
257 100, BPF_F_NO_PREALLOC);
258 assert(map_fd_ipv4 >= 0);
259
260 map_fd_ipv6 = bpf_create_map(BPF_MAP_TYPE_LPM_TRIE,
261 key_size_ipv6, sizeof(value),
262 100, BPF_F_NO_PREALLOC);
263 assert(map_fd_ipv6 >= 0);
264
265 /* Fill data some IPv4 and IPv6 address ranges */
266 value = 1;
267 key_ipv4->prefixlen = 16;
268 inet_pton(AF_INET, "192.168.0.0", key_ipv4->data);
269 assert(bpf_map_update_elem(map_fd_ipv4, key_ipv4, &value, 0) == 0);
270
271 value = 2;
272 key_ipv4->prefixlen = 24;
273 inet_pton(AF_INET, "192.168.0.0", key_ipv4->data);
274 assert(bpf_map_update_elem(map_fd_ipv4, key_ipv4, &value, 0) == 0);
275
276 value = 3;
277 key_ipv4->prefixlen = 24;
278 inet_pton(AF_INET, "192.168.128.0", key_ipv4->data);
279 assert(bpf_map_update_elem(map_fd_ipv4, key_ipv4, &value, 0) == 0);
280
281 value = 5;
282 key_ipv4->prefixlen = 24;
283 inet_pton(AF_INET, "192.168.1.0", key_ipv4->data);
284 assert(bpf_map_update_elem(map_fd_ipv4, key_ipv4, &value, 0) == 0);
285
286 value = 4;
287 key_ipv4->prefixlen = 23;
288 inet_pton(AF_INET, "192.168.0.0", key_ipv4->data);
289 assert(bpf_map_update_elem(map_fd_ipv4, key_ipv4, &value, 0) == 0);
290
291 value = 0xdeadbeef;
292 key_ipv6->prefixlen = 64;
293 inet_pton(AF_INET6, "2a00:1450:4001:814::200e", key_ipv6->data);
294 assert(bpf_map_update_elem(map_fd_ipv6, key_ipv6, &value, 0) == 0);
295
296 /* Set tprefixlen to maximum for lookups */
297 key_ipv4->prefixlen = 32;
298 key_ipv6->prefixlen = 128;
299
300 /* Test some lookups that should come back with a value */
301 inet_pton(AF_INET, "192.168.128.23", key_ipv4->data);
302 assert(bpf_map_lookup_elem(map_fd_ipv4, key_ipv4, &value) == 0);
303 assert(value == 3);
304
305 inet_pton(AF_INET, "192.168.0.1", key_ipv4->data);
306 assert(bpf_map_lookup_elem(map_fd_ipv4, key_ipv4, &value) == 0);
307 assert(value == 2);
308
309 inet_pton(AF_INET6, "2a00:1450:4001:814::", key_ipv6->data);
310 assert(bpf_map_lookup_elem(map_fd_ipv6, key_ipv6, &value) == 0);
311 assert(value == 0xdeadbeef);
312
313 inet_pton(AF_INET6, "2a00:1450:4001:814::1", key_ipv6->data);
314 assert(bpf_map_lookup_elem(map_fd_ipv6, key_ipv6, &value) == 0);
315 assert(value == 0xdeadbeef);
316
317 /* Test some lookups that should not match any entry */
318 inet_pton(AF_INET, "10.0.0.1", key_ipv4->data);
319 assert(bpf_map_lookup_elem(map_fd_ipv4, key_ipv4, &value) == -1 &&
320 errno == ENOENT);
321
322 inet_pton(AF_INET, "11.11.11.11", key_ipv4->data);
323 assert(bpf_map_lookup_elem(map_fd_ipv4, key_ipv4, &value) == -1 &&
324 errno == ENOENT);
325
326 inet_pton(AF_INET6, "2a00:ffff::", key_ipv6->data);
327 assert(bpf_map_lookup_elem(map_fd_ipv6, key_ipv6, &value) == -1 &&
328 errno == ENOENT);
329
330 close(map_fd_ipv4);
331 close(map_fd_ipv6);
332}
333
334int main(void)
335{
336 struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY };
337 int i, ret;
338
339 /* we want predictable, pseudo random tests */
340 srand(0xf00ba1);
341
342 /* allow unlimited locked memory */
343 ret = setrlimit(RLIMIT_MEMLOCK, &limit);
344 if (ret < 0)
345 perror("Unable to lift memlock rlimit");
346
347 test_lpm_basic();
348 test_lpm_order();
349
350 /* Test with 8, 16, 24, 32, ... 128 bit prefix length */
351 for (i = 1; i <= 16; ++i)
352 test_lpm_map(i);
353
354 test_lpm_ipaddr();
355
356 printf("test_lpm: OK\n");
357 return 0;
358}
diff --git a/tools/testing/selftests/bpf/test_lru_map.c b/tools/testing/selftests/bpf/test_lru_map.c
index 9f7bd1915c21..00b0aff56e2e 100644
--- a/tools/testing/selftests/bpf/test_lru_map.c
+++ b/tools/testing/selftests/bpf/test_lru_map.c
@@ -18,7 +18,7 @@
18#include <sys/wait.h> 18#include <sys/wait.h>
19#include <sys/resource.h> 19#include <sys/resource.h>
20 20
21#include "bpf_sys.h" 21#include <bpf/bpf.h>
22#include "bpf_util.h" 22#include "bpf_util.h"
23 23
24#define LOCAL_FREE_TARGET (128) 24#define LOCAL_FREE_TARGET (128)
@@ -30,11 +30,11 @@ static int create_map(int map_type, int map_flags, unsigned int size)
30{ 30{
31 int map_fd; 31 int map_fd;
32 32
33 map_fd = bpf_map_create(map_type, sizeof(unsigned long long), 33 map_fd = bpf_create_map(map_type, sizeof(unsigned long long),
34 sizeof(unsigned long long), size, map_flags); 34 sizeof(unsigned long long), size, map_flags);
35 35
36 if (map_fd == -1) 36 if (map_fd == -1)
37 perror("bpf_map_create"); 37 perror("bpf_create_map");
38 38
39 return map_fd; 39 return map_fd;
40} 40}
@@ -45,9 +45,9 @@ static int map_subset(int map0, int map1)
45 unsigned long long value0[nr_cpus], value1[nr_cpus]; 45 unsigned long long value0[nr_cpus], value1[nr_cpus];
46 int ret; 46 int ret;
47 47
48 while (!bpf_map_next_key(map1, &next_key, &next_key)) { 48 while (!bpf_map_get_next_key(map1, &next_key, &next_key)) {
49 assert(!bpf_map_lookup(map1, &next_key, value1)); 49 assert(!bpf_map_lookup_elem(map1, &next_key, value1));
50 ret = bpf_map_lookup(map0, &next_key, value0); 50 ret = bpf_map_lookup_elem(map0, &next_key, value0);
51 if (ret) { 51 if (ret) {
52 printf("key:%llu not found from map. %s(%d)\n", 52 printf("key:%llu not found from map. %s(%d)\n",
53 next_key, strerror(errno), errno); 53 next_key, strerror(errno), errno);
@@ -119,52 +119,54 @@ static void test_lru_sanity0(int map_type, int map_flags)
119 /* insert key=1 element */ 119 /* insert key=1 element */
120 120
121 key = 1; 121 key = 1;
122 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 122 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
123 assert(!bpf_map_update(expected_map_fd, &key, value, BPF_NOEXIST)); 123 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
124 BPF_NOEXIST));
124 125
125 /* BPF_NOEXIST means: add new element if it doesn't exist */ 126 /* BPF_NOEXIST means: add new element if it doesn't exist */
126 assert(bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST) == -1 && 127 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST) == -1
127 /* key=1 already exists */ 128 /* key=1 already exists */
128 errno == EEXIST); 129 && errno == EEXIST);
129 130
130 assert(bpf_map_update(lru_map_fd, &key, value, -1) == -1 && 131 assert(bpf_map_update_elem(lru_map_fd, &key, value, -1) == -1 &&
131 errno == EINVAL); 132 errno == EINVAL);
132 133
133 /* insert key=2 element */ 134 /* insert key=2 element */
134 135
135 /* check that key=2 is not found */ 136 /* check that key=2 is not found */
136 key = 2; 137 key = 2;
137 assert(bpf_map_lookup(lru_map_fd, &key, value) == -1 && 138 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
138 errno == ENOENT); 139 errno == ENOENT);
139 140
140 /* BPF_EXIST means: update existing element */ 141 /* BPF_EXIST means: update existing element */
141 assert(bpf_map_update(lru_map_fd, &key, value, BPF_EXIST) == -1 && 142 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_EXIST) == -1 &&
142 /* key=2 is not there */ 143 /* key=2 is not there */
143 errno == ENOENT); 144 errno == ENOENT);
144 145
145 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 146 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
146 147
147 /* insert key=3 element */ 148 /* insert key=3 element */
148 149
149 /* check that key=3 is not found */ 150 /* check that key=3 is not found */
150 key = 3; 151 key = 3;
151 assert(bpf_map_lookup(lru_map_fd, &key, value) == -1 && 152 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
152 errno == ENOENT); 153 errno == ENOENT);
153 154
154 /* check that key=1 can be found and mark the ref bit to 155 /* check that key=1 can be found and mark the ref bit to
155 * stop LRU from removing key=1 156 * stop LRU from removing key=1
156 */ 157 */
157 key = 1; 158 key = 1;
158 assert(!bpf_map_lookup(lru_map_fd, &key, value)); 159 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value));
159 assert(value[0] == 1234); 160 assert(value[0] == 1234);
160 161
161 key = 3; 162 key = 3;
162 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 163 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
163 assert(!bpf_map_update(expected_map_fd, &key, value, BPF_NOEXIST)); 164 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
165 BPF_NOEXIST));
164 166
165 /* key=2 has been removed from the LRU */ 167 /* key=2 has been removed from the LRU */
166 key = 2; 168 key = 2;
167 assert(bpf_map_lookup(lru_map_fd, &key, value) == -1); 169 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1);
168 170
169 assert(map_equal(lru_map_fd, expected_map_fd)); 171 assert(map_equal(lru_map_fd, expected_map_fd));
170 172
@@ -217,14 +219,15 @@ static void test_lru_sanity1(int map_type, int map_flags, unsigned int tgt_free)
217 /* Insert 1 to tgt_free (+tgt_free keys) */ 219 /* Insert 1 to tgt_free (+tgt_free keys) */
218 end_key = 1 + tgt_free; 220 end_key = 1 + tgt_free;
219 for (key = 1; key < end_key; key++) 221 for (key = 1; key < end_key; key++)
220 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 222 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
223 BPF_NOEXIST));
221 224
222 /* Lookup 1 to tgt_free/2 */ 225 /* Lookup 1 to tgt_free/2 */
223 end_key = 1 + batch_size; 226 end_key = 1 + batch_size;
224 for (key = 1; key < end_key; key++) { 227 for (key = 1; key < end_key; key++) {
225 assert(!bpf_map_lookup(lru_map_fd, &key, value)); 228 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value));
226 assert(!bpf_map_update(expected_map_fd, &key, value, 229 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
227 BPF_NOEXIST)); 230 BPF_NOEXIST));
228 } 231 }
229 232
230 /* Insert 1+tgt_free to 2*tgt_free 233 /* Insert 1+tgt_free to 2*tgt_free
@@ -234,9 +237,10 @@ static void test_lru_sanity1(int map_type, int map_flags, unsigned int tgt_free)
234 key = 1 + tgt_free; 237 key = 1 + tgt_free;
235 end_key = key + tgt_free; 238 end_key = key + tgt_free;
236 for (; key < end_key; key++) { 239 for (; key < end_key; key++) {
237 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 240 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
238 assert(!bpf_map_update(expected_map_fd, &key, value, 241 BPF_NOEXIST));
239 BPF_NOEXIST)); 242 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
243 BPF_NOEXIST));
240 } 244 }
241 245
242 assert(map_equal(lru_map_fd, expected_map_fd)); 246 assert(map_equal(lru_map_fd, expected_map_fd));
@@ -301,9 +305,10 @@ static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free)
301 /* Insert 1 to tgt_free (+tgt_free keys) */ 305 /* Insert 1 to tgt_free (+tgt_free keys) */
302 end_key = 1 + tgt_free; 306 end_key = 1 + tgt_free;
303 for (key = 1; key < end_key; key++) 307 for (key = 1; key < end_key; key++)
304 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 308 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
309 BPF_NOEXIST));
305 310
306 /* Any bpf_map_update will require to acquire a new node 311 /* Any bpf_map_update_elem will require to acquire a new node
307 * from LRU first. 312 * from LRU first.
308 * 313 *
309 * The local list is running out of free nodes. 314 * The local list is running out of free nodes.
@@ -316,10 +321,12 @@ static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free)
316 */ 321 */
317 key = 1; 322 key = 1;
318 if (map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) { 323 if (map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
319 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 324 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
320 assert(!bpf_map_delete(lru_map_fd, &key)); 325 BPF_NOEXIST));
326 assert(!bpf_map_delete_elem(lru_map_fd, &key));
321 } else { 327 } else {
322 assert(bpf_map_update(lru_map_fd, &key, value, BPF_EXIST)); 328 assert(bpf_map_update_elem(lru_map_fd, &key, value,
329 BPF_EXIST));
323 } 330 }
324 331
325 /* Re-insert 1 to tgt_free/2 again and do a lookup 332 /* Re-insert 1 to tgt_free/2 again and do a lookup
@@ -328,12 +335,13 @@ static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free)
328 end_key = 1 + batch_size; 335 end_key = 1 + batch_size;
329 value[0] = 4321; 336 value[0] = 4321;
330 for (key = 1; key < end_key; key++) { 337 for (key = 1; key < end_key; key++) {
331 assert(bpf_map_lookup(lru_map_fd, &key, value)); 338 assert(bpf_map_lookup_elem(lru_map_fd, &key, value));
332 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 339 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
333 assert(!bpf_map_lookup(lru_map_fd, &key, value)); 340 BPF_NOEXIST));
341 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value));
334 assert(value[0] == 4321); 342 assert(value[0] == 4321);
335 assert(!bpf_map_update(expected_map_fd, &key, value, 343 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
336 BPF_NOEXIST)); 344 BPF_NOEXIST));
337 } 345 }
338 346
339 value[0] = 1234; 347 value[0] = 1234;
@@ -344,14 +352,16 @@ static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free)
344 /* These newly added but not referenced keys will be 352 /* These newly added but not referenced keys will be
345 * gone during the next LRU shrink. 353 * gone during the next LRU shrink.
346 */ 354 */
347 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 355 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
356 BPF_NOEXIST));
348 357
349 /* Insert 1+tgt_free*3/2 to tgt_free*5/2 */ 358 /* Insert 1+tgt_free*3/2 to tgt_free*5/2 */
350 end_key = key + tgt_free; 359 end_key = key + tgt_free;
351 for (; key < end_key; key++) { 360 for (; key < end_key; key++) {
352 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 361 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
353 assert(!bpf_map_update(expected_map_fd, &key, value, 362 BPF_NOEXIST));
354 BPF_NOEXIST)); 363 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
364 BPF_NOEXIST));
355 } 365 }
356 366
357 assert(map_equal(lru_map_fd, expected_map_fd)); 367 assert(map_equal(lru_map_fd, expected_map_fd));
@@ -401,14 +411,15 @@ static void test_lru_sanity3(int map_type, int map_flags, unsigned int tgt_free)
401 /* Insert 1 to 2*tgt_free (+2*tgt_free keys) */ 411 /* Insert 1 to 2*tgt_free (+2*tgt_free keys) */
402 end_key = 1 + (2 * tgt_free); 412 end_key = 1 + (2 * tgt_free);
403 for (key = 1; key < end_key; key++) 413 for (key = 1; key < end_key; key++)
404 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 414 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
415 BPF_NOEXIST));
405 416
406 /* Lookup key 1 to tgt_free*3/2 */ 417 /* Lookup key 1 to tgt_free*3/2 */
407 end_key = tgt_free + batch_size; 418 end_key = tgt_free + batch_size;
408 for (key = 1; key < end_key; key++) { 419 for (key = 1; key < end_key; key++) {
409 assert(!bpf_map_lookup(lru_map_fd, &key, value)); 420 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value));
410 assert(!bpf_map_update(expected_map_fd, &key, value, 421 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
411 BPF_NOEXIST)); 422 BPF_NOEXIST));
412 } 423 }
413 424
414 /* Add 1+2*tgt_free to tgt_free*5/2 425 /* Add 1+2*tgt_free to tgt_free*5/2
@@ -417,9 +428,10 @@ static void test_lru_sanity3(int map_type, int map_flags, unsigned int tgt_free)
417 key = 2 * tgt_free + 1; 428 key = 2 * tgt_free + 1;
418 end_key = key + batch_size; 429 end_key = key + batch_size;
419 for (; key < end_key; key++) { 430 for (; key < end_key; key++) {
420 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 431 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
421 assert(!bpf_map_update(expected_map_fd, &key, value, 432 BPF_NOEXIST));
422 BPF_NOEXIST)); 433 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
434 BPF_NOEXIST));
423 } 435 }
424 436
425 assert(map_equal(lru_map_fd, expected_map_fd)); 437 assert(map_equal(lru_map_fd, expected_map_fd));
@@ -457,27 +469,29 @@ static void test_lru_sanity4(int map_type, int map_flags, unsigned int tgt_free)
457 value[0] = 1234; 469 value[0] = 1234;
458 470
459 for (key = 1; key <= 2 * tgt_free; key++) 471 for (key = 1; key <= 2 * tgt_free; key++)
460 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 472 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
473 BPF_NOEXIST));
461 474
462 key = 1; 475 key = 1;
463 assert(bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 476 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
464 477
465 for (key = 1; key <= tgt_free; key++) { 478 for (key = 1; key <= tgt_free; key++) {
466 assert(!bpf_map_lookup(lru_map_fd, &key, value)); 479 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value));
467 assert(!bpf_map_update(expected_map_fd, &key, value, 480 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
468 BPF_NOEXIST)); 481 BPF_NOEXIST));
469 } 482 }
470 483
471 for (; key <= 2 * tgt_free; key++) { 484 for (; key <= 2 * tgt_free; key++) {
472 assert(!bpf_map_delete(lru_map_fd, &key)); 485 assert(!bpf_map_delete_elem(lru_map_fd, &key));
473 assert(bpf_map_delete(lru_map_fd, &key)); 486 assert(bpf_map_delete_elem(lru_map_fd, &key));
474 } 487 }
475 488
476 end_key = key + 2 * tgt_free; 489 end_key = key + 2 * tgt_free;
477 for (; key < end_key; key++) { 490 for (; key < end_key; key++) {
478 assert(!bpf_map_update(lru_map_fd, &key, value, BPF_NOEXIST)); 491 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
479 assert(!bpf_map_update(expected_map_fd, &key, value, 492 BPF_NOEXIST));
480 BPF_NOEXIST)); 493 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
494 BPF_NOEXIST));
481 } 495 }
482 496
483 assert(map_equal(lru_map_fd, expected_map_fd)); 497 assert(map_equal(lru_map_fd, expected_map_fd));
@@ -493,16 +507,16 @@ static void do_test_lru_sanity5(unsigned long long last_key, int map_fd)
493 unsigned long long key, value[nr_cpus]; 507 unsigned long long key, value[nr_cpus];
494 508
495 /* Ensure the last key inserted by previous CPU can be found */ 509 /* Ensure the last key inserted by previous CPU can be found */
496 assert(!bpf_map_lookup(map_fd, &last_key, value)); 510 assert(!bpf_map_lookup_elem(map_fd, &last_key, value));
497 511
498 value[0] = 1234; 512 value[0] = 1234;
499 513
500 key = last_key + 1; 514 key = last_key + 1;
501 assert(!bpf_map_update(map_fd, &key, value, BPF_NOEXIST)); 515 assert(!bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST));
502 assert(!bpf_map_lookup(map_fd, &key, value)); 516 assert(!bpf_map_lookup_elem(map_fd, &key, value));
503 517
504 /* Cannot find the last key because it was removed by LRU */ 518 /* Cannot find the last key because it was removed by LRU */
505 assert(bpf_map_lookup(map_fd, &last_key, value)); 519 assert(bpf_map_lookup_elem(map_fd, &last_key, value));
506} 520}
507 521
508/* Test map with only one element */ 522/* Test map with only one element */
@@ -523,7 +537,7 @@ static void test_lru_sanity5(int map_type, int map_flags)
523 537
524 value[0] = 1234; 538 value[0] = 1234;
525 key = 0; 539 key = 0;
526 assert(!bpf_map_update(map_fd, &key, value, BPF_NOEXIST)); 540 assert(!bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST));
527 541
528 while (sched_next_online(0, &next_cpu) != -1) { 542 while (sched_next_online(0, &next_cpu) != -1) {
529 pid_t pid; 543 pid_t pid;
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index eedfef8d2946..cada17ac00b8 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -21,7 +21,7 @@
21 21
22#include <linux/bpf.h> 22#include <linux/bpf.h>
23 23
24#include "bpf_sys.h" 24#include <bpf/bpf.h>
25#include "bpf_util.h" 25#include "bpf_util.h"
26 26
27static int map_flags; 27static int map_flags;
@@ -31,7 +31,7 @@ static void test_hashmap(int task, void *data)
31 long long key, next_key, value; 31 long long key, next_key, value;
32 int fd; 32 int fd;
33 33
34 fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 34 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
35 2, map_flags); 35 2, map_flags);
36 if (fd < 0) { 36 if (fd < 0) {
37 printf("Failed to create hashmap '%s'!\n", strerror(errno)); 37 printf("Failed to create hashmap '%s'!\n", strerror(errno));
@@ -41,69 +41,70 @@ static void test_hashmap(int task, void *data)
41 key = 1; 41 key = 1;
42 value = 1234; 42 value = 1234;
43 /* Insert key=1 element. */ 43 /* Insert key=1 element. */
44 assert(bpf_map_update(fd, &key, &value, BPF_ANY) == 0); 44 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
45 45
46 value = 0; 46 value = 0;
47 /* BPF_NOEXIST means add new element if it doesn't exist. */ 47 /* BPF_NOEXIST means add new element if it doesn't exist. */
48 assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 && 48 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
49 /* key=1 already exists. */ 49 /* key=1 already exists. */
50 errno == EEXIST); 50 errno == EEXIST);
51 51
52 /* -1 is an invalid flag. */ 52 /* -1 is an invalid flag. */
53 assert(bpf_map_update(fd, &key, &value, -1) == -1 && errno == EINVAL); 53 assert(bpf_map_update_elem(fd, &key, &value, -1) == -1 &&
54 errno == EINVAL);
54 55
55 /* Check that key=1 can be found. */ 56 /* Check that key=1 can be found. */
56 assert(bpf_map_lookup(fd, &key, &value) == 0 && value == 1234); 57 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
57 58
58 key = 2; 59 key = 2;
59 /* Check that key=2 is not found. */ 60 /* Check that key=2 is not found. */
60 assert(bpf_map_lookup(fd, &key, &value) == -1 && errno == ENOENT); 61 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
61 62
62 /* BPF_EXIST means update existing element. */ 63 /* BPF_EXIST means update existing element. */
63 assert(bpf_map_update(fd, &key, &value, BPF_EXIST) == -1 && 64 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 &&
64 /* key=2 is not there. */ 65 /* key=2 is not there. */
65 errno == ENOENT); 66 errno == ENOENT);
66 67
67 /* Insert key=2 element. */ 68 /* Insert key=2 element. */
68 assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == 0); 69 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
69 70
70 /* key=1 and key=2 were inserted, check that key=0 cannot be 71 /* key=1 and key=2 were inserted, check that key=0 cannot be
71 * inserted due to max_entries limit. 72 * inserted due to max_entries limit.
72 */ 73 */
73 key = 0; 74 key = 0;
74 assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 && 75 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
75 errno == E2BIG); 76 errno == E2BIG);
76 77
77 /* Update existing element, though the map is full. */ 78 /* Update existing element, though the map is full. */
78 key = 1; 79 key = 1;
79 assert(bpf_map_update(fd, &key, &value, BPF_EXIST) == 0); 80 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
80 key = 2; 81 key = 2;
81 assert(bpf_map_update(fd, &key, &value, BPF_ANY) == 0); 82 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
82 key = 1; 83 key = 1;
83 assert(bpf_map_update(fd, &key, &value, BPF_ANY) == 0); 84 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
84 85
85 /* Check that key = 0 doesn't exist. */ 86 /* Check that key = 0 doesn't exist. */
86 key = 0; 87 key = 0;
87 assert(bpf_map_delete(fd, &key) == -1 && errno == ENOENT); 88 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
88 89
89 /* Iterate over two elements. */ 90 /* Iterate over two elements. */
90 assert(bpf_map_next_key(fd, &key, &next_key) == 0 && 91 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
91 (next_key == 1 || next_key == 2)); 92 (next_key == 1 || next_key == 2));
92 assert(bpf_map_next_key(fd, &next_key, &next_key) == 0 && 93 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
93 (next_key == 1 || next_key == 2)); 94 (next_key == 1 || next_key == 2));
94 assert(bpf_map_next_key(fd, &next_key, &next_key) == -1 && 95 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
95 errno == ENOENT); 96 errno == ENOENT);
96 97
97 /* Delete both elements. */ 98 /* Delete both elements. */
98 key = 1; 99 key = 1;
99 assert(bpf_map_delete(fd, &key) == 0); 100 assert(bpf_map_delete_elem(fd, &key) == 0);
100 key = 2; 101 key = 2;
101 assert(bpf_map_delete(fd, &key) == 0); 102 assert(bpf_map_delete_elem(fd, &key) == 0);
102 assert(bpf_map_delete(fd, &key) == -1 && errno == ENOENT); 103 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
103 104
104 key = 0; 105 key = 0;
105 /* Check that map is empty. */ 106 /* Check that map is empty. */
106 assert(bpf_map_next_key(fd, &key, &next_key) == -1 && 107 assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 &&
107 errno == ENOENT); 108 errno == ENOENT);
108 109
109 close(fd); 110 close(fd);
@@ -117,7 +118,7 @@ static void test_hashmap_percpu(int task, void *data)
117 int expected_key_mask = 0; 118 int expected_key_mask = 0;
118 int fd, i; 119 int fd, i;
119 120
120 fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key), 121 fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key),
121 sizeof(value[0]), 2, map_flags); 122 sizeof(value[0]), 2, map_flags);
122 if (fd < 0) { 123 if (fd < 0) {
123 printf("Failed to create hashmap '%s'!\n", strerror(errno)); 124 printf("Failed to create hashmap '%s'!\n", strerror(errno));
@@ -130,53 +131,54 @@ static void test_hashmap_percpu(int task, void *data)
130 key = 1; 131 key = 1;
131 /* Insert key=1 element. */ 132 /* Insert key=1 element. */
132 assert(!(expected_key_mask & key)); 133 assert(!(expected_key_mask & key));
133 assert(bpf_map_update(fd, &key, value, BPF_ANY) == 0); 134 assert(bpf_map_update_elem(fd, &key, value, BPF_ANY) == 0);
134 expected_key_mask |= key; 135 expected_key_mask |= key;
135 136
136 /* BPF_NOEXIST means add new element if it doesn't exist. */ 137 /* BPF_NOEXIST means add new element if it doesn't exist. */
137 assert(bpf_map_update(fd, &key, value, BPF_NOEXIST) == -1 && 138 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 &&
138 /* key=1 already exists. */ 139 /* key=1 already exists. */
139 errno == EEXIST); 140 errno == EEXIST);
140 141
141 /* -1 is an invalid flag. */ 142 /* -1 is an invalid flag. */
142 assert(bpf_map_update(fd, &key, value, -1) == -1 && errno == EINVAL); 143 assert(bpf_map_update_elem(fd, &key, value, -1) == -1 &&
144 errno == EINVAL);
143 145
144 /* Check that key=1 can be found. Value could be 0 if the lookup 146 /* Check that key=1 can be found. Value could be 0 if the lookup
145 * was run from a different CPU. 147 * was run from a different CPU.
146 */ 148 */
147 value[0] = 1; 149 value[0] = 1;
148 assert(bpf_map_lookup(fd, &key, value) == 0 && value[0] == 100); 150 assert(bpf_map_lookup_elem(fd, &key, value) == 0 && value[0] == 100);
149 151
150 key = 2; 152 key = 2;
151 /* Check that key=2 is not found. */ 153 /* Check that key=2 is not found. */
152 assert(bpf_map_lookup(fd, &key, value) == -1 && errno == ENOENT); 154 assert(bpf_map_lookup_elem(fd, &key, value) == -1 && errno == ENOENT);
153 155
154 /* BPF_EXIST means update existing element. */ 156 /* BPF_EXIST means update existing element. */
155 assert(bpf_map_update(fd, &key, value, BPF_EXIST) == -1 && 157 assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == -1 &&
156 /* key=2 is not there. */ 158 /* key=2 is not there. */
157 errno == ENOENT); 159 errno == ENOENT);
158 160
159 /* Insert key=2 element. */ 161 /* Insert key=2 element. */
160 assert(!(expected_key_mask & key)); 162 assert(!(expected_key_mask & key));
161 assert(bpf_map_update(fd, &key, value, BPF_NOEXIST) == 0); 163 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0);
162 expected_key_mask |= key; 164 expected_key_mask |= key;
163 165
164 /* key=1 and key=2 were inserted, check that key=0 cannot be 166 /* key=1 and key=2 were inserted, check that key=0 cannot be
165 * inserted due to max_entries limit. 167 * inserted due to max_entries limit.
166 */ 168 */
167 key = 0; 169 key = 0;
168 assert(bpf_map_update(fd, &key, value, BPF_NOEXIST) == -1 && 170 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 &&
169 errno == E2BIG); 171 errno == E2BIG);
170 172
171 /* Check that key = 0 doesn't exist. */ 173 /* Check that key = 0 doesn't exist. */
172 assert(bpf_map_delete(fd, &key) == -1 && errno == ENOENT); 174 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
173 175
174 /* Iterate over two elements. */ 176 /* Iterate over two elements. */
175 while (!bpf_map_next_key(fd, &key, &next_key)) { 177 while (!bpf_map_get_next_key(fd, &key, &next_key)) {
176 assert((expected_key_mask & next_key) == next_key); 178 assert((expected_key_mask & next_key) == next_key);
177 expected_key_mask &= ~next_key; 179 expected_key_mask &= ~next_key;
178 180
179 assert(bpf_map_lookup(fd, &next_key, value) == 0); 181 assert(bpf_map_lookup_elem(fd, &next_key, value) == 0);
180 182
181 for (i = 0; i < nr_cpus; i++) 183 for (i = 0; i < nr_cpus; i++)
182 assert(value[i] == i + 100); 184 assert(value[i] == i + 100);
@@ -187,18 +189,18 @@ static void test_hashmap_percpu(int task, void *data)
187 189
188 /* Update with BPF_EXIST. */ 190 /* Update with BPF_EXIST. */
189 key = 1; 191 key = 1;
190 assert(bpf_map_update(fd, &key, value, BPF_EXIST) == 0); 192 assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0);
191 193
192 /* Delete both elements. */ 194 /* Delete both elements. */
193 key = 1; 195 key = 1;
194 assert(bpf_map_delete(fd, &key) == 0); 196 assert(bpf_map_delete_elem(fd, &key) == 0);
195 key = 2; 197 key = 2;
196 assert(bpf_map_delete(fd, &key) == 0); 198 assert(bpf_map_delete_elem(fd, &key) == 0);
197 assert(bpf_map_delete(fd, &key) == -1 && errno == ENOENT); 199 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
198 200
199 key = 0; 201 key = 0;
200 /* Check that map is empty. */ 202 /* Check that map is empty. */
201 assert(bpf_map_next_key(fd, &key, &next_key) == -1 && 203 assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 &&
202 errno == ENOENT); 204 errno == ENOENT);
203 205
204 close(fd); 206 close(fd);
@@ -209,7 +211,7 @@ static void test_arraymap(int task, void *data)
209 int key, next_key, fd; 211 int key, next_key, fd;
210 long long value; 212 long long value;
211 213
212 fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value), 214 fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value),
213 2, 0); 215 2, 0);
214 if (fd < 0) { 216 if (fd < 0) {
215 printf("Failed to create arraymap '%s'!\n", strerror(errno)); 217 printf("Failed to create arraymap '%s'!\n", strerror(errno));
@@ -219,40 +221,40 @@ static void test_arraymap(int task, void *data)
219 key = 1; 221 key = 1;
220 value = 1234; 222 value = 1234;
221 /* Insert key=1 element. */ 223 /* Insert key=1 element. */
222 assert(bpf_map_update(fd, &key, &value, BPF_ANY) == 0); 224 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
223 225
224 value = 0; 226 value = 0;
225 assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 && 227 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
226 errno == EEXIST); 228 errno == EEXIST);
227 229
228 /* Check that key=1 can be found. */ 230 /* Check that key=1 can be found. */
229 assert(bpf_map_lookup(fd, &key, &value) == 0 && value == 1234); 231 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
230 232
231 key = 0; 233 key = 0;
232 /* Check that key=0 is also found and zero initialized. */ 234 /* Check that key=0 is also found and zero initialized. */
233 assert(bpf_map_lookup(fd, &key, &value) == 0 && value == 0); 235 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
234 236
235 /* key=0 and key=1 were inserted, check that key=2 cannot be inserted 237 /* key=0 and key=1 were inserted, check that key=2 cannot be inserted
236 * due to max_entries limit. 238 * due to max_entries limit.
237 */ 239 */
238 key = 2; 240 key = 2;
239 assert(bpf_map_update(fd, &key, &value, BPF_EXIST) == -1 && 241 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 &&
240 errno == E2BIG); 242 errno == E2BIG);
241 243
242 /* Check that key = 2 doesn't exist. */ 244 /* Check that key = 2 doesn't exist. */
243 assert(bpf_map_lookup(fd, &key, &value) == -1 && errno == ENOENT); 245 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
244 246
245 /* Iterate over two elements. */ 247 /* Iterate over two elements. */
246 assert(bpf_map_next_key(fd, &key, &next_key) == 0 && 248 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
247 next_key == 0); 249 next_key == 0);
248 assert(bpf_map_next_key(fd, &next_key, &next_key) == 0 && 250 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
249 next_key == 1); 251 next_key == 1);
250 assert(bpf_map_next_key(fd, &next_key, &next_key) == -1 && 252 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
251 errno == ENOENT); 253 errno == ENOENT);
252 254
253 /* Delete shouldn't succeed. */ 255 /* Delete shouldn't succeed. */
254 key = 1; 256 key = 1;
255 assert(bpf_map_delete(fd, &key) == -1 && errno == EINVAL); 257 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL);
256 258
257 close(fd); 259 close(fd);
258} 260}
@@ -263,7 +265,7 @@ static void test_arraymap_percpu(int task, void *data)
263 int key, next_key, fd, i; 265 int key, next_key, fd, i;
264 long values[nr_cpus]; 266 long values[nr_cpus];
265 267
266 fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key), 268 fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
267 sizeof(values[0]), 2, 0); 269 sizeof(values[0]), 2, 0);
268 if (fd < 0) { 270 if (fd < 0) {
269 printf("Failed to create arraymap '%s'!\n", strerror(errno)); 271 printf("Failed to create arraymap '%s'!\n", strerror(errno));
@@ -275,39 +277,39 @@ static void test_arraymap_percpu(int task, void *data)
275 277
276 key = 1; 278 key = 1;
277 /* Insert key=1 element. */ 279 /* Insert key=1 element. */
278 assert(bpf_map_update(fd, &key, values, BPF_ANY) == 0); 280 assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
279 281
280 values[0] = 0; 282 values[0] = 0;
281 assert(bpf_map_update(fd, &key, values, BPF_NOEXIST) == -1 && 283 assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) == -1 &&
282 errno == EEXIST); 284 errno == EEXIST);
283 285
284 /* Check that key=1 can be found. */ 286 /* Check that key=1 can be found. */
285 assert(bpf_map_lookup(fd, &key, values) == 0 && values[0] == 100); 287 assert(bpf_map_lookup_elem(fd, &key, values) == 0 && values[0] == 100);
286 288
287 key = 0; 289 key = 0;
288 /* Check that key=0 is also found and zero initialized. */ 290 /* Check that key=0 is also found and zero initialized. */
289 assert(bpf_map_lookup(fd, &key, values) == 0 && 291 assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
290 values[0] == 0 && values[nr_cpus - 1] == 0); 292 values[0] == 0 && values[nr_cpus - 1] == 0);
291 293
292 /* Check that key=2 cannot be inserted due to max_entries limit. */ 294 /* Check that key=2 cannot be inserted due to max_entries limit. */
293 key = 2; 295 key = 2;
294 assert(bpf_map_update(fd, &key, values, BPF_EXIST) == -1 && 296 assert(bpf_map_update_elem(fd, &key, values, BPF_EXIST) == -1 &&
295 errno == E2BIG); 297 errno == E2BIG);
296 298
297 /* Check that key = 2 doesn't exist. */ 299 /* Check that key = 2 doesn't exist. */
298 assert(bpf_map_lookup(fd, &key, values) == -1 && errno == ENOENT); 300 assert(bpf_map_lookup_elem(fd, &key, values) == -1 && errno == ENOENT);
299 301
300 /* Iterate over two elements. */ 302 /* Iterate over two elements. */
301 assert(bpf_map_next_key(fd, &key, &next_key) == 0 && 303 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
302 next_key == 0); 304 next_key == 0);
303 assert(bpf_map_next_key(fd, &next_key, &next_key) == 0 && 305 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
304 next_key == 1); 306 next_key == 1);
305 assert(bpf_map_next_key(fd, &next_key, &next_key) == -1 && 307 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
306 errno == ENOENT); 308 errno == ENOENT);
307 309
308 /* Delete shouldn't succeed. */ 310 /* Delete shouldn't succeed. */
309 key = 1; 311 key = 1;
310 assert(bpf_map_delete(fd, &key) == -1 && errno == EINVAL); 312 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL);
311 313
312 close(fd); 314 close(fd);
313} 315}
@@ -319,7 +321,7 @@ static void test_arraymap_percpu_many_keys(void)
319 long values[nr_cpus]; 321 long values[nr_cpus];
320 int key, fd, i; 322 int key, fd, i;
321 323
322 fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key), 324 fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
323 sizeof(values[0]), nr_keys, 0); 325 sizeof(values[0]), nr_keys, 0);
324 if (fd < 0) { 326 if (fd < 0) {
325 printf("Failed to create per-cpu arraymap '%s'!\n", 327 printf("Failed to create per-cpu arraymap '%s'!\n",
@@ -331,13 +333,13 @@ static void test_arraymap_percpu_many_keys(void)
331 values[i] = i + 10; 333 values[i] = i + 10;
332 334
333 for (key = 0; key < nr_keys; key++) 335 for (key = 0; key < nr_keys; key++)
334 assert(bpf_map_update(fd, &key, values, BPF_ANY) == 0); 336 assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
335 337
336 for (key = 0; key < nr_keys; key++) { 338 for (key = 0; key < nr_keys; key++) {
337 for (i = 0; i < nr_cpus; i++) 339 for (i = 0; i < nr_cpus; i++)
338 values[i] = 0; 340 values[i] = 0;
339 341
340 assert(bpf_map_lookup(fd, &key, values) == 0); 342 assert(bpf_map_lookup_elem(fd, &key, values) == 0);
341 343
342 for (i = 0; i < nr_cpus; i++) 344 for (i = 0; i < nr_cpus; i++)
343 assert(values[i] == i + 10); 345 assert(values[i] == i + 10);
@@ -357,7 +359,7 @@ static void test_map_large(void)
357 } key; 359 } key;
358 int fd, i, value; 360 int fd, i, value;
359 361
360 fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 362 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
361 MAP_SIZE, map_flags); 363 MAP_SIZE, map_flags);
362 if (fd < 0) { 364 if (fd < 0) {
363 printf("Failed to create large map '%s'!\n", strerror(errno)); 365 printf("Failed to create large map '%s'!\n", strerror(errno));
@@ -368,22 +370,22 @@ static void test_map_large(void)
368 key = (struct bigkey) { .c = i }; 370 key = (struct bigkey) { .c = i };
369 value = i; 371 value = i;
370 372
371 assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == 0); 373 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
372 } 374 }
373 375
374 key.c = -1; 376 key.c = -1;
375 assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 && 377 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
376 errno == E2BIG); 378 errno == E2BIG);
377 379
378 /* Iterate through all elements. */ 380 /* Iterate through all elements. */
379 for (i = 0; i < MAP_SIZE; i++) 381 for (i = 0; i < MAP_SIZE; i++)
380 assert(bpf_map_next_key(fd, &key, &key) == 0); 382 assert(bpf_map_get_next_key(fd, &key, &key) == 0);
381 assert(bpf_map_next_key(fd, &key, &key) == -1 && errno == ENOENT); 383 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
382 384
383 key.c = 0; 385 key.c = 0;
384 assert(bpf_map_lookup(fd, &key, &value) == 0 && value == 0); 386 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
385 key.a = 1; 387 key.a = 1;
386 assert(bpf_map_lookup(fd, &key, &value) == -1 && errno == ENOENT); 388 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
387 389
388 close(fd); 390 close(fd);
389} 391}
@@ -437,10 +439,12 @@ static void do_work(int fn, void *data)
437 key = value = i; 439 key = value = i;
438 440
439 if (do_update) { 441 if (do_update) {
440 assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == 0); 442 assert(bpf_map_update_elem(fd, &key, &value,
441 assert(bpf_map_update(fd, &key, &value, BPF_EXIST) == 0); 443 BPF_NOEXIST) == 0);
444 assert(bpf_map_update_elem(fd, &key, &value,
445 BPF_EXIST) == 0);
442 } else { 446 } else {
443 assert(bpf_map_delete(fd, &key) == 0); 447 assert(bpf_map_delete_elem(fd, &key) == 0);
444 } 448 }
445 } 449 }
446} 450}
@@ -450,7 +454,7 @@ static void test_map_parallel(void)
450 int i, fd, key = 0, value = 0; 454 int i, fd, key = 0, value = 0;
451 int data[2]; 455 int data[2];
452 456
453 fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 457 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
454 MAP_SIZE, map_flags); 458 MAP_SIZE, map_flags);
455 if (fd < 0) { 459 if (fd < 0) {
456 printf("Failed to create map for parallel test '%s'!\n", 460 printf("Failed to create map for parallel test '%s'!\n",
@@ -468,20 +472,20 @@ static void test_map_parallel(void)
468 run_parallel(TASKS, do_work, data); 472 run_parallel(TASKS, do_work, data);
469 473
470 /* Check that key=0 is already there. */ 474 /* Check that key=0 is already there. */
471 assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 && 475 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
472 errno == EEXIST); 476 errno == EEXIST);
473 477
474 /* Check that all elements were inserted. */ 478 /* Check that all elements were inserted. */
475 key = -1; 479 key = -1;
476 for (i = 0; i < MAP_SIZE; i++) 480 for (i = 0; i < MAP_SIZE; i++)
477 assert(bpf_map_next_key(fd, &key, &key) == 0); 481 assert(bpf_map_get_next_key(fd, &key, &key) == 0);
478 assert(bpf_map_next_key(fd, &key, &key) == -1 && errno == ENOENT); 482 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
479 483
480 /* Another check for all elements */ 484 /* Another check for all elements */
481 for (i = 0; i < MAP_SIZE; i++) { 485 for (i = 0; i < MAP_SIZE; i++) {
482 key = MAP_SIZE - i - 1; 486 key = MAP_SIZE - i - 1;
483 487
484 assert(bpf_map_lookup(fd, &key, &value) == 0 && 488 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 &&
485 value == key); 489 value == key);
486 } 490 }
487 491
@@ -491,7 +495,7 @@ static void test_map_parallel(void)
491 495
492 /* Nothing should be left. */ 496 /* Nothing should be left. */
493 key = -1; 497 key = -1;
494 assert(bpf_map_next_key(fd, &key, &key) == -1 && errno == ENOENT); 498 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
495} 499}
496 500
497static void run_all_tests(void) 501static void run_all_tests(void)
diff --git a/tools/testing/selftests/bpf/test_tag.c b/tools/testing/selftests/bpf/test_tag.c
new file mode 100644
index 000000000000..de409fc50c35
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_tag.c
@@ -0,0 +1,203 @@
1#include <stdint.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <ctype.h>
5#include <time.h>
6#include <errno.h>
7#include <unistd.h>
8#include <string.h>
9#include <sched.h>
10#include <limits.h>
11#include <assert.h>
12
13#include <sys/socket.h>
14#include <sys/resource.h>
15
16#include <linux/filter.h>
17#include <linux/bpf.h>
18#include <linux/if_alg.h>
19
20#include <bpf/bpf.h>
21
22#include "../../../include/linux/filter.h"
23
24static struct bpf_insn prog[BPF_MAXINSNS];
25
26static void bpf_gen_imm_prog(unsigned int insns, int fd_map)
27{
28 int i;
29
30 srand(time(NULL));
31 for (i = 0; i < insns; i++)
32 prog[i] = BPF_ALU64_IMM(BPF_MOV, i % BPF_REG_10, rand());
33 prog[i - 1] = BPF_EXIT_INSN();
34}
35
36static void bpf_gen_map_prog(unsigned int insns, int fd_map)
37{
38 int i, j = 0;
39
40 for (i = 0; i + 1 < insns; i += 2) {
41 struct bpf_insn tmp[] = {
42 BPF_LD_MAP_FD(j++ % BPF_REG_10, fd_map)
43 };
44
45 memcpy(&prog[i], tmp, sizeof(tmp));
46 }
47 if (insns % 2 == 0)
48 prog[insns - 2] = BPF_ALU64_IMM(BPF_MOV, i % BPF_REG_10, 42);
49 prog[insns - 1] = BPF_EXIT_INSN();
50}
51
52static int bpf_try_load_prog(int insns, int fd_map,
53 void (*bpf_filler)(unsigned int insns,
54 int fd_map))
55{
56 int fd_prog;
57
58 bpf_filler(insns, fd_map);
59 fd_prog = bpf_load_program(BPF_PROG_TYPE_SCHED_CLS, prog, insns, "", 0,
60 NULL, 0);
61 assert(fd_prog > 0);
62 if (fd_map > 0)
63 bpf_filler(insns, 0);
64 return fd_prog;
65}
66
67static int __hex2bin(char ch)
68{
69 if ((ch >= '0') && (ch <= '9'))
70 return ch - '0';
71 ch = tolower(ch);
72 if ((ch >= 'a') && (ch <= 'f'))
73 return ch - 'a' + 10;
74 return -1;
75}
76
77static int hex2bin(uint8_t *dst, const char *src, size_t count)
78{
79 while (count--) {
80 int hi = __hex2bin(*src++);
81 int lo = __hex2bin(*src++);
82
83 if ((hi < 0) || (lo < 0))
84 return -1;
85 *dst++ = (hi << 4) | lo;
86 }
87 return 0;
88}
89
90static void tag_from_fdinfo(int fd_prog, uint8_t *tag, uint32_t len)
91{
92 const int prefix_len = sizeof("prog_tag:\t") - 1;
93 char buff[256];
94 int ret = -1;
95 FILE *fp;
96
97 snprintf(buff, sizeof(buff), "/proc/%d/fdinfo/%d", getpid(),
98 fd_prog);
99 fp = fopen(buff, "r");
100 assert(fp);
101
102 while (fgets(buff, sizeof(buff), fp)) {
103 if (strncmp(buff, "prog_tag:\t", prefix_len))
104 continue;
105 ret = hex2bin(tag, buff + prefix_len, len);
106 break;
107 }
108
109 fclose(fp);
110 assert(!ret);
111}
112
113static void tag_from_alg(int insns, uint8_t *tag, uint32_t len)
114{
115 static const struct sockaddr_alg alg = {
116 .salg_family = AF_ALG,
117 .salg_type = "hash",
118 .salg_name = "sha1",
119 };
120 int fd_base, fd_alg, ret;
121 ssize_t size;
122
123 fd_base = socket(AF_ALG, SOCK_SEQPACKET, 0);
124 assert(fd_base > 0);
125
126 ret = bind(fd_base, (struct sockaddr *)&alg, sizeof(alg));
127 assert(!ret);
128
129 fd_alg = accept(fd_base, NULL, 0);
130 assert(fd_alg > 0);
131
132 insns *= sizeof(struct bpf_insn);
133 size = write(fd_alg, prog, insns);
134 assert(size == insns);
135
136 size = read(fd_alg, tag, len);
137 assert(size == len);
138
139 close(fd_alg);
140 close(fd_base);
141}
142
143static void tag_dump(const char *prefix, uint8_t *tag, uint32_t len)
144{
145 int i;
146
147 printf("%s", prefix);
148 for (i = 0; i < len; i++)
149 printf("%02x", tag[i]);
150 printf("\n");
151}
152
153static void tag_exit_report(int insns, int fd_map, uint8_t *ftag,
154 uint8_t *atag, uint32_t len)
155{
156 printf("Program tag mismatch for %d insns%s!\n", insns,
157 fd_map < 0 ? "" : " with map");
158
159 tag_dump(" fdinfo result: ", ftag, len);
160 tag_dump(" af_alg result: ", atag, len);
161 exit(1);
162}
163
164static void do_test(uint32_t *tests, int start_insns, int fd_map,
165 void (*bpf_filler)(unsigned int insns, int fd))
166{
167 int i, fd_prog;
168
169 for (i = start_insns; i <= BPF_MAXINSNS; i++) {
170 uint8_t ftag[8], atag[sizeof(ftag)];
171
172 fd_prog = bpf_try_load_prog(i, fd_map, bpf_filler);
173 tag_from_fdinfo(fd_prog, ftag, sizeof(ftag));
174 tag_from_alg(i, atag, sizeof(atag));
175 if (memcmp(ftag, atag, sizeof(ftag)))
176 tag_exit_report(i, fd_map, ftag, atag, sizeof(ftag));
177
178 close(fd_prog);
179 sched_yield();
180 (*tests)++;
181 }
182}
183
184int main(void)
185{
186 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
187 uint32_t tests = 0;
188 int i, fd_map;
189
190 setrlimit(RLIMIT_MEMLOCK, &rinf);
191 fd_map = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(int),
192 sizeof(int), 1, BPF_F_NO_PREALLOC);
193 assert(fd_map > 0);
194
195 for (i = 0; i < 5; i++) {
196 do_test(&tests, 2, -1, bpf_gen_imm_prog);
197 do_test(&tests, 3, fd_map, bpf_gen_map_prog);
198 }
199
200 printf("test_tag: OK (%u tests)\n", tests);
201 close(fd_map);
202 return 0;
203}
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 853d7e43434a..e1f5b9eea1e8 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -8,7 +8,9 @@
8 * License as published by the Free Software Foundation. 8 * License as published by the Free Software Foundation.
9 */ 9 */
10 10
11#include <stdint.h>
11#include <stdio.h> 12#include <stdio.h>
13#include <stdlib.h>
12#include <unistd.h> 14#include <unistd.h>
13#include <errno.h> 15#include <errno.h>
14#include <string.h> 16#include <string.h>
@@ -16,6 +18,7 @@
16#include <stdbool.h> 18#include <stdbool.h>
17#include <sched.h> 19#include <sched.h>
18 20
21#include <sys/capability.h>
19#include <sys/resource.h> 22#include <sys/resource.h>
20 23
21#include <linux/unistd.h> 24#include <linux/unistd.h>
@@ -23,9 +26,9 @@
23#include <linux/bpf_perf_event.h> 26#include <linux/bpf_perf_event.h>
24#include <linux/bpf.h> 27#include <linux/bpf.h>
25 28
26#include "../../../include/linux/filter.h" 29#include <bpf/bpf.h>
27 30
28#include "bpf_sys.h" 31#include "../../../include/linux/filter.h"
29 32
30#ifndef ARRAY_SIZE 33#ifndef ARRAY_SIZE
31# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 34# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@@ -859,15 +862,451 @@ static struct bpf_test tests[] = {
859 .result = REJECT, 862 .result = REJECT,
860 }, 863 },
861 { 864 {
862 "check non-u32 access to cb", 865 "check cb access: byte",
863 .insns = { 866 .insns = {
864 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_1, 867 BPF_MOV64_IMM(BPF_REG_0, 0),
868 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
869 offsetof(struct __sk_buff, cb[0])),
870 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
871 offsetof(struct __sk_buff, cb[0]) + 1),
872 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
873 offsetof(struct __sk_buff, cb[0]) + 2),
874 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
875 offsetof(struct __sk_buff, cb[0]) + 3),
876 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
877 offsetof(struct __sk_buff, cb[1])),
878 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
879 offsetof(struct __sk_buff, cb[1]) + 1),
880 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
881 offsetof(struct __sk_buff, cb[1]) + 2),
882 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
883 offsetof(struct __sk_buff, cb[1]) + 3),
884 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
885 offsetof(struct __sk_buff, cb[2])),
886 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
887 offsetof(struct __sk_buff, cb[2]) + 1),
888 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
889 offsetof(struct __sk_buff, cb[2]) + 2),
890 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
891 offsetof(struct __sk_buff, cb[2]) + 3),
892 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
893 offsetof(struct __sk_buff, cb[3])),
894 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
895 offsetof(struct __sk_buff, cb[3]) + 1),
896 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
897 offsetof(struct __sk_buff, cb[3]) + 2),
898 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
899 offsetof(struct __sk_buff, cb[3]) + 3),
900 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
901 offsetof(struct __sk_buff, cb[4])),
902 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
903 offsetof(struct __sk_buff, cb[4]) + 1),
904 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
905 offsetof(struct __sk_buff, cb[4]) + 2),
906 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
907 offsetof(struct __sk_buff, cb[4]) + 3),
908 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
909 offsetof(struct __sk_buff, cb[0])),
910 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
911 offsetof(struct __sk_buff, cb[0]) + 1),
912 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
913 offsetof(struct __sk_buff, cb[0]) + 2),
914 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
915 offsetof(struct __sk_buff, cb[0]) + 3),
916 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
917 offsetof(struct __sk_buff, cb[1])),
918 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
919 offsetof(struct __sk_buff, cb[1]) + 1),
920 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
921 offsetof(struct __sk_buff, cb[1]) + 2),
922 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
923 offsetof(struct __sk_buff, cb[1]) + 3),
924 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
925 offsetof(struct __sk_buff, cb[2])),
926 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
927 offsetof(struct __sk_buff, cb[2]) + 1),
928 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
929 offsetof(struct __sk_buff, cb[2]) + 2),
930 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
931 offsetof(struct __sk_buff, cb[2]) + 3),
932 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
933 offsetof(struct __sk_buff, cb[3])),
934 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
935 offsetof(struct __sk_buff, cb[3]) + 1),
936 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
937 offsetof(struct __sk_buff, cb[3]) + 2),
938 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
939 offsetof(struct __sk_buff, cb[3]) + 3),
940 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
941 offsetof(struct __sk_buff, cb[4])),
942 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
943 offsetof(struct __sk_buff, cb[4]) + 1),
944 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
945 offsetof(struct __sk_buff, cb[4]) + 2),
946 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
947 offsetof(struct __sk_buff, cb[4]) + 3),
948 BPF_EXIT_INSN(),
949 },
950 .result = ACCEPT,
951 },
952 {
953 "check cb access: byte, oob 1",
954 .insns = {
955 BPF_MOV64_IMM(BPF_REG_0, 0),
956 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
957 offsetof(struct __sk_buff, cb[4]) + 4),
958 BPF_EXIT_INSN(),
959 },
960 .errstr = "invalid bpf_context access",
961 .result = REJECT,
962 },
963 {
964 "check cb access: byte, oob 2",
965 .insns = {
966 BPF_MOV64_IMM(BPF_REG_0, 0),
967 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
968 offsetof(struct __sk_buff, cb[0]) - 1),
969 BPF_EXIT_INSN(),
970 },
971 .errstr = "invalid bpf_context access",
972 .result = REJECT,
973 },
974 {
975 "check cb access: byte, oob 3",
976 .insns = {
977 BPF_MOV64_IMM(BPF_REG_0, 0),
978 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
979 offsetof(struct __sk_buff, cb[4]) + 4),
980 BPF_EXIT_INSN(),
981 },
982 .errstr = "invalid bpf_context access",
983 .result = REJECT,
984 },
985 {
986 "check cb access: byte, oob 4",
987 .insns = {
988 BPF_MOV64_IMM(BPF_REG_0, 0),
989 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
990 offsetof(struct __sk_buff, cb[0]) - 1),
991 BPF_EXIT_INSN(),
992 },
993 .errstr = "invalid bpf_context access",
994 .result = REJECT,
995 },
996 {
997 "check cb access: byte, wrong type",
998 .insns = {
999 BPF_MOV64_IMM(BPF_REG_0, 0),
1000 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
1001 offsetof(struct __sk_buff, cb[0])),
1002 BPF_EXIT_INSN(),
1003 },
1004 .errstr = "invalid bpf_context access",
1005 .result = REJECT,
1006 .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
1007 },
1008 {
1009 "check cb access: half",
1010 .insns = {
1011 BPF_MOV64_IMM(BPF_REG_0, 0),
1012 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1013 offsetof(struct __sk_buff, cb[0])),
1014 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1015 offsetof(struct __sk_buff, cb[0]) + 2),
1016 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1017 offsetof(struct __sk_buff, cb[1])),
1018 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1019 offsetof(struct __sk_buff, cb[1]) + 2),
1020 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1021 offsetof(struct __sk_buff, cb[2])),
1022 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1023 offsetof(struct __sk_buff, cb[2]) + 2),
1024 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1025 offsetof(struct __sk_buff, cb[3])),
1026 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1027 offsetof(struct __sk_buff, cb[3]) + 2),
1028 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1029 offsetof(struct __sk_buff, cb[4])),
1030 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1031 offsetof(struct __sk_buff, cb[4]) + 2),
1032 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1033 offsetof(struct __sk_buff, cb[0])),
1034 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1035 offsetof(struct __sk_buff, cb[0]) + 2),
1036 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1037 offsetof(struct __sk_buff, cb[1])),
1038 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1039 offsetof(struct __sk_buff, cb[1]) + 2),
1040 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1041 offsetof(struct __sk_buff, cb[2])),
1042 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1043 offsetof(struct __sk_buff, cb[2]) + 2),
1044 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1045 offsetof(struct __sk_buff, cb[3])),
1046 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1047 offsetof(struct __sk_buff, cb[3]) + 2),
1048 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1049 offsetof(struct __sk_buff, cb[4])),
1050 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1051 offsetof(struct __sk_buff, cb[4]) + 2),
1052 BPF_EXIT_INSN(),
1053 },
1054 .result = ACCEPT,
1055 },
1056 {
1057 "check cb access: half, unaligned",
1058 .insns = {
1059 BPF_MOV64_IMM(BPF_REG_0, 0),
1060 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1061 offsetof(struct __sk_buff, cb[0]) + 1),
1062 BPF_EXIT_INSN(),
1063 },
1064 .errstr = "misaligned access",
1065 .result = REJECT,
1066 },
1067 {
1068 "check cb access: half, oob 1",
1069 .insns = {
1070 BPF_MOV64_IMM(BPF_REG_0, 0),
1071 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1072 offsetof(struct __sk_buff, cb[4]) + 4),
1073 BPF_EXIT_INSN(),
1074 },
1075 .errstr = "invalid bpf_context access",
1076 .result = REJECT,
1077 },
1078 {
1079 "check cb access: half, oob 2",
1080 .insns = {
1081 BPF_MOV64_IMM(BPF_REG_0, 0),
1082 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1083 offsetof(struct __sk_buff, cb[0]) - 2),
1084 BPF_EXIT_INSN(),
1085 },
1086 .errstr = "invalid bpf_context access",
1087 .result = REJECT,
1088 },
1089 {
1090 "check cb access: half, oob 3",
1091 .insns = {
1092 BPF_MOV64_IMM(BPF_REG_0, 0),
1093 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1094 offsetof(struct __sk_buff, cb[4]) + 4),
1095 BPF_EXIT_INSN(),
1096 },
1097 .errstr = "invalid bpf_context access",
1098 .result = REJECT,
1099 },
1100 {
1101 "check cb access: half, oob 4",
1102 .insns = {
1103 BPF_MOV64_IMM(BPF_REG_0, 0),
1104 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1105 offsetof(struct __sk_buff, cb[0]) - 2),
1106 BPF_EXIT_INSN(),
1107 },
1108 .errstr = "invalid bpf_context access",
1109 .result = REJECT,
1110 },
1111 {
1112 "check cb access: half, wrong type",
1113 .insns = {
1114 BPF_MOV64_IMM(BPF_REG_0, 0),
1115 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1116 offsetof(struct __sk_buff, cb[0])),
1117 BPF_EXIT_INSN(),
1118 },
1119 .errstr = "invalid bpf_context access",
1120 .result = REJECT,
1121 .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
1122 },
1123 {
1124 "check cb access: word",
1125 .insns = {
1126 BPF_MOV64_IMM(BPF_REG_0, 0),
1127 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1128 offsetof(struct __sk_buff, cb[0])),
1129 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1130 offsetof(struct __sk_buff, cb[1])),
1131 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1132 offsetof(struct __sk_buff, cb[2])),
1133 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1134 offsetof(struct __sk_buff, cb[3])),
1135 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1136 offsetof(struct __sk_buff, cb[4])),
1137 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1138 offsetof(struct __sk_buff, cb[0])),
1139 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1140 offsetof(struct __sk_buff, cb[1])),
1141 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1142 offsetof(struct __sk_buff, cb[2])),
1143 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1144 offsetof(struct __sk_buff, cb[3])),
1145 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
1146 offsetof(struct __sk_buff, cb[4])),
1147 BPF_EXIT_INSN(),
1148 },
1149 .result = ACCEPT,
1150 },
1151 {
1152 "check cb access: word, unaligned 1",
1153 .insns = {
1154 BPF_MOV64_IMM(BPF_REG_0, 0),
1155 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1156 offsetof(struct __sk_buff, cb[0]) + 2),
1157 BPF_EXIT_INSN(),
1158 },
1159 .errstr = "misaligned access",
1160 .result = REJECT,
1161 },
1162 {
1163 "check cb access: word, unaligned 2",
1164 .insns = {
1165 BPF_MOV64_IMM(BPF_REG_0, 0),
1166 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1167 offsetof(struct __sk_buff, cb[4]) + 1),
1168 BPF_EXIT_INSN(),
1169 },
1170 .errstr = "misaligned access",
1171 .result = REJECT,
1172 },
1173 {
1174 "check cb access: word, unaligned 3",
1175 .insns = {
1176 BPF_MOV64_IMM(BPF_REG_0, 0),
1177 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1178 offsetof(struct __sk_buff, cb[4]) + 2),
1179 BPF_EXIT_INSN(),
1180 },
1181 .errstr = "misaligned access",
1182 .result = REJECT,
1183 },
1184 {
1185 "check cb access: word, unaligned 4",
1186 .insns = {
1187 BPF_MOV64_IMM(BPF_REG_0, 0),
1188 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
1189 offsetof(struct __sk_buff, cb[4]) + 3),
1190 BPF_EXIT_INSN(),
1191 },
1192 .errstr = "misaligned access",
1193 .result = REJECT,
1194 },
1195 {
1196 "check cb access: double",
1197 .insns = {
1198 BPF_MOV64_IMM(BPF_REG_0, 0),
1199 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
1200 offsetof(struct __sk_buff, cb[0])),
1201 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
1202 offsetof(struct __sk_buff, cb[2])),
1203 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1,
1204 offsetof(struct __sk_buff, cb[0])),
1205 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1,
1206 offsetof(struct __sk_buff, cb[2])),
1207 BPF_EXIT_INSN(),
1208 },
1209 .result = ACCEPT,
1210 },
1211 {
1212 "check cb access: double, unaligned 1",
1213 .insns = {
1214 BPF_MOV64_IMM(BPF_REG_0, 0),
1215 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
1216 offsetof(struct __sk_buff, cb[1])),
1217 BPF_EXIT_INSN(),
1218 },
1219 .errstr = "misaligned access",
1220 .result = REJECT,
1221 },
1222 {
1223 "check cb access: double, unaligned 2",
1224 .insns = {
1225 BPF_MOV64_IMM(BPF_REG_0, 0),
1226 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
1227 offsetof(struct __sk_buff, cb[3])),
1228 BPF_EXIT_INSN(),
1229 },
1230 .errstr = "misaligned access",
1231 .result = REJECT,
1232 },
1233 {
1234 "check cb access: double, oob 1",
1235 .insns = {
1236 BPF_MOV64_IMM(BPF_REG_0, 0),
1237 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
1238 offsetof(struct __sk_buff, cb[4])),
1239 BPF_EXIT_INSN(),
1240 },
1241 .errstr = "invalid bpf_context access",
1242 .result = REJECT,
1243 },
1244 {
1245 "check cb access: double, oob 2",
1246 .insns = {
1247 BPF_MOV64_IMM(BPF_REG_0, 0),
1248 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
1249 offsetof(struct __sk_buff, cb[4]) + 8),
1250 BPF_EXIT_INSN(),
1251 },
1252 .errstr = "invalid bpf_context access",
1253 .result = REJECT,
1254 },
1255 {
1256 "check cb access: double, oob 3",
1257 .insns = {
1258 BPF_MOV64_IMM(BPF_REG_0, 0),
1259 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
1260 offsetof(struct __sk_buff, cb[0]) - 8),
1261 BPF_EXIT_INSN(),
1262 },
1263 .errstr = "invalid bpf_context access",
1264 .result = REJECT,
1265 },
1266 {
1267 "check cb access: double, oob 4",
1268 .insns = {
1269 BPF_MOV64_IMM(BPF_REG_0, 0),
1270 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1,
1271 offsetof(struct __sk_buff, cb[4])),
1272 BPF_EXIT_INSN(),
1273 },
1274 .errstr = "invalid bpf_context access",
1275 .result = REJECT,
1276 },
1277 {
1278 "check cb access: double, oob 5",
1279 .insns = {
1280 BPF_MOV64_IMM(BPF_REG_0, 0),
1281 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1,
1282 offsetof(struct __sk_buff, cb[4]) + 8),
1283 BPF_EXIT_INSN(),
1284 },
1285 .errstr = "invalid bpf_context access",
1286 .result = REJECT,
1287 },
1288 {
1289 "check cb access: double, oob 6",
1290 .insns = {
1291 BPF_MOV64_IMM(BPF_REG_0, 0),
1292 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1,
1293 offsetof(struct __sk_buff, cb[0]) - 8),
1294 BPF_EXIT_INSN(),
1295 },
1296 .errstr = "invalid bpf_context access",
1297 .result = REJECT,
1298 },
1299 {
1300 "check cb access: double, wrong type",
1301 .insns = {
1302 BPF_MOV64_IMM(BPF_REG_0, 0),
1303 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
865 offsetof(struct __sk_buff, cb[0])), 1304 offsetof(struct __sk_buff, cb[0])),
866 BPF_EXIT_INSN(), 1305 BPF_EXIT_INSN(),
867 }, 1306 },
868 .errstr = "invalid bpf_context access", 1307 .errstr = "invalid bpf_context access",
869 .errstr_unpriv = "R1 leaks addr",
870 .result = REJECT, 1308 .result = REJECT,
1309 .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
871 }, 1310 },
872 { 1311 {
873 "check out of range skb->cb access", 1312 "check out of range skb->cb access",
@@ -1890,6 +2329,107 @@ static struct bpf_test tests[] = {
1890 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2329 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
1891 }, 2330 },
1892 { 2331 {
2332 "direct packet access: test11 (shift, good access)",
2333 .insns = {
2334 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2335 offsetof(struct __sk_buff, data)),
2336 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2337 offsetof(struct __sk_buff, data_end)),
2338 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
2339 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 22),
2340 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 8),
2341 BPF_MOV64_IMM(BPF_REG_3, 144),
2342 BPF_MOV64_REG(BPF_REG_5, BPF_REG_3),
2343 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 23),
2344 BPF_ALU64_IMM(BPF_RSH, BPF_REG_5, 3),
2345 BPF_MOV64_REG(BPF_REG_6, BPF_REG_2),
2346 BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_5),
2347 BPF_MOV64_IMM(BPF_REG_0, 1),
2348 BPF_EXIT_INSN(),
2349 BPF_MOV64_IMM(BPF_REG_0, 0),
2350 BPF_EXIT_INSN(),
2351 },
2352 .result = ACCEPT,
2353 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2354 },
2355 {
2356 "direct packet access: test12 (and, good access)",
2357 .insns = {
2358 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2359 offsetof(struct __sk_buff, data)),
2360 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2361 offsetof(struct __sk_buff, data_end)),
2362 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
2363 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 22),
2364 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 8),
2365 BPF_MOV64_IMM(BPF_REG_3, 144),
2366 BPF_MOV64_REG(BPF_REG_5, BPF_REG_3),
2367 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 23),
2368 BPF_ALU64_IMM(BPF_AND, BPF_REG_5, 15),
2369 BPF_MOV64_REG(BPF_REG_6, BPF_REG_2),
2370 BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_5),
2371 BPF_MOV64_IMM(BPF_REG_0, 1),
2372 BPF_EXIT_INSN(),
2373 BPF_MOV64_IMM(BPF_REG_0, 0),
2374 BPF_EXIT_INSN(),
2375 },
2376 .result = ACCEPT,
2377 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2378 },
2379 {
2380 "direct packet access: test13 (branches, good access)",
2381 .insns = {
2382 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2383 offsetof(struct __sk_buff, data)),
2384 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2385 offsetof(struct __sk_buff, data_end)),
2386 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
2387 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 22),
2388 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 13),
2389 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2390 offsetof(struct __sk_buff, mark)),
2391 BPF_MOV64_IMM(BPF_REG_4, 1),
2392 BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_4, 2),
2393 BPF_MOV64_IMM(BPF_REG_3, 14),
2394 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
2395 BPF_MOV64_IMM(BPF_REG_3, 24),
2396 BPF_MOV64_REG(BPF_REG_5, BPF_REG_3),
2397 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 23),
2398 BPF_ALU64_IMM(BPF_AND, BPF_REG_5, 15),
2399 BPF_MOV64_REG(BPF_REG_6, BPF_REG_2),
2400 BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_5),
2401 BPF_MOV64_IMM(BPF_REG_0, 1),
2402 BPF_EXIT_INSN(),
2403 BPF_MOV64_IMM(BPF_REG_0, 0),
2404 BPF_EXIT_INSN(),
2405 },
2406 .result = ACCEPT,
2407 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2408 },
2409 {
2410 "direct packet access: test14 (pkt_ptr += 0, CONST_IMM, good access)",
2411 .insns = {
2412 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2413 offsetof(struct __sk_buff, data)),
2414 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2415 offsetof(struct __sk_buff, data_end)),
2416 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
2417 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 22),
2418 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 7),
2419 BPF_MOV64_IMM(BPF_REG_5, 12),
2420 BPF_ALU64_IMM(BPF_RSH, BPF_REG_5, 4),
2421 BPF_MOV64_REG(BPF_REG_6, BPF_REG_2),
2422 BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_5),
2423 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_6, 0),
2424 BPF_MOV64_IMM(BPF_REG_0, 1),
2425 BPF_EXIT_INSN(),
2426 BPF_MOV64_IMM(BPF_REG_0, 0),
2427 BPF_EXIT_INSN(),
2428 },
2429 .result = ACCEPT,
2430 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2431 },
2432 {
1893 "helper access to packet: test1, valid packet_ptr range", 2433 "helper access to packet: test1, valid packet_ptr range",
1894 .insns = { 2434 .insns = {
1895 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 2435 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
@@ -2905,6 +3445,1012 @@ static struct bpf_test tests[] = {
2905 .result = REJECT, 3445 .result = REJECT,
2906 .errstr = "invalid bpf_context access", 3446 .errstr = "invalid bpf_context access",
2907 }, 3447 },
3448 {
3449 "helper access to map: full range",
3450 .insns = {
3451 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3452 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3453 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3454 BPF_LD_MAP_FD(BPF_REG_1, 0),
3455 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3456 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
3457 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3458 BPF_MOV64_IMM(BPF_REG_2, sizeof(struct test_val)),
3459 BPF_MOV64_IMM(BPF_REG_3, 0),
3460 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3461 BPF_EXIT_INSN(),
3462 },
3463 .fixup_map2 = { 3 },
3464 .result = ACCEPT,
3465 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3466 },
3467 {
3468 "helper access to map: partial range",
3469 .insns = {
3470 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3471 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3472 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3473 BPF_LD_MAP_FD(BPF_REG_1, 0),
3474 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3475 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
3476 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3477 BPF_MOV64_IMM(BPF_REG_2, 8),
3478 BPF_MOV64_IMM(BPF_REG_3, 0),
3479 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3480 BPF_EXIT_INSN(),
3481 },
3482 .fixup_map2 = { 3 },
3483 .result = ACCEPT,
3484 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3485 },
3486 {
3487 "helper access to map: empty range",
3488 .insns = {
3489 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3490 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3491 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3492 BPF_LD_MAP_FD(BPF_REG_1, 0),
3493 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3494 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
3495 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3496 BPF_MOV64_IMM(BPF_REG_2, 0),
3497 BPF_MOV64_IMM(BPF_REG_3, 0),
3498 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3499 BPF_EXIT_INSN(),
3500 },
3501 .fixup_map2 = { 3 },
3502 .errstr = "invalid access to map value, value_size=48 off=0 size=0",
3503 .result = REJECT,
3504 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3505 },
3506 {
3507 "helper access to map: out-of-bound range",
3508 .insns = {
3509 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3510 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3511 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3512 BPF_LD_MAP_FD(BPF_REG_1, 0),
3513 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3514 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
3515 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3516 BPF_MOV64_IMM(BPF_REG_2, sizeof(struct test_val) + 8),
3517 BPF_MOV64_IMM(BPF_REG_3, 0),
3518 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3519 BPF_EXIT_INSN(),
3520 },
3521 .fixup_map2 = { 3 },
3522 .errstr = "invalid access to map value, value_size=48 off=0 size=56",
3523 .result = REJECT,
3524 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3525 },
3526 {
3527 "helper access to map: negative range",
3528 .insns = {
3529 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3530 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3531 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3532 BPF_LD_MAP_FD(BPF_REG_1, 0),
3533 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3534 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
3535 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3536 BPF_MOV64_IMM(BPF_REG_2, -8),
3537 BPF_MOV64_IMM(BPF_REG_3, 0),
3538 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3539 BPF_EXIT_INSN(),
3540 },
3541 .fixup_map2 = { 3 },
3542 .errstr = "invalid access to map value, value_size=48 off=0 size=-8",
3543 .result = REJECT,
3544 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3545 },
3546 {
3547 "helper access to adjusted map (via const imm): full range",
3548 .insns = {
3549 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3550 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3551 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3552 BPF_LD_MAP_FD(BPF_REG_1, 0),
3553 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3554 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
3555 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3556 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1,
3557 offsetof(struct test_val, foo)),
3558 BPF_MOV64_IMM(BPF_REG_2,
3559 sizeof(struct test_val) -
3560 offsetof(struct test_val, foo)),
3561 BPF_MOV64_IMM(BPF_REG_3, 0),
3562 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3563 BPF_EXIT_INSN(),
3564 },
3565 .fixup_map2 = { 3 },
3566 .result = ACCEPT,
3567 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3568 },
3569 {
3570 "helper access to adjusted map (via const imm): partial range",
3571 .insns = {
3572 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3573 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3574 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3575 BPF_LD_MAP_FD(BPF_REG_1, 0),
3576 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3577 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
3578 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3579 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1,
3580 offsetof(struct test_val, foo)),
3581 BPF_MOV64_IMM(BPF_REG_2, 8),
3582 BPF_MOV64_IMM(BPF_REG_3, 0),
3583 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3584 BPF_EXIT_INSN(),
3585 },
3586 .fixup_map2 = { 3 },
3587 .result = ACCEPT,
3588 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3589 },
3590 {
3591 "helper access to adjusted map (via const imm): empty range",
3592 .insns = {
3593 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3594 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3595 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3596 BPF_LD_MAP_FD(BPF_REG_1, 0),
3597 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3598 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
3599 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3600 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1,
3601 offsetof(struct test_val, foo)),
3602 BPF_MOV64_IMM(BPF_REG_2, 0),
3603 BPF_MOV64_IMM(BPF_REG_3, 0),
3604 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3605 BPF_EXIT_INSN(),
3606 },
3607 .fixup_map2 = { 3 },
3608 .errstr = "R1 min value is outside of the array range",
3609 .result = REJECT,
3610 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3611 },
3612 {
3613 "helper access to adjusted map (via const imm): out-of-bound range",
3614 .insns = {
3615 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3616 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3617 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3618 BPF_LD_MAP_FD(BPF_REG_1, 0),
3619 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3620 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
3621 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3622 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1,
3623 offsetof(struct test_val, foo)),
3624 BPF_MOV64_IMM(BPF_REG_2,
3625 sizeof(struct test_val) -
3626 offsetof(struct test_val, foo) + 8),
3627 BPF_MOV64_IMM(BPF_REG_3, 0),
3628 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3629 BPF_EXIT_INSN(),
3630 },
3631 .fixup_map2 = { 3 },
3632 .errstr = "invalid access to map value, value_size=48 off=4 size=52",
3633 .result = REJECT,
3634 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3635 },
3636 {
3637 "helper access to adjusted map (via const imm): negative range (> adjustment)",
3638 .insns = {
3639 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3640 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3641 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3642 BPF_LD_MAP_FD(BPF_REG_1, 0),
3643 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3644 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
3645 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3646 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1,
3647 offsetof(struct test_val, foo)),
3648 BPF_MOV64_IMM(BPF_REG_2, -8),
3649 BPF_MOV64_IMM(BPF_REG_3, 0),
3650 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3651 BPF_EXIT_INSN(),
3652 },
3653 .fixup_map2 = { 3 },
3654 .errstr = "invalid access to map value, value_size=48 off=4 size=-8",
3655 .result = REJECT,
3656 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3657 },
3658 {
3659 "helper access to adjusted map (via const imm): negative range (< adjustment)",
3660 .insns = {
3661 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3662 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3663 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3664 BPF_LD_MAP_FD(BPF_REG_1, 0),
3665 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3666 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
3667 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3668 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1,
3669 offsetof(struct test_val, foo)),
3670 BPF_MOV64_IMM(BPF_REG_2, -1),
3671 BPF_MOV64_IMM(BPF_REG_3, 0),
3672 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3673 BPF_EXIT_INSN(),
3674 },
3675 .fixup_map2 = { 3 },
3676 .errstr = "R1 min value is outside of the array range",
3677 .result = REJECT,
3678 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3679 },
3680 {
3681 "helper access to adjusted map (via const reg): full range",
3682 .insns = {
3683 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3684 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3685 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3686 BPF_LD_MAP_FD(BPF_REG_1, 0),
3687 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3688 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
3689 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3690 BPF_MOV64_IMM(BPF_REG_3,
3691 offsetof(struct test_val, foo)),
3692 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
3693 BPF_MOV64_IMM(BPF_REG_2,
3694 sizeof(struct test_val) -
3695 offsetof(struct test_val, foo)),
3696 BPF_MOV64_IMM(BPF_REG_3, 0),
3697 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3698 BPF_EXIT_INSN(),
3699 },
3700 .fixup_map2 = { 3 },
3701 .result = ACCEPT,
3702 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3703 },
3704 {
3705 "helper access to adjusted map (via const reg): partial range",
3706 .insns = {
3707 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3708 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3709 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3710 BPF_LD_MAP_FD(BPF_REG_1, 0),
3711 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3712 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
3713 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3714 BPF_MOV64_IMM(BPF_REG_3,
3715 offsetof(struct test_val, foo)),
3716 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
3717 BPF_MOV64_IMM(BPF_REG_2, 8),
3718 BPF_MOV64_IMM(BPF_REG_3, 0),
3719 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3720 BPF_EXIT_INSN(),
3721 },
3722 .fixup_map2 = { 3 },
3723 .result = ACCEPT,
3724 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3725 },
3726 {
3727 "helper access to adjusted map (via const reg): empty range",
3728 .insns = {
3729 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3730 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3731 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3732 BPF_LD_MAP_FD(BPF_REG_1, 0),
3733 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3734 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
3735 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3736 BPF_MOV64_IMM(BPF_REG_3, 0),
3737 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
3738 BPF_MOV64_IMM(BPF_REG_2, 0),
3739 BPF_MOV64_IMM(BPF_REG_3, 0),
3740 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3741 BPF_EXIT_INSN(),
3742 },
3743 .fixup_map2 = { 3 },
3744 .errstr = "R1 min value is outside of the array range",
3745 .result = REJECT,
3746 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3747 },
3748 {
3749 "helper access to adjusted map (via const reg): out-of-bound range",
3750 .insns = {
3751 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3752 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3753 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3754 BPF_LD_MAP_FD(BPF_REG_1, 0),
3755 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3756 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
3757 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3758 BPF_MOV64_IMM(BPF_REG_3,
3759 offsetof(struct test_val, foo)),
3760 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
3761 BPF_MOV64_IMM(BPF_REG_2,
3762 sizeof(struct test_val) -
3763 offsetof(struct test_val, foo) + 8),
3764 BPF_MOV64_IMM(BPF_REG_3, 0),
3765 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3766 BPF_EXIT_INSN(),
3767 },
3768 .fixup_map2 = { 3 },
3769 .errstr = "invalid access to map value, value_size=48 off=4 size=52",
3770 .result = REJECT,
3771 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3772 },
3773 {
3774 "helper access to adjusted map (via const reg): negative range (> adjustment)",
3775 .insns = {
3776 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3777 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3778 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3779 BPF_LD_MAP_FD(BPF_REG_1, 0),
3780 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3781 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
3782 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3783 BPF_MOV64_IMM(BPF_REG_3,
3784 offsetof(struct test_val, foo)),
3785 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
3786 BPF_MOV64_IMM(BPF_REG_2, -8),
3787 BPF_MOV64_IMM(BPF_REG_3, 0),
3788 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3789 BPF_EXIT_INSN(),
3790 },
3791 .fixup_map2 = { 3 },
3792 .errstr = "invalid access to map value, value_size=48 off=4 size=-8",
3793 .result = REJECT,
3794 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3795 },
3796 {
3797 "helper access to adjusted map (via const reg): negative range (< adjustment)",
3798 .insns = {
3799 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3800 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3801 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3802 BPF_LD_MAP_FD(BPF_REG_1, 0),
3803 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3804 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
3805 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3806 BPF_MOV64_IMM(BPF_REG_3,
3807 offsetof(struct test_val, foo)),
3808 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
3809 BPF_MOV64_IMM(BPF_REG_2, -1),
3810 BPF_MOV64_IMM(BPF_REG_3, 0),
3811 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3812 BPF_EXIT_INSN(),
3813 },
3814 .fixup_map2 = { 3 },
3815 .errstr = "R1 min value is outside of the array range",
3816 .result = REJECT,
3817 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3818 },
3819 {
3820 "helper access to adjusted map (via variable): full range",
3821 .insns = {
3822 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3823 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3824 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3825 BPF_LD_MAP_FD(BPF_REG_1, 0),
3826 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3827 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
3828 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3829 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
3830 BPF_JMP_IMM(BPF_JGT, BPF_REG_3,
3831 offsetof(struct test_val, foo), 4),
3832 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
3833 BPF_MOV64_IMM(BPF_REG_2,
3834 sizeof(struct test_val) -
3835 offsetof(struct test_val, foo)),
3836 BPF_MOV64_IMM(BPF_REG_3, 0),
3837 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3838 BPF_EXIT_INSN(),
3839 },
3840 .fixup_map2 = { 3 },
3841 .result = ACCEPT,
3842 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3843 },
3844 {
3845 "helper access to adjusted map (via variable): partial range",
3846 .insns = {
3847 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3848 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3849 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3850 BPF_LD_MAP_FD(BPF_REG_1, 0),
3851 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3852 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
3853 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3854 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
3855 BPF_JMP_IMM(BPF_JGT, BPF_REG_3,
3856 offsetof(struct test_val, foo), 4),
3857 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
3858 BPF_MOV64_IMM(BPF_REG_2, 8),
3859 BPF_MOV64_IMM(BPF_REG_3, 0),
3860 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3861 BPF_EXIT_INSN(),
3862 },
3863 .fixup_map2 = { 3 },
3864 .result = ACCEPT,
3865 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3866 },
3867 {
3868 "helper access to adjusted map (via variable): empty range",
3869 .insns = {
3870 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3871 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3872 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3873 BPF_LD_MAP_FD(BPF_REG_1, 0),
3874 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3875 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
3876 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3877 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
3878 BPF_JMP_IMM(BPF_JGT, BPF_REG_3,
3879 offsetof(struct test_val, foo), 4),
3880 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
3881 BPF_MOV64_IMM(BPF_REG_2, 0),
3882 BPF_MOV64_IMM(BPF_REG_3, 0),
3883 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3884 BPF_EXIT_INSN(),
3885 },
3886 .fixup_map2 = { 3 },
3887 .errstr = "R1 min value is outside of the array range",
3888 .result = REJECT,
3889 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3890 },
3891 {
3892 "helper access to adjusted map (via variable): no max check",
3893 .insns = {
3894 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3895 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3896 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3897 BPF_LD_MAP_FD(BPF_REG_1, 0),
3898 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3899 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
3900 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3901 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
3902 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
3903 BPF_MOV64_IMM(BPF_REG_2, 0),
3904 BPF_MOV64_IMM(BPF_REG_3, 0),
3905 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3906 BPF_EXIT_INSN(),
3907 },
3908 .fixup_map2 = { 3 },
3909 .errstr = "R1 min value is negative, either use unsigned index or do a if (index >=0) check",
3910 .result = REJECT,
3911 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3912 },
3913 {
3914 "helper access to adjusted map (via variable): wrong max check",
3915 .insns = {
3916 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3917 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3918 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3919 BPF_LD_MAP_FD(BPF_REG_1, 0),
3920 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3921 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
3922 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
3923 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
3924 BPF_JMP_IMM(BPF_JGT, BPF_REG_3,
3925 offsetof(struct test_val, foo), 4),
3926 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
3927 BPF_MOV64_IMM(BPF_REG_2,
3928 sizeof(struct test_val) -
3929 offsetof(struct test_val, foo) + 1),
3930 BPF_MOV64_IMM(BPF_REG_3, 0),
3931 BPF_EMIT_CALL(BPF_FUNC_probe_read),
3932 BPF_EXIT_INSN(),
3933 },
3934 .fixup_map2 = { 3 },
3935 .errstr = "invalid access to map value, value_size=48 off=4 size=45",
3936 .result = REJECT,
3937 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3938 },
3939 {
3940 "map element value is preserved across register spilling",
3941 .insns = {
3942 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3943 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3944 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3945 BPF_LD_MAP_FD(BPF_REG_1, 0),
3946 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3947 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
3948 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 42),
3949 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3950 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -184),
3951 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
3952 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_1, 0),
3953 BPF_ST_MEM(BPF_DW, BPF_REG_3, 0, 42),
3954 BPF_EXIT_INSN(),
3955 },
3956 .fixup_map2 = { 3 },
3957 .errstr_unpriv = "R0 leaks addr",
3958 .result = ACCEPT,
3959 .result_unpriv = REJECT,
3960 },
3961 {
3962 "map element value (adjusted) is preserved across register spilling",
3963 .insns = {
3964 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3965 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3966 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
3967 BPF_LD_MAP_FD(BPF_REG_1, 0),
3968 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3969 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
3970 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0,
3971 offsetof(struct test_val, foo)),
3972 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 42),
3973 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3974 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -184),
3975 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
3976 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_1, 0),
3977 BPF_ST_MEM(BPF_DW, BPF_REG_3, 0, 42),
3978 BPF_EXIT_INSN(),
3979 },
3980 .fixup_map2 = { 3 },
3981 .errstr_unpriv = "R0 pointer arithmetic prohibited",
3982 .result = ACCEPT,
3983 .result_unpriv = REJECT,
3984 },
3985 {
3986 "helper access to variable memory: stack, bitwise AND + JMP, correct bounds",
3987 .insns = {
3988 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3989 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
3990 BPF_MOV64_IMM(BPF_REG_0, 0),
3991 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64),
3992 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56),
3993 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48),
3994 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40),
3995 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -32),
3996 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
3997 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
3998 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
3999 BPF_MOV64_IMM(BPF_REG_2, 16),
4000 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
4001 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
4002 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 64),
4003 BPF_MOV64_IMM(BPF_REG_4, 0),
4004 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
4005 BPF_MOV64_IMM(BPF_REG_3, 0),
4006 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4007 BPF_MOV64_IMM(BPF_REG_0, 0),
4008 BPF_EXIT_INSN(),
4009 },
4010 .result = ACCEPT,
4011 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4012 },
4013 {
4014 "helper access to variable memory: stack, bitwise AND, zero included",
4015 .insns = {
4016 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
4017 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
4018 BPF_MOV64_IMM(BPF_REG_2, 16),
4019 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
4020 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
4021 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 64),
4022 BPF_MOV64_IMM(BPF_REG_3, 0),
4023 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4024 BPF_EXIT_INSN(),
4025 },
4026 .errstr = "invalid stack type R1 off=-64 access_size=0",
4027 .result = REJECT,
4028 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4029 },
4030 {
4031 "helper access to variable memory: stack, bitwise AND + JMP, wrong max",
4032 .insns = {
4033 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
4034 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
4035 BPF_MOV64_IMM(BPF_REG_2, 16),
4036 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
4037 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
4038 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 65),
4039 BPF_MOV64_IMM(BPF_REG_4, 0),
4040 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
4041 BPF_MOV64_IMM(BPF_REG_3, 0),
4042 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4043 BPF_MOV64_IMM(BPF_REG_0, 0),
4044 BPF_EXIT_INSN(),
4045 },
4046 .errstr = "invalid stack type R1 off=-64 access_size=65",
4047 .result = REJECT,
4048 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4049 },
4050 {
4051 "helper access to variable memory: stack, JMP, correct bounds",
4052 .insns = {
4053 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
4054 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
4055 BPF_MOV64_IMM(BPF_REG_0, 0),
4056 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64),
4057 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56),
4058 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48),
4059 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40),
4060 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -32),
4061 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
4062 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
4063 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
4064 BPF_MOV64_IMM(BPF_REG_2, 16),
4065 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
4066 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
4067 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 64, 4),
4068 BPF_MOV64_IMM(BPF_REG_4, 0),
4069 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
4070 BPF_MOV64_IMM(BPF_REG_3, 0),
4071 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4072 BPF_MOV64_IMM(BPF_REG_0, 0),
4073 BPF_EXIT_INSN(),
4074 },
4075 .result = ACCEPT,
4076 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4077 },
4078 {
4079 "helper access to variable memory: stack, JMP (signed), correct bounds",
4080 .insns = {
4081 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
4082 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
4083 BPF_MOV64_IMM(BPF_REG_0, 0),
4084 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64),
4085 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56),
4086 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48),
4087 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40),
4088 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -32),
4089 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
4090 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
4091 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
4092 BPF_MOV64_IMM(BPF_REG_2, 16),
4093 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
4094 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
4095 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, 64, 4),
4096 BPF_MOV64_IMM(BPF_REG_4, 0),
4097 BPF_JMP_REG(BPF_JSGE, BPF_REG_4, BPF_REG_2, 2),
4098 BPF_MOV64_IMM(BPF_REG_3, 0),
4099 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4100 BPF_MOV64_IMM(BPF_REG_0, 0),
4101 BPF_EXIT_INSN(),
4102 },
4103 .result = ACCEPT,
4104 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4105 },
4106 {
4107 "helper access to variable memory: stack, JMP, bounds + offset",
4108 .insns = {
4109 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
4110 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
4111 BPF_MOV64_IMM(BPF_REG_2, 16),
4112 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
4113 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
4114 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 64, 5),
4115 BPF_MOV64_IMM(BPF_REG_4, 0),
4116 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 3),
4117 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
4118 BPF_MOV64_IMM(BPF_REG_3, 0),
4119 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4120 BPF_MOV64_IMM(BPF_REG_0, 0),
4121 BPF_EXIT_INSN(),
4122 },
4123 .errstr = "invalid stack type R1 off=-64 access_size=65",
4124 .result = REJECT,
4125 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4126 },
4127 {
4128 "helper access to variable memory: stack, JMP, wrong max",
4129 .insns = {
4130 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
4131 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
4132 BPF_MOV64_IMM(BPF_REG_2, 16),
4133 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
4134 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
4135 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 65, 4),
4136 BPF_MOV64_IMM(BPF_REG_4, 0),
4137 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
4138 BPF_MOV64_IMM(BPF_REG_3, 0),
4139 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4140 BPF_MOV64_IMM(BPF_REG_0, 0),
4141 BPF_EXIT_INSN(),
4142 },
4143 .errstr = "invalid stack type R1 off=-64 access_size=65",
4144 .result = REJECT,
4145 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4146 },
4147 {
4148 "helper access to variable memory: stack, JMP, no max check",
4149 .insns = {
4150 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
4151 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
4152 BPF_MOV64_IMM(BPF_REG_2, 16),
4153 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
4154 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
4155 BPF_MOV64_IMM(BPF_REG_4, 0),
4156 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
4157 BPF_MOV64_IMM(BPF_REG_3, 0),
4158 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4159 BPF_MOV64_IMM(BPF_REG_0, 0),
4160 BPF_EXIT_INSN(),
4161 },
4162 .errstr = "R2 unbounded memory access",
4163 .result = REJECT,
4164 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4165 },
4166 {
4167 "helper access to variable memory: stack, JMP, no min check",
4168 .insns = {
4169 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
4170 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
4171 BPF_MOV64_IMM(BPF_REG_2, 16),
4172 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
4173 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
4174 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 64, 3),
4175 BPF_MOV64_IMM(BPF_REG_3, 0),
4176 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4177 BPF_MOV64_IMM(BPF_REG_0, 0),
4178 BPF_EXIT_INSN(),
4179 },
4180 .errstr = "invalid stack type R1 off=-64 access_size=0",
4181 .result = REJECT,
4182 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4183 },
4184 {
4185 "helper access to variable memory: stack, JMP (signed), no min check",
4186 .insns = {
4187 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
4188 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
4189 BPF_MOV64_IMM(BPF_REG_2, 16),
4190 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
4191 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
4192 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, 64, 3),
4193 BPF_MOV64_IMM(BPF_REG_3, 0),
4194 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4195 BPF_MOV64_IMM(BPF_REG_0, 0),
4196 BPF_EXIT_INSN(),
4197 },
4198 .errstr = "R2 min value is negative",
4199 .result = REJECT,
4200 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4201 },
4202 {
4203 "helper access to variable memory: map, JMP, correct bounds",
4204 .insns = {
4205 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4206 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4207 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4208 BPF_LD_MAP_FD(BPF_REG_1, 0),
4209 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4210 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 10),
4211 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4212 BPF_MOV64_IMM(BPF_REG_2, sizeof(struct test_val)),
4213 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
4214 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
4215 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2,
4216 sizeof(struct test_val), 4),
4217 BPF_MOV64_IMM(BPF_REG_4, 0),
4218 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
4219 BPF_MOV64_IMM(BPF_REG_3, 0),
4220 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4221 BPF_MOV64_IMM(BPF_REG_0, 0),
4222 BPF_EXIT_INSN(),
4223 },
4224 .fixup_map2 = { 3 },
4225 .result = ACCEPT,
4226 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4227 },
4228 {
4229 "helper access to variable memory: map, JMP, wrong max",
4230 .insns = {
4231 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4232 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4233 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4234 BPF_LD_MAP_FD(BPF_REG_1, 0),
4235 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4236 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 10),
4237 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4238 BPF_MOV64_IMM(BPF_REG_2, sizeof(struct test_val)),
4239 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
4240 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
4241 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2,
4242 sizeof(struct test_val) + 1, 4),
4243 BPF_MOV64_IMM(BPF_REG_4, 0),
4244 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
4245 BPF_MOV64_IMM(BPF_REG_3, 0),
4246 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4247 BPF_MOV64_IMM(BPF_REG_0, 0),
4248 BPF_EXIT_INSN(),
4249 },
4250 .fixup_map2 = { 3 },
4251 .errstr = "invalid access to map value, value_size=48 off=0 size=49",
4252 .result = REJECT,
4253 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4254 },
4255 {
4256 "helper access to variable memory: map adjusted, JMP, correct bounds",
4257 .insns = {
4258 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4259 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4260 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4261 BPF_LD_MAP_FD(BPF_REG_1, 0),
4262 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4263 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 11),
4264 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4265 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 20),
4266 BPF_MOV64_IMM(BPF_REG_2, sizeof(struct test_val)),
4267 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
4268 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
4269 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2,
4270 sizeof(struct test_val) - 20, 4),
4271 BPF_MOV64_IMM(BPF_REG_4, 0),
4272 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
4273 BPF_MOV64_IMM(BPF_REG_3, 0),
4274 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4275 BPF_MOV64_IMM(BPF_REG_0, 0),
4276 BPF_EXIT_INSN(),
4277 },
4278 .fixup_map2 = { 3 },
4279 .result = ACCEPT,
4280 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4281 },
4282 {
4283 "helper access to variable memory: map adjusted, JMP, wrong max",
4284 .insns = {
4285 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4286 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4287 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4288 BPF_LD_MAP_FD(BPF_REG_1, 0),
4289 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4290 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 11),
4291 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
4292 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 20),
4293 BPF_MOV64_IMM(BPF_REG_2, sizeof(struct test_val)),
4294 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
4295 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
4296 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2,
4297 sizeof(struct test_val) - 19, 4),
4298 BPF_MOV64_IMM(BPF_REG_4, 0),
4299 BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
4300 BPF_MOV64_IMM(BPF_REG_3, 0),
4301 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4302 BPF_MOV64_IMM(BPF_REG_0, 0),
4303 BPF_EXIT_INSN(),
4304 },
4305 .fixup_map2 = { 3 },
4306 .errstr = "R1 min value is outside of the array range",
4307 .result = REJECT,
4308 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4309 },
4310 {
4311 "helper access to variable memory: size > 0 not allowed on NULL",
4312 .insns = {
4313 BPF_MOV64_IMM(BPF_REG_1, 0),
4314 BPF_MOV64_IMM(BPF_REG_2, 0),
4315 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
4316 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
4317 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 64),
4318 BPF_MOV64_IMM(BPF_REG_3, 0),
4319 BPF_MOV64_IMM(BPF_REG_4, 0),
4320 BPF_MOV64_IMM(BPF_REG_5, 0),
4321 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
4322 BPF_EXIT_INSN(),
4323 },
4324 .errstr = "R1 type=imm expected=fp",
4325 .result = REJECT,
4326 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
4327 },
4328 {
4329 "helper access to variable memory: size = 0 not allowed on != NULL",
4330 .insns = {
4331 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
4332 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
4333 BPF_MOV64_IMM(BPF_REG_2, 0),
4334 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, 0),
4335 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 8),
4336 BPF_MOV64_IMM(BPF_REG_3, 0),
4337 BPF_MOV64_IMM(BPF_REG_4, 0),
4338 BPF_MOV64_IMM(BPF_REG_5, 0),
4339 BPF_EMIT_CALL(BPF_FUNC_csum_diff),
4340 BPF_EXIT_INSN(),
4341 },
4342 .errstr = "invalid stack type R1 off=-8 access_size=0",
4343 .result = REJECT,
4344 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
4345 },
4346 {
4347 "helper access to variable memory: 8 bytes leak",
4348 .insns = {
4349 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
4350 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
4351 BPF_MOV64_IMM(BPF_REG_0, 0),
4352 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64),
4353 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56),
4354 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48),
4355 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40),
4356 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
4357 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
4358 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
4359 BPF_MOV64_IMM(BPF_REG_2, 0),
4360 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
4361 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
4362 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 63),
4363 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
4364 BPF_MOV64_IMM(BPF_REG_3, 0),
4365 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4366 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
4367 BPF_EXIT_INSN(),
4368 },
4369 .errstr = "invalid indirect read from stack off -64+32 size 64",
4370 .result = REJECT,
4371 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4372 },
4373 {
4374 "helper access to variable memory: 8 bytes no leak (init memory)",
4375 .insns = {
4376 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
4377 BPF_MOV64_IMM(BPF_REG_0, 0),
4378 BPF_MOV64_IMM(BPF_REG_0, 0),
4379 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64),
4380 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56),
4381 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48),
4382 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40),
4383 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -32),
4384 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
4385 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
4386 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
4387 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
4388 BPF_MOV64_IMM(BPF_REG_2, 0),
4389 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 32),
4390 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 32),
4391 BPF_MOV64_IMM(BPF_REG_3, 0),
4392 BPF_EMIT_CALL(BPF_FUNC_probe_read),
4393 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
4394 BPF_EXIT_INSN(),
4395 },
4396 .result = ACCEPT,
4397 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
4398 },
4399 {
4400 "invalid and of negative number",
4401 .insns = {
4402 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
4403 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4404 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4405 BPF_LD_MAP_FD(BPF_REG_1, 0),
4406 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
4407 BPF_FUNC_map_lookup_elem),
4408 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
4409 BPF_MOV64_IMM(BPF_REG_1, 6),
4410 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, -4),
4411 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
4412 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
4413 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
4414 offsetof(struct test_val, foo)),
4415 BPF_EXIT_INSN(),
4416 },
4417 .fixup_map2 = { 3 },
4418 .errstr_unpriv = "R0 pointer arithmetic prohibited",
4419 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
4420 .result = REJECT,
4421 .result_unpriv = REJECT,
4422 },
4423 {
4424 "invalid range check",
4425 .insns = {
4426 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
4427 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4428 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4429 BPF_LD_MAP_FD(BPF_REG_1, 0),
4430 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
4431 BPF_FUNC_map_lookup_elem),
4432 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 12),
4433 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
4434 BPF_MOV64_IMM(BPF_REG_9, 1),
4435 BPF_ALU32_IMM(BPF_MOD, BPF_REG_1, 2),
4436 BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 1),
4437 BPF_ALU32_REG(BPF_AND, BPF_REG_9, BPF_REG_1),
4438 BPF_ALU32_IMM(BPF_ADD, BPF_REG_9, 1),
4439 BPF_ALU32_IMM(BPF_RSH, BPF_REG_9, 1),
4440 BPF_MOV32_IMM(BPF_REG_3, 1),
4441 BPF_ALU32_REG(BPF_SUB, BPF_REG_3, BPF_REG_9),
4442 BPF_ALU32_IMM(BPF_MUL, BPF_REG_3, 0x10000000),
4443 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_3),
4444 BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_3, 0),
4445 BPF_MOV64_REG(BPF_REG_0, 0),
4446 BPF_EXIT_INSN(),
4447 },
4448 .fixup_map2 = { 3 },
4449 .errstr_unpriv = "R0 pointer arithmetic prohibited",
4450 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
4451 .result = REJECT,
4452 .result_unpriv = REJECT,
4453 }
2908}; 4454};
2909 4455
2910static int probe_filter_length(const struct bpf_insn *fp) 4456static int probe_filter_length(const struct bpf_insn *fp)
@@ -2921,7 +4467,7 @@ static int create_map(uint32_t size_value, uint32_t max_elem)
2921{ 4467{
2922 int fd; 4468 int fd;
2923 4469
2924 fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(long long), 4470 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(long long),
2925 size_value, max_elem, BPF_F_NO_PREALLOC); 4471 size_value, max_elem, BPF_F_NO_PREALLOC);
2926 if (fd < 0) 4472 if (fd < 0)
2927 printf("Failed to create hash map '%s'!\n", strerror(errno)); 4473 printf("Failed to create hash map '%s'!\n", strerror(errno));
@@ -2933,7 +4479,7 @@ static int create_prog_array(void)
2933{ 4479{
2934 int fd; 4480 int fd;
2935 4481
2936 fd = bpf_map_create(BPF_MAP_TYPE_PROG_ARRAY, sizeof(int), 4482 fd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY, sizeof(int),
2937 sizeof(int), 4, 0); 4483 sizeof(int), 4, 0);
2938 if (fd < 0) 4484 if (fd < 0)
2939 printf("Failed to create prog array '%s'!\n", strerror(errno)); 4485 printf("Failed to create prog array '%s'!\n", strerror(errno));
@@ -2991,9 +4537,9 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
2991 4537
2992 do_test_fixup(test, prog, &fd_f1, &fd_f2, &fd_f3); 4538 do_test_fixup(test, prog, &fd_f1, &fd_f2, &fd_f3);
2993 4539
2994 fd_prog = bpf_prog_load(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, 4540 fd_prog = bpf_load_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
2995 prog, prog_len * sizeof(struct bpf_insn), 4541 prog, prog_len, "GPL", 0, bpf_vlog,
2996 "GPL", bpf_vlog, sizeof(bpf_vlog)); 4542 sizeof(bpf_vlog));
2997 4543
2998 expected_ret = unpriv && test->result_unpriv != UNDEF ? 4544 expected_ret = unpriv && test->result_unpriv != UNDEF ?
2999 test->result_unpriv : test->result; 4545 test->result_unpriv : test->result;
@@ -3031,6 +4577,55 @@ fail_log:
3031 goto close_fds; 4577 goto close_fds;
3032} 4578}
3033 4579
4580static bool is_admin(void)
4581{
4582 cap_t caps;
4583 cap_flag_value_t sysadmin = CAP_CLEAR;
4584 const cap_value_t cap_val = CAP_SYS_ADMIN;
4585
4586 if (!CAP_IS_SUPPORTED(CAP_SETFCAP)) {
4587 perror("cap_get_flag");
4588 return false;
4589 }
4590 caps = cap_get_proc();
4591 if (!caps) {
4592 perror("cap_get_proc");
4593 return false;
4594 }
4595 if (cap_get_flag(caps, cap_val, CAP_EFFECTIVE, &sysadmin))
4596 perror("cap_get_flag");
4597 if (cap_free(caps))
4598 perror("cap_free");
4599 return (sysadmin == CAP_SET);
4600}
4601
4602static int set_admin(bool admin)
4603{
4604 cap_t caps;
4605 const cap_value_t cap_val = CAP_SYS_ADMIN;
4606 int ret = -1;
4607
4608 caps = cap_get_proc();
4609 if (!caps) {
4610 perror("cap_get_proc");
4611 return -1;
4612 }
4613 if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_val,
4614 admin ? CAP_SET : CAP_CLEAR)) {
4615 perror("cap_set_flag");
4616 goto out;
4617 }
4618 if (cap_set_proc(caps)) {
4619 perror("cap_set_proc");
4620 goto out;
4621 }
4622 ret = 0;
4623out:
4624 if (cap_free(caps))
4625 perror("cap_free");
4626 return ret;
4627}
4628
3034static int do_test(bool unpriv, unsigned int from, unsigned int to) 4629static int do_test(bool unpriv, unsigned int from, unsigned int to)
3035{ 4630{
3036 int i, passes = 0, errors = 0; 4631 int i, passes = 0, errors = 0;
@@ -3041,11 +4636,19 @@ static int do_test(bool unpriv, unsigned int from, unsigned int to)
3041 /* Program types that are not supported by non-root we 4636 /* Program types that are not supported by non-root we
3042 * skip right away. 4637 * skip right away.
3043 */ 4638 */
3044 if (unpriv && test->prog_type) 4639 if (!test->prog_type) {
3045 continue; 4640 if (!unpriv)
4641 set_admin(false);
4642 printf("#%d/u %s ", i, test->descr);
4643 do_test_single(test, true, &passes, &errors);
4644 if (!unpriv)
4645 set_admin(true);
4646 }
3046 4647
3047 printf("#%d %s ", i, test->descr); 4648 if (!unpriv) {
3048 do_test_single(test, unpriv, &passes, &errors); 4649 printf("#%d/p %s ", i, test->descr);
4650 do_test_single(test, false, &passes, &errors);
4651 }
3049 } 4652 }
3050 4653
3051 printf("Summary: %d PASSED, %d FAILED\n", passes, errors); 4654 printf("Summary: %d PASSED, %d FAILED\n", passes, errors);
@@ -3057,7 +4660,7 @@ int main(int argc, char **argv)
3057 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY }; 4660 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
3058 struct rlimit rlim = { 1 << 20, 1 << 20 }; 4661 struct rlimit rlim = { 1 << 20, 1 << 20 };
3059 unsigned int from = 0, to = ARRAY_SIZE(tests); 4662 unsigned int from = 0, to = ARRAY_SIZE(tests);
3060 bool unpriv = geteuid() != 0; 4663 bool unpriv = !is_admin();
3061 4664
3062 if (argc == 3) { 4665 if (argc == 3) {
3063 unsigned int l = atoi(argv[argc - 2]); 4666 unsigned int l = atoi(argv[argc - 2]);
diff --git a/tools/testing/selftests/breakpoints/Makefile b/tools/testing/selftests/breakpoints/Makefile
index 61b79e8df1f4..72aa103e4141 100644
--- a/tools/testing/selftests/breakpoints/Makefile
+++ b/tools/testing/selftests/breakpoints/Makefile
@@ -3,17 +3,13 @@ uname_M := $(shell uname -m 2>/dev/null || echo not)
3ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) 3ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
4 4
5ifeq ($(ARCH),x86) 5ifeq ($(ARCH),x86)
6TEST_PROGS := breakpoint_test 6TEST_GEN_PROGS := breakpoint_test
7endif 7endif
8ifeq ($(ARCH),aarch64) 8ifeq ($(ARCH),aarch64)
9TEST_PROGS := breakpoint_test_arm64 9TEST_GEN_PROGS := breakpoint_test_arm64
10endif 10endif
11 11
12TEST_PROGS += step_after_suspend_test 12TEST_GEN_PROGS += step_after_suspend_test
13
14all: $(TEST_PROGS)
15 13
16include ../lib.mk 14include ../lib.mk
17 15
18clean:
19 rm -fr breakpoint_test breakpoint_test_arm64 step_after_suspend_test
diff --git a/tools/testing/selftests/capabilities/Makefile b/tools/testing/selftests/capabilities/Makefile
index 008602aed920..29b8adfdac71 100644
--- a/tools/testing/selftests/capabilities/Makefile
+++ b/tools/testing/selftests/capabilities/Makefile
@@ -1,15 +1,8 @@
1TEST_FILES := validate_cap 1TEST_GEN_FILES := validate_cap
2TEST_PROGS := test_execve 2TEST_GEN_PROGS := test_execve
3
4BINARIES := $(TEST_FILES) $(TEST_PROGS)
5 3
6CFLAGS += -O2 -g -std=gnu99 -Wall 4CFLAGS += -O2 -g -std=gnu99 -Wall
7LDLIBS += -lcap-ng -lrt -ldl 5LDLIBS += -lcap-ng -lrt -ldl
8 6
9all: $(BINARIES)
10
11clean:
12 $(RM) $(BINARIES)
13
14include ../lib.mk 7include ../lib.mk
15 8
diff --git a/tools/testing/selftests/cpufreq/Makefile b/tools/testing/selftests/cpufreq/Makefile
new file mode 100644
index 000000000000..3955cd96f3a2
--- /dev/null
+++ b/tools/testing/selftests/cpufreq/Makefile
@@ -0,0 +1,8 @@
1all:
2
3TEST_PROGS := main.sh
4TEST_FILES := cpu.sh cpufreq.sh governor.sh module.sh special-tests.sh
5
6include ../lib.mk
7
8clean:
diff --git a/tools/testing/selftests/cpufreq/cpu.sh b/tools/testing/selftests/cpufreq/cpu.sh
new file mode 100755
index 000000000000..8e08a83d65f2
--- /dev/null
+++ b/tools/testing/selftests/cpufreq/cpu.sh
@@ -0,0 +1,84 @@
1#!/bin/bash
2#
3# CPU helpers
4
5# protect against multiple inclusion
6if [ $FILE_CPU ]; then
7 return 0
8else
9 FILE_CPU=DONE
10fi
11
12source cpufreq.sh
13
14for_each_cpu()
15{
16 cpus=$(ls $CPUROOT | grep "cpu[0-9].*")
17 for cpu in $cpus; do
18 $@ $cpu
19 done
20}
21
22for_each_non_boot_cpu()
23{
24 cpus=$(ls $CPUROOT | grep "cpu[1-9].*")
25 for cpu in $cpus; do
26 $@ $cpu
27 done
28}
29
30#$1: cpu
31offline_cpu()
32{
33 printf "Offline $1\n"
34 echo 0 > $CPUROOT/$1/online
35}
36
37#$1: cpu
38online_cpu()
39{
40 printf "Online $1\n"
41 echo 1 > $CPUROOT/$1/online
42}
43
44#$1: cpu
45reboot_cpu()
46{
47 offline_cpu $1
48 online_cpu $1
49}
50
51# Reboot CPUs
52# param: number of times we want to run the loop
53reboot_cpus()
54{
55 printf "** Test: Running ${FUNCNAME[0]} for $1 loops **\n\n"
56
57 for i in `seq 1 $1`; do
58 for_each_non_boot_cpu offline_cpu
59 for_each_non_boot_cpu online_cpu
60 printf "\n"
61 done
62
63 printf "\n%s\n\n" "------------------------------------------------"
64}
65
66# Prints warning for all CPUs with missing cpufreq directory
67print_unmanaged_cpus()
68{
69 for_each_cpu cpu_should_have_cpufreq_directory
70}
71
72# Counts CPUs with cpufreq directories
73count_cpufreq_managed_cpus()
74{
75 count=0;
76
77 for cpu in `ls $CPUROOT | grep "cpu[0-9].*"`; do
78 if [ -d $CPUROOT/$cpu/cpufreq ]; then
79 let count=count+1;
80 fi
81 done
82
83 echo $count;
84}
diff --git a/tools/testing/selftests/cpufreq/cpufreq.sh b/tools/testing/selftests/cpufreq/cpufreq.sh
new file mode 100755
index 000000000000..1ed3832030b4
--- /dev/null
+++ b/tools/testing/selftests/cpufreq/cpufreq.sh
@@ -0,0 +1,241 @@
1#!/bin/bash
2
3# protect against multiple inclusion
4if [ $FILE_CPUFREQ ]; then
5 return 0
6else
7 FILE_CPUFREQ=DONE
8fi
9
10source cpu.sh
11
12
13# $1: cpu
14cpu_should_have_cpufreq_directory()
15{
16 if [ ! -d $CPUROOT/$1/cpufreq ]; then
17 printf "Warning: No cpufreq directory present for $1\n"
18 fi
19}
20
21cpu_should_not_have_cpufreq_directory()
22{
23 if [ -d $CPUROOT/$1/cpufreq ]; then
24 printf "Warning: cpufreq directory present for $1\n"
25 fi
26}
27
28for_each_policy()
29{
30 policies=$(ls $CPUFREQROOT| grep "policy[0-9].*")
31 for policy in $policies; do
32 $@ $policy
33 done
34}
35
36for_each_policy_concurrent()
37{
38 policies=$(ls $CPUFREQROOT| grep "policy[0-9].*")
39 for policy in $policies; do
40 $@ $policy &
41 done
42}
43
44# $1: Path
45read_cpufreq_files_in_dir()
46{
47 local files=`ls $1`
48
49 printf "Printing directory: $1\n\n"
50
51 for file in $files; do
52 if [ -f $1/$file ]; then
53 printf "$file:"
54 cat $1/$file
55 else
56 printf "\n"
57 read_cpufreq_files_in_dir "$1/$file"
58 fi
59 done
60 printf "\n"
61}
62
63
64read_all_cpufreq_files()
65{
66 printf "** Test: Running ${FUNCNAME[0]} **\n\n"
67
68 read_cpufreq_files_in_dir $CPUFREQROOT
69
70 printf "%s\n\n" "------------------------------------------------"
71}
72
73
74# UPDATE CPUFREQ FILES
75
76# $1: directory path
77update_cpufreq_files_in_dir()
78{
79 local files=`ls $1`
80
81 printf "Updating directory: $1\n\n"
82
83 for file in $files; do
84 if [ -f $1/$file ]; then
85 # file is writable ?
86 local wfile=$(ls -l $1/$file | awk '$1 ~ /^.*w.*/ { print $NF; }')
87
88 if [ ! -z $wfile ]; then
89 # scaling_setspeed is a special file and we
90 # should skip updating it
91 if [ $file != "scaling_setspeed" ]; then
92 local val=$(cat $1/$file)
93 printf "Writing $val to: $file\n"
94 echo $val > $1/$file
95 fi
96 fi
97 else
98 printf "\n"
99 update_cpufreq_files_in_dir "$1/$file"
100 fi
101 done
102
103 printf "\n"
104}
105
106# Update all writable files with their existing values
107update_all_cpufreq_files()
108{
109 printf "** Test: Running ${FUNCNAME[0]} **\n\n"
110
111 update_cpufreq_files_in_dir $CPUFREQROOT
112
113 printf "%s\n\n" "------------------------------------------------"
114}
115
116
117# CHANGE CPU FREQUENCIES
118
119# $1: policy
120find_current_freq()
121{
122 cat $CPUFREQROOT/$1/scaling_cur_freq
123}
124
125# $1: policy
126# $2: frequency
127set_cpu_frequency()
128{
129 printf "Change frequency for $1 to $2\n"
130 echo $2 > $CPUFREQROOT/$1/scaling_setspeed
131}
132
133# $1: policy
134test_all_frequencies()
135{
136 local filepath="$CPUFREQROOT/$1"
137
138 backup_governor $1
139
140 local found=$(switch_governor $1 "userspace")
141 if [ $found = 1 ]; then
142 printf "${FUNCNAME[0]}: userspace governor not available for: $1\n"
143 return;
144 fi
145
146 printf "Switched governor for $1 to userspace\n\n"
147
148 local freqs=$(cat $filepath/scaling_available_frequencies)
149 printf "Available frequencies for $1: $freqs\n\n"
150
151 # Set all frequencies one-by-one
152 for freq in $freqs; do
153 set_cpu_frequency $1 $freq
154 done
155
156 printf "\n"
157
158 restore_governor $1
159}
160
161# $1: loop count
162shuffle_frequency_for_all_cpus()
163{
164 printf "** Test: Running ${FUNCNAME[0]} for $1 loops **\n\n"
165
166 for i in `seq 1 $1`; do
167 for_each_policy test_all_frequencies
168 done
169 printf "\n%s\n\n" "------------------------------------------------"
170}
171
172# Basic cpufreq tests
173cpufreq_basic_tests()
174{
175 printf "*** RUNNING CPUFREQ SANITY TESTS ***\n"
176 printf "====================================\n\n"
177
178 count=$(count_cpufreq_managed_cpus)
179 if [ $count = 0 ]; then
180 printf "No cpu is managed by cpufreq core, exiting\n"
181 exit;
182 else
183 printf "CPUFreq manages: $count CPUs\n\n"
184 fi
185
186 # Detect & print which CPUs are not managed by cpufreq
187 print_unmanaged_cpus
188
189 # read/update all cpufreq files
190 read_all_cpufreq_files
191 update_all_cpufreq_files
192
193 # hotplug cpus
194 reboot_cpus 5
195
196 # Test all frequencies
197 shuffle_frequency_for_all_cpus 2
198
199 # Test all governors
200 shuffle_governors_for_all_cpus 1
201}
202
203# Suspend/resume
204# $1: "suspend" or "hibernate", $2: loop count
205do_suspend()
206{
207 printf "** Test: Running ${FUNCNAME[0]}: Trying $1 for $2 loops **\n\n"
208
209 # Is the directory available
210 if [ ! -d $SYSFS/power/ -o ! -f $SYSFS/power/state ]; then
211 printf "$SYSFS/power/state not available\n"
212 return 1
213 fi
214
215 if [ $1 = "suspend" ]; then
216 filename="mem"
217 elif [ $1 = "hibernate" ]; then
218 filename="disk"
219 else
220 printf "$1 is not a valid option\n"
221 return 1
222 fi
223
224 if [ -n $filename ]; then
225 present=$(cat $SYSFS/power/state | grep $filename)
226
227 if [ -z "$present" ]; then
228 printf "Tried to $1 but $filename isn't present in $SYSFS/power/state\n"
229 return 1;
230 fi
231
232 for i in `seq 1 $2`; do
233 printf "Starting $1\n"
234 echo $filename > $SYSFS/power/state
235 printf "Came out of $1\n"
236
237 printf "Do basic tests after finishing $1 to verify cpufreq state\n\n"
238 cpufreq_basic_tests
239 done
240 fi
241}
diff --git a/tools/testing/selftests/cpufreq/governor.sh b/tools/testing/selftests/cpufreq/governor.sh
new file mode 100755
index 000000000000..def645103555
--- /dev/null
+++ b/tools/testing/selftests/cpufreq/governor.sh
@@ -0,0 +1,153 @@
1#!/bin/bash
2#
3# Test governors
4
5# protect against multiple inclusion
6if [ $FILE_GOVERNOR ]; then
7 return 0
8else
9 FILE_GOVERNOR=DONE
10fi
11
12source cpu.sh
13source cpufreq.sh
14
15CUR_GOV=
16CUR_FREQ=
17
18# Find governor's directory path
19# $1: policy, $2: governor
20find_gov_directory()
21{
22 if [ -d $CPUFREQROOT/$2 ]; then
23 printf "$CPUFREQROOT/$2\n"
24 elif [ -d $CPUFREQROOT/$1/$2 ]; then
25 printf "$CPUFREQROOT/$1/$2\n"
26 else
27 printf "INVALID\n"
28 fi
29}
30
31# $1: policy
32find_current_governor()
33{
34 cat $CPUFREQROOT/$1/scaling_governor
35}
36
37# $1: policy
38backup_governor()
39{
40 CUR_GOV=$(find_current_governor $1)
41
42 printf "Governor backup done for $1: $CUR_GOV\n"
43
44 if [ $CUR_GOV == "userspace" ]; then
45 CUR_FREQ=$(find_current_freq $1)
46 printf "Governor frequency backup done for $1: $CUR_FREQ\n"
47 fi
48
49 printf "\n"
50}
51
52# $1: policy
53restore_governor()
54{
55 __switch_governor $1 $CUR_GOV
56
57 printf "Governor restored for $1 to $CUR_GOV\n"
58
59 if [ $CUR_GOV == "userspace" ]; then
60 set_cpu_frequency $1 $CUR_FREQ
61 printf "Governor frequency restored for $1: $CUR_FREQ\n"
62 fi
63
64 printf "\n"
65}
66
67# param:
68# $1: policy, $2: governor
69__switch_governor()
70{
71 echo $2 > $CPUFREQROOT/$1/scaling_governor
72}
73
74# param:
75# $1: cpu, $2: governor
76__switch_governor_for_cpu()
77{
78 echo $2 > $CPUROOT/$1/cpufreq/scaling_governor
79}
80
81# SWITCH GOVERNORS
82
83# $1: cpu, $2: governor
84switch_governor()
85{
86 local filepath=$CPUFREQROOT/$1/scaling_available_governors
87
88 # check if governor is available
89 local found=$(cat $filepath | grep $2 | wc -l)
90 if [ $found = 0 ]; then
91 echo 1;
92 return
93 fi
94
95 __switch_governor $1 $2
96 echo 0;
97}
98
99# $1: policy, $2: governor
100switch_show_governor()
101{
102 cur_gov=find_current_governor
103 if [ $cur_gov == "userspace" ]; then
104 cur_freq=find_current_freq
105 fi
106
107 # switch governor
108 __switch_governor $1 $2
109
110 printf "\nSwitched governor for $1 to $2\n\n"
111
112 if [ $2 == "userspace" -o $2 == "powersave" -o $2 == "performance" ]; then
113 printf "No files to read for $2 governor\n\n"
114 return
115 fi
116
117 # show governor files
118 local govpath=$(find_gov_directory $1 $2)
119 read_cpufreq_files_in_dir $govpath
120}
121
122# $1: function to be called, $2: policy
123call_for_each_governor()
124{
125 local filepath=$CPUFREQROOT/$2/scaling_available_governors
126
127 # Exit if cpu isn't managed by cpufreq core
128 if [ ! -f $filepath ]; then
129 return;
130 fi
131
132 backup_governor $2
133
134 local governors=$(cat $filepath)
135 printf "Available governors for $2: $governors\n"
136
137 for governor in $governors; do
138 $1 $2 $governor
139 done
140
141 restore_governor $2
142}
143
144# $1: loop count
145shuffle_governors_for_all_cpus()
146{
147 printf "** Test: Running ${FUNCNAME[0]} for $1 loops **\n\n"
148
149 for i in `seq 1 $1`; do
150 for_each_policy call_for_each_governor switch_show_governor
151 done
152 printf "%s\n\n" "------------------------------------------------"
153}
diff --git a/tools/testing/selftests/cpufreq/main.sh b/tools/testing/selftests/cpufreq/main.sh
new file mode 100755
index 000000000000..01bac76ac0ec
--- /dev/null
+++ b/tools/testing/selftests/cpufreq/main.sh
@@ -0,0 +1,194 @@
1#!/bin/bash
2
3source cpu.sh
4source cpufreq.sh
5source governor.sh
6source module.sh
7source special-tests.sh
8
9FUNC=basic # do basic tests by default
10OUTFILE=cpufreq_selftest
11SYSFS=
12CPUROOT=
13CPUFREQROOT=
14
15helpme()
16{
17 printf "Usage: $0 [-h] [-todg args]
18 [-h <help>]
19 [-o <output-file-for-dump>]
20 [-t <basic: Basic cpufreq testing
21 suspend: suspend/resume,
22 hibernate: hibernate/resume,
23 modtest: test driver or governor modules. Only to be used with -d or -g options,
24 sptest1: Simple governor switch to produce lockdep.
25 sptest2: Concurrent governor switch to produce lockdep.
26 sptest3: Governor races, shuffle between governors quickly.
27 sptest4: CPU hotplugs with updates to cpufreq files.>]
28 [-d <driver's module name: only with \"-t modtest>\"]
29 [-g <governor's module name: only with \"-t modtest>\"]
30 \n"
31 exit 2
32}
33
34prerequisite()
35{
36 msg="skip all tests:"
37
38 if [ $UID != 0 ]; then
39 echo $msg must be run as root >&2
40 exit 2
41 fi
42
43 taskset -p 01 $$
44
45 SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
46
47 if [ ! -d "$SYSFS" ]; then
48 echo $msg sysfs is not mounted >&2
49 exit 2
50 fi
51
52 CPUROOT=$SYSFS/devices/system/cpu
53 CPUFREQROOT="$CPUROOT/cpufreq"
54
55 if ! ls $CPUROOT/cpu* > /dev/null 2>&1; then
56 echo $msg cpus not available in sysfs >&2
57 exit 2
58 fi
59
60 if ! ls $CPUROOT/cpufreq > /dev/null 2>&1; then
61 echo $msg cpufreq directory not available in sysfs >&2
62 exit 2
63 fi
64}
65
66parse_arguments()
67{
68 while getopts ht:o:d:g: arg
69 do
70 case $arg in
71 h) # --help
72 helpme
73 ;;
74
75 t) # --func_type (Function to perform: basic, suspend, hibernate, modtest, sptest1/2/3/4 (default: basic))
76 FUNC=$OPTARG
77 ;;
78
79 o) # --output-file (Output file to store dumps)
80 OUTFILE=$OPTARG
81 ;;
82
83 d) # --driver-mod-name (Name of the driver module)
84 DRIVER_MOD=$OPTARG
85 ;;
86
87 g) # --governor-mod-name (Name of the governor module)
88 GOVERNOR_MOD=$OPTARG
89 ;;
90
91 \?)
92 helpme
93 ;;
94 esac
95 done
96}
97
98do_test()
99{
100 # Check if CPUs are managed by cpufreq or not
101 count=$(count_cpufreq_managed_cpus)
102
103 if [ $count = 0 -a $FUNC != "modtest" ]; then
104 echo "No cpu is managed by cpufreq core, exiting"
105 exit 2;
106 fi
107
108 case "$FUNC" in
109 "basic")
110 cpufreq_basic_tests
111 ;;
112
113 "suspend")
114 do_suspend "suspend" 1
115 ;;
116
117 "hibernate")
118 do_suspend "hibernate" 1
119 ;;
120
121 "modtest")
122 # Do we have modules in place?
123 if [ -z $DRIVER_MOD ] && [ -z $GOVERNOR_MOD ]; then
124 echo "No driver or governor module passed with -d or -g"
125 exit 2;
126 fi
127
128 if [ $DRIVER_MOD ]; then
129 if [ $GOVERNOR_MOD ]; then
130 module_test $DRIVER_MOD $GOVERNOR_MOD
131 else
132 module_driver_test $DRIVER_MOD
133 fi
134 else
135 if [ $count = 0 ]; then
136 echo "No cpu is managed by cpufreq core, exiting"
137 exit 2;
138 fi
139
140 module_governor_test $GOVERNOR_MOD
141 fi
142 ;;
143
144 "sptest1")
145 simple_lockdep
146 ;;
147
148 "sptest2")
149 concurrent_lockdep
150 ;;
151
152 "sptest3")
153 governor_race
154 ;;
155
156 "sptest4")
157 hotplug_with_updates
158 ;;
159
160 *)
161 echo "Invalid [-f] function type"
162 helpme
163 ;;
164 esac
165}
166
167# clear dumps
168# $1: file name
169clear_dumps()
170{
171 echo "" > $1.txt
172 echo "" > $1.dmesg_cpufreq.txt
173 echo "" > $1.dmesg_full.txt
174}
175
176# $1: output file name
177dmesg_dumps()
178{
179 dmesg | grep cpufreq >> $1.dmesg_cpufreq.txt
180
181 # We may need the full logs as well
182 dmesg >> $1.dmesg_full.txt
183}
184
185# Parse arguments
186parse_arguments $@
187
188# Make sure all requirements are met
189prerequisite
190
191# Run requested functions
192clear_dumps $OUTFILE
193do_test >> $OUTFILE.txt
194dmesg_dumps $OUTFILE
diff --git a/tools/testing/selftests/cpufreq/module.sh b/tools/testing/selftests/cpufreq/module.sh
new file mode 100755
index 000000000000..8ff2244a33a1
--- /dev/null
+++ b/tools/testing/selftests/cpufreq/module.sh
@@ -0,0 +1,243 @@
1#!/bin/bash
2#
3# Modules specific tests cases
4
5# protect against multiple inclusion
6if [ $FILE_MODULE ]; then
7 return 0
8else
9 FILE_MODULE=DONE
10fi
11
12source cpu.sh
13source cpufreq.sh
14source governor.sh
15
16# Check basic insmod/rmmod
17# $1: module
18test_basic_insmod_rmmod()
19{
20 printf "** Test: Running ${FUNCNAME[0]} **\n\n"
21
22 printf "Inserting $1 module\n"
23 # insert module
24 insmod $1
25 if [ $? != 0 ]; then
26 printf "Insmod $1 failed\n"
27 exit;
28 fi
29
30 printf "Removing $1 module\n"
31 # remove module
32 rmmod $1
33 if [ $? != 0 ]; then
34 printf "rmmod $1 failed\n"
35 exit;
36 fi
37
38 printf "\n"
39}
40
41# Insert cpufreq driver module and perform basic tests
42# $1: cpufreq-driver module to insert
43# $2: If we want to play with CPUs (1) or not (0)
44module_driver_test_single()
45{
46 printf "** Test: Running ${FUNCNAME[0]} for driver $1 and cpus_hotplug=$2 **\n\n"
47
48 if [ $2 -eq 1 ]; then
49 # offline all non-boot CPUs
50 for_each_non_boot_cpu offline_cpu
51 printf "\n"
52 fi
53
54 # insert module
55 printf "Inserting $1 module\n\n"
56 insmod $1
57 if [ $? != 0 ]; then
58 printf "Insmod $1 failed\n"
59 return;
60 fi
61
62 if [ $2 -eq 1 ]; then
63 # online all non-boot CPUs
64 for_each_non_boot_cpu online_cpu
65 printf "\n"
66 fi
67
68 # run basic tests
69 cpufreq_basic_tests
70
71 # remove module
72 printf "Removing $1 module\n\n"
73 rmmod $1
74 if [ $? != 0 ]; then
75 printf "rmmod $1 failed\n"
76 return;
77 fi
78
79 # There shouldn't be any cpufreq directories now.
80 for_each_cpu cpu_should_not_have_cpufreq_directory
81 printf "\n"
82}
83
84# $1: cpufreq-driver module to insert
85module_driver_test()
86{
87 printf "** Test: Running ${FUNCNAME[0]} **\n\n"
88
89 # check if module is present or not
90 ls $1 > /dev/null
91 if [ $? != 0 ]; then
92 printf "$1: not present in `pwd` folder\n"
93 return;
94 fi
95
96 # test basic module tests
97 test_basic_insmod_rmmod $1
98
99 # Do simple module test
100 module_driver_test_single $1 0
101
102 # Remove CPUs before inserting module and then bring them back
103 module_driver_test_single $1 1
104 printf "\n"
105}
106
107# find governor name based on governor module name
108# $1: governor module name
109find_gov_name()
110{
111 if [ $1 = "cpufreq_ondemand.ko" ]; then
112 printf "ondemand"
113 elif [ $1 = "cpufreq_conservative.ko" ]; then
114 printf "conservative"
115 elif [ $1 = "cpufreq_userspace.ko" ]; then
116 printf "userspace"
117 elif [ $1 = "cpufreq_performance.ko" ]; then
118 printf "performance"
119 elif [ $1 = "cpufreq_powersave.ko" ]; then
120 printf "powersave"
121 elif [ $1 = "cpufreq_schedutil.ko" ]; then
122 printf "schedutil"
123 fi
124}
125
126# $1: governor string, $2: governor module, $3: policy
127# example: module_governor_test_single "ondemand" "cpufreq_ondemand.ko" 2
128module_governor_test_single()
129{
130 printf "** Test: Running ${FUNCNAME[0]} for $3 **\n\n"
131
132 backup_governor $3
133
134 # switch to new governor
135 printf "Switch from $CUR_GOV to $1\n"
136 switch_show_governor $3 $1
137
138 # try removing module, it should fail as governor is used
139 printf "Removing $2 module\n\n"
140 rmmod $2
141 if [ $? = 0 ]; then
142 printf "WARN: rmmod $2 succeeded even if governor is used\n"
143 insmod $2
144 else
145 printf "Pass: unable to remove $2 while it is being used\n\n"
146 fi
147
148 # switch back to old governor
149 printf "Switchback to $CUR_GOV from $1\n"
150 restore_governor $3
151 printf "\n"
152}
153
154# Insert cpufreq governor module and perform basic tests
155# $1: cpufreq-governor module to insert
156module_governor_test()
157{
158 printf "** Test: Running ${FUNCNAME[0]} **\n\n"
159
160 # check if module is present or not
161 ls $1 > /dev/null
162 if [ $? != 0 ]; then
163 printf "$1: not present in `pwd` folder\n"
164 return;
165 fi
166
167 # test basic module tests
168 test_basic_insmod_rmmod $1
169
170 # insert module
171 printf "Inserting $1 module\n\n"
172 insmod $1
173 if [ $? != 0 ]; then
174 printf "Insmod $1 failed\n"
175 return;
176 fi
177
178 # switch to new governor for each cpu
179 for_each_policy module_governor_test_single $(find_gov_name $1) $1
180
181 # remove module
182 printf "Removing $1 module\n\n"
183 rmmod $1
184 if [ $? != 0 ]; then
185 printf "rmmod $1 failed\n"
186 return;
187 fi
188 printf "\n"
189}
190
191# test modules: driver and governor
192# $1: driver module, $2: governor module
193module_test()
194{
195 printf "** Test: Running ${FUNCNAME[0]} **\n\n"
196
197 # check if modules are present or not
198 ls $1 $2 > /dev/null
199 if [ $? != 0 ]; then
200 printf "$1 or $2: is not present in `pwd` folder\n"
201 return;
202 fi
203
204 # TEST1: Insert gov after driver
205 # insert driver module
206 printf "Inserting $1 module\n\n"
207 insmod $1
208 if [ $? != 0 ]; then
209 printf "Insmod $1 failed\n"
210 return;
211 fi
212
213 # run governor tests
214 module_governor_test $2
215
216 # remove driver module
217 printf "Removing $1 module\n\n"
218 rmmod $1
219 if [ $? != 0 ]; then
220 printf "rmmod $1 failed\n"
221 return;
222 fi
223
224 # TEST2: Insert driver after governor
225 # insert governor module
226 printf "Inserting $2 module\n\n"
227 insmod $2
228 if [ $? != 0 ]; then
229 printf "Insmod $2 failed\n"
230 return;
231 fi
232
233 # run governor tests
234 module_driver_test $1
235
236 # remove driver module
237 printf "Removing $2 module\n\n"
238 rmmod $2
239 if [ $? != 0 ]; then
240 printf "rmmod $2 failed\n"
241 return;
242 fi
243}
diff --git a/tools/testing/selftests/cpufreq/special-tests.sh b/tools/testing/selftests/cpufreq/special-tests.sh
new file mode 100755
index 000000000000..58b730f23ef7
--- /dev/null
+++ b/tools/testing/selftests/cpufreq/special-tests.sh
@@ -0,0 +1,115 @@
1#!/bin/bash
2#
3# Special test cases reported by people
4
5# Testcase 1: Reported here: http://marc.info/?l=linux-pm&m=140618592709858&w=2
6
7# protect against multiple inclusion
8if [ $FILE_SPECIAL ]; then
9 return 0
10else
11 FILE_SPECIAL=DONE
12fi
13
14source cpu.sh
15source cpufreq.sh
16source governor.sh
17
18# Test 1
19# $1: policy
20__simple_lockdep()
21{
22 # switch to ondemand
23 __switch_governor $1 "ondemand"
24
25 # cat ondemand files
26 local ondir=$(find_gov_directory $1 "ondemand")
27 if [ -z $ondir ]; then
28 printf "${FUNCNAME[0]}Ondemand directory not created, quit"
29 return
30 fi
31
32 cat $ondir/*
33
34 # switch to conservative
35 __switch_governor $1 "conservative"
36}
37
38simple_lockdep()
39{
40 printf "** Test: Running ${FUNCNAME[0]} **\n"
41
42 for_each_policy __simple_lockdep
43}
44
45# Test 2
46# $1: policy
47__concurrent_lockdep()
48{
49 for i in `seq 0 100`; do
50 __simple_lockdep $1
51 done
52}
53
54concurrent_lockdep()
55{
56 printf "** Test: Running ${FUNCNAME[0]} **\n"
57
58 for_each_policy_concurrent __concurrent_lockdep
59}
60
61# Test 3
62quick_shuffle()
63{
64 # this is called concurrently from governor_race
65 for I in `seq 1000`
66 do
67 echo ondemand | sudo tee $CPUFREQROOT/policy*/scaling_governor &
68 echo userspace | sudo tee $CPUFREQROOT/policy*/scaling_governor &
69 done
70}
71
72governor_race()
73{
74 printf "** Test: Running ${FUNCNAME[0]} **\n"
75
76 # run 8 concurrent instances
77 for I in `seq 8`
78 do
79 quick_shuffle &
80 done
81}
82
83# Test 4
84# $1: cpu
85hotplug_with_updates_cpu()
86{
87 local filepath="$CPUROOT/$1/cpufreq"
88
89 # switch to ondemand
90 __switch_governor_for_cpu $1 "ondemand"
91
92 for i in `seq 1 5000`
93 do
94 reboot_cpu $1
95 done &
96
97 local freqs=$(cat $filepath/scaling_available_frequencies)
98 local oldfreq=$(cat $filepath/scaling_min_freq)
99
100 for j in `seq 1 5000`
101 do
102 # Set all frequencies one-by-one
103 for freq in $freqs; do
104 echo $freq > $filepath/scaling_min_freq
105 done
106 done
107
108 # restore old freq
109 echo $oldfreq > $filepath/scaling_min_freq
110}
111
112hotplug_with_updates()
113{
114 for_each_non_boot_cpu hotplug_with_updates_cpu
115}
diff --git a/tools/testing/selftests/efivarfs/Makefile b/tools/testing/selftests/efivarfs/Makefile
index 736c3ddfc787..c49dcea69319 100644
--- a/tools/testing/selftests/efivarfs/Makefile
+++ b/tools/testing/selftests/efivarfs/Makefile
@@ -1,13 +1,7 @@
1CFLAGS = -Wall 1CFLAGS = -Wall
2 2
3test_objs = open-unlink create-read 3TEST_GEN_FILES := open-unlink create-read
4
5all: $(test_objs)
6
7TEST_PROGS := efivarfs.sh 4TEST_PROGS := efivarfs.sh
8TEST_FILES := $(test_objs)
9 5
10include ../lib.mk 6include ../lib.mk
11 7
12clean:
13 rm -f $(test_objs)
diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftests/exec/Makefile
index d4300602bf37..2e13035dff7f 100644
--- a/tools/testing/selftests/exec/Makefile
+++ b/tools/testing/selftests/exec/Makefile
@@ -1,27 +1,23 @@
1CFLAGS = -Wall 1CFLAGS = -Wall
2BINARIES = execveat
3DEPS = execveat.symlink execveat.denatured script subdir
4all: $(BINARIES) $(DEPS)
5 2
6subdir: 3TEST_GEN_PROGS := execveat
4TEST_GEN_FILES := execveat.symlink execveat.denatured script subdir
5# Makefile is a run-time dependency, since it's accessed by the execveat test
6TEST_FILES := Makefile
7
8EXTRA_CLEAN := $(OUTPUT)/subdir.moved $(OUTPUT)/execveat.moved $(OUTPUT)/xxxxx*
9
10include ../lib.mk
11
12$(OUTPUT)/subdir:
7 mkdir -p $@ 13 mkdir -p $@
8script: 14$(OUTPUT)/script:
9 echo '#!/bin/sh' > $@ 15 echo '#!/bin/sh' > $@
10 echo 'exit $$*' >> $@ 16 echo 'exit $$*' >> $@
11 chmod +x $@ 17 chmod +x $@
12execveat.symlink: execveat 18$(OUTPUT)/execveat.symlink: $(OUTPUT)/execveat
13 ln -s -f $< $@ 19 cd $(OUTPUT) && ln -s -f $(shell basename $<) $(shell basename $@)
14execveat.denatured: execveat 20$(OUTPUT)/execveat.denatured: $(OUTPUT)/execveat
15 cp $< $@ 21 cp $< $@
16 chmod -x $@ 22 chmod -x $@
17%: %.c
18 $(CC) $(CFLAGS) -o $@ $^
19
20TEST_PROGS := execveat
21# Makefile is a run-time dependency, since it's accessed by the execveat test
22TEST_FILES := $(DEPS) Makefile
23
24include ../lib.mk
25 23
26clean:
27 rm -rf $(BINARIES) $(DEPS) subdir.moved execveat.moved xxxxx*
diff --git a/tools/testing/selftests/firmware/Makefile b/tools/testing/selftests/firmware/Makefile
index 9bf82234855b..1894d625af2d 100644
--- a/tools/testing/selftests/firmware/Makefile
+++ b/tools/testing/selftests/firmware/Makefile
@@ -3,7 +3,7 @@
3# No binaries, but make sure arg-less "make" doesn't trigger "run_tests" 3# No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
4all: 4all:
5 5
6TEST_PROGS := fw_filesystem.sh fw_userhelper.sh 6TEST_PROGS := fw_filesystem.sh fw_fallback.sh
7 7
8include ../lib.mk 8include ../lib.mk
9 9
diff --git a/tools/testing/selftests/firmware/fw_fallback.sh b/tools/testing/selftests/firmware/fw_fallback.sh
new file mode 100755
index 000000000000..2e4c22d5abf7
--- /dev/null
+++ b/tools/testing/selftests/firmware/fw_fallback.sh
@@ -0,0 +1,224 @@
1#!/bin/sh
2# This validates that the kernel will fall back to using the fallback mechanism
3# to load firmware it can't find on disk itself. We must request a firmware
4# that the kernel won't find, and any installed helper (e.g. udev) also
5# won't find so that we can do the load ourself manually.
6set -e
7
8modprobe test_firmware
9
10DIR=/sys/devices/virtual/misc/test_firmware
11
12# CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/
13# These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that
14# as an indicator for CONFIG_FW_LOADER_USER_HELPER.
15HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
16
17if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
18 OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
19else
20 echo "usermode helper disabled so ignoring test"
21 exit 0
22fi
23
24FWPATH=$(mktemp -d)
25FW="$FWPATH/test-firmware.bin"
26
27test_finish()
28{
29 echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
30 rm -f "$FW"
31 rmdir "$FWPATH"
32}
33
34load_fw()
35{
36 local name="$1"
37 local file="$2"
38
39 # This will block until our load (below) has finished.
40 echo -n "$name" >"$DIR"/trigger_request &
41
42 # Give kernel a chance to react.
43 local timeout=10
44 while [ ! -e "$DIR"/"$name"/loading ]; do
45 sleep 0.1
46 timeout=$(( $timeout - 1 ))
47 if [ "$timeout" -eq 0 ]; then
48 echo "$0: firmware interface never appeared" >&2
49 exit 1
50 fi
51 done
52
53 echo 1 >"$DIR"/"$name"/loading
54 cat "$file" >"$DIR"/"$name"/data
55 echo 0 >"$DIR"/"$name"/loading
56
57 # Wait for request to finish.
58 wait
59}
60
61load_fw_cancel()
62{
63 local name="$1"
64 local file="$2"
65
66 # This will block until our load (below) has finished.
67 echo -n "$name" >"$DIR"/trigger_request 2>/dev/null &
68
69 # Give kernel a chance to react.
70 local timeout=10
71 while [ ! -e "$DIR"/"$name"/loading ]; do
72 sleep 0.1
73 timeout=$(( $timeout - 1 ))
74 if [ "$timeout" -eq 0 ]; then
75 echo "$0: firmware interface never appeared" >&2
76 exit 1
77 fi
78 done
79
80 echo -1 >"$DIR"/"$name"/loading
81
82 # Wait for request to finish.
83 wait
84}
85
86load_fw_custom()
87{
88 local name="$1"
89 local file="$2"
90
91 echo -n "$name" >"$DIR"/trigger_custom_fallback 2>/dev/null &
92
93 # Give kernel a chance to react.
94 local timeout=10
95 while [ ! -e "$DIR"/"$name"/loading ]; do
96 sleep 0.1
97 timeout=$(( $timeout - 1 ))
98 if [ "$timeout" -eq 0 ]; then
99 echo "$0: firmware interface never appeared" >&2
100 exit 1
101 fi
102 done
103
104 echo 1 >"$DIR"/"$name"/loading
105 cat "$file" >"$DIR"/"$name"/data
106 echo 0 >"$DIR"/"$name"/loading
107
108 # Wait for request to finish.
109 wait
110}
111
112
113load_fw_custom_cancel()
114{
115 local name="$1"
116 local file="$2"
117
118 echo -n "$name" >"$DIR"/trigger_custom_fallback 2>/dev/null &
119
120 # Give kernel a chance to react.
121 local timeout=10
122 while [ ! -e "$DIR"/"$name"/loading ]; do
123 sleep 0.1
124 timeout=$(( $timeout - 1 ))
125 if [ "$timeout" -eq 0 ]; then
126 echo "$0: firmware interface never appeared" >&2
127 exit 1
128 fi
129 done
130
131 echo -1 >"$DIR"/"$name"/loading
132
133 # Wait for request to finish.
134 wait
135}
136
137
138trap "test_finish" EXIT
139
140# This is an unlikely real-world firmware content. :)
141echo "ABCD0123" >"$FW"
142NAME=$(basename "$FW")
143
144DEVPATH="$DIR"/"nope-$NAME"/loading
145
146# Test failure when doing nothing (timeout works).
147echo -n 2 >/sys/class/firmware/timeout
148echo -n "nope-$NAME" >"$DIR"/trigger_request 2>/dev/null &
149
150# Give the kernel some time to load the loading file, must be less
151# than the timeout above.
152sleep 1
153if [ ! -f $DEVPATH ]; then
154 echo "$0: fallback mechanism immediately cancelled"
155 echo ""
156 echo "The file never appeared: $DEVPATH"
157 echo ""
158 echo "This might be a distribution udev rule setup by your distribution"
159 echo "to immediately cancel all fallback requests, this must be"
160 echo "removed before running these tests. To confirm look for"
161 echo "a firmware rule like /lib/udev/rules.d/50-firmware.rules"
162 echo "and see if you have something like this:"
163 echo ""
164 echo "SUBSYSTEM==\"firmware\", ACTION==\"add\", ATTR{loading}=\"-1\""
165 echo ""
166 echo "If you do remove this file or comment out this line before"
167 echo "proceeding with these tests."
168 exit 1
169fi
170
171if diff -q "$FW" /dev/test_firmware >/dev/null ; then
172 echo "$0: firmware was not expected to match" >&2
173 exit 1
174else
175 echo "$0: timeout works"
176fi
177
178# Put timeout high enough for us to do work but not so long that failures
179# slow down this test too much.
180echo 4 >/sys/class/firmware/timeout
181
182# Load this script instead of the desired firmware.
183load_fw "$NAME" "$0"
184if diff -q "$FW" /dev/test_firmware >/dev/null ; then
185 echo "$0: firmware was not expected to match" >&2
186 exit 1
187else
188 echo "$0: firmware comparison works"
189fi
190
191# Do a proper load, which should work correctly.
192load_fw "$NAME" "$FW"
193if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
194 echo "$0: firmware was not loaded" >&2
195 exit 1
196else
197 echo "$0: fallback mechanism works"
198fi
199
200load_fw_cancel "nope-$NAME" "$FW"
201if diff -q "$FW" /dev/test_firmware >/dev/null ; then
202 echo "$0: firmware was expected to be cancelled" >&2
203 exit 1
204else
205 echo "$0: cancelling fallback mechanism works"
206fi
207
208load_fw_custom "$NAME" "$FW"
209if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
210 echo "$0: firmware was not loaded" >&2
211 exit 1
212else
213 echo "$0: custom fallback loading mechanism works"
214fi
215
216load_fw_custom_cancel "nope-$NAME" "$FW"
217if diff -q "$FW" /dev/test_firmware >/dev/null ; then
218 echo "$0: firmware was expected to be cancelled" >&2
219 exit 1
220else
221 echo "$0: cancelling custom fallback mechanism works"
222fi
223
224exit 0
diff --git a/tools/testing/selftests/firmware/fw_filesystem.sh b/tools/testing/selftests/firmware/fw_filesystem.sh
index 5c495ad7958a..e35691239350 100755
--- a/tools/testing/selftests/firmware/fw_filesystem.sh
+++ b/tools/testing/selftests/firmware/fw_filesystem.sh
@@ -5,9 +5,24 @@
5# know so we can be sure we're not accidentally testing the user helper. 5# know so we can be sure we're not accidentally testing the user helper.
6set -e 6set -e
7 7
8modprobe test_firmware
9
10DIR=/sys/devices/virtual/misc/test_firmware 8DIR=/sys/devices/virtual/misc/test_firmware
9TEST_DIR=$(dirname $0)
10
11test_modprobe()
12{
13 if [ ! -d $DIR ]; then
14 echo "$0: $DIR not present"
15 echo "You must have the following enabled in your kernel:"
16 cat $TEST_DIR/config
17 exit 1
18 fi
19}
20
21trap "test_modprobe" EXIT
22
23if [ ! -d $DIR ]; then
24 modprobe test_firmware
25fi
11 26
12# 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/
13# These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that 28# These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that
@@ -48,18 +63,18 @@ echo "ABCD0123" >"$FW"
48 63
49NAME=$(basename "$FW") 64NAME=$(basename "$FW")
50 65
51if printf '\000' >"$DIR"/trigger_request; then 66if printf '\000' >"$DIR"/trigger_request 2> /dev/null; then
52 echo "$0: empty filename should not succeed" >&2 67 echo "$0: empty filename should not succeed" >&2
53 exit 1 68 exit 1
54fi 69fi
55 70
56if printf '\000' >"$DIR"/trigger_async_request; then 71if printf '\000' >"$DIR"/trigger_async_request 2> /dev/null; then
57 echo "$0: empty filename should not succeed (async)" >&2 72 echo "$0: empty filename should not succeed (async)" >&2
58 exit 1 73 exit 1
59fi 74fi
60 75
61# Request a firmware that doesn't exist, it should fail. 76# Request a firmware that doesn't exist, it should fail.
62if echo -n "nope-$NAME" >"$DIR"/trigger_request; then 77if echo -n "nope-$NAME" >"$DIR"/trigger_request 2> /dev/null; then
63 echo "$0: firmware shouldn't have loaded" >&2 78 echo "$0: firmware shouldn't have loaded" >&2
64 exit 1 79 exit 1
65fi 80fi
diff --git a/tools/testing/selftests/firmware/fw_userhelper.sh b/tools/testing/selftests/firmware/fw_userhelper.sh
deleted file mode 100755
index b9983f8e09f6..000000000000
--- a/tools/testing/selftests/firmware/fw_userhelper.sh
+++ /dev/null
@@ -1,99 +0,0 @@
1#!/bin/sh
2# This validates that the kernel will fall back to using the user helper
3# to load firmware it can't find on disk itself. We must request a firmware
4# that the kernel won't find, and any installed helper (e.g. udev) also
5# won't find so that we can do the load ourself manually.
6set -e
7
8modprobe test_firmware
9
10DIR=/sys/devices/virtual/misc/test_firmware
11
12# CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/
13# These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that
14# as an indicator for CONFIG_FW_LOADER_USER_HELPER.
15HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
16
17if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
18 OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
19else
20 echo "usermode helper disabled so ignoring test"
21 exit 0
22fi
23
24FWPATH=$(mktemp -d)
25FW="$FWPATH/test-firmware.bin"
26
27test_finish()
28{
29 echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
30 rm -f "$FW"
31 rmdir "$FWPATH"
32}
33
34load_fw()
35{
36 local name="$1"
37 local file="$2"
38
39 # This will block until our load (below) has finished.
40 echo -n "$name" >"$DIR"/trigger_request &
41
42 # Give kernel a chance to react.
43 local timeout=10
44 while [ ! -e "$DIR"/"$name"/loading ]; do
45 sleep 0.1
46 timeout=$(( $timeout - 1 ))
47 if [ "$timeout" -eq 0 ]; then
48 echo "$0: firmware interface never appeared" >&2
49 exit 1
50 fi
51 done
52
53 echo 1 >"$DIR"/"$name"/loading
54 cat "$file" >"$DIR"/"$name"/data
55 echo 0 >"$DIR"/"$name"/loading
56
57 # Wait for request to finish.
58 wait
59}
60
61trap "test_finish" EXIT
62
63# This is an unlikely real-world firmware content. :)
64echo "ABCD0123" >"$FW"
65NAME=$(basename "$FW")
66
67# Test failure when doing nothing (timeout works).
68echo 1 >/sys/class/firmware/timeout
69echo -n "$NAME" >"$DIR"/trigger_request
70if diff -q "$FW" /dev/test_firmware >/dev/null ; then
71 echo "$0: firmware was not expected to match" >&2
72 exit 1
73else
74 echo "$0: timeout works"
75fi
76
77# Put timeout high enough for us to do work but not so long that failures
78# slow down this test too much.
79echo 4 >/sys/class/firmware/timeout
80
81# Load this script instead of the desired firmware.
82load_fw "$NAME" "$0"
83if diff -q "$FW" /dev/test_firmware >/dev/null ; then
84 echo "$0: firmware was not expected to match" >&2
85 exit 1
86else
87 echo "$0: firmware comparison works"
88fi
89
90# Do a proper load, which should work correctly.
91load_fw "$NAME" "$FW"
92if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
93 echo "$0: firmware was not loaded" >&2
94 exit 1
95else
96 echo "$0: user helper firmware loading works"
97fi
98
99exit 0
diff --git a/tools/testing/selftests/ftrace/Makefile b/tools/testing/selftests/ftrace/Makefile
index 4e6ed13e7f66..a8a5e21850e7 100644
--- a/tools/testing/selftests/ftrace/Makefile
+++ b/tools/testing/selftests/ftrace/Makefile
@@ -1,9 +1,7 @@
1all: 1all:
2 2
3TEST_PROGS := ftracetest 3TEST_PROGS := ftracetest
4TEST_DIRS := test.d 4TEST_FILES := test.d
5EXTRA_CLEAN := $(OUTPUT)/logs/*
5 6
6include ../lib.mk 7include ../lib.mk
7
8clean:
9 rm -rf logs/*
diff --git a/tools/testing/selftests/futex/Makefile b/tools/testing/selftests/futex/Makefile
index 6a1752956283..653c5cd9e44d 100644
--- a/tools/testing/selftests/futex/Makefile
+++ b/tools/testing/selftests/futex/Makefile
@@ -3,13 +3,18 @@ SUBDIRS := functional
3TEST_PROGS := run.sh 3TEST_PROGS := run.sh
4 4
5.PHONY: all clean 5.PHONY: all clean
6all:
7 for DIR in $(SUBDIRS); do $(MAKE) -C $$DIR $@ ; done
8 6
9include ../lib.mk 7include ../lib.mk
10 8
9all:
10 for DIR in $(SUBDIRS); do \
11 BUILD_TARGET=$$OUTPUT/$$DIR; \
12 mkdir $$BUILD_TARGET -p; \
13 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
14 done
15
11override define RUN_TESTS 16override define RUN_TESTS
12 ./run.sh 17 @if [ `dirname $(OUTPUT)` = $(PWD) ]; then ./run.sh; fi
13endef 18endef
14 19
15override define INSTALL_RULE 20override define INSTALL_RULE
@@ -17,7 +22,9 @@ override define INSTALL_RULE
17 install -t $(INSTALL_PATH) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) 22 install -t $(INSTALL_PATH) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES)
18 23
19 @for SUBDIR in $(SUBDIRS); do \ 24 @for SUBDIR in $(SUBDIRS); do \
20 $(MAKE) -C $$SUBDIR INSTALL_PATH=$(INSTALL_PATH)/$$SUBDIR install; \ 25 BUILD_TARGET=$$OUTPUT/$$SUBDIR; \
26 mkdir $$BUILD_TARGET -p; \
27 $(MAKE) OUTPUT=$$BUILD_TARGET -C $$SUBDIR INSTALL_PATH=$(INSTALL_PATH)/$$SUBDIR install; \
21 done; 28 done;
22endef 29endef
23 30
@@ -26,4 +33,8 @@ override define EMIT_TESTS
26endef 33endef
27 34
28clean: 35clean:
29 for DIR in $(SUBDIRS); do $(MAKE) -C $$DIR $@ ; done 36 for DIR in $(SUBDIRS); do \
37 BUILD_TARGET=$$OUTPUT/$$DIR; \
38 mkdir $$BUILD_TARGET -p; \
39 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
40 done
diff --git a/tools/testing/selftests/futex/functional/Makefile b/tools/testing/selftests/futex/functional/Makefile
index 9d6b75ef7b5d..a648e7a6cbc3 100644
--- a/tools/testing/selftests/futex/functional/Makefile
+++ b/tools/testing/selftests/futex/functional/Makefile
@@ -2,8 +2,11 @@ INCLUDES := -I../include -I../../
2CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE -pthread $(INCLUDES) 2CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE -pthread $(INCLUDES)
3LDFLAGS := $(LDFLAGS) -pthread -lrt 3LDFLAGS := $(LDFLAGS) -pthread -lrt
4 4
5HEADERS := ../include/futextest.h 5HEADERS := \
6TARGETS := \ 6 ../include/futextest.h \
7 ../include/atomic.h \
8 ../include/logging.h
9TEST_GEN_FILES := \
7 futex_wait_timeout \ 10 futex_wait_timeout \
8 futex_wait_wouldblock \ 11 futex_wait_wouldblock \
9 futex_requeue_pi \ 12 futex_requeue_pi \
@@ -12,14 +15,8 @@ TARGETS := \
12 futex_wait_uninitialized_heap \ 15 futex_wait_uninitialized_heap \
13 futex_wait_private_mapped_file 16 futex_wait_private_mapped_file
14 17
15TEST_PROGS := $(TARGETS) run.sh 18TEST_PROGS := run.sh
16
17.PHONY: all clean
18all: $(TARGETS)
19
20$(TARGETS): $(HEADERS)
21 19
22include ../../lib.mk 20include ../../lib.mk
23 21
24clean: 22$(TEST_GEN_FILES): $(HEADERS)
25 rm -f $(TARGETS)
diff --git a/tools/testing/selftests/futex/include/logging.h b/tools/testing/selftests/futex/include/logging.h
index 014aa01197af..e14469103f07 100644
--- a/tools/testing/selftests/futex/include/logging.h
+++ b/tools/testing/selftests/futex/include/logging.h
@@ -21,6 +21,7 @@
21#ifndef _LOGGING_H 21#ifndef _LOGGING_H
22#define _LOGGING_H 22#define _LOGGING_H
23 23
24#include <stdio.h>
24#include <string.h> 25#include <string.h>
25#include <unistd.h> 26#include <unistd.h>
26#include <linux/futex.h> 27#include <linux/futex.h>
diff --git a/tools/testing/selftests/gpio/.gitignore b/tools/testing/selftests/gpio/.gitignore
new file mode 100644
index 000000000000..7d14f743d1a4
--- /dev/null
+++ b/tools/testing/selftests/gpio/.gitignore
@@ -0,0 +1 @@
gpio-mockup-chardev
diff --git a/tools/testing/selftests/intel_pstate/Makefile b/tools/testing/selftests/intel_pstate/Makefile
index f5f1a28715ff..19678e90efb2 100644
--- a/tools/testing/selftests/intel_pstate/Makefile
+++ b/tools/testing/selftests/intel_pstate/Makefile
@@ -1,15 +1,10 @@
1CC := $(CROSS_COMPILE)gcc
2CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE 1CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE
3LDFLAGS := $(LDFLAGS) -lm 2LDFLAGS := $(LDFLAGS) -lm
4 3
5TARGETS := msr aperf 4TEST_GEN_FILES := msr aperf
6 5
7TEST_PROGS := $(TARGETS) run.sh 6TEST_PROGS := run.sh
8 7
9.PHONY: all clean 8include ../lib.mk
10all: $(TARGETS)
11 9
12$(TARGETS): $(HEADERS) 10$(TEST_GEN_FILES): $(HEADERS)
13
14clean:
15 rm -f $(TARGETS)
diff --git a/tools/testing/selftests/intel_pstate/aperf.c b/tools/testing/selftests/intel_pstate/aperf.c
index 6046e183f4ad..cd72f3dc83e9 100644
--- a/tools/testing/selftests/intel_pstate/aperf.c
+++ b/tools/testing/selftests/intel_pstate/aperf.c
@@ -14,7 +14,7 @@ void usage(char *name) {
14} 14}
15 15
16int main(int argc, char **argv) { 16int main(int argc, char **argv) {
17 int i, cpu, fd; 17 unsigned int i, cpu, fd;
18 char msr_file_name[64]; 18 char msr_file_name[64];
19 long long tsc, old_tsc, new_tsc; 19 long long tsc, old_tsc, new_tsc;
20 long long aperf, old_aperf, new_aperf; 20 long long aperf, old_aperf, new_aperf;
diff --git a/tools/testing/selftests/ipc/.gitignore b/tools/testing/selftests/ipc/.gitignore
index 84b66a3c1f74..9af04c9353c0 100644
--- a/tools/testing/selftests/ipc/.gitignore
+++ b/tools/testing/selftests/ipc/.gitignore
@@ -1 +1,2 @@
1msgque_test 1msgque_test
2msgque
diff --git a/tools/testing/selftests/ipc/Makefile b/tools/testing/selftests/ipc/Makefile
index 25d2e702c68a..30ef4c7f53ea 100644
--- a/tools/testing/selftests/ipc/Makefile
+++ b/tools/testing/selftests/ipc/Makefile
@@ -11,12 +11,7 @@ endif
11 11
12CFLAGS += -I../../../../usr/include/ 12CFLAGS += -I../../../../usr/include/
13 13
14all: 14TEST_GEN_PROGS := msgque
15 $(CC) $(CFLAGS) msgque.c -o msgque_test
16
17TEST_PROGS := msgque_test
18 15
19include ../lib.mk 16include ../lib.mk
20 17
21clean:
22 rm -fr ./msgque_test
diff --git a/tools/testing/selftests/kcmp/Makefile b/tools/testing/selftests/kcmp/Makefile
index 2ae7450a9a89..47aa9887f9d4 100644
--- a/tools/testing/selftests/kcmp/Makefile
+++ b/tools/testing/selftests/kcmp/Makefile
@@ -1,10 +1,8 @@
1CFLAGS += -I../../../../usr/include/ 1CFLAGS += -I../../../../usr/include/
2 2
3all: kcmp_test 3TEST_GEN_PROGS := kcmp_test
4 4
5TEST_PROGS := kcmp_test 5EXTRA_CLEAN := $(OUTPUT)/kcmp-test-file
6 6
7include ../lib.mk 7include ../lib.mk
8 8
9clean:
10 $(RM) kcmp_test kcmp-test-file
diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk
index 50a93f5f13d6..775c589ac3c0 100644
--- a/tools/testing/selftests/lib.mk
+++ b/tools/testing/selftests/lib.mk
@@ -2,9 +2,19 @@
2# Makefile can operate with or without the kbuild infrastructure. 2# Makefile can operate with or without the kbuild infrastructure.
3CC := $(CROSS_COMPILE)gcc 3CC := $(CROSS_COMPILE)gcc
4 4
5ifeq (0,$(MAKELEVEL))
6OUTPUT := $(shell pwd)
7endif
8
9TEST_GEN_PROGS := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS))
10TEST_GEN_FILES := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_FILES))
11
12all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES)
13
5define RUN_TESTS 14define RUN_TESTS
6 @for TEST in $(TEST_PROGS); do \ 15 @for TEST in $(TEST_GEN_PROGS) $(TEST_PROGS); do \
7 (./$$TEST && echo "selftests: $$TEST [PASS]") || echo "selftests: $$TEST [FAIL]"; \ 16 BASENAME_TEST=`basename $$TEST`; \
17 cd `dirname $$TEST`; (./$$BASENAME_TEST && echo "selftests: $$BASENAME_TEST [PASS]") || echo "selftests: $$BASENAME_TEST [FAIL]"; cd -;\
8 done; 18 done;
9endef 19endef
10 20
@@ -14,8 +24,13 @@ run_tests: all
14define INSTALL_RULE 24define INSTALL_RULE
15 @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then \ 25 @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then \
16 mkdir -p ${INSTALL_PATH}; \ 26 mkdir -p ${INSTALL_PATH}; \
17 echo "rsync -a $(TEST_DIRS) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/"; \ 27 echo "rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/"; \
18 rsync -a $(TEST_DIRS) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/; \ 28 rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/; \
29 fi
30 @if [ "X$(TEST_GEN_PROGS)$(TEST_GEN_PROGS_EXTENDED)$(TEST_GEN_FILES)" != "X" ]; then \
31 mkdir -p ${INSTALL_PATH}; \
32 echo "rsync -a $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/"; \
33 rsync -a $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/; \
19 fi 34 fi
20endef 35endef
21 36
@@ -27,12 +42,25 @@ else
27endif 42endif
28 43
29define EMIT_TESTS 44define EMIT_TESTS
30 @for TEST in $(TEST_PROGS); do \ 45 @for TEST in $(TEST_GEN_PROGS) $(TEST_PROGS); do \
31 echo "(./$$TEST && echo \"selftests: $$TEST [PASS]\") || echo \"selftests: $$TEST [FAIL]\""; \ 46 BASENAME_TEST=`basename $$TEST`; \
47 echo "(./$$BASENAME_TEST && echo \"selftests: $$BASENAME_TEST [PASS]\") || echo \"selftests: $$BASENAME_TEST [FAIL]\""; \
32 done; 48 done;
33endef 49endef
34 50
35emit_tests: 51emit_tests:
36 $(EMIT_TESTS) 52 $(EMIT_TESTS)
37 53
54clean:
55 $(RM) -r $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(EXTRA_CLEAN)
56
57$(OUTPUT)/%:%.c
58 $(LINK.c) $^ $(LDLIBS) -o $@
59
60$(OUTPUT)/%.o:%.S
61 $(COMPILE.S) $^ -o $@
62
63$(OUTPUT)/%:%.S
64 $(LINK.S) $^ $(LDLIBS) -o $@
65
38.PHONY: run_tests all clean install emit_tests 66.PHONY: run_tests all clean install emit_tests
diff --git a/tools/testing/selftests/locking/ww_mutex.sh b/tools/testing/selftests/locking/ww_mutex.sh
new file mode 100644
index 000000000000..6905da965f3b
--- /dev/null
+++ b/tools/testing/selftests/locking/ww_mutex.sh
@@ -0,0 +1,10 @@
1#!/bin/sh
2# Runs API tests for struct ww_mutex (Wait/Wound mutexes)
3
4if /sbin/modprobe -q test-ww_mutex; then
5 /sbin/modprobe -q -r test-ww_mutex
6 echo "locking/ww_mutex: ok"
7else
8 echo "locking/ww_mutex: [FAIL]"
9 exit 1
10fi
diff --git a/tools/testing/selftests/membarrier/Makefile b/tools/testing/selftests/membarrier/Makefile
index a1a97085847d..02845532b059 100644
--- a/tools/testing/selftests/membarrier/Makefile
+++ b/tools/testing/selftests/membarrier/Makefile
@@ -1,10 +1,6 @@
1CFLAGS += -g -I../../../../usr/include/ 1CFLAGS += -g -I../../../../usr/include/
2 2
3TEST_PROGS := membarrier_test 3TEST_GEN_PROGS := membarrier_test
4
5all: $(TEST_PROGS)
6 4
7include ../lib.mk 5include ../lib.mk
8 6
9clean:
10 $(RM) $(TEST_PROGS)
diff --git a/tools/testing/selftests/memfd/Makefile b/tools/testing/selftests/memfd/Makefile
index fd396ac811b6..79891d033de1 100644
--- a/tools/testing/selftests/memfd/Makefile
+++ b/tools/testing/selftests/memfd/Makefile
@@ -1,22 +1,13 @@
1CC = $(CROSS_COMPILE)gcc
2CFLAGS += -D_FILE_OFFSET_BITS=64 1CFLAGS += -D_FILE_OFFSET_BITS=64
3CFLAGS += -I../../../../include/uapi/ 2CFLAGS += -I../../../../include/uapi/
4CFLAGS += -I../../../../include/ 3CFLAGS += -I../../../../include/
5CFLAGS += -I../../../../usr/include/ 4CFLAGS += -I../../../../usr/include/
6 5
7TEST_PROGS := memfd_test 6TEST_PROGS := run_fuse_test.sh
8 7TEST_GEN_FILES := memfd_test fuse_mnt fuse_test
9all: $(TEST_PROGS)
10
11include ../lib.mk
12
13build_fuse: fuse_mnt fuse_test
14 8
15fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags) 9fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags)
16fuse_mnt: LDFLAGS += $(shell pkg-config fuse --libs) 10fuse_mnt: LDFLAGS += $(shell pkg-config fuse --libs)
17 11
18run_fuse: build_fuse 12include ../lib.mk
19 @./run_fuse_test.sh || echo "fuse_test: [FAIL]"
20 13
21clean:
22 $(RM) memfd_test fuse_test
diff --git a/tools/testing/selftests/mount/Makefile b/tools/testing/selftests/mount/Makefile
index 5e35c9c50b72..9093d7ffe87f 100644
--- a/tools/testing/selftests/mount/Makefile
+++ b/tools/testing/selftests/mount/Makefile
@@ -1,14 +1,11 @@
1# Makefile for mount selftests. 1# Makefile for mount selftests.
2CFLAGS = -Wall \ 2CFLAGS = -Wall \
3 -O2 3 -O2
4all: unprivileged-remount-test
5 4
6unprivileged-remount-test: unprivileged-remount-test.c 5TEST_GEN_PROGS := unprivileged-remount-test
7 $(CC) $(CFLAGS) unprivileged-remount-test.c -o unprivileged-remount-test
8 6
9include ../lib.mk 7include ../lib.mk
10 8
11TEST_PROGS := unprivileged-remount-test
12override RUN_TESTS := if [ -f /proc/self/uid_map ] ; \ 9override RUN_TESTS := if [ -f /proc/self/uid_map ] ; \
13 then \ 10 then \
14 ./unprivileged-remount-test ; \ 11 ./unprivileged-remount-test ; \
@@ -17,5 +14,3 @@ override RUN_TESTS := if [ -f /proc/self/uid_map ] ; \
17 fi 14 fi
18override EMIT_TESTS := echo "$(RUN_TESTS)" 15override EMIT_TESTS := echo "$(RUN_TESTS)"
19 16
20clean:
21 rm -f unprivileged-remount-test
diff --git a/tools/testing/selftests/mqueue/Makefile b/tools/testing/selftests/mqueue/Makefile
index eebac29acbd9..79a664aeb8d7 100644
--- a/tools/testing/selftests/mqueue/Makefile
+++ b/tools/testing/selftests/mqueue/Makefile
@@ -1,8 +1,6 @@
1CFLAGS += -O2 1CFLAGS += -O2
2LDLIBS = -lrt -lpthread -lpopt 2LDLIBS = -lrt -lpthread -lpopt
3TEST_PROGS := mq_open_tests mq_perf_tests 3TEST_GEN_PROGS := mq_open_tests mq_perf_tests
4
5all: $(TEST_PROGS)
6 4
7include ../lib.mk 5include ../lib.mk
8 6
@@ -16,5 +14,3 @@ override define EMIT_TESTS
16 echo "./mq_perf_tests || echo \"selftests: mq_perf_tests [FAIL]\"" 14 echo "./mq_perf_tests || echo \"selftests: mq_perf_tests [FAIL]\""
17endef 15endef
18 16
19clean:
20 rm -f mq_open_tests mq_perf_tests
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index e24e4c82542e..fbfe5d0d5c2e 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -3,20 +3,13 @@
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
6NET_PROGS = socket
7NET_PROGS += psock_fanout psock_tpacket
8NET_PROGS += reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
9NET_PROGS += reuseport_dualstack
10
11all: $(NET_PROGS)
12reuseport_bpf_numa: LDFLAGS += -lnuma 6reuseport_bpf_numa: LDFLAGS += -lnuma
13%: %.c
14 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
15 7
16TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh 8TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh
17TEST_FILES := $(NET_PROGS) 9TEST_GEN_FILES = socket
10TEST_GEN_FILES += psock_fanout psock_tpacket
11TEST_GEN_FILES += reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
12TEST_GEN_FILES += reuseport_dualstack
18 13
19include ../lib.mk 14include ../lib.mk
20 15
21clean:
22 $(RM) $(NET_PROGS)
diff --git a/tools/testing/selftests/net/psock_lib.h b/tools/testing/selftests/net/psock_lib.h
index 24bc7ec1be7d..a77da88bf946 100644
--- a/tools/testing/selftests/net/psock_lib.h
+++ b/tools/testing/selftests/net/psock_lib.h
@@ -40,14 +40,39 @@
40 40
41static __maybe_unused void sock_setfilter(int fd, int lvl, int optnum) 41static __maybe_unused void sock_setfilter(int fd, int lvl, int optnum)
42{ 42{
43 /* the filter below checks for all of the following conditions that
44 * are based on the contents of create_payload()
45 * ether type 0x800 and
46 * ip proto udp and
47 * skb->len == DATA_LEN and
48 * udp[38] == 'a' or udp[38] == 'b'
49 * It can be generated from the following bpf_asm input:
50 * ldh [12]
51 * jne #0x800, drop ; ETH_P_IP
52 * ldb [23]
53 * jneq #17, drop ; IPPROTO_UDP
54 * ld len ; ld skb->len
55 * jlt #100, drop ; DATA_LEN
56 * ldb [80]
57 * jeq #97, pass ; DATA_CHAR
58 * jne #98, drop ; DATA_CHAR_1
59 * pass:
60 * ret #-1
61 * drop:
62 * ret #0
63 */
43 struct sock_filter bpf_filter[] = { 64 struct sock_filter bpf_filter[] = {
44 { 0x80, 0, 0, 0x00000000 }, /* LD pktlen */ 65 { 0x28, 0, 0, 0x0000000c },
45 { 0x35, 0, 4, DATA_LEN }, /* JGE DATA_LEN [f goto nomatch]*/ 66 { 0x15, 0, 8, 0x00000800 },
46 { 0x30, 0, 0, 0x00000050 }, /* LD ip[80] */ 67 { 0x30, 0, 0, 0x00000017 },
47 { 0x15, 1, 0, DATA_CHAR }, /* JEQ DATA_CHAR [t goto match]*/ 68 { 0x15, 0, 6, 0x00000011 },
48 { 0x15, 0, 1, DATA_CHAR_1}, /* JEQ DATA_CHAR_1 [t goto match]*/ 69 { 0x80, 0, 0, 0000000000 },
49 { 0x06, 0, 0, 0x00000060 }, /* RET match */ 70 { 0x35, 0, 4, 0x00000064 },
50 { 0x06, 0, 0, 0x00000000 }, /* RET no match */ 71 { 0x30, 0, 0, 0x00000050 },
72 { 0x15, 1, 0, 0x00000061 },
73 { 0x15, 0, 1, 0x00000062 },
74 { 0x06, 0, 0, 0xffffffff },
75 { 0x06, 0, 0, 0000000000 },
51 }; 76 };
52 struct sock_fprog bpf_prog; 77 struct sock_fprog bpf_prog;
53 78
diff --git a/tools/testing/selftests/net/psock_tpacket.c b/tools/testing/selftests/net/psock_tpacket.c
index 24adf709bd9d..7f6cd9fdacf3 100644
--- a/tools/testing/selftests/net/psock_tpacket.c
+++ b/tools/testing/selftests/net/psock_tpacket.c
@@ -110,7 +110,7 @@ static unsigned int total_packets, total_bytes;
110 110
111static int pfsocket(int ver) 111static int pfsocket(int ver)
112{ 112{
113 int ret, sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 113 int ret, sock = socket(PF_PACKET, SOCK_RAW, 0);
114 if (sock == -1) { 114 if (sock == -1) {
115 perror("socket"); 115 perror("socket");
116 exit(1); 116 exit(1);
@@ -239,7 +239,6 @@ static void walk_v1_v2_rx(int sock, struct ring *ring)
239 bug_on(ring->type != PACKET_RX_RING); 239 bug_on(ring->type != PACKET_RX_RING);
240 240
241 pair_udp_open(udp_sock, PORT_BASE); 241 pair_udp_open(udp_sock, PORT_BASE);
242 pair_udp_setfilter(sock);
243 242
244 memset(&pfd, 0, sizeof(pfd)); 243 memset(&pfd, 0, sizeof(pfd));
245 pfd.fd = sock; 244 pfd.fd = sock;
@@ -311,20 +310,33 @@ static inline void __v2_tx_user_ready(struct tpacket2_hdr *hdr)
311 __sync_synchronize(); 310 __sync_synchronize();
312} 311}
313 312
314static inline int __v1_v2_tx_kernel_ready(void *base, int version) 313static inline int __v3_tx_kernel_ready(struct tpacket3_hdr *hdr)
314{
315 return !(hdr->tp_status & (TP_STATUS_SEND_REQUEST | TP_STATUS_SENDING));
316}
317
318static inline void __v3_tx_user_ready(struct tpacket3_hdr *hdr)
319{
320 hdr->tp_status = TP_STATUS_SEND_REQUEST;
321 __sync_synchronize();
322}
323
324static inline int __tx_kernel_ready(void *base, int version)
315{ 325{
316 switch (version) { 326 switch (version) {
317 case TPACKET_V1: 327 case TPACKET_V1:
318 return __v1_tx_kernel_ready(base); 328 return __v1_tx_kernel_ready(base);
319 case TPACKET_V2: 329 case TPACKET_V2:
320 return __v2_tx_kernel_ready(base); 330 return __v2_tx_kernel_ready(base);
331 case TPACKET_V3:
332 return __v3_tx_kernel_ready(base);
321 default: 333 default:
322 bug_on(1); 334 bug_on(1);
323 return 0; 335 return 0;
324 } 336 }
325} 337}
326 338
327static inline void __v1_v2_tx_user_ready(void *base, int version) 339static inline void __tx_user_ready(void *base, int version)
328{ 340{
329 switch (version) { 341 switch (version) {
330 case TPACKET_V1: 342 case TPACKET_V1:
@@ -333,6 +345,9 @@ static inline void __v1_v2_tx_user_ready(void *base, int version)
333 case TPACKET_V2: 345 case TPACKET_V2:
334 __v2_tx_user_ready(base); 346 __v2_tx_user_ready(base);
335 break; 347 break;
348 case TPACKET_V3:
349 __v3_tx_user_ready(base);
350 break;
336 } 351 }
337} 352}
338 353
@@ -348,7 +363,22 @@ static void __v1_v2_set_packet_loss_discard(int sock)
348 } 363 }
349} 364}
350 365
351static void walk_v1_v2_tx(int sock, struct ring *ring) 366static inline void *get_next_frame(struct ring *ring, int n)
367{
368 uint8_t *f0 = ring->rd[0].iov_base;
369
370 switch (ring->version) {
371 case TPACKET_V1:
372 case TPACKET_V2:
373 return ring->rd[n].iov_base;
374 case TPACKET_V3:
375 return f0 + (n * ring->req3.tp_frame_size);
376 default:
377 bug_on(1);
378 }
379}
380
381static void walk_tx(int sock, struct ring *ring)
352{ 382{
353 struct pollfd pfd; 383 struct pollfd pfd;
354 int rcv_sock, ret; 384 int rcv_sock, ret;
@@ -360,9 +390,19 @@ static void walk_v1_v2_tx(int sock, struct ring *ring)
360 .sll_family = PF_PACKET, 390 .sll_family = PF_PACKET,
361 .sll_halen = ETH_ALEN, 391 .sll_halen = ETH_ALEN,
362 }; 392 };
393 int nframes;
394
395 /* TPACKET_V{1,2} sets up the ring->rd* related variables based
396 * on frames (e.g., rd_num is tp_frame_nr) whereas V3 sets these
397 * up based on blocks (e.g, rd_num is tp_block_nr)
398 */
399 if (ring->version <= TPACKET_V2)
400 nframes = ring->rd_num;
401 else
402 nframes = ring->req3.tp_frame_nr;
363 403
364 bug_on(ring->type != PACKET_TX_RING); 404 bug_on(ring->type != PACKET_TX_RING);
365 bug_on(ring->rd_num < NUM_PACKETS); 405 bug_on(nframes < NUM_PACKETS);
366 406
367 rcv_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 407 rcv_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
368 if (rcv_sock == -1) { 408 if (rcv_sock == -1) {
@@ -388,10 +428,11 @@ static void walk_v1_v2_tx(int sock, struct ring *ring)
388 create_payload(packet, &packet_len); 428 create_payload(packet, &packet_len);
389 429
390 while (total_packets > 0) { 430 while (total_packets > 0) {
391 while (__v1_v2_tx_kernel_ready(ring->rd[frame_num].iov_base, 431 void *next = get_next_frame(ring, frame_num);
392 ring->version) && 432
433 while (__tx_kernel_ready(next, ring->version) &&
393 total_packets > 0) { 434 total_packets > 0) {
394 ppd.raw = ring->rd[frame_num].iov_base; 435 ppd.raw = next;
395 436
396 switch (ring->version) { 437 switch (ring->version) {
397 case TPACKET_V1: 438 case TPACKET_V1:
@@ -413,14 +454,27 @@ static void walk_v1_v2_tx(int sock, struct ring *ring)
413 packet_len); 454 packet_len);
414 total_bytes += ppd.v2->tp_h.tp_snaplen; 455 total_bytes += ppd.v2->tp_h.tp_snaplen;
415 break; 456 break;
457 case TPACKET_V3: {
458 struct tpacket3_hdr *tx = next;
459
460 tx->tp_snaplen = packet_len;
461 tx->tp_len = packet_len;
462 tx->tp_next_offset = 0;
463
464 memcpy((uint8_t *)tx + TPACKET3_HDRLEN -
465 sizeof(struct sockaddr_ll), packet,
466 packet_len);
467 total_bytes += tx->tp_snaplen;
468 break;
469 }
416 } 470 }
417 471
418 status_bar_update(); 472 status_bar_update();
419 total_packets--; 473 total_packets--;
420 474
421 __v1_v2_tx_user_ready(ppd.raw, ring->version); 475 __tx_user_ready(next, ring->version);
422 476
423 frame_num = (frame_num + 1) % ring->rd_num; 477 frame_num = (frame_num + 1) % nframes;
424 } 478 }
425 479
426 poll(&pfd, 1, 1); 480 poll(&pfd, 1, 1);
@@ -460,7 +514,7 @@ static void walk_v1_v2(int sock, struct ring *ring)
460 if (ring->type == PACKET_RX_RING) 514 if (ring->type == PACKET_RX_RING)
461 walk_v1_v2_rx(sock, ring); 515 walk_v1_v2_rx(sock, ring);
462 else 516 else
463 walk_v1_v2_tx(sock, ring); 517 walk_tx(sock, ring);
464} 518}
465 519
466static uint64_t __v3_prev_block_seq_num = 0; 520static uint64_t __v3_prev_block_seq_num = 0;
@@ -546,7 +600,6 @@ static void walk_v3_rx(int sock, struct ring *ring)
546 bug_on(ring->type != PACKET_RX_RING); 600 bug_on(ring->type != PACKET_RX_RING);
547 601
548 pair_udp_open(udp_sock, PORT_BASE); 602 pair_udp_open(udp_sock, PORT_BASE);
549 pair_udp_setfilter(sock);
550 603
551 memset(&pfd, 0, sizeof(pfd)); 604 memset(&pfd, 0, sizeof(pfd));
552 pfd.fd = sock; 605 pfd.fd = sock;
@@ -583,7 +636,7 @@ static void walk_v3(int sock, struct ring *ring)
583 if (ring->type == PACKET_RX_RING) 636 if (ring->type == PACKET_RX_RING)
584 walk_v3_rx(sock, ring); 637 walk_v3_rx(sock, ring);
585 else 638 else
586 bug_on(1); 639 walk_tx(sock, ring);
587} 640}
588 641
589static void __v1_v2_fill(struct ring *ring, unsigned int blocks) 642static void __v1_v2_fill(struct ring *ring, unsigned int blocks)
@@ -602,12 +655,13 @@ static void __v1_v2_fill(struct ring *ring, unsigned int blocks)
602 ring->flen = ring->req.tp_frame_size; 655 ring->flen = ring->req.tp_frame_size;
603} 656}
604 657
605static void __v3_fill(struct ring *ring, unsigned int blocks) 658static void __v3_fill(struct ring *ring, unsigned int blocks, int type)
606{ 659{
607 ring->req3.tp_retire_blk_tov = 64; 660 if (type == PACKET_RX_RING) {
608 ring->req3.tp_sizeof_priv = 0; 661 ring->req3.tp_retire_blk_tov = 64;
609 ring->req3.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH; 662 ring->req3.tp_sizeof_priv = 0;
610 663 ring->req3.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH;
664 }
611 ring->req3.tp_block_size = getpagesize() << 2; 665 ring->req3.tp_block_size = getpagesize() << 2;
612 ring->req3.tp_frame_size = TPACKET_ALIGNMENT << 7; 666 ring->req3.tp_frame_size = TPACKET_ALIGNMENT << 7;
613 ring->req3.tp_block_nr = blocks; 667 ring->req3.tp_block_nr = blocks;
@@ -641,7 +695,7 @@ static void setup_ring(int sock, struct ring *ring, int version, int type)
641 break; 695 break;
642 696
643 case TPACKET_V3: 697 case TPACKET_V3:
644 __v3_fill(ring, blocks); 698 __v3_fill(ring, blocks, type);
645 ret = setsockopt(sock, SOL_PACKET, type, &ring->req3, 699 ret = setsockopt(sock, SOL_PACKET, type, &ring->req3,
646 sizeof(ring->req3)); 700 sizeof(ring->req3));
647 break; 701 break;
@@ -685,6 +739,8 @@ static void bind_ring(int sock, struct ring *ring)
685{ 739{
686 int ret; 740 int ret;
687 741
742 pair_udp_setfilter(sock);
743
688 ring->ll.sll_family = PF_PACKET; 744 ring->ll.sll_family = PF_PACKET;
689 ring->ll.sll_protocol = htons(ETH_P_ALL); 745 ring->ll.sll_protocol = htons(ETH_P_ALL);
690 ring->ll.sll_ifindex = if_nametoindex("lo"); 746 ring->ll.sll_ifindex = if_nametoindex("lo");
@@ -796,6 +852,7 @@ int main(void)
796 ret |= test_tpacket(TPACKET_V2, PACKET_TX_RING); 852 ret |= test_tpacket(TPACKET_V2, PACKET_TX_RING);
797 853
798 ret |= test_tpacket(TPACKET_V3, PACKET_RX_RING); 854 ret |= test_tpacket(TPACKET_V3, PACKET_RX_RING);
855 ret |= test_tpacket(TPACKET_V3, PACKET_TX_RING);
799 856
800 if (ret) 857 if (ret)
801 return 1; 858 return 1;
diff --git a/tools/testing/selftests/nsfs/Makefile b/tools/testing/selftests/nsfs/Makefile
index 2306054a901a..9ff7c7f80625 100644
--- a/tools/testing/selftests/nsfs/Makefile
+++ b/tools/testing/selftests/nsfs/Makefile
@@ -1,12 +1,5 @@
1TEST_PROGS := owner pidns 1TEST_GEN_PROGS := owner pidns
2 2
3CFLAGS := -Wall -Werror 3CFLAGS := -Wall -Werror
4 4
5all: owner pidns
6owner: owner.c
7pidns: pidns.c
8
9clean:
10 $(RM) owner pidns
11
12include ../lib.mk 5include ../lib.mk
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index c2c4211ba58b..1c5d0575802e 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -34,31 +34,35 @@ endif
34all: $(SUB_DIRS) 34all: $(SUB_DIRS)
35 35
36$(SUB_DIRS): 36$(SUB_DIRS):
37 $(MAKE) -k -C $@ all 37 BUILD_TARGET=$$OUTPUT/$@; mkdir -p $$BUILD_TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -k -C $@ all
38 38
39include ../lib.mk 39include ../lib.mk
40 40
41override define RUN_TESTS 41override define RUN_TESTS
42 @for TARGET in $(SUB_DIRS); do \ 42 @for TARGET in $(SUB_DIRS); do \
43 $(MAKE) -C $$TARGET run_tests; \ 43 BUILD_TARGET=$$OUTPUT/$$TARGET; \
44 $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests;\
44 done; 45 done;
45endef 46endef
46 47
47override define INSTALL_RULE 48override define INSTALL_RULE
48 @for TARGET in $(SUB_DIRS); do \ 49 @for TARGET in $(SUB_DIRS); do \
49 $(MAKE) -C $$TARGET install; \ 50 BUILD_TARGET=$$OUTPUT/$$TARGET; \
51 $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install;\
50 done; 52 done;
51endef 53endef
52 54
53override define EMIT_TESTS 55override define EMIT_TESTS
54 @for TARGET in $(SUB_DIRS); do \ 56 @for TARGET in $(SUB_DIRS); do \
55 $(MAKE) -s -C $$TARGET emit_tests; \ 57 BUILD_TARGET=$$OUTPUT/$$TARGET; \
58 $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests;\
56 done; 59 done;
57endef 60endef
58 61
59clean: 62clean:
60 @for TARGET in $(SUB_DIRS); do \ 63 @for TARGET in $(SUB_DIRS); do \
61 $(MAKE) -C $$TARGET clean; \ 64 BUILD_TARGET=$$OUTPUT/$$TARGET; \
65 $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET clean; \
62 done; 66 done;
63 rm -f tags 67 rm -f tags
64 68
diff --git a/tools/testing/selftests/powerpc/alignment/Makefile b/tools/testing/selftests/powerpc/alignment/Makefile
index ad6a4e49da91..16b22004e75f 100644
--- a/tools/testing/selftests/powerpc/alignment/Makefile
+++ b/tools/testing/selftests/powerpc/alignment/Makefile
@@ -1,10 +1,5 @@
1TEST_PROGS := copy_unaligned copy_first_unaligned paste_unaligned paste_last_unaligned 1TEST_GEN_PROGS := copy_unaligned copy_first_unaligned paste_unaligned paste_last_unaligned
2
3all: $(TEST_PROGS)
4
5$(TEST_PROGS): ../harness.c ../utils.c copy_paste_unaligned_common.c
6 2
7include ../../lib.mk 3include ../../lib.mk
8 4
9clean: 5$(TEST_GEN_PROGS): ../harness.c ../utils.c copy_paste_unaligned_common.c
10 rm -f $(TEST_PROGS)
diff --git a/tools/testing/selftests/powerpc/benchmarks/Makefile b/tools/testing/selftests/powerpc/benchmarks/Makefile
index 545077f98f72..fb96a89bd953 100644
--- a/tools/testing/selftests/powerpc/benchmarks/Makefile
+++ b/tools/testing/selftests/powerpc/benchmarks/Makefile
@@ -1,16 +1,11 @@
1TEST_PROGS := gettimeofday context_switch mmap_bench futex_bench null_syscall 1TEST_GEN_PROGS := gettimeofday context_switch mmap_bench futex_bench null_syscall
2 2
3CFLAGS += -O2 3CFLAGS += -O2
4 4
5all: $(TEST_PROGS)
6
7$(TEST_PROGS): ../harness.c
8
9context_switch: ../utils.c
10context_switch: CFLAGS += -maltivec -mvsx -mabi=altivec
11context_switch: LDLIBS += -lpthread
12
13include ../../lib.mk 5include ../../lib.mk
14 6
15clean: 7$(TEST_GEN_PROGS): ../harness.c
16 rm -f $(TEST_PROGS) *.o 8
9$(OUTPUT)/context_switch: ../utils.c
10$(OUTPUT)/context_switch: CFLAGS += -maltivec -mvsx -mabi=altivec
11$(OUTPUT)/context_switch: LDLIBS += -lpthread
diff --git a/tools/testing/selftests/powerpc/context_switch/Makefile b/tools/testing/selftests/powerpc/context_switch/Makefile
index e164d1466466..e9351bb4285d 100644
--- a/tools/testing/selftests/powerpc/context_switch/Makefile
+++ b/tools/testing/selftests/powerpc/context_switch/Makefile
@@ -1,10 +1,5 @@
1TEST_PROGS := cp_abort 1TEST_GEN_PROGS := cp_abort
2
3all: $(TEST_PROGS)
4
5$(TEST_PROGS): ../harness.c ../utils.c
6 2
7include ../../lib.mk 3include ../../lib.mk
8 4
9clean: 5$(TEST_GEN_PROGS): ../harness.c ../utils.c
10 rm -f $(TEST_PROGS)
diff --git a/tools/testing/selftests/powerpc/copyloops/Makefile b/tools/testing/selftests/powerpc/copyloops/Makefile
index 384843ea0d40..681ab19d0a84 100644
--- a/tools/testing/selftests/powerpc/copyloops/Makefile
+++ b/tools/testing/selftests/powerpc/copyloops/Makefile
@@ -7,19 +7,14 @@ CFLAGS += -maltivec
7# Use our CFLAGS for the implicit .S rule 7# Use our CFLAGS for the implicit .S rule
8ASFLAGS = $(CFLAGS) 8ASFLAGS = $(CFLAGS)
9 9
10TEST_PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7 10TEST_GEN_PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7
11EXTRA_SOURCES := validate.c ../harness.c 11EXTRA_SOURCES := validate.c ../harness.c
12 12
13all: $(TEST_PROGS)
14
15copyuser_64: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_base
16copyuser_power7: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_power7
17memcpy_64: CPPFLAGS += -D COPY_LOOP=test_memcpy
18memcpy_power7: CPPFLAGS += -D COPY_LOOP=test_memcpy_power7
19
20$(TEST_PROGS): $(EXTRA_SOURCES)
21
22include ../../lib.mk 13include ../../lib.mk
23 14
24clean: 15$(OUTPUT)/copyuser_64: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_base
25 rm -f $(TEST_PROGS) *.o 16$(OUTPUT)/copyuser_power7: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_power7
17$(OUTPUT)/memcpy_64: CPPFLAGS += -D COPY_LOOP=test_memcpy
18$(OUTPUT)/memcpy_power7: CPPFLAGS += -D COPY_LOOP=test_memcpy_power7
19
20$(TEST_GEN_PROGS): $(EXTRA_SOURCES)
diff --git a/tools/testing/selftests/powerpc/dscr/Makefile b/tools/testing/selftests/powerpc/dscr/Makefile
index 49327ee84e3a..c5639deb8887 100644
--- a/tools/testing/selftests/powerpc/dscr/Makefile
+++ b/tools/testing/selftests/powerpc/dscr/Makefile
@@ -1,14 +1,9 @@
1TEST_PROGS := dscr_default_test dscr_explicit_test dscr_user_test \ 1TEST_GEN_PROGS := dscr_default_test dscr_explicit_test dscr_user_test \
2 dscr_inherit_test dscr_inherit_exec_test dscr_sysfs_test \ 2 dscr_inherit_test dscr_inherit_exec_test dscr_sysfs_test \
3 dscr_sysfs_thread_test 3 dscr_sysfs_thread_test
4 4
5dscr_default_test: LDLIBS += -lpthread
6
7all: $(TEST_PROGS)
8
9$(TEST_PROGS): ../harness.c
10
11include ../../lib.mk 5include ../../lib.mk
12 6
13clean: 7$(OUTPUT)/dscr_default_test: LDLIBS += -lpthread
14 rm -f $(TEST_PROGS) *.o 8
9$(TEST_GEN_PROGS): ../harness.c
diff --git a/tools/testing/selftests/powerpc/math/Makefile b/tools/testing/selftests/powerpc/math/Makefile
index a505b66d408a..fa8bae920c91 100644
--- a/tools/testing/selftests/powerpc/math/Makefile
+++ b/tools/testing/selftests/powerpc/math/Makefile
@@ -1,22 +1,17 @@
1TEST_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal vsx_preempt 1TEST_GEN_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal vsx_preempt
2 2
3all: $(TEST_PROGS) 3include ../../lib.mk
4
5$(TEST_PROGS): ../harness.c
6$(TEST_PROGS): CFLAGS += -O2 -g -pthread -m64 -maltivec
7
8fpu_syscall: fpu_asm.S
9fpu_preempt: fpu_asm.S
10fpu_signal: fpu_asm.S
11 4
12vmx_syscall: vmx_asm.S 5$(TEST_GEN_PROGS): ../harness.c
13vmx_preempt: vmx_asm.S 6$(TEST_GEN_PROGS): CFLAGS += -O2 -g -pthread -m64 -maltivec
14vmx_signal: vmx_asm.S
15 7
16vsx_preempt: CFLAGS += -mvsx 8$(OUTPUT)/fpu_syscall: fpu_asm.S
17vsx_preempt: vsx_asm.S 9$(OUTPUT)/fpu_preempt: fpu_asm.S
10$(OUTPUT)/fpu_signal: fpu_asm.S
18 11
19include ../../lib.mk 12$(OUTPUT)/vmx_syscall: vmx_asm.S
13$(OUTPUT)/vmx_preempt: vmx_asm.S
14$(OUTPUT)/vmx_signal: vmx_asm.S
20 15
21clean: 16$(OUTPUT)/vsx_preempt: CFLAGS += -mvsx
22 rm -f $(TEST_PROGS) *.o 17$(OUTPUT)/vsx_preempt: vsx_asm.S
diff --git a/tools/testing/selftests/powerpc/mm/Makefile b/tools/testing/selftests/powerpc/mm/Makefile
index 3bdb96eae558..1cffe54dccfb 100644
--- a/tools/testing/selftests/powerpc/mm/Makefile
+++ b/tools/testing/selftests/powerpc/mm/Makefile
@@ -1,19 +1,15 @@
1noarg: 1noarg:
2 $(MAKE) -C ../ 2 $(MAKE) -C ../
3 3
4TEST_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao 4TEST_GEN_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao
5TEST_FILES := tempfile 5TEST_GEN_FILES := tempfile
6 6
7all: $(TEST_PROGS) $(TEST_FILES) 7include ../../lib.mk
8
9$(TEST_PROGS): ../harness.c
10 8
11prot_sao: ../utils.c 9$(TEST_GEN_PROGS): ../harness.c
12 10
13include ../../lib.mk 11$(OUTPUT)/prot_sao: ../utils.c
14 12
15tempfile: 13$(OUTPUT)/tempfile:
16 dd if=/dev/zero of=tempfile bs=64k count=1 14 dd if=/dev/zero of=$@ bs=64k count=1
17 15
18clean:
19 rm -f $(TEST_PROGS) tempfile
diff --git a/tools/testing/selftests/powerpc/pmu/Makefile b/tools/testing/selftests/powerpc/pmu/Makefile
index ac41a7177f2e..e4e55d1d3e0f 100644
--- a/tools/testing/selftests/powerpc/pmu/Makefile
+++ b/tools/testing/selftests/powerpc/pmu/Makefile
@@ -1,44 +1,44 @@
1noarg: 1noarg:
2 $(MAKE) -C ../ 2 $(MAKE) -C ../
3 3
4TEST_PROGS := count_instructions l3_bank_test per_event_excludes 4TEST_GEN_PROGS := count_instructions l3_bank_test per_event_excludes
5EXTRA_SOURCES := ../harness.c event.c lib.c ../utils.c 5EXTRA_SOURCES := ../harness.c event.c lib.c ../utils.c
6 6
7all: $(TEST_PROGS) ebb 7include ../../lib.mk
8
9all: $(TEST_GEN_PROGS) ebb
8 10
9$(TEST_PROGS): $(EXTRA_SOURCES) 11$(TEST_GEN_PROGS): $(EXTRA_SOURCES)
10 12
11# loop.S can only be built 64-bit 13# loop.S can only be built 64-bit
12count_instructions: loop.S count_instructions.c $(EXTRA_SOURCES) 14$(OUTPUT)/count_instructions: loop.S count_instructions.c $(EXTRA_SOURCES)
13 $(CC) $(CFLAGS) -m64 -o $@ $^ 15 $(CC) $(CFLAGS) -m64 -o $@ $^
14 16
15per_event_excludes: ../utils.c 17$(OUTPUT)/per_event_excludes: ../utils.c
16
17include ../../lib.mk
18 18
19DEFAULT_RUN_TESTS := $(RUN_TESTS) 19DEFAULT_RUN_TESTS := $(RUN_TESTS)
20override define RUN_TESTS 20override define RUN_TESTS
21 $(DEFAULT_RUN_TESTS) 21 $(DEFAULT_RUN_TESTS)
22 $(MAKE) -C ebb run_tests 22 TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests
23endef 23endef
24 24
25DEFAULT_EMIT_TESTS := $(EMIT_TESTS) 25DEFAULT_EMIT_TESTS := $(EMIT_TESTS)
26override define EMIT_TESTS 26override define EMIT_TESTS
27 $(DEFAULT_EMIT_TESTS) 27 $(DEFAULT_EMIT_TESTS)
28 $(MAKE) -s -C ebb emit_tests 28 TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests
29endef 29endef
30 30
31DEFAULT_INSTALL_RULE := $(INSTALL_RULE) 31DEFAULT_INSTALL_RULE := $(INSTALL_RULE)
32override define INSTALL_RULE 32override define INSTALL_RULE
33 $(DEFAULT_INSTALL_RULE) 33 $(DEFAULT_INSTALL_RULE)
34 $(MAKE) -C ebb install 34 TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install
35endef 35endef
36 36
37clean: 37clean:
38 rm -f $(TEST_PROGS) loop.o 38 $(RM) $(TEST_GEN_PROGS) $(OUTPUT)/loop.o
39 $(MAKE) -C ebb clean 39 TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET clean
40 40
41ebb: 41ebb:
42 $(MAKE) -k -C $@ all 42 TARGET=$@; BUILD_TARGET=$$OUTPUT/$$TARGET; mkdir -p $$BUILD_TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -k -C $$TARGET all
43 43
44.PHONY: all run_tests clean ebb 44.PHONY: all run_tests clean ebb
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/Makefile b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
index 8d2279c4bb4b..6001fb0a377a 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/Makefile
+++ b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
@@ -4,7 +4,7 @@ noarg:
4# The EBB handler is 64-bit code and everything links against it 4# The EBB handler is 64-bit code and everything links against it
5CFLAGS += -m64 5CFLAGS += -m64
6 6
7TEST_PROGS := reg_access_test event_attributes_test cycles_test \ 7TEST_GEN_PROGS := reg_access_test event_attributes_test cycles_test \
8 cycles_with_freeze_test pmc56_overflow_test \ 8 cycles_with_freeze_test pmc56_overflow_test \
9 ebb_vs_cpu_event_test cpu_event_vs_ebb_test \ 9 ebb_vs_cpu_event_test cpu_event_vs_ebb_test \
10 cpu_event_pinned_vs_ebb_test task_event_vs_ebb_test \ 10 cpu_event_pinned_vs_ebb_test task_event_vs_ebb_test \
@@ -16,16 +16,11 @@ TEST_PROGS := reg_access_test event_attributes_test cycles_test \
16 lost_exception_test no_handler_test \ 16 lost_exception_test no_handler_test \
17 cycles_with_mmcr2_test 17 cycles_with_mmcr2_test
18 18
19all: $(TEST_PROGS) 19include ../../../lib.mk
20 20
21$(TEST_PROGS): ../../harness.c ../../utils.c ../event.c ../lib.c \ 21$(TEST_GEN_PROGS): ../../harness.c ../../utils.c ../event.c ../lib.c \
22 ebb.c ebb_handler.S trace.c busy_loop.S 22 ebb.c ebb_handler.S trace.c busy_loop.S
23 23
24instruction_count_test: ../loop.S 24$(OUTPUT)/instruction_count_test: ../loop.S
25
26lost_exception_test: ../lib.c
27
28include ../../../lib.mk
29 25
30clean: 26$(OUTPUT)/lost_exception_test: ../lib.c
31 rm -f $(TEST_PROGS)
diff --git a/tools/testing/selftests/powerpc/primitives/Makefile b/tools/testing/selftests/powerpc/primitives/Makefile
index b68c6221d3d1..175366db7be8 100644
--- a/tools/testing/selftests/powerpc/primitives/Makefile
+++ b/tools/testing/selftests/powerpc/primitives/Makefile
@@ -1,12 +1,7 @@
1CFLAGS += -I$(CURDIR) 1CFLAGS += -I$(CURDIR)
2 2
3TEST_PROGS := load_unaligned_zeropad 3TEST_GEN_PROGS := load_unaligned_zeropad
4
5all: $(TEST_PROGS)
6
7$(TEST_PROGS): ../harness.c
8 4
9include ../../lib.mk 5include ../../lib.mk
10 6
11clean: 7$(TEST_GEN_PROGS): ../harness.c
12 rm -f $(TEST_PROGS) *.o
diff --git a/tools/testing/selftests/powerpc/stringloops/Makefile b/tools/testing/selftests/powerpc/stringloops/Makefile
index 2a728f4d2873..557b9379f3bb 100644
--- a/tools/testing/selftests/powerpc/stringloops/Makefile
+++ b/tools/testing/selftests/powerpc/stringloops/Makefile
@@ -2,14 +2,9 @@
2CFLAGS += -m64 2CFLAGS += -m64
3CFLAGS += -I$(CURDIR) 3CFLAGS += -I$(CURDIR)
4 4
5TEST_PROGS := memcmp 5TEST_GEN_PROGS := memcmp
6EXTRA_SOURCES := memcmp_64.S ../harness.c 6EXTRA_SOURCES := memcmp_64.S ../harness.c
7 7
8all: $(TEST_PROGS)
9
10$(TEST_PROGS): $(EXTRA_SOURCES)
11
12include ../../lib.mk 8include ../../lib.mk
13 9
14clean: 10$(TEST_GEN_PROGS): $(EXTRA_SOURCES)
15 rm -f $(TEST_PROGS) *.o
diff --git a/tools/testing/selftests/powerpc/switch_endian/Makefile b/tools/testing/selftests/powerpc/switch_endian/Makefile
index e21d10674e54..b92c2a132c4f 100644
--- a/tools/testing/selftests/powerpc/switch_endian/Makefile
+++ b/tools/testing/selftests/powerpc/switch_endian/Makefile
@@ -1,18 +1,15 @@
1TEST_PROGS := switch_endian_test 1TEST_GEN_PROGS := switch_endian_test
2 2
3ASFLAGS += -O2 -Wall -g -nostdlib -m64 3ASFLAGS += -O2 -Wall -g -nostdlib -m64
4 4
5all: $(TEST_PROGS) 5EXTRA_CLEAN = $(OUTPUT)/*.o $(OUTPUT)/check-reversed.S
6 6
7switch_endian_test: check-reversed.S 7include ../../lib.mk
8
9$(OUTPUT)/switch_endian_test: $(OUTPUT)/check-reversed.S
8 10
9check-reversed.o: check.o 11$(OUTPUT)/check-reversed.o: $(OUTPUT)/check.o
10 $(CROSS_COMPILE)objcopy -j .text --reverse-bytes=4 -O binary $< $@ 12 $(CROSS_COMPILE)objcopy -j .text --reverse-bytes=4 -O binary $< $@
11 13
12check-reversed.S: check-reversed.o 14$(OUTPUT)/check-reversed.S: $(OUTPUT)/check-reversed.o
13 hexdump -v -e '/1 ".byte 0x%02X\n"' $< > $@ 15 hexdump -v -e '/1 ".byte 0x%02X\n"' $< > $@
14
15include ../../lib.mk
16
17clean:
18 rm -f $(TEST_PROGS) *.o check-reversed.S
diff --git a/tools/testing/selftests/powerpc/syscalls/Makefile b/tools/testing/selftests/powerpc/syscalls/Makefile
index b35c7945bec5..da22ca7c38c1 100644
--- a/tools/testing/selftests/powerpc/syscalls/Makefile
+++ b/tools/testing/selftests/powerpc/syscalls/Makefile
@@ -1,12 +1,7 @@
1TEST_PROGS := ipc_unmuxed 1TEST_GEN_PROGS := ipc_unmuxed
2 2
3CFLAGS += -I../../../../../usr/include 3CFLAGS += -I../../../../../usr/include
4 4
5all: $(TEST_PROGS)
6
7$(TEST_PROGS): ../harness.c
8
9include ../../lib.mk 5include ../../lib.mk
10 6
11clean: 7$(TEST_GEN_PROGS): ../harness.c
12 rm -f $(TEST_PROGS) *.o
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index c6c53c82fdd6..5576ee6a51f2 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,23 +1,19 @@
1SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu \ 1SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu \
2 tm-signal-context-chk-vmx tm-signal-context-chk-vsx 2 tm-signal-context-chk-vmx tm-signal-context-chk-vsx
3 3
4TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \ 4TEST_GEN_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \
5 tm-vmxcopy tm-fork tm-tar tm-tmspr $(SIGNAL_CONTEXT_CHK_TESTS) 5 tm-vmxcopy tm-fork tm-tar tm-tmspr $(SIGNAL_CONTEXT_CHK_TESTS)
6 6
7all: $(TEST_PROGS) 7include ../../lib.mk
8 8
9$(TEST_PROGS): ../harness.c ../utils.c 9$(TEST_GEN_PROGS): ../harness.c ../utils.c
10 10
11CFLAGS += -mhtm 11CFLAGS += -mhtm
12 12
13tm-syscall: tm-syscall-asm.S 13$(OUTPUT)/tm-syscall: tm-syscall-asm.S
14tm-syscall: CFLAGS += -I../../../../../usr/include 14$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include
15tm-tmspr: CFLAGS += -pthread 15$(OUTPUT)/tm-tmspr: CFLAGS += -pthread
16 16
17SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS))
17$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S 18$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
18$(SIGNAL_CONTEXT_CHK_TESTS): CFLAGS += -mhtm -m64 -mvsx 19$(SIGNAL_CONTEXT_CHK_TESTS): CFLAGS += -mhtm -m64 -mvsx
19
20include ../../lib.mk
21
22clean:
23 rm -f $(TEST_PROGS) *.o
diff --git a/tools/testing/selftests/powerpc/vphn/Makefile b/tools/testing/selftests/powerpc/vphn/Makefile
index a485f2e286ae..f8ced26748f8 100644
--- a/tools/testing/selftests/powerpc/vphn/Makefile
+++ b/tools/testing/selftests/powerpc/vphn/Makefile
@@ -1,12 +1,8 @@
1TEST_PROGS := test-vphn 1TEST_GEN_PROGS := test-vphn
2 2
3CFLAGS += -m64 3CFLAGS += -m64
4 4
5all: $(TEST_PROGS)
6
7$(TEST_PROGS): ../harness.c
8
9include ../../lib.mk 5include ../../lib.mk
10 6
11clean: 7$(TEST_GEN_PROGS): ../harness.c
12 rm -f $(TEST_PROGS) 8
diff --git a/tools/testing/selftests/pstore/Makefile b/tools/testing/selftests/pstore/Makefile
index bd7abe24ea08..c5f2440ba1f7 100644
--- a/tools/testing/selftests/pstore/Makefile
+++ b/tools/testing/selftests/pstore/Makefile
@@ -5,11 +5,9 @@ all:
5 5
6TEST_PROGS := pstore_tests pstore_post_reboot_tests 6TEST_PROGS := pstore_tests pstore_post_reboot_tests
7TEST_FILES := common_tests pstore_crash_test 7TEST_FILES := common_tests pstore_crash_test
8EXTRA_CLEAN := logs/* *uuid
8 9
9include ../lib.mk 10include ../lib.mk
10 11
11run_crash: 12run_crash:
12 @sh pstore_crash_test || { echo "pstore_crash_test: [FAIL]"; exit 1; } 13 @sh pstore_crash_test || { echo "pstore_crash_test: [FAIL]"; exit 1; }
13
14clean:
15 rm -rf logs/* *uuid
diff --git a/tools/testing/selftests/ptrace/Makefile b/tools/testing/selftests/ptrace/Makefile
index 453927fea90c..8a2bc5562179 100644
--- a/tools/testing/selftests/ptrace/Makefile
+++ b/tools/testing/selftests/ptrace/Makefile
@@ -1,11 +1,5 @@
1CFLAGS += -iquote../../../../include/uapi -Wall 1CFLAGS += -iquote../../../../include/uapi -Wall
2peeksiginfo: peeksiginfo.c
3 2
4all: peeksiginfo 3TEST_GEN_PROGS := peeksiginfo
5
6clean:
7 rm -f peeksiginfo
8
9TEST_PROGS := peeksiginfo
10 4
11include ../lib.mk 5include ../lib.mk
diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFLIST b/tools/testing/selftests/rcutorture/configs/lock/CFLIST
index b9611c523723..41bae5824339 100644
--- a/tools/testing/selftests/rcutorture/configs/lock/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/lock/CFLIST
@@ -4,3 +4,4 @@ LOCK03
4LOCK04 4LOCK04
5LOCK05 5LOCK05
6LOCK06 6LOCK06
7LOCK07
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK07 b/tools/testing/selftests/rcutorture/configs/lock/LOCK07
new file mode 100644
index 000000000000..1d1da1477fc3
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK07
@@ -0,0 +1,6 @@
1CONFIG_SMP=y
2CONFIG_NR_CPUS=4
3CONFIG_HOTPLUG_CPU=y
4CONFIG_PREEMPT_NONE=n
5CONFIG_PREEMPT_VOLUNTARY=n
6CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK07.boot b/tools/testing/selftests/rcutorture/configs/lock/LOCK07.boot
new file mode 100644
index 000000000000..97dadd1a9e45
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK07.boot
@@ -0,0 +1 @@
locktorture.torture_type=ww_mutex_lock
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFcommon b/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
index f824b4c9d9d9..d2d2a86139db 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
+++ b/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
@@ -1,5 +1,2 @@
1CONFIG_RCU_TORTURE_TEST=y 1CONFIG_RCU_TORTURE_TEST=y
2CONFIG_PRINTK_TIME=y 2CONFIG_PRINTK_TIME=y
3CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
4CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
5CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY01 b/tools/testing/selftests/rcutorture/configs/rcu/TINY01
index 0a63e073a00c..6db705e55487 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TINY01
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY01
@@ -7,6 +7,7 @@ CONFIG_HZ_PERIODIC=n
7CONFIG_NO_HZ_IDLE=y 7CONFIG_NO_HZ_IDLE=y
8CONFIG_NO_HZ_FULL=n 8CONFIG_NO_HZ_FULL=n
9CONFIG_RCU_TRACE=n 9CONFIG_RCU_TRACE=n
10#CHECK#CONFIG_RCU_STALL_COMMON=n
10CONFIG_DEBUG_LOCK_ALLOC=n 11CONFIG_DEBUG_LOCK_ALLOC=n
11CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 12CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
12CONFIG_PREEMPT_COUNT=n 13CONFIG_PREEMPT_COUNT=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY02 b/tools/testing/selftests/rcutorture/configs/rcu/TINY02
index f1892e0371c9..a59f7686e219 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TINY02
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY02
@@ -8,7 +8,8 @@ CONFIG_NO_HZ_IDLE=n
8CONFIG_NO_HZ_FULL=n 8CONFIG_NO_HZ_FULL=n
9CONFIG_RCU_TRACE=y 9CONFIG_RCU_TRACE=y
10CONFIG_PROVE_LOCKING=y 10CONFIG_PROVE_LOCKING=y
11CONFIG_PROVE_RCU_REPEATEDLY=y
11#CHECK#CONFIG_PROVE_RCU=y 12#CHECK#CONFIG_PROVE_RCU=y
12CONFIG_DEBUG_LOCK_ALLOC=y 13CONFIG_DEBUG_LOCK_ALLOC=y
13CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 14CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
14CONFIG_PREEMPT_COUNT=y 15CONFIG_PREEMPT_COUNT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01 b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
index f572b873c620..359cb258f639 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE01
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
@@ -16,3 +16,6 @@ CONFIG_DEBUG_LOCK_ALLOC=n
16CONFIG_RCU_BOOST=n 16CONFIG_RCU_BOOST=n
17CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 17CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
18CONFIG_RCU_EXPERT=y 18CONFIG_RCU_EXPERT=y
19CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
20CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
21CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE02 b/tools/testing/selftests/rcutorture/configs/rcu/TREE02
index ef6a22c44dea..c1ab5926568b 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE02
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE02
@@ -20,3 +20,7 @@ CONFIG_PROVE_LOCKING=n
20CONFIG_RCU_BOOST=n 20CONFIG_RCU_BOOST=n
21CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 21CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
22CONFIG_RCU_EXPERT=y 22CONFIG_RCU_EXPERT=y
23CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
24CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
25CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
26CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE03 b/tools/testing/selftests/rcutorture/configs/rcu/TREE03
index 7a17c503b382..3b93ee544e70 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE03
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE03
@@ -17,3 +17,6 @@ CONFIG_RCU_BOOST=y
17CONFIG_RCU_KTHREAD_PRIO=2 17CONFIG_RCU_KTHREAD_PRIO=2
18CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 18CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
19CONFIG_RCU_EXPERT=y 19CONFIG_RCU_EXPERT=y
20CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
21CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
22CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
index 17cbe098b115..5af758e783c7 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
@@ -19,3 +19,7 @@ CONFIG_RCU_NOCB_CPU=n
19CONFIG_DEBUG_LOCK_ALLOC=n 19CONFIG_DEBUG_LOCK_ALLOC=n
20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
21CONFIG_RCU_EXPERT=y 21CONFIG_RCU_EXPERT=y
22CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
23CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
24CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
25CONFIG_RCU_EQS_DEBUG=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE05 b/tools/testing/selftests/rcutorture/configs/rcu/TREE05
index 1257d3227b1e..d4cdc0d74e16 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE05
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05
@@ -19,3 +19,6 @@ CONFIG_PROVE_LOCKING=y
19#CHECK#CONFIG_PROVE_RCU=y 19#CHECK#CONFIG_PROVE_RCU=y
20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
21CONFIG_RCU_EXPERT=y 21CONFIG_RCU_EXPERT=y
22CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
23CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
24CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE06 b/tools/testing/selftests/rcutorture/configs/rcu/TREE06
index d3e456b74cbe..4cb02bd28f08 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE06
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE06
@@ -20,3 +20,6 @@ CONFIG_PROVE_LOCKING=y
20#CHECK#CONFIG_PROVE_RCU=y 20#CHECK#CONFIG_PROVE_RCU=y
21CONFIG_DEBUG_OBJECTS_RCU_HEAD=y 21CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
22CONFIG_RCU_EXPERT=y 22CONFIG_RCU_EXPERT=y
23CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
24CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
25CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE07 b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
index 3956b4131f72..b12a3ea1867e 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE07
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
@@ -19,3 +19,6 @@ CONFIG_RCU_NOCB_CPU=n
19CONFIG_DEBUG_LOCK_ALLOC=n 19CONFIG_DEBUG_LOCK_ALLOC=n
20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
21CONFIG_RCU_EXPERT=y 21CONFIG_RCU_EXPERT=y
22CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
23CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
24CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08 b/tools/testing/selftests/rcutorture/configs/rcu/TREE08
index bb9b0c1a23c2..099cc63c6a3b 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE08
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08
@@ -17,8 +17,8 @@ CONFIG_RCU_FANOUT_LEAF=2
17CONFIG_RCU_NOCB_CPU=y 17CONFIG_RCU_NOCB_CPU=y
18CONFIG_RCU_NOCB_CPU_ALL=y 18CONFIG_RCU_NOCB_CPU_ALL=y
19CONFIG_DEBUG_LOCK_ALLOC=n 19CONFIG_DEBUG_LOCK_ALLOC=n
20CONFIG_PROVE_LOCKING=y 20CONFIG_PROVE_LOCKING=n
21#CHECK#CONFIG_PROVE_RCU=y
22CONFIG_RCU_BOOST=n 21CONFIG_RCU_BOOST=n
23CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 22CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
24CONFIG_RCU_EXPERT=y 23CONFIG_RCU_EXPERT=y
24CONFIG_RCU_EQS_DEBUG=y
diff --git a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
index 4e2b1893d40d..364801b1a230 100644
--- a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
+++ b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
@@ -14,6 +14,7 @@ CONFIG_NO_HZ_FULL_SYSIDLE -- Do one.
14CONFIG_PREEMPT -- Do half. (First three and #8.) 14CONFIG_PREEMPT -- Do half. (First three and #8.)
15CONFIG_PROVE_LOCKING -- Do several, covering CONFIG_DEBUG_LOCK_ALLOC=y and not. 15CONFIG_PROVE_LOCKING -- Do several, covering CONFIG_DEBUG_LOCK_ALLOC=y and not.
16CONFIG_PROVE_RCU -- Hardwired to CONFIG_PROVE_LOCKING. 16CONFIG_PROVE_RCU -- Hardwired to CONFIG_PROVE_LOCKING.
17CONFIG_PROVE_RCU_REPEATEDLY -- Do one.
17CONFIG_RCU_BOOST -- one of PREEMPT_RCU. 18CONFIG_RCU_BOOST -- one of PREEMPT_RCU.
18CONFIG_RCU_KTHREAD_PRIO -- set to 2 for _BOOST testing. 19CONFIG_RCU_KTHREAD_PRIO -- set to 2 for _BOOST testing.
19CONFIG_RCU_FANOUT -- Cover hierarchy, but overlap with others. 20CONFIG_RCU_FANOUT -- Cover hierarchy, but overlap with others.
@@ -25,7 +26,12 @@ CONFIG_RCU_NOCB_CPU_NONE -- Do one.
25CONFIG_RCU_NOCB_CPU_ZERO -- Do one. 26CONFIG_RCU_NOCB_CPU_ZERO -- Do one.
26CONFIG_RCU_TRACE -- Do half. 27CONFIG_RCU_TRACE -- Do half.
27CONFIG_SMP -- Need one !SMP for PREEMPT_RCU. 28CONFIG_SMP -- Need one !SMP for PREEMPT_RCU.
28!RCU_EXPERT -- Do a few, but these have to be vanilla configurations. 29CONFIG_RCU_EXPERT=n -- Do a few, but these have to be vanilla configurations.
30CONFIG_RCU_EQS_DEBUG -- Do at least one for CONFIG_NO_HZ_FULL and not.
31CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP -- Do for all but a couple TREE scenarios.
32CONFIG_RCU_TORTURE_TEST_SLOW_INIT -- Do for all but a couple TREE scenarios.
33CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT -- Do for all but a couple TREE scenarios.
34
29RCU-bh: Do one with PREEMPT and one with !PREEMPT. 35RCU-bh: Do one with PREEMPT and one with !PREEMPT.
30RCU-sched: Do one with PREEMPT but not BOOST. 36RCU-sched: Do one with PREEMPT but not BOOST.
31 37
@@ -72,7 +78,30 @@ CONFIG_RCU_TORTURE_TEST_RUNNABLE
72 78
73 Always used in KVM testing. 79 Always used in KVM testing.
74 80
81CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT_DELAY
82CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY
83CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP_DELAY
84
85 Inspection suffices, ignore.
86
75CONFIG_PREEMPT_RCU 87CONFIG_PREEMPT_RCU
76CONFIG_TREE_RCU 88CONFIG_TREE_RCU
89CONFIG_TINY_RCU
90
91 These are controlled by CONFIG_PREEMPT and/or CONFIG_SMP.
92
93CONFIG_SPARSE_RCU_POINTER
94
95 Makes sense only for sparse runs, not for kernel builds.
96
97CONFIG_SRCU
98CONFIG_TASKS_RCU
99
100 Selected by CONFIG_RCU_TORTURE_TEST, so cannot disable.
101
102CONFIG_RCU_TRACE
103
104 Implied by CONFIG_RCU_TRACE for Tree RCU.
105
77 106
78 These are controlled by CONFIG_PREEMPT. 107boot parameters ignored: TBD
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/.gitignore b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/.gitignore
new file mode 100644
index 000000000000..712a3d41a325
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/.gitignore
@@ -0,0 +1 @@
srcu.c
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/Makefile b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/Makefile
new file mode 100644
index 000000000000..16b01559fa55
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/Makefile
@@ -0,0 +1,16 @@
1all: srcu.c store_buffering
2
3LINUX_SOURCE = ../../../../../..
4
5modified_srcu_input = $(LINUX_SOURCE)/include/linux/srcu.h \
6 $(LINUX_SOURCE)/kernel/rcu/srcu.c
7
8modified_srcu_output = include/linux/srcu.h srcu.c
9
10include/linux/srcu.h: srcu.c
11
12srcu.c: modify_srcu.awk Makefile $(modified_srcu_input)
13 awk -f modify_srcu.awk $(modified_srcu_input) $(modified_srcu_output)
14
15store_buffering:
16 @cd tests/store_buffering; make
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/delay.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/delay.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/delay.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/export.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/export.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/export.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/mutex.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/mutex.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/mutex.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/percpu.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/percpu.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/percpu.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/preempt.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/preempt.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/preempt.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/rcupdate.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/rcupdate.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/rcupdate.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/sched.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/sched.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/sched.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/smp.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/smp.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/smp.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/workqueue.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/workqueue.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/workqueue.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/uapi/linux/types.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/uapi/linux/types.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/uapi/linux/types.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/.gitignore b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/.gitignore
new file mode 100644
index 000000000000..1d016e66980a
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/.gitignore
@@ -0,0 +1 @@
srcu.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/kconfig.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/kconfig.h
new file mode 100644
index 000000000000..f2860dd1b407
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/kconfig.h
@@ -0,0 +1 @@
#include <LINUX_SOURCE/linux/kconfig.h>
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h
new file mode 100644
index 000000000000..4a3d538fef12
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h
@@ -0,0 +1,155 @@
1/*
2 * This header has been modifies to remove definitions of types that
3 * are defined in standard userspace headers or are problematic for some
4 * other reason.
5 */
6
7#ifndef _LINUX_TYPES_H
8#define _LINUX_TYPES_H
9
10#define __EXPORTED_HEADERS__
11#include <uapi/linux/types.h>
12
13#ifndef __ASSEMBLY__
14
15#define DECLARE_BITMAP(name, bits) \
16 unsigned long name[BITS_TO_LONGS(bits)]
17
18typedef __u32 __kernel_dev_t;
19
20/* bsd */
21typedef unsigned char u_char;
22typedef unsigned short u_short;
23typedef unsigned int u_int;
24typedef unsigned long u_long;
25
26/* sysv */
27typedef unsigned char unchar;
28typedef unsigned short ushort;
29typedef unsigned int uint;
30typedef unsigned long ulong;
31
32#ifndef __BIT_TYPES_DEFINED__
33#define __BIT_TYPES_DEFINED__
34
35typedef __u8 u_int8_t;
36typedef __s8 int8_t;
37typedef __u16 u_int16_t;
38typedef __s16 int16_t;
39typedef __u32 u_int32_t;
40typedef __s32 int32_t;
41
42#endif /* !(__BIT_TYPES_DEFINED__) */
43
44typedef __u8 uint8_t;
45typedef __u16 uint16_t;
46typedef __u32 uint32_t;
47
48/* this is a special 64bit data type that is 8-byte aligned */
49#define aligned_u64 __u64 __attribute__((aligned(8)))
50#define aligned_be64 __be64 __attribute__((aligned(8)))
51#define aligned_le64 __le64 __attribute__((aligned(8)))
52
53/**
54 * The type used for indexing onto a disc or disc partition.
55 *
56 * Linux always considers sectors to be 512 bytes long independently
57 * of the devices real block size.
58 *
59 * blkcnt_t is the type of the inode's block count.
60 */
61#ifdef CONFIG_LBDAF
62typedef u64 sector_t;
63#else
64typedef unsigned long sector_t;
65#endif
66
67/*
68 * The type of an index into the pagecache.
69 */
70#define pgoff_t unsigned long
71
72/*
73 * A dma_addr_t can hold any valid DMA address, i.e., any address returned
74 * by the DMA API.
75 *
76 * If the DMA API only uses 32-bit addresses, dma_addr_t need only be 32
77 * bits wide. Bus addresses, e.g., PCI BARs, may be wider than 32 bits,
78 * but drivers do memory-mapped I/O to ioremapped kernel virtual addresses,
79 * so they don't care about the size of the actual bus addresses.
80 */
81#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
82typedef u64 dma_addr_t;
83#else
84typedef u32 dma_addr_t;
85#endif
86
87#ifdef CONFIG_PHYS_ADDR_T_64BIT
88typedef u64 phys_addr_t;
89#else
90typedef u32 phys_addr_t;
91#endif
92
93typedef phys_addr_t resource_size_t;
94
95/*
96 * This type is the placeholder for a hardware interrupt number. It has to be
97 * big enough to enclose whatever representation is used by a given platform.
98 */
99typedef unsigned long irq_hw_number_t;
100
101typedef struct {
102 int counter;
103} atomic_t;
104
105#ifdef CONFIG_64BIT
106typedef struct {
107 long counter;
108} atomic64_t;
109#endif
110
111struct list_head {
112 struct list_head *next, *prev;
113};
114
115struct hlist_head {
116 struct hlist_node *first;
117};
118
119struct hlist_node {
120 struct hlist_node *next, **pprev;
121};
122
123/**
124 * struct callback_head - callback structure for use with RCU and task_work
125 * @next: next update requests in a list
126 * @func: actual update function to call after the grace period.
127 *
128 * The struct is aligned to size of pointer. On most architectures it happens
129 * naturally due ABI requirements, but some architectures (like CRIS) have
130 * weird ABI and we need to ask it explicitly.
131 *
132 * The alignment is required to guarantee that bits 0 and 1 of @next will be
133 * clear under normal conditions -- as long as we use call_rcu(),
134 * call_rcu_bh(), call_rcu_sched(), or call_srcu() to queue callback.
135 *
136 * This guarantee is important for few reasons:
137 * - future call_rcu_lazy() will make use of lower bits in the pointer;
138 * - the structure shares storage spacer in struct page with @compound_head,
139 * which encode PageTail() in bit 0. The guarantee is needed to avoid
140 * false-positive PageTail().
141 */
142struct callback_head {
143 struct callback_head *next;
144 void (*func)(struct callback_head *head);
145} __attribute__((aligned(sizeof(void *))));
146#define rcu_head callback_head
147
148typedef void (*rcu_callback_t)(struct rcu_head *head);
149typedef void (*call_rcu_func_t)(struct rcu_head *head, rcu_callback_t func);
150
151/* clocksource cycle base type */
152typedef u64 cycle_t;
153
154#endif /* __ASSEMBLY__ */
155#endif /* _LINUX_TYPES_H */
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk
new file mode 100755
index 000000000000..8ff89043d0a9
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk
@@ -0,0 +1,375 @@
1#!/bin/awk -f
2
3# Modify SRCU for formal verification. The first argument should be srcu.h and
4# the second should be srcu.c. Outputs modified srcu.h and srcu.c into the
5# current directory.
6
7BEGIN {
8 if (ARGC != 5) {
9 print "Usange: input.h input.c output.h output.c" > "/dev/stderr";
10 exit 1;
11 }
12 h_output = ARGV[3];
13 c_output = ARGV[4];
14 ARGC = 3;
15
16 # Tokenize using FS and not RS as FS supports regular expressions. Each
17 # record is one line of source, except that backslashed lines are
18 # combined. Comments are treated as field separators, as are quotes.
19 quote_regexp="\"([^\\\\\"]|\\\\.)*\"";
20 comment_regexp="\\/\\*([^*]|\\*+[^*/])*\\*\\/|\\/\\/.*(\n|$)";
21 FS="([ \\\\\t\n\v\f;,.=(){}+*/<>&|^-]|\\[|\\]|" comment_regexp "|" quote_regexp ")+";
22
23 inside_srcu_struct = 0;
24 inside_srcu_init_def = 0;
25 srcu_init_param_name = "";
26 in_macro = 0;
27 brace_nesting = 0;
28 paren_nesting = 0;
29
30 # Allow the manipulation of the last field separator after has been
31 # seen.
32 last_fs = "";
33 # Whether the last field separator was intended to be output.
34 last_fs_print = 0;
35
36 # rcu_batches stores the initialization for each instance of struct
37 # rcu_batch
38
39 in_comment = 0;
40
41 outputfile = "";
42}
43
44{
45 prev_outputfile = outputfile;
46 if (FILENAME ~ /\.h$/) {
47 outputfile = h_output;
48 if (FNR != NR) {
49 print "Incorrect file order" > "/dev/stderr";
50 exit 1;
51 }
52 }
53 else
54 outputfile = c_output;
55
56 if (prev_outputfile && outputfile != prev_outputfile) {
57 new_outputfile = outputfile;
58 outputfile = prev_outputfile;
59 update_fieldsep("", 0);
60 outputfile = new_outputfile;
61 }
62}
63
64# Combine the next line into $0.
65function combine_line() {
66 ret = getline next_line;
67 if (ret == 0) {
68 # Don't allow two consecutive getlines at the end of the file
69 if (eof_found) {
70 print "Error: expected more input." > "/dev/stderr";
71 exit 1;
72 } else {
73 eof_found = 1;
74 }
75 } else if (ret == -1) {
76 print "Error reading next line of file" FILENAME > "/dev/stderr";
77 exit 1;
78 }
79 $0 = $0 "\n" next_line;
80}
81
82# Combine backslashed lines and multiline comments.
83function combine_backslashes() {
84 while (/\\$|\/\*([^*]|\*+[^*\/])*\**$/) {
85 combine_line();
86 }
87}
88
89function read_line() {
90 combine_line();
91 combine_backslashes();
92}
93
94# Print out field separators and update variables that depend on them. Only
95# print if p is true. Call with sep="" and p=0 to print out the last field
96# separator.
97function update_fieldsep(sep, p) {
98 # Count braces
99 sep_tmp = sep;
100 gsub(quote_regexp "|" comment_regexp, "", sep_tmp);
101 while (1)
102 {
103 if (sub("[^{}()]*\\{", "", sep_tmp)) {
104 brace_nesting++;
105 continue;
106 }
107 if (sub("[^{}()]*\\}", "", sep_tmp)) {
108 brace_nesting--;
109 if (brace_nesting < 0) {
110 print "Unbalanced braces!" > "/dev/stderr";
111 exit 1;
112 }
113 continue;
114 }
115 if (sub("[^{}()]*\\(", "", sep_tmp)) {
116 paren_nesting++;
117 continue;
118 }
119 if (sub("[^{}()]*\\)", "", sep_tmp)) {
120 paren_nesting--;
121 if (paren_nesting < 0) {
122 print "Unbalanced parenthesis!" > "/dev/stderr";
123 exit 1;
124 }
125 continue;
126 }
127
128 break;
129 }
130
131 if (last_fs_print)
132 printf("%s", last_fs) > outputfile;
133 last_fs = sep;
134 last_fs_print = p;
135}
136
137# Shifts the fields down by n positions. Calls next if there are no more. If p
138# is true then print out field separators.
139function shift_fields(n, p) {
140 do {
141 if (match($0, FS) > 0) {
142 update_fieldsep(substr($0, RSTART, RLENGTH), p);
143 if (RSTART + RLENGTH <= length())
144 $0 = substr($0, RSTART + RLENGTH);
145 else
146 $0 = "";
147 } else {
148 update_fieldsep("", 0);
149 print "" > outputfile;
150 next;
151 }
152 } while (--n > 0);
153}
154
155# Shifts and prints the first n fields.
156function print_fields(n) {
157 do {
158 update_fieldsep("", 0);
159 printf("%s", $1) > outputfile;
160 shift_fields(1, 1);
161 } while (--n > 0);
162}
163
164{
165 combine_backslashes();
166}
167
168# Print leading FS
169{
170 if (match($0, "^(" FS ")+") > 0) {
171 update_fieldsep(substr($0, RSTART, RLENGTH), 1);
172 if (RSTART + RLENGTH <= length())
173 $0 = substr($0, RSTART + RLENGTH);
174 else
175 $0 = "";
176 }
177}
178
179# Parse the line.
180{
181 while (NF > 0) {
182 if ($1 == "struct" && NF < 3) {
183 read_line();
184 continue;
185 }
186
187 if (FILENAME ~ /\.h$/ && !inside_srcu_struct &&
188 brace_nesting == 0 && paren_nesting == 0 &&
189 $1 == "struct" && $2 == "srcu_struct" &&
190 $0 ~ "^struct(" FS ")+srcu_struct(" FS ")+\\{") {
191 inside_srcu_struct = 1;
192 print_fields(2);
193 continue;
194 }
195 if (inside_srcu_struct && brace_nesting == 0 &&
196 paren_nesting == 0) {
197 inside_srcu_struct = 0;
198 update_fieldsep("", 0);
199 for (name in rcu_batches)
200 print "extern struct rcu_batch " name ";" > outputfile;
201 }
202
203 if (inside_srcu_struct && $1 == "struct" && $2 == "rcu_batch") {
204 # Move rcu_batches outside of the struct.
205 rcu_batches[$3] = "";
206 shift_fields(3, 1);
207 sub(/;[[:space:]]*$/, "", last_fs);
208 continue;
209 }
210
211 if (FILENAME ~ /\.h$/ && !inside_srcu_init_def &&
212 $1 == "#define" && $2 == "__SRCU_STRUCT_INIT") {
213 inside_srcu_init_def = 1;
214 srcu_init_param_name = $3;
215 in_macro = 1;
216 print_fields(3);
217 continue;
218 }
219 if (inside_srcu_init_def && brace_nesting == 0 &&
220 paren_nesting == 0) {
221 inside_srcu_init_def = 0;
222 in_macro = 0;
223 continue;
224 }
225
226 if (inside_srcu_init_def && brace_nesting == 1 &&
227 paren_nesting == 0 && last_fs ~ /\.[[:space:]]*$/ &&
228 $1 ~ /^[[:alnum:]_]+$/) {
229 name = $1;
230 if (name in rcu_batches) {
231 # Remove the dot.
232 sub(/\.[[:space:]]*$/, "", last_fs);
233
234 old_record = $0;
235 do
236 shift_fields(1, 0);
237 while (last_fs !~ /,/ || paren_nesting > 0);
238 end_loc = length(old_record) - length($0);
239 end_loc += index(last_fs, ",") - length(last_fs);
240
241 last_fs = substr(last_fs, index(last_fs, ",") + 1);
242 last_fs_print = 1;
243
244 match(old_record, "^"name"("FS")+=");
245 start_loc = RSTART + RLENGTH;
246
247 len = end_loc - start_loc;
248 initializer = substr(old_record, start_loc, len);
249 gsub(srcu_init_param_name "\\.", "", initializer);
250 rcu_batches[name] = initializer;
251 continue;
252 }
253 }
254
255 # Don't include a nonexistent file
256 if (!in_macro && $1 == "#include" && /^#include[[:space:]]+"rcu\.h"/) {
257 update_fieldsep("", 0);
258 next;
259 }
260
261 # Ignore most preprocessor stuff.
262 if (!in_macro && $1 ~ /#/) {
263 break;
264 }
265
266 if (brace_nesting > 0 && $1 ~ "^[[:alnum:]_]+$" && NF < 2) {
267 read_line();
268 continue;
269 }
270 if (brace_nesting > 0 &&
271 $0 ~ "^[[:alnum:]_]+[[:space:]]*(\\.|->)[[:space:]]*[[:alnum:]_]+" &&
272 $2 in rcu_batches) {
273 # Make uses of rcu_batches global. Somewhat unreliable.
274 shift_fields(1, 0);
275 print_fields(1);
276 continue;
277 }
278
279 if ($1 == "static" && NF < 3) {
280 read_line();
281 continue;
282 }
283 if ($1 == "static" && ($2 == "bool" && $3 == "try_check_zero" ||
284 $2 == "void" && $3 == "srcu_flip")) {
285 shift_fields(1, 1);
286 print_fields(2);
287 continue;
288 }
289
290 # Distinguish between read-side and write-side memory barriers.
291 if ($1 == "smp_mb" && NF < 2) {
292 read_line();
293 continue;
294 }
295 if (match($0, /^smp_mb[[:space:]();\/*]*[[:alnum:]]/)) {
296 barrier_letter = substr($0, RLENGTH, 1);
297 if (barrier_letter ~ /A|D/)
298 new_barrier_name = "sync_smp_mb";
299 else if (barrier_letter ~ /B|C/)
300 new_barrier_name = "rs_smp_mb";
301 else {
302 print "Unrecognized memory barrier." > "/dev/null";
303 exit 1;
304 }
305
306 shift_fields(1, 1);
307 printf("%s", new_barrier_name) > outputfile;
308 continue;
309 }
310
311 # Skip definition of rcu_synchronize, since it is already
312 # defined in misc.h. Only present in old versions of srcu.
313 if (brace_nesting == 0 && paren_nesting == 0 &&
314 $1 == "struct" && $2 == "rcu_synchronize" &&
315 $0 ~ "^struct(" FS ")+rcu_synchronize(" FS ")+\\{") {
316 shift_fields(2, 0);
317 while (brace_nesting) {
318 if (NF < 2)
319 read_line();
320 shift_fields(1, 0);
321 }
322 }
323
324 # Skip definition of wakeme_after_rcu for the same reason
325 if (brace_nesting == 0 && $1 == "static" && $2 == "void" &&
326 $3 == "wakeme_after_rcu") {
327 while (NF < 5)
328 read_line();
329 shift_fields(3, 0);
330 do {
331 while (NF < 3)
332 read_line();
333 shift_fields(1, 0);
334 } while (paren_nesting || brace_nesting);
335 }
336
337 if ($1 ~ /^(unsigned|long)$/ && NF < 3) {
338 read_line();
339 continue;
340 }
341
342 # Give srcu_batches_completed the correct type for old SRCU.
343 if (brace_nesting == 0 && $1 == "long" &&
344 $2 == "srcu_batches_completed") {
345 update_fieldsep("", 0);
346 printf("unsigned ") > outputfile;
347 print_fields(2);
348 continue;
349 }
350 if (brace_nesting == 0 && $1 == "unsigned" && $2 == "long" &&
351 $3 == "srcu_batches_completed") {
352 print_fields(3);
353 continue;
354 }
355
356 # Just print out the input code by default.
357 print_fields(1);
358 }
359 update_fieldsep("", 0);
360 print > outputfile;
361 next;
362}
363
364END {
365 update_fieldsep("", 0);
366
367 if (brace_nesting != 0) {
368 print "Unbalanced braces!" > "/dev/stderr";
369 exit 1;
370 }
371
372 # Define the rcu_batches
373 for (name in rcu_batches)
374 print "struct rcu_batch " name " = " rcu_batches[name] ";" > c_output;
375}
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/assume.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/assume.h
new file mode 100644
index 000000000000..a64955447995
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/assume.h
@@ -0,0 +1,16 @@
1#ifndef ASSUME_H
2#define ASSUME_H
3
4/* Provide an assumption macro that can be disabled for gcc. */
5#ifdef RUN
6#define assume(x) \
7 do { \
8 /* Evaluate x to suppress warnings. */ \
9 (void) (x); \
10 } while (0)
11
12#else
13#define assume(x) __CPROVER_assume(x)
14#endif
15
16#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/barriers.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/barriers.h
new file mode 100644
index 000000000000..6687acc08e6d
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/barriers.h
@@ -0,0 +1,41 @@
1#ifndef BARRIERS_H
2#define BARRIERS_H
3
4#define barrier() __asm__ __volatile__("" : : : "memory")
5
6#ifdef RUN
7#define smp_mb() __sync_synchronize()
8#define smp_mb__after_unlock_lock() __sync_synchronize()
9#else
10/*
11 * Copied from CBMC's implementation of __sync_synchronize(), which
12 * seems to be disabled by default.
13 */
14#define smp_mb() __CPROVER_fence("WWfence", "RRfence", "RWfence", "WRfence", \
15 "WWcumul", "RRcumul", "RWcumul", "WRcumul")
16#define smp_mb__after_unlock_lock() __CPROVER_fence("WWfence", "RRfence", "RWfence", "WRfence", \
17 "WWcumul", "RRcumul", "RWcumul", "WRcumul")
18#endif
19
20/*
21 * Allow memory barriers to be disabled in either the read or write side
22 * of SRCU individually.
23 */
24
25#ifndef NO_SYNC_SMP_MB
26#define sync_smp_mb() smp_mb()
27#else
28#define sync_smp_mb() do {} while (0)
29#endif
30
31#ifndef NO_READ_SIDE_SMP_MB
32#define rs_smp_mb() smp_mb()
33#else
34#define rs_smp_mb() do {} while (0)
35#endif
36
37#define ACCESS_ONCE(x) (*(volatile typeof(x) *) &(x))
38#define READ_ONCE(x) ACCESS_ONCE(x)
39#define WRITE_ONCE(x, val) (ACCESS_ONCE(x) = (val))
40
41#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/bug_on.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/bug_on.h
new file mode 100644
index 000000000000..2a80e91f78e7
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/bug_on.h
@@ -0,0 +1,13 @@
1#ifndef BUG_ON_H
2#define BUG_ON_H
3
4#include <assert.h>
5
6#define BUG() assert(0)
7#define BUG_ON(x) assert(!(x))
8
9/* Does it make sense to treat warnings as errors? */
10#define WARN() BUG()
11#define WARN_ON(x) (BUG_ON(x), false)
12
13#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/combined_source.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/combined_source.c
new file mode 100644
index 000000000000..29eb5d2697ed
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/combined_source.c
@@ -0,0 +1,13 @@
1#include <config.h>
2
3/* Include all source files. */
4
5#include "include_srcu.c"
6
7#include "preempt.c"
8#include "misc.c"
9
10/* Used by test.c files */
11#include <pthread.h>
12#include <stdlib.h>
13#include <linux/srcu.h>
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/config.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/config.h
new file mode 100644
index 000000000000..a60038aeea7a
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/config.h
@@ -0,0 +1,27 @@
1/* "Cheater" definitions based on restricted Kconfig choices. */
2
3#undef CONFIG_TINY_RCU
4#undef __CHECKER__
5#undef CONFIG_DEBUG_LOCK_ALLOC
6#undef CONFIG_DEBUG_OBJECTS_RCU_HEAD
7#undef CONFIG_HOTPLUG_CPU
8#undef CONFIG_MODULES
9#undef CONFIG_NO_HZ_FULL_SYSIDLE
10#undef CONFIG_PREEMPT_COUNT
11#undef CONFIG_PREEMPT_RCU
12#undef CONFIG_PROVE_RCU
13#undef CONFIG_RCU_NOCB_CPU
14#undef CONFIG_RCU_NOCB_CPU_ALL
15#undef CONFIG_RCU_STALL_COMMON
16#undef CONFIG_RCU_TRACE
17#undef CONFIG_RCU_USER_QS
18#undef CONFIG_TASKS_RCU
19#define CONFIG_TREE_RCU
20
21#define CONFIG_GENERIC_ATOMIC64
22
23#if NR_CPUS > 1
24#define CONFIG_SMP
25#else
26#undef CONFIG_SMP
27#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/include_srcu.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/include_srcu.c
new file mode 100644
index 000000000000..5ec582a53018
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/include_srcu.c
@@ -0,0 +1,31 @@
1#include <config.h>
2
3#include <assert.h>
4#include <errno.h>
5#include <inttypes.h>
6#include <pthread.h>
7#include <stddef.h>
8#include <string.h>
9#include <sys/types.h>
10
11#include "int_typedefs.h"
12
13#include "barriers.h"
14#include "bug_on.h"
15#include "locks.h"
16#include "misc.h"
17#include "preempt.h"
18#include "percpu.h"
19#include "workqueues.h"
20
21#ifdef USE_SIMPLE_SYNC_SRCU
22#define synchronize_srcu(sp) synchronize_srcu_original(sp)
23#endif
24
25#include <srcu.c>
26
27#ifdef USE_SIMPLE_SYNC_SRCU
28#undef synchronize_srcu
29
30#include "simple_sync_srcu.c"
31#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/int_typedefs.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/int_typedefs.h
new file mode 100644
index 000000000000..3aad63917858
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/int_typedefs.h
@@ -0,0 +1,33 @@
1#ifndef INT_TYPEDEFS_H
2#define INT_TYPEDEFS_H
3
4#include <inttypes.h>
5
6typedef int8_t s8;
7typedef uint8_t u8;
8typedef int16_t s16;
9typedef uint16_t u16;
10typedef int32_t s32;
11typedef uint32_t u32;
12typedef int64_t s64;
13typedef uint64_t u64;
14
15typedef int8_t __s8;
16typedef uint8_t __u8;
17typedef int16_t __s16;
18typedef uint16_t __u16;
19typedef int32_t __s32;
20typedef uint32_t __u32;
21typedef int64_t __s64;
22typedef uint64_t __u64;
23
24#define S8_C(x) INT8_C(x)
25#define U8_C(x) UINT8_C(x)
26#define S16_C(x) INT16_C(x)
27#define U16_C(x) UINT16_C(x)
28#define S32_C(x) INT32_C(x)
29#define U32_C(x) UINT32_C(x)
30#define S64_C(x) INT64_C(x)
31#define U64_C(x) UINT64_C(x)
32
33#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/locks.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/locks.h
new file mode 100644
index 000000000000..356004665576
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/locks.h
@@ -0,0 +1,220 @@
1#ifndef LOCKS_H
2#define LOCKS_H
3
4#include <limits.h>
5#include <pthread.h>
6#include <stdbool.h>
7
8#include "assume.h"
9#include "bug_on.h"
10#include "preempt.h"
11
12int nondet_int(void);
13
14#define __acquire(x)
15#define __acquires(x)
16#define __release(x)
17#define __releases(x)
18
19/* Only use one lock mechanism. Select which one. */
20#ifdef PTHREAD_LOCK
21struct lock_impl {
22 pthread_mutex_t mutex;
23};
24
25static inline void lock_impl_lock(struct lock_impl *lock)
26{
27 BUG_ON(pthread_mutex_lock(&lock->mutex));
28}
29
30static inline void lock_impl_unlock(struct lock_impl *lock)
31{
32 BUG_ON(pthread_mutex_unlock(&lock->mutex));
33}
34
35static inline bool lock_impl_trylock(struct lock_impl *lock)
36{
37 int err = pthread_mutex_trylock(&lock->mutex);
38
39 if (!err)
40 return true;
41 else if (err == EBUSY)
42 return false;
43 BUG();
44}
45
46static inline void lock_impl_init(struct lock_impl *lock)
47{
48 pthread_mutex_init(&lock->mutex, NULL);
49}
50
51#define LOCK_IMPL_INITIALIZER {.mutex = PTHREAD_MUTEX_INITIALIZER}
52
53#else /* !defined(PTHREAD_LOCK) */
54/* Spinlock that assumes that it always gets the lock immediately. */
55
56struct lock_impl {
57 bool locked;
58};
59
60static inline bool lock_impl_trylock(struct lock_impl *lock)
61{
62#ifdef RUN
63 /* TODO: Should this be a test and set? */
64 return __sync_bool_compare_and_swap(&lock->locked, false, true);
65#else
66 __CPROVER_atomic_begin();
67 bool old_locked = lock->locked;
68 lock->locked = true;
69 __CPROVER_atomic_end();
70
71 /* Minimal barrier to prevent accesses leaking out of lock. */
72 __CPROVER_fence("RRfence", "RWfence");
73
74 return !old_locked;
75#endif
76}
77
78static inline void lock_impl_lock(struct lock_impl *lock)
79{
80 /*
81 * CBMC doesn't support busy waiting, so just assume that the
82 * lock is available.
83 */
84 assume(lock_impl_trylock(lock));
85
86 /*
87 * If the lock was already held by this thread then the assumption
88 * is unsatisfiable (deadlock).
89 */
90}
91
92static inline void lock_impl_unlock(struct lock_impl *lock)
93{
94#ifdef RUN
95 BUG_ON(!__sync_bool_compare_and_swap(&lock->locked, true, false));
96#else
97 /* Minimal barrier to prevent accesses leaking out of lock. */
98 __CPROVER_fence("RWfence", "WWfence");
99
100 __CPROVER_atomic_begin();
101 bool old_locked = lock->locked;
102 lock->locked = false;
103 __CPROVER_atomic_end();
104
105 BUG_ON(!old_locked);
106#endif
107}
108
109static inline void lock_impl_init(struct lock_impl *lock)
110{
111 lock->locked = false;
112}
113
114#define LOCK_IMPL_INITIALIZER {.locked = false}
115
116#endif /* !defined(PTHREAD_LOCK) */
117
118/*
119 * Implement spinlocks using the lock mechanism. Wrap the lock to prevent mixing
120 * locks of different types.
121 */
122typedef struct {
123 struct lock_impl internal_lock;
124} spinlock_t;
125
126#define SPIN_LOCK_UNLOCKED {.internal_lock = LOCK_IMPL_INITIALIZER}
127#define __SPIN_LOCK_UNLOCKED(x) SPIN_LOCK_UNLOCKED
128#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
129
130static inline void spin_lock_init(spinlock_t *lock)
131{
132 lock_impl_init(&lock->internal_lock);
133}
134
135static inline void spin_lock(spinlock_t *lock)
136{
137 /*
138 * Spin locks also need to be removed in order to eliminate all
139 * memory barriers. They are only used by the write side anyway.
140 */
141#ifndef NO_SYNC_SMP_MB
142 preempt_disable();
143 lock_impl_lock(&lock->internal_lock);
144#endif
145}
146
147static inline void spin_unlock(spinlock_t *lock)
148{
149#ifndef NO_SYNC_SMP_MB
150 lock_impl_unlock(&lock->internal_lock);
151 preempt_enable();
152#endif
153}
154
155/* Don't bother with interrupts */
156#define spin_lock_irq(lock) spin_lock(lock)
157#define spin_unlock_irq(lock) spin_unlock(lock)
158#define spin_lock_irqsave(lock, flags) spin_lock(lock)
159#define spin_unlock_irqrestore(lock, flags) spin_unlock(lock)
160
161/*
162 * This is supposed to return an int, but I think that a bool should work as
163 * well.
164 */
165static inline bool spin_trylock(spinlock_t *lock)
166{
167#ifndef NO_SYNC_SMP_MB
168 preempt_disable();
169 return lock_impl_trylock(&lock->internal_lock);
170#else
171 return true;
172#endif
173}
174
175struct completion {
176 /* Hopefuly this won't overflow. */
177 unsigned int count;
178};
179
180#define COMPLETION_INITIALIZER(x) {.count = 0}
181#define DECLARE_COMPLETION(x) struct completion x = COMPLETION_INITIALIZER(x)
182#define DECLARE_COMPLETION_ONSTACK(x) DECLARE_COMPLETION(x)
183
184static inline void init_completion(struct completion *c)
185{
186 c->count = 0;
187}
188
189static inline void wait_for_completion(struct completion *c)
190{
191 unsigned int prev_count = __sync_fetch_and_sub(&c->count, 1);
192
193 assume(prev_count);
194}
195
196static inline void complete(struct completion *c)
197{
198 unsigned int prev_count = __sync_fetch_and_add(&c->count, 1);
199
200 BUG_ON(prev_count == UINT_MAX);
201}
202
203/* This function probably isn't very useful for CBMC. */
204static inline bool try_wait_for_completion(struct completion *c)
205{
206 BUG();
207}
208
209static inline bool completion_done(struct completion *c)
210{
211 return c->count;
212}
213
214/* TODO: Implement complete_all */
215static inline void complete_all(struct completion *c)
216{
217 BUG();
218}
219
220#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.c
new file mode 100644
index 000000000000..ca892e3b2351
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.c
@@ -0,0 +1,11 @@
1#include <config.h>
2
3#include "misc.h"
4#include "bug_on.h"
5
6struct rcu_head;
7
8void wakeme_after_rcu(struct rcu_head *head)
9{
10 BUG();
11}
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.h
new file mode 100644
index 000000000000..aca50030f954
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.h
@@ -0,0 +1,58 @@
1#ifndef MISC_H
2#define MISC_H
3
4#include "assume.h"
5#include "int_typedefs.h"
6#include "locks.h"
7
8#include <linux/types.h>
9
10/* Probably won't need to deal with bottom halves. */
11static inline void local_bh_disable(void) {}
12static inline void local_bh_enable(void) {}
13
14#define MODULE_ALIAS(X)
15#define module_param(...)
16#define EXPORT_SYMBOL_GPL(x)
17
18#define container_of(ptr, type, member) ({ \
19 const typeof(((type *)0)->member) *__mptr = (ptr); \
20 (type *)((char *)__mptr - offsetof(type, member)); \
21})
22
23#ifndef USE_SIMPLE_SYNC_SRCU
24/* Abuse udelay to make sure that busy loops terminate. */
25#define udelay(x) assume(0)
26
27#else
28
29/* The simple custom synchronize_srcu is ok with try_check_zero failing. */
30#define udelay(x) do { } while (0)
31#endif
32
33#define trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c) \
34 do { } while (0)
35
36#define notrace
37
38/* Avoid including rcupdate.h */
39struct rcu_synchronize {
40 struct rcu_head head;
41 struct completion completion;
42};
43
44void wakeme_after_rcu(struct rcu_head *head);
45
46#define rcu_lock_acquire(a) do { } while (0)
47#define rcu_lock_release(a) do { } while (0)
48#define rcu_lockdep_assert(c, s) do { } while (0)
49#define RCU_LOCKDEP_WARN(c, s) do { } while (0)
50
51/* Let CBMC non-deterministically choose switch between normal and expedited. */
52bool rcu_gp_is_normal(void);
53bool rcu_gp_is_expedited(void);
54
55/* Do the same for old versions of rcu. */
56#define rcu_expedited (rcu_gp_is_expedited())
57
58#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/percpu.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/percpu.h
new file mode 100644
index 000000000000..3de5a49de49b
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/percpu.h
@@ -0,0 +1,92 @@
1#ifndef PERCPU_H
2#define PERCPU_H
3
4#include <stddef.h>
5#include "bug_on.h"
6#include "preempt.h"
7
8#define __percpu
9
10/* Maximum size of any percpu data. */
11#define PERCPU_OFFSET (4 * sizeof(long))
12
13/* Ignore alignment, as CBMC doesn't care about false sharing. */
14#define alloc_percpu(type) __alloc_percpu(sizeof(type), 1)
15
16static inline void *__alloc_percpu(size_t size, size_t align)
17{
18 BUG();
19 return NULL;
20}
21
22static inline void free_percpu(void *ptr)
23{
24 BUG();
25}
26
27#define per_cpu_ptr(ptr, cpu) \
28 ((typeof(ptr)) ((char *) (ptr) + PERCPU_OFFSET * cpu))
29
30#define __this_cpu_inc(pcp) __this_cpu_add(pcp, 1)
31#define __this_cpu_dec(pcp) __this_cpu_sub(pcp, 1)
32#define __this_cpu_sub(pcp, n) __this_cpu_add(pcp, -(typeof(pcp)) (n))
33
34#define this_cpu_inc(pcp) this_cpu_add(pcp, 1)
35#define this_cpu_dec(pcp) this_cpu_sub(pcp, 1)
36#define this_cpu_sub(pcp, n) this_cpu_add(pcp, -(typeof(pcp)) (n))
37
38/* Make CBMC use atomics to work around bug. */
39#ifdef RUN
40#define THIS_CPU_ADD_HELPER(ptr, x) (*(ptr) += (x))
41#else
42/*
43 * Split the atomic into a read and a write so that it has the least
44 * possible ordering.
45 */
46#define THIS_CPU_ADD_HELPER(ptr, x) \
47 do { \
48 typeof(ptr) this_cpu_add_helper_ptr = (ptr); \
49 typeof(ptr) this_cpu_add_helper_x = (x); \
50 typeof(*ptr) this_cpu_add_helper_temp; \
51 __CPROVER_atomic_begin(); \
52 this_cpu_add_helper_temp = *(this_cpu_add_helper_ptr); \
53 __CPROVER_atomic_end(); \
54 this_cpu_add_helper_temp += this_cpu_add_helper_x; \
55 __CPROVER_atomic_begin(); \
56 *(this_cpu_add_helper_ptr) = this_cpu_add_helper_temp; \
57 __CPROVER_atomic_end(); \
58 } while (0)
59#endif
60
61/*
62 * For some reason CBMC needs an atomic operation even though this is percpu
63 * data.
64 */
65#define __this_cpu_add(pcp, n) \
66 do { \
67 BUG_ON(preemptible()); \
68 THIS_CPU_ADD_HELPER(per_cpu_ptr(&(pcp), thread_cpu_id), \
69 (typeof(pcp)) (n)); \
70 } while (0)
71
72#define this_cpu_add(pcp, n) \
73 do { \
74 int this_cpu_add_impl_cpu = get_cpu(); \
75 THIS_CPU_ADD_HELPER(per_cpu_ptr(&(pcp), this_cpu_add_impl_cpu), \
76 (typeof(pcp)) (n)); \
77 put_cpu(); \
78 } while (0)
79
80/*
81 * This will cause a compiler warning because of the cast from char[][] to
82 * type*. This will cause a compile time error if type is too big.
83 */
84#define DEFINE_PER_CPU(type, name) \
85 char name[NR_CPUS][PERCPU_OFFSET]; \
86 typedef char percpu_too_big_##name \
87 [sizeof(type) > PERCPU_OFFSET ? -1 : 1]
88
89#define for_each_possible_cpu(cpu) \
90 for ((cpu) = 0; (cpu) < NR_CPUS; ++(cpu))
91
92#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.c
new file mode 100644
index 000000000000..4f1b068e9b7a
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.c
@@ -0,0 +1,78 @@
1#include <config.h>
2
3#include "preempt.h"
4
5#include "assume.h"
6#include "locks.h"
7
8/* Support NR_CPUS of at most 64 */
9#define CPU_PREEMPTION_LOCKS_INIT0 LOCK_IMPL_INITIALIZER
10#define CPU_PREEMPTION_LOCKS_INIT1 \
11 CPU_PREEMPTION_LOCKS_INIT0, CPU_PREEMPTION_LOCKS_INIT0
12#define CPU_PREEMPTION_LOCKS_INIT2 \
13 CPU_PREEMPTION_LOCKS_INIT1, CPU_PREEMPTION_LOCKS_INIT1
14#define CPU_PREEMPTION_LOCKS_INIT3 \
15 CPU_PREEMPTION_LOCKS_INIT2, CPU_PREEMPTION_LOCKS_INIT2
16#define CPU_PREEMPTION_LOCKS_INIT4 \
17 CPU_PREEMPTION_LOCKS_INIT3, CPU_PREEMPTION_LOCKS_INIT3
18#define CPU_PREEMPTION_LOCKS_INIT5 \
19 CPU_PREEMPTION_LOCKS_INIT4, CPU_PREEMPTION_LOCKS_INIT4
20
21/*
22 * Simulate disabling preemption by locking a particular cpu. NR_CPUS
23 * should be the actual number of cpus, not just the maximum.
24 */
25struct lock_impl cpu_preemption_locks[NR_CPUS] = {
26 CPU_PREEMPTION_LOCKS_INIT0
27#if (NR_CPUS - 1) & 1
28 , CPU_PREEMPTION_LOCKS_INIT0
29#endif
30#if (NR_CPUS - 1) & 2
31 , CPU_PREEMPTION_LOCKS_INIT1
32#endif
33#if (NR_CPUS - 1) & 4
34 , CPU_PREEMPTION_LOCKS_INIT2
35#endif
36#if (NR_CPUS - 1) & 8
37 , CPU_PREEMPTION_LOCKS_INIT3
38#endif
39#if (NR_CPUS - 1) & 16
40 , CPU_PREEMPTION_LOCKS_INIT4
41#endif
42#if (NR_CPUS - 1) & 32
43 , CPU_PREEMPTION_LOCKS_INIT5
44#endif
45};
46
47#undef CPU_PREEMPTION_LOCKS_INIT0
48#undef CPU_PREEMPTION_LOCKS_INIT1
49#undef CPU_PREEMPTION_LOCKS_INIT2
50#undef CPU_PREEMPTION_LOCKS_INIT3
51#undef CPU_PREEMPTION_LOCKS_INIT4
52#undef CPU_PREEMPTION_LOCKS_INIT5
53
54__thread int thread_cpu_id;
55__thread int preempt_disable_count;
56
57void preempt_disable(void)
58{
59 BUG_ON(preempt_disable_count < 0 || preempt_disable_count == INT_MAX);
60
61 if (preempt_disable_count++)
62 return;
63
64 thread_cpu_id = nondet_int();
65 assume(thread_cpu_id >= 0);
66 assume(thread_cpu_id < NR_CPUS);
67 lock_impl_lock(&cpu_preemption_locks[thread_cpu_id]);
68}
69
70void preempt_enable(void)
71{
72 BUG_ON(preempt_disable_count < 1);
73
74 if (--preempt_disable_count)
75 return;
76
77 lock_impl_unlock(&cpu_preemption_locks[thread_cpu_id]);
78}
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h
new file mode 100644
index 000000000000..2f95ee0e4dd5
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h
@@ -0,0 +1,58 @@
1#ifndef PREEMPT_H
2#define PREEMPT_H
3
4#include <stdbool.h>
5
6#include "bug_on.h"
7
8/* This flag contains garbage if preempt_disable_count is 0. */
9extern __thread int thread_cpu_id;
10
11/* Support recursive preemption disabling. */
12extern __thread int preempt_disable_count;
13
14void preempt_disable(void);
15void preempt_enable(void);
16
17static inline void preempt_disable_notrace(void)
18{
19 preempt_disable();
20}
21
22static inline void preempt_enable_no_resched(void)
23{
24 preempt_enable();
25}
26
27static inline void preempt_enable_notrace(void)
28{
29 preempt_enable();
30}
31
32static inline int preempt_count(void)
33{
34 return preempt_disable_count;
35}
36
37static inline bool preemptible(void)
38{
39 return !preempt_count();
40}
41
42static inline int get_cpu(void)
43{
44 preempt_disable();
45 return thread_cpu_id;
46}
47
48static inline void put_cpu(void)
49{
50 preempt_enable();
51}
52
53static inline void might_sleep(void)
54{
55 BUG_ON(preempt_disable_count);
56}
57
58#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/simple_sync_srcu.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/simple_sync_srcu.c
new file mode 100644
index 000000000000..ac9cbc62b411
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/simple_sync_srcu.c
@@ -0,0 +1,50 @@
1#include <config.h>
2
3#include <assert.h>
4#include <errno.h>
5#include <inttypes.h>
6#include <pthread.h>
7#include <stddef.h>
8#include <string.h>
9#include <sys/types.h>
10
11#include "int_typedefs.h"
12
13#include "barriers.h"
14#include "bug_on.h"
15#include "locks.h"
16#include "misc.h"
17#include "preempt.h"
18#include "percpu.h"
19#include "workqueues.h"
20
21#include <linux/srcu.h>
22
23/* Functions needed from modify_srcu.c */
24bool try_check_zero(struct srcu_struct *sp, int idx, int trycount);
25void srcu_flip(struct srcu_struct *sp);
26
27/* Simpler implementation of synchronize_srcu that ignores batching. */
28void synchronize_srcu(struct srcu_struct *sp)
29{
30 int idx;
31 /*
32 * This code assumes that try_check_zero will succeed anyway,
33 * so there is no point in multiple tries.
34 */
35 const int trycount = 1;
36
37 might_sleep();
38
39 /* Ignore the lock, as multiple writers aren't working yet anyway. */
40
41 idx = 1 ^ (sp->completed & 1);
42
43 /* For comments see srcu_advance_batches. */
44
45 assume(try_check_zero(sp, idx, trycount));
46
47 srcu_flip(sp);
48
49 assume(try_check_zero(sp, idx^1, trycount));
50}
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/workqueues.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/workqueues.h
new file mode 100644
index 000000000000..e58c8dfd3e90
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/workqueues.h
@@ -0,0 +1,102 @@
1#ifndef WORKQUEUES_H
2#define WORKQUEUES_H
3
4#include <stdbool.h>
5
6#include "barriers.h"
7#include "bug_on.h"
8#include "int_typedefs.h"
9
10#include <linux/types.h>
11
12/* Stub workqueue implementation. */
13
14struct work_struct;
15typedef void (*work_func_t)(struct work_struct *work);
16void delayed_work_timer_fn(unsigned long __data);
17
18struct work_struct {
19/* atomic_long_t data; */
20 unsigned long data;
21
22 struct list_head entry;
23 work_func_t func;
24#ifdef CONFIG_LOCKDEP
25 struct lockdep_map lockdep_map;
26#endif
27};
28
29struct timer_list {
30 struct hlist_node entry;
31 unsigned long expires;
32 void (*function)(unsigned long);
33 unsigned long data;
34 u32 flags;
35 int slack;
36};
37
38struct delayed_work {
39 struct work_struct work;
40 struct timer_list timer;
41
42 /* target workqueue and CPU ->timer uses to queue ->work */
43 struct workqueue_struct *wq;
44 int cpu;
45};
46
47
48static inline bool schedule_work(struct work_struct *work)
49{
50 BUG();
51 return true;
52}
53
54static inline bool schedule_work_on(int cpu, struct work_struct *work)
55{
56 BUG();
57 return true;
58}
59
60static inline bool queue_work(struct workqueue_struct *wq,
61 struct work_struct *work)
62{
63 BUG();
64 return true;
65}
66
67static inline bool queue_delayed_work(struct workqueue_struct *wq,
68 struct delayed_work *dwork,
69 unsigned long delay)
70{
71 BUG();
72 return true;
73}
74
75#define INIT_WORK(w, f) \
76 do { \
77 (w)->data = 0; \
78 (w)->func = (f); \
79 } while (0)
80
81#define INIT_DELAYED_WORK(w, f) INIT_WORK(&(w)->work, (f))
82
83#define __WORK_INITIALIZER(n, f) { \
84 .data = 0, \
85 .entry = { &(n).entry, &(n).entry }, \
86 .func = f \
87 }
88
89/* Don't bother initializing timer. */
90#define __DELAYED_WORK_INITIALIZER(n, f, tflags) { \
91 .work = __WORK_INITIALIZER((n).work, (f)), \
92 }
93
94#define DECLARE_WORK(n, f) \
95 struct workqueue_struct n = __WORK_INITIALIZER
96
97#define DECLARE_DELAYED_WORK(n, f) \
98 struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f, 0)
99
100#define system_power_efficient_wq ((struct workqueue_struct *) NULL)
101
102#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/.gitignore b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/.gitignore
new file mode 100644
index 000000000000..f47cb2045f13
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/.gitignore
@@ -0,0 +1 @@
*.out
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/Makefile b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/Makefile
new file mode 100644
index 000000000000..3a3aee149225
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/Makefile
@@ -0,0 +1,11 @@
1CBMC_FLAGS = -I../.. -I../../src -I../../include -I../../empty_includes -32 -pointer-check -mm pso
2
3all:
4 for i in ./*.pass; do \
5 echo $$i ; \
6 CBMC_FLAGS="$(CBMC_FLAGS)" sh ../test_script.sh --should-pass $$i > $$i.out 2>&1 ; \
7 done
8 for i in ./*.fail; do \
9 echo $$i ; \
10 CBMC_FLAGS="$(CBMC_FLAGS)" sh ../test_script.sh --should-fail $$i > $$i.out 2>&1 ; \
11 done
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/assert_end.fail b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/assert_end.fail
new file mode 100644
index 000000000000..40c8075919d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/assert_end.fail
@@ -0,0 +1 @@
test_cbmc_options="-DASSERT_END"
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force.fail b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force.fail
new file mode 100644
index 000000000000..ada5baf0b60d
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force.fail
@@ -0,0 +1 @@
test_cbmc_options="-DFORCE_FAILURE"
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force2.fail b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force2.fail
new file mode 100644
index 000000000000..8fe00c8db466
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force2.fail
@@ -0,0 +1 @@
test_cbmc_options="-DFORCE_FAILURE_2"
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force3.fail b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force3.fail
new file mode 100644
index 000000000000..612ed6772844
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force3.fail
@@ -0,0 +1 @@
test_cbmc_options="-DFORCE_FAILURE_3"
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/main.pass b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/main.pass
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/main.pass
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/test.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/test.c
new file mode 100644
index 000000000000..470b1105a112
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/test.c
@@ -0,0 +1,72 @@
1#include <src/combined_source.c>
2
3int x;
4int y;
5
6int __unbuffered_tpr_x;
7int __unbuffered_tpr_y;
8
9DEFINE_SRCU(ss);
10
11void rcu_reader(void)
12{
13 int idx;
14
15#ifndef FORCE_FAILURE_3
16 idx = srcu_read_lock(&ss);
17#endif
18 might_sleep();
19
20 __unbuffered_tpr_y = READ_ONCE(y);
21#ifdef FORCE_FAILURE
22 srcu_read_unlock(&ss, idx);
23 idx = srcu_read_lock(&ss);
24#endif
25 WRITE_ONCE(x, 1);
26
27#ifndef FORCE_FAILURE_3
28 srcu_read_unlock(&ss, idx);
29#endif
30 might_sleep();
31}
32
33void *thread_update(void *arg)
34{
35 WRITE_ONCE(y, 1);
36#ifndef FORCE_FAILURE_2
37 synchronize_srcu(&ss);
38#endif
39 might_sleep();
40 __unbuffered_tpr_x = READ_ONCE(x);
41
42 return NULL;
43}
44
45void *thread_process_reader(void *arg)
46{
47 rcu_reader();
48
49 return NULL;
50}
51
52int main(int argc, char *argv[])
53{
54 pthread_t tu;
55 pthread_t tpr;
56
57 if (pthread_create(&tu, NULL, thread_update, NULL))
58 abort();
59 if (pthread_create(&tpr, NULL, thread_process_reader, NULL))
60 abort();
61 if (pthread_join(tu, NULL))
62 abort();
63 if (pthread_join(tpr, NULL))
64 abort();
65 assert(__unbuffered_tpr_y != 0 || __unbuffered_tpr_x != 0);
66
67#ifdef ASSERT_END
68 assert(0);
69#endif
70
71 return 0;
72}
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/test_script.sh b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/test_script.sh
new file mode 100755
index 000000000000..d1545972a0fa
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/test_script.sh
@@ -0,0 +1,102 @@
1#!/bin/sh
2
3# This script expects a mode (either --should-pass or --should-fail) followed by
4# an input file. The script uses the following environment variables. The test C
5# source file is expected to be named test.c in the directory containing the
6# input file.
7#
8# CBMC: The command to run CBMC. Default: cbmc
9# CBMC_FLAGS: Additional flags to pass to CBMC
10# NR_CPUS: Number of cpus to run tests with. Default specified by the test
11# SYNC_SRCU_MODE: Choose implementation of synchronize_srcu. Defaults to simple.
12# kernel: Version included in the linux kernel source.
13# simple: Use try_check_zero directly.
14#
15# The input file is a script that is sourced by this file. It can define any of
16# the following variables to configure the test.
17#
18# test_cbmc_options: Extra options to pass to CBMC.
19# min_cpus_fail: Minimum number of CPUs (NR_CPUS) for verification to fail.
20# The test is expected to pass if it is run with fewer. (Only
21# useful for .fail files)
22# default_cpus: Quantity of CPUs to use for the test, if not specified on the
23# command line. Default: Larger of 2 and MIN_CPUS_FAIL.
24
25set -e
26
27if test "$#" -ne 2; then
28 echo "Expected one option followed by an input file" 1>&2
29 exit 99
30fi
31
32if test "x$1" = "x--should-pass"; then
33 should_pass="yes"
34elif test "x$1" = "x--should-fail"; then
35 should_pass="no"
36else
37 echo "Unrecognized argument '$1'" 1>&2
38
39 # Exit code 99 indicates a hard error.
40 exit 99
41fi
42
43CBMC=${CBMC:-cbmc}
44
45SYNC_SRCU_MODE=${SYNC_SRCU_MODE:-simple}
46
47case ${SYNC_SRCU_MODE} in
48kernel) sync_srcu_mode_flags="" ;;
49simple) sync_srcu_mode_flags="-DUSE_SIMPLE_SYNC_SRCU" ;;
50
51*)
52 echo "Unrecognized argument '${SYNC_SRCU_MODE}'" 1>&2
53 exit 99
54 ;;
55esac
56
57min_cpus_fail=1
58
59c_file=`dirname "$2"`/test.c
60
61# Source the input file.
62. $2
63
64if test ${min_cpus_fail} -gt 2; then
65 default_default_cpus=${min_cpus_fail}
66else
67 default_default_cpus=2
68fi
69default_cpus=${default_cpus:-${default_default_cpus}}
70cpus=${NR_CPUS:-${default_cpus}}
71
72# Check if there are two few cpus to make the test fail.
73if test $cpus -lt ${min_cpus_fail:-0}; then
74 should_pass="yes"
75fi
76
77cbmc_opts="-DNR_CPUS=${cpus} ${sync_srcu_mode_flags} ${test_cbmc_options} ${CBMC_FLAGS}"
78
79echo "Running CBMC: ${CBMC} ${cbmc_opts} ${c_file}"
80if ${CBMC} ${cbmc_opts} "${c_file}"; then
81 # Verification successful. Make sure that it was supposed to verify.
82 test "x${should_pass}" = xyes
83else
84 cbmc_exit_status=$?
85
86 # An exit status of 10 indicates a failed verification.
87 # (see cbmc_parse_optionst::do_bmc in the CBMC source code)
88 if test ${cbmc_exit_status} -eq 10 && test "x${should_pass}" = xno; then
89 :
90 else
91 echo "CBMC returned ${cbmc_exit_status} exit status" 1>&2
92
93 # Parse errors have exit status 6. Any other type of error
94 # should be considered a hard error.
95 if test ${cbmc_exit_status} -ne 6 && \
96 test ${cbmc_exit_status} -ne 10; then
97 exit 99
98 else
99 exit 1
100 fi
101 fi
102fi
diff --git a/tools/testing/selftests/seccomp/Makefile b/tools/testing/selftests/seccomp/Makefile
index 8401e87e34e1..5fa6fd2246b1 100644
--- a/tools/testing/selftests/seccomp/Makefile
+++ b/tools/testing/selftests/seccomp/Makefile
@@ -1,10 +1,6 @@
1TEST_PROGS := seccomp_bpf 1TEST_GEN_PROGS := seccomp_bpf
2CFLAGS += -Wl,-no-as-needed -Wall 2CFLAGS += -Wl,-no-as-needed -Wall
3LDFLAGS += -lpthread 3LDFLAGS += -lpthread
4 4
5all: $(TEST_PROGS)
6
7include ../lib.mk 5include ../lib.mk
8 6
9clean:
10 $(RM) $(TEST_PROGS)
diff --git a/tools/testing/selftests/sigaltstack/Makefile b/tools/testing/selftests/sigaltstack/Makefile
index 56af56eda6fa..f68fbf80d8be 100644
--- a/tools/testing/selftests/sigaltstack/Makefile
+++ b/tools/testing/selftests/sigaltstack/Makefile
@@ -1,8 +1,5 @@
1CFLAGS = -Wall 1CFLAGS = -Wall
2BINARIES = sas 2TEST_GEN_PROGS = sas
3all: $(BINARIES)
4 3
5include ../lib.mk 4include ../lib.mk
6 5
7clean:
8 rm -rf $(BINARIES)
diff --git a/tools/testing/selftests/sigaltstack/sas.c b/tools/testing/selftests/sigaltstack/sas.c
index 1bb01258e559..ccd07343d418 100644
--- a/tools/testing/selftests/sigaltstack/sas.c
+++ b/tools/testing/selftests/sigaltstack/sas.c
@@ -57,7 +57,7 @@ void my_usr1(int sig, siginfo_t *si, void *u)
57 exit(EXIT_FAILURE); 57 exit(EXIT_FAILURE);
58 } 58 }
59 if (stk.ss_flags != SS_DISABLE) 59 if (stk.ss_flags != SS_DISABLE)
60 printf("[FAIL]\tss_flags=%i, should be SS_DISABLE\n", 60 printf("[FAIL]\tss_flags=%x, should be SS_DISABLE\n",
61 stk.ss_flags); 61 stk.ss_flags);
62 else 62 else
63 printf("[OK]\tsigaltstack is disabled in sighandler\n"); 63 printf("[OK]\tsigaltstack is disabled in sighandler\n");
@@ -122,7 +122,8 @@ int main(void)
122 if (stk.ss_flags == SS_DISABLE) { 122 if (stk.ss_flags == SS_DISABLE) {
123 printf("[OK]\tInitial sigaltstack state was SS_DISABLE\n"); 123 printf("[OK]\tInitial sigaltstack state was SS_DISABLE\n");
124 } else { 124 } else {
125 printf("[FAIL]\tInitial sigaltstack state was %i; should have been SS_DISABLE\n", stk.ss_flags); 125 printf("[FAIL]\tInitial sigaltstack state was %x; "
126 "should have been SS_DISABLE\n", stk.ss_flags);
126 return EXIT_FAILURE; 127 return EXIT_FAILURE;
127 } 128 }
128 129
@@ -165,7 +166,7 @@ int main(void)
165 exit(EXIT_FAILURE); 166 exit(EXIT_FAILURE);
166 } 167 }
167 if (stk.ss_flags != SS_AUTODISARM) { 168 if (stk.ss_flags != SS_AUTODISARM) {
168 printf("[FAIL]\tss_flags=%i, should be SS_AUTODISARM\n", 169 printf("[FAIL]\tss_flags=%x, should be SS_AUTODISARM\n",
169 stk.ss_flags); 170 stk.ss_flags);
170 exit(EXIT_FAILURE); 171 exit(EXIT_FAILURE);
171 } 172 }
diff --git a/tools/testing/selftests/size/Makefile b/tools/testing/selftests/size/Makefile
index bbd0b5398b61..4685b3e421fc 100644
--- a/tools/testing/selftests/size/Makefile
+++ b/tools/testing/selftests/size/Makefile
@@ -1,11 +1,5 @@
1all: get_size 1CFLAGS := -static -ffreestanding -nostartfiles -s
2 2
3get_size: get_size.c 3TEST_GEN_PROGS := get_size
4 $(CC) -static -ffreestanding -nostartfiles -s $< -o $@
5
6TEST_PROGS := get_size
7 4
8include ../lib.mk 5include ../lib.mk
9
10clean:
11 $(RM) get_size
diff --git a/tools/testing/selftests/splice/Makefile b/tools/testing/selftests/splice/Makefile
new file mode 100644
index 000000000000..de51f439d4a6
--- /dev/null
+++ b/tools/testing/selftests/splice/Makefile
@@ -0,0 +1,8 @@
1TEST_PROGS := default_file_splice_read.sh
2EXTRA := default_file_splice_read
3all: $(TEST_PROGS) $(EXTRA)
4
5include ../lib.mk
6
7clean:
8 rm -fr $(TEST_PROGS) $(EXTRA)
diff --git a/tools/testing/selftests/splice/default_file_splice_read.c b/tools/testing/selftests/splice/default_file_splice_read.c
new file mode 100644
index 000000000000..01dd6091554c
--- /dev/null
+++ b/tools/testing/selftests/splice/default_file_splice_read.c
@@ -0,0 +1,8 @@
1#define _GNU_SOURCE
2#include <fcntl.h>
3
4int main(int argc, char **argv)
5{
6 splice(0, 0, 1, 0, 1<<30, 0);
7 return 0;
8}
diff --git a/tools/testing/selftests/splice/default_file_splice_read.sh b/tools/testing/selftests/splice/default_file_splice_read.sh
new file mode 100755
index 000000000000..1ea2adeabc94
--- /dev/null
+++ b/tools/testing/selftests/splice/default_file_splice_read.sh
@@ -0,0 +1,7 @@
1#!/bin/sh
2n=`./default_file_splice_read </dev/null | wc -c`
3
4test "$n" = 0 && exit 0
5
6echo "default_file_splice_read broken: leaked $n"
7exit 1
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile
index 1d5556869137..b90e50c36f9f 100644
--- a/tools/testing/selftests/timers/Makefile
+++ b/tools/testing/selftests/timers/Makefile
@@ -1,20 +1,16 @@
1CC = $(CROSS_COMPILE)gcc
2BUILD_FLAGS = -DKTEST 1BUILD_FLAGS = -DKTEST
3CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS) 2CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS)
4LDFLAGS += -lrt -lpthread 3LDFLAGS += -lrt -lpthread
5 4
6# these are all "safe" tests that don't modify 5# these are all "safe" tests that don't modify
7# system time or require escalated privledges 6# system time or require escalated privledges
8TEST_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \ 7TEST_GEN_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
9 inconsistency-check raw_skew threadtest rtctest 8 inconsistency-check raw_skew threadtest rtctest
10 9
11TEST_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \ 10TEST_GEN_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \
12 skew_consistency clocksource-switch leap-a-day \ 11 skew_consistency clocksource-switch leap-a-day \
13 leapcrash set-tai set-2038 set-tz 12 leapcrash set-tai set-2038 set-tz
14 13
15bins = $(TEST_PROGS) $(TEST_PROGS_EXTENDED)
16
17all: ${bins}
18 14
19include ../lib.mk 15include ../lib.mk
20 16
@@ -34,5 +30,3 @@ run_destructive_tests: run_tests
34 ./set-tai 30 ./set-tai
35 ./set-2038 31 ./set-2038
36 32
37clean:
38 rm -f ${bins}
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index bbab7f4664ac..4cff7e7ddcc4 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -1,33 +1,33 @@
1# Makefile for vm selftests 1# Makefile for vm selftests
2 2
3CFLAGS = -Wall -I ../../../../usr/include $(EXTRA_CFLAGS) 3CFLAGS = -Wall -I ../../../../usr/include $(EXTRA_CFLAGS)
4BINARIES = compaction_test 4LDLIBS = -lrt
5BINARIES += hugepage-mmap 5TEST_GEN_FILES = compaction_test
6BINARIES += hugepage-shm 6TEST_GEN_FILES += hugepage-mmap
7BINARIES += map_hugetlb 7TEST_GEN_FILES += hugepage-shm
8BINARIES += mlock2-tests 8TEST_GEN_FILES += map_hugetlb
9BINARIES += on-fault-limit 9TEST_GEN_FILES += mlock2-tests
10BINARIES += thuge-gen 10TEST_GEN_FILES += on-fault-limit
11BINARIES += transhuge-stress 11TEST_GEN_FILES += thuge-gen
12BINARIES += userfaultfd 12TEST_GEN_FILES += transhuge-stress
13BINARIES += mlock-random-test 13TEST_GEN_FILES += userfaultfd
14 14TEST_GEN_FILES += userfaultfd_hugetlb
15all: $(BINARIES) 15TEST_GEN_FILES += userfaultfd_shmem
16%: %.c 16TEST_GEN_FILES += mlock-random-test
17 $(CC) $(CFLAGS) -o $@ $^ -lrt
18userfaultfd: userfaultfd.c ../../../../usr/include/linux/kernel.h
19 $(CC) $(CFLAGS) -O2 -o $@ $< -lpthread
20
21mlock-random-test: mlock-random-test.c
22 $(CC) $(CFLAGS) -o $@ $< -lcap
23
24../../../../usr/include/linux/kernel.h:
25 make -C ../../../.. headers_install
26 17
27TEST_PROGS := run_vmtests 18TEST_PROGS := run_vmtests
28TEST_FILES := $(BINARIES)
29 19
30include ../lib.mk 20include ../lib.mk
31 21
32clean: 22$(OUTPUT)/userfaultfd: LDLIBS += -lpthread ../../../../usr/include/linux/kernel.h
33 $(RM) $(BINARIES) 23
24$(OUTPUT)/userfaultfd_hugetlb: userfaultfd.c ../../../../usr/include/linux/kernel.h
25 $(CC) $(CFLAGS) -DHUGETLB_TEST -O2 -o $@ $< -lpthread
26
27$(OUTPUT)/userfaultfd_shmem: userfaultfd.c ../../../../usr/include/linux/kernel.h
28 $(CC) $(CFLAGS) -DSHMEM_TEST -O2 -o $@ $< -lpthread
29
30$(OUTPUT)/mlock-random-test: LDLIBS += -lcap
31
32../../../../usr/include/linux/kernel.h:
33 make -C ../../../.. headers_install
diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
index e11968b3677e..c92f6cf31d0a 100755
--- a/tools/testing/selftests/vm/run_vmtests
+++ b/tools/testing/selftests/vm/run_vmtests
@@ -103,6 +103,30 @@ else
103 echo "[PASS]" 103 echo "[PASS]"
104fi 104fi
105 105
106echo "----------------------------"
107echo "running userfaultfd_hugetlb"
108echo "----------------------------"
109# 258MB total huge pages == 128MB src and 128MB dst
110./userfaultfd_hugetlb 128 32 $mnt/ufd_test_file
111if [ $? -ne 0 ]; then
112 echo "[FAIL]"
113 exitcode=1
114else
115 echo "[PASS]"
116fi
117rm -f $mnt/ufd_test_file
118
119echo "----------------------------"
120echo "running userfaultfd_shmem"
121echo "----------------------------"
122./userfaultfd_shmem 128 32
123if [ $? -ne 0 ]; then
124 echo "[FAIL]"
125 exitcode=1
126else
127 echo "[PASS]"
128fi
129
106#cleanup 130#cleanup
107umount $mnt 131umount $mnt
108rm -rf $mnt 132rm -rf $mnt
diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c
index d77ed41b2094..e9449c801888 100644
--- a/tools/testing/selftests/vm/userfaultfd.c
+++ b/tools/testing/selftests/vm/userfaultfd.c
@@ -63,6 +63,7 @@
63#include <sys/mman.h> 63#include <sys/mman.h>
64#include <sys/syscall.h> 64#include <sys/syscall.h>
65#include <sys/ioctl.h> 65#include <sys/ioctl.h>
66#include <sys/wait.h>
66#include <pthread.h> 67#include <pthread.h>
67#include <linux/userfaultfd.h> 68#include <linux/userfaultfd.h>
68 69
@@ -76,8 +77,12 @@ static unsigned long nr_cpus, nr_pages, nr_pages_per_cpu, page_size;
76#define BOUNCE_POLL (1<<3) 77#define BOUNCE_POLL (1<<3)
77static int bounces; 78static int bounces;
78 79
80#ifdef HUGETLB_TEST
81static int huge_fd;
82static char *huge_fd_off0;
83#endif
79static unsigned long long *count_verify; 84static unsigned long long *count_verify;
80static int uffd, finished, *pipefd; 85static int uffd, uffd_flags, finished, *pipefd;
81static char *area_src, *area_dst; 86static char *area_src, *area_dst;
82static char *zeropage; 87static char *zeropage;
83pthread_attr_t attr; 88pthread_attr_t attr;
@@ -97,6 +102,102 @@ pthread_attr_t attr;
97 ~(unsigned long)(sizeof(unsigned long long) \ 102 ~(unsigned long)(sizeof(unsigned long long) \
98 - 1))) 103 - 1)))
99 104
105#if !defined(HUGETLB_TEST) && !defined(SHMEM_TEST)
106
107/* Anonymous memory */
108#define EXPECTED_IOCTLS ((1 << _UFFDIO_WAKE) | \
109 (1 << _UFFDIO_COPY) | \
110 (1 << _UFFDIO_ZEROPAGE))
111
112static int release_pages(char *rel_area)
113{
114 int ret = 0;
115
116 if (madvise(rel_area, nr_pages * page_size, MADV_DONTNEED)) {
117 perror("madvise");
118 ret = 1;
119 }
120
121 return ret;
122}
123
124static void allocate_area(void **alloc_area)
125{
126 if (posix_memalign(alloc_area, page_size, nr_pages * page_size)) {
127 fprintf(stderr, "out of memory\n");
128 *alloc_area = NULL;
129 }
130}
131
132#else /* HUGETLB_TEST or SHMEM_TEST */
133
134#define EXPECTED_IOCTLS UFFD_API_RANGE_IOCTLS_BASIC
135
136#ifdef HUGETLB_TEST
137
138/* HugeTLB memory */
139static int release_pages(char *rel_area)
140{
141 int ret = 0;
142
143 if (fallocate(huge_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
144 rel_area == huge_fd_off0 ? 0 :
145 nr_pages * page_size,
146 nr_pages * page_size)) {
147 perror("fallocate");
148 ret = 1;
149 }
150
151 return ret;
152}
153
154
155static void allocate_area(void **alloc_area)
156{
157 *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
158 MAP_PRIVATE | MAP_HUGETLB, huge_fd,
159 *alloc_area == area_src ? 0 :
160 nr_pages * page_size);
161 if (*alloc_area == MAP_FAILED) {
162 fprintf(stderr, "mmap of hugetlbfs file failed\n");
163 *alloc_area = NULL;
164 }
165
166 if (*alloc_area == area_src)
167 huge_fd_off0 = *alloc_area;
168}
169
170#elif defined(SHMEM_TEST)
171
172/* Shared memory */
173static int release_pages(char *rel_area)
174{
175 int ret = 0;
176
177 if (madvise(rel_area, nr_pages * page_size, MADV_REMOVE)) {
178 perror("madvise");
179 ret = 1;
180 }
181
182 return ret;
183}
184
185static void allocate_area(void **alloc_area)
186{
187 *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
188 MAP_ANONYMOUS | MAP_SHARED, -1, 0);
189 if (*alloc_area == MAP_FAILED) {
190 fprintf(stderr, "shared memory mmap failed\n");
191 *alloc_area = NULL;
192 }
193}
194
195#else /* SHMEM_TEST */
196#error "Undefined test type"
197#endif /* HUGETLB_TEST */
198
199#endif /* !defined(HUGETLB_TEST) && !defined(SHMEM_TEST) */
200
100static int my_bcmp(char *str1, char *str2, size_t n) 201static int my_bcmp(char *str1, char *str2, size_t n)
101{ 202{
102 unsigned long i; 203 unsigned long i;
@@ -217,7 +318,7 @@ static void *locking_thread(void *arg)
217 return NULL; 318 return NULL;
218} 319}
219 320
220static int copy_page(unsigned long offset) 321static int copy_page(int ufd, unsigned long offset)
221{ 322{
222 struct uffdio_copy uffdio_copy; 323 struct uffdio_copy uffdio_copy;
223 324
@@ -229,7 +330,7 @@ static int copy_page(unsigned long offset)
229 uffdio_copy.len = page_size; 330 uffdio_copy.len = page_size;
230 uffdio_copy.mode = 0; 331 uffdio_copy.mode = 0;
231 uffdio_copy.copy = 0; 332 uffdio_copy.copy = 0;
232 if (ioctl(uffd, UFFDIO_COPY, &uffdio_copy)) { 333 if (ioctl(ufd, UFFDIO_COPY, &uffdio_copy)) {
233 /* real retval in ufdio_copy.copy */ 334 /* real retval in ufdio_copy.copy */
234 if (uffdio_copy.copy != -EEXIST) 335 if (uffdio_copy.copy != -EEXIST)
235 fprintf(stderr, "UFFDIO_COPY error %Ld\n", 336 fprintf(stderr, "UFFDIO_COPY error %Ld\n",
@@ -247,6 +348,7 @@ static void *uffd_poll_thread(void *arg)
247 unsigned long cpu = (unsigned long) arg; 348 unsigned long cpu = (unsigned long) arg;
248 struct pollfd pollfd[2]; 349 struct pollfd pollfd[2];
249 struct uffd_msg msg; 350 struct uffd_msg msg;
351 struct uffdio_register uffd_reg;
250 int ret; 352 int ret;
251 unsigned long offset; 353 unsigned long offset;
252 char tmp_chr; 354 char tmp_chr;
@@ -278,16 +380,35 @@ static void *uffd_poll_thread(void *arg)
278 continue; 380 continue;
279 perror("nonblocking read error"), exit(1); 381 perror("nonblocking read error"), exit(1);
280 } 382 }
281 if (msg.event != UFFD_EVENT_PAGEFAULT) 383 switch (msg.event) {
384 default:
282 fprintf(stderr, "unexpected msg event %u\n", 385 fprintf(stderr, "unexpected msg event %u\n",
283 msg.event), exit(1); 386 msg.event), exit(1);
284 if (msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE) 387 break;
285 fprintf(stderr, "unexpected write fault\n"), exit(1); 388 case UFFD_EVENT_PAGEFAULT:
286 offset = (char *)(unsigned long)msg.arg.pagefault.address - 389 if (msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)
287 area_dst; 390 fprintf(stderr, "unexpected write fault\n"), exit(1);
288 offset &= ~(page_size-1); 391 offset = (char *)(unsigned long)msg.arg.pagefault.address -
289 if (copy_page(offset)) 392 area_dst;
290 userfaults++; 393 offset &= ~(page_size-1);
394 if (copy_page(uffd, offset))
395 userfaults++;
396 break;
397 case UFFD_EVENT_FORK:
398 uffd = msg.arg.fork.ufd;
399 pollfd[0].fd = uffd;
400 break;
401 case UFFD_EVENT_REMOVE:
402 uffd_reg.range.start = msg.arg.remove.start;
403 uffd_reg.range.len = msg.arg.remove.end -
404 msg.arg.remove.start;
405 if (ioctl(uffd, UFFDIO_UNREGISTER, &uffd_reg.range))
406 fprintf(stderr, "remove failure\n"), exit(1);
407 break;
408 case UFFD_EVENT_REMAP:
409 area_dst = (char *)(unsigned long)msg.arg.remap.to;
410 break;
411 }
291 } 412 }
292 return (void *)userfaults; 413 return (void *)userfaults;
293} 414}
@@ -324,7 +445,7 @@ static void *uffd_read_thread(void *arg)
324 offset = (char *)(unsigned long)msg.arg.pagefault.address - 445 offset = (char *)(unsigned long)msg.arg.pagefault.address -
325 area_dst; 446 area_dst;
326 offset &= ~(page_size-1); 447 offset &= ~(page_size-1);
327 if (copy_page(offset)) 448 if (copy_page(uffd, offset))
328 (*this_cpu_userfaults)++; 449 (*this_cpu_userfaults)++;
329 } 450 }
330 return (void *)NULL; 451 return (void *)NULL;
@@ -338,7 +459,7 @@ static void *background_thread(void *arg)
338 for (page_nr = cpu * nr_pages_per_cpu; 459 for (page_nr = cpu * nr_pages_per_cpu;
339 page_nr < (cpu+1) * nr_pages_per_cpu; 460 page_nr < (cpu+1) * nr_pages_per_cpu;
340 page_nr++) 461 page_nr++)
341 copy_page(page_nr * page_size); 462 copy_page(uffd, page_nr * page_size);
342 463
343 return NULL; 464 return NULL;
344} 465}
@@ -384,10 +505,8 @@ static int stress(unsigned long *userfaults)
384 * UFFDIO_COPY without writing zero pages into area_dst 505 * UFFDIO_COPY without writing zero pages into area_dst
385 * because the background threads already completed). 506 * because the background threads already completed).
386 */ 507 */
387 if (madvise(area_src, nr_pages * page_size, MADV_DONTNEED)) { 508 if (release_pages(area_src))
388 perror("madvise");
389 return 1; 509 return 1;
390 }
391 510
392 for (cpu = 0; cpu < nr_cpus; cpu++) { 511 for (cpu = 0; cpu < nr_cpus; cpu++) {
393 char c; 512 char c;
@@ -414,27 +533,9 @@ static int stress(unsigned long *userfaults)
414 return 0; 533 return 0;
415} 534}
416 535
417static int userfaultfd_stress(void) 536static int userfaultfd_open(int features)
418{ 537{
419 void *area;
420 char *tmp_area;
421 unsigned long nr;
422 struct uffdio_register uffdio_register;
423 struct uffdio_api uffdio_api; 538 struct uffdio_api uffdio_api;
424 unsigned long cpu;
425 int uffd_flags, err;
426 unsigned long userfaults[nr_cpus];
427
428 if (posix_memalign(&area, page_size, nr_pages * page_size)) {
429 fprintf(stderr, "out of memory\n");
430 return 1;
431 }
432 area_src = area;
433 if (posix_memalign(&area, page_size, nr_pages * page_size)) {
434 fprintf(stderr, "out of memory\n");
435 return 1;
436 }
437 area_dst = area;
438 539
439 uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK); 540 uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
440 if (uffd < 0) { 541 if (uffd < 0) {
@@ -445,7 +546,7 @@ static int userfaultfd_stress(void)
445 uffd_flags = fcntl(uffd, F_GETFD, NULL); 546 uffd_flags = fcntl(uffd, F_GETFD, NULL);
446 547
447 uffdio_api.api = UFFD_API; 548 uffdio_api.api = UFFD_API;
448 uffdio_api.features = 0; 549 uffdio_api.features = features;
449 if (ioctl(uffd, UFFDIO_API, &uffdio_api)) { 550 if (ioctl(uffd, UFFDIO_API, &uffdio_api)) {
450 fprintf(stderr, "UFFDIO_API\n"); 551 fprintf(stderr, "UFFDIO_API\n");
451 return 1; 552 return 1;
@@ -455,6 +556,233 @@ static int userfaultfd_stress(void)
455 return 1; 556 return 1;
456 } 557 }
457 558
559 return 0;
560}
561
562/*
563 * For non-cooperative userfaultfd test we fork() a process that will
564 * generate pagefaults, will mremap the area monitored by the
565 * userfaultfd and at last this process will release the monitored
566 * area.
567 * For the anonymous and shared memory the area is divided into two
568 * parts, the first part is accessed before mremap, and the second
569 * part is accessed after mremap. Since hugetlbfs does not support
570 * mremap, the entire monitored area is accessed in a single pass for
571 * HUGETLB_TEST.
572 * The release of the pages currently generates event for shmem and
573 * anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked
574 * for hugetlb.
575 */
576static int faulting_process(void)
577{
578 unsigned long nr;
579 unsigned long long count;
580
581#ifndef HUGETLB_TEST
582 unsigned long split_nr_pages = (nr_pages + 1) / 2;
583#else
584 unsigned long split_nr_pages = nr_pages;
585#endif
586
587 for (nr = 0; nr < split_nr_pages; nr++) {
588 count = *area_count(area_dst, nr);
589 if (count != count_verify[nr]) {
590 fprintf(stderr,
591 "nr %lu memory corruption %Lu %Lu\n",
592 nr, count,
593 count_verify[nr]), exit(1);
594 }
595 }
596
597#ifndef HUGETLB_TEST
598 area_dst = mremap(area_dst, nr_pages * page_size, nr_pages * page_size,
599 MREMAP_MAYMOVE | MREMAP_FIXED, area_src);
600 if (area_dst == MAP_FAILED)
601 perror("mremap"), exit(1);
602
603 for (; nr < nr_pages; nr++) {
604 count = *area_count(area_dst, nr);
605 if (count != count_verify[nr]) {
606 fprintf(stderr,
607 "nr %lu memory corruption %Lu %Lu\n",
608 nr, count,
609 count_verify[nr]), exit(1);
610 }
611 }
612
613 if (release_pages(area_dst))
614 return 1;
615
616 for (nr = 0; nr < nr_pages; nr++) {
617 if (my_bcmp(area_dst + nr * page_size, zeropage, page_size))
618 fprintf(stderr, "nr %lu is not zero\n", nr), exit(1);
619 }
620
621#endif /* HUGETLB_TEST */
622
623 return 0;
624}
625
626static int uffdio_zeropage(int ufd, unsigned long offset)
627{
628 struct uffdio_zeropage uffdio_zeropage;
629 int ret;
630 unsigned long has_zeropage = EXPECTED_IOCTLS & (1 << _UFFDIO_ZEROPAGE);
631
632 if (offset >= nr_pages * page_size)
633 fprintf(stderr, "unexpected offset %lu\n",
634 offset), exit(1);
635 uffdio_zeropage.range.start = (unsigned long) area_dst + offset;
636 uffdio_zeropage.range.len = page_size;
637 uffdio_zeropage.mode = 0;
638 ret = ioctl(ufd, UFFDIO_ZEROPAGE, &uffdio_zeropage);
639 if (ret) {
640 /* real retval in ufdio_zeropage.zeropage */
641 if (has_zeropage) {
642 if (uffdio_zeropage.zeropage == -EEXIST)
643 fprintf(stderr, "UFFDIO_ZEROPAGE -EEXIST\n"),
644 exit(1);
645 else
646 fprintf(stderr, "UFFDIO_ZEROPAGE error %Ld\n",
647 uffdio_zeropage.zeropage), exit(1);
648 } else {
649 if (uffdio_zeropage.zeropage != -EINVAL)
650 fprintf(stderr,
651 "UFFDIO_ZEROPAGE not -EINVAL %Ld\n",
652 uffdio_zeropage.zeropage), exit(1);
653 }
654 } else if (has_zeropage) {
655 if (uffdio_zeropage.zeropage != page_size) {
656 fprintf(stderr, "UFFDIO_ZEROPAGE unexpected %Ld\n",
657 uffdio_zeropage.zeropage), exit(1);
658 } else
659 return 1;
660 } else {
661 fprintf(stderr,
662 "UFFDIO_ZEROPAGE succeeded %Ld\n",
663 uffdio_zeropage.zeropage), exit(1);
664 }
665
666 return 0;
667}
668
669/* exercise UFFDIO_ZEROPAGE */
670static int userfaultfd_zeropage_test(void)
671{
672 struct uffdio_register uffdio_register;
673 unsigned long expected_ioctls;
674
675 printf("testing UFFDIO_ZEROPAGE: ");
676 fflush(stdout);
677
678 if (release_pages(area_dst))
679 return 1;
680
681 if (userfaultfd_open(0) < 0)
682 return 1;
683 uffdio_register.range.start = (unsigned long) area_dst;
684 uffdio_register.range.len = nr_pages * page_size;
685 uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
686 if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
687 fprintf(stderr, "register failure\n"), exit(1);
688
689 expected_ioctls = EXPECTED_IOCTLS;
690 if ((uffdio_register.ioctls & expected_ioctls) !=
691 expected_ioctls)
692 fprintf(stderr,
693 "unexpected missing ioctl for anon memory\n"),
694 exit(1);
695
696 if (uffdio_zeropage(uffd, 0)) {
697 if (my_bcmp(area_dst, zeropage, page_size))
698 fprintf(stderr, "zeropage is not zero\n"), exit(1);
699 }
700
701 close(uffd);
702 printf("done.\n");
703 return 0;
704}
705
706static int userfaultfd_events_test(void)
707{
708 struct uffdio_register uffdio_register;
709 unsigned long expected_ioctls;
710 unsigned long userfaults;
711 pthread_t uffd_mon;
712 int err, features;
713 pid_t pid;
714 char c;
715
716 printf("testing events (fork, remap, remove): ");
717 fflush(stdout);
718
719 if (release_pages(area_dst))
720 return 1;
721
722 features = UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_EVENT_REMAP |
723 UFFD_FEATURE_EVENT_REMOVE;
724 if (userfaultfd_open(features) < 0)
725 return 1;
726 fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
727
728 uffdio_register.range.start = (unsigned long) area_dst;
729 uffdio_register.range.len = nr_pages * page_size;
730 uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
731 if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
732 fprintf(stderr, "register failure\n"), exit(1);
733
734 expected_ioctls = EXPECTED_IOCTLS;
735 if ((uffdio_register.ioctls & expected_ioctls) !=
736 expected_ioctls)
737 fprintf(stderr,
738 "unexpected missing ioctl for anon memory\n"),
739 exit(1);
740
741 if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, NULL))
742 perror("uffd_poll_thread create"), exit(1);
743
744 pid = fork();
745 if (pid < 0)
746 perror("fork"), exit(1);
747
748 if (!pid)
749 return faulting_process();
750
751 waitpid(pid, &err, 0);
752 if (err)
753 fprintf(stderr, "faulting process failed\n"), exit(1);
754
755 if (write(pipefd[1], &c, sizeof(c)) != sizeof(c))
756 perror("pipe write"), exit(1);
757 if (pthread_join(uffd_mon, (void **)&userfaults))
758 return 1;
759
760 close(uffd);
761 printf("userfaults: %ld\n", userfaults);
762
763 return userfaults != nr_pages;
764}
765
766static int userfaultfd_stress(void)
767{
768 void *area;
769 char *tmp_area;
770 unsigned long nr;
771 struct uffdio_register uffdio_register;
772 unsigned long cpu;
773 int err;
774 unsigned long userfaults[nr_cpus];
775
776 allocate_area((void **)&area_src);
777 if (!area_src)
778 return 1;
779 allocate_area((void **)&area_dst);
780 if (!area_dst)
781 return 1;
782
783 if (userfaultfd_open(0) < 0)
784 return 1;
785
458 count_verify = malloc(nr_pages * sizeof(unsigned long long)); 786 count_verify = malloc(nr_pages * sizeof(unsigned long long));
459 if (!count_verify) { 787 if (!count_verify) {
460 perror("count_verify"); 788 perror("count_verify");
@@ -528,9 +856,7 @@ static int userfaultfd_stress(void)
528 fprintf(stderr, "register failure\n"); 856 fprintf(stderr, "register failure\n");
529 return 1; 857 return 1;
530 } 858 }
531 expected_ioctls = (1 << _UFFDIO_WAKE) | 859 expected_ioctls = EXPECTED_IOCTLS;
532 (1 << _UFFDIO_COPY) |
533 (1 << _UFFDIO_ZEROPAGE);
534 if ((uffdio_register.ioctls & expected_ioctls) != 860 if ((uffdio_register.ioctls & expected_ioctls) !=
535 expected_ioctls) { 861 expected_ioctls) {
536 fprintf(stderr, 862 fprintf(stderr,
@@ -562,10 +888,8 @@ static int userfaultfd_stress(void)
562 * MADV_DONTNEED only after the UFFDIO_REGISTER, so it's 888 * MADV_DONTNEED only after the UFFDIO_REGISTER, so it's
563 * required to MADV_DONTNEED here. 889 * required to MADV_DONTNEED here.
564 */ 890 */
565 if (madvise(area_dst, nr_pages * page_size, MADV_DONTNEED)) { 891 if (release_pages(area_dst))
566 perror("madvise 2");
567 return 1; 892 return 1;
568 }
569 893
570 /* bounce pass */ 894 /* bounce pass */
571 if (stress(userfaults)) 895 if (stress(userfaults))
@@ -603,9 +927,15 @@ static int userfaultfd_stress(void)
603 printf("\n"); 927 printf("\n");
604 } 928 }
605 929
606 return err; 930 if (err)
931 return err;
932
933 close(uffd);
934 return userfaultfd_zeropage_test() || userfaultfd_events_test();
607} 935}
608 936
937#ifndef HUGETLB_TEST
938
609int main(int argc, char **argv) 939int main(int argc, char **argv)
610{ 940{
611 if (argc < 3) 941 if (argc < 3)
@@ -632,6 +962,74 @@ int main(int argc, char **argv)
632 return userfaultfd_stress(); 962 return userfaultfd_stress();
633} 963}
634 964
965#else /* HUGETLB_TEST */
966
967/*
968 * Copied from mlock2-tests.c
969 */
970unsigned long default_huge_page_size(void)
971{
972 unsigned long hps = 0;
973 char *line = NULL;
974 size_t linelen = 0;
975 FILE *f = fopen("/proc/meminfo", "r");
976
977 if (!f)
978 return 0;
979 while (getline(&line, &linelen, f) > 0) {
980 if (sscanf(line, "Hugepagesize: %lu kB", &hps) == 1) {
981 hps <<= 10;
982 break;
983 }
984 }
985
986 free(line);
987 fclose(f);
988 return hps;
989}
990
991int main(int argc, char **argv)
992{
993 if (argc < 4)
994 fprintf(stderr, "Usage: <MiB> <bounces> <hugetlbfs_file>\n"),
995 exit(1);
996 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
997 page_size = default_huge_page_size();
998 if (!page_size)
999 fprintf(stderr, "Unable to determine huge page size\n"),
1000 exit(2);
1001 if ((unsigned long) area_count(NULL, 0) + sizeof(unsigned long long) * 2
1002 > page_size)
1003 fprintf(stderr, "Impossible to run this test\n"), exit(2);
1004 nr_pages_per_cpu = atol(argv[1]) * 1024*1024 / page_size /
1005 nr_cpus;
1006 if (!nr_pages_per_cpu) {
1007 fprintf(stderr, "invalid MiB\n");
1008 fprintf(stderr, "Usage: <MiB> <bounces>\n"), exit(1);
1009 }
1010 bounces = atoi(argv[2]);
1011 if (bounces <= 0) {
1012 fprintf(stderr, "invalid bounces\n");
1013 fprintf(stderr, "Usage: <MiB> <bounces>\n"), exit(1);
1014 }
1015 nr_pages = nr_pages_per_cpu * nr_cpus;
1016 huge_fd = open(argv[3], O_CREAT | O_RDWR, 0755);
1017 if (huge_fd < 0) {
1018 fprintf(stderr, "Open of %s failed", argv[3]);
1019 perror("open");
1020 exit(1);
1021 }
1022 if (ftruncate(huge_fd, 0)) {
1023 fprintf(stderr, "ftruncate %s to size 0 failed", argv[3]);
1024 perror("ftruncate");
1025 exit(1);
1026 }
1027 printf("nr_pages: %lu, nr_pages_per_cpu: %lu\n",
1028 nr_pages, nr_pages_per_cpu);
1029 return userfaultfd_stress();
1030}
1031
1032#endif
635#else /* __NR_userfaultfd */ 1033#else /* __NR_userfaultfd */
636 1034
637#warning "missing __NR_userfaultfd definition" 1035#warning "missing __NR_userfaultfd definition"
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index 8c1cb423cfe6..38e0a9ca5d71 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -5,18 +5,21 @@ include ../lib.mk
5.PHONY: all all_32 all_64 warn_32bit_failure clean 5.PHONY: all all_32 all_64 warn_32bit_failure clean
6 6
7TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall test_mremap_vdso \ 7TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall test_mremap_vdso \
8 check_initial_reg_state sigreturn ldt_gdt iopl \ 8 check_initial_reg_state sigreturn ldt_gdt iopl mpx-mini-test ioperm \
9 protection_keys test_vdso 9 protection_keys test_vdso
10TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ 10TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \
11 test_FCMOV test_FCOMI test_FISTTP \ 11 test_FCMOV test_FCOMI test_FISTTP \
12 vdso_restorer 12 vdso_restorer
13TARGETS_C_64BIT_ONLY := fsgsbase 13TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip
14 14
15TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) 15TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
16TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY) 16TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY)
17BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32) 17BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32)
18BINARIES_64 := $(TARGETS_C_64BIT_ALL:%=%_64) 18BINARIES_64 := $(TARGETS_C_64BIT_ALL:%=%_64)
19 19
20BINARIES_32 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_32))
21BINARIES_64 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_64))
22
20CFLAGS := -O2 -g -std=gnu99 -pthread -Wall 23CFLAGS := -O2 -g -std=gnu99 -pthread -Wall
21 24
22UNAME_M := $(shell uname -m) 25UNAME_M := $(shell uname -m)
@@ -40,10 +43,10 @@ all_64: $(BINARIES_64)
40clean: 43clean:
41 $(RM) $(BINARIES_32) $(BINARIES_64) 44 $(RM) $(BINARIES_32) $(BINARIES_64)
42 45
43$(TARGETS_C_32BIT_ALL:%=%_32): %_32: %.c 46$(BINARIES_32): $(OUTPUT)/%_32: %.c
44 $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm 47 $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm
45 48
46$(TARGETS_C_64BIT_ALL:%=%_64): %_64: %.c 49$(BINARIES_64): $(OUTPUT)/%_64: %.c
47 $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl 50 $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
48 51
49# x86_64 users should be encouraged to install 32-bit libraries 52# x86_64 users should be encouraged to install 32-bit libraries
@@ -65,12 +68,12 @@ warn_32bit_failure:
65endif 68endif
66 69
67# Some tests have additional dependencies. 70# Some tests have additional dependencies.
68sysret_ss_attrs_64: thunks.S 71$(OUTPUT)/sysret_ss_attrs_64: thunks.S
69ptrace_syscall_32: raw_syscall_helper_32.S 72$(OUTPUT)/ptrace_syscall_32: raw_syscall_helper_32.S
70test_syscall_vdso_32: thunks_32.S 73$(OUTPUT)/test_syscall_vdso_32: thunks_32.S
71 74
72# check_initial_reg_state is special: it needs a custom entry, and it 75# check_initial_reg_state is special: it needs a custom entry, and it
73# needs to be static so that its interpreter doesn't destroy its initial 76# needs to be static so that its interpreter doesn't destroy its initial
74# state. 77# state.
75check_initial_reg_state_32: CFLAGS += -Wl,-ereal_start -static 78$(OUTPUT)/check_initial_reg_state_32: CFLAGS += -Wl,-ereal_start -static
76check_initial_reg_state_64: CFLAGS += -Wl,-ereal_start -static 79$(OUTPUT)/check_initial_reg_state_64: CFLAGS += -Wl,-ereal_start -static
diff --git a/tools/testing/selftests/x86/ioperm.c b/tools/testing/selftests/x86/ioperm.c
new file mode 100644
index 000000000000..b77313ba2ab1
--- /dev/null
+++ b/tools/testing/selftests/x86/ioperm.c
@@ -0,0 +1,170 @@
1/*
2 * ioperm.c - Test case for ioperm(2)
3 * Copyright (c) 2015 Andrew Lutomirski
4 */
5
6#define _GNU_SOURCE
7#include <err.h>
8#include <stdio.h>
9#include <stdint.h>
10#include <signal.h>
11#include <setjmp.h>
12#include <stdlib.h>
13#include <string.h>
14#include <errno.h>
15#include <unistd.h>
16#include <sys/types.h>
17#include <sys/wait.h>
18#include <stdbool.h>
19#include <sched.h>
20#include <sys/io.h>
21
22static int nerrs = 0;
23
24static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
25 int flags)
26{
27 struct sigaction sa;
28 memset(&sa, 0, sizeof(sa));
29 sa.sa_sigaction = handler;
30 sa.sa_flags = SA_SIGINFO | flags;
31 sigemptyset(&sa.sa_mask);
32 if (sigaction(sig, &sa, 0))
33 err(1, "sigaction");
34
35}
36
37static void clearhandler(int sig)
38{
39 struct sigaction sa;
40 memset(&sa, 0, sizeof(sa));
41 sa.sa_handler = SIG_DFL;
42 sigemptyset(&sa.sa_mask);
43 if (sigaction(sig, &sa, 0))
44 err(1, "sigaction");
45}
46
47static jmp_buf jmpbuf;
48
49static void sigsegv(int sig, siginfo_t *si, void *ctx_void)
50{
51 siglongjmp(jmpbuf, 1);
52}
53
54static bool try_outb(unsigned short port)
55{
56 sethandler(SIGSEGV, sigsegv, SA_RESETHAND);
57 if (sigsetjmp(jmpbuf, 1) != 0) {
58 return false;
59 } else {
60 asm volatile ("outb %%al, %w[port]"
61 : : [port] "Nd" (port), "a" (0));
62 return true;
63 }
64 clearhandler(SIGSEGV);
65}
66
67static void expect_ok(unsigned short port)
68{
69 if (!try_outb(port)) {
70 printf("[FAIL]\toutb to 0x%02hx failed\n", port);
71 exit(1);
72 }
73
74 printf("[OK]\toutb to 0x%02hx worked\n", port);
75}
76
77static void expect_gp(unsigned short port)
78{
79 if (try_outb(port)) {
80 printf("[FAIL]\toutb to 0x%02hx worked\n", port);
81 exit(1);
82 }
83
84 printf("[OK]\toutb to 0x%02hx failed\n", port);
85}
86
87int main(void)
88{
89 cpu_set_t cpuset;
90 CPU_ZERO(&cpuset);
91 CPU_SET(0, &cpuset);
92 if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
93 err(1, "sched_setaffinity to CPU 0");
94
95 expect_gp(0x80);
96 expect_gp(0xed);
97
98 /*
99 * Probe for ioperm support. Note that clearing ioperm bits
100 * works even as nonroot.
101 */
102 printf("[RUN]\tenable 0x80\n");
103 if (ioperm(0x80, 1, 1) != 0) {
104 printf("[OK]\tioperm(0x80, 1, 1) failed (%d) -- try running as root\n",
105 errno);
106 return 0;
107 }
108 expect_ok(0x80);
109 expect_gp(0xed);
110
111 printf("[RUN]\tdisable 0x80\n");
112 if (ioperm(0x80, 1, 0) != 0) {
113 printf("[FAIL]\tioperm(0x80, 1, 0) failed (%d)", errno);
114 return 1;
115 }
116 expect_gp(0x80);
117 expect_gp(0xed);
118
119 /* Make sure that fork() preserves ioperm. */
120 if (ioperm(0x80, 1, 1) != 0) {
121 printf("[FAIL]\tioperm(0x80, 1, 0) failed (%d)", errno);
122 return 1;
123 }
124
125 pid_t child = fork();
126 if (child == -1)
127 err(1, "fork");
128
129 if (child == 0) {
130 printf("[RUN]\tchild: check that we inherited permissions\n");
131 expect_ok(0x80);
132 expect_gp(0xed);
133 return 0;
134 } else {
135 int status;
136 if (waitpid(child, &status, 0) != child ||
137 !WIFEXITED(status)) {
138 printf("[FAIL]\tChild died\n");
139 nerrs++;
140 } else if (WEXITSTATUS(status) != 0) {
141 printf("[FAIL]\tChild failed\n");
142 nerrs++;
143 } else {
144 printf("[OK]\tChild succeeded\n");
145 }
146 }
147
148 /* Test the capability checks. */
149
150 printf("\tDrop privileges\n");
151 if (setresuid(1, 1, 1) != 0) {
152 printf("[WARN]\tDropping privileges failed\n");
153 return 0;
154 }
155
156 printf("[RUN]\tdisable 0x80\n");
157 if (ioperm(0x80, 1, 0) != 0) {
158 printf("[FAIL]\tioperm(0x80, 1, 0) failed (%d)", errno);
159 return 1;
160 }
161 printf("[OK]\tit worked\n");
162
163 printf("[RUN]\tenable 0x80 again\n");
164 if (ioperm(0x80, 1, 1) == 0) {
165 printf("[FAIL]\tit succeeded but should have failed.\n");
166 return 1;
167 }
168 printf("[OK]\tit failed\n");
169 return 0;
170}
diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c
index df9e0a0cdf29..3237bc010e1c 100644
--- a/tools/testing/selftests/x86/protection_keys.c
+++ b/tools/testing/selftests/x86/protection_keys.c
@@ -192,7 +192,7 @@ void lots_o_noops_around_write(int *write_to_me)
192#define SYS_pkey_alloc 381 192#define SYS_pkey_alloc 381
193#define SYS_pkey_free 382 193#define SYS_pkey_free 382
194#define REG_IP_IDX REG_EIP 194#define REG_IP_IDX REG_EIP
195#define si_pkey_offset 0x18 195#define si_pkey_offset 0x14
196#else 196#else
197#define SYS_mprotect_key 329 197#define SYS_mprotect_key 329
198#define SYS_pkey_alloc 330 198#define SYS_pkey_alloc 330
@@ -462,7 +462,7 @@ void pkey_disable_set(int pkey, int flags)
462 unsigned long syscall_flags = 0; 462 unsigned long syscall_flags = 0;
463 int ret; 463 int ret;
464 int pkey_rights; 464 int pkey_rights;
465 u32 orig_pkru; 465 u32 orig_pkru = rdpkru();
466 466
467 dprintf1("START->%s(%d, 0x%x)\n", __func__, 467 dprintf1("START->%s(%d, 0x%x)\n", __func__,
468 pkey, flags); 468 pkey, flags);
@@ -812,8 +812,6 @@ void setup_hugetlbfs(void)
812{ 812{
813 int err; 813 int err;
814 int fd; 814 int fd;
815 int validated_nr_pages;
816 int i;
817 char buf[] = "123"; 815 char buf[] = "123";
818 816
819 if (geteuid() != 0) { 817 if (geteuid() != 0) {
@@ -1116,11 +1114,6 @@ void test_pkey_syscalls_on_non_allocated_pkey(int *ptr, u16 pkey)
1116 err = sys_pkey_free(i); 1114 err = sys_pkey_free(i);
1117 pkey_assert(err); 1115 pkey_assert(err);
1118 1116
1119 /* not enforced when pkey_get() is not a syscall
1120 err = pkey_get(i, 0);
1121 pkey_assert(err < 0);
1122 */
1123
1124 err = sys_pkey_free(i); 1117 err = sys_pkey_free(i);
1125 pkey_assert(err); 1118 pkey_assert(err);
1126 1119
@@ -1133,14 +1126,8 @@ void test_pkey_syscalls_on_non_allocated_pkey(int *ptr, u16 pkey)
1133void test_pkey_syscalls_bad_args(int *ptr, u16 pkey) 1126void test_pkey_syscalls_bad_args(int *ptr, u16 pkey)
1134{ 1127{
1135 int err; 1128 int err;
1136 int bad_flag = (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE) + 1;
1137 int bad_pkey = NR_PKEYS+99; 1129 int bad_pkey = NR_PKEYS+99;
1138 1130
1139 /* not enforced when pkey_get() is not a syscall
1140 err = pkey_get(bad_pkey, bad_flag);
1141 pkey_assert(err < 0);
1142 */
1143
1144 /* pass a known-invalid pkey in: */ 1131 /* pass a known-invalid pkey in: */
1145 err = sys_mprotect_pkey(ptr, PAGE_SIZE, PROT_READ, bad_pkey); 1132 err = sys_mprotect_pkey(ptr, PAGE_SIZE, PROT_READ, bad_pkey);
1146 pkey_assert(err); 1133 pkey_assert(err);
@@ -1149,8 +1136,6 @@ void test_pkey_syscalls_bad_args(int *ptr, u16 pkey)
1149/* Assumes that all pkeys other than 'pkey' are unallocated */ 1136/* Assumes that all pkeys other than 'pkey' are unallocated */
1150void test_pkey_alloc_exhaust(int *ptr, u16 pkey) 1137void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
1151{ 1138{
1152 unsigned long flags;
1153 unsigned long init_val;
1154 int err; 1139 int err;
1155 int allocated_pkeys[NR_PKEYS] = {0}; 1140 int allocated_pkeys[NR_PKEYS] = {0};
1156 int nr_allocated_pkeys = 0; 1141 int nr_allocated_pkeys = 0;
diff --git a/tools/testing/selftests/x86/sysret_rip.c b/tools/testing/selftests/x86/sysret_rip.c
new file mode 100644
index 000000000000..d85ec5b3671c
--- /dev/null
+++ b/tools/testing/selftests/x86/sysret_rip.c
@@ -0,0 +1,195 @@
1/*
2 * sigreturn.c - tests that x86 avoids Intel SYSRET pitfalls
3 * Copyright (c) 2014-2016 Andrew Lutomirski
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 */
14
15#define _GNU_SOURCE
16
17#include <stdlib.h>
18#include <unistd.h>
19#include <stdio.h>
20#include <string.h>
21#include <inttypes.h>
22#include <sys/signal.h>
23#include <sys/ucontext.h>
24#include <sys/syscall.h>
25#include <err.h>
26#include <stddef.h>
27#include <stdbool.h>
28#include <setjmp.h>
29#include <sys/user.h>
30#include <sys/mman.h>
31#include <assert.h>
32
33
34asm (
35 ".pushsection \".text\", \"ax\"\n\t"
36 ".balign 4096\n\t"
37 "test_page: .globl test_page\n\t"
38 ".fill 4094,1,0xcc\n\t"
39 "test_syscall_insn:\n\t"
40 "syscall\n\t"
41 ".ifne . - test_page - 4096\n\t"
42 ".error \"test page is not one page long\"\n\t"
43 ".endif\n\t"
44 ".popsection"
45 );
46
47extern const char test_page[];
48static void const *current_test_page_addr = test_page;
49
50static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
51 int flags)
52{
53 struct sigaction sa;
54 memset(&sa, 0, sizeof(sa));
55 sa.sa_sigaction = handler;
56 sa.sa_flags = SA_SIGINFO | flags;
57 sigemptyset(&sa.sa_mask);
58 if (sigaction(sig, &sa, 0))
59 err(1, "sigaction");
60}
61
62static void clearhandler(int sig)
63{
64 struct sigaction sa;
65 memset(&sa, 0, sizeof(sa));
66 sa.sa_handler = SIG_DFL;
67 sigemptyset(&sa.sa_mask);
68 if (sigaction(sig, &sa, 0))
69 err(1, "sigaction");
70}
71
72/* State used by our signal handlers. */
73static gregset_t initial_regs;
74
75static volatile unsigned long rip;
76
77static void sigsegv_for_sigreturn_test(int sig, siginfo_t *info, void *ctx_void)
78{
79 ucontext_t *ctx = (ucontext_t*)ctx_void;
80
81 if (rip != ctx->uc_mcontext.gregs[REG_RIP]) {
82 printf("[FAIL]\tRequested RIP=0x%lx but got RIP=0x%lx\n",
83 rip, (unsigned long)ctx->uc_mcontext.gregs[REG_RIP]);
84 fflush(stdout);
85 _exit(1);
86 }
87
88 memcpy(&ctx->uc_mcontext.gregs, &initial_regs, sizeof(gregset_t));
89
90 printf("[OK]\tGot SIGSEGV at RIP=0x%lx\n", rip);
91}
92
93static void sigusr1(int sig, siginfo_t *info, void *ctx_void)
94{
95 ucontext_t *ctx = (ucontext_t*)ctx_void;
96
97 memcpy(&initial_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
98
99 /* Set IP and CX to match so that SYSRET can happen. */
100 ctx->uc_mcontext.gregs[REG_RIP] = rip;
101 ctx->uc_mcontext.gregs[REG_RCX] = rip;
102
103 /* R11 and EFLAGS should already match. */
104 assert(ctx->uc_mcontext.gregs[REG_EFL] ==
105 ctx->uc_mcontext.gregs[REG_R11]);
106
107 sethandler(SIGSEGV, sigsegv_for_sigreturn_test, SA_RESETHAND);
108
109 return;
110}
111
112static void test_sigreturn_to(unsigned long ip)
113{
114 rip = ip;
115 printf("[RUN]\tsigreturn to 0x%lx\n", ip);
116 raise(SIGUSR1);
117}
118
119static jmp_buf jmpbuf;
120
121static void sigsegv_for_fallthrough(int sig, siginfo_t *info, void *ctx_void)
122{
123 ucontext_t *ctx = (ucontext_t*)ctx_void;
124
125 if (rip != ctx->uc_mcontext.gregs[REG_RIP]) {
126 printf("[FAIL]\tExpected SIGSEGV at 0x%lx but got RIP=0x%lx\n",
127 rip, (unsigned long)ctx->uc_mcontext.gregs[REG_RIP]);
128 fflush(stdout);
129 _exit(1);
130 }
131
132 siglongjmp(jmpbuf, 1);
133}
134
135static void test_syscall_fallthrough_to(unsigned long ip)
136{
137 void *new_address = (void *)(ip - 4096);
138 void *ret;
139
140 printf("[RUN]\tTrying a SYSCALL that falls through to 0x%lx\n", ip);
141
142 ret = mremap((void *)current_test_page_addr, 4096, 4096,
143 MREMAP_MAYMOVE | MREMAP_FIXED, new_address);
144 if (ret == MAP_FAILED) {
145 if (ip <= (1UL << 47) - PAGE_SIZE) {
146 err(1, "mremap to %p", new_address);
147 } else {
148 printf("[OK]\tmremap to %p failed\n", new_address);
149 return;
150 }
151 }
152
153 if (ret != new_address)
154 errx(1, "mremap malfunctioned: asked for %p but got %p\n",
155 new_address, ret);
156
157 current_test_page_addr = new_address;
158 rip = ip;
159
160 if (sigsetjmp(jmpbuf, 1) == 0) {
161 asm volatile ("call *%[syscall_insn]" :: "a" (SYS_getpid),
162 [syscall_insn] "rm" (ip - 2));
163 errx(1, "[FAIL]\tSyscall trampoline returned");
164 }
165
166 printf("[OK]\tWe survived\n");
167}
168
169int main()
170{
171 /*
172 * When the kernel returns from a slow-path syscall, it will
173 * detect whether SYSRET is appropriate. If it incorrectly
174 * thinks that SYSRET is appropriate when RIP is noncanonical,
175 * it'll crash on Intel CPUs.
176 */
177 sethandler(SIGUSR1, sigusr1, 0);
178 for (int i = 47; i < 64; i++)
179 test_sigreturn_to(1UL<<i);
180
181 clearhandler(SIGUSR1);
182
183 sethandler(SIGSEGV, sigsegv_for_fallthrough, 0);
184
185 /* One extra test to check that we didn't screw up the mremap logic. */
186 test_syscall_fallthrough_to((1UL << 47) - 2*PAGE_SIZE);
187
188 /* These are the interesting cases. */
189 for (int i = 47; i < 64; i++) {
190 test_syscall_fallthrough_to((1UL<<i) - PAGE_SIZE);
191 test_syscall_fallthrough_to(1UL<<i);
192 }
193
194 return 0;
195}
diff --git a/tools/testing/selftests/zram/Makefile b/tools/testing/selftests/zram/Makefile
index 29d80346e3eb..c3a87e5f9d36 100644
--- a/tools/testing/selftests/zram/Makefile
+++ b/tools/testing/selftests/zram/Makefile
@@ -2,8 +2,7 @@ all:
2 2
3TEST_PROGS := zram.sh 3TEST_PROGS := zram.sh
4TEST_FILES := zram01.sh zram02.sh zram_lib.sh 4TEST_FILES := zram01.sh zram02.sh zram_lib.sh
5EXTRA_CLEAN := err.log
5 6
6include ../lib.mk 7include ../lib.mk
7 8
8clean:
9 $(RM) err.log
diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c
index 88d5e71be044..95dd14648ba5 100644
--- a/tools/usb/ffs-test.c
+++ b/tools/usb/ffs-test.c
@@ -22,7 +22,7 @@
22/* $(CROSS_COMPILE)cc -Wall -Wextra -g -o ffs-test ffs-test.c -lpthread */ 22/* $(CROSS_COMPILE)cc -Wall -Wextra -g -o ffs-test ffs-test.c -lpthread */
23 23
24 24
25#define _BSD_SOURCE /* for endian.h */ 25#define _DEFAULT_SOURCE /* for endian.h */
26 26
27#include <endian.h> 27#include <endian.h>
28#include <errno.h> 28#include <errno.h>
@@ -110,16 +110,25 @@ static const struct {
110 struct usb_functionfs_descs_head_v2 header; 110 struct usb_functionfs_descs_head_v2 header;
111 __le32 fs_count; 111 __le32 fs_count;
112 __le32 hs_count; 112 __le32 hs_count;
113 __le32 ss_count;
113 struct { 114 struct {
114 struct usb_interface_descriptor intf; 115 struct usb_interface_descriptor intf;
115 struct usb_endpoint_descriptor_no_audio sink; 116 struct usb_endpoint_descriptor_no_audio sink;
116 struct usb_endpoint_descriptor_no_audio source; 117 struct usb_endpoint_descriptor_no_audio source;
117 } __attribute__((packed)) fs_descs, hs_descs; 118 } __attribute__((packed)) fs_descs, hs_descs;
119 struct {
120 struct usb_interface_descriptor intf;
121 struct usb_endpoint_descriptor_no_audio sink;
122 struct usb_ss_ep_comp_descriptor sink_comp;
123 struct usb_endpoint_descriptor_no_audio source;
124 struct usb_ss_ep_comp_descriptor source_comp;
125 } ss_descs;
118} __attribute__((packed)) descriptors = { 126} __attribute__((packed)) descriptors = {
119 .header = { 127 .header = {
120 .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2), 128 .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2),
121 .flags = cpu_to_le32(FUNCTIONFS_HAS_FS_DESC | 129 .flags = cpu_to_le32(FUNCTIONFS_HAS_FS_DESC |
122 FUNCTIONFS_HAS_HS_DESC), 130 FUNCTIONFS_HAS_HS_DESC |
131 FUNCTIONFS_HAS_SS_DESC),
123 .length = cpu_to_le32(sizeof descriptors), 132 .length = cpu_to_le32(sizeof descriptors),
124 }, 133 },
125 .fs_count = cpu_to_le32(3), 134 .fs_count = cpu_to_le32(3),
@@ -171,6 +180,45 @@ static const struct {
171 .bInterval = 1, /* NAK every 1 uframe */ 180 .bInterval = 1, /* NAK every 1 uframe */
172 }, 181 },
173 }, 182 },
183 .ss_count = cpu_to_le32(5),
184 .ss_descs = {
185 .intf = {
186 .bLength = sizeof descriptors.fs_descs.intf,
187 .bDescriptorType = USB_DT_INTERFACE,
188 .bNumEndpoints = 2,
189 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
190 .iInterface = 1,
191 },
192 .sink = {
193 .bLength = sizeof descriptors.hs_descs.sink,
194 .bDescriptorType = USB_DT_ENDPOINT,
195 .bEndpointAddress = 1 | USB_DIR_IN,
196 .bmAttributes = USB_ENDPOINT_XFER_BULK,
197 .wMaxPacketSize = cpu_to_le16(1024),
198 },
199 .sink_comp = {
200 .bLength = USB_DT_SS_EP_COMP_SIZE,
201 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
202 .bMaxBurst = 0,
203 .bmAttributes = 0,
204 .wBytesPerInterval = 0,
205 },
206 .source = {
207 .bLength = sizeof descriptors.hs_descs.source,
208 .bDescriptorType = USB_DT_ENDPOINT,
209 .bEndpointAddress = 2 | USB_DIR_OUT,
210 .bmAttributes = USB_ENDPOINT_XFER_BULK,
211 .wMaxPacketSize = cpu_to_le16(1024),
212 .bInterval = 1, /* NAK every 1 uframe */
213 },
214 .source_comp = {
215 .bLength = USB_DT_SS_EP_COMP_SIZE,
216 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
217 .bMaxBurst = 0,
218 .bmAttributes = 0,
219 .wBytesPerInterval = 0,
220 },
221 },
174}; 222};
175 223
176static size_t descs_to_legacy(void **legacy, const void *descriptors_v2) 224static size_t descs_to_legacy(void **legacy, const void *descriptors_v2)
diff --git a/tools/usb/usbip/README b/tools/usb/usbip/README
index 831f49fea3ce..5eb2b6c7722b 100644
--- a/tools/usb/usbip/README
+++ b/tools/usb/usbip/README
@@ -4,10 +4,33 @@
4# Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 4# Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
5# 2005-2008 Takahiro Hirofuchi 5# 2005-2008 Takahiro Hirofuchi
6 6
7[Overview]
8USB/IP protocol allows to pass USB device from server to client over the
9network. Server is a machine which provides (shares) a USB device. Client is
10a machine which uses USB device provided by server over the network.
11The USB device may be either physical device connected to a server or
12software entity created on a server using USB gadget subsystem.
13Whole project consists of four parts:
14
15 - usbip-vhci
16 A client side kernel module which provides a virtual USB Host Controller
17 and allows to import a USB device from a remote machine.
18
19 - usbip-host (stub driver)
20 A server side module which provides a USB device driver which can be
21 bound to a physical USB device to make it exportable.
22
23 - usbip-vudc
24 A server side module which provides a virtual USB Device Controller and allows
25 to export a USB device created using USB Gadget Subsystem.
26
27 - usbip-utils
28 A set of userspace tools used to handle connection and management.
29 Used on both sides.
7 30
8[Requirements] 31[Requirements]
9 - USB/IP device drivers 32 - USB/IP device drivers
10 Found in the staging directory of the Linux kernel. 33 Found in the drivers/usb/usbip/ directory of the Linux kernel tree.
11 34
12 - libudev >= 2.0 35 - libudev >= 2.0
13 libudev library 36 libudev library
@@ -36,6 +59,10 @@
36 59
37 60
38[Usage] 61[Usage]
62On a server side there are two entities which can be shared.
63First of them is physical usb device connected to the machine.
64To make it available below steps should be executed:
65
39 server:# (Physically attach your USB device.) 66 server:# (Physically attach your USB device.)
40 67
41 server:# insmod usbip-core.ko 68 server:# insmod usbip-core.ko
@@ -52,6 +79,30 @@
52 - The USB device 1-2 is now exportable to other hosts! 79 - The USB device 1-2 is now exportable to other hosts!
53 - Use `usbip unbind --busid 1-2' to stop exporting the device. 80 - Use `usbip unbind --busid 1-2' to stop exporting the device.
54 81
82Second of shareable entities is USB Gadget created using USB Gadget Subsystem
83on a server machine. To make it available below steps should be executed:
84
85 server:# (Create your USB gadget)
86 - Currently the most preferable way of creating a new USB gadget
87 is ConfigFS Composite Gadget. Please refer to its documentation
88 for details.
89 - See vudc_server_example.sh for a short example of USB gadget creation
90
91 server:# insmod usbip-core.ko
92 server:# insmod usbip-vudc.ko
93 - To create more than one instance of vudc use num module param
94
95 server:# (Bind gadget to one of available vudc)
96 - Assign your new gadget to USB/IP UDC
97 - Using ConfigFS interface you may do this simply by:
98 server:# cd /sys/kernel/config/usb_gadget/<gadget_name>
99 server:# echo "usbip-vudc.0" > UDC
100
101 server:# usbipd -D --device
102 - Start usbip daemon.
103
104To attach new device to client machine below commands should be used:
105
55 client:# insmod usbip-core.ko 106 client:# insmod usbip-core.ko
56 client:# insmod vhci-hcd.ko 107 client:# insmod vhci-hcd.ko
57 108
@@ -60,6 +111,8 @@
60 111
61 client:# usbip attach --remote <host> --busid 1-2 112 client:# usbip attach --remote <host> --busid 1-2
62 - Connect the remote USB device. 113 - Connect the remote USB device.
114 - When using vudc on a server side busid is really vudc instance name.
115 For example: usbip-vudc.0
63 116
64 client:# usbip port 117 client:# usbip port
65 - Show virtual port status. 118 - Show virtual port status.
@@ -192,6 +245,8 @@ Detach the imported device:
192 - http://usbip.wiki.sourceforge.net/how-to-debug-usbip 245 - http://usbip.wiki.sourceforge.net/how-to-debug-usbip
193 - usbip-host.ko must be bound to the target device. 246 - usbip-host.ko must be bound to the target device.
194 - See /proc/bus/usb/devices and find "Driver=..." lines of the device. 247 - See /proc/bus/usb/devices and find "Driver=..." lines of the device.
248 - Target USB gadget must be bound to vudc
249 (using USB gadget susbsys, not usbip bind command)
195 - Shutdown firewall. 250 - Shutdown firewall.
196 - usbip now uses TCP port 3240. 251 - usbip now uses TCP port 3240.
197 - Disable SELinux. 252 - Disable SELinux.
diff --git a/tools/usb/usbip/vudc/vudc_server_example.sh b/tools/usb/usbip/vudc/vudc_server_example.sh
new file mode 100755
index 000000000000..2736be64f203
--- /dev/null
+++ b/tools/usb/usbip/vudc/vudc_server_example.sh
@@ -0,0 +1,107 @@
1#!/bin/bash
2
3################################################################################
4# This is free and unencumbered software released into the public domain.
5#
6# Anyone is free to copy, modify, publish, use, compile, sell, or
7# distribute this software, either in source code form or as a compiled
8# binary, for any purpose, commercial or non-commercial, and by any
9# means.
10#
11# In jurisdictions that recognize copyright laws, the author or authors
12# of this software dedicate any and all copyright interest in the
13# software to the public domain. We make this dedication for the benefit
14# of the public at large and to the detriment of our heirs and
15# successors. We intend this dedication to be an overt act of
16# relinquishment in perpetuity of all present and future rights to this
17# software under copyright law.
18#
19# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25# OTHER DEALINGS IN THE SOFTWARE.
26#
27# For more information, please refer to <http://unlicense.org/>
28################################################################################
29
30################################################################################
31# This is a sample script which shows how to use vUDC with ConfigFS gadgets
32################################################################################
33
34# Stop script on error
35set -e
36
37################################################################################
38# Create your USB gadget
39# You may use bare ConfigFS interface (as below)
40# or libusbgx or gt toool
41# Instead of ConfigFS gadgets you may use any of legacy gadgets.
42################################################################################
43CONFIGFS_MOUNT_POINT="/sys/kernel/config"
44GADGET_NAME="g1"
45ID_VENDOR="0x1d6b"
46ID_PRODUCT="0x0104"
47
48cd ${CONFIGFS_MOUNT_POINT}/usb_gadget
49# Create a new USB gadget
50mkdir ${GADGET_NAME}
51cd ${GADGET_NAME}
52
53# This gadget contains one function - ACM (serial port over USB)
54FUNC_DIR="functions/acm.ser0"
55mkdir ${FUNC_DIR}
56
57# Just one configuration
58mkdir configs/c.1
59ln -s ${FUNC_DIR} configs/c.1
60
61# Set our gadget identity
62echo ${ID_VENDOR} > idVendor
63echo ${ID_PRODUCT} > idProduct
64
65################################################################################
66# Load vudc-module if vudc is not available
67# You may change value of num param to get more than one vUDC instance
68################################################################################
69[[ -d /sys/class/udc/usbip-vudc.0 ]] || modprobe usbip-vudc num=1
70
71################################################################################
72# Bind gadget to our vUDC
73# By default we bind to first one but you may change this if you would like
74# to use more than one instance
75################################################################################
76echo "usbip-vudc.0" > UDC
77
78################################################################################
79# Let's now run our usbip daemon in a USB device mode
80################################################################################
81usbipd --device &
82
83################################################################################
84# Now your USB gadget is available using USB/IP protocol.
85# To prepare your client, you should ensure that usbip-vhci module is inside
86# your kernel. If it's not then you can load it:
87#
88# $ modprobe usbip-vhci
89#
90# To check availability of your gadget you may try to list devices exported
91# on a remote server:
92#
93# $ modprobe usbip-vhci
94# $ usbip list -r $SERVER_IP
95# Exportable USB devices
96# ======================
97# usbipd: info: request 0x8005(6): complete
98# - 127.0.0.1
99# usbip-vudc.0: Linux Foundation : unknown product (1d6b:0104)
100# : /sys/devices/platform/usbip-vudc.0
101# : (Defined at Interface level) (00/00/00)
102#
103# To attach this device to your client you may use:
104#
105# $ usbip attach -r $SERVER_IP -d usbip-vudc.0
106#
107################################################################################
diff --git a/tools/vm/Makefile b/tools/vm/Makefile
index 93aadaf7ff63..006029456988 100644
--- a/tools/vm/Makefile
+++ b/tools/vm/Makefile
@@ -9,6 +9,8 @@ CC = $(CROSS_COMPILE)gcc
9CFLAGS = -Wall -Wextra -I../lib/ 9CFLAGS = -Wall -Wextra -I../lib/
10LDFLAGS = $(LIBS) 10LDFLAGS = $(LIBS)
11 11
12all: $(TARGETS)
13
12$(TARGETS): $(LIBS) 14$(TARGETS): $(LIBS)
13 15
14$(LIBS): 16$(LIBS):
@@ -20,3 +22,9 @@ $(LIBS):
20clean: 22clean:
21 $(RM) page-types slabinfo page_owner_sort 23 $(RM) page-types slabinfo page_owner_sort
22 make -C $(LIB_DIR) clean 24 make -C $(LIB_DIR) clean
25
26sbindir ?= /usr/sbin
27
28install: all
29 install -d $(DESTDIR)$(sbindir)
30 install -m 755 -p $(TARGETS) $(DESTDIR)$(sbindir)