aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile8
-rw-r--r--tools/arch/arm/include/uapi/asm/kvm.h10
-rw-r--r--tools/arch/arm64/include/uapi/asm/kvm.h10
-rw-r--r--tools/arch/powerpc/include/uapi/asm/kvm.h3
-rw-r--r--tools/arch/s390/include/uapi/asm/kvm.h26
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h2
-rw-r--r--tools/arch/x86/include/asm/disabled-features.h8
-rw-r--r--tools/arch/x86/include/asm/required-features.h8
-rw-r--r--tools/arch/x86/include/uapi/asm/kvm.h3
-rw-r--r--tools/arch/x86/include/uapi/asm/vmx.h25
-rw-r--r--tools/build/feature/test-bpf.c1
-rwxr-xr-xtools/hv/bondvf.sh33
-rw-r--r--tools/hv/hv_kvp_daemon.c44
-rw-r--r--tools/hv/hv_vss_daemon.c4
-rw-r--r--tools/iio/Makefile2
-rw-r--r--tools/iio/iio_utils.h2
-rw-r--r--tools/include/asm/sections.h4
-rw-r--r--tools/include/linux/bitops.h10
-rw-r--r--tools/include/linux/compiler-gcc.h10
-rw-r--r--tools/include/linux/compiler.h16
-rw-r--r--tools/include/linux/debug_locks.h (renamed from tools/lib/lockdep/uinclude/linux/debug_locks.h)3
-rw-r--r--tools/include/linux/delay.h4
-rw-r--r--tools/include/linux/err.h5
-rw-r--r--tools/include/linux/filter.h10
-rw-r--r--tools/include/linux/ftrace.h4
-rw-r--r--tools/include/linux/gfp.h4
-rw-r--r--tools/include/linux/hardirq.h (renamed from tools/lib/lockdep/uinclude/linux/hardirq.h)0
-rw-r--r--tools/include/linux/interrupt.h4
-rw-r--r--tools/include/linux/irqflags.h (renamed from tools/lib/lockdep/uinclude/linux/irqflags.h)8
-rw-r--r--tools/include/linux/jhash.h175
-rw-r--r--tools/include/linux/kallsyms.h (renamed from tools/lib/lockdep/uinclude/linux/kallsyms.h)3
-rw-r--r--tools/include/linux/kern_levels.h (renamed from tools/lib/lockdep/uinclude/linux/kern_levels.h)0
-rw-r--r--tools/include/linux/kernel.h39
-rw-r--r--tools/include/linux/kmemcheck.h (renamed from tools/lib/lockdep/uinclude/linux/kmemcheck.h)0
-rw-r--r--tools/include/linux/linkage.h4
-rw-r--r--tools/include/linux/lockdep.h (renamed from tools/lib/lockdep/uinclude/linux/lockdep.h)34
-rw-r--r--tools/include/linux/module.h (renamed from tools/lib/lockdep/uinclude/linux/module.h)5
-rw-r--r--tools/include/linux/mutex.h4
-rw-r--r--tools/include/linux/proc_fs.h4
-rw-r--r--tools/include/linux/rcu.h (renamed from tools/lib/lockdep/uinclude/linux/rcu.h)3
-rw-r--r--tools/include/linux/sched/clock.h4
-rw-r--r--tools/include/linux/sched/mm.h4
-rw-r--r--tools/include/linux/sched/task.h4
-rw-r--r--tools/include/linux/seq_file.h4
-rw-r--r--tools/include/linux/spinlock.h26
-rw-r--r--tools/include/linux/stacktrace.h (renamed from tools/lib/lockdep/uinclude/linux/stacktrace.h)0
-rw-r--r--tools/include/linux/unaligned/packed_struct.h46
-rw-r--r--tools/include/trace/events/lock.h4
-rw-r--r--tools/include/uapi/linux/bpf.h149
-rw-r--r--tools/include/uapi/linux/stat.h8
-rwxr-xr-xtools/kvm/kvm_stat/kvm_stat669
-rw-r--r--tools/kvm/kvm_stat/kvm_stat.txt12
-rw-r--r--tools/lib/api/fs/fs.c30
-rw-r--r--tools/lib/api/fs/fs.h4
-rw-r--r--tools/lib/bpf/bpf.c90
-rw-r--r--tools/lib/bpf/bpf.h9
-rw-r--r--tools/lib/lockdep/Makefile9
-rw-r--r--tools/lib/lockdep/lockdep.c19
-rw-r--r--tools/lib/lockdep/preload.c5
-rw-r--r--tools/lib/lockdep/rbtree.c2
-rwxr-xr-xtools/lib/lockdep/run_tests.sh8
-rw-r--r--tools/lib/lockdep/uinclude/asm/hash.h6
-rw-r--r--tools/lib/lockdep/uinclude/asm/hweight.h3
-rw-r--r--tools/lib/lockdep/uinclude/asm/sections.h3
-rw-r--r--tools/lib/lockdep/uinclude/linux/bitops.h3
-rw-r--r--tools/lib/lockdep/uinclude/linux/compiler.h10
-rw-r--r--tools/lib/lockdep/uinclude/linux/delay.h3
-rw-r--r--tools/lib/lockdep/uinclude/linux/ftrace.h3
-rw-r--r--tools/lib/lockdep/uinclude/linux/gfp.h3
-rw-r--r--tools/lib/lockdep/uinclude/linux/hash.h1
-rw-r--r--tools/lib/lockdep/uinclude/linux/interrupt.h3
-rw-r--r--tools/lib/lockdep/uinclude/linux/kernel.h47
-rw-r--r--tools/lib/lockdep/uinclude/linux/linkage.h3
-rw-r--r--tools/lib/lockdep/uinclude/linux/list.h1
-rw-r--r--tools/lib/lockdep/uinclude/linux/mutex.h3
-rw-r--r--tools/lib/lockdep/uinclude/linux/poison.h1
-rw-r--r--tools/lib/lockdep/uinclude/linux/prefetch.h6
-rw-r--r--tools/lib/lockdep/uinclude/linux/proc_fs.h3
-rw-r--r--tools/lib/lockdep/uinclude/linux/rbtree_augmented.h2
-rw-r--r--tools/lib/lockdep/uinclude/linux/seq_file.h3
-rw-r--r--tools/lib/lockdep/uinclude/linux/spinlock.h25
-rw-r--r--tools/lib/lockdep/uinclude/linux/stringify.h7
-rw-r--r--tools/lib/lockdep/uinclude/trace/events/lock.h3
-rw-r--r--tools/net/bpf_jit_disasm.c37
-rw-r--r--tools/objtool/Build1
-rw-r--r--tools/objtool/Documentation/stack-validation.txt153
-rw-r--r--tools/objtool/Makefile2
-rw-r--r--tools/objtool/arch.h64
-rw-r--r--tools/objtool/arch/x86/decode.c400
-rw-r--r--tools/objtool/arch/x86/insn/x86-opcode-map.txt2
-rw-r--r--tools/objtool/builtin-check.c1280
-rw-r--r--tools/objtool/cfi.h55
-rw-r--r--tools/objtool/check.c1655
-rw-r--r--tools/objtool/check.h66
-rw-r--r--tools/objtool/elf.c59
-rw-r--r--tools/objtool/elf.h6
-rw-r--r--tools/objtool/special.c6
-rw-r--r--tools/objtool/warn.h10
-rw-r--r--tools/perf/Documentation/intel-pt.txt78
-rw-r--r--tools/perf/Documentation/itrace.txt8
-rw-r--r--tools/perf/Documentation/perf-ftrace.txt33
-rw-r--r--tools/perf/Documentation/perf-probe.txt8
-rw-r--r--tools/perf/Documentation/perf-script-perl.txt2
-rw-r--r--tools/perf/Documentation/perf-script-python.txt23
-rw-r--r--tools/perf/Documentation/perf-script.txt22
-rw-r--r--tools/perf/Documentation/perf-stat.txt14
-rw-r--r--tools/perf/Makefile.config38
-rw-r--r--tools/perf/Makefile.perf2
-rw-r--r--tools/perf/arch/Build2
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c29
-rw-r--r--tools/perf/arch/common.c1
-rw-r--r--tools/perf/arch/powerpc/util/Build2
-rw-r--r--tools/perf/arch/powerpc/util/unwind-libdw.c73
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-32.c12
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-64.c30
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-src.c30
-rw-r--r--tools/perf/arch/x86/util/intel-bts.c4
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c9
-rw-r--r--tools/perf/bench/numa.c2
-rw-r--r--tools/perf/builtin-c2c.c4
-rw-r--r--tools/perf/builtin-config.c67
-rw-r--r--tools/perf/builtin-diff.c5
-rw-r--r--tools/perf/builtin-ftrace.c159
-rw-r--r--tools/perf/builtin-help.c48
-rw-r--r--tools/perf/builtin-kmem.c4
-rw-r--r--tools/perf/builtin-record.c4
-rw-r--r--tools/perf/builtin-report.c8
-rw-r--r--tools/perf/builtin-sched.c2
-rw-r--r--tools/perf/builtin-script.c355
-rw-r--r--tools/perf/builtin-stat.c58
-rw-r--r--tools/perf/builtin-top.c4
-rw-r--r--tools/perf/builtin-trace.c4
-rw-r--r--tools/perf/jvmti/jvmti_agent.c2
-rw-r--r--tools/perf/jvmti/jvmti_agent.h2
-rw-r--r--tools/perf/jvmti/libjvmti.c5
-rw-r--r--tools/perf/pmu-events/Build4
-rw-r--r--tools/perf/pmu-events/jevents.c4
-rw-r--r--tools/perf/scripts/python/bin/intel-pt-events-record13
-rw-r--r--tools/perf/scripts/python/bin/intel-pt-events-report3
-rw-r--r--tools/perf/scripts/python/intel-pt-events.py128
-rw-r--r--tools/perf/tests/Build2
-rw-r--r--tools/perf/tests/attr.c10
-rw-r--r--tools/perf/tests/attr.py48
-rw-r--r--tools/perf/tests/bp_signal.c17
-rw-r--r--tools/perf/tests/bp_signal_overflow.c3
-rw-r--r--tools/perf/tests/bpf-script-test-prologue.c9
-rw-r--r--tools/perf/tests/builtin-test.c7
-rw-r--r--tools/perf/tests/code-reading.c20
-rw-r--r--tools/perf/tests/dwarf-unwind.c15
-rw-r--r--tools/perf/tests/parse-events.c13
-rw-r--r--tools/perf/tests/task-exit.c2
-rw-r--r--tools/perf/tests/tests.h3
-rw-r--r--tools/perf/ui/browsers/annotate.c54
-rw-r--r--tools/perf/ui/gtk/annotate.c3
-rw-r--r--tools/perf/ui/hist.c2
-rw-r--r--tools/perf/util/annotate.c82
-rw-r--r--tools/perf/util/annotate.h4
-rw-r--r--tools/perf/util/auxtrace.c18
-rw-r--r--tools/perf/util/auxtrace.h6
-rw-r--r--tools/perf/util/build-id.c45
-rw-r--r--tools/perf/util/build-id.h1
-rw-r--r--tools/perf/util/cache.h3
-rw-r--r--tools/perf/util/callchain.c13
-rw-r--r--tools/perf/util/config.c43
-rw-r--r--tools/perf/util/config.h4
-rw-r--r--tools/perf/util/data-convert-bt.c6
-rw-r--r--tools/perf/util/debug.h11
-rw-r--r--tools/perf/util/dso.c100
-rw-r--r--tools/perf/util/dso.h9
-rw-r--r--tools/perf/util/event.h121
-rw-r--r--tools/perf/util/evlist.h3
-rw-r--r--tools/perf/util/evsel.c54
-rw-r--r--tools/perf/util/evsel_fprintf.c33
-rw-r--r--tools/perf/util/genelf_debug.c5
-rw-r--r--tools/perf/util/header.c17
-rw-r--r--tools/perf/util/help-unknown-cmd.c2
-rw-r--r--tools/perf/util/intel-bts.c2
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c304
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.h13
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-log.h4
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c110
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h7
-rw-r--r--tools/perf/util/intel-pt-decoder/x86-opcode-map.txt2
-rw-r--r--tools/perf/util/intel-pt.c642
-rw-r--r--tools/perf/util/machine.c21
-rw-r--r--tools/perf/util/pmu.h4
-rw-r--r--tools/perf/util/probe-event.c2
-rw-r--r--tools/perf/util/probe-event.h4
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c5
-rw-r--r--tools/perf/util/session.c2
-rw-r--r--tools/perf/util/sort.c22
-rw-r--r--tools/perf/util/srcline.c49
-rw-r--r--tools/perf/util/stat-shadow.c33
-rw-r--r--tools/perf/util/stat.c2
-rw-r--r--tools/perf/util/stat.h2
-rw-r--r--tools/perf/util/strbuf.h4
-rw-r--r--tools/perf/util/symbol-elf.c41
-rw-r--r--tools/perf/util/symbol.c4
-rw-r--r--tools/perf/util/trace-event-parse.c4
-rw-r--r--tools/perf/util/unwind-libdw.c22
-rw-r--r--tools/perf/util/unwind-libunwind-local.c11
-rw-r--r--tools/perf/util/usage.c62
-rw-r--r--tools/perf/util/util.c52
-rw-r--r--tools/perf/util/util.h21
-rw-r--r--tools/power/acpi/.gitignore4
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixxf.c10
-rw-r--r--tools/power/cpupower/utils/helpers/amd.c31
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h2
-rw-r--r--tools/power/cpupower/utils/helpers/misc.c23
-rw-r--r--tools/power/x86/turbostat/turbostat.c94
-rw-r--r--tools/power/x86/x86_energy_perf_policy/Makefile27
-rw-r--r--tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8241
-rw-r--r--tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c1504
-rw-r--r--tools/testing/nvdimm/test/iomap.c6
-rw-r--r--tools/testing/nvdimm/test/nfit.c4
-rw-r--r--tools/testing/nvdimm/test/nfit_test.h4
-rw-r--r--tools/testing/selftests/bpf/Makefile9
-rw-r--r--tools/testing/selftests/bpf/bpf_endian.h41
-rw-r--r--tools/testing/selftests/bpf/include/uapi/linux/types.h22
-rw-r--r--tools/testing/selftests/bpf/test_align.c458
-rw-r--r--tools/testing/selftests/bpf/test_maps.c50
-rw-r--r--tools/testing/selftests/bpf/test_obj_id.c35
-rw-r--r--tools/testing/selftests/bpf/test_pkt_access.c1
-rw-r--r--tools/testing/selftests/bpf/test_pkt_md_access.c35
-rw-r--r--tools/testing/selftests/bpf/test_progs.c225
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c672
-rwxr-xr-xtools/testing/selftests/ftrace/ftracetest2
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/functions4
-rw-r--r--tools/testing/selftests/ftrace/test.d/instances/instance-event.tc8
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc21
-rwxr-xr-xtools/testing/selftests/ntb/ntb_test.sh2
-rw-r--r--tools/testing/selftests/powerpc/tm/.gitignore1
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile4
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-resched-dscr.c2
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c118
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/configcheck.sh2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-build.sh2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh5
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/CFLIST2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-C.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-N2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-P6
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-t10
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-t.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-u9
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-u.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TINY025
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE015
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot4
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE025
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE034
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot4
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE044
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE054
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE064
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE076
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE081
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE08-T21
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcuperf/TINY (renamed from tools/testing/selftests/rcutorture/configs/rcu/TREE02-T)19
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcuperf/TREE1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcuperf/TREE541
-rw-r--r--tools/testing/selftests/rcutorture/doc/TINY_RCU.txt1
-rw-r--r--tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt34
-rwxr-xr-xtools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk2
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c51
-rw-r--r--tools/testing/selftests/tc-testing/.gitignore1
-rw-r--r--tools/testing/selftests/tc-testing/README102
-rw-r--r--tools/testing/selftests/tc-testing/TODO.txt10
-rw-r--r--tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt69
-rw-r--r--tools/testing/selftests/tc-testing/creating-testcases/template.json40
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/tests.json1115
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/tests.json21
-rwxr-xr-xtools/testing/selftests/tc-testing/tdc.py413
-rw-r--r--tools/testing/selftests/tc-testing/tdc_config.py17
-rw-r--r--tools/testing/selftests/tc-testing/tdc_helper.py75
-rw-r--r--tools/testing/selftests/timers/Makefile5
-rw-r--r--tools/testing/selftests/timers/freq-step.c268
-rw-r--r--tools/testing/selftests/timers/inconsistency-check.c4
-rw-r--r--tools/usb/testusb.c16
-rw-r--r--tools/usb/usbip/libsrc/vhci_driver.c133
-rw-r--r--tools/usb/usbip/libsrc/vhci_driver.h10
-rw-r--r--tools/usb/usbip/src/usbip_attach.c5
286 files changed, 12011 insertions, 3309 deletions
diff --git a/tools/Makefile b/tools/Makefile
index c8a90d01dd8e..221e1ce78b06 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -19,6 +19,7 @@ help:
19 @echo ' kvm_stat - top-like utility for displaying kvm statistics' 19 @echo ' kvm_stat - top-like utility for displaying kvm statistics'
20 @echo ' leds - LEDs tools' 20 @echo ' leds - LEDs tools'
21 @echo ' lguest - a minimal 32-bit x86 hypervisor' 21 @echo ' lguest - a minimal 32-bit x86 hypervisor'
22 @echo ' liblockdep - user-space wrapper for kernel locking-validator'
22 @echo ' net - misc networking tools' 23 @echo ' net - misc networking tools'
23 @echo ' perf - Linux performance measurement and analysis tool' 24 @echo ' perf - Linux performance measurement and analysis tool'
24 @echo ' selftests - various kernel selftests' 25 @echo ' selftests - various kernel selftests'
@@ -89,7 +90,7 @@ freefall: FORCE
89kvm_stat: FORCE 90kvm_stat: FORCE
90 $(call descend,kvm/$@) 91 $(call descend,kvm/$@)
91 92
92all: acpi cgroup cpupower gpio hv firewire lguest \ 93all: acpi cgroup cpupower gpio hv firewire lguest liblockdep \
93 perf selftests turbostat usb \ 94 perf selftests turbostat usb \
94 virtio vm net x86_energy_perf_policy \ 95 virtio vm net x86_energy_perf_policy \
95 tmon freefall objtool kvm_stat 96 tmon freefall objtool kvm_stat
@@ -103,6 +104,9 @@ cpupower_install:
103cgroup_install firewire_install gpio_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install objtool_install: 104cgroup_install firewire_install gpio_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install objtool_install:
104 $(call descend,$(@:_install=),install) 105 $(call descend,$(@:_install=),install)
105 106
107liblockdep_install:
108 $(call descend,lib/lockdep,install)
109
106selftests_install: 110selftests_install:
107 $(call descend,testing/$(@:_install=),install) 111 $(call descend,testing/$(@:_install=),install)
108 112
@@ -119,7 +123,7 @@ kvm_stat_install:
119 $(call descend,kvm/$(@:_install=),install) 123 $(call descend,kvm/$(@:_install=),install)
120 124
121install: acpi_install cgroup_install cpupower_install gpio_install \ 125install: acpi_install cgroup_install cpupower_install gpio_install \
122 hv_install firewire_install lguest_install \ 126 hv_install firewire_install lguest_install liblockdep_install \
123 perf_install selftests_install turbostat_install usb_install \ 127 perf_install selftests_install turbostat_install usb_install \
124 virtio_install vm_install net_install x86_energy_perf_policy_install \ 128 virtio_install vm_install net_install x86_energy_perf_policy_install \
125 tmon_install freefall_install objtool_install kvm_stat_install 129 tmon_install freefall_install objtool_install kvm_stat_install
diff --git a/tools/arch/arm/include/uapi/asm/kvm.h b/tools/arch/arm/include/uapi/asm/kvm.h
index 6ebd3e6a1fd1..5e3c673fa3f4 100644
--- a/tools/arch/arm/include/uapi/asm/kvm.h
+++ b/tools/arch/arm/include/uapi/asm/kvm.h
@@ -27,6 +27,8 @@
27#define __KVM_HAVE_IRQ_LINE 27#define __KVM_HAVE_IRQ_LINE
28#define __KVM_HAVE_READONLY_MEM 28#define __KVM_HAVE_READONLY_MEM
29 29
30#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
31
30#define KVM_REG_SIZE(id) \ 32#define KVM_REG_SIZE(id) \
31 (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT)) 33 (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
32 34
@@ -114,6 +116,8 @@ struct kvm_debug_exit_arch {
114}; 116};
115 117
116struct kvm_sync_regs { 118struct kvm_sync_regs {
119 /* Used with KVM_CAP_ARM_USER_IRQ */
120 __u64 device_irq_level;
117}; 121};
118 122
119struct kvm_arch_memory_slot { 123struct kvm_arch_memory_slot {
@@ -192,13 +196,17 @@ struct kvm_arch_memory_slot {
192#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5 196#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
193#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6 197#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
194#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7 198#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
199#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8
195#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10 200#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
196#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \ 201#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
197 (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) 202 (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
198#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff 203#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
199#define VGIC_LEVEL_INFO_LINE_LEVEL 0 204#define VGIC_LEVEL_INFO_LINE_LEVEL 0
200 205
201#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 206#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
207#define KVM_DEV_ARM_ITS_SAVE_TABLES 1
208#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2
209#define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3
202 210
203/* KVM_IRQ_LINE irq field index values */ 211/* KVM_IRQ_LINE irq field index values */
204#define KVM_ARM_IRQ_TYPE_SHIFT 24 212#define KVM_ARM_IRQ_TYPE_SHIFT 24
diff --git a/tools/arch/arm64/include/uapi/asm/kvm.h b/tools/arch/arm64/include/uapi/asm/kvm.h
index c2860358ae3e..70eea2ecc663 100644
--- a/tools/arch/arm64/include/uapi/asm/kvm.h
+++ b/tools/arch/arm64/include/uapi/asm/kvm.h
@@ -39,6 +39,8 @@
39#define __KVM_HAVE_IRQ_LINE 39#define __KVM_HAVE_IRQ_LINE
40#define __KVM_HAVE_READONLY_MEM 40#define __KVM_HAVE_READONLY_MEM
41 41
42#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
43
42#define KVM_REG_SIZE(id) \ 44#define KVM_REG_SIZE(id) \
43 (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT)) 45 (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
44 46
@@ -143,6 +145,8 @@ struct kvm_debug_exit_arch {
143#define KVM_GUESTDBG_USE_HW (1 << 17) 145#define KVM_GUESTDBG_USE_HW (1 << 17)
144 146
145struct kvm_sync_regs { 147struct kvm_sync_regs {
148 /* Used with KVM_CAP_ARM_USER_IRQ */
149 __u64 device_irq_level;
146}; 150};
147 151
148struct kvm_arch_memory_slot { 152struct kvm_arch_memory_slot {
@@ -212,13 +216,17 @@ struct kvm_arch_memory_slot {
212#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5 216#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
213#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6 217#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
214#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7 218#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
219#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8
215#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10 220#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
216#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \ 221#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
217 (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) 222 (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
218#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff 223#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
219#define VGIC_LEVEL_INFO_LINE_LEVEL 0 224#define VGIC_LEVEL_INFO_LINE_LEVEL 0
220 225
221#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 226#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
227#define KVM_DEV_ARM_ITS_SAVE_TABLES 1
228#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2
229#define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3
222 230
223/* Device Control API on vcpu fd */ 231/* Device Control API on vcpu fd */
224#define KVM_ARM_VCPU_PMU_V3_CTRL 0 232#define KVM_ARM_VCPU_PMU_V3_CTRL 0
diff --git a/tools/arch/powerpc/include/uapi/asm/kvm.h b/tools/arch/powerpc/include/uapi/asm/kvm.h
index 4edbe4bb0e8b..07fbeb927834 100644
--- a/tools/arch/powerpc/include/uapi/asm/kvm.h
+++ b/tools/arch/powerpc/include/uapi/asm/kvm.h
@@ -29,6 +29,9 @@
29#define __KVM_HAVE_IRQ_LINE 29#define __KVM_HAVE_IRQ_LINE
30#define __KVM_HAVE_GUEST_DEBUG 30#define __KVM_HAVE_GUEST_DEBUG
31 31
32/* Not always available, but if it is, this is the correct offset. */
33#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
34
32struct kvm_regs { 35struct kvm_regs {
33 __u64 pc; 36 __u64 pc;
34 __u64 cr; 37 __u64 cr;
diff --git a/tools/arch/s390/include/uapi/asm/kvm.h b/tools/arch/s390/include/uapi/asm/kvm.h
index 7f4fd65e9208..3dd2a1d308dd 100644
--- a/tools/arch/s390/include/uapi/asm/kvm.h
+++ b/tools/arch/s390/include/uapi/asm/kvm.h
@@ -26,6 +26,8 @@
26#define KVM_DEV_FLIC_ADAPTER_REGISTER 6 26#define KVM_DEV_FLIC_ADAPTER_REGISTER 6
27#define KVM_DEV_FLIC_ADAPTER_MODIFY 7 27#define KVM_DEV_FLIC_ADAPTER_MODIFY 7
28#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8 28#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8
29#define KVM_DEV_FLIC_AISM 9
30#define KVM_DEV_FLIC_AIRQ_INJECT 10
29/* 31/*
30 * We can have up to 4*64k pending subchannels + 8 adapter interrupts, 32 * We can have up to 4*64k pending subchannels + 8 adapter interrupts,
31 * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts. 33 * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
@@ -41,7 +43,14 @@ struct kvm_s390_io_adapter {
41 __u8 isc; 43 __u8 isc;
42 __u8 maskable; 44 __u8 maskable;
43 __u8 swap; 45 __u8 swap;
44 __u8 pad; 46 __u8 flags;
47};
48
49#define KVM_S390_ADAPTER_SUPPRESSIBLE 0x01
50
51struct kvm_s390_ais_req {
52 __u8 isc;
53 __u16 mode;
45}; 54};
46 55
47#define KVM_S390_IO_ADAPTER_MASK 1 56#define KVM_S390_IO_ADAPTER_MASK 1
@@ -110,6 +119,7 @@ struct kvm_s390_vm_cpu_machine {
110#define KVM_S390_VM_CPU_FEAT_CMMA 10 119#define KVM_S390_VM_CPU_FEAT_CMMA 10
111#define KVM_S390_VM_CPU_FEAT_PFMFI 11 120#define KVM_S390_VM_CPU_FEAT_PFMFI 11
112#define KVM_S390_VM_CPU_FEAT_SIGPIF 12 121#define KVM_S390_VM_CPU_FEAT_SIGPIF 12
122#define KVM_S390_VM_CPU_FEAT_KSS 13
113struct kvm_s390_vm_cpu_feat { 123struct kvm_s390_vm_cpu_feat {
114 __u64 feat[16]; 124 __u64 feat[16];
115}; 125};
@@ -198,6 +208,10 @@ struct kvm_guest_debug_arch {
198#define KVM_SYNC_VRS (1UL << 6) 208#define KVM_SYNC_VRS (1UL << 6)
199#define KVM_SYNC_RICCB (1UL << 7) 209#define KVM_SYNC_RICCB (1UL << 7)
200#define KVM_SYNC_FPRS (1UL << 8) 210#define KVM_SYNC_FPRS (1UL << 8)
211#define KVM_SYNC_GSCB (1UL << 9)
212/* length and alignment of the sdnx as a power of two */
213#define SDNXC 8
214#define SDNXL (1UL << SDNXC)
201/* definition of registers in kvm_run */ 215/* definition of registers in kvm_run */
202struct kvm_sync_regs { 216struct kvm_sync_regs {
203 __u64 prefix; /* prefix register */ 217 __u64 prefix; /* prefix register */
@@ -218,8 +232,16 @@ struct kvm_sync_regs {
218 }; 232 };
219 __u8 reserved[512]; /* for future vector expansion */ 233 __u8 reserved[512]; /* for future vector expansion */
220 __u32 fpc; /* valid on KVM_SYNC_VRS or KVM_SYNC_FPRS */ 234 __u32 fpc; /* valid on KVM_SYNC_VRS or KVM_SYNC_FPRS */
221 __u8 padding[52]; /* riccb needs to be 64byte aligned */ 235 __u8 padding1[52]; /* riccb needs to be 64byte aligned */
222 __u8 riccb[64]; /* runtime instrumentation controls block */ 236 __u8 riccb[64]; /* runtime instrumentation controls block */
237 __u8 padding2[192]; /* sdnx needs to be 256byte aligned */
238 union {
239 __u8 sdnx[SDNXL]; /* state description annex */
240 struct {
241 __u64 reserved1[2];
242 __u64 gscb[4];
243 };
244 };
223}; 245};
224 246
225#define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1) 247#define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1)
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index 0fe00446f9ca..2701e5f8145b 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -202,6 +202,8 @@
202#define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */ 202#define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */
203#define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */ 203#define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */
204 204
205#define X86_FEATURE_MBA ( 7*32+18) /* Memory Bandwidth Allocation */
206
205/* Virtualization flags: Linux defined, word 8 */ 207/* Virtualization flags: Linux defined, word 8 */
206#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ 208#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
207#define X86_FEATURE_VNMI ( 8*32+ 1) /* Intel Virtual NMI */ 209#define X86_FEATURE_VNMI ( 8*32+ 1) /* Intel Virtual NMI */
diff --git a/tools/arch/x86/include/asm/disabled-features.h b/tools/arch/x86/include/asm/disabled-features.h
index 85599ad4d024..5dff775af7cd 100644
--- a/tools/arch/x86/include/asm/disabled-features.h
+++ b/tools/arch/x86/include/asm/disabled-features.h
@@ -36,6 +36,12 @@
36# define DISABLE_OSPKE (1<<(X86_FEATURE_OSPKE & 31)) 36# define DISABLE_OSPKE (1<<(X86_FEATURE_OSPKE & 31))
37#endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */ 37#endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */
38 38
39#ifdef CONFIG_X86_5LEVEL
40# define DISABLE_LA57 0
41#else
42# define DISABLE_LA57 (1<<(X86_FEATURE_LA57 & 31))
43#endif
44
39/* 45/*
40 * Make sure to add features to the correct mask 46 * Make sure to add features to the correct mask
41 */ 47 */
@@ -55,7 +61,7 @@
55#define DISABLED_MASK13 0 61#define DISABLED_MASK13 0
56#define DISABLED_MASK14 0 62#define DISABLED_MASK14 0
57#define DISABLED_MASK15 0 63#define DISABLED_MASK15 0
58#define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE) 64#define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57)
59#define DISABLED_MASK17 0 65#define DISABLED_MASK17 0
60#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18) 66#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
61 67
diff --git a/tools/arch/x86/include/asm/required-features.h b/tools/arch/x86/include/asm/required-features.h
index fac9a5c0abe9..d91ba04dd007 100644
--- a/tools/arch/x86/include/asm/required-features.h
+++ b/tools/arch/x86/include/asm/required-features.h
@@ -53,6 +53,12 @@
53# define NEED_MOVBE 0 53# define NEED_MOVBE 0
54#endif 54#endif
55 55
56#ifdef CONFIG_X86_5LEVEL
57# define NEED_LA57 (1<<(X86_FEATURE_LA57 & 31))
58#else
59# define NEED_LA57 0
60#endif
61
56#ifdef CONFIG_X86_64 62#ifdef CONFIG_X86_64
57#ifdef CONFIG_PARAVIRT 63#ifdef CONFIG_PARAVIRT
58/* Paravirtualized systems may not have PSE or PGE available */ 64/* Paravirtualized systems may not have PSE or PGE available */
@@ -98,7 +104,7 @@
98#define REQUIRED_MASK13 0 104#define REQUIRED_MASK13 0
99#define REQUIRED_MASK14 0 105#define REQUIRED_MASK14 0
100#define REQUIRED_MASK15 0 106#define REQUIRED_MASK15 0
101#define REQUIRED_MASK16 0 107#define REQUIRED_MASK16 (NEED_LA57)
102#define REQUIRED_MASK17 0 108#define REQUIRED_MASK17 0
103#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18) 109#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
104 110
diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h
index 739c0c594022..c2824d02ba37 100644
--- a/tools/arch/x86/include/uapi/asm/kvm.h
+++ b/tools/arch/x86/include/uapi/asm/kvm.h
@@ -9,6 +9,9 @@
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/ioctl.h> 10#include <linux/ioctl.h>
11 11
12#define KVM_PIO_PAGE_OFFSET 1
13#define KVM_COALESCED_MMIO_PAGE_OFFSET 2
14
12#define DE_VECTOR 0 15#define DE_VECTOR 0
13#define DB_VECTOR 1 16#define DB_VECTOR 1
14#define BP_VECTOR 3 17#define BP_VECTOR 3
diff --git a/tools/arch/x86/include/uapi/asm/vmx.h b/tools/arch/x86/include/uapi/asm/vmx.h
index 14458658e988..690a2dcf4078 100644
--- a/tools/arch/x86/include/uapi/asm/vmx.h
+++ b/tools/arch/x86/include/uapi/asm/vmx.h
@@ -76,7 +76,11 @@
76#define EXIT_REASON_WBINVD 54 76#define EXIT_REASON_WBINVD 54
77#define EXIT_REASON_XSETBV 55 77#define EXIT_REASON_XSETBV 55
78#define EXIT_REASON_APIC_WRITE 56 78#define EXIT_REASON_APIC_WRITE 56
79#define EXIT_REASON_RDRAND 57
79#define EXIT_REASON_INVPCID 58 80#define EXIT_REASON_INVPCID 58
81#define EXIT_REASON_VMFUNC 59
82#define EXIT_REASON_ENCLS 60
83#define EXIT_REASON_RDSEED 61
80#define EXIT_REASON_PML_FULL 62 84#define EXIT_REASON_PML_FULL 62
81#define EXIT_REASON_XSAVES 63 85#define EXIT_REASON_XSAVES 63
82#define EXIT_REASON_XRSTORS 64 86#define EXIT_REASON_XRSTORS 64
@@ -90,6 +94,7 @@
90 { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \ 94 { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \
91 { EXIT_REASON_CPUID, "CPUID" }, \ 95 { EXIT_REASON_CPUID, "CPUID" }, \
92 { EXIT_REASON_HLT, "HLT" }, \ 96 { EXIT_REASON_HLT, "HLT" }, \
97 { EXIT_REASON_INVD, "INVD" }, \
93 { EXIT_REASON_INVLPG, "INVLPG" }, \ 98 { EXIT_REASON_INVLPG, "INVLPG" }, \
94 { EXIT_REASON_RDPMC, "RDPMC" }, \ 99 { EXIT_REASON_RDPMC, "RDPMC" }, \
95 { EXIT_REASON_RDTSC, "RDTSC" }, \ 100 { EXIT_REASON_RDTSC, "RDTSC" }, \
@@ -108,6 +113,8 @@
108 { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \ 113 { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \
109 { EXIT_REASON_MSR_READ, "MSR_READ" }, \ 114 { EXIT_REASON_MSR_READ, "MSR_READ" }, \
110 { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \ 115 { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \
116 { EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \
117 { EXIT_REASON_MSR_LOAD_FAIL, "MSR_LOAD_FAIL" }, \
111 { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \ 118 { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \
112 { EXIT_REASON_MONITOR_TRAP_FLAG, "MONITOR_TRAP_FLAG" }, \ 119 { EXIT_REASON_MONITOR_TRAP_FLAG, "MONITOR_TRAP_FLAG" }, \
113 { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \ 120 { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \
@@ -115,20 +122,24 @@
115 { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \ 122 { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
116 { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \ 123 { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
117 { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \ 124 { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
118 { EXIT_REASON_GDTR_IDTR, "GDTR_IDTR" }, \ 125 { EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \
119 { EXIT_REASON_LDTR_TR, "LDTR_TR" }, \ 126 { EXIT_REASON_GDTR_IDTR, "GDTR_IDTR" }, \
127 { EXIT_REASON_LDTR_TR, "LDTR_TR" }, \
120 { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \ 128 { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
121 { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \ 129 { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
122 { EXIT_REASON_INVEPT, "INVEPT" }, \ 130 { EXIT_REASON_INVEPT, "INVEPT" }, \
131 { EXIT_REASON_RDTSCP, "RDTSCP" }, \
123 { EXIT_REASON_PREEMPTION_TIMER, "PREEMPTION_TIMER" }, \ 132 { EXIT_REASON_PREEMPTION_TIMER, "PREEMPTION_TIMER" }, \
133 { EXIT_REASON_INVVPID, "INVVPID" }, \
124 { EXIT_REASON_WBINVD, "WBINVD" }, \ 134 { EXIT_REASON_WBINVD, "WBINVD" }, \
135 { EXIT_REASON_XSETBV, "XSETBV" }, \
125 { EXIT_REASON_APIC_WRITE, "APIC_WRITE" }, \ 136 { EXIT_REASON_APIC_WRITE, "APIC_WRITE" }, \
126 { EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \ 137 { EXIT_REASON_RDRAND, "RDRAND" }, \
127 { EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \
128 { EXIT_REASON_MSR_LOAD_FAIL, "MSR_LOAD_FAIL" }, \
129 { EXIT_REASON_INVD, "INVD" }, \
130 { EXIT_REASON_INVVPID, "INVVPID" }, \
131 { EXIT_REASON_INVPCID, "INVPCID" }, \ 138 { EXIT_REASON_INVPCID, "INVPCID" }, \
139 { EXIT_REASON_VMFUNC, "VMFUNC" }, \
140 { EXIT_REASON_ENCLS, "ENCLS" }, \
141 { EXIT_REASON_RDSEED, "RDSEED" }, \
142 { EXIT_REASON_PML_FULL, "PML_FULL" }, \
132 { EXIT_REASON_XSAVES, "XSAVES" }, \ 143 { EXIT_REASON_XSAVES, "XSAVES" }, \
133 { EXIT_REASON_XRSTORS, "XRSTORS" } 144 { EXIT_REASON_XRSTORS, "XRSTORS" }
134 145
diff --git a/tools/build/feature/test-bpf.c b/tools/build/feature/test-bpf.c
index ebc6dceddb58..7598361ef1f1 100644
--- a/tools/build/feature/test-bpf.c
+++ b/tools/build/feature/test-bpf.c
@@ -29,6 +29,7 @@ int main(void)
29 attr.log_size = 0; 29 attr.log_size = 0;
30 attr.log_level = 0; 30 attr.log_level = 0;
31 attr.kern_version = 0; 31 attr.kern_version = 0;
32 attr.prog_flags = 0;
32 33
33 /* 34 /*
34 * Test existence of __NR_bpf and BPF_PROG_LOAD. 35 * Test existence of __NR_bpf and BPF_PROG_LOAD.
diff --git a/tools/hv/bondvf.sh b/tools/hv/bondvf.sh
index d85968cb1bf2..89b25068cd98 100755
--- a/tools/hv/bondvf.sh
+++ b/tools/hv/bondvf.sh
@@ -102,15 +102,30 @@ function create_bond_cfg_redhat {
102} 102}
103 103
104function del_eth_cfg_ubuntu { 104function del_eth_cfg_ubuntu {
105 local fn=$cfgdir/interfaces 105 local mainfn=$cfgdir/interfaces
106 local fnlist=( $mainfn )
107
108 local dirlist=(`awk '/^[ \t]*source/{print $2}' $mainfn`)
109
110 local i
111 for i in "${dirlist[@]}"
112 do
113 fnlist+=(`ls $i 2>/dev/null`)
114 done
115
106 local tmpfl=$(mktemp) 116 local tmpfl=$(mktemp)
107 117
108 local nic_start='^[ \t]*(auto|iface|mapping|allow-.*)[ \t]+'$1 118 local nic_start='^[ \t]*(auto|iface|mapping|allow-.*)[ \t]+'$1
109 local nic_end='^[ \t]*(auto|iface|mapping|allow-.*|source)' 119 local nic_end='^[ \t]*(auto|iface|mapping|allow-.*|source)'
110 120
111 awk "/$nic_end/{x=0} x{next} /$nic_start/{x=1;next} 1" $fn >$tmpfl 121 local fn
122 for fn in "${fnlist[@]}"
123 do
124 awk "/$nic_end/{x=0} x{next} /$nic_start/{x=1;next} 1" \
125 $fn >$tmpfl
112 126
113 cp $tmpfl $fn 127 cp $tmpfl $fn
128 done
114 129
115 rm $tmpfl 130 rm $tmpfl
116} 131}
@@ -119,7 +134,6 @@ function create_eth_cfg_ubuntu {
119 local fn=$cfgdir/interfaces 134 local fn=$cfgdir/interfaces
120 135
121 del_eth_cfg_ubuntu $1 136 del_eth_cfg_ubuntu $1
122
123 echo $'\n'auto $1 >>$fn 137 echo $'\n'auto $1 >>$fn
124 echo iface $1 inet manual >>$fn 138 echo iface $1 inet manual >>$fn
125 echo bond-master $2 >>$fn 139 echo bond-master $2 >>$fn
@@ -128,7 +142,10 @@ function create_eth_cfg_ubuntu {
128function create_eth_cfg_pri_ubuntu { 142function create_eth_cfg_pri_ubuntu {
129 local fn=$cfgdir/interfaces 143 local fn=$cfgdir/interfaces
130 144
131 create_eth_cfg_ubuntu $1 $2 145 del_eth_cfg_ubuntu $1
146 echo $'\n'allow-hotplug $1 >>$fn
147 echo iface $1 inet manual >>$fn
148 echo bond-master $2 >>$fn
132 echo bond-primary $1 >>$fn 149 echo bond-primary $1 >>$fn
133} 150}
134 151
@@ -153,7 +170,11 @@ function create_eth_cfg_suse {
153} 170}
154 171
155function create_eth_cfg_pri_suse { 172function create_eth_cfg_pri_suse {
156 create_eth_cfg_suse $1 173 local fn=$cfgdir/ifcfg-$1
174
175 rm -f $fn
176 echo BOOTPROTO=none >>$fn
177 echo STARTMODE=hotplug >>$fn
157} 178}
158 179
159function create_bond_cfg_suse { 180function create_bond_cfg_suse {
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index f1758fcbc37d..88b20e007c05 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -39,6 +39,7 @@
39#include <fcntl.h> 39#include <fcntl.h>
40#include <dirent.h> 40#include <dirent.h>
41#include <net/if.h> 41#include <net/if.h>
42#include <limits.h>
42#include <getopt.h> 43#include <getopt.h>
43 44
44/* 45/*
@@ -97,6 +98,8 @@ static struct utsname uts_buf;
97#define KVP_SCRIPTS_PATH "/usr/libexec/hypervkvpd/" 98#define KVP_SCRIPTS_PATH "/usr/libexec/hypervkvpd/"
98#endif 99#endif
99 100
101#define KVP_NET_DIR "/sys/class/net/"
102
100#define MAX_FILE_NAME 100 103#define MAX_FILE_NAME 100
101#define ENTRIES_PER_BLOCK 50 104#define ENTRIES_PER_BLOCK 50
102 105
@@ -596,26 +599,21 @@ static char *kvp_get_if_name(char *guid)
596 DIR *dir; 599 DIR *dir;
597 struct dirent *entry; 600 struct dirent *entry;
598 FILE *file; 601 FILE *file;
599 char *p, *q, *x; 602 char *p, *x;
600 char *if_name = NULL; 603 char *if_name = NULL;
601 char buf[256]; 604 char buf[256];
602 char *kvp_net_dir = "/sys/class/net/"; 605 char dev_id[PATH_MAX];
603 char dev_id[256];
604 606
605 dir = opendir(kvp_net_dir); 607 dir = opendir(KVP_NET_DIR);
606 if (dir == NULL) 608 if (dir == NULL)
607 return NULL; 609 return NULL;
608 610
609 snprintf(dev_id, sizeof(dev_id), "%s", kvp_net_dir);
610 q = dev_id + strlen(kvp_net_dir);
611
612 while ((entry = readdir(dir)) != NULL) { 611 while ((entry = readdir(dir)) != NULL) {
613 /* 612 /*
614 * Set the state for the next pass. 613 * Set the state for the next pass.
615 */ 614 */
616 *q = '\0'; 615 snprintf(dev_id, sizeof(dev_id), "%s%s/device/device_id",
617 strcat(dev_id, entry->d_name); 616 KVP_NET_DIR, entry->d_name);
618 strcat(dev_id, "/device/device_id");
619 617
620 file = fopen(dev_id, "r"); 618 file = fopen(dev_id, "r");
621 if (file == NULL) 619 if (file == NULL)
@@ -653,12 +651,12 @@ static char *kvp_if_name_to_mac(char *if_name)
653 FILE *file; 651 FILE *file;
654 char *p, *x; 652 char *p, *x;
655 char buf[256]; 653 char buf[256];
656 char addr_file[256]; 654 char addr_file[PATH_MAX];
657 unsigned int i; 655 unsigned int i;
658 char *mac_addr = NULL; 656 char *mac_addr = NULL;
659 657
660 snprintf(addr_file, sizeof(addr_file), "%s%s%s", "/sys/class/net/", 658 snprintf(addr_file, sizeof(addr_file), "%s%s%s", KVP_NET_DIR,
661 if_name, "/address"); 659 if_name, "/address");
662 660
663 file = fopen(addr_file, "r"); 661 file = fopen(addr_file, "r");
664 if (file == NULL) 662 if (file == NULL)
@@ -688,28 +686,22 @@ static char *kvp_mac_to_if_name(char *mac)
688 DIR *dir; 686 DIR *dir;
689 struct dirent *entry; 687 struct dirent *entry;
690 FILE *file; 688 FILE *file;
691 char *p, *q, *x; 689 char *p, *x;
692 char *if_name = NULL; 690 char *if_name = NULL;
693 char buf[256]; 691 char buf[256];
694 char *kvp_net_dir = "/sys/class/net/"; 692 char dev_id[PATH_MAX];
695 char dev_id[256];
696 unsigned int i; 693 unsigned int i;
697 694
698 dir = opendir(kvp_net_dir); 695 dir = opendir(KVP_NET_DIR);
699 if (dir == NULL) 696 if (dir == NULL)
700 return NULL; 697 return NULL;
701 698
702 snprintf(dev_id, sizeof(dev_id), "%s", kvp_net_dir);
703 q = dev_id + strlen(kvp_net_dir);
704
705 while ((entry = readdir(dir)) != NULL) { 699 while ((entry = readdir(dir)) != NULL) {
706 /* 700 /*
707 * Set the state for the next pass. 701 * Set the state for the next pass.
708 */ 702 */
709 *q = '\0'; 703 snprintf(dev_id, sizeof(dev_id), "%s%s/address", KVP_NET_DIR,
710 704 entry->d_name);
711 strcat(dev_id, entry->d_name);
712 strcat(dev_id, "/address");
713 705
714 file = fopen(dev_id, "r"); 706 file = fopen(dev_id, "r");
715 if (file == NULL) 707 if (file == NULL)
@@ -1218,9 +1210,9 @@ static int process_ip_string(FILE *f, char *ip_string, int type)
1218static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) 1210static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
1219{ 1211{
1220 int error = 0; 1212 int error = 0;
1221 char if_file[128]; 1213 char if_file[PATH_MAX];
1222 FILE *file; 1214 FILE *file;
1223 char cmd[512]; 1215 char cmd[PATH_MAX];
1224 char *mac_addr; 1216 char *mac_addr;
1225 1217
1226 /* 1218 /*
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index e0829809c897..7ba54195934c 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -261,7 +261,9 @@ int main(int argc, char *argv[])
261 if (len != sizeof(struct hv_vss_msg)) { 261 if (len != sizeof(struct hv_vss_msg)) {
262 syslog(LOG_ERR, "write failed; error: %d %s", errno, 262 syslog(LOG_ERR, "write failed; error: %d %s", errno,
263 strerror(errno)); 263 strerror(errno));
264 exit(EXIT_FAILURE); 264
265 if (op == VSS_OP_FREEZE)
266 vss_operate(VSS_OP_THAW);
265 } 267 }
266 } 268 }
267 269
diff --git a/tools/iio/Makefile b/tools/iio/Makefile
index 5446d625e17d..8f08e03a9a5e 100644
--- a/tools/iio/Makefile
+++ b/tools/iio/Makefile
@@ -1,5 +1,5 @@
1CC = $(CROSS_COMPILE)gcc 1CC = $(CROSS_COMPILE)gcc
2CFLAGS += -Wall -g -D_GNU_SOURCE 2CFLAGS += -Wall -g -D_GNU_SOURCE -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
3 3
4BINDIR=usr/bin 4BINDIR=usr/bin
5INSTALL_PROGRAM=install -m 755 -p 5INSTALL_PROGRAM=install -m 755 -p
diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h
index 780f2014f8fa..8b379da26e35 100644
--- a/tools/iio/iio_utils.h
+++ b/tools/iio/iio_utils.h
@@ -13,7 +13,7 @@
13#include <stdint.h> 13#include <stdint.h>
14 14
15/* Made up value to limit allocation sizes */ 15/* Made up value to limit allocation sizes */
16#define IIO_MAX_NAME_LENGTH 30 16#define IIO_MAX_NAME_LENGTH 64
17 17
18#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements" 18#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
19#define FORMAT_TYPE_FILE "%s_type" 19#define FORMAT_TYPE_FILE "%s_type"
diff --git a/tools/include/asm/sections.h b/tools/include/asm/sections.h
new file mode 100644
index 000000000000..a80643d7a7f1
--- /dev/null
+++ b/tools/include/asm/sections.h
@@ -0,0 +1,4 @@
1#ifndef __TOOLS_INCLUDE_LINUX_ASM_SECTIONS_H
2#define __TOOLS_INCLUDE_LINUX_ASM_SECTIONS_H
3
4#endif /* __TOOLS_INCLUDE_LINUX_ASM_SECTIONS_H */
diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h
index 1aecad369af5..969db1981868 100644
--- a/tools/include/linux/bitops.h
+++ b/tools/include/linux/bitops.h
@@ -61,4 +61,14 @@ static inline unsigned fls_long(unsigned long l)
61 return fls64(l); 61 return fls64(l);
62} 62}
63 63
64/**
65 * rol32 - rotate a 32-bit value left
66 * @word: value to rotate
67 * @shift: bits to roll
68 */
69static inline __u32 rol32(__u32 word, unsigned int shift)
70{
71 return (word << shift) | (word >> ((-shift) & 31));
72}
73
64#endif 74#endif
diff --git a/tools/include/linux/compiler-gcc.h b/tools/include/linux/compiler-gcc.h
index 825d44f89a29..bd39b2090ad1 100644
--- a/tools/include/linux/compiler-gcc.h
+++ b/tools/include/linux/compiler-gcc.h
@@ -19,3 +19,13 @@
19 19
20/* &a[0] degrades to a pointer: a different type from an array */ 20/* &a[0] degrades to a pointer: a different type from an array */
21#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) 21#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
22
23#define noinline __attribute__((noinline))
24
25#define __packed __attribute__((packed))
26
27#define __noreturn __attribute__((noreturn))
28
29#define __aligned(x) __attribute__((aligned(x)))
30#define __printf(a, b) __attribute__((format(printf, a, b)))
31#define __scanf(a, b) __attribute__((format(scanf, a, b)))
diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 23299d7e7160..d7a5604c38d7 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -17,6 +17,10 @@
17# define __always_inline inline __attribute__((always_inline)) 17# define __always_inline inline __attribute__((always_inline))
18#endif 18#endif
19 19
20#ifndef noinline
21#define noinline
22#endif
23
20/* Are two types/vars the same type (ignoring qualifiers)? */ 24/* Are two types/vars the same type (ignoring qualifiers)? */
21#ifndef __same_type 25#ifndef __same_type
22# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) 26# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
@@ -45,6 +49,10 @@
45# define __maybe_unused __attribute__((unused)) 49# define __maybe_unused __attribute__((unused))
46#endif 50#endif
47 51
52#ifndef __used
53# define __used __attribute__((__unused__))
54#endif
55
48#ifndef __packed 56#ifndef __packed
49# define __packed __attribute__((__packed__)) 57# define __packed __attribute__((__packed__))
50#endif 58#endif
@@ -65,6 +73,14 @@
65# define unlikely(x) __builtin_expect(!!(x), 0) 73# define unlikely(x) __builtin_expect(!!(x), 0)
66#endif 74#endif
67 75
76#ifndef __init
77# define __init
78#endif
79
80#ifndef noinline
81# define noinline
82#endif
83
68#define uninitialized_var(x) x = *(&(x)) 84#define uninitialized_var(x) x = *(&(x))
69 85
70#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) 86#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
diff --git a/tools/lib/lockdep/uinclude/linux/debug_locks.h b/tools/include/linux/debug_locks.h
index f38eb64df794..61cc7f501168 100644
--- a/tools/lib/lockdep/uinclude/linux/debug_locks.h
+++ b/tools/include/linux/debug_locks.h
@@ -3,8 +3,9 @@
3 3
4#include <stddef.h> 4#include <stddef.h>
5#include <linux/compiler.h> 5#include <linux/compiler.h>
6#include <asm/bug.h>
6 7
7#define DEBUG_LOCKS_WARN_ON(x) (x) 8#define DEBUG_LOCKS_WARN_ON(x) WARN_ON(x)
8 9
9extern bool debug_locks; 10extern bool debug_locks;
10extern bool debug_locks_silent; 11extern bool debug_locks_silent;
diff --git a/tools/include/linux/delay.h b/tools/include/linux/delay.h
new file mode 100644
index 000000000000..55aa4173af1f
--- /dev/null
+++ b/tools/include/linux/delay.h
@@ -0,0 +1,4 @@
1#ifndef _TOOLS_INCLUDE_LINUX_DELAY_H
2#define _TOOLS_INCLUDE_LINUX_DELAY_H
3
4#endif /* _TOOLS_INCLUDE_LINUX_DELAY_H */
diff --git a/tools/include/linux/err.h b/tools/include/linux/err.h
index bdc3dd8131d4..abf0478a8fb2 100644
--- a/tools/include/linux/err.h
+++ b/tools/include/linux/err.h
@@ -46,4 +46,9 @@ static inline bool __must_check IS_ERR(__force const void *ptr)
46 return IS_ERR_VALUE((unsigned long)ptr); 46 return IS_ERR_VALUE((unsigned long)ptr);
47} 47}
48 48
49static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
50{
51 return unlikely(!ptr) || IS_ERR_VALUE((unsigned long)ptr);
52}
53
49#endif /* _LINUX_ERR_H */ 54#endif /* _LINUX_ERR_H */
diff --git a/tools/include/linux/filter.h b/tools/include/linux/filter.h
index 390d7c9685fd..4ce25d43e8e3 100644
--- a/tools/include/linux/filter.h
+++ b/tools/include/linux/filter.h
@@ -208,6 +208,16 @@
208 .off = OFF, \ 208 .off = OFF, \
209 .imm = IMM }) 209 .imm = IMM })
210 210
211/* Unconditional jumps, goto pc + off16 */
212
213#define BPF_JMP_A(OFF) \
214 ((struct bpf_insn) { \
215 .code = BPF_JMP | BPF_JA, \
216 .dst_reg = 0, \
217 .src_reg = 0, \
218 .off = OFF, \
219 .imm = 0 })
220
211/* Function call */ 221/* Function call */
212 222
213#define BPF_EMIT_CALL(FUNC) \ 223#define BPF_EMIT_CALL(FUNC) \
diff --git a/tools/include/linux/ftrace.h b/tools/include/linux/ftrace.h
new file mode 100644
index 000000000000..949f541ce11e
--- /dev/null
+++ b/tools/include/linux/ftrace.h
@@ -0,0 +1,4 @@
1#ifndef _TOOLS_INCLUDE_LINUX_FTRACE_H
2#define _TOOLS_INCLUDE_LINUX_FTRACE_H
3
4#endif /* _TOOLS_INCLUDE_LINUX_FTRACE_H */
diff --git a/tools/include/linux/gfp.h b/tools/include/linux/gfp.h
new file mode 100644
index 000000000000..22030756fbc0
--- /dev/null
+++ b/tools/include/linux/gfp.h
@@ -0,0 +1,4 @@
1#ifndef _TOOLS_INCLUDE_LINUX_GFP_H
2#define _TOOLS_INCLUDE_LINUX_GFP_H
3
4#endif /* _TOOLS_INCLUDE_LINUX_GFP_H */
diff --git a/tools/lib/lockdep/uinclude/linux/hardirq.h b/tools/include/linux/hardirq.h
index c8f3f8f58729..c8f3f8f58729 100644
--- a/tools/lib/lockdep/uinclude/linux/hardirq.h
+++ b/tools/include/linux/hardirq.h
diff --git a/tools/include/linux/interrupt.h b/tools/include/linux/interrupt.h
new file mode 100644
index 000000000000..6be25bbdca9e
--- /dev/null
+++ b/tools/include/linux/interrupt.h
@@ -0,0 +1,4 @@
1#ifndef _TOOLS_INCLUDE_LINUX_INTERRUPT_H
2#define _TOOLS_INCLUDE_LINUX_INTERRUPT_H
3
4#endif /* _TOOLS_INCLUDE_LINUX_INTERRUPT_H */
diff --git a/tools/lib/lockdep/uinclude/linux/irqflags.h b/tools/include/linux/irqflags.h
index 6cc296f0fad0..df77669cfe1c 100644
--- a/tools/lib/lockdep/uinclude/linux/irqflags.h
+++ b/tools/include/linux/irqflags.h
@@ -17,19 +17,19 @@
17#define raw_local_irq_disable() do { } while (0) 17#define raw_local_irq_disable() do { } while (0)
18#define raw_local_irq_enable() do { } while (0) 18#define raw_local_irq_enable() do { } while (0)
19#define raw_local_irq_save(flags) ((flags) = 0) 19#define raw_local_irq_save(flags) ((flags) = 0)
20#define raw_local_irq_restore(flags) do { } while (0) 20#define raw_local_irq_restore(flags) ((void)(flags))
21#define raw_local_save_flags(flags) ((flags) = 0) 21#define raw_local_save_flags(flags) ((flags) = 0)
22#define raw_irqs_disabled_flags(flags) do { } while (0) 22#define raw_irqs_disabled_flags(flags) ((void)(flags))
23#define raw_irqs_disabled() 0 23#define raw_irqs_disabled() 0
24#define raw_safe_halt() 24#define raw_safe_halt()
25 25
26#define local_irq_enable() do { } while (0) 26#define local_irq_enable() do { } while (0)
27#define local_irq_disable() do { } while (0) 27#define local_irq_disable() do { } while (0)
28#define local_irq_save(flags) ((flags) = 0) 28#define local_irq_save(flags) ((flags) = 0)
29#define local_irq_restore(flags) do { } while (0) 29#define local_irq_restore(flags) ((void)(flags))
30#define local_save_flags(flags) ((flags) = 0) 30#define local_save_flags(flags) ((flags) = 0)
31#define irqs_disabled() (1) 31#define irqs_disabled() (1)
32#define irqs_disabled_flags(flags) (0) 32#define irqs_disabled_flags(flags) ((void)(flags), 0)
33#define safe_halt() do { } while (0) 33#define safe_halt() do { } while (0)
34 34
35#define trace_lock_release(x, y) 35#define trace_lock_release(x, y)
diff --git a/tools/include/linux/jhash.h b/tools/include/linux/jhash.h
new file mode 100644
index 000000000000..348c6f47e4cc
--- /dev/null
+++ b/tools/include/linux/jhash.h
@@ -0,0 +1,175 @@
1#ifndef _LINUX_JHASH_H
2#define _LINUX_JHASH_H
3
4/* jhash.h: Jenkins hash support.
5 *
6 * Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net)
7 *
8 * http://burtleburtle.net/bob/hash/
9 *
10 * These are the credits from Bob's sources:
11 *
12 * lookup3.c, by Bob Jenkins, May 2006, Public Domain.
13 *
14 * These are functions for producing 32-bit hashes for hash table lookup.
15 * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
16 * are externally useful functions. Routines to test the hash are included
17 * if SELF_TEST is defined. You can use this free for any purpose. It's in
18 * the public domain. It has no warranty.
19 *
20 * Copyright (C) 2009-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
21 *
22 * I've modified Bob's hash to be useful in the Linux kernel, and
23 * any bugs present are my fault.
24 * Jozsef
25 */
26#include <linux/bitops.h>
27#include <linux/unaligned/packed_struct.h>
28
29/* Best hash sizes are of power of two */
30#define jhash_size(n) ((u32)1<<(n))
31/* Mask the hash value, i.e (value & jhash_mask(n)) instead of (value % n) */
32#define jhash_mask(n) (jhash_size(n)-1)
33
34/* __jhash_mix -- mix 3 32-bit values reversibly. */
35#define __jhash_mix(a, b, c) \
36{ \
37 a -= c; a ^= rol32(c, 4); c += b; \
38 b -= a; b ^= rol32(a, 6); a += c; \
39 c -= b; c ^= rol32(b, 8); b += a; \
40 a -= c; a ^= rol32(c, 16); c += b; \
41 b -= a; b ^= rol32(a, 19); a += c; \
42 c -= b; c ^= rol32(b, 4); b += a; \
43}
44
45/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */
46#define __jhash_final(a, b, c) \
47{ \
48 c ^= b; c -= rol32(b, 14); \
49 a ^= c; a -= rol32(c, 11); \
50 b ^= a; b -= rol32(a, 25); \
51 c ^= b; c -= rol32(b, 16); \
52 a ^= c; a -= rol32(c, 4); \
53 b ^= a; b -= rol32(a, 14); \
54 c ^= b; c -= rol32(b, 24); \
55}
56
57/* An arbitrary initial parameter */
58#define JHASH_INITVAL 0xdeadbeef
59
60/* jhash - hash an arbitrary key
61 * @k: sequence of bytes as key
62 * @length: the length of the key
63 * @initval: the previous hash, or an arbitray value
64 *
65 * The generic version, hashes an arbitrary sequence of bytes.
66 * No alignment or length assumptions are made about the input key.
67 *
68 * Returns the hash value of the key. The result depends on endianness.
69 */
70static inline u32 jhash(const void *key, u32 length, u32 initval)
71{
72 u32 a, b, c;
73 const u8 *k = key;
74
75 /* Set up the internal state */
76 a = b = c = JHASH_INITVAL + length + initval;
77
78 /* All but the last block: affect some 32 bits of (a,b,c) */
79 while (length > 12) {
80 a += __get_unaligned_cpu32(k);
81 b += __get_unaligned_cpu32(k + 4);
82 c += __get_unaligned_cpu32(k + 8);
83 __jhash_mix(a, b, c);
84 length -= 12;
85 k += 12;
86 }
87 /* Last block: affect all 32 bits of (c) */
88 /* All the case statements fall through */
89 switch (length) {
90 case 12: c += (u32)k[11]<<24;
91 case 11: c += (u32)k[10]<<16;
92 case 10: c += (u32)k[9]<<8;
93 case 9: c += k[8];
94 case 8: b += (u32)k[7]<<24;
95 case 7: b += (u32)k[6]<<16;
96 case 6: b += (u32)k[5]<<8;
97 case 5: b += k[4];
98 case 4: a += (u32)k[3]<<24;
99 case 3: a += (u32)k[2]<<16;
100 case 2: a += (u32)k[1]<<8;
101 case 1: a += k[0];
102 __jhash_final(a, b, c);
103 case 0: /* Nothing left to add */
104 break;
105 }
106
107 return c;
108}
109
110/* jhash2 - hash an array of u32's
111 * @k: the key which must be an array of u32's
112 * @length: the number of u32's in the key
113 * @initval: the previous hash, or an arbitray value
114 *
115 * Returns the hash value of the key.
116 */
117static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
118{
119 u32 a, b, c;
120
121 /* Set up the internal state */
122 a = b = c = JHASH_INITVAL + (length<<2) + initval;
123
124 /* Handle most of the key */
125 while (length > 3) {
126 a += k[0];
127 b += k[1];
128 c += k[2];
129 __jhash_mix(a, b, c);
130 length -= 3;
131 k += 3;
132 }
133
134 /* Handle the last 3 u32's: all the case statements fall through */
135 switch (length) {
136 case 3: c += k[2];
137 case 2: b += k[1];
138 case 1: a += k[0];
139 __jhash_final(a, b, c);
140 case 0: /* Nothing left to add */
141 break;
142 }
143
144 return c;
145}
146
147
148/* __jhash_nwords - hash exactly 3, 2 or 1 word(s) */
149static inline u32 __jhash_nwords(u32 a, u32 b, u32 c, u32 initval)
150{
151 a += initval;
152 b += initval;
153 c += initval;
154
155 __jhash_final(a, b, c);
156
157 return c;
158}
159
160static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
161{
162 return __jhash_nwords(a, b, c, initval + JHASH_INITVAL + (3 << 2));
163}
164
165static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
166{
167 return __jhash_nwords(a, b, 0, initval + JHASH_INITVAL + (2 << 2));
168}
169
170static inline u32 jhash_1word(u32 a, u32 initval)
171{
172 return __jhash_nwords(a, 0, 0, initval + JHASH_INITVAL + (1 << 2));
173}
174
175#endif /* _LINUX_JHASH_H */
diff --git a/tools/lib/lockdep/uinclude/linux/kallsyms.h b/tools/include/linux/kallsyms.h
index b0f2dbdf1a15..582cc1e5f3a4 100644
--- a/tools/lib/lockdep/uinclude/linux/kallsyms.h
+++ b/tools/include/linux/kallsyms.h
@@ -3,6 +3,7 @@
3 3
4#include <linux/kernel.h> 4#include <linux/kernel.h>
5#include <stdio.h> 5#include <stdio.h>
6#include <unistd.h>
6 7
7#define KSYM_NAME_LEN 128 8#define KSYM_NAME_LEN 128
8 9
@@ -24,7 +25,7 @@ static inline void print_ip_sym(unsigned long ip)
24 25
25 name = backtrace_symbols((void **)&ip, 1); 26 name = backtrace_symbols((void **)&ip, 1);
26 27
27 printf("%s\n", *name); 28 dprintf(STDOUT_FILENO, "%s\n", *name);
28 29
29 free(name); 30 free(name);
30} 31}
diff --git a/tools/lib/lockdep/uinclude/linux/kern_levels.h b/tools/include/linux/kern_levels.h
index 3b9bade28698..3b9bade28698 100644
--- a/tools/lib/lockdep/uinclude/linux/kern_levels.h
+++ b/tools/include/linux/kern_levels.h
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 73ccc48126bb..77d2e94ca5df 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -5,6 +5,8 @@
5#include <stddef.h> 5#include <stddef.h>
6#include <assert.h> 6#include <assert.h>
7#include <linux/compiler.h> 7#include <linux/compiler.h>
8#include <endian.h>
9#include <byteswap.h>
8 10
9#ifndef UINT_MAX 11#ifndef UINT_MAX
10#define UINT_MAX (~0U) 12#define UINT_MAX (~0U)
@@ -32,6 +34,7 @@
32 (type *)((char *)__mptr - offsetof(type, member)); }) 34 (type *)((char *)__mptr - offsetof(type, member)); })
33#endif 35#endif
34 36
37#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
35#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) 38#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
36 39
37#ifndef max 40#ifndef max
@@ -67,12 +70,33 @@
67#endif 70#endif
68#endif 71#endif
69 72
70/* 73#if __BYTE_ORDER == __BIG_ENDIAN
71 * Both need more care to handle endianness 74#define cpu_to_le16 bswap_16
72 * (Don't use bitmap_copy_le() for now) 75#define cpu_to_le32 bswap_32
73 */ 76#define cpu_to_le64 bswap_64
74#define cpu_to_le64(x) (x) 77#define le16_to_cpu bswap_16
75#define cpu_to_le32(x) (x) 78#define le32_to_cpu bswap_32
79#define le64_to_cpu bswap_64
80#define cpu_to_be16
81#define cpu_to_be32
82#define cpu_to_be64
83#define be16_to_cpu
84#define be32_to_cpu
85#define be64_to_cpu
86#else
87#define cpu_to_le16
88#define cpu_to_le32
89#define cpu_to_le64
90#define le16_to_cpu
91#define le32_to_cpu
92#define le64_to_cpu
93#define cpu_to_be16 bswap_16
94#define cpu_to_be32 bswap_32
95#define cpu_to_be64 bswap_64
96#define be16_to_cpu bswap_16
97#define be32_to_cpu bswap_32
98#define be64_to_cpu bswap_64
99#endif
76 100
77int vscnprintf(char *buf, size_t size, const char *fmt, va_list args); 101int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
78int scnprintf(char * buf, size_t size, const char * fmt, ...); 102int scnprintf(char * buf, size_t size, const char * fmt, ...);
@@ -89,4 +113,7 @@ int scnprintf(char * buf, size_t size, const char * fmt, ...);
89#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) 113#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
90#define round_down(x, y) ((x) & ~__round_mask(x, y)) 114#define round_down(x, y) ((x) & ~__round_mask(x, y))
91 115
116#define current_gfp_context(k) 0
117#define synchronize_sched()
118
92#endif 119#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kmemcheck.h b/tools/include/linux/kmemcheck.h
index 94d598bc6abe..94d598bc6abe 100644
--- a/tools/lib/lockdep/uinclude/linux/kmemcheck.h
+++ b/tools/include/linux/kmemcheck.h
diff --git a/tools/include/linux/linkage.h b/tools/include/linux/linkage.h
new file mode 100644
index 000000000000..bc763d500262
--- /dev/null
+++ b/tools/include/linux/linkage.h
@@ -0,0 +1,4 @@
1#ifndef _TOOLS_INCLUDE_LINUX_LINKAGE_H
2#define _TOOLS_INCLUDE_LINUX_LINKAGE_H
3
4#endif /* _TOOLS_INCLUDE_LINUX_LINKAGE_H */
diff --git a/tools/lib/lockdep/uinclude/linux/lockdep.h b/tools/include/linux/lockdep.h
index c808c7d02d21..8da3e8effafa 100644
--- a/tools/lib/lockdep/uinclude/linux/lockdep.h
+++ b/tools/include/linux/lockdep.h
@@ -7,8 +7,15 @@
7#include <limits.h> 7#include <limits.h>
8#include <linux/utsname.h> 8#include <linux/utsname.h>
9#include <linux/compiler.h> 9#include <linux/compiler.h>
10#include <linux/export.h>
11#include <linux/kern_levels.h>
12#include <linux/err.h>
13#include <linux/rcu.h>
14#include <linux/list.h>
15#include <linux/hardirq.h>
16#include <unistd.h>
10 17
11#define MAX_LOCK_DEPTH 2000UL 18#define MAX_LOCK_DEPTH 63UL
12 19
13#define asmlinkage 20#define asmlinkage
14#define __visible 21#define __visible
@@ -29,31 +36,32 @@ extern struct task_struct *__curr(void);
29 36
30#define current (__curr()) 37#define current (__curr())
31 38
32#define debug_locks_off() 1 39static inline int debug_locks_off(void)
40{
41 return 1;
42}
43
33#define task_pid_nr(tsk) ((tsk)->pid) 44#define task_pid_nr(tsk) ((tsk)->pid)
34 45
35#define KSYM_NAME_LEN 128 46#define KSYM_NAME_LEN 128
36#define printk printf 47#define printk(...) dprintf(STDOUT_FILENO, __VA_ARGS__)
48#define pr_err(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
49#define pr_warn pr_err
37 50
38#define list_del_rcu list_del 51#define list_del_rcu list_del
39 52
40#define atomic_t unsigned long 53#define atomic_t unsigned long
41#define atomic_inc(x) ((*(x))++) 54#define atomic_inc(x) ((*(x))++)
42 55
43static struct new_utsname *init_utsname(void)
44{
45 static struct new_utsname n = (struct new_utsname) {
46 .release = "liblockdep",
47 .version = LIBLOCKDEP_VERSION,
48 };
49
50 return &n;
51}
52
53#define print_tainted() "" 56#define print_tainted() ""
54#define static_obj(x) 1 57#define static_obj(x) 1
55 58
56#define debug_show_all_locks() 59#define debug_show_all_locks()
57extern void debug_check_no_locks_held(void); 60extern void debug_check_no_locks_held(void);
58 61
62static __used bool __is_kernel_percpu_address(unsigned long addr, void *can_addr)
63{
64 return false;
65}
66
59#endif 67#endif
diff --git a/tools/lib/lockdep/uinclude/linux/module.h b/tools/include/linux/module.h
index 09c7a7be8ccc..07055db296f3 100644
--- a/tools/lib/lockdep/uinclude/linux/module.h
+++ b/tools/include/linux/module.h
@@ -3,4 +3,9 @@
3 3
4#define module_param(name, type, perm) 4#define module_param(name, type, perm)
5 5
6static inline bool __is_module_percpu_address(unsigned long addr, unsigned long *can_addr)
7{
8 return false;
9}
10
6#endif 11#endif
diff --git a/tools/include/linux/mutex.h b/tools/include/linux/mutex.h
new file mode 100644
index 000000000000..a8180d25f2fc
--- /dev/null
+++ b/tools/include/linux/mutex.h
@@ -0,0 +1,4 @@
1#ifndef _TOOLS_INCLUDE_LINUX_MUTEX_H
2#define _TOOLS_INCLUDE_LINUX_MUTEX_H
3
4#endif /* _TOOLS_INCLUDE_LINUX_MUTEX_H */
diff --git a/tools/include/linux/proc_fs.h b/tools/include/linux/proc_fs.h
new file mode 100644
index 000000000000..8b3b03b64fda
--- /dev/null
+++ b/tools/include/linux/proc_fs.h
@@ -0,0 +1,4 @@
1#ifndef _TOOLS_INCLUDE_LINUX_PROC_FS_H
2#define _TOOLS_INCLUDE_LINUX_PROC_FS_H
3
4#endif /* _TOOLS_INCLUDE_LINUX_PROC_FS_H */
diff --git a/tools/lib/lockdep/uinclude/linux/rcu.h b/tools/include/linux/rcu.h
index 042ee8e463c9..5080649dad04 100644
--- a/tools/lib/lockdep/uinclude/linux/rcu.h
+++ b/tools/include/linux/rcu.h
@@ -18,4 +18,7 @@ static inline bool rcu_is_watching(void)
18 return false; 18 return false;
19} 19}
20 20
21#define rcu_assign_pointer(p, v) ((p) = (v))
22#define RCU_INIT_POINTER(p, v) p=(v)
23
21#endif 24#endif
diff --git a/tools/include/linux/sched/clock.h b/tools/include/linux/sched/clock.h
new file mode 100644
index 000000000000..5837d17c4182
--- /dev/null
+++ b/tools/include/linux/sched/clock.h
@@ -0,0 +1,4 @@
1#ifndef _TOOLS_PERF_LINUX_SCHED_CLOCK_H
2#define _TOOLS_PERF_LINUX_SCHED_CLOCK_H
3
4#endif /* _TOOLS_PERF_LINUX_SCHED_CLOCK_H */
diff --git a/tools/include/linux/sched/mm.h b/tools/include/linux/sched/mm.h
new file mode 100644
index 000000000000..c8d9f19c1f35
--- /dev/null
+++ b/tools/include/linux/sched/mm.h
@@ -0,0 +1,4 @@
1#ifndef _TOOLS_PERF_LINUX_SCHED_MM_H
2#define _TOOLS_PERF_LINUX_SCHED_MM_H
3
4#endif /* _TOOLS_PERF_LINUX_SCHED_MM_H */
diff --git a/tools/include/linux/sched/task.h b/tools/include/linux/sched/task.h
new file mode 100644
index 000000000000..a97890eca110
--- /dev/null
+++ b/tools/include/linux/sched/task.h
@@ -0,0 +1,4 @@
1#ifndef _TOOLS_PERF_LINUX_SCHED_TASK_H
2#define _TOOLS_PERF_LINUX_SCHED_TASK_H
3
4#endif /* _TOOLS_PERF_LINUX_SCHED_TASK_H */
diff --git a/tools/include/linux/seq_file.h b/tools/include/linux/seq_file.h
new file mode 100644
index 000000000000..102fd9217f1f
--- /dev/null
+++ b/tools/include/linux/seq_file.h
@@ -0,0 +1,4 @@
1#ifndef _TOOLS_INCLUDE_LINUX_SEQ_FILE_H
2#define _TOOLS_INCLUDE_LINUX_SEQ_FILE_H
3
4#endif /* _TOOLS_INCLUDE_LINUX_SEQ_FILE_H */
diff --git a/tools/include/linux/spinlock.h b/tools/include/linux/spinlock.h
index 58397dcb19d6..417cda4f793f 100644
--- a/tools/include/linux/spinlock.h
+++ b/tools/include/linux/spinlock.h
@@ -1,5 +1,31 @@
1#ifndef __LINUX_SPINLOCK_H_
2#define __LINUX_SPINLOCK_H_
3
4#include <pthread.h>
5#include <stdbool.h>
6
1#define spinlock_t pthread_mutex_t 7#define spinlock_t pthread_mutex_t
2#define DEFINE_SPINLOCK(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER; 8#define DEFINE_SPINLOCK(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER;
3 9
4#define spin_lock_irqsave(x, f) (void)f, pthread_mutex_lock(x) 10#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) 11#define spin_unlock_irqrestore(x, f) (void)f, pthread_mutex_unlock(x)
12
13#define arch_spinlock_t pthread_mutex_t
14#define __ARCH_SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER
15
16static inline void arch_spin_lock(arch_spinlock_t *mutex)
17{
18 pthread_mutex_lock(mutex);
19}
20
21static inline void arch_spin_unlock(arch_spinlock_t *mutex)
22{
23 pthread_mutex_unlock(mutex);
24}
25
26static inline bool arch_spin_is_locked(arch_spinlock_t *mutex)
27{
28 return true;
29}
30
31#endif
diff --git a/tools/lib/lockdep/uinclude/linux/stacktrace.h b/tools/include/linux/stacktrace.h
index 39aecc6b19d1..39aecc6b19d1 100644
--- a/tools/lib/lockdep/uinclude/linux/stacktrace.h
+++ b/tools/include/linux/stacktrace.h
diff --git a/tools/include/linux/unaligned/packed_struct.h b/tools/include/linux/unaligned/packed_struct.h
new file mode 100644
index 000000000000..c0d817de4df2
--- /dev/null
+++ b/tools/include/linux/unaligned/packed_struct.h
@@ -0,0 +1,46 @@
1#ifndef _LINUX_UNALIGNED_PACKED_STRUCT_H
2#define _LINUX_UNALIGNED_PACKED_STRUCT_H
3
4#include <linux/kernel.h>
5
6struct __una_u16 { u16 x; } __packed;
7struct __una_u32 { u32 x; } __packed;
8struct __una_u64 { u64 x; } __packed;
9
10static inline u16 __get_unaligned_cpu16(const void *p)
11{
12 const struct __una_u16 *ptr = (const struct __una_u16 *)p;
13 return ptr->x;
14}
15
16static inline u32 __get_unaligned_cpu32(const void *p)
17{
18 const struct __una_u32 *ptr = (const struct __una_u32 *)p;
19 return ptr->x;
20}
21
22static inline u64 __get_unaligned_cpu64(const void *p)
23{
24 const struct __una_u64 *ptr = (const struct __una_u64 *)p;
25 return ptr->x;
26}
27
28static inline void __put_unaligned_cpu16(u16 val, void *p)
29{
30 struct __una_u16 *ptr = (struct __una_u16 *)p;
31 ptr->x = val;
32}
33
34static inline void __put_unaligned_cpu32(u32 val, void *p)
35{
36 struct __una_u32 *ptr = (struct __una_u32 *)p;
37 ptr->x = val;
38}
39
40static inline void __put_unaligned_cpu64(u64 val, void *p)
41{
42 struct __una_u64 *ptr = (struct __una_u64 *)p;
43 ptr->x = val;
44}
45
46#endif /* _LINUX_UNALIGNED_PACKED_STRUCT_H */
diff --git a/tools/include/trace/events/lock.h b/tools/include/trace/events/lock.h
new file mode 100644
index 000000000000..5b15fd5ee1af
--- /dev/null
+++ b/tools/include/trace/events/lock.h
@@ -0,0 +1,4 @@
1#ifndef _TOOLS_INCLUDE_TRACE_EVENTS_LOCK_H
2#define _TOOLS_INCLUDE_TRACE_EVENTS_LOCK_H
3
4#endif /* _TOOLS_INCLUDE_TRACE_EVENTS_LOCK_H */
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index e553529929f6..ce2988be4f0e 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -82,6 +82,11 @@ enum bpf_cmd {
82 BPF_PROG_ATTACH, 82 BPF_PROG_ATTACH,
83 BPF_PROG_DETACH, 83 BPF_PROG_DETACH,
84 BPF_PROG_TEST_RUN, 84 BPF_PROG_TEST_RUN,
85 BPF_PROG_GET_NEXT_ID,
86 BPF_MAP_GET_NEXT_ID,
87 BPF_PROG_GET_FD_BY_ID,
88 BPF_MAP_GET_FD_BY_ID,
89 BPF_OBJ_GET_INFO_BY_FD,
85}; 90};
86 91
87enum bpf_map_type { 92enum bpf_map_type {
@@ -115,12 +120,14 @@ enum bpf_prog_type {
115 BPF_PROG_TYPE_LWT_IN, 120 BPF_PROG_TYPE_LWT_IN,
116 BPF_PROG_TYPE_LWT_OUT, 121 BPF_PROG_TYPE_LWT_OUT,
117 BPF_PROG_TYPE_LWT_XMIT, 122 BPF_PROG_TYPE_LWT_XMIT,
123 BPF_PROG_TYPE_SOCK_OPS,
118}; 124};
119 125
120enum bpf_attach_type { 126enum bpf_attach_type {
121 BPF_CGROUP_INET_INGRESS, 127 BPF_CGROUP_INET_INGRESS,
122 BPF_CGROUP_INET_EGRESS, 128 BPF_CGROUP_INET_EGRESS,
123 BPF_CGROUP_INET_SOCK_CREATE, 129 BPF_CGROUP_INET_SOCK_CREATE,
130 BPF_CGROUP_SOCK_OPS,
124 __MAX_BPF_ATTACH_TYPE 131 __MAX_BPF_ATTACH_TYPE
125}; 132};
126 133
@@ -132,6 +139,13 @@ enum bpf_attach_type {
132 */ 139 */
133#define BPF_F_ALLOW_OVERRIDE (1U << 0) 140#define BPF_F_ALLOW_OVERRIDE (1U << 0)
134 141
142/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
143 * verifier will perform strict alignment checking as if the kernel
144 * has been built with CONFIG_EFFICIENT_UNALIGNED_ACCESS not set,
145 * and NET_IP_ALIGN defined to 2.
146 */
147#define BPF_F_STRICT_ALIGNMENT (1U << 0)
148
135#define BPF_PSEUDO_MAP_FD 1 149#define BPF_PSEUDO_MAP_FD 1
136 150
137/* flags for BPF_MAP_UPDATE_ELEM command */ 151/* flags for BPF_MAP_UPDATE_ELEM command */
@@ -177,6 +191,7 @@ union bpf_attr {
177 __u32 log_size; /* size of user buffer */ 191 __u32 log_size; /* size of user buffer */
178 __aligned_u64 log_buf; /* user supplied buffer */ 192 __aligned_u64 log_buf; /* user supplied buffer */
179 __u32 kern_version; /* checked when prog_type=kprobe */ 193 __u32 kern_version; /* checked when prog_type=kprobe */
194 __u32 prog_flags;
180 }; 195 };
181 196
182 struct { /* anonymous struct used by BPF_OBJ_* commands */ 197 struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -201,6 +216,21 @@ union bpf_attr {
201 __u32 repeat; 216 __u32 repeat;
202 __u32 duration; 217 __u32 duration;
203 } test; 218 } test;
219
220 struct { /* anonymous struct used by BPF_*_GET_*_ID */
221 union {
222 __u32 start_id;
223 __u32 prog_id;
224 __u32 map_id;
225 };
226 __u32 next_id;
227 };
228
229 struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */
230 __u32 bpf_fd;
231 __u32 info_len;
232 __aligned_u64 info;
233 } info;
204} __attribute__((aligned(8))); 234} __attribute__((aligned(8)));
205 235
206/* BPF helper function descriptions: 236/* BPF helper function descriptions:
@@ -305,8 +335,11 @@ union bpf_attr {
305 * @flags: room for future extensions 335 * @flags: room for future extensions
306 * Return: 0 on success or negative error 336 * Return: 0 on success or negative error
307 * 337 *
308 * u64 bpf_perf_event_read(&map, index) 338 * u64 bpf_perf_event_read(map, flags)
309 * Return: Number events read or error code 339 * read perf event counter value
340 * @map: pointer to perf_event_array map
341 * @flags: index of event in the map or bitmask flags
342 * Return: value of perf event counter read or error code
310 * 343 *
311 * int bpf_redirect(ifindex, flags) 344 * int bpf_redirect(ifindex, flags)
312 * redirect to another netdev 345 * redirect to another netdev
@@ -320,11 +353,11 @@ union bpf_attr {
320 * @skb: pointer to skb 353 * @skb: pointer to skb
321 * Return: realm if != 0 354 * Return: realm if != 0
322 * 355 *
323 * int bpf_perf_event_output(ctx, map, index, data, size) 356 * int bpf_perf_event_output(ctx, map, flags, data, size)
324 * output perf raw sample 357 * output perf raw sample
325 * @ctx: struct pt_regs* 358 * @ctx: struct pt_regs*
326 * @map: pointer to perf_event_array map 359 * @map: pointer to perf_event_array map
327 * @index: index of event in the map 360 * @flags: index of event in the map or bitmask flags
328 * @data: data on stack to be output as raw data 361 * @data: data on stack to be output as raw data
329 * @size: size of data 362 * @size: size of data
330 * Return: 0 on success or negative error 363 * Return: 0 on success or negative error
@@ -481,8 +514,31 @@ union bpf_attr {
481 * u32 bpf_get_socket_uid(skb) 514 * u32 bpf_get_socket_uid(skb)
482 * Get the owner uid of the socket stored inside sk_buff. 515 * Get the owner uid of the socket stored inside sk_buff.
483 * @skb: pointer to skb 516 * @skb: pointer to skb
484 * Return: uid of the socket owner on success or 0 if the socket pointer 517 * Return: uid of the socket owner on success or overflowuid if failed.
485 * inside sk_buff is NULL 518 *
519 * u32 bpf_set_hash(skb, hash)
520 * Set full skb->hash.
521 * @skb: pointer to skb
522 * @hash: hash to set
523 *
524 * int bpf_setsockopt(bpf_socket, level, optname, optval, optlen)
525 * Calls setsockopt. Not all opts are available, only those with
526 * integer optvals plus TCP_CONGESTION.
527 * Supported levels: SOL_SOCKET and IPROTO_TCP
528 * @bpf_socket: pointer to bpf_socket
529 * @level: SOL_SOCKET or IPROTO_TCP
530 * @optname: option name
531 * @optval: pointer to option value
532 * @optlen: length of optval in byes
533 * Return: 0 or negative error
534 *
535 * int bpf_skb_adjust_room(skb, len_diff, mode, flags)
536 * Grow or shrink room in sk_buff.
537 * @skb: pointer to skb
538 * @len_diff: (signed) amount of room to grow/shrink
539 * @mode: operation mode (enum bpf_adj_room_mode)
540 * @flags: reserved for future use
541 * Return: 0 on success or negative error code
486 */ 542 */
487#define __BPF_FUNC_MAPPER(FN) \ 543#define __BPF_FUNC_MAPPER(FN) \
488 FN(unspec), \ 544 FN(unspec), \
@@ -532,7 +588,10 @@ union bpf_attr {
532 FN(xdp_adjust_head), \ 588 FN(xdp_adjust_head), \
533 FN(probe_read_str), \ 589 FN(probe_read_str), \
534 FN(get_socket_cookie), \ 590 FN(get_socket_cookie), \
535 FN(get_socket_uid), 591 FN(get_socket_uid), \
592 FN(set_hash), \
593 FN(setsockopt), \
594 FN(skb_adjust_room),
536 595
537/* integer value in 'imm' field of BPF_CALL instruction selects which helper 596/* integer value in 'imm' field of BPF_CALL instruction selects which helper
538 * function eBPF program intends to call 597 * function eBPF program intends to call
@@ -582,6 +641,11 @@ enum bpf_func_id {
582/* BPF_FUNC_perf_event_output for sk_buff input context. */ 641/* BPF_FUNC_perf_event_output for sk_buff input context. */
583#define BPF_F_CTXLEN_MASK (0xfffffULL << 32) 642#define BPF_F_CTXLEN_MASK (0xfffffULL << 32)
584 643
644/* Mode for BPF_FUNC_skb_adjust_room helper. */
645enum bpf_adj_room_mode {
646 BPF_ADJ_ROOM_NET_OPTS,
647};
648
585/* user accessible mirror of in-kernel sk_buff. 649/* user accessible mirror of in-kernel sk_buff.
586 * new fields can only be added to the end of this structure 650 * new fields can only be added to the end of this structure
587 */ 651 */
@@ -663,4 +727,75 @@ struct xdp_md {
663 __u32 data_end; 727 __u32 data_end;
664}; 728};
665 729
730#define BPF_TAG_SIZE 8
731
732struct bpf_prog_info {
733 __u32 type;
734 __u32 id;
735 __u8 tag[BPF_TAG_SIZE];
736 __u32 jited_prog_len;
737 __u32 xlated_prog_len;
738 __aligned_u64 jited_prog_insns;
739 __aligned_u64 xlated_prog_insns;
740} __attribute__((aligned(8)));
741
742struct bpf_map_info {
743 __u32 type;
744 __u32 id;
745 __u32 key_size;
746 __u32 value_size;
747 __u32 max_entries;
748 __u32 map_flags;
749} __attribute__((aligned(8)));
750
751/* User bpf_sock_ops struct to access socket values and specify request ops
752 * and their replies.
753 * New fields can only be added at the end of this structure
754 */
755struct bpf_sock_ops {
756 __u32 op;
757 union {
758 __u32 reply;
759 __u32 replylong[4];
760 };
761 __u32 family;
762 __u32 remote_ip4;
763 __u32 local_ip4;
764 __u32 remote_ip6[4];
765 __u32 local_ip6[4];
766 __u32 remote_port;
767 __u32 local_port;
768};
769
770/* List of known BPF sock_ops operators.
771 * New entries can only be added at the end
772 */
773enum {
774 BPF_SOCK_OPS_VOID,
775 BPF_SOCK_OPS_TIMEOUT_INIT, /* Should return SYN-RTO value to use or
776 * -1 if default value should be used
777 */
778 BPF_SOCK_OPS_RWND_INIT, /* Should return initial advertized
779 * window (in packets) or -1 if default
780 * value should be used
781 */
782 BPF_SOCK_OPS_TCP_CONNECT_CB, /* Calls BPF program right before an
783 * active connection is initialized
784 */
785 BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB, /* Calls BPF program when an
786 * active connection is
787 * established
788 */
789 BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB, /* Calls BPF program when a
790 * passive connection is
791 * established
792 */
793 BPF_SOCK_OPS_NEEDS_ECN, /* If connection's congestion control
794 * needs ECN
795 */
796};
797
798#define TCP_BPF_IW 1001 /* Set TCP initial congestion window */
799#define TCP_BPF_SNDCWND_CLAMP 1002 /* Set sndcwnd_clamp */
800
666#endif /* _UAPI__LINUX_BPF_H__ */ 801#endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/tools/include/uapi/linux/stat.h b/tools/include/uapi/linux/stat.h
index d538897b8e08..17b10304c393 100644
--- a/tools/include/uapi/linux/stat.h
+++ b/tools/include/uapi/linux/stat.h
@@ -48,17 +48,13 @@
48 * tv_sec holds the number of seconds before (negative) or after (positive) 48 * tv_sec holds the number of seconds before (negative) or after (positive)
49 * 00:00:00 1st January 1970 UTC. 49 * 00:00:00 1st January 1970 UTC.
50 * 50 *
51 * tv_nsec holds a number of nanoseconds before (0..-999,999,999 if tv_sec is 51 * tv_nsec holds a number of nanoseconds (0..999,999,999) after the tv_sec time.
52 * negative) or after (0..999,999,999 if tv_sec is positive) the tv_sec time.
53 *
54 * Note that if both tv_sec and tv_nsec are non-zero, then the two values must
55 * either be both positive or both negative.
56 * 52 *
57 * __reserved is held in case we need a yet finer resolution. 53 * __reserved is held in case we need a yet finer resolution.
58 */ 54 */
59struct statx_timestamp { 55struct statx_timestamp {
60 __s64 tv_sec; 56 __s64 tv_sec;
61 __s32 tv_nsec; 57 __u32 tv_nsec;
62 __s32 __reserved; 58 __s32 __reserved;
63}; 59};
64 60
diff --git a/tools/kvm/kvm_stat/kvm_stat b/tools/kvm/kvm_stat/kvm_stat
index 8f74ed8e7237..dd8f00cfb8b4 100755
--- a/tools/kvm/kvm_stat/kvm_stat
+++ b/tools/kvm/kvm_stat/kvm_stat
@@ -295,114 +295,6 @@ class ArchS390(Arch):
295ARCH = Arch.get_arch() 295ARCH = Arch.get_arch()
296 296
297 297
298def walkdir(path):
299 """Returns os.walk() data for specified directory.
300
301 As it is only a wrapper it returns the same 3-tuple of (dirpath,
302 dirnames, filenames).
303 """
304 return next(os.walk(path))
305
306
307def parse_int_list(list_string):
308 """Returns an int list from a string of comma separated integers and
309 integer ranges."""
310 integers = []
311 members = list_string.split(',')
312
313 for member in members:
314 if '-' not in member:
315 integers.append(int(member))
316 else:
317 int_range = member.split('-')
318 integers.extend(range(int(int_range[0]),
319 int(int_range[1]) + 1))
320
321 return integers
322
323
324def get_pid_from_gname(gname):
325 """Fuzzy function to convert guest name to QEMU process pid.
326
327 Returns a list of potential pids, can be empty if no match found.
328 Throws an exception on processing errors.
329
330 """
331 pids = []
332 try:
333 child = subprocess.Popen(['ps', '-A', '--format', 'pid,args'],
334 stdout=subprocess.PIPE)
335 except:
336 raise Exception
337 for line in child.stdout:
338 line = line.lstrip().split(' ', 1)
339 # perform a sanity check before calling the more expensive
340 # function to possibly extract the guest name
341 if ' -name ' in line[1] and gname == get_gname_from_pid(line[0]):
342 pids.append(int(line[0]))
343 child.stdout.close()
344
345 return pids
346
347
348def get_gname_from_pid(pid):
349 """Returns the guest name for a QEMU process pid.
350
351 Extracts the guest name from the QEMU comma line by processing the '-name'
352 option. Will also handle names specified out of sequence.
353
354 """
355 name = ''
356 try:
357 line = open('/proc/{}/cmdline'.format(pid), 'rb').read().split('\0')
358 parms = line[line.index('-name') + 1].split(',')
359 while '' in parms:
360 # commas are escaped (i.e. ',,'), hence e.g. 'foo,bar' results in
361 # ['foo', '', 'bar'], which we revert here
362 idx = parms.index('')
363 parms[idx - 1] += ',' + parms[idx + 1]
364 del parms[idx:idx+2]
365 # the '-name' switch allows for two ways to specify the guest name,
366 # where the plain name overrides the name specified via 'guest='
367 for arg in parms:
368 if '=' not in arg:
369 name = arg
370 break
371 if arg[:6] == 'guest=':
372 name = arg[6:]
373 except (ValueError, IOError, IndexError):
374 pass
375
376 return name
377
378
379def get_online_cpus():
380 """Returns a list of cpu id integers."""
381 with open('/sys/devices/system/cpu/online') as cpu_list:
382 cpu_string = cpu_list.readline()
383 return parse_int_list(cpu_string)
384
385
386def get_filters():
387 """Returns a dict of trace events, their filter ids and
388 the values that can be filtered.
389
390 Trace events can be filtered for special values by setting a
391 filter string via an ioctl. The string normally has the format
392 identifier==value. For each filter a new event will be created, to
393 be able to distinguish the events.
394
395 """
396 filters = {}
397 filters['kvm_userspace_exit'] = ('reason', USERSPACE_EXIT_REASONS)
398 if ARCH.exit_reasons:
399 filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons)
400 return filters
401
402libc = ctypes.CDLL('libc.so.6', use_errno=True)
403syscall = libc.syscall
404
405
406class perf_event_attr(ctypes.Structure): 298class perf_event_attr(ctypes.Structure):
407 """Struct that holds the necessary data to set up a trace event. 299 """Struct that holds the necessary data to set up a trace event.
408 300
@@ -432,25 +324,6 @@ class perf_event_attr(ctypes.Structure):
432 self.read_format = PERF_FORMAT_GROUP 324 self.read_format = PERF_FORMAT_GROUP
433 325
434 326
435def perf_event_open(attr, pid, cpu, group_fd, flags):
436 """Wrapper for the sys_perf_evt_open() syscall.
437
438 Used to set up performance events, returns a file descriptor or -1
439 on error.
440
441 Attributes are:
442 - syscall number
443 - struct perf_event_attr *
444 - pid or -1 to monitor all pids
445 - cpu number or -1 to monitor all cpus
446 - The file descriptor of the group leader or -1 to create a group.
447 - flags
448
449 """
450 return syscall(ARCH.sc_perf_evt_open, ctypes.pointer(attr),
451 ctypes.c_int(pid), ctypes.c_int(cpu),
452 ctypes.c_int(group_fd), ctypes.c_long(flags))
453
454PERF_TYPE_TRACEPOINT = 2 327PERF_TYPE_TRACEPOINT = 2
455PERF_FORMAT_GROUP = 1 << 3 328PERF_FORMAT_GROUP = 1 << 3
456 329
@@ -495,6 +368,8 @@ class Event(object):
495 """Represents a performance event and manages its life cycle.""" 368 """Represents a performance event and manages its life cycle."""
496 def __init__(self, name, group, trace_cpu, trace_pid, trace_point, 369 def __init__(self, name, group, trace_cpu, trace_pid, trace_point,
497 trace_filter, trace_set='kvm'): 370 trace_filter, trace_set='kvm'):
371 self.libc = ctypes.CDLL('libc.so.6', use_errno=True)
372 self.syscall = self.libc.syscall
498 self.name = name 373 self.name = name
499 self.fd = None 374 self.fd = None
500 self.setup_event(group, trace_cpu, trace_pid, trace_point, 375 self.setup_event(group, trace_cpu, trace_pid, trace_point,
@@ -511,6 +386,25 @@ class Event(object):
511 if self.fd: 386 if self.fd:
512 os.close(self.fd) 387 os.close(self.fd)
513 388
389 def perf_event_open(self, attr, pid, cpu, group_fd, flags):
390 """Wrapper for the sys_perf_evt_open() syscall.
391
392 Used to set up performance events, returns a file descriptor or -1
393 on error.
394
395 Attributes are:
396 - syscall number
397 - struct perf_event_attr *
398 - pid or -1 to monitor all pids
399 - cpu number or -1 to monitor all cpus
400 - The file descriptor of the group leader or -1 to create a group.
401 - flags
402
403 """
404 return self.syscall(ARCH.sc_perf_evt_open, ctypes.pointer(attr),
405 ctypes.c_int(pid), ctypes.c_int(cpu),
406 ctypes.c_int(group_fd), ctypes.c_long(flags))
407
514 def setup_event_attribute(self, trace_set, trace_point): 408 def setup_event_attribute(self, trace_set, trace_point):
515 """Returns an initialized ctype perf_event_attr struct.""" 409 """Returns an initialized ctype perf_event_attr struct."""
516 410
@@ -539,8 +433,8 @@ class Event(object):
539 if group.events: 433 if group.events:
540 group_leader = group.events[0].fd 434 group_leader = group.events[0].fd
541 435
542 fd = perf_event_open(event_attr, trace_pid, 436 fd = self.perf_event_open(event_attr, trace_pid,
543 trace_cpu, group_leader, 0) 437 trace_cpu, group_leader, 0)
544 if fd == -1: 438 if fd == -1:
545 err = ctypes.get_errno() 439 err = ctypes.get_errno()
546 raise OSError(err, os.strerror(err), 440 raise OSError(err, os.strerror(err),
@@ -575,17 +469,53 @@ class Event(object):
575 fcntl.ioctl(self.fd, ARCH.ioctl_numbers['RESET'], 0) 469 fcntl.ioctl(self.fd, ARCH.ioctl_numbers['RESET'], 0)
576 470
577 471
578class TracepointProvider(object): 472class Provider(object):
473 """Encapsulates functionalities used by all providers."""
474 @staticmethod
475 def is_field_wanted(fields_filter, field):
476 """Indicate whether field is valid according to fields_filter."""
477 if not fields_filter:
478 return True
479 return re.match(fields_filter, field) is not None
480
481 @staticmethod
482 def walkdir(path):
483 """Returns os.walk() data for specified directory.
484
485 As it is only a wrapper it returns the same 3-tuple of (dirpath,
486 dirnames, filenames).
487 """
488 return next(os.walk(path))
489
490
491class TracepointProvider(Provider):
579 """Data provider for the stats class. 492 """Data provider for the stats class.
580 493
581 Manages the events/groups from which it acquires its data. 494 Manages the events/groups from which it acquires its data.
582 495
583 """ 496 """
584 def __init__(self): 497 def __init__(self, pid, fields_filter):
585 self.group_leaders = [] 498 self.group_leaders = []
586 self.filters = get_filters() 499 self.filters = self.get_filters()
587 self._fields = self.get_available_fields() 500 self.update_fields(fields_filter)
588 self._pid = 0 501 self.pid = pid
502
503 @staticmethod
504 def get_filters():
505 """Returns a dict of trace events, their filter ids and
506 the values that can be filtered.
507
508 Trace events can be filtered for special values by setting a
509 filter string via an ioctl. The string normally has the format
510 identifier==value. For each filter a new event will be created, to
511 be able to distinguish the events.
512
513 """
514 filters = {}
515 filters['kvm_userspace_exit'] = ('reason', USERSPACE_EXIT_REASONS)
516 if ARCH.exit_reasons:
517 filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons)
518 return filters
589 519
590 def get_available_fields(self): 520 def get_available_fields(self):
591 """Returns a list of available event's of format 'event name(filter 521 """Returns a list of available event's of format 'event name(filter
@@ -603,7 +533,7 @@ class TracepointProvider(object):
603 533
604 """ 534 """
605 path = os.path.join(PATH_DEBUGFS_TRACING, 'events', 'kvm') 535 path = os.path.join(PATH_DEBUGFS_TRACING, 'events', 'kvm')
606 fields = walkdir(path)[1] 536 fields = self.walkdir(path)[1]
607 extra = [] 537 extra = []
608 for field in fields: 538 for field in fields:
609 if field in self.filters: 539 if field in self.filters:
@@ -613,6 +543,34 @@ class TracepointProvider(object):
613 fields += extra 543 fields += extra
614 return fields 544 return fields
615 545
546 def update_fields(self, fields_filter):
547 """Refresh fields, applying fields_filter"""
548 self._fields = [field for field in self.get_available_fields()
549 if self.is_field_wanted(fields_filter, field)]
550
551 @staticmethod
552 def get_online_cpus():
553 """Returns a list of cpu id integers."""
554 def parse_int_list(list_string):
555 """Returns an int list from a string of comma separated integers and
556 integer ranges."""
557 integers = []
558 members = list_string.split(',')
559
560 for member in members:
561 if '-' not in member:
562 integers.append(int(member))
563 else:
564 int_range = member.split('-')
565 integers.extend(range(int(int_range[0]),
566 int(int_range[1]) + 1))
567
568 return integers
569
570 with open('/sys/devices/system/cpu/online') as cpu_list:
571 cpu_string = cpu_list.readline()
572 return parse_int_list(cpu_string)
573
616 def setup_traces(self): 574 def setup_traces(self):
617 """Creates all event and group objects needed to be able to retrieve 575 """Creates all event and group objects needed to be able to retrieve
618 data.""" 576 data."""
@@ -621,9 +579,9 @@ class TracepointProvider(object):
621 # Fetch list of all threads of the monitored pid, as qemu 579 # Fetch list of all threads of the monitored pid, as qemu
622 # starts a thread for each vcpu. 580 # starts a thread for each vcpu.
623 path = os.path.join('/proc', str(self._pid), 'task') 581 path = os.path.join('/proc', str(self._pid), 'task')
624 groupids = walkdir(path)[1] 582 groupids = self.walkdir(path)[1]
625 else: 583 else:
626 groupids = get_online_cpus() 584 groupids = self.get_online_cpus()
627 585
628 # The constant is needed as a buffer for python libs, std 586 # The constant is needed as a buffer for python libs, std
629 # streams and other files that the script opens. 587 # streams and other files that the script opens.
@@ -671,9 +629,6 @@ class TracepointProvider(object):
671 629
672 self.group_leaders.append(group) 630 self.group_leaders.append(group)
673 631
674 def available_fields(self):
675 return self.get_available_fields()
676
677 @property 632 @property
678 def fields(self): 633 def fields(self):
679 return self._fields 634 return self._fields
@@ -707,7 +662,7 @@ class TracepointProvider(object):
707 self.setup_traces() 662 self.setup_traces()
708 self.fields = self._fields 663 self.fields = self._fields
709 664
710 def read(self): 665 def read(self, by_guest=0):
711 """Returns 'event name: current value' for all enabled events.""" 666 """Returns 'event name: current value' for all enabled events."""
712 ret = defaultdict(int) 667 ret = defaultdict(int)
713 for group in self.group_leaders: 668 for group in self.group_leaders:
@@ -723,16 +678,17 @@ class TracepointProvider(object):
723 event.reset() 678 event.reset()
724 679
725 680
726class DebugfsProvider(object): 681class DebugfsProvider(Provider):
727 """Provides data from the files that KVM creates in the kvm debugfs 682 """Provides data from the files that KVM creates in the kvm debugfs
728 folder.""" 683 folder."""
729 def __init__(self): 684 def __init__(self, pid, fields_filter, include_past):
730 self._fields = self.get_available_fields() 685 self.update_fields(fields_filter)
731 self._baseline = {} 686 self._baseline = {}
732 self._pid = 0
733 self.do_read = True 687 self.do_read = True
734 self.paths = [] 688 self.paths = []
735 self.reset() 689 self.pid = pid
690 if include_past:
691 self.restore()
736 692
737 def get_available_fields(self): 693 def get_available_fields(self):
738 """"Returns a list of available fields. 694 """"Returns a list of available fields.
@@ -740,7 +696,12 @@ class DebugfsProvider(object):
740 The fields are all available KVM debugfs files 696 The fields are all available KVM debugfs files
741 697
742 """ 698 """
743 return walkdir(PATH_DEBUGFS_KVM)[2] 699 return self.walkdir(PATH_DEBUGFS_KVM)[2]
700
701 def update_fields(self, fields_filter):
702 """Refresh fields, applying fields_filter"""
703 self._fields = [field for field in self.get_available_fields()
704 if self.is_field_wanted(fields_filter, field)]
744 705
745 @property 706 @property
746 def fields(self): 707 def fields(self):
@@ -757,10 +718,9 @@ class DebugfsProvider(object):
757 718
758 @pid.setter 719 @pid.setter
759 def pid(self, pid): 720 def pid(self, pid):
721 self._pid = pid
760 if pid != 0: 722 if pid != 0:
761 self._pid = pid 723 vms = self.walkdir(PATH_DEBUGFS_KVM)[1]
762
763 vms = walkdir(PATH_DEBUGFS_KVM)[1]
764 if len(vms) == 0: 724 if len(vms) == 0:
765 self.do_read = False 725 self.do_read = False
766 726
@@ -771,8 +731,15 @@ class DebugfsProvider(object):
771 self.do_read = True 731 self.do_read = True
772 self.reset() 732 self.reset()
773 733
774 def read(self, reset=0): 734 def read(self, reset=0, by_guest=0):
775 """Returns a dict with format:'file name / field -> current value'.""" 735 """Returns a dict with format:'file name / field -> current value'.
736
737 Parameter 'reset':
738 0 plain read
739 1 reset field counts to 0
740 2 restore the original field counts
741
742 """
776 results = {} 743 results = {}
777 744
778 # If no debugfs filtering support is available, then don't read. 745 # If no debugfs filtering support is available, then don't read.
@@ -789,12 +756,22 @@ class DebugfsProvider(object):
789 for field in self._fields: 756 for field in self._fields:
790 value = self.read_field(field, path) 757 value = self.read_field(field, path)
791 key = path + field 758 key = path + field
792 if reset: 759 if reset == 1:
793 self._baseline[key] = value 760 self._baseline[key] = value
761 if reset == 2:
762 self._baseline[key] = 0
794 if self._baseline.get(key, -1) == -1: 763 if self._baseline.get(key, -1) == -1:
795 self._baseline[key] = value 764 self._baseline[key] = value
796 results[field] = (results.get(field, 0) + value - 765 increment = (results.get(field, 0) + value -
797 self._baseline.get(key, 0)) 766 self._baseline.get(key, 0))
767 if by_guest:
768 pid = key.split('-')[0]
769 if pid in results:
770 results[pid] += increment
771 else:
772 results[pid] = increment
773 else:
774 results[field] = increment
798 775
799 return results 776 return results
800 777
@@ -813,6 +790,11 @@ class DebugfsProvider(object):
813 self._baseline = {} 790 self._baseline = {}
814 self.read(1) 791 self.read(1)
815 792
793 def restore(self):
794 """Reset field counters"""
795 self._baseline = {}
796 self.read(2)
797
816 798
817class Stats(object): 799class Stats(object):
818 """Manages the data providers and the data they provide. 800 """Manages the data providers and the data they provide.
@@ -821,33 +803,32 @@ class Stats(object):
821 provider data. 803 provider data.
822 804
823 """ 805 """
824 def __init__(self, providers, pid, fields=None): 806 def __init__(self, options):
825 self.providers = providers 807 self.providers = self.get_providers(options)
826 self._pid_filter = pid 808 self._pid_filter = options.pid
827 self._fields_filter = fields 809 self._fields_filter = options.fields
828 self.values = {} 810 self.values = {}
829 self.update_provider_pid() 811
830 self.update_provider_filters() 812 @staticmethod
813 def get_providers(options):
814 """Returns a list of data providers depending on the passed options."""
815 providers = []
816
817 if options.debugfs:
818 providers.append(DebugfsProvider(options.pid, options.fields,
819 options.dbgfs_include_past))
820 if options.tracepoints or not providers:
821 providers.append(TracepointProvider(options.pid, options.fields))
822
823 return providers
831 824
832 def update_provider_filters(self): 825 def update_provider_filters(self):
833 """Propagates fields filters to providers.""" 826 """Propagates fields filters to providers."""
834 def wanted(key):
835 if not self._fields_filter:
836 return True
837 return re.match(self._fields_filter, key) is not None
838
839 # As we reset the counters when updating the fields we can 827 # As we reset the counters when updating the fields we can
840 # also clear the cache of old values. 828 # also clear the cache of old values.
841 self.values = {} 829 self.values = {}
842 for provider in self.providers: 830 for provider in self.providers:
843 provider_fields = [key for key in provider.get_available_fields() 831 provider.update_fields(self._fields_filter)
844 if wanted(key)]
845 provider.fields = provider_fields
846
847 def update_provider_pid(self):
848 """Propagates pid filters to providers."""
849 for provider in self.providers:
850 provider.pid = self._pid_filter
851 832
852 def reset(self): 833 def reset(self):
853 self.values = {} 834 self.values = {}
@@ -873,27 +854,52 @@ class Stats(object):
873 if pid != self._pid_filter: 854 if pid != self._pid_filter:
874 self._pid_filter = pid 855 self._pid_filter = pid
875 self.values = {} 856 self.values = {}
876 self.update_provider_pid() 857 for provider in self.providers:
858 provider.pid = self._pid_filter
877 859
878 def get(self): 860 def get(self, by_guest=0):
879 """Returns a dict with field -> (value, delta to last value) of all 861 """Returns a dict with field -> (value, delta to last value) of all
880 provider data.""" 862 provider data."""
881 for provider in self.providers: 863 for provider in self.providers:
882 new = provider.read() 864 new = provider.read(by_guest=by_guest)
883 for key in provider.fields: 865 for key in new if by_guest else provider.fields:
884 oldval = self.values.get(key, (0, 0))[0] 866 oldval = self.values.get(key, (0, 0))[0]
885 newval = new.get(key, 0) 867 newval = new.get(key, 0)
886 newdelta = newval - oldval 868 newdelta = newval - oldval
887 self.values[key] = (newval, newdelta) 869 self.values[key] = (newval, newdelta)
888 return self.values 870 return self.values
889 871
890LABEL_WIDTH = 40 872 def toggle_display_guests(self, to_pid):
891NUMBER_WIDTH = 10 873 """Toggle between collection of stats by individual event and by
892DELAY_INITIAL = 0.25 874 guest pid
893DELAY_REGULAR = 3.0 875
876 Events reported by DebugfsProvider change when switching to/from
877 reading by guest values. Hence we have to remove the excess event
878 names from self.values.
879
880 """
881 if any(isinstance(ins, TracepointProvider) for ins in self.providers):
882 return 1
883 if to_pid:
884 for provider in self.providers:
885 if isinstance(provider, DebugfsProvider):
886 for key in provider.fields:
887 if key in self.values.keys():
888 del self.values[key]
889 else:
890 oldvals = self.values.copy()
891 for key in oldvals:
892 if key.isdigit():
893 del self.values[key]
894 # Update oldval (see get())
895 self.get(to_pid)
896 return 0
897
898DELAY_DEFAULT = 3.0
894MAX_GUEST_NAME_LEN = 48 899MAX_GUEST_NAME_LEN = 48
895MAX_REGEX_LEN = 44 900MAX_REGEX_LEN = 44
896DEFAULT_REGEX = r'^[^\(]*$' 901DEFAULT_REGEX = r'^[^\(]*$'
902SORT_DEFAULT = 0
897 903
898 904
899class Tui(object): 905class Tui(object):
@@ -901,7 +907,10 @@ class Tui(object):
901 def __init__(self, stats): 907 def __init__(self, stats):
902 self.stats = stats 908 self.stats = stats
903 self.screen = None 909 self.screen = None
904 self.update_drilldown() 910 self._delay_initial = 0.25
911 self._delay_regular = DELAY_DEFAULT
912 self._sorting = SORT_DEFAULT
913 self._display_guests = 0
905 914
906 def __enter__(self): 915 def __enter__(self):
907 """Initialises curses for later use. Based on curses.wrapper 916 """Initialises curses for later use. Based on curses.wrapper
@@ -929,7 +938,7 @@ class Tui(object):
929 return self 938 return self
930 939
931 def __exit__(self, *exception): 940 def __exit__(self, *exception):
932 """Resets the terminal to its normal state. Based on curses.wrappre 941 """Resets the terminal to its normal state. Based on curses.wrapper
933 implementation from the Python standard library.""" 942 implementation from the Python standard library."""
934 if self.screen: 943 if self.screen:
935 self.screen.keypad(0) 944 self.screen.keypad(0)
@@ -937,6 +946,86 @@ class Tui(object):
937 curses.nocbreak() 946 curses.nocbreak()
938 curses.endwin() 947 curses.endwin()
939 948
949 def get_all_gnames(self):
950 """Returns a list of (pid, gname) tuples of all running guests"""
951 res = []
952 try:
953 child = subprocess.Popen(['ps', '-A', '--format', 'pid,args'],
954 stdout=subprocess.PIPE)
955 except:
956 raise Exception
957 for line in child.stdout:
958 line = line.lstrip().split(' ', 1)
959 # perform a sanity check before calling the more expensive
960 # function to possibly extract the guest name
961 if ' -name ' in line[1]:
962 res.append((line[0], self.get_gname_from_pid(line[0])))
963 child.stdout.close()
964
965 return res
966
967 def print_all_gnames(self, row):
968 """Print a list of all running guests along with their pids."""
969 self.screen.addstr(row, 2, '%8s %-60s' %
970 ('Pid', 'Guest Name (fuzzy list, might be '
971 'inaccurate!)'),
972 curses.A_UNDERLINE)
973 row += 1
974 try:
975 for line in self.get_all_gnames():
976 self.screen.addstr(row, 2, '%8s %-60s' % (line[0], line[1]))
977 row += 1
978 if row >= self.screen.getmaxyx()[0]:
979 break
980 except Exception:
981 self.screen.addstr(row + 1, 2, 'Not available')
982
983 def get_pid_from_gname(self, gname):
984 """Fuzzy function to convert guest name to QEMU process pid.
985
986 Returns a list of potential pids, can be empty if no match found.
987 Throws an exception on processing errors.
988
989 """
990 pids = []
991 for line in self.get_all_gnames():
992 if gname == line[1]:
993 pids.append(int(line[0]))
994
995 return pids
996
997 @staticmethod
998 def get_gname_from_pid(pid):
999 """Returns the guest name for a QEMU process pid.
1000
1001 Extracts the guest name from the QEMU comma line by processing the
1002 '-name' option. Will also handle names specified out of sequence.
1003
1004 """
1005 name = ''
1006 try:
1007 line = open('/proc/{}/cmdline'
1008 .format(pid), 'rb').read().split('\0')
1009 parms = line[line.index('-name') + 1].split(',')
1010 while '' in parms:
1011 # commas are escaped (i.e. ',,'), hence e.g. 'foo,bar' results
1012 # in # ['foo', '', 'bar'], which we revert here
1013 idx = parms.index('')
1014 parms[idx - 1] += ',' + parms[idx + 1]
1015 del parms[idx:idx+2]
1016 # the '-name' switch allows for two ways to specify the guest name,
1017 # where the plain name overrides the name specified via 'guest='
1018 for arg in parms:
1019 if '=' not in arg:
1020 name = arg
1021 break
1022 if arg[:6] == 'guest=':
1023 name = arg[6:]
1024 except (ValueError, IOError, IndexError):
1025 pass
1026
1027 return name
1028
940 def update_drilldown(self): 1029 def update_drilldown(self):
941 """Sets or removes a filter that only allows fields without braces.""" 1030 """Sets or removes a filter that only allows fields without braces."""
942 if not self.stats.fields_filter: 1031 if not self.stats.fields_filter:
@@ -954,7 +1043,7 @@ class Tui(object):
954 if pid is None: 1043 if pid is None:
955 pid = self.stats.pid_filter 1044 pid = self.stats.pid_filter
956 self.screen.erase() 1045 self.screen.erase()
957 gname = get_gname_from_pid(pid) 1046 gname = self.get_gname_from_pid(pid)
958 if gname: 1047 if gname:
959 gname = ('({})'.format(gname[:MAX_GUEST_NAME_LEN] + '...' 1048 gname = ('({})'.format(gname[:MAX_GUEST_NAME_LEN] + '...'
960 if len(gname) > MAX_GUEST_NAME_LEN 1049 if len(gname) > MAX_GUEST_NAME_LEN
@@ -970,13 +1059,13 @@ class Tui(object):
970 if len(regex) > MAX_REGEX_LEN: 1059 if len(regex) > MAX_REGEX_LEN:
971 regex = regex[:MAX_REGEX_LEN] + '...' 1060 regex = regex[:MAX_REGEX_LEN] + '...'
972 self.screen.addstr(1, 17, 'regex filter: {0}'.format(regex)) 1061 self.screen.addstr(1, 17, 'regex filter: {0}'.format(regex))
973 self.screen.addstr(2, 1, 'Event') 1062 if self._display_guests:
974 self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH - 1063 col_name = 'Guest Name'
975 len('Total'), 'Total') 1064 else:
976 self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH + 7 - 1065 col_name = 'Event'
977 len('%Total'), '%Total') 1066 self.screen.addstr(2, 1, '%-40s %10s%7s %8s' %
978 self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH + 7 + 8 - 1067 (col_name, 'Total', '%Total', 'CurAvg/s'),
979 len('Current'), 'Current') 1068 curses.A_STANDOUT)
980 self.screen.addstr(4, 1, 'Collecting data...') 1069 self.screen.addstr(4, 1, 'Collecting data...')
981 self.screen.refresh() 1070 self.screen.refresh()
982 1071
@@ -984,16 +1073,25 @@ class Tui(object):
984 row = 3 1073 row = 3
985 self.screen.move(row, 0) 1074 self.screen.move(row, 0)
986 self.screen.clrtobot() 1075 self.screen.clrtobot()
987 stats = self.stats.get() 1076 stats = self.stats.get(self._display_guests)
988 1077
989 def sortkey(x): 1078 def sortCurAvg(x):
1079 # sort by current events if available
990 if stats[x][1]: 1080 if stats[x][1]:
991 return (-stats[x][1], -stats[x][0]) 1081 return (-stats[x][1], -stats[x][0])
992 else: 1082 else:
993 return (0, -stats[x][0]) 1083 return (0, -stats[x][0])
1084
1085 def sortTotal(x):
1086 # sort by totals
1087 return (0, -stats[x][0])
994 total = 0. 1088 total = 0.
995 for val in stats.values(): 1089 for val in stats.values():
996 total += val[0] 1090 total += val[0]
1091 if self._sorting == SORT_DEFAULT:
1092 sortkey = sortCurAvg
1093 else:
1094 sortkey = sortTotal
997 for key in sorted(stats.keys(), key=sortkey): 1095 for key in sorted(stats.keys(), key=sortkey):
998 1096
999 if row >= self.screen.getmaxyx()[0]: 1097 if row >= self.screen.getmaxyx()[0]:
@@ -1001,18 +1099,61 @@ class Tui(object):
1001 values = stats[key] 1099 values = stats[key]
1002 if not values[0] and not values[1]: 1100 if not values[0] and not values[1]:
1003 break 1101 break
1004 col = 1 1102 if values[0] is not None:
1005 self.screen.addstr(row, col, key) 1103 cur = int(round(values[1] / sleeptime)) if values[1] else ''
1006 col += LABEL_WIDTH 1104 if self._display_guests:
1007 self.screen.addstr(row, col, '%10d' % (values[0],)) 1105 key = self.get_gname_from_pid(key)
1008 col += NUMBER_WIDTH 1106 self.screen.addstr(row, 1, '%-40s %10d%7.1f %8s' %
1009 self.screen.addstr(row, col, '%7.1f' % (values[0] * 100 / total,)) 1107 (key, values[0], values[0] * 100 / total,
1010 col += 7 1108 cur))
1011 if values[1] is not None:
1012 self.screen.addstr(row, col, '%8d' % (values[1] / sleeptime,))
1013 row += 1 1109 row += 1
1110 if row == 3:
1111 self.screen.addstr(4, 1, 'No matching events reported yet')
1014 self.screen.refresh() 1112 self.screen.refresh()
1015 1113
1114 def show_msg(self, text):
1115 """Display message centered text and exit on key press"""
1116 hint = 'Press any key to continue'
1117 curses.cbreak()
1118 self.screen.erase()
1119 (x, term_width) = self.screen.getmaxyx()
1120 row = 2
1121 for line in text:
1122 start = (term_width - len(line)) / 2
1123 self.screen.addstr(row, start, line)
1124 row += 1
1125 self.screen.addstr(row + 1, (term_width - len(hint)) / 2, hint,
1126 curses.A_STANDOUT)
1127 self.screen.getkey()
1128
1129 def show_help_interactive(self):
1130 """Display help with list of interactive commands"""
1131 msg = (' b toggle events by guests (debugfs only, honors'
1132 ' filters)',
1133 ' c clear filter',
1134 ' f filter by regular expression',
1135 ' g filter by guest name',
1136 ' h display interactive commands reference',
1137 ' o toggle sorting order (Total vs CurAvg/s)',
1138 ' p filter by PID',
1139 ' q quit',
1140 ' r reset stats',
1141 ' s set update interval',
1142 ' x toggle reporting of stats for individual child trace'
1143 ' events',
1144 'Any other key refreshes statistics immediately')
1145 curses.cbreak()
1146 self.screen.erase()
1147 self.screen.addstr(0, 0, "Interactive commands reference",
1148 curses.A_BOLD)
1149 self.screen.addstr(2, 0, "Press any key to exit", curses.A_STANDOUT)
1150 row = 4
1151 for line in msg:
1152 self.screen.addstr(row, 0, line)
1153 row += 1
1154 self.screen.getkey()
1155 self.refresh_header()
1156
1016 def show_filter_selection(self): 1157 def show_filter_selection(self):
1017 """Draws filter selection mask. 1158 """Draws filter selection mask.
1018 1159
@@ -1059,6 +1200,7 @@ class Tui(object):
1059 'This might limit the shown data to the trace ' 1200 'This might limit the shown data to the trace '
1060 'statistics.') 1201 'statistics.')
1061 self.screen.addstr(5, 0, msg) 1202 self.screen.addstr(5, 0, msg)
1203 self.print_all_gnames(7)
1062 1204
1063 curses.echo() 1205 curses.echo()
1064 self.screen.addstr(3, 0, "Pid [0 or pid]: ") 1206 self.screen.addstr(3, 0, "Pid [0 or pid]: ")
@@ -1077,10 +1219,40 @@ class Tui(object):
1077 self.refresh_header(pid) 1219 self.refresh_header(pid)
1078 self.update_pid(pid) 1220 self.update_pid(pid)
1079 break 1221 break
1080
1081 except ValueError: 1222 except ValueError:
1082 msg = '"' + str(pid) + '": Not a valid pid' 1223 msg = '"' + str(pid) + '": Not a valid pid'
1083 continue 1224
1225 def show_set_update_interval(self):
1226 """Draws update interval selection mask."""
1227 msg = ''
1228 while True:
1229 self.screen.erase()
1230 self.screen.addstr(0, 0, 'Set update interval (defaults to %fs).' %
1231 DELAY_DEFAULT, curses.A_BOLD)
1232 self.screen.addstr(4, 0, msg)
1233 self.screen.addstr(2, 0, 'Change delay from %.1fs to ' %
1234 self._delay_regular)
1235 curses.echo()
1236 val = self.screen.getstr()
1237 curses.noecho()
1238
1239 try:
1240 if len(val) > 0:
1241 delay = float(val)
1242 if delay < 0.1:
1243 msg = '"' + str(val) + '": Value must be >=0.1'
1244 continue
1245 if delay > 25.5:
1246 msg = '"' + str(val) + '": Value must be <=25.5'
1247 continue
1248 else:
1249 delay = DELAY_DEFAULT
1250 self._delay_regular = delay
1251 break
1252
1253 except ValueError:
1254 msg = '"' + str(val) + '": Invalid value'
1255 self.refresh_header()
1084 1256
1085 def show_vm_selection_by_guest_name(self): 1257 def show_vm_selection_by_guest_name(self):
1086 """Draws guest selection mask. 1258 """Draws guest selection mask.
@@ -1098,6 +1270,7 @@ class Tui(object):
1098 'This might limit the shown data to the trace ' 1270 'This might limit the shown data to the trace '
1099 'statistics.') 1271 'statistics.')
1100 self.screen.addstr(5, 0, msg) 1272 self.screen.addstr(5, 0, msg)
1273 self.print_all_gnames(7)
1101 curses.echo() 1274 curses.echo()
1102 self.screen.addstr(3, 0, "Guest [ENTER or guest]: ") 1275 self.screen.addstr(3, 0, "Guest [ENTER or guest]: ")
1103 gname = self.screen.getstr() 1276 gname = self.screen.getstr()
@@ -1110,7 +1283,7 @@ class Tui(object):
1110 else: 1283 else:
1111 pids = [] 1284 pids = []
1112 try: 1285 try:
1113 pids = get_pid_from_gname(gname) 1286 pids = self.get_pid_from_gname(gname)
1114 except: 1287 except:
1115 msg = '"' + gname + '": Internal error while searching, ' \ 1288 msg = '"' + gname + '": Internal error while searching, ' \
1116 'use pid filter instead' 1289 'use pid filter instead'
@@ -1128,38 +1301,60 @@ class Tui(object):
1128 1301
1129 def show_stats(self): 1302 def show_stats(self):
1130 """Refreshes the screen and processes user input.""" 1303 """Refreshes the screen and processes user input."""
1131 sleeptime = DELAY_INITIAL 1304 sleeptime = self._delay_initial
1132 self.refresh_header() 1305 self.refresh_header()
1306 start = 0.0 # result based on init value never appears on screen
1133 while True: 1307 while True:
1134 self.refresh_body(sleeptime) 1308 self.refresh_body(time.time() - start)
1135 curses.halfdelay(int(sleeptime * 10)) 1309 curses.halfdelay(int(sleeptime * 10))
1136 sleeptime = DELAY_REGULAR 1310 start = time.time()
1311 sleeptime = self._delay_regular
1137 try: 1312 try:
1138 char = self.screen.getkey() 1313 char = self.screen.getkey()
1139 if char == 'x': 1314 if char == 'b':
1315 self._display_guests = not self._display_guests
1316 if self.stats.toggle_display_guests(self._display_guests):
1317 self.show_msg(['Command not available with tracepoints'
1318 ' enabled', 'Restart with debugfs only '
1319 '(see option \'-d\') and try again!'])
1320 self._display_guests = not self._display_guests
1140 self.refresh_header() 1321 self.refresh_header()
1141 self.update_drilldown()
1142 sleeptime = DELAY_INITIAL
1143 if char == 'q':
1144 break
1145 if char == 'c': 1322 if char == 'c':
1146 self.stats.fields_filter = DEFAULT_REGEX 1323 self.stats.fields_filter = DEFAULT_REGEX
1147 self.refresh_header(0) 1324 self.refresh_header(0)
1148 self.update_pid(0) 1325 self.update_pid(0)
1149 sleeptime = DELAY_INITIAL
1150 if char == 'f': 1326 if char == 'f':
1327 curses.curs_set(1)
1151 self.show_filter_selection() 1328 self.show_filter_selection()
1152 sleeptime = DELAY_INITIAL 1329 curses.curs_set(0)
1330 sleeptime = self._delay_initial
1153 if char == 'g': 1331 if char == 'g':
1332 curses.curs_set(1)
1154 self.show_vm_selection_by_guest_name() 1333 self.show_vm_selection_by_guest_name()
1155 sleeptime = DELAY_INITIAL 1334 curses.curs_set(0)
1335 sleeptime = self._delay_initial
1336 if char == 'h':
1337 self.show_help_interactive()
1338 if char == 'o':
1339 self._sorting = not self._sorting
1156 if char == 'p': 1340 if char == 'p':
1341 curses.curs_set(1)
1157 self.show_vm_selection_by_pid() 1342 self.show_vm_selection_by_pid()
1158 sleeptime = DELAY_INITIAL 1343 curses.curs_set(0)
1344 sleeptime = self._delay_initial
1345 if char == 'q':
1346 break
1159 if char == 'r': 1347 if char == 'r':
1160 self.refresh_header()
1161 self.stats.reset() 1348 self.stats.reset()
1162 sleeptime = DELAY_INITIAL 1349 if char == 's':
1350 curses.curs_set(1)
1351 self.show_set_update_interval()
1352 curses.curs_set(0)
1353 sleeptime = self._delay_initial
1354 if char == 'x':
1355 self.update_drilldown()
1356 # prevents display of current values on next refresh
1357 self.stats.get()
1163 except KeyboardInterrupt: 1358 except KeyboardInterrupt:
1164 break 1359 break
1165 except curses.error: 1360 except curses.error:
@@ -1227,13 +1422,17 @@ Requirements:
1227 the large number of files that are possibly opened. 1422 the large number of files that are possibly opened.
1228 1423
1229Interactive Commands: 1424Interactive Commands:
1425 b toggle events by guests (debugfs only, honors filters)
1230 c clear filter 1426 c clear filter
1231 f filter by regular expression 1427 f filter by regular expression
1232 g filter by guest name 1428 g filter by guest name
1429 h display interactive commands reference
1430 o toggle sorting order (Total vs CurAvg/s)
1233 p filter by PID 1431 p filter by PID
1234 q quit 1432 q quit
1235 x toggle reporting of stats for individual child trace events
1236 r reset stats 1433 r reset stats
1434 s set update interval
1435 x toggle reporting of stats for individual child trace events
1237Press any other key to refresh statistics immediately. 1436Press any other key to refresh statistics immediately.
1238""" 1437"""
1239 1438
@@ -1246,7 +1445,7 @@ Press any other key to refresh statistics immediately.
1246 1445
1247 def cb_guest_to_pid(option, opt, val, parser): 1446 def cb_guest_to_pid(option, opt, val, parser):
1248 try: 1447 try:
1249 pids = get_pid_from_gname(val) 1448 pids = Tui.get_pid_from_gname(val)
1250 except: 1449 except:
1251 raise optparse.OptionValueError('Error while searching for guest ' 1450 raise optparse.OptionValueError('Error while searching for guest '
1252 '"{}", use "-p" to specify a pid ' 1451 '"{}", use "-p" to specify a pid '
@@ -1268,6 +1467,13 @@ Press any other key to refresh statistics immediately.
1268 dest='once', 1467 dest='once',
1269 help='run in batch mode for one second', 1468 help='run in batch mode for one second',
1270 ) 1469 )
1470 optparser.add_option('-i', '--debugfs-include-past',
1471 action='store_true',
1472 default=False,
1473 dest='dbgfs_include_past',
1474 help='include all available data on past events for '
1475 'debugfs',
1476 )
1271 optparser.add_option('-l', '--log', 1477 optparser.add_option('-l', '--log',
1272 action='store_true', 1478 action='store_true',
1273 default=False, 1479 default=False,
@@ -1288,7 +1494,7 @@ Press any other key to refresh statistics immediately.
1288 ) 1494 )
1289 optparser.add_option('-f', '--fields', 1495 optparser.add_option('-f', '--fields',
1290 action='store', 1496 action='store',
1291 default=None, 1497 default=DEFAULT_REGEX,
1292 dest='fields', 1498 dest='fields',
1293 help='fields to display (regex)', 1499 help='fields to display (regex)',
1294 ) 1500 )
@@ -1311,20 +1517,6 @@ Press any other key to refresh statistics immediately.
1311 return options 1517 return options
1312 1518
1313 1519
1314def get_providers(options):
1315 """Returns a list of data providers depending on the passed options."""
1316 providers = []
1317
1318 if options.tracepoints:
1319 providers.append(TracepointProvider())
1320 if options.debugfs:
1321 providers.append(DebugfsProvider())
1322 if len(providers) == 0:
1323 providers.append(TracepointProvider())
1324
1325 return providers
1326
1327
1328def check_access(options): 1520def check_access(options):
1329 """Exits if the current user can't access all needed directories.""" 1521 """Exits if the current user can't access all needed directories."""
1330 if not os.path.exists('/sys/kernel/debug'): 1522 if not os.path.exists('/sys/kernel/debug'):
@@ -1365,8 +1557,7 @@ def main():
1365 sys.stderr.write('Did you use a (unsupported) tid instead of a pid?\n') 1557 sys.stderr.write('Did you use a (unsupported) tid instead of a pid?\n')
1366 sys.exit('Specified pid does not exist.') 1558 sys.exit('Specified pid does not exist.')
1367 1559
1368 providers = get_providers(options) 1560 stats = Stats(options)
1369 stats = Stats(providers, options.pid, fields=options.fields)
1370 1561
1371 if options.log: 1562 if options.log:
1372 log(stats) 1563 log(stats)
diff --git a/tools/kvm/kvm_stat/kvm_stat.txt b/tools/kvm/kvm_stat/kvm_stat.txt
index 109431bdc63c..e5cf836be8a1 100644
--- a/tools/kvm/kvm_stat/kvm_stat.txt
+++ b/tools/kvm/kvm_stat/kvm_stat.txt
@@ -29,18 +29,26 @@ meaning of events.
29INTERACTIVE COMMANDS 29INTERACTIVE COMMANDS
30-------------------- 30--------------------
31[horizontal] 31[horizontal]
32*b*:: toggle events by guests (debugfs only, honors filters)
33
32*c*:: clear filter 34*c*:: clear filter
33 35
34*f*:: filter by regular expression 36*f*:: filter by regular expression
35 37
36*g*:: filter by guest name 38*g*:: filter by guest name
37 39
40*h*:: display interactive commands reference
41
42*o*:: toggle sorting order (Total vs CurAvg/s)
43
38*p*:: filter by PID 44*p*:: filter by PID
39 45
40*q*:: quit 46*q*:: quit
41 47
42*r*:: reset stats 48*r*:: reset stats
43 49
50*s*:: set update interval
51
44*x*:: toggle reporting of stats for child trace events 52*x*:: toggle reporting of stats for child trace events
45 53
46Press any other key to refresh statistics immediately. 54Press any other key to refresh statistics immediately.
@@ -64,6 +72,10 @@ OPTIONS
64--debugfs:: 72--debugfs::
65 retrieve statistics from debugfs 73 retrieve statistics from debugfs
66 74
75-i::
76--debugfs-include-past::
77 include all available data on past events for debugfs
78
67-p<pid>:: 79-p<pid>::
68--pid=<pid>:: 80--pid=<pid>::
69 limit statistics to one virtual machine (pid) 81 limit statistics to one virtual machine (pid)
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
index 809c7721cd24..a7ecf8f469f4 100644
--- a/tools/lib/api/fs/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -387,6 +387,22 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep)
387 return err; 387 return err;
388} 388}
389 389
390int filename__write_int(const char *filename, int value)
391{
392 int fd = open(filename, O_WRONLY), err = -1;
393 char buf[64];
394
395 if (fd < 0)
396 return err;
397
398 sprintf(buf, "%d", value);
399 if (write(fd, buf, sizeof(buf)) == sizeof(buf))
400 err = 0;
401
402 close(fd);
403 return err;
404}
405
390int procfs__read_str(const char *entry, char **buf, size_t *sizep) 406int procfs__read_str(const char *entry, char **buf, size_t *sizep)
391{ 407{
392 char path[PATH_MAX]; 408 char path[PATH_MAX];
@@ -480,3 +496,17 @@ int sysctl__read_int(const char *sysctl, int *value)
480 496
481 return filename__read_int(path, value); 497 return filename__read_int(path, value);
482} 498}
499
500int sysfs__write_int(const char *entry, int value)
501{
502 char path[PATH_MAX];
503 const char *sysfs = sysfs__mountpoint();
504
505 if (!sysfs)
506 return -1;
507
508 if (snprintf(path, sizeof(path), "%s/%s", sysfs, entry) >= PATH_MAX)
509 return -1;
510
511 return filename__write_int(path, value);
512}
diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h
index 956c21127d1e..45605348461e 100644
--- a/tools/lib/api/fs/fs.h
+++ b/tools/lib/api/fs/fs.h
@@ -31,6 +31,8 @@ int filename__read_int(const char *filename, int *value);
31int filename__read_ull(const char *filename, unsigned long long *value); 31int filename__read_ull(const char *filename, unsigned long long *value);
32int filename__read_str(const char *filename, char **buf, size_t *sizep); 32int filename__read_str(const char *filename, char **buf, size_t *sizep);
33 33
34int filename__write_int(const char *filename, int value);
35
34int procfs__read_str(const char *entry, char **buf, size_t *sizep); 36int procfs__read_str(const char *entry, char **buf, size_t *sizep);
35 37
36int sysctl__read_int(const char *sysctl, int *value); 38int sysctl__read_int(const char *sysctl, int *value);
@@ -38,4 +40,6 @@ int sysfs__read_int(const char *entry, int *value);
38int sysfs__read_ull(const char *entry, unsigned long long *value); 40int sysfs__read_ull(const char *entry, unsigned long long *value);
39int sysfs__read_str(const char *entry, char **buf, size_t *sizep); 41int sysfs__read_str(const char *entry, char **buf, size_t *sizep);
40int sysfs__read_bool(const char *entry, bool *value); 42int sysfs__read_bool(const char *entry, bool *value);
43
44int sysfs__write_int(const char *entry, int value);
41#endif /* __API_FS__ */ 45#endif /* __API_FS__ */
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 4fe444b8092e..7e0405e1651d 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -117,6 +117,28 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
117 return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 117 return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
118} 118}
119 119
120int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
121 size_t insns_cnt, int strict_alignment,
122 const char *license, __u32 kern_version,
123 char *log_buf, size_t log_buf_sz)
124{
125 union bpf_attr attr;
126
127 bzero(&attr, sizeof(attr));
128 attr.prog_type = type;
129 attr.insn_cnt = (__u32)insns_cnt;
130 attr.insns = ptr_to_u64(insns);
131 attr.license = ptr_to_u64(license);
132 attr.log_buf = ptr_to_u64(log_buf);
133 attr.log_size = log_buf_sz;
134 attr.log_level = 2;
135 log_buf[0] = 0;
136 attr.kern_version = kern_version;
137 attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0;
138
139 return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
140}
141
120int bpf_map_update_elem(int fd, const void *key, const void *value, 142int bpf_map_update_elem(int fd, const void *key, const void *value,
121 __u64 flags) 143 __u64 flags)
122{ 144{
@@ -235,3 +257,71 @@ int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size,
235 *duration = attr.test.duration; 257 *duration = attr.test.duration;
236 return ret; 258 return ret;
237} 259}
260
261int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id)
262{
263 union bpf_attr attr;
264 int err;
265
266 bzero(&attr, sizeof(attr));
267 attr.start_id = start_id;
268
269 err = sys_bpf(BPF_PROG_GET_NEXT_ID, &attr, sizeof(attr));
270 if (!err)
271 *next_id = attr.next_id;
272
273 return err;
274}
275
276int bpf_map_get_next_id(__u32 start_id, __u32 *next_id)
277{
278 union bpf_attr attr;
279 int err;
280
281 bzero(&attr, sizeof(attr));
282 attr.start_id = start_id;
283
284 err = sys_bpf(BPF_MAP_GET_NEXT_ID, &attr, sizeof(attr));
285 if (!err)
286 *next_id = attr.next_id;
287
288 return err;
289}
290
291int bpf_prog_get_fd_by_id(__u32 id)
292{
293 union bpf_attr attr;
294
295 bzero(&attr, sizeof(attr));
296 attr.prog_id = id;
297
298 return sys_bpf(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr));
299}
300
301int bpf_map_get_fd_by_id(__u32 id)
302{
303 union bpf_attr attr;
304
305 bzero(&attr, sizeof(attr));
306 attr.map_id = id;
307
308 return sys_bpf(BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr));
309}
310
311int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len)
312{
313 union bpf_attr attr;
314 int err;
315
316 bzero(&attr, sizeof(attr));
317 bzero(info, *info_len);
318 attr.info.bpf_fd = prog_fd;
319 attr.info.info_len = *info_len;
320 attr.info.info = ptr_to_u64(info);
321
322 err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr));
323 if (!err)
324 *info_len = attr.info.info_len;
325
326 return err;
327}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index edb4daeff7a5..16de44a14b48 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -35,6 +35,10 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
35 size_t insns_cnt, const char *license, 35 size_t insns_cnt, const char *license,
36 __u32 kern_version, char *log_buf, 36 __u32 kern_version, char *log_buf,
37 size_t log_buf_sz); 37 size_t log_buf_sz);
38int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
39 size_t insns_cnt, int strict_alignment,
40 const char *license, __u32 kern_version,
41 char *log_buf, size_t log_buf_sz);
38 42
39int bpf_map_update_elem(int fd, const void *key, const void *value, 43int bpf_map_update_elem(int fd, const void *key, const void *value,
40 __u64 flags); 44 __u64 flags);
@@ -50,5 +54,10 @@ int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
50int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size, 54int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size,
51 void *data_out, __u32 *size_out, __u32 *retval, 55 void *data_out, __u32 *size_out, __u32 *retval,
52 __u32 *duration); 56 __u32 *duration);
57int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id);
58int bpf_map_get_next_id(__u32 start_id, __u32 *next_id);
59int bpf_prog_get_fd_by_id(__u32 id);
60int bpf_map_get_fd_by_id(__u32 id);
61int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len);
53 62
54#endif 63#endif
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
index 3bc0ef9f8923..ed9ace59d112 100644
--- a/tools/lib/lockdep/Makefile
+++ b/tools/lib/lockdep/Makefile
@@ -79,6 +79,7 @@ INCLUDES = -I. -I./uinclude -I./include -I../../include $(CONFIG_INCLUDES)
79# Set compile option CFLAGS if not set elsewhere 79# Set compile option CFLAGS if not set elsewhere
80CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g 80CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g
81CFLAGS += -fPIC 81CFLAGS += -fPIC
82CFLAGS += -Wall
82 83
83override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) 84override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
84 85
@@ -100,7 +101,7 @@ include $(srctree)/tools/build/Makefile.include
100 101
101do_compile_shared_library = \ 102do_compile_shared_library = \
102 ($(print_shared_lib_compile) \ 103 ($(print_shared_lib_compile) \
103 $(CC) --shared $^ -o $@ -lpthread -ldl -Wl,-soname='"$@"';$(shell ln -sf $@ liblockdep.so)) 104 $(CC) $(LDFLAGS) --shared $^ -o $@ -lpthread -ldl -Wl,-soname='$(@F)';$(shell ln -sf $(@F) $(@D)/liblockdep.so))
104 105
105do_build_static_lib = \ 106do_build_static_lib = \
106 ($(print_static_lib_build) \ 107 ($(print_static_lib_build) \
@@ -118,10 +119,10 @@ all_cmd: $(CMD_TARGETS)
118$(LIB_IN): force 119$(LIB_IN): force
119 $(Q)$(MAKE) $(build)=liblockdep 120 $(Q)$(MAKE) $(build)=liblockdep
120 121
121liblockdep.so.$(LIBLOCKDEP_VERSION): $(LIB_IN) 122$(OUTPUT)liblockdep.so.$(LIBLOCKDEP_VERSION): $(LIB_IN)
122 $(Q)$(do_compile_shared_library) 123 $(Q)$(do_compile_shared_library)
123 124
124liblockdep.a: $(LIB_IN) 125$(OUTPUT)liblockdep.a: $(LIB_IN)
125 $(Q)$(do_build_static_lib) 126 $(Q)$(do_build_static_lib)
126 127
127tags: force 128tags: force
@@ -149,7 +150,7 @@ install_lib: all_cmd
149install: install_lib 150install: install_lib
150 151
151clean: 152clean:
152 $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d .*.cmd 153 $(RM) $(OUTPUT)*.o *~ $(TARGETS) $(OUTPUT)*.a $(OUTPUT)*liblockdep*.so* $(VERSION_FILES) $(OUTPUT).*.d $(OUTPUT).*.cmd
153 $(RM) tags TAGS 154 $(RM) tags TAGS
154 155
155PHONY += force 156PHONY += force
diff --git a/tools/lib/lockdep/lockdep.c b/tools/lib/lockdep/lockdep.c
index a0a2e3a266af..ced6d7443cea 100644
--- a/tools/lib/lockdep/lockdep.c
+++ b/tools/lib/lockdep/lockdep.c
@@ -1,8 +1,27 @@
1#include <linux/lockdep.h> 1#include <linux/lockdep.h>
2#include <stdlib.h>
2 3
3/* Trivial API wrappers, we don't (yet) have RCU in user-space: */ 4/* Trivial API wrappers, we don't (yet) have RCU in user-space: */
4#define hlist_for_each_entry_rcu hlist_for_each_entry 5#define hlist_for_each_entry_rcu hlist_for_each_entry
5#define hlist_add_head_rcu hlist_add_head 6#define hlist_add_head_rcu hlist_add_head
6#define hlist_del_rcu hlist_del 7#define hlist_del_rcu hlist_del
8#define list_for_each_entry_rcu list_for_each_entry
9#define list_add_tail_rcu list_add_tail
10
11u32 prandom_u32(void)
12{
13 /* Used only by lock_pin_lock() which is dead code */
14 abort();
15}
16
17static struct new_utsname *init_utsname(void)
18{
19 static struct new_utsname n = (struct new_utsname) {
20 .release = "liblockdep",
21 .version = LIBLOCKDEP_VERSION,
22 };
23
24 return &n;
25}
7 26
8#include "../../../kernel/locking/lockdep.c" 27#include "../../../kernel/locking/lockdep.c"
diff --git a/tools/lib/lockdep/preload.c b/tools/lib/lockdep/preload.c
index 52844847569c..6a2d3c5d4e92 100644
--- a/tools/lib/lockdep/preload.c
+++ b/tools/lib/lockdep/preload.c
@@ -4,6 +4,7 @@
4#include <dlfcn.h> 4#include <dlfcn.h>
5#include <stdlib.h> 5#include <stdlib.h>
6#include <sysexits.h> 6#include <sysexits.h>
7#include <unistd.h>
7#include "include/liblockdep/mutex.h" 8#include "include/liblockdep/mutex.h"
8#include "../../include/linux/rbtree.h" 9#include "../../include/linux/rbtree.h"
9 10
@@ -122,8 +123,6 @@ static struct rb_node **__get_lock_node(void *lock, struct rb_node **parent)
122#define LIBLOCKDEP_STATIC_ENTRIES 1024 123#define LIBLOCKDEP_STATIC_ENTRIES 1024
123#endif 124#endif
124 125
125#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
126
127static struct lock_lookup __locks[LIBLOCKDEP_STATIC_ENTRIES]; 126static struct lock_lookup __locks[LIBLOCKDEP_STATIC_ENTRIES];
128static int __locks_nr; 127static int __locks_nr;
129 128
@@ -149,7 +148,7 @@ static struct lock_lookup *alloc_lock(void)
149 148
150 int idx = __locks_nr++; 149 int idx = __locks_nr++;
151 if (idx >= ARRAY_SIZE(__locks)) { 150 if (idx >= ARRAY_SIZE(__locks)) {
152 fprintf(stderr, 151 dprintf(STDERR_FILENO,
153 "LOCKDEP error: insufficient LIBLOCKDEP_STATIC_ENTRIES\n"); 152 "LOCKDEP error: insufficient LIBLOCKDEP_STATIC_ENTRIES\n");
154 exit(EX_UNAVAILABLE); 153 exit(EX_UNAVAILABLE);
155 } 154 }
diff --git a/tools/lib/lockdep/rbtree.c b/tools/lib/lockdep/rbtree.c
index f7f43033c8b7..297c304571f8 100644
--- a/tools/lib/lockdep/rbtree.c
+++ b/tools/lib/lockdep/rbtree.c
@@ -1 +1 @@
#include "../../../lib/rbtree.c" #include "../../lib/rbtree.c"
diff --git a/tools/lib/lockdep/run_tests.sh b/tools/lib/lockdep/run_tests.sh
index 1069d96248c1..f9b94098fc98 100755
--- a/tools/lib/lockdep/run_tests.sh
+++ b/tools/lib/lockdep/run_tests.sh
@@ -4,9 +4,9 @@ make &> /dev/null
4 4
5for i in `ls tests/*.c`; do 5for i in `ls tests/*.c`; do
6 testname=$(basename "$i" .c) 6 testname=$(basename "$i" .c)
7 gcc -o tests/$testname -pthread -lpthread $i liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &> /dev/null 7 gcc -o tests/$testname -pthread $i liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &> /dev/null
8 echo -ne "$testname... " 8 echo -ne "$testname... "
9 if [ $(timeout 1 ./tests/$testname | wc -l) -gt 0 ]; then 9 if [ $(timeout 1 ./tests/$testname 2>&1 | wc -l) -gt 0 ]; then
10 echo "PASSED!" 10 echo "PASSED!"
11 else 11 else
12 echo "FAILED!" 12 echo "FAILED!"
@@ -18,9 +18,9 @@ done
18 18
19for i in `ls tests/*.c`; do 19for i in `ls tests/*.c`; do
20 testname=$(basename "$i" .c) 20 testname=$(basename "$i" .c)
21 gcc -o tests/$testname -pthread -lpthread -Iinclude $i &> /dev/null 21 gcc -o tests/$testname -pthread -Iinclude $i &> /dev/null
22 echo -ne "(PRELOAD) $testname... " 22 echo -ne "(PRELOAD) $testname... "
23 if [ $(timeout 1 ./lockdep ./tests/$testname | wc -l) -gt 0 ]; then 23 if [ $(timeout 1 ./lockdep ./tests/$testname 2>&1 | wc -l) -gt 0 ]; then
24 echo "PASSED!" 24 echo "PASSED!"
25 else 25 else
26 echo "FAILED!" 26 echo "FAILED!"
diff --git a/tools/lib/lockdep/uinclude/asm/hash.h b/tools/lib/lockdep/uinclude/asm/hash.h
deleted file mode 100644
index d82b170bb216..000000000000
--- a/tools/lib/lockdep/uinclude/asm/hash.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef __ASM_GENERIC_HASH_H
2#define __ASM_GENERIC_HASH_H
3
4/* Stub */
5
6#endif /* __ASM_GENERIC_HASH_H */
diff --git a/tools/lib/lockdep/uinclude/asm/hweight.h b/tools/lib/lockdep/uinclude/asm/hweight.h
deleted file mode 100644
index fab00ff936d1..000000000000
--- a/tools/lib/lockdep/uinclude/asm/hweight.h
+++ /dev/null
@@ -1,3 +0,0 @@
1
2/* empty file */
3
diff --git a/tools/lib/lockdep/uinclude/asm/sections.h b/tools/lib/lockdep/uinclude/asm/sections.h
deleted file mode 100644
index fab00ff936d1..000000000000
--- a/tools/lib/lockdep/uinclude/asm/sections.h
+++ /dev/null
@@ -1,3 +0,0 @@
1
2/* empty file */
3
diff --git a/tools/lib/lockdep/uinclude/linux/bitops.h b/tools/lib/lockdep/uinclude/linux/bitops.h
deleted file mode 100644
index fab00ff936d1..000000000000
--- a/tools/lib/lockdep/uinclude/linux/bitops.h
+++ /dev/null
@@ -1,3 +0,0 @@
1
2/* empty file */
3
diff --git a/tools/lib/lockdep/uinclude/linux/compiler.h b/tools/lib/lockdep/uinclude/linux/compiler.h
deleted file mode 100644
index fd3e56a83fc2..000000000000
--- a/tools/lib/lockdep/uinclude/linux/compiler.h
+++ /dev/null
@@ -1,10 +0,0 @@
1#ifndef _LIBLOCKDEP_LINUX_COMPILER_H_
2#define _LIBLOCKDEP_LINUX_COMPILER_H_
3
4#define __used __attribute__((__unused__))
5#define unlikely
6#define READ_ONCE(x) (x)
7#define WRITE_ONCE(x, val) x=(val)
8#define RCU_INIT_POINTER(p, v) p=(v)
9
10#endif
diff --git a/tools/lib/lockdep/uinclude/linux/delay.h b/tools/lib/lockdep/uinclude/linux/delay.h
deleted file mode 100644
index fab00ff936d1..000000000000
--- a/tools/lib/lockdep/uinclude/linux/delay.h
+++ /dev/null
@@ -1,3 +0,0 @@
1
2/* empty file */
3
diff --git a/tools/lib/lockdep/uinclude/linux/ftrace.h b/tools/lib/lockdep/uinclude/linux/ftrace.h
deleted file mode 100644
index fab00ff936d1..000000000000
--- a/tools/lib/lockdep/uinclude/linux/ftrace.h
+++ /dev/null
@@ -1,3 +0,0 @@
1
2/* empty file */
3
diff --git a/tools/lib/lockdep/uinclude/linux/gfp.h b/tools/lib/lockdep/uinclude/linux/gfp.h
deleted file mode 100644
index fab00ff936d1..000000000000
--- a/tools/lib/lockdep/uinclude/linux/gfp.h
+++ /dev/null
@@ -1,3 +0,0 @@
1
2/* empty file */
3
diff --git a/tools/lib/lockdep/uinclude/linux/hash.h b/tools/lib/lockdep/uinclude/linux/hash.h
deleted file mode 100644
index 0f8479858dc0..000000000000
--- a/tools/lib/lockdep/uinclude/linux/hash.h
+++ /dev/null
@@ -1 +0,0 @@
1#include "../../../include/linux/hash.h"
diff --git a/tools/lib/lockdep/uinclude/linux/interrupt.h b/tools/lib/lockdep/uinclude/linux/interrupt.h
deleted file mode 100644
index fab00ff936d1..000000000000
--- a/tools/lib/lockdep/uinclude/linux/interrupt.h
+++ /dev/null
@@ -1,3 +0,0 @@
1
2/* empty file */
3
diff --git a/tools/lib/lockdep/uinclude/linux/kernel.h b/tools/lib/lockdep/uinclude/linux/kernel.h
deleted file mode 100644
index 276c7a8b2ed1..000000000000
--- a/tools/lib/lockdep/uinclude/linux/kernel.h
+++ /dev/null
@@ -1,47 +0,0 @@
1#ifndef _LIBLOCKDEP_LINUX_KERNEL_H_
2#define _LIBLOCKDEP_LINUX_KERNEL_H_
3
4#include <linux/export.h>
5#include <linux/types.h>
6#include <linux/rcu.h>
7#include <linux/hardirq.h>
8#include <linux/kern_levels.h>
9
10#ifndef container_of
11#define container_of(ptr, type, member) ({ \
12 const typeof(((type *)0)->member) * __mptr = (ptr); \
13 (type *)((char *)__mptr - offsetof(type, member)); })
14#endif
15
16#define max(x, y) ({ \
17 typeof(x) _max1 = (x); \
18 typeof(y) _max2 = (y); \
19 (void) (&_max1 == &_max2); \
20 _max1 > _max2 ? _max1 : _max2; })
21
22#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
23#define WARN_ON(x) (x)
24#define WARN_ON_ONCE(x) (x)
25#define likely(x) (x)
26#define WARN(x, y...) (x)
27#define uninitialized_var(x) x
28#define __init
29#define noinline
30#define list_add_tail_rcu list_add_tail
31#define list_for_each_entry_rcu list_for_each_entry
32#define barrier()
33#define synchronize_sched()
34
35#ifndef CALLER_ADDR0
36#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
37#endif
38
39#ifndef _RET_IP_
40#define _RET_IP_ CALLER_ADDR0
41#endif
42
43#ifndef _THIS_IP_
44#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
45#endif
46
47#endif
diff --git a/tools/lib/lockdep/uinclude/linux/linkage.h b/tools/lib/lockdep/uinclude/linux/linkage.h
deleted file mode 100644
index fab00ff936d1..000000000000
--- a/tools/lib/lockdep/uinclude/linux/linkage.h
+++ /dev/null
@@ -1,3 +0,0 @@
1
2/* empty file */
3
diff --git a/tools/lib/lockdep/uinclude/linux/list.h b/tools/lib/lockdep/uinclude/linux/list.h
deleted file mode 100644
index 6e9ef31ed82e..000000000000
--- a/tools/lib/lockdep/uinclude/linux/list.h
+++ /dev/null
@@ -1 +0,0 @@
1#include "../../../include/linux/list.h"
diff --git a/tools/lib/lockdep/uinclude/linux/mutex.h b/tools/lib/lockdep/uinclude/linux/mutex.h
deleted file mode 100644
index fab00ff936d1..000000000000
--- a/tools/lib/lockdep/uinclude/linux/mutex.h
+++ /dev/null
@@ -1,3 +0,0 @@
1
2/* empty file */
3
diff --git a/tools/lib/lockdep/uinclude/linux/poison.h b/tools/lib/lockdep/uinclude/linux/poison.h
deleted file mode 100644
index 0c27bdf14233..000000000000
--- a/tools/lib/lockdep/uinclude/linux/poison.h
+++ /dev/null
@@ -1 +0,0 @@
1#include "../../../include/linux/poison.h"
diff --git a/tools/lib/lockdep/uinclude/linux/prefetch.h b/tools/lib/lockdep/uinclude/linux/prefetch.h
deleted file mode 100644
index d73fe6f850ac..000000000000
--- a/tools/lib/lockdep/uinclude/linux/prefetch.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef _LIBLOCKDEP_LINUX_PREFETCH_H_
2#define _LIBLOCKDEP_LINUX_PREFETCH_H
3
4static inline void prefetch(void *a __attribute__((unused))) { }
5
6#endif
diff --git a/tools/lib/lockdep/uinclude/linux/proc_fs.h b/tools/lib/lockdep/uinclude/linux/proc_fs.h
deleted file mode 100644
index fab00ff936d1..000000000000
--- a/tools/lib/lockdep/uinclude/linux/proc_fs.h
+++ /dev/null
@@ -1,3 +0,0 @@
1
2/* empty file */
3
diff --git a/tools/lib/lockdep/uinclude/linux/rbtree_augmented.h b/tools/lib/lockdep/uinclude/linux/rbtree_augmented.h
deleted file mode 100644
index c3759477379c..000000000000
--- a/tools/lib/lockdep/uinclude/linux/rbtree_augmented.h
+++ /dev/null
@@ -1,2 +0,0 @@
1#define __always_inline
2#include "../../../include/linux/rbtree_augmented.h"
diff --git a/tools/lib/lockdep/uinclude/linux/seq_file.h b/tools/lib/lockdep/uinclude/linux/seq_file.h
deleted file mode 100644
index fab00ff936d1..000000000000
--- a/tools/lib/lockdep/uinclude/linux/seq_file.h
+++ /dev/null
@@ -1,3 +0,0 @@
1
2/* empty file */
3
diff --git a/tools/lib/lockdep/uinclude/linux/spinlock.h b/tools/lib/lockdep/uinclude/linux/spinlock.h
deleted file mode 100644
index 68c1aa2bcba5..000000000000
--- a/tools/lib/lockdep/uinclude/linux/spinlock.h
+++ /dev/null
@@ -1,25 +0,0 @@
1#ifndef _LIBLOCKDEP_SPINLOCK_H_
2#define _LIBLOCKDEP_SPINLOCK_H_
3
4#include <pthread.h>
5#include <stdbool.h>
6
7#define arch_spinlock_t pthread_mutex_t
8#define __ARCH_SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER
9
10static inline void arch_spin_lock(arch_spinlock_t *mutex)
11{
12 pthread_mutex_lock(mutex);
13}
14
15static inline void arch_spin_unlock(arch_spinlock_t *mutex)
16{
17 pthread_mutex_unlock(mutex);
18}
19
20static inline bool arch_spin_is_locked(arch_spinlock_t *mutex)
21{
22 return true;
23}
24
25#endif
diff --git a/tools/lib/lockdep/uinclude/linux/stringify.h b/tools/lib/lockdep/uinclude/linux/stringify.h
deleted file mode 100644
index 05dfcd1ac118..000000000000
--- a/tools/lib/lockdep/uinclude/linux/stringify.h
+++ /dev/null
@@ -1,7 +0,0 @@
1#ifndef _LIBLOCKDEP_LINUX_STRINGIFY_H_
2#define _LIBLOCKDEP_LINUX_STRINGIFY_H_
3
4#define __stringify_1(x...) #x
5#define __stringify(x...) __stringify_1(x)
6
7#endif
diff --git a/tools/lib/lockdep/uinclude/trace/events/lock.h b/tools/lib/lockdep/uinclude/trace/events/lock.h
deleted file mode 100644
index fab00ff936d1..000000000000
--- a/tools/lib/lockdep/uinclude/trace/events/lock.h
+++ /dev/null
@@ -1,3 +0,0 @@
1
2/* empty file */
3
diff --git a/tools/net/bpf_jit_disasm.c b/tools/net/bpf_jit_disasm.c
index ad572e6cdbd0..422d9abd666a 100644
--- a/tools/net/bpf_jit_disasm.c
+++ b/tools/net/bpf_jit_disasm.c
@@ -159,8 +159,8 @@ static void put_log_buff(char *buff)
159 free(buff); 159 free(buff);
160} 160}
161 161
162static unsigned int get_last_jit_image(char *haystack, size_t hlen, 162static uint8_t *get_last_jit_image(char *haystack, size_t hlen,
163 uint8_t *image, size_t ilen) 163 unsigned int *ilen)
164{ 164{
165 char *ptr, *pptr, *tmp; 165 char *ptr, *pptr, *tmp;
166 off_t off = 0; 166 off_t off = 0;
@@ -168,9 +168,10 @@ static unsigned int get_last_jit_image(char *haystack, size_t hlen,
168 regmatch_t pmatch[1]; 168 regmatch_t pmatch[1];
169 unsigned long base; 169 unsigned long base;
170 regex_t regex; 170 regex_t regex;
171 uint8_t *image;
171 172
172 if (hlen == 0) 173 if (hlen == 0)
173 return 0; 174 return NULL;
174 175
175 ret = regcomp(&regex, "flen=[[:alnum:]]+ proglen=[[:digit:]]+ " 176 ret = regcomp(&regex, "flen=[[:alnum:]]+ proglen=[[:digit:]]+ "
176 "pass=[[:digit:]]+ image=[[:xdigit:]]+", REG_EXTENDED); 177 "pass=[[:digit:]]+ image=[[:xdigit:]]+", REG_EXTENDED);
@@ -194,11 +195,22 @@ static unsigned int get_last_jit_image(char *haystack, size_t hlen,
194 &flen, &proglen, &pass, &base); 195 &flen, &proglen, &pass, &base);
195 if (ret != 4) { 196 if (ret != 4) {
196 regfree(&regex); 197 regfree(&regex);
197 return 0; 198 return NULL;
199 }
200 if (proglen > 1000000) {
201 printf("proglen of %d too big, stopping\n", proglen);
202 return NULL;
198 } 203 }
199 204
205 image = malloc(proglen);
206 if (!image) {
207 printf("Out of memory\n");
208 return NULL;
209 }
210 memset(image, 0, proglen);
211
200 tmp = ptr = haystack + off; 212 tmp = ptr = haystack + off;
201 while ((ptr = strtok(tmp, "\n")) != NULL && ulen < ilen) { 213 while ((ptr = strtok(tmp, "\n")) != NULL && ulen < proglen) {
202 tmp = NULL; 214 tmp = NULL;
203 if (!strstr(ptr, "JIT code")) 215 if (!strstr(ptr, "JIT code"))
204 continue; 216 continue;
@@ -208,10 +220,12 @@ static unsigned int get_last_jit_image(char *haystack, size_t hlen,
208 ptr = pptr; 220 ptr = pptr;
209 do { 221 do {
210 image[ulen++] = (uint8_t) strtoul(pptr, &pptr, 16); 222 image[ulen++] = (uint8_t) strtoul(pptr, &pptr, 16);
211 if (ptr == pptr || ulen >= ilen) { 223 if (ptr == pptr) {
212 ulen--; 224 ulen--;
213 break; 225 break;
214 } 226 }
227 if (ulen >= proglen)
228 break;
215 ptr = pptr; 229 ptr = pptr;
216 } while (1); 230 } while (1);
217 } 231 }
@@ -222,7 +236,8 @@ static unsigned int get_last_jit_image(char *haystack, size_t hlen,
222 printf("%lx + <x>:\n", base); 236 printf("%lx + <x>:\n", base);
223 237
224 regfree(&regex); 238 regfree(&regex);
225 return ulen; 239 *ilen = ulen;
240 return image;
226} 241}
227 242
228static void usage(void) 243static void usage(void)
@@ -237,12 +252,12 @@ static void usage(void)
237int main(int argc, char **argv) 252int main(int argc, char **argv)
238{ 253{
239 unsigned int len, klen, opt, opcodes = 0; 254 unsigned int len, klen, opt, opcodes = 0;
240 static uint8_t image[32768];
241 char *kbuff, *file = NULL; 255 char *kbuff, *file = NULL;
242 char *ofile = NULL; 256 char *ofile = NULL;
243 int ofd; 257 int ofd;
244 ssize_t nr; 258 ssize_t nr;
245 uint8_t *pos; 259 uint8_t *pos;
260 uint8_t *image = NULL;
246 261
247 while ((opt = getopt(argc, argv, "of:O:")) != -1) { 262 while ((opt = getopt(argc, argv, "of:O:")) != -1) {
248 switch (opt) { 263 switch (opt) {
@@ -262,7 +277,6 @@ int main(int argc, char **argv)
262 } 277 }
263 278
264 bfd_init(); 279 bfd_init();
265 memset(image, 0, sizeof(image));
266 280
267 kbuff = get_log_buff(file, &klen); 281 kbuff = get_log_buff(file, &klen);
268 if (!kbuff) { 282 if (!kbuff) {
@@ -270,8 +284,8 @@ int main(int argc, char **argv)
270 return -1; 284 return -1;
271 } 285 }
272 286
273 len = get_last_jit_image(kbuff, klen, image, sizeof(image)); 287 image = get_last_jit_image(kbuff, klen, &len);
274 if (len <= 0) { 288 if (!image) {
275 fprintf(stderr, "No JIT image found!\n"); 289 fprintf(stderr, "No JIT image found!\n");
276 goto done; 290 goto done;
277 } 291 }
@@ -301,5 +315,6 @@ int main(int argc, char **argv)
301 315
302done: 316done:
303 put_log_buff(kbuff); 317 put_log_buff(kbuff);
318 free(image);
304 return 0; 319 return 0;
305} 320}
diff --git a/tools/objtool/Build b/tools/objtool/Build
index d6cdece5e58b..6f2e1987c4d9 100644
--- a/tools/objtool/Build
+++ b/tools/objtool/Build
@@ -1,5 +1,6 @@
1objtool-y += arch/$(SRCARCH)/ 1objtool-y += arch/$(SRCARCH)/
2objtool-y += builtin-check.o 2objtool-y += builtin-check.o
3objtool-y += check.o
3objtool-y += elf.o 4objtool-y += elf.o
4objtool-y += special.o 5objtool-y += special.o
5objtool-y += objtool.o 6objtool-y += objtool.o
diff --git a/tools/objtool/Documentation/stack-validation.txt b/tools/objtool/Documentation/stack-validation.txt
index 55a60d331f47..17c1195f11f4 100644
--- a/tools/objtool/Documentation/stack-validation.txt
+++ b/tools/objtool/Documentation/stack-validation.txt
@@ -127,28 +127,13 @@ b) 100% reliable stack traces for DWARF enabled kernels
127 127
128c) Higher live patching compatibility rate 128c) Higher live patching compatibility rate
129 129
130 (NOTE: This is not yet implemented) 130 Livepatch has an optional "consistency model", which is needed for
131 131 more complex patches. In order for the consistency model to work,
132 Currently with CONFIG_LIVEPATCH there's a basic live patching 132 stack traces need to be reliable (or an unreliable condition needs to
133 framework which is safe for roughly 85-90% of "security" fixes. But 133 be detectable). Objtool makes that possible.
134 patches can't have complex features like function dependency or
135 prototype changes, or data structure changes.
136
137 There's a strong need to support patches which have the more complex
138 features so that the patch compatibility rate for security fixes can
139 eventually approach something resembling 100%. To achieve that, a
140 "consistency model" is needed, which allows tasks to be safely
141 transitioned from an unpatched state to a patched state.
142
143 One of the key requirements of the currently proposed livepatch
144 consistency model [*] is that it needs to walk the stack of each
145 sleeping task to determine if it can be transitioned to the patched
146 state. If objtool can ensure that stack traces are reliable, this
147 consistency model can be used and the live patching compatibility
148 rate can be improved significantly.
149
150 [*] https://lkml.kernel.org/r/cover.1423499826.git.jpoimboe@redhat.com
151 134
135 For more details, see the livepatch documentation in the Linux kernel
136 source tree at Documentation/livepatch/livepatch.txt.
152 137
153Rules 138Rules
154----- 139-----
@@ -201,80 +186,84 @@ To achieve the validation, objtool enforces the following rules:
201 return normally. 186 return normally.
202 187
203 188
204Errors in .S files 189Objtool warnings
205------------------ 190----------------
206 191
207If you're getting an error in a compiled .S file which you don't 192For asm files, if you're getting an error which doesn't make sense,
208understand, first make sure that the affected code follows the above 193first make sure that the affected code follows the above rules.
209rules. 194
195For C files, the common culprits are inline asm statements and calls to
196"noreturn" functions. See below for more details.
197
198Another possible cause for errors in C code is if the Makefile removes
199-fno-omit-frame-pointer or adds -fomit-frame-pointer to the gcc options.
210 200
211Here are some examples of common warnings reported by objtool, what 201Here are some examples of common warnings reported by objtool, what
212they mean, and suggestions for how to fix them. 202they mean, and suggestions for how to fix them.
213 203
214 204
2151. asm_file.o: warning: objtool: func()+0x128: call without frame pointer save/setup 2051. file.o: warning: objtool: func()+0x128: call without frame pointer save/setup
216 206
217 The func() function made a function call without first saving and/or 207 The func() function made a function call without first saving and/or
218 updating the frame pointer. 208 updating the frame pointer, and CONFIG_FRAME_POINTER is enabled.
219
220 If func() is indeed a callable function, add proper frame pointer
221 logic using the FRAME_BEGIN and FRAME_END macros. Otherwise, remove
222 its ELF function annotation by changing ENDPROC to END.
223 209
224 If you're getting this error in a .c file, see the "Errors in .c 210 If the error is for an asm file, and func() is indeed a callable
225 files" section. 211 function, add proper frame pointer logic using the FRAME_BEGIN and
212 FRAME_END macros. Otherwise, if it's not a callable function, remove
213 its ELF function annotation by changing ENDPROC to END, and instead
214 use the manual CFI hint macros in asm/undwarf.h.
226 215
216 If it's a GCC-compiled .c file, the error may be because the function
217 uses an inline asm() statement which has a "call" instruction. An
218 asm() statement with a call instruction must declare the use of the
219 stack pointer in its output operand. For example, on x86_64:
227 220
2282. asm_file.o: warning: objtool: .text+0x53: return instruction outside of a callable function 221 register void *__sp asm("rsp");
229 222 asm volatile("call func" : "+r" (__sp));
230 A return instruction was detected, but objtool couldn't find a way
231 for a callable function to reach the instruction.
232 223
233 If the return instruction is inside (or reachable from) a callable 224 Otherwise the stack frame may not get created before the call.
234 function, the function needs to be annotated with the ENTRY/ENDPROC
235 macros.
236 225
237 If you _really_ need a return instruction outside of a function, and
238 are 100% sure that it won't affect stack traces, you can tell
239 objtool to ignore it. See the "Adding exceptions" section below.
240 226
2272. file.o: warning: objtool: .text+0x53: unreachable instruction
241 228
2423. asm_file.o: warning: objtool: func()+0x9: function has unreachable instruction 229 Objtool couldn't find a code path to reach the instruction.
243 230
244 The instruction lives inside of a callable function, but there's no 231 If the error is for an asm file, and the instruction is inside (or
245 possible control flow path from the beginning of the function to the 232 reachable from) a callable function, the function should be annotated
246 instruction. 233 with the ENTRY/ENDPROC macros (ENDPROC is the important one).
234 Otherwise, the code should probably be annotated with the CFI hint
235 macros in asm/undwarf.h so objtool and the unwinder can know the
236 stack state associated with the code.
247 237
248 If the instruction is actually needed, and it's actually in a 238 If you're 100% sure the code won't affect stack traces, or if you're
249 callable function, ensure that its function is properly annotated 239 a just a bad person, you can tell objtool to ignore it. See the
250 with ENTRY/ENDPROC. 240 "Adding exceptions" section below.
251 241
252 If it's not actually in a callable function (e.g. kernel entry code), 242 If it's not actually in a callable function (e.g. kernel entry code),
253 change ENDPROC to END. 243 change ENDPROC to END.
254 244
255 245
2564. asm_file.o: warning: objtool: func(): can't find starting instruction 2464. file.o: warning: objtool: func(): can't find starting instruction
257 or 247 or
258 asm_file.o: warning: objtool: func()+0x11dd: can't decode instruction 248 file.o: warning: objtool: func()+0x11dd: can't decode instruction
259 249
260 Did you put data in a text section? If so, that can confuse 250 Does the file have data in a text section? If so, that can confuse
261 objtool's instruction decoder. Move the data to a more appropriate 251 objtool's instruction decoder. Move the data to a more appropriate
262 section like .data or .rodata. 252 section like .data or .rodata.
263 253
264 254
2655. asm_file.o: warning: objtool: func()+0x6: kernel entry/exit from callable instruction 2555. file.o: warning: objtool: func()+0x6: unsupported instruction in callable function
266
267 This is a kernel entry/exit instruction like sysenter or sysret.
268 Such instructions aren't allowed in a callable function, and are most
269 likely part of the kernel entry code.
270 256
271 If the instruction isn't actually in a callable function, change 257 This is a kernel entry/exit instruction like sysenter or iret. Such
272 ENDPROC to END. 258 instructions aren't allowed in a callable function, and are most
259 likely part of the kernel entry code. They should usually not have
260 the callable function annotation (ENDPROC) and should always be
261 annotated with the CFI hint macros in asm/undwarf.h.
273 262
274 263
2756. asm_file.o: warning: objtool: func()+0x26: sibling call from callable instruction with changed frame pointer 2646. file.o: warning: objtool: func()+0x26: sibling call from callable instruction with modified stack frame
276 265
277 This is a dynamic jump or a jump to an undefined symbol. Stacktool 266 This is a dynamic jump or a jump to an undefined symbol. Objtool
278 assumed it's a sibling call and detected that the frame pointer 267 assumed it's a sibling call and detected that the frame pointer
279 wasn't first restored to its original state. 268 wasn't first restored to its original state.
280 269
@@ -282,24 +271,28 @@ they mean, and suggestions for how to fix them.
282 destination code to the local file. 271 destination code to the local file.
283 272
284 If the instruction is not actually in a callable function (e.g. 273 If the instruction is not actually in a callable function (e.g.
285 kernel entry code), change ENDPROC to END. 274 kernel entry code), change ENDPROC to END and annotate manually with
275 the CFI hint macros in asm/undwarf.h.
286 276
287 277
2887. asm_file: warning: objtool: func()+0x5c: frame pointer state mismatch 2787. file: warning: objtool: func()+0x5c: stack state mismatch
289 279
290 The instruction's frame pointer state is inconsistent, depending on 280 The instruction's frame pointer state is inconsistent, depending on
291 which execution path was taken to reach the instruction. 281 which execution path was taken to reach the instruction.
292 282
293 Make sure the function pushes and sets up the frame pointer (for 283 Make sure that, when CONFIG_FRAME_POINTER is enabled, the function
294 x86_64, this means rbp) at the beginning of the function and pops it 284 pushes and sets up the frame pointer (for x86_64, this means rbp) at
295 at the end of the function. Also make sure that no other code in the 285 the beginning of the function and pops it at the end of the function.
296 function touches the frame pointer. 286 Also make sure that no other code in the function touches the frame
287 pointer.
297 288
289 Another possibility is that the code has some asm or inline asm which
290 does some unusual things to the stack or the frame pointer. In such
291 cases it's probably appropriate to use the CFI hint macros in
292 asm/undwarf.h.
298 293
299Errors in .c files
300------------------
301 294
3021. c_file.o: warning: objtool: funcA() falls through to next function funcB() 2958. file.o: warning: objtool: funcA() falls through to next function funcB()
303 296
304 This means that funcA() doesn't end with a return instruction or an 297 This means that funcA() doesn't end with a return instruction or an
305 unconditional jump, and that objtool has determined that the function 298 unconditional jump, and that objtool has determined that the function
@@ -318,22 +311,6 @@ Errors in .c files
318 might be corrupt due to a gcc bug. For more details, see: 311 might be corrupt due to a gcc bug. For more details, see:
319 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70646 312 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70646
320 313
3212. If you're getting any other objtool error in a compiled .c file, it
322 may be because the file uses an asm() statement which has a "call"
323 instruction. An asm() statement with a call instruction must declare
324 the use of the stack pointer in its output operand. For example, on
325 x86_64:
326
327 register void *__sp asm("rsp");
328 asm volatile("call func" : "+r" (__sp));
329
330 Otherwise the stack frame may not get created before the call.
331
3323. Another possible cause for errors in C code is if the Makefile removes
333 -fno-omit-frame-pointer or adds -fomit-frame-pointer to the gcc options.
334
335Also see the above section for .S file errors for more information what
336the individual error messages mean.
337 314
338If the error doesn't seem to make sense, it could be a bug in objtool. 315If the error doesn't seem to make sense, it could be a bug in objtool.
339Feel free to ask the objtool maintainer for help. 316Feel free to ask the objtool maintainer for help.
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 27e019c09bd2..0e2765e243c0 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -25,7 +25,7 @@ OBJTOOL_IN := $(OBJTOOL)-in.o
25all: $(OBJTOOL) 25all: $(OBJTOOL)
26 26
27INCLUDES := -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi 27INCLUDES := -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi
28CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES) 28CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -Wno-switch-default -Wno-switch-enum -fomit-frame-pointer -O2 -g $(INCLUDES)
29LDFLAGS += -lelf $(LIBSUBCMD) 29LDFLAGS += -lelf $(LIBSUBCMD)
30 30
31# Allow old libelf to be used: 31# Allow old libelf to be used:
diff --git a/tools/objtool/arch.h b/tools/objtool/arch.h
index a59e061c0b4a..21aeca874edb 100644
--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@ -19,25 +19,63 @@
19#define _ARCH_H 19#define _ARCH_H
20 20
21#include <stdbool.h> 21#include <stdbool.h>
22#include <linux/list.h>
22#include "elf.h" 23#include "elf.h"
24#include "cfi.h"
23 25
24#define INSN_FP_SAVE 1 26#define INSN_JUMP_CONDITIONAL 1
25#define INSN_FP_SETUP 2 27#define INSN_JUMP_UNCONDITIONAL 2
26#define INSN_FP_RESTORE 3 28#define INSN_JUMP_DYNAMIC 3
27#define INSN_JUMP_CONDITIONAL 4 29#define INSN_CALL 4
28#define INSN_JUMP_UNCONDITIONAL 5 30#define INSN_CALL_DYNAMIC 5
29#define INSN_JUMP_DYNAMIC 6 31#define INSN_RETURN 6
30#define INSN_CALL 7 32#define INSN_CONTEXT_SWITCH 7
31#define INSN_CALL_DYNAMIC 8 33#define INSN_STACK 8
32#define INSN_RETURN 9 34#define INSN_NOP 9
33#define INSN_CONTEXT_SWITCH 10 35#define INSN_OTHER 10
34#define INSN_NOP 11
35#define INSN_OTHER 12
36#define INSN_LAST INSN_OTHER 36#define INSN_LAST INSN_OTHER
37 37
38enum op_dest_type {
39 OP_DEST_REG,
40 OP_DEST_REG_INDIRECT,
41 OP_DEST_MEM,
42 OP_DEST_PUSH,
43 OP_DEST_LEAVE,
44};
45
46struct op_dest {
47 enum op_dest_type type;
48 unsigned char reg;
49 int offset;
50};
51
52enum op_src_type {
53 OP_SRC_REG,
54 OP_SRC_REG_INDIRECT,
55 OP_SRC_CONST,
56 OP_SRC_POP,
57 OP_SRC_ADD,
58 OP_SRC_AND,
59};
60
61struct op_src {
62 enum op_src_type type;
63 unsigned char reg;
64 int offset;
65};
66
67struct stack_op {
68 struct op_dest dest;
69 struct op_src src;
70};
71
72void arch_initial_func_cfi_state(struct cfi_state *state);
73
38int arch_decode_instruction(struct elf *elf, struct section *sec, 74int arch_decode_instruction(struct elf *elf, struct section *sec,
39 unsigned long offset, unsigned int maxlen, 75 unsigned long offset, unsigned int maxlen,
40 unsigned int *len, unsigned char *type, 76 unsigned int *len, unsigned char *type,
41 unsigned long *displacement); 77 unsigned long *immediate, struct stack_op *op);
78
79bool arch_callee_saved_reg(unsigned char reg);
42 80
43#endif /* _ARCH_H */ 81#endif /* _ARCH_H */
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 6ac99e3266eb..a36c2eba64e7 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -27,6 +27,17 @@
27#include "../../arch.h" 27#include "../../arch.h"
28#include "../../warn.h" 28#include "../../warn.h"
29 29
30static unsigned char op_to_cfi_reg[][2] = {
31 {CFI_AX, CFI_R8},
32 {CFI_CX, CFI_R9},
33 {CFI_DX, CFI_R10},
34 {CFI_BX, CFI_R11},
35 {CFI_SP, CFI_R12},
36 {CFI_BP, CFI_R13},
37 {CFI_SI, CFI_R14},
38 {CFI_DI, CFI_R15},
39};
40
30static int is_x86_64(struct elf *elf) 41static int is_x86_64(struct elf *elf)
31{ 42{
32 switch (elf->ehdr.e_machine) { 43 switch (elf->ehdr.e_machine) {
@@ -40,24 +51,50 @@ static int is_x86_64(struct elf *elf)
40 } 51 }
41} 52}
42 53
54bool arch_callee_saved_reg(unsigned char reg)
55{
56 switch (reg) {
57 case CFI_BP:
58 case CFI_BX:
59 case CFI_R12:
60 case CFI_R13:
61 case CFI_R14:
62 case CFI_R15:
63 return true;
64
65 case CFI_AX:
66 case CFI_CX:
67 case CFI_DX:
68 case CFI_SI:
69 case CFI_DI:
70 case CFI_SP:
71 case CFI_R8:
72 case CFI_R9:
73 case CFI_R10:
74 case CFI_R11:
75 case CFI_RA:
76 default:
77 return false;
78 }
79}
80
43int arch_decode_instruction(struct elf *elf, struct section *sec, 81int arch_decode_instruction(struct elf *elf, struct section *sec,
44 unsigned long offset, unsigned int maxlen, 82 unsigned long offset, unsigned int maxlen,
45 unsigned int *len, unsigned char *type, 83 unsigned int *len, unsigned char *type,
46 unsigned long *immediate) 84 unsigned long *immediate, struct stack_op *op)
47{ 85{
48 struct insn insn; 86 struct insn insn;
49 int x86_64; 87 int x86_64, sign;
50 unsigned char op1, op2, ext; 88 unsigned char op1, op2, rex = 0, rex_b = 0, rex_r = 0, rex_w = 0,
89 modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
90 sib = 0;
51 91
52 x86_64 = is_x86_64(elf); 92 x86_64 = is_x86_64(elf);
53 if (x86_64 == -1) 93 if (x86_64 == -1)
54 return -1; 94 return -1;
55 95
56 insn_init(&insn, (void *)(sec->data + offset), maxlen, x86_64); 96 insn_init(&insn, sec->data->d_buf + offset, maxlen, x86_64);
57 insn_get_length(&insn); 97 insn_get_length(&insn);
58 insn_get_opcode(&insn);
59 insn_get_modrm(&insn);
60 insn_get_immediate(&insn);
61 98
62 if (!insn_complete(&insn)) { 99 if (!insn_complete(&insn)) {
63 WARN_FUNC("can't decode instruction", sec, offset); 100 WARN_FUNC("can't decode instruction", sec, offset);
@@ -73,67 +110,323 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
73 op1 = insn.opcode.bytes[0]; 110 op1 = insn.opcode.bytes[0];
74 op2 = insn.opcode.bytes[1]; 111 op2 = insn.opcode.bytes[1];
75 112
113 if (insn.rex_prefix.nbytes) {
114 rex = insn.rex_prefix.bytes[0];
115 rex_w = X86_REX_W(rex) >> 3;
116 rex_r = X86_REX_R(rex) >> 2;
117 rex_b = X86_REX_B(rex);
118 }
119
120 if (insn.modrm.nbytes) {
121 modrm = insn.modrm.bytes[0];
122 modrm_mod = X86_MODRM_MOD(modrm);
123 modrm_reg = X86_MODRM_REG(modrm);
124 modrm_rm = X86_MODRM_RM(modrm);
125 }
126
127 if (insn.sib.nbytes)
128 sib = insn.sib.bytes[0];
129
76 switch (op1) { 130 switch (op1) {
77 case 0x55: 131
78 if (!insn.rex_prefix.nbytes) 132 case 0x1:
79 /* push rbp */ 133 case 0x29:
80 *type = INSN_FP_SAVE; 134 if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
135
136 /* add/sub reg, %rsp */
137 *type = INSN_STACK;
138 op->src.type = OP_SRC_ADD;
139 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
140 op->dest.type = OP_SRC_REG;
141 op->dest.reg = CFI_SP;
142 }
143 break;
144
145 case 0x50 ... 0x57:
146
147 /* push reg */
148 *type = INSN_STACK;
149 op->src.type = OP_SRC_REG;
150 op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
151 op->dest.type = OP_DEST_PUSH;
152
81 break; 153 break;
82 154
83 case 0x5d: 155 case 0x58 ... 0x5f:
84 if (!insn.rex_prefix.nbytes) 156
85 /* pop rbp */ 157 /* pop reg */
86 *type = INSN_FP_RESTORE; 158 *type = INSN_STACK;
159 op->src.type = OP_SRC_POP;
160 op->dest.type = OP_DEST_REG;
161 op->dest.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
162
163 break;
164
165 case 0x68:
166 case 0x6a:
167 /* push immediate */
168 *type = INSN_STACK;
169 op->src.type = OP_SRC_CONST;
170 op->dest.type = OP_DEST_PUSH;
87 break; 171 break;
88 172
89 case 0x70 ... 0x7f: 173 case 0x70 ... 0x7f:
90 *type = INSN_JUMP_CONDITIONAL; 174 *type = INSN_JUMP_CONDITIONAL;
91 break; 175 break;
92 176
177 case 0x81:
178 case 0x83:
179 if (rex != 0x48)
180 break;
181
182 if (modrm == 0xe4) {
183 /* and imm, %rsp */
184 *type = INSN_STACK;
185 op->src.type = OP_SRC_AND;
186 op->src.reg = CFI_SP;
187 op->src.offset = insn.immediate.value;
188 op->dest.type = OP_DEST_REG;
189 op->dest.reg = CFI_SP;
190 break;
191 }
192
193 if (modrm == 0xc4)
194 sign = 1;
195 else if (modrm == 0xec)
196 sign = -1;
197 else
198 break;
199
200 /* add/sub imm, %rsp */
201 *type = INSN_STACK;
202 op->src.type = OP_SRC_ADD;
203 op->src.reg = CFI_SP;
204 op->src.offset = insn.immediate.value * sign;
205 op->dest.type = OP_DEST_REG;
206 op->dest.reg = CFI_SP;
207 break;
208
93 case 0x89: 209 case 0x89:
94 if (insn.rex_prefix.nbytes == 1 && 210 if (rex == 0x48 && modrm == 0xe5) {
95 insn.rex_prefix.bytes[0] == 0x48 && 211
96 insn.modrm.nbytes && insn.modrm.bytes[0] == 0xe5) 212 /* mov %rsp, %rbp */
97 /* mov rsp, rbp */ 213 *type = INSN_STACK;
98 *type = INSN_FP_SETUP; 214 op->src.type = OP_SRC_REG;
215 op->src.reg = CFI_SP;
216 op->dest.type = OP_DEST_REG;
217 op->dest.reg = CFI_BP;
218 break;
219 }
220 /* fallthrough */
221 case 0x88:
222 if (!rex_b &&
223 (modrm_mod == 1 || modrm_mod == 2) && modrm_rm == 5) {
224
225 /* mov reg, disp(%rbp) */
226 *type = INSN_STACK;
227 op->src.type = OP_SRC_REG;
228 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
229 op->dest.type = OP_DEST_REG_INDIRECT;
230 op->dest.reg = CFI_BP;
231 op->dest.offset = insn.displacement.value;
232
233 } else if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) {
234
235 /* mov reg, disp(%rsp) */
236 *type = INSN_STACK;
237 op->src.type = OP_SRC_REG;
238 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
239 op->dest.type = OP_DEST_REG_INDIRECT;
240 op->dest.reg = CFI_SP;
241 op->dest.offset = insn.displacement.value;
242 }
243
244 break;
245
246 case 0x8b:
247 if (rex_w && !rex_b && modrm_mod == 1 && modrm_rm == 5) {
248
249 /* mov disp(%rbp), reg */
250 *type = INSN_STACK;
251 op->src.type = OP_SRC_REG_INDIRECT;
252 op->src.reg = CFI_BP;
253 op->src.offset = insn.displacement.value;
254 op->dest.type = OP_DEST_REG;
255 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
256
257 } else if (rex_w && !rex_b && sib == 0x24 &&
258 modrm_mod != 3 && modrm_rm == 4) {
259
260 /* mov disp(%rsp), reg */
261 *type = INSN_STACK;
262 op->src.type = OP_SRC_REG_INDIRECT;
263 op->src.reg = CFI_SP;
264 op->src.offset = insn.displacement.value;
265 op->dest.type = OP_DEST_REG;
266 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
267 }
268
99 break; 269 break;
100 270
101 case 0x8d: 271 case 0x8d:
102 if (insn.rex_prefix.nbytes && 272 if (rex == 0x48 && modrm == 0x65) {
103 insn.rex_prefix.bytes[0] == 0x48 && 273
104 insn.modrm.nbytes && insn.modrm.bytes[0] == 0x2c && 274 /* lea -disp(%rbp), %rsp */
105 insn.sib.nbytes && insn.sib.bytes[0] == 0x24) 275 *type = INSN_STACK;
106 /* lea %(rsp), %rbp */ 276 op->src.type = OP_SRC_ADD;
107 *type = INSN_FP_SETUP; 277 op->src.reg = CFI_BP;
278 op->src.offset = insn.displacement.value;
279 op->dest.type = OP_DEST_REG;
280 op->dest.reg = CFI_SP;
281 break;
282 }
283
284 if (rex == 0x4c && modrm == 0x54 && sib == 0x24 &&
285 insn.displacement.value == 8) {
286
287 /*
288 * lea 0x8(%rsp), %r10
289 *
290 * Here r10 is the "drap" pointer, used as a stack
291 * pointer helper when the stack gets realigned.
292 */
293 *type = INSN_STACK;
294 op->src.type = OP_SRC_ADD;
295 op->src.reg = CFI_SP;
296 op->src.offset = 8;
297 op->dest.type = OP_DEST_REG;
298 op->dest.reg = CFI_R10;
299 break;
300 }
301
302 if (rex == 0x4c && modrm == 0x6c && sib == 0x24 &&
303 insn.displacement.value == 16) {
304
305 /*
306 * lea 0x10(%rsp), %r13
307 *
308 * Here r13 is the "drap" pointer, used as a stack
309 * pointer helper when the stack gets realigned.
310 */
311 *type = INSN_STACK;
312 op->src.type = OP_SRC_ADD;
313 op->src.reg = CFI_SP;
314 op->src.offset = 16;
315 op->dest.type = OP_DEST_REG;
316 op->dest.reg = CFI_R13;
317 break;
318 }
319
320 if (rex == 0x49 && modrm == 0x62 &&
321 insn.displacement.value == -8) {
322
323 /*
324 * lea -0x8(%r10), %rsp
325 *
326 * Restoring rsp back to its original value after a
327 * stack realignment.
328 */
329 *type = INSN_STACK;
330 op->src.type = OP_SRC_ADD;
331 op->src.reg = CFI_R10;
332 op->src.offset = -8;
333 op->dest.type = OP_DEST_REG;
334 op->dest.reg = CFI_SP;
335 break;
336 }
337
338 if (rex == 0x49 && modrm == 0x65 &&
339 insn.displacement.value == -16) {
340
341 /*
342 * lea -0x10(%r13), %rsp
343 *
344 * Restoring rsp back to its original value after a
345 * stack realignment.
346 */
347 *type = INSN_STACK;
348 op->src.type = OP_SRC_ADD;
349 op->src.reg = CFI_R13;
350 op->src.offset = -16;
351 op->dest.type = OP_DEST_REG;
352 op->dest.reg = CFI_SP;
353 break;
354 }
355
356 break;
357
358 case 0x8f:
359 /* pop to mem */
360 *type = INSN_STACK;
361 op->src.type = OP_SRC_POP;
362 op->dest.type = OP_DEST_MEM;
108 break; 363 break;
109 364
110 case 0x90: 365 case 0x90:
111 *type = INSN_NOP; 366 *type = INSN_NOP;
112 break; 367 break;
113 368
369 case 0x9c:
370 /* pushf */
371 *type = INSN_STACK;
372 op->src.type = OP_SRC_CONST;
373 op->dest.type = OP_DEST_PUSH;
374 break;
375
376 case 0x9d:
377 /* popf */
378 *type = INSN_STACK;
379 op->src.type = OP_SRC_POP;
380 op->dest.type = OP_DEST_MEM;
381 break;
382
114 case 0x0f: 383 case 0x0f:
384
115 if (op2 >= 0x80 && op2 <= 0x8f) 385 if (op2 >= 0x80 && op2 <= 0x8f)
116 *type = INSN_JUMP_CONDITIONAL; 386 *type = INSN_JUMP_CONDITIONAL;
117 else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 || 387 else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 ||
118 op2 == 0x35) 388 op2 == 0x35)
389
119 /* sysenter, sysret */ 390 /* sysenter, sysret */
120 *type = INSN_CONTEXT_SWITCH; 391 *type = INSN_CONTEXT_SWITCH;
392
121 else if (op2 == 0x0d || op2 == 0x1f) 393 else if (op2 == 0x0d || op2 == 0x1f)
394
122 /* nopl/nopw */ 395 /* nopl/nopw */
123 *type = INSN_NOP; 396 *type = INSN_NOP;
124 else if (op2 == 0x01 && insn.modrm.nbytes && 397
125 (insn.modrm.bytes[0] == 0xc2 || 398 else if (op2 == 0xa0 || op2 == 0xa8) {
126 insn.modrm.bytes[0] == 0xd8)) 399
127 /* vmlaunch, vmrun */ 400 /* push fs/gs */
128 *type = INSN_CONTEXT_SWITCH; 401 *type = INSN_STACK;
402 op->src.type = OP_SRC_CONST;
403 op->dest.type = OP_DEST_PUSH;
404
405 } else if (op2 == 0xa1 || op2 == 0xa9) {
406
407 /* pop fs/gs */
408 *type = INSN_STACK;
409 op->src.type = OP_SRC_POP;
410 op->dest.type = OP_DEST_MEM;
411 }
129 412
130 break; 413 break;
131 414
132 case 0xc9: /* leave */ 415 case 0xc9:
133 *type = INSN_FP_RESTORE; 416 /*
417 * leave
418 *
419 * equivalent to:
420 * mov bp, sp
421 * pop bp
422 */
423 *type = INSN_STACK;
424 op->dest.type = OP_DEST_LEAVE;
425
134 break; 426 break;
135 427
136 case 0xe3: /* jecxz/jrcxz */ 428 case 0xe3:
429 /* jecxz/jrcxz */
137 *type = INSN_JUMP_CONDITIONAL; 430 *type = INSN_JUMP_CONDITIONAL;
138 break; 431 break;
139 432
@@ -158,14 +451,27 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
158 break; 451 break;
159 452
160 case 0xff: 453 case 0xff:
161 ext = X86_MODRM_REG(insn.modrm.bytes[0]); 454 if (modrm_reg == 2 || modrm_reg == 3)
162 if (ext == 2 || ext == 3) 455
163 *type = INSN_CALL_DYNAMIC; 456 *type = INSN_CALL_DYNAMIC;
164 else if (ext == 4) 457
458 else if (modrm_reg == 4)
459
165 *type = INSN_JUMP_DYNAMIC; 460 *type = INSN_JUMP_DYNAMIC;
166 else if (ext == 5) /*jmpf */ 461
462 else if (modrm_reg == 5)
463
464 /* jmpf */
167 *type = INSN_CONTEXT_SWITCH; 465 *type = INSN_CONTEXT_SWITCH;
168 466
467 else if (modrm_reg == 6) {
468
469 /* push from mem */
470 *type = INSN_STACK;
471 op->src.type = OP_SRC_CONST;
472 op->dest.type = OP_DEST_PUSH;
473 }
474
169 break; 475 break;
170 476
171 default: 477 default:
@@ -176,3 +482,21 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
176 482
177 return 0; 483 return 0;
178} 484}
485
486void arch_initial_func_cfi_state(struct cfi_state *state)
487{
488 int i;
489
490 for (i = 0; i < CFI_NUM_REGS; i++) {
491 state->regs[i].base = CFI_UNDEFINED;
492 state->regs[i].offset = 0;
493 }
494
495 /* initial CFA (call frame address) */
496 state->cfa.base = CFI_SP;
497 state->cfa.offset = 8;
498
499 /* initial RA (return address) */
500 state->regs[16].base = CFI_CFA;
501 state->regs[16].offset = -8;
502}
diff --git a/tools/objtool/arch/x86/insn/x86-opcode-map.txt b/tools/objtool/arch/x86/insn/x86-opcode-map.txt
index 767be7c76034..12e377184ee4 100644
--- a/tools/objtool/arch/x86/insn/x86-opcode-map.txt
+++ b/tools/objtool/arch/x86/insn/x86-opcode-map.txt
@@ -1009,7 +1009,7 @@ GrpTable: Grp15
10091: fxstor | RDGSBASE Ry (F3),(11B) 10091: fxstor | RDGSBASE Ry (F3),(11B)
10102: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B) 10102: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B)
10113: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B) 10113: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B)
10124: XSAVE 10124: XSAVE | ptwrite Ey (F3),(11B)
10135: XRSTOR | lfence (11B) 10135: XRSTOR | lfence (11B)
10146: XSAVEOPT | clwb (66) | mfence (11B) 10146: XSAVEOPT | clwb (66) | mfence (11B)
10157: clflush | clflushopt (66) | sfence (11B) 10157: clflush | clflushopt (66) | sfence (11B)
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index 282a60368b14..365c34ecab26 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com> 2 * Copyright (C) 2015-2017 Josh Poimboeuf <jpoimboe@redhat.com>
3 * 3 *
4 * This program is free software; you can redistribute it and/or 4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License 5 * modify it under the terms of the GNU General Public License
@@ -25,1286 +25,32 @@
25 * For more information, see tools/objtool/Documentation/stack-validation.txt. 25 * For more information, see tools/objtool/Documentation/stack-validation.txt.
26 */ 26 */
27 27
28#include <string.h>
29#include <stdlib.h>
30#include <subcmd/parse-options.h> 28#include <subcmd/parse-options.h>
31
32#include "builtin.h" 29#include "builtin.h"
33#include "elf.h" 30#include "check.h"
34#include "special.h"
35#include "arch.h"
36#include "warn.h"
37
38#include <linux/hashtable.h>
39#include <linux/kernel.h>
40
41#define STATE_FP_SAVED 0x1
42#define STATE_FP_SETUP 0x2
43#define STATE_FENTRY 0x4
44
45struct instruction {
46 struct list_head list;
47 struct hlist_node hash;
48 struct section *sec;
49 unsigned long offset;
50 unsigned int len, state;
51 unsigned char type;
52 unsigned long immediate;
53 bool alt_group, visited, dead_end;
54 struct symbol *call_dest;
55 struct instruction *jump_dest;
56 struct list_head alts;
57 struct symbol *func;
58};
59
60struct alternative {
61 struct list_head list;
62 struct instruction *insn;
63};
64
65struct objtool_file {
66 struct elf *elf;
67 struct list_head insn_list;
68 DECLARE_HASHTABLE(insn_hash, 16);
69 struct section *rodata, *whitelist;
70 bool ignore_unreachables, c_file;
71};
72
73const char *objname;
74static bool nofp;
75
76static struct instruction *find_insn(struct objtool_file *file,
77 struct section *sec, unsigned long offset)
78{
79 struct instruction *insn;
80
81 hash_for_each_possible(file->insn_hash, insn, hash, offset)
82 if (insn->sec == sec && insn->offset == offset)
83 return insn;
84
85 return NULL;
86}
87
88static struct instruction *next_insn_same_sec(struct objtool_file *file,
89 struct instruction *insn)
90{
91 struct instruction *next = list_next_entry(insn, list);
92
93 if (&next->list == &file->insn_list || next->sec != insn->sec)
94 return NULL;
95
96 return next;
97}
98
99static bool gcov_enabled(struct objtool_file *file)
100{
101 struct section *sec;
102 struct symbol *sym;
103
104 list_for_each_entry(sec, &file->elf->sections, list)
105 list_for_each_entry(sym, &sec->symbol_list, list)
106 if (!strncmp(sym->name, "__gcov_.", 8))
107 return true;
108
109 return false;
110}
111
112#define for_each_insn(file, insn) \
113 list_for_each_entry(insn, &file->insn_list, list)
114
115#define func_for_each_insn(file, func, insn) \
116 for (insn = find_insn(file, func->sec, func->offset); \
117 insn && &insn->list != &file->insn_list && \
118 insn->sec == func->sec && \
119 insn->offset < func->offset + func->len; \
120 insn = list_next_entry(insn, list))
121
122#define func_for_each_insn_continue_reverse(file, func, insn) \
123 for (insn = list_prev_entry(insn, list); \
124 &insn->list != &file->insn_list && \
125 insn->sec == func->sec && insn->offset >= func->offset; \
126 insn = list_prev_entry(insn, list))
127
128#define sec_for_each_insn_from(file, insn) \
129 for (; insn; insn = next_insn_same_sec(file, insn))
130
131
132/*
133 * Check if the function has been manually whitelisted with the
134 * STACK_FRAME_NON_STANDARD macro, or if it should be automatically whitelisted
135 * due to its use of a context switching instruction.
136 */
137static bool ignore_func(struct objtool_file *file, struct symbol *func)
138{
139 struct rela *rela;
140 struct instruction *insn;
141
142 /* check for STACK_FRAME_NON_STANDARD */
143 if (file->whitelist && file->whitelist->rela)
144 list_for_each_entry(rela, &file->whitelist->rela->rela_list, list) {
145 if (rela->sym->type == STT_SECTION &&
146 rela->sym->sec == func->sec &&
147 rela->addend == func->offset)
148 return true;
149 if (rela->sym->type == STT_FUNC && rela->sym == func)
150 return true;
151 }
152
153 /* check if it has a context switching instruction */
154 func_for_each_insn(file, func, insn)
155 if (insn->type == INSN_CONTEXT_SWITCH)
156 return true;
157
158 return false;
159}
160
161/*
162 * This checks to see if the given function is a "noreturn" function.
163 *
164 * For global functions which are outside the scope of this object file, we
165 * have to keep a manual list of them.
166 *
167 * For local functions, we have to detect them manually by simply looking for
168 * the lack of a return instruction.
169 *
170 * Returns:
171 * -1: error
172 * 0: no dead end
173 * 1: dead end
174 */
175static int __dead_end_function(struct objtool_file *file, struct symbol *func,
176 int recursion)
177{
178 int i;
179 struct instruction *insn;
180 bool empty = true;
181
182 /*
183 * Unfortunately these have to be hard coded because the noreturn
184 * attribute isn't provided in ELF data.
185 */
186 static const char * const global_noreturns[] = {
187 "__stack_chk_fail",
188 "panic",
189 "do_exit",
190 "do_task_dead",
191 "__module_put_and_exit",
192 "complete_and_exit",
193 "kvm_spurious_fault",
194 "__reiserfs_panic",
195 "lbug_with_loc"
196 };
197
198 if (func->bind == STB_WEAK)
199 return 0;
200
201 if (func->bind == STB_GLOBAL)
202 for (i = 0; i < ARRAY_SIZE(global_noreturns); i++)
203 if (!strcmp(func->name, global_noreturns[i]))
204 return 1;
205
206 if (!func->sec)
207 return 0;
208
209 func_for_each_insn(file, func, insn) {
210 empty = false;
211
212 if (insn->type == INSN_RETURN)
213 return 0;
214 }
215
216 if (empty)
217 return 0;
218
219 /*
220 * A function can have a sibling call instead of a return. In that
221 * case, the function's dead-end status depends on whether the target
222 * of the sibling call returns.
223 */
224 func_for_each_insn(file, func, insn) {
225 if (insn->sec != func->sec ||
226 insn->offset >= func->offset + func->len)
227 break;
228
229 if (insn->type == INSN_JUMP_UNCONDITIONAL) {
230 struct instruction *dest = insn->jump_dest;
231 struct symbol *dest_func;
232
233 if (!dest)
234 /* sibling call to another file */
235 return 0;
236
237 if (dest->sec != func->sec ||
238 dest->offset < func->offset ||
239 dest->offset >= func->offset + func->len) {
240 /* local sibling call */
241 dest_func = find_symbol_by_offset(dest->sec,
242 dest->offset);
243 if (!dest_func)
244 continue;
245
246 if (recursion == 5) {
247 WARN_FUNC("infinite recursion (objtool bug!)",
248 dest->sec, dest->offset);
249 return -1;
250 }
251
252 return __dead_end_function(file, dest_func,
253 recursion + 1);
254 }
255 }
256
257 if (insn->type == INSN_JUMP_DYNAMIC && list_empty(&insn->alts))
258 /* sibling call */
259 return 0;
260 }
261
262 return 1;
263}
264
265static int dead_end_function(struct objtool_file *file, struct symbol *func)
266{
267 return __dead_end_function(file, func, 0);
268}
269
270/*
271 * Call the arch-specific instruction decoder for all the instructions and add
272 * them to the global instruction list.
273 */
274static int decode_instructions(struct objtool_file *file)
275{
276 struct section *sec;
277 struct symbol *func;
278 unsigned long offset;
279 struct instruction *insn;
280 int ret;
281
282 list_for_each_entry(sec, &file->elf->sections, list) {
283
284 if (!(sec->sh.sh_flags & SHF_EXECINSTR))
285 continue;
286
287 for (offset = 0; offset < sec->len; offset += insn->len) {
288 insn = malloc(sizeof(*insn));
289 memset(insn, 0, sizeof(*insn));
290
291 INIT_LIST_HEAD(&insn->alts);
292 insn->sec = sec;
293 insn->offset = offset;
294
295 ret = arch_decode_instruction(file->elf, sec, offset,
296 sec->len - offset,
297 &insn->len, &insn->type,
298 &insn->immediate);
299 if (ret)
300 return ret;
301
302 if (!insn->type || insn->type > INSN_LAST) {
303 WARN_FUNC("invalid instruction type %d",
304 insn->sec, insn->offset, insn->type);
305 return -1;
306 }
307
308 hash_add(file->insn_hash, &insn->hash, insn->offset);
309 list_add_tail(&insn->list, &file->insn_list);
310 }
311
312 list_for_each_entry(func, &sec->symbol_list, list) {
313 if (func->type != STT_FUNC)
314 continue;
315
316 if (!find_insn(file, sec, func->offset)) {
317 WARN("%s(): can't find starting instruction",
318 func->name);
319 return -1;
320 }
321
322 func_for_each_insn(file, func, insn)
323 if (!insn->func)
324 insn->func = func;
325 }
326 }
327
328 return 0;
329}
330
331/*
332 * Find all uses of the unreachable() macro, which are code path dead ends.
333 */
334static int add_dead_ends(struct objtool_file *file)
335{
336 struct section *sec;
337 struct rela *rela;
338 struct instruction *insn;
339 bool found;
340
341 sec = find_section_by_name(file->elf, ".rela.discard.unreachable");
342 if (!sec)
343 return 0;
344
345 list_for_each_entry(rela, &sec->rela_list, list) {
346 if (rela->sym->type != STT_SECTION) {
347 WARN("unexpected relocation symbol type in %s", sec->name);
348 return -1;
349 }
350 insn = find_insn(file, rela->sym->sec, rela->addend);
351 if (insn)
352 insn = list_prev_entry(insn, list);
353 else if (rela->addend == rela->sym->sec->len) {
354 found = false;
355 list_for_each_entry_reverse(insn, &file->insn_list, list) {
356 if (insn->sec == rela->sym->sec) {
357 found = true;
358 break;
359 }
360 }
361
362 if (!found) {
363 WARN("can't find unreachable insn at %s+0x%x",
364 rela->sym->sec->name, rela->addend);
365 return -1;
366 }
367 } else {
368 WARN("can't find unreachable insn at %s+0x%x",
369 rela->sym->sec->name, rela->addend);
370 return -1;
371 }
372
373 insn->dead_end = true;
374 }
375
376 return 0;
377}
378
379/*
380 * Warnings shouldn't be reported for ignored functions.
381 */
382static void add_ignores(struct objtool_file *file)
383{
384 struct instruction *insn;
385 struct section *sec;
386 struct symbol *func;
387
388 list_for_each_entry(sec, &file->elf->sections, list) {
389 list_for_each_entry(func, &sec->symbol_list, list) {
390 if (func->type != STT_FUNC)
391 continue;
392
393 if (!ignore_func(file, func))
394 continue;
395
396 func_for_each_insn(file, func, insn)
397 insn->visited = true;
398 }
399 }
400}
401
402/*
403 * Find the destination instructions for all jumps.
404 */
405static int add_jump_destinations(struct objtool_file *file)
406{
407 struct instruction *insn;
408 struct rela *rela;
409 struct section *dest_sec;
410 unsigned long dest_off;
411
412 for_each_insn(file, insn) {
413 if (insn->type != INSN_JUMP_CONDITIONAL &&
414 insn->type != INSN_JUMP_UNCONDITIONAL)
415 continue;
416
417 /* skip ignores */
418 if (insn->visited)
419 continue;
420
421 rela = find_rela_by_dest_range(insn->sec, insn->offset,
422 insn->len);
423 if (!rela) {
424 dest_sec = insn->sec;
425 dest_off = insn->offset + insn->len + insn->immediate;
426 } else if (rela->sym->type == STT_SECTION) {
427 dest_sec = rela->sym->sec;
428 dest_off = rela->addend + 4;
429 } else if (rela->sym->sec->idx) {
430 dest_sec = rela->sym->sec;
431 dest_off = rela->sym->sym.st_value + rela->addend + 4;
432 } else {
433 /* sibling call */
434 insn->jump_dest = 0;
435 continue;
436 }
437
438 insn->jump_dest = find_insn(file, dest_sec, dest_off);
439 if (!insn->jump_dest) {
440
441 /*
442 * This is a special case where an alt instruction
443 * jumps past the end of the section. These are
444 * handled later in handle_group_alt().
445 */
446 if (!strcmp(insn->sec->name, ".altinstr_replacement"))
447 continue;
448
449 WARN_FUNC("can't find jump dest instruction at %s+0x%lx",
450 insn->sec, insn->offset, dest_sec->name,
451 dest_off);
452 return -1;
453 }
454 }
455
456 return 0;
457}
458
459/*
460 * Find the destination instructions for all calls.
461 */
462static int add_call_destinations(struct objtool_file *file)
463{
464 struct instruction *insn;
465 unsigned long dest_off;
466 struct rela *rela;
467
468 for_each_insn(file, insn) {
469 if (insn->type != INSN_CALL)
470 continue;
471
472 rela = find_rela_by_dest_range(insn->sec, insn->offset,
473 insn->len);
474 if (!rela) {
475 dest_off = insn->offset + insn->len + insn->immediate;
476 insn->call_dest = find_symbol_by_offset(insn->sec,
477 dest_off);
478 if (!insn->call_dest) {
479 WARN_FUNC("can't find call dest symbol at offset 0x%lx",
480 insn->sec, insn->offset, dest_off);
481 return -1;
482 }
483 } else if (rela->sym->type == STT_SECTION) {
484 insn->call_dest = find_symbol_by_offset(rela->sym->sec,
485 rela->addend+4);
486 if (!insn->call_dest ||
487 insn->call_dest->type != STT_FUNC) {
488 WARN_FUNC("can't find call dest symbol at %s+0x%x",
489 insn->sec, insn->offset,
490 rela->sym->sec->name,
491 rela->addend + 4);
492 return -1;
493 }
494 } else
495 insn->call_dest = rela->sym;
496 }
497
498 return 0;
499}
500
501/*
502 * The .alternatives section requires some extra special care, over and above
503 * what other special sections require:
504 *
505 * 1. Because alternatives are patched in-place, we need to insert a fake jump
506 * instruction at the end so that validate_branch() skips all the original
507 * replaced instructions when validating the new instruction path.
508 *
509 * 2. An added wrinkle is that the new instruction length might be zero. In
510 * that case the old instructions are replaced with noops. We simulate that
511 * by creating a fake jump as the only new instruction.
512 *
513 * 3. In some cases, the alternative section includes an instruction which
514 * conditionally jumps to the _end_ of the entry. We have to modify these
515 * jumps' destinations to point back to .text rather than the end of the
516 * entry in .altinstr_replacement.
517 *
518 * 4. It has been requested that we don't validate the !POPCNT feature path
519 * which is a "very very small percentage of machines".
520 */
521static int handle_group_alt(struct objtool_file *file,
522 struct special_alt *special_alt,
523 struct instruction *orig_insn,
524 struct instruction **new_insn)
525{
526 struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump;
527 unsigned long dest_off;
528
529 last_orig_insn = NULL;
530 insn = orig_insn;
531 sec_for_each_insn_from(file, insn) {
532 if (insn->offset >= special_alt->orig_off + special_alt->orig_len)
533 break;
534
535 if (special_alt->skip_orig)
536 insn->type = INSN_NOP;
537
538 insn->alt_group = true;
539 last_orig_insn = insn;
540 }
541
542 if (!next_insn_same_sec(file, last_orig_insn)) {
543 WARN("%s: don't know how to handle alternatives at end of section",
544 special_alt->orig_sec->name);
545 return -1;
546 }
547
548 fake_jump = malloc(sizeof(*fake_jump));
549 if (!fake_jump) {
550 WARN("malloc failed");
551 return -1;
552 }
553 memset(fake_jump, 0, sizeof(*fake_jump));
554 INIT_LIST_HEAD(&fake_jump->alts);
555 fake_jump->sec = special_alt->new_sec;
556 fake_jump->offset = -1;
557 fake_jump->type = INSN_JUMP_UNCONDITIONAL;
558 fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
559
560 if (!special_alt->new_len) {
561 *new_insn = fake_jump;
562 return 0;
563 }
564
565 last_new_insn = NULL;
566 insn = *new_insn;
567 sec_for_each_insn_from(file, insn) {
568 if (insn->offset >= special_alt->new_off + special_alt->new_len)
569 break;
570
571 last_new_insn = insn;
572
573 if (insn->type != INSN_JUMP_CONDITIONAL &&
574 insn->type != INSN_JUMP_UNCONDITIONAL)
575 continue;
576
577 if (!insn->immediate)
578 continue;
579
580 dest_off = insn->offset + insn->len + insn->immediate;
581 if (dest_off == special_alt->new_off + special_alt->new_len)
582 insn->jump_dest = fake_jump;
583
584 if (!insn->jump_dest) {
585 WARN_FUNC("can't find alternative jump destination",
586 insn->sec, insn->offset);
587 return -1;
588 }
589 }
590
591 if (!last_new_insn) {
592 WARN_FUNC("can't find last new alternative instruction",
593 special_alt->new_sec, special_alt->new_off);
594 return -1;
595 }
596
597 list_add(&fake_jump->list, &last_new_insn->list);
598
599 return 0;
600}
601
602/*
603 * A jump table entry can either convert a nop to a jump or a jump to a nop.
604 * If the original instruction is a jump, make the alt entry an effective nop
605 * by just skipping the original instruction.
606 */
607static int handle_jump_alt(struct objtool_file *file,
608 struct special_alt *special_alt,
609 struct instruction *orig_insn,
610 struct instruction **new_insn)
611{
612 if (orig_insn->type == INSN_NOP)
613 return 0;
614
615 if (orig_insn->type != INSN_JUMP_UNCONDITIONAL) {
616 WARN_FUNC("unsupported instruction at jump label",
617 orig_insn->sec, orig_insn->offset);
618 return -1;
619 }
620
621 *new_insn = list_next_entry(orig_insn, list);
622 return 0;
623}
624
625/*
626 * Read all the special sections which have alternate instructions which can be
627 * patched in or redirected to at runtime. Each instruction having alternate
628 * instruction(s) has them added to its insn->alts list, which will be
629 * traversed in validate_branch().
630 */
631static int add_special_section_alts(struct objtool_file *file)
632{
633 struct list_head special_alts;
634 struct instruction *orig_insn, *new_insn;
635 struct special_alt *special_alt, *tmp;
636 struct alternative *alt;
637 int ret;
638
639 ret = special_get_alts(file->elf, &special_alts);
640 if (ret)
641 return ret;
642
643 list_for_each_entry_safe(special_alt, tmp, &special_alts, list) {
644 alt = malloc(sizeof(*alt));
645 if (!alt) {
646 WARN("malloc failed");
647 ret = -1;
648 goto out;
649 }
650
651 orig_insn = find_insn(file, special_alt->orig_sec,
652 special_alt->orig_off);
653 if (!orig_insn) {
654 WARN_FUNC("special: can't find orig instruction",
655 special_alt->orig_sec, special_alt->orig_off);
656 ret = -1;
657 goto out;
658 }
659 31
660 new_insn = NULL; 32bool nofp;
661 if (!special_alt->group || special_alt->new_len) {
662 new_insn = find_insn(file, special_alt->new_sec,
663 special_alt->new_off);
664 if (!new_insn) {
665 WARN_FUNC("special: can't find new instruction",
666 special_alt->new_sec,
667 special_alt->new_off);
668 ret = -1;
669 goto out;
670 }
671 }
672 33
673 if (special_alt->group) { 34static const char * const check_usage[] = {
674 ret = handle_group_alt(file, special_alt, orig_insn,
675 &new_insn);
676 if (ret)
677 goto out;
678 } else if (special_alt->jump_or_nop) {
679 ret = handle_jump_alt(file, special_alt, orig_insn,
680 &new_insn);
681 if (ret)
682 goto out;
683 }
684
685 alt->insn = new_insn;
686 list_add_tail(&alt->list, &orig_insn->alts);
687
688 list_del(&special_alt->list);
689 free(special_alt);
690 }
691
692out:
693 return ret;
694}
695
696static int add_switch_table(struct objtool_file *file, struct symbol *func,
697 struct instruction *insn, struct rela *table,
698 struct rela *next_table)
699{
700 struct rela *rela = table;
701 struct instruction *alt_insn;
702 struct alternative *alt;
703
704 list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) {
705 if (rela == next_table)
706 break;
707
708 if (rela->sym->sec != insn->sec ||
709 rela->addend <= func->offset ||
710 rela->addend >= func->offset + func->len)
711 break;
712
713 alt_insn = find_insn(file, insn->sec, rela->addend);
714 if (!alt_insn) {
715 WARN("%s: can't find instruction at %s+0x%x",
716 file->rodata->rela->name, insn->sec->name,
717 rela->addend);
718 return -1;
719 }
720
721 alt = malloc(sizeof(*alt));
722 if (!alt) {
723 WARN("malloc failed");
724 return -1;
725 }
726
727 alt->insn = alt_insn;
728 list_add_tail(&alt->list, &insn->alts);
729 }
730
731 return 0;
732}
733
734/*
735 * find_switch_table() - Given a dynamic jump, find the switch jump table in
736 * .rodata associated with it.
737 *
738 * There are 3 basic patterns:
739 *
740 * 1. jmpq *[rodata addr](,%reg,8)
741 *
742 * This is the most common case by far. It jumps to an address in a simple
743 * jump table which is stored in .rodata.
744 *
745 * 2. jmpq *[rodata addr](%rip)
746 *
747 * This is caused by a rare GCC quirk, currently only seen in three driver
748 * functions in the kernel, only with certain obscure non-distro configs.
749 *
750 * As part of an optimization, GCC makes a copy of an existing switch jump
751 * table, modifies it, and then hard-codes the jump (albeit with an indirect
752 * jump) to use a single entry in the table. The rest of the jump table and
753 * some of its jump targets remain as dead code.
754 *
755 * In such a case we can just crudely ignore all unreachable instruction
756 * warnings for the entire object file. Ideally we would just ignore them
757 * for the function, but that would require redesigning the code quite a
758 * bit. And honestly that's just not worth doing: unreachable instruction
759 * warnings are of questionable value anyway, and this is such a rare issue.
760 *
761 * 3. mov [rodata addr],%reg1
762 * ... some instructions ...
763 * jmpq *(%reg1,%reg2,8)
764 *
765 * This is a fairly uncommon pattern which is new for GCC 6. As of this
766 * writing, there are 11 occurrences of it in the allmodconfig kernel.
767 *
768 * TODO: Once we have DWARF CFI and smarter instruction decoding logic,
769 * ensure the same register is used in the mov and jump instructions.
770 */
771static struct rela *find_switch_table(struct objtool_file *file,
772 struct symbol *func,
773 struct instruction *insn)
774{
775 struct rela *text_rela, *rodata_rela;
776 struct instruction *orig_insn = insn;
777
778 text_rela = find_rela_by_dest_range(insn->sec, insn->offset, insn->len);
779 if (text_rela && text_rela->sym == file->rodata->sym) {
780 /* case 1 */
781 rodata_rela = find_rela_by_dest(file->rodata,
782 text_rela->addend);
783 if (rodata_rela)
784 return rodata_rela;
785
786 /* case 2 */
787 rodata_rela = find_rela_by_dest(file->rodata,
788 text_rela->addend + 4);
789 if (!rodata_rela)
790 return NULL;
791 file->ignore_unreachables = true;
792 return rodata_rela;
793 }
794
795 /* case 3 */
796 func_for_each_insn_continue_reverse(file, func, insn) {
797 if (insn->type == INSN_JUMP_DYNAMIC)
798 break;
799
800 /* allow small jumps within the range */
801 if (insn->type == INSN_JUMP_UNCONDITIONAL &&
802 insn->jump_dest &&
803 (insn->jump_dest->offset <= insn->offset ||
804 insn->jump_dest->offset > orig_insn->offset))
805 break;
806
807 /* look for a relocation which references .rodata */
808 text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
809 insn->len);
810 if (!text_rela || text_rela->sym != file->rodata->sym)
811 continue;
812
813 /*
814 * Make sure the .rodata address isn't associated with a
815 * symbol. gcc jump tables are anonymous data.
816 */
817 if (find_symbol_containing(file->rodata, text_rela->addend))
818 continue;
819
820 return find_rela_by_dest(file->rodata, text_rela->addend);
821 }
822
823 return NULL;
824}
825
826static int add_func_switch_tables(struct objtool_file *file,
827 struct symbol *func)
828{
829 struct instruction *insn, *prev_jump = NULL;
830 struct rela *rela, *prev_rela = NULL;
831 int ret;
832
833 func_for_each_insn(file, func, insn) {
834 if (insn->type != INSN_JUMP_DYNAMIC)
835 continue;
836
837 rela = find_switch_table(file, func, insn);
838 if (!rela)
839 continue;
840
841 /*
842 * We found a switch table, but we don't know yet how big it
843 * is. Don't add it until we reach the end of the function or
844 * the beginning of another switch table in the same function.
845 */
846 if (prev_jump) {
847 ret = add_switch_table(file, func, prev_jump, prev_rela,
848 rela);
849 if (ret)
850 return ret;
851 }
852
853 prev_jump = insn;
854 prev_rela = rela;
855 }
856
857 if (prev_jump) {
858 ret = add_switch_table(file, func, prev_jump, prev_rela, NULL);
859 if (ret)
860 return ret;
861 }
862
863 return 0;
864}
865
866/*
867 * For some switch statements, gcc generates a jump table in the .rodata
868 * section which contains a list of addresses within the function to jump to.
869 * This finds these jump tables and adds them to the insn->alts lists.
870 */
871static int add_switch_table_alts(struct objtool_file *file)
872{
873 struct section *sec;
874 struct symbol *func;
875 int ret;
876
877 if (!file->rodata || !file->rodata->rela)
878 return 0;
879
880 list_for_each_entry(sec, &file->elf->sections, list) {
881 list_for_each_entry(func, &sec->symbol_list, list) {
882 if (func->type != STT_FUNC)
883 continue;
884
885 ret = add_func_switch_tables(file, func);
886 if (ret)
887 return ret;
888 }
889 }
890
891 return 0;
892}
893
894static int decode_sections(struct objtool_file *file)
895{
896 int ret;
897
898 ret = decode_instructions(file);
899 if (ret)
900 return ret;
901
902 ret = add_dead_ends(file);
903 if (ret)
904 return ret;
905
906 add_ignores(file);
907
908 ret = add_jump_destinations(file);
909 if (ret)
910 return ret;
911
912 ret = add_call_destinations(file);
913 if (ret)
914 return ret;
915
916 ret = add_special_section_alts(file);
917 if (ret)
918 return ret;
919
920 ret = add_switch_table_alts(file);
921 if (ret)
922 return ret;
923
924 return 0;
925}
926
927static bool is_fentry_call(struct instruction *insn)
928{
929 if (insn->type == INSN_CALL &&
930 insn->call_dest->type == STT_NOTYPE &&
931 !strcmp(insn->call_dest->name, "__fentry__"))
932 return true;
933
934 return false;
935}
936
937static bool has_modified_stack_frame(struct instruction *insn)
938{
939 return (insn->state & STATE_FP_SAVED) ||
940 (insn->state & STATE_FP_SETUP);
941}
942
943static bool has_valid_stack_frame(struct instruction *insn)
944{
945 return (insn->state & STATE_FP_SAVED) &&
946 (insn->state & STATE_FP_SETUP);
947}
948
949static unsigned int frame_state(unsigned long state)
950{
951 return (state & (STATE_FP_SAVED | STATE_FP_SETUP));
952}
953
954/*
955 * Follow the branch starting at the given instruction, and recursively follow
956 * any other branches (jumps). Meanwhile, track the frame pointer state at
957 * each instruction and validate all the rules described in
958 * tools/objtool/Documentation/stack-validation.txt.
959 */
960static int validate_branch(struct objtool_file *file,
961 struct instruction *first, unsigned char first_state)
962{
963 struct alternative *alt;
964 struct instruction *insn;
965 struct section *sec;
966 struct symbol *func = NULL;
967 unsigned char state;
968 int ret;
969
970 insn = first;
971 sec = insn->sec;
972 state = first_state;
973
974 if (insn->alt_group && list_empty(&insn->alts)) {
975 WARN_FUNC("don't know how to handle branch to middle of alternative instruction group",
976 sec, insn->offset);
977 return 1;
978 }
979
980 while (1) {
981 if (file->c_file && insn->func) {
982 if (func && func != insn->func) {
983 WARN("%s() falls through to next function %s()",
984 func->name, insn->func->name);
985 return 1;
986 }
987
988 func = insn->func;
989 }
990
991 if (insn->visited) {
992 if (frame_state(insn->state) != frame_state(state)) {
993 WARN_FUNC("frame pointer state mismatch",
994 sec, insn->offset);
995 return 1;
996 }
997
998 return 0;
999 }
1000
1001 insn->visited = true;
1002 insn->state = state;
1003
1004 list_for_each_entry(alt, &insn->alts, list) {
1005 ret = validate_branch(file, alt->insn, state);
1006 if (ret)
1007 return 1;
1008 }
1009
1010 switch (insn->type) {
1011
1012 case INSN_FP_SAVE:
1013 if (!nofp) {
1014 if (state & STATE_FP_SAVED) {
1015 WARN_FUNC("duplicate frame pointer save",
1016 sec, insn->offset);
1017 return 1;
1018 }
1019 state |= STATE_FP_SAVED;
1020 }
1021 break;
1022
1023 case INSN_FP_SETUP:
1024 if (!nofp) {
1025 if (state & STATE_FP_SETUP) {
1026 WARN_FUNC("duplicate frame pointer setup",
1027 sec, insn->offset);
1028 return 1;
1029 }
1030 state |= STATE_FP_SETUP;
1031 }
1032 break;
1033
1034 case INSN_FP_RESTORE:
1035 if (!nofp) {
1036 if (has_valid_stack_frame(insn))
1037 state &= ~STATE_FP_SETUP;
1038
1039 state &= ~STATE_FP_SAVED;
1040 }
1041 break;
1042
1043 case INSN_RETURN:
1044 if (!nofp && has_modified_stack_frame(insn)) {
1045 WARN_FUNC("return without frame pointer restore",
1046 sec, insn->offset);
1047 return 1;
1048 }
1049 return 0;
1050
1051 case INSN_CALL:
1052 if (is_fentry_call(insn)) {
1053 state |= STATE_FENTRY;
1054 break;
1055 }
1056
1057 ret = dead_end_function(file, insn->call_dest);
1058 if (ret == 1)
1059 return 0;
1060 if (ret == -1)
1061 return 1;
1062
1063 /* fallthrough */
1064 case INSN_CALL_DYNAMIC:
1065 if (!nofp && !has_valid_stack_frame(insn)) {
1066 WARN_FUNC("call without frame pointer save/setup",
1067 sec, insn->offset);
1068 return 1;
1069 }
1070 break;
1071
1072 case INSN_JUMP_CONDITIONAL:
1073 case INSN_JUMP_UNCONDITIONAL:
1074 if (insn->jump_dest) {
1075 ret = validate_branch(file, insn->jump_dest,
1076 state);
1077 if (ret)
1078 return 1;
1079 } else if (has_modified_stack_frame(insn)) {
1080 WARN_FUNC("sibling call from callable instruction with changed frame pointer",
1081 sec, insn->offset);
1082 return 1;
1083 } /* else it's a sibling call */
1084
1085 if (insn->type == INSN_JUMP_UNCONDITIONAL)
1086 return 0;
1087
1088 break;
1089
1090 case INSN_JUMP_DYNAMIC:
1091 if (list_empty(&insn->alts) &&
1092 has_modified_stack_frame(insn)) {
1093 WARN_FUNC("sibling call from callable instruction with changed frame pointer",
1094 sec, insn->offset);
1095 return 1;
1096 }
1097
1098 return 0;
1099
1100 default:
1101 break;
1102 }
1103
1104 if (insn->dead_end)
1105 return 0;
1106
1107 insn = next_insn_same_sec(file, insn);
1108 if (!insn) {
1109 WARN("%s: unexpected end of section", sec->name);
1110 return 1;
1111 }
1112 }
1113
1114 return 0;
1115}
1116
1117static bool is_kasan_insn(struct instruction *insn)
1118{
1119 return (insn->type == INSN_CALL &&
1120 !strcmp(insn->call_dest->name, "__asan_handle_no_return"));
1121}
1122
1123static bool is_ubsan_insn(struct instruction *insn)
1124{
1125 return (insn->type == INSN_CALL &&
1126 !strcmp(insn->call_dest->name,
1127 "__ubsan_handle_builtin_unreachable"));
1128}
1129
1130static bool ignore_unreachable_insn(struct symbol *func,
1131 struct instruction *insn)
1132{
1133 int i;
1134
1135 if (insn->type == INSN_NOP)
1136 return true;
1137
1138 /*
1139 * Check if this (or a subsequent) instruction is related to
1140 * CONFIG_UBSAN or CONFIG_KASAN.
1141 *
1142 * End the search at 5 instructions to avoid going into the weeds.
1143 */
1144 for (i = 0; i < 5; i++) {
1145
1146 if (is_kasan_insn(insn) || is_ubsan_insn(insn))
1147 return true;
1148
1149 if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest) {
1150 insn = insn->jump_dest;
1151 continue;
1152 }
1153
1154 if (insn->offset + insn->len >= func->offset + func->len)
1155 break;
1156 insn = list_next_entry(insn, list);
1157 }
1158
1159 return false;
1160}
1161
1162static int validate_functions(struct objtool_file *file)
1163{
1164 struct section *sec;
1165 struct symbol *func;
1166 struct instruction *insn;
1167 int ret, warnings = 0;
1168
1169 list_for_each_entry(sec, &file->elf->sections, list) {
1170 list_for_each_entry(func, &sec->symbol_list, list) {
1171 if (func->type != STT_FUNC)
1172 continue;
1173
1174 insn = find_insn(file, sec, func->offset);
1175 if (!insn)
1176 continue;
1177
1178 ret = validate_branch(file, insn, 0);
1179 warnings += ret;
1180 }
1181 }
1182
1183 list_for_each_entry(sec, &file->elf->sections, list) {
1184 list_for_each_entry(func, &sec->symbol_list, list) {
1185 if (func->type != STT_FUNC)
1186 continue;
1187
1188 func_for_each_insn(file, func, insn) {
1189 if (insn->visited)
1190 continue;
1191
1192 insn->visited = true;
1193
1194 if (file->ignore_unreachables || warnings ||
1195 ignore_unreachable_insn(func, insn))
1196 continue;
1197
1198 /*
1199 * gcov produces a lot of unreachable
1200 * instructions. If we get an unreachable
1201 * warning and the file has gcov enabled, just
1202 * ignore it, and all other such warnings for
1203 * the file.
1204 */
1205 if (!file->ignore_unreachables &&
1206 gcov_enabled(file)) {
1207 file->ignore_unreachables = true;
1208 continue;
1209 }
1210
1211 WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset);
1212 warnings++;
1213 }
1214 }
1215 }
1216
1217 return warnings;
1218}
1219
1220static int validate_uncallable_instructions(struct objtool_file *file)
1221{
1222 struct instruction *insn;
1223 int warnings = 0;
1224
1225 for_each_insn(file, insn) {
1226 if (!insn->visited && insn->type == INSN_RETURN) {
1227 WARN_FUNC("return instruction outside of a callable function",
1228 insn->sec, insn->offset);
1229 warnings++;
1230 }
1231 }
1232
1233 return warnings;
1234}
1235
1236static void cleanup(struct objtool_file *file)
1237{
1238 struct instruction *insn, *tmpinsn;
1239 struct alternative *alt, *tmpalt;
1240
1241 list_for_each_entry_safe(insn, tmpinsn, &file->insn_list, list) {
1242 list_for_each_entry_safe(alt, tmpalt, &insn->alts, list) {
1243 list_del(&alt->list);
1244 free(alt);
1245 }
1246 list_del(&insn->list);
1247 hash_del(&insn->hash);
1248 free(insn);
1249 }
1250 elf_close(file->elf);
1251}
1252
1253const char * const check_usage[] = {
1254 "objtool check [<options>] file.o", 35 "objtool check [<options>] file.o",
1255 NULL, 36 NULL,
1256}; 37};
1257 38
39const struct option check_options[] = {
40 OPT_BOOLEAN('f', "no-fp", &nofp, "Skip frame pointer validation"),
41 OPT_END(),
42};
43
1258int cmd_check(int argc, const char **argv) 44int cmd_check(int argc, const char **argv)
1259{ 45{
1260 struct objtool_file file; 46 const char *objname;
1261 int ret, warnings = 0;
1262
1263 const struct option options[] = {
1264 OPT_BOOLEAN('f', "no-fp", &nofp, "Skip frame pointer validation"),
1265 OPT_END(),
1266 };
1267 47
1268 argc = parse_options(argc, argv, options, check_usage, 0); 48 argc = parse_options(argc, argv, check_options, check_usage, 0);
1269 49
1270 if (argc != 1) 50 if (argc != 1)
1271 usage_with_options(check_usage, options); 51 usage_with_options(check_usage, check_options);
1272 52
1273 objname = argv[0]; 53 objname = argv[0];
1274 54
1275 file.elf = elf_open(objname); 55 return check(objname, nofp);
1276 if (!file.elf) {
1277 fprintf(stderr, "error reading elf file %s\n", objname);
1278 return 1;
1279 }
1280
1281 INIT_LIST_HEAD(&file.insn_list);
1282 hash_init(file.insn_hash);
1283 file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard");
1284 file.rodata = find_section_by_name(file.elf, ".rodata");
1285 file.ignore_unreachables = false;
1286 file.c_file = find_section_by_name(file.elf, ".comment");
1287
1288 ret = decode_sections(&file);
1289 if (ret < 0)
1290 goto out;
1291 warnings += ret;
1292
1293 ret = validate_functions(&file);
1294 if (ret < 0)
1295 goto out;
1296 warnings += ret;
1297
1298 ret = validate_uncallable_instructions(&file);
1299 if (ret < 0)
1300 goto out;
1301 warnings += ret;
1302
1303out:
1304 cleanup(&file);
1305
1306 /* ignore warnings for now until we get all the code cleaned up */
1307 if (ret || warnings)
1308 return 0;
1309 return 0;
1310} 56}
diff --git a/tools/objtool/cfi.h b/tools/objtool/cfi.h
new file mode 100644
index 000000000000..443ab2c69992
--- /dev/null
+++ b/tools/objtool/cfi.h
@@ -0,0 +1,55 @@
1/*
2 * Copyright (C) 2015-2017 Josh Poimboeuf <jpoimboe@redhat.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef _OBJTOOL_CFI_H
19#define _OBJTOOL_CFI_H
20
21#define CFI_UNDEFINED -1
22#define CFI_CFA -2
23#define CFI_SP_INDIRECT -3
24#define CFI_BP_INDIRECT -4
25
26#define CFI_AX 0
27#define CFI_DX 1
28#define CFI_CX 2
29#define CFI_BX 3
30#define CFI_SI 4
31#define CFI_DI 5
32#define CFI_BP 6
33#define CFI_SP 7
34#define CFI_R8 8
35#define CFI_R9 9
36#define CFI_R10 10
37#define CFI_R11 11
38#define CFI_R12 12
39#define CFI_R13 13
40#define CFI_R14 14
41#define CFI_R15 15
42#define CFI_RA 16
43#define CFI_NUM_REGS 17
44
45struct cfi_reg {
46 int base;
47 int offset;
48};
49
50struct cfi_state {
51 struct cfi_reg cfa;
52 struct cfi_reg regs[CFI_NUM_REGS];
53};
54
55#endif /* _OBJTOOL_CFI_H */
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
new file mode 100644
index 000000000000..fea222192c57
--- /dev/null
+++ b/tools/objtool/check.c
@@ -0,0 +1,1655 @@
1/*
2 * Copyright (C) 2015-2017 Josh Poimboeuf <jpoimboe@redhat.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <string.h>
19#include <stdlib.h>
20
21#include "check.h"
22#include "elf.h"
23#include "special.h"
24#include "arch.h"
25#include "warn.h"
26
27#include <linux/hashtable.h>
28#include <linux/kernel.h>
29
30struct alternative {
31 struct list_head list;
32 struct instruction *insn;
33};
34
35const char *objname;
36static bool nofp;
37struct cfi_state initial_func_cfi;
38
39static struct instruction *find_insn(struct objtool_file *file,
40 struct section *sec, unsigned long offset)
41{
42 struct instruction *insn;
43
44 hash_for_each_possible(file->insn_hash, insn, hash, offset)
45 if (insn->sec == sec && insn->offset == offset)
46 return insn;
47
48 return NULL;
49}
50
51static struct instruction *next_insn_same_sec(struct objtool_file *file,
52 struct instruction *insn)
53{
54 struct instruction *next = list_next_entry(insn, list);
55
56 if (!next || &next->list == &file->insn_list || next->sec != insn->sec)
57 return NULL;
58
59 return next;
60}
61
62static bool gcov_enabled(struct objtool_file *file)
63{
64 struct section *sec;
65 struct symbol *sym;
66
67 for_each_sec(file, sec)
68 list_for_each_entry(sym, &sec->symbol_list, list)
69 if (!strncmp(sym->name, "__gcov_.", 8))
70 return true;
71
72 return false;
73}
74
75#define func_for_each_insn(file, func, insn) \
76 for (insn = find_insn(file, func->sec, func->offset); \
77 insn && &insn->list != &file->insn_list && \
78 insn->sec == func->sec && \
79 insn->offset < func->offset + func->len; \
80 insn = list_next_entry(insn, list))
81
82#define func_for_each_insn_continue_reverse(file, func, insn) \
83 for (insn = list_prev_entry(insn, list); \
84 &insn->list != &file->insn_list && \
85 insn->sec == func->sec && insn->offset >= func->offset; \
86 insn = list_prev_entry(insn, list))
87
88#define sec_for_each_insn_from(file, insn) \
89 for (; insn; insn = next_insn_same_sec(file, insn))
90
91#define sec_for_each_insn_continue(file, insn) \
92 for (insn = next_insn_same_sec(file, insn); insn; \
93 insn = next_insn_same_sec(file, insn))
94
95/*
96 * Check if the function has been manually whitelisted with the
97 * STACK_FRAME_NON_STANDARD macro, or if it should be automatically whitelisted
98 * due to its use of a context switching instruction.
99 */
100static bool ignore_func(struct objtool_file *file, struct symbol *func)
101{
102 struct rela *rela;
103 struct instruction *insn;
104
105 /* check for STACK_FRAME_NON_STANDARD */
106 if (file->whitelist && file->whitelist->rela)
107 list_for_each_entry(rela, &file->whitelist->rela->rela_list, list) {
108 if (rela->sym->type == STT_SECTION &&
109 rela->sym->sec == func->sec &&
110 rela->addend == func->offset)
111 return true;
112 if (rela->sym->type == STT_FUNC && rela->sym == func)
113 return true;
114 }
115
116 /* check if it has a context switching instruction */
117 func_for_each_insn(file, func, insn)
118 if (insn->type == INSN_CONTEXT_SWITCH)
119 return true;
120
121 return false;
122}
123
124/*
125 * This checks to see if the given function is a "noreturn" function.
126 *
127 * For global functions which are outside the scope of this object file, we
128 * have to keep a manual list of them.
129 *
130 * For local functions, we have to detect them manually by simply looking for
131 * the lack of a return instruction.
132 *
133 * Returns:
134 * -1: error
135 * 0: no dead end
136 * 1: dead end
137 */
138static int __dead_end_function(struct objtool_file *file, struct symbol *func,
139 int recursion)
140{
141 int i;
142 struct instruction *insn;
143 bool empty = true;
144
145 /*
146 * Unfortunately these have to be hard coded because the noreturn
147 * attribute isn't provided in ELF data.
148 */
149 static const char * const global_noreturns[] = {
150 "__stack_chk_fail",
151 "panic",
152 "do_exit",
153 "do_task_dead",
154 "__module_put_and_exit",
155 "complete_and_exit",
156 "kvm_spurious_fault",
157 "__reiserfs_panic",
158 "lbug_with_loc",
159 "fortify_panic",
160 };
161
162 if (func->bind == STB_WEAK)
163 return 0;
164
165 if (func->bind == STB_GLOBAL)
166 for (i = 0; i < ARRAY_SIZE(global_noreturns); i++)
167 if (!strcmp(func->name, global_noreturns[i]))
168 return 1;
169
170 if (!func->sec)
171 return 0;
172
173 func_for_each_insn(file, func, insn) {
174 empty = false;
175
176 if (insn->type == INSN_RETURN)
177 return 0;
178 }
179
180 if (empty)
181 return 0;
182
183 /*
184 * A function can have a sibling call instead of a return. In that
185 * case, the function's dead-end status depends on whether the target
186 * of the sibling call returns.
187 */
188 func_for_each_insn(file, func, insn) {
189 if (insn->sec != func->sec ||
190 insn->offset >= func->offset + func->len)
191 break;
192
193 if (insn->type == INSN_JUMP_UNCONDITIONAL) {
194 struct instruction *dest = insn->jump_dest;
195 struct symbol *dest_func;
196
197 if (!dest)
198 /* sibling call to another file */
199 return 0;
200
201 if (dest->sec != func->sec ||
202 dest->offset < func->offset ||
203 dest->offset >= func->offset + func->len) {
204 /* local sibling call */
205 dest_func = find_symbol_by_offset(dest->sec,
206 dest->offset);
207 if (!dest_func)
208 continue;
209
210 if (recursion == 5) {
211 WARN_FUNC("infinite recursion (objtool bug!)",
212 dest->sec, dest->offset);
213 return -1;
214 }
215
216 return __dead_end_function(file, dest_func,
217 recursion + 1);
218 }
219 }
220
221 if (insn->type == INSN_JUMP_DYNAMIC && list_empty(&insn->alts))
222 /* sibling call */
223 return 0;
224 }
225
226 return 1;
227}
228
229static int dead_end_function(struct objtool_file *file, struct symbol *func)
230{
231 return __dead_end_function(file, func, 0);
232}
233
234static void clear_insn_state(struct insn_state *state)
235{
236 int i;
237
238 memset(state, 0, sizeof(*state));
239 state->cfa.base = CFI_UNDEFINED;
240 for (i = 0; i < CFI_NUM_REGS; i++)
241 state->regs[i].base = CFI_UNDEFINED;
242 state->drap_reg = CFI_UNDEFINED;
243}
244
245/*
246 * Call the arch-specific instruction decoder for all the instructions and add
247 * them to the global instruction list.
248 */
249static int decode_instructions(struct objtool_file *file)
250{
251 struct section *sec;
252 struct symbol *func;
253 unsigned long offset;
254 struct instruction *insn;
255 int ret;
256
257 for_each_sec(file, sec) {
258
259 if (!(sec->sh.sh_flags & SHF_EXECINSTR))
260 continue;
261
262 for (offset = 0; offset < sec->len; offset += insn->len) {
263 insn = malloc(sizeof(*insn));
264 if (!insn) {
265 WARN("malloc failed");
266 return -1;
267 }
268 memset(insn, 0, sizeof(*insn));
269 INIT_LIST_HEAD(&insn->alts);
270 clear_insn_state(&insn->state);
271
272 insn->sec = sec;
273 insn->offset = offset;
274
275 ret = arch_decode_instruction(file->elf, sec, offset,
276 sec->len - offset,
277 &insn->len, &insn->type,
278 &insn->immediate,
279 &insn->stack_op);
280 if (ret)
281 return ret;
282
283 if (!insn->type || insn->type > INSN_LAST) {
284 WARN_FUNC("invalid instruction type %d",
285 insn->sec, insn->offset, insn->type);
286 return -1;
287 }
288
289 hash_add(file->insn_hash, &insn->hash, insn->offset);
290 list_add_tail(&insn->list, &file->insn_list);
291 }
292
293 list_for_each_entry(func, &sec->symbol_list, list) {
294 if (func->type != STT_FUNC)
295 continue;
296
297 if (!find_insn(file, sec, func->offset)) {
298 WARN("%s(): can't find starting instruction",
299 func->name);
300 return -1;
301 }
302
303 func_for_each_insn(file, func, insn)
304 if (!insn->func)
305 insn->func = func;
306 }
307 }
308
309 return 0;
310}
311
312/*
313 * Find all uses of the unreachable() macro, which are code path dead ends.
314 */
315static int add_dead_ends(struct objtool_file *file)
316{
317 struct section *sec;
318 struct rela *rela;
319 struct instruction *insn;
320 bool found;
321
322 sec = find_section_by_name(file->elf, ".rela.discard.unreachable");
323 if (!sec)
324 return 0;
325
326 list_for_each_entry(rela, &sec->rela_list, list) {
327 if (rela->sym->type != STT_SECTION) {
328 WARN("unexpected relocation symbol type in %s", sec->name);
329 return -1;
330 }
331 insn = find_insn(file, rela->sym->sec, rela->addend);
332 if (insn)
333 insn = list_prev_entry(insn, list);
334 else if (rela->addend == rela->sym->sec->len) {
335 found = false;
336 list_for_each_entry_reverse(insn, &file->insn_list, list) {
337 if (insn->sec == rela->sym->sec) {
338 found = true;
339 break;
340 }
341 }
342
343 if (!found) {
344 WARN("can't find unreachable insn at %s+0x%x",
345 rela->sym->sec->name, rela->addend);
346 return -1;
347 }
348 } else {
349 WARN("can't find unreachable insn at %s+0x%x",
350 rela->sym->sec->name, rela->addend);
351 return -1;
352 }
353
354 insn->dead_end = true;
355 }
356
357 return 0;
358}
359
360/*
361 * Warnings shouldn't be reported for ignored functions.
362 */
363static void add_ignores(struct objtool_file *file)
364{
365 struct instruction *insn;
366 struct section *sec;
367 struct symbol *func;
368
369 for_each_sec(file, sec) {
370 list_for_each_entry(func, &sec->symbol_list, list) {
371 if (func->type != STT_FUNC)
372 continue;
373
374 if (!ignore_func(file, func))
375 continue;
376
377 func_for_each_insn(file, func, insn)
378 insn->ignore = true;
379 }
380 }
381}
382
383/*
384 * Find the destination instructions for all jumps.
385 */
386static int add_jump_destinations(struct objtool_file *file)
387{
388 struct instruction *insn;
389 struct rela *rela;
390 struct section *dest_sec;
391 unsigned long dest_off;
392
393 for_each_insn(file, insn) {
394 if (insn->type != INSN_JUMP_CONDITIONAL &&
395 insn->type != INSN_JUMP_UNCONDITIONAL)
396 continue;
397
398 if (insn->ignore)
399 continue;
400
401 rela = find_rela_by_dest_range(insn->sec, insn->offset,
402 insn->len);
403 if (!rela) {
404 dest_sec = insn->sec;
405 dest_off = insn->offset + insn->len + insn->immediate;
406 } else if (rela->sym->type == STT_SECTION) {
407 dest_sec = rela->sym->sec;
408 dest_off = rela->addend + 4;
409 } else if (rela->sym->sec->idx) {
410 dest_sec = rela->sym->sec;
411 dest_off = rela->sym->sym.st_value + rela->addend + 4;
412 } else {
413 /* sibling call */
414 insn->jump_dest = 0;
415 continue;
416 }
417
418 insn->jump_dest = find_insn(file, dest_sec, dest_off);
419 if (!insn->jump_dest) {
420
421 /*
422 * This is a special case where an alt instruction
423 * jumps past the end of the section. These are
424 * handled later in handle_group_alt().
425 */
426 if (!strcmp(insn->sec->name, ".altinstr_replacement"))
427 continue;
428
429 WARN_FUNC("can't find jump dest instruction at %s+0x%lx",
430 insn->sec, insn->offset, dest_sec->name,
431 dest_off);
432 return -1;
433 }
434 }
435
436 return 0;
437}
438
439/*
440 * Find the destination instructions for all calls.
441 */
442static int add_call_destinations(struct objtool_file *file)
443{
444 struct instruction *insn;
445 unsigned long dest_off;
446 struct rela *rela;
447
448 for_each_insn(file, insn) {
449 if (insn->type != INSN_CALL)
450 continue;
451
452 rela = find_rela_by_dest_range(insn->sec, insn->offset,
453 insn->len);
454 if (!rela) {
455 dest_off = insn->offset + insn->len + insn->immediate;
456 insn->call_dest = find_symbol_by_offset(insn->sec,
457 dest_off);
458 if (!insn->call_dest) {
459 WARN_FUNC("can't find call dest symbol at offset 0x%lx",
460 insn->sec, insn->offset, dest_off);
461 return -1;
462 }
463 } else if (rela->sym->type == STT_SECTION) {
464 insn->call_dest = find_symbol_by_offset(rela->sym->sec,
465 rela->addend+4);
466 if (!insn->call_dest ||
467 insn->call_dest->type != STT_FUNC) {
468 WARN_FUNC("can't find call dest symbol at %s+0x%x",
469 insn->sec, insn->offset,
470 rela->sym->sec->name,
471 rela->addend + 4);
472 return -1;
473 }
474 } else
475 insn->call_dest = rela->sym;
476 }
477
478 return 0;
479}
480
481/*
482 * The .alternatives section requires some extra special care, over and above
483 * what other special sections require:
484 *
485 * 1. Because alternatives are patched in-place, we need to insert a fake jump
486 * instruction at the end so that validate_branch() skips all the original
487 * replaced instructions when validating the new instruction path.
488 *
489 * 2. An added wrinkle is that the new instruction length might be zero. In
490 * that case the old instructions are replaced with noops. We simulate that
491 * by creating a fake jump as the only new instruction.
492 *
493 * 3. In some cases, the alternative section includes an instruction which
494 * conditionally jumps to the _end_ of the entry. We have to modify these
495 * jumps' destinations to point back to .text rather than the end of the
496 * entry in .altinstr_replacement.
497 *
498 * 4. It has been requested that we don't validate the !POPCNT feature path
499 * which is a "very very small percentage of machines".
500 */
501static int handle_group_alt(struct objtool_file *file,
502 struct special_alt *special_alt,
503 struct instruction *orig_insn,
504 struct instruction **new_insn)
505{
506 struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump;
507 unsigned long dest_off;
508
509 last_orig_insn = NULL;
510 insn = orig_insn;
511 sec_for_each_insn_from(file, insn) {
512 if (insn->offset >= special_alt->orig_off + special_alt->orig_len)
513 break;
514
515 if (special_alt->skip_orig)
516 insn->type = INSN_NOP;
517
518 insn->alt_group = true;
519 last_orig_insn = insn;
520 }
521
522 if (!next_insn_same_sec(file, last_orig_insn)) {
523 WARN("%s: don't know how to handle alternatives at end of section",
524 special_alt->orig_sec->name);
525 return -1;
526 }
527
528 fake_jump = malloc(sizeof(*fake_jump));
529 if (!fake_jump) {
530 WARN("malloc failed");
531 return -1;
532 }
533 memset(fake_jump, 0, sizeof(*fake_jump));
534 INIT_LIST_HEAD(&fake_jump->alts);
535 clear_insn_state(&fake_jump->state);
536
537 fake_jump->sec = special_alt->new_sec;
538 fake_jump->offset = -1;
539 fake_jump->type = INSN_JUMP_UNCONDITIONAL;
540 fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
541 fake_jump->ignore = true;
542
543 if (!special_alt->new_len) {
544 *new_insn = fake_jump;
545 return 0;
546 }
547
548 last_new_insn = NULL;
549 insn = *new_insn;
550 sec_for_each_insn_from(file, insn) {
551 if (insn->offset >= special_alt->new_off + special_alt->new_len)
552 break;
553
554 last_new_insn = insn;
555
556 if (insn->type != INSN_JUMP_CONDITIONAL &&
557 insn->type != INSN_JUMP_UNCONDITIONAL)
558 continue;
559
560 if (!insn->immediate)
561 continue;
562
563 dest_off = insn->offset + insn->len + insn->immediate;
564 if (dest_off == special_alt->new_off + special_alt->new_len)
565 insn->jump_dest = fake_jump;
566
567 if (!insn->jump_dest) {
568 WARN_FUNC("can't find alternative jump destination",
569 insn->sec, insn->offset);
570 return -1;
571 }
572 }
573
574 if (!last_new_insn) {
575 WARN_FUNC("can't find last new alternative instruction",
576 special_alt->new_sec, special_alt->new_off);
577 return -1;
578 }
579
580 list_add(&fake_jump->list, &last_new_insn->list);
581
582 return 0;
583}
584
585/*
586 * A jump table entry can either convert a nop to a jump or a jump to a nop.
587 * If the original instruction is a jump, make the alt entry an effective nop
588 * by just skipping the original instruction.
589 */
590static int handle_jump_alt(struct objtool_file *file,
591 struct special_alt *special_alt,
592 struct instruction *orig_insn,
593 struct instruction **new_insn)
594{
595 if (orig_insn->type == INSN_NOP)
596 return 0;
597
598 if (orig_insn->type != INSN_JUMP_UNCONDITIONAL) {
599 WARN_FUNC("unsupported instruction at jump label",
600 orig_insn->sec, orig_insn->offset);
601 return -1;
602 }
603
604 *new_insn = list_next_entry(orig_insn, list);
605 return 0;
606}
607
608/*
609 * Read all the special sections which have alternate instructions which can be
610 * patched in or redirected to at runtime. Each instruction having alternate
611 * instruction(s) has them added to its insn->alts list, which will be
612 * traversed in validate_branch().
613 */
614static int add_special_section_alts(struct objtool_file *file)
615{
616 struct list_head special_alts;
617 struct instruction *orig_insn, *new_insn;
618 struct special_alt *special_alt, *tmp;
619 struct alternative *alt;
620 int ret;
621
622 ret = special_get_alts(file->elf, &special_alts);
623 if (ret)
624 return ret;
625
626 list_for_each_entry_safe(special_alt, tmp, &special_alts, list) {
627 alt = malloc(sizeof(*alt));
628 if (!alt) {
629 WARN("malloc failed");
630 ret = -1;
631 goto out;
632 }
633
634 orig_insn = find_insn(file, special_alt->orig_sec,
635 special_alt->orig_off);
636 if (!orig_insn) {
637 WARN_FUNC("special: can't find orig instruction",
638 special_alt->orig_sec, special_alt->orig_off);
639 ret = -1;
640 goto out;
641 }
642
643 new_insn = NULL;
644 if (!special_alt->group || special_alt->new_len) {
645 new_insn = find_insn(file, special_alt->new_sec,
646 special_alt->new_off);
647 if (!new_insn) {
648 WARN_FUNC("special: can't find new instruction",
649 special_alt->new_sec,
650 special_alt->new_off);
651 ret = -1;
652 goto out;
653 }
654 }
655
656 if (special_alt->group) {
657 ret = handle_group_alt(file, special_alt, orig_insn,
658 &new_insn);
659 if (ret)
660 goto out;
661 } else if (special_alt->jump_or_nop) {
662 ret = handle_jump_alt(file, special_alt, orig_insn,
663 &new_insn);
664 if (ret)
665 goto out;
666 }
667
668 alt->insn = new_insn;
669 list_add_tail(&alt->list, &orig_insn->alts);
670
671 list_del(&special_alt->list);
672 free(special_alt);
673 }
674
675out:
676 return ret;
677}
678
679static int add_switch_table(struct objtool_file *file, struct symbol *func,
680 struct instruction *insn, struct rela *table,
681 struct rela *next_table)
682{
683 struct rela *rela = table;
684 struct instruction *alt_insn;
685 struct alternative *alt;
686
687 list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) {
688 if (rela == next_table)
689 break;
690
691 if (rela->sym->sec != insn->sec ||
692 rela->addend <= func->offset ||
693 rela->addend >= func->offset + func->len)
694 break;
695
696 alt_insn = find_insn(file, insn->sec, rela->addend);
697 if (!alt_insn) {
698 WARN("%s: can't find instruction at %s+0x%x",
699 file->rodata->rela->name, insn->sec->name,
700 rela->addend);
701 return -1;
702 }
703
704 alt = malloc(sizeof(*alt));
705 if (!alt) {
706 WARN("malloc failed");
707 return -1;
708 }
709
710 alt->insn = alt_insn;
711 list_add_tail(&alt->list, &insn->alts);
712 }
713
714 return 0;
715}
716
717/*
718 * find_switch_table() - Given a dynamic jump, find the switch jump table in
719 * .rodata associated with it.
720 *
721 * There are 3 basic patterns:
722 *
723 * 1. jmpq *[rodata addr](,%reg,8)
724 *
725 * This is the most common case by far. It jumps to an address in a simple
726 * jump table which is stored in .rodata.
727 *
728 * 2. jmpq *[rodata addr](%rip)
729 *
730 * This is caused by a rare GCC quirk, currently only seen in three driver
731 * functions in the kernel, only with certain obscure non-distro configs.
732 *
733 * As part of an optimization, GCC makes a copy of an existing switch jump
734 * table, modifies it, and then hard-codes the jump (albeit with an indirect
735 * jump) to use a single entry in the table. The rest of the jump table and
736 * some of its jump targets remain as dead code.
737 *
738 * In such a case we can just crudely ignore all unreachable instruction
739 * warnings for the entire object file. Ideally we would just ignore them
740 * for the function, but that would require redesigning the code quite a
741 * bit. And honestly that's just not worth doing: unreachable instruction
742 * warnings are of questionable value anyway, and this is such a rare issue.
743 *
744 * 3. mov [rodata addr],%reg1
745 * ... some instructions ...
746 * jmpq *(%reg1,%reg2,8)
747 *
748 * This is a fairly uncommon pattern which is new for GCC 6. As of this
749 * writing, there are 11 occurrences of it in the allmodconfig kernel.
750 *
751 * TODO: Once we have DWARF CFI and smarter instruction decoding logic,
752 * ensure the same register is used in the mov and jump instructions.
753 */
754static struct rela *find_switch_table(struct objtool_file *file,
755 struct symbol *func,
756 struct instruction *insn)
757{
758 struct rela *text_rela, *rodata_rela;
759 struct instruction *orig_insn = insn;
760
761 text_rela = find_rela_by_dest_range(insn->sec, insn->offset, insn->len);
762 if (text_rela && text_rela->sym == file->rodata->sym) {
763 /* case 1 */
764 rodata_rela = find_rela_by_dest(file->rodata,
765 text_rela->addend);
766 if (rodata_rela)
767 return rodata_rela;
768
769 /* case 2 */
770 rodata_rela = find_rela_by_dest(file->rodata,
771 text_rela->addend + 4);
772 if (!rodata_rela)
773 return NULL;
774 file->ignore_unreachables = true;
775 return rodata_rela;
776 }
777
778 /* case 3 */
779 func_for_each_insn_continue_reverse(file, func, insn) {
780 if (insn->type == INSN_JUMP_DYNAMIC)
781 break;
782
783 /* allow small jumps within the range */
784 if (insn->type == INSN_JUMP_UNCONDITIONAL &&
785 insn->jump_dest &&
786 (insn->jump_dest->offset <= insn->offset ||
787 insn->jump_dest->offset > orig_insn->offset))
788 break;
789
790 /* look for a relocation which references .rodata */
791 text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
792 insn->len);
793 if (!text_rela || text_rela->sym != file->rodata->sym)
794 continue;
795
796 /*
797 * Make sure the .rodata address isn't associated with a
798 * symbol. gcc jump tables are anonymous data.
799 */
800 if (find_symbol_containing(file->rodata, text_rela->addend))
801 continue;
802
803 return find_rela_by_dest(file->rodata, text_rela->addend);
804 }
805
806 return NULL;
807}
808
809static int add_func_switch_tables(struct objtool_file *file,
810 struct symbol *func)
811{
812 struct instruction *insn, *prev_jump = NULL;
813 struct rela *rela, *prev_rela = NULL;
814 int ret;
815
816 func_for_each_insn(file, func, insn) {
817 if (insn->type != INSN_JUMP_DYNAMIC)
818 continue;
819
820 rela = find_switch_table(file, func, insn);
821 if (!rela)
822 continue;
823
824 /*
825 * We found a switch table, but we don't know yet how big it
826 * is. Don't add it until we reach the end of the function or
827 * the beginning of another switch table in the same function.
828 */
829 if (prev_jump) {
830 ret = add_switch_table(file, func, prev_jump, prev_rela,
831 rela);
832 if (ret)
833 return ret;
834 }
835
836 prev_jump = insn;
837 prev_rela = rela;
838 }
839
840 if (prev_jump) {
841 ret = add_switch_table(file, func, prev_jump, prev_rela, NULL);
842 if (ret)
843 return ret;
844 }
845
846 return 0;
847}
848
849/*
850 * For some switch statements, gcc generates a jump table in the .rodata
851 * section which contains a list of addresses within the function to jump to.
852 * This finds these jump tables and adds them to the insn->alts lists.
853 */
854static int add_switch_table_alts(struct objtool_file *file)
855{
856 struct section *sec;
857 struct symbol *func;
858 int ret;
859
860 if (!file->rodata || !file->rodata->rela)
861 return 0;
862
863 for_each_sec(file, sec) {
864 list_for_each_entry(func, &sec->symbol_list, list) {
865 if (func->type != STT_FUNC)
866 continue;
867
868 ret = add_func_switch_tables(file, func);
869 if (ret)
870 return ret;
871 }
872 }
873
874 return 0;
875}
876
877static int decode_sections(struct objtool_file *file)
878{
879 int ret;
880
881 ret = decode_instructions(file);
882 if (ret)
883 return ret;
884
885 ret = add_dead_ends(file);
886 if (ret)
887 return ret;
888
889 add_ignores(file);
890
891 ret = add_jump_destinations(file);
892 if (ret)
893 return ret;
894
895 ret = add_call_destinations(file);
896 if (ret)
897 return ret;
898
899 ret = add_special_section_alts(file);
900 if (ret)
901 return ret;
902
903 ret = add_switch_table_alts(file);
904 if (ret)
905 return ret;
906
907 return 0;
908}
909
910static bool is_fentry_call(struct instruction *insn)
911{
912 if (insn->type == INSN_CALL &&
913 insn->call_dest->type == STT_NOTYPE &&
914 !strcmp(insn->call_dest->name, "__fentry__"))
915 return true;
916
917 return false;
918}
919
920static bool has_modified_stack_frame(struct insn_state *state)
921{
922 int i;
923
924 if (state->cfa.base != initial_func_cfi.cfa.base ||
925 state->cfa.offset != initial_func_cfi.cfa.offset ||
926 state->stack_size != initial_func_cfi.cfa.offset ||
927 state->drap)
928 return true;
929
930 for (i = 0; i < CFI_NUM_REGS; i++)
931 if (state->regs[i].base != initial_func_cfi.regs[i].base ||
932 state->regs[i].offset != initial_func_cfi.regs[i].offset)
933 return true;
934
935 return false;
936}
937
938static bool has_valid_stack_frame(struct insn_state *state)
939{
940 if (state->cfa.base == CFI_BP && state->regs[CFI_BP].base == CFI_CFA &&
941 state->regs[CFI_BP].offset == -16)
942 return true;
943
944 if (state->drap && state->regs[CFI_BP].base == CFI_BP)
945 return true;
946
947 return false;
948}
949
950static void save_reg(struct insn_state *state, unsigned char reg, int base,
951 int offset)
952{
953 if ((arch_callee_saved_reg(reg) ||
954 (state->drap && reg == state->drap_reg)) &&
955 state->regs[reg].base == CFI_UNDEFINED) {
956 state->regs[reg].base = base;
957 state->regs[reg].offset = offset;
958 }
959}
960
961static void restore_reg(struct insn_state *state, unsigned char reg)
962{
963 state->regs[reg].base = CFI_UNDEFINED;
964 state->regs[reg].offset = 0;
965}
966
967/*
968 * A note about DRAP stack alignment:
969 *
970 * GCC has the concept of a DRAP register, which is used to help keep track of
971 * the stack pointer when aligning the stack. r10 or r13 is used as the DRAP
972 * register. The typical DRAP pattern is:
973 *
974 * 4c 8d 54 24 08 lea 0x8(%rsp),%r10
975 * 48 83 e4 c0 and $0xffffffffffffffc0,%rsp
976 * 41 ff 72 f8 pushq -0x8(%r10)
977 * 55 push %rbp
978 * 48 89 e5 mov %rsp,%rbp
979 * (more pushes)
980 * 41 52 push %r10
981 * ...
982 * 41 5a pop %r10
983 * (more pops)
984 * 5d pop %rbp
985 * 49 8d 62 f8 lea -0x8(%r10),%rsp
986 * c3 retq
987 *
988 * There are some variations in the epilogues, like:
989 *
990 * 5b pop %rbx
991 * 41 5a pop %r10
992 * 41 5c pop %r12
993 * 41 5d pop %r13
994 * 41 5e pop %r14
995 * c9 leaveq
996 * 49 8d 62 f8 lea -0x8(%r10),%rsp
997 * c3 retq
998 *
999 * and:
1000 *
1001 * 4c 8b 55 e8 mov -0x18(%rbp),%r10
1002 * 48 8b 5d e0 mov -0x20(%rbp),%rbx
1003 * 4c 8b 65 f0 mov -0x10(%rbp),%r12
1004 * 4c 8b 6d f8 mov -0x8(%rbp),%r13
1005 * c9 leaveq
1006 * 49 8d 62 f8 lea -0x8(%r10),%rsp
1007 * c3 retq
1008 *
1009 * Sometimes r13 is used as the DRAP register, in which case it's saved and
1010 * restored beforehand:
1011 *
1012 * 41 55 push %r13
1013 * 4c 8d 6c 24 10 lea 0x10(%rsp),%r13
1014 * 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
1015 * ...
1016 * 49 8d 65 f0 lea -0x10(%r13),%rsp
1017 * 41 5d pop %r13
1018 * c3 retq
1019 */
1020static int update_insn_state(struct instruction *insn, struct insn_state *state)
1021{
1022 struct stack_op *op = &insn->stack_op;
1023 struct cfi_reg *cfa = &state->cfa;
1024 struct cfi_reg *regs = state->regs;
1025
1026 /* stack operations don't make sense with an undefined CFA */
1027 if (cfa->base == CFI_UNDEFINED) {
1028 if (insn->func) {
1029 WARN_FUNC("undefined stack state", insn->sec, insn->offset);
1030 return -1;
1031 }
1032 return 0;
1033 }
1034
1035 switch (op->dest.type) {
1036
1037 case OP_DEST_REG:
1038 switch (op->src.type) {
1039
1040 case OP_SRC_REG:
1041 if (cfa->base == op->src.reg && cfa->base == CFI_SP &&
1042 op->dest.reg == CFI_BP && regs[CFI_BP].base == CFI_CFA &&
1043 regs[CFI_BP].offset == -cfa->offset) {
1044
1045 /* mov %rsp, %rbp */
1046 cfa->base = op->dest.reg;
1047 state->bp_scratch = false;
1048 } else if (state->drap) {
1049
1050 /* drap: mov %rsp, %rbp */
1051 regs[CFI_BP].base = CFI_BP;
1052 regs[CFI_BP].offset = -state->stack_size;
1053 state->bp_scratch = false;
1054 } else if (!nofp) {
1055
1056 WARN_FUNC("unknown stack-related register move",
1057 insn->sec, insn->offset);
1058 return -1;
1059 }
1060
1061 break;
1062
1063 case OP_SRC_ADD:
1064 if (op->dest.reg == CFI_SP && op->src.reg == CFI_SP) {
1065
1066 /* add imm, %rsp */
1067 state->stack_size -= op->src.offset;
1068 if (cfa->base == CFI_SP)
1069 cfa->offset -= op->src.offset;
1070 break;
1071 }
1072
1073 if (op->dest.reg == CFI_SP && op->src.reg == CFI_BP) {
1074
1075 /* lea disp(%rbp), %rsp */
1076 state->stack_size = -(op->src.offset + regs[CFI_BP].offset);
1077 break;
1078 }
1079
1080 if (op->dest.reg != CFI_BP && op->src.reg == CFI_SP &&
1081 cfa->base == CFI_SP) {
1082
1083 /* drap: lea disp(%rsp), %drap */
1084 state->drap_reg = op->dest.reg;
1085 break;
1086 }
1087
1088 if (state->drap && op->dest.reg == CFI_SP &&
1089 op->src.reg == state->drap_reg) {
1090
1091 /* drap: lea disp(%drap), %rsp */
1092 cfa->base = CFI_SP;
1093 cfa->offset = state->stack_size = -op->src.offset;
1094 state->drap_reg = CFI_UNDEFINED;
1095 state->drap = false;
1096 break;
1097 }
1098
1099 if (op->dest.reg == state->cfa.base) {
1100 WARN_FUNC("unsupported stack register modification",
1101 insn->sec, insn->offset);
1102 return -1;
1103 }
1104
1105 break;
1106
1107 case OP_SRC_AND:
1108 if (op->dest.reg != CFI_SP ||
1109 (state->drap_reg != CFI_UNDEFINED && cfa->base != CFI_SP) ||
1110 (state->drap_reg == CFI_UNDEFINED && cfa->base != CFI_BP)) {
1111 WARN_FUNC("unsupported stack pointer realignment",
1112 insn->sec, insn->offset);
1113 return -1;
1114 }
1115
1116 if (state->drap_reg != CFI_UNDEFINED) {
1117 /* drap: and imm, %rsp */
1118 cfa->base = state->drap_reg;
1119 cfa->offset = state->stack_size = 0;
1120 state->drap = true;
1121
1122 }
1123
1124 /*
1125 * Older versions of GCC (4.8ish) realign the stack
1126 * without DRAP, with a frame pointer.
1127 */
1128
1129 break;
1130
1131 case OP_SRC_POP:
1132 if (!state->drap && op->dest.type == OP_DEST_REG &&
1133 op->dest.reg == cfa->base) {
1134
1135 /* pop %rbp */
1136 cfa->base = CFI_SP;
1137 }
1138
1139 if (regs[op->dest.reg].offset == -state->stack_size) {
1140
1141 if (state->drap && cfa->base == CFI_BP_INDIRECT &&
1142 op->dest.type == OP_DEST_REG &&
1143 op->dest.reg == state->drap_reg) {
1144
1145 /* drap: pop %drap */
1146 cfa->base = state->drap_reg;
1147 cfa->offset = 0;
1148 }
1149
1150 restore_reg(state, op->dest.reg);
1151 }
1152
1153 state->stack_size -= 8;
1154 if (cfa->base == CFI_SP)
1155 cfa->offset -= 8;
1156
1157 break;
1158
1159 case OP_SRC_REG_INDIRECT:
1160 if (state->drap && op->src.reg == CFI_BP &&
1161 op->src.offset == regs[op->dest.reg].offset) {
1162
1163 /* drap: mov disp(%rbp), %reg */
1164 if (op->dest.reg == state->drap_reg) {
1165 cfa->base = state->drap_reg;
1166 cfa->offset = 0;
1167 }
1168
1169 restore_reg(state, op->dest.reg);
1170
1171 } else if (op->src.reg == cfa->base &&
1172 op->src.offset == regs[op->dest.reg].offset + cfa->offset) {
1173
1174 /* mov disp(%rbp), %reg */
1175 /* mov disp(%rsp), %reg */
1176 restore_reg(state, op->dest.reg);
1177 }
1178
1179 break;
1180
1181 default:
1182 WARN_FUNC("unknown stack-related instruction",
1183 insn->sec, insn->offset);
1184 return -1;
1185 }
1186
1187 break;
1188
1189 case OP_DEST_PUSH:
1190 state->stack_size += 8;
1191 if (cfa->base == CFI_SP)
1192 cfa->offset += 8;
1193
1194 if (op->src.type != OP_SRC_REG)
1195 break;
1196
1197 if (state->drap) {
1198 if (op->src.reg == cfa->base && op->src.reg == state->drap_reg) {
1199
1200 /* drap: push %drap */
1201 cfa->base = CFI_BP_INDIRECT;
1202 cfa->offset = -state->stack_size;
1203
1204 /* save drap so we know when to undefine it */
1205 save_reg(state, op->src.reg, CFI_CFA, -state->stack_size);
1206
1207 } else if (op->src.reg == CFI_BP && cfa->base == state->drap_reg) {
1208
1209 /* drap: push %rbp */
1210 state->stack_size = 0;
1211
1212 } else if (regs[op->src.reg].base == CFI_UNDEFINED) {
1213
1214 /* drap: push %reg */
1215 save_reg(state, op->src.reg, CFI_BP, -state->stack_size);
1216 }
1217
1218 } else {
1219
1220 /* push %reg */
1221 save_reg(state, op->src.reg, CFI_CFA, -state->stack_size);
1222 }
1223
1224 /* detect when asm code uses rbp as a scratch register */
1225 if (!nofp && insn->func && op->src.reg == CFI_BP &&
1226 cfa->base != CFI_BP)
1227 state->bp_scratch = true;
1228 break;
1229
1230 case OP_DEST_REG_INDIRECT:
1231
1232 if (state->drap) {
1233 if (op->src.reg == cfa->base && op->src.reg == state->drap_reg) {
1234
1235 /* drap: mov %drap, disp(%rbp) */
1236 cfa->base = CFI_BP_INDIRECT;
1237 cfa->offset = op->dest.offset;
1238
1239 /* save drap so we know when to undefine it */
1240 save_reg(state, op->src.reg, CFI_CFA, op->dest.offset);
1241 }
1242
1243 else if (regs[op->src.reg].base == CFI_UNDEFINED) {
1244
1245 /* drap: mov reg, disp(%rbp) */
1246 save_reg(state, op->src.reg, CFI_BP, op->dest.offset);
1247 }
1248
1249 } else if (op->dest.reg == cfa->base) {
1250
1251 /* mov reg, disp(%rbp) */
1252 /* mov reg, disp(%rsp) */
1253 save_reg(state, op->src.reg, CFI_CFA,
1254 op->dest.offset - state->cfa.offset);
1255 }
1256
1257 break;
1258
1259 case OP_DEST_LEAVE:
1260 if ((!state->drap && cfa->base != CFI_BP) ||
1261 (state->drap && cfa->base != state->drap_reg)) {
1262 WARN_FUNC("leave instruction with modified stack frame",
1263 insn->sec, insn->offset);
1264 return -1;
1265 }
1266
1267 /* leave (mov %rbp, %rsp; pop %rbp) */
1268
1269 state->stack_size = -state->regs[CFI_BP].offset - 8;
1270 restore_reg(state, CFI_BP);
1271
1272 if (!state->drap) {
1273 cfa->base = CFI_SP;
1274 cfa->offset -= 8;
1275 }
1276
1277 break;
1278
1279 case OP_DEST_MEM:
1280 if (op->src.type != OP_SRC_POP) {
1281 WARN_FUNC("unknown stack-related memory operation",
1282 insn->sec, insn->offset);
1283 return -1;
1284 }
1285
1286 /* pop mem */
1287 state->stack_size -= 8;
1288 if (cfa->base == CFI_SP)
1289 cfa->offset -= 8;
1290
1291 break;
1292
1293 default:
1294 WARN_FUNC("unknown stack-related instruction",
1295 insn->sec, insn->offset);
1296 return -1;
1297 }
1298
1299 return 0;
1300}
1301
1302static bool insn_state_match(struct instruction *insn, struct insn_state *state)
1303{
1304 struct insn_state *state1 = &insn->state, *state2 = state;
1305 int i;
1306
1307 if (memcmp(&state1->cfa, &state2->cfa, sizeof(state1->cfa))) {
1308 WARN_FUNC("stack state mismatch: cfa1=%d%+d cfa2=%d%+d",
1309 insn->sec, insn->offset,
1310 state1->cfa.base, state1->cfa.offset,
1311 state2->cfa.base, state2->cfa.offset);
1312
1313 } else if (memcmp(&state1->regs, &state2->regs, sizeof(state1->regs))) {
1314 for (i = 0; i < CFI_NUM_REGS; i++) {
1315 if (!memcmp(&state1->regs[i], &state2->regs[i],
1316 sizeof(struct cfi_reg)))
1317 continue;
1318
1319 WARN_FUNC("stack state mismatch: reg1[%d]=%d%+d reg2[%d]=%d%+d",
1320 insn->sec, insn->offset,
1321 i, state1->regs[i].base, state1->regs[i].offset,
1322 i, state2->regs[i].base, state2->regs[i].offset);
1323 break;
1324 }
1325
1326 } else if (state1->drap != state2->drap ||
1327 (state1->drap && state1->drap_reg != state2->drap_reg)) {
1328 WARN_FUNC("stack state mismatch: drap1=%d(%d) drap2=%d(%d)",
1329 insn->sec, insn->offset,
1330 state1->drap, state1->drap_reg,
1331 state2->drap, state2->drap_reg);
1332
1333 } else
1334 return true;
1335
1336 return false;
1337}
1338
1339/*
1340 * Follow the branch starting at the given instruction, and recursively follow
1341 * any other branches (jumps). Meanwhile, track the frame pointer state at
1342 * each instruction and validate all the rules described in
1343 * tools/objtool/Documentation/stack-validation.txt.
1344 */
1345static int validate_branch(struct objtool_file *file, struct instruction *first,
1346 struct insn_state state)
1347{
1348 struct alternative *alt;
1349 struct instruction *insn;
1350 struct section *sec;
1351 struct symbol *func = NULL;
1352 int ret;
1353
1354 insn = first;
1355 sec = insn->sec;
1356
1357 if (insn->alt_group && list_empty(&insn->alts)) {
1358 WARN_FUNC("don't know how to handle branch to middle of alternative instruction group",
1359 sec, insn->offset);
1360 return -1;
1361 }
1362
1363 while (1) {
1364 if (file->c_file && insn->func) {
1365 if (func && func != insn->func) {
1366 WARN("%s() falls through to next function %s()",
1367 func->name, insn->func->name);
1368 return 1;
1369 }
1370 }
1371
1372 func = insn->func;
1373
1374 if (insn->visited) {
1375 if (!!insn_state_match(insn, &state))
1376 return 1;
1377
1378 return 0;
1379 }
1380
1381 insn->state = state;
1382
1383 insn->visited = true;
1384
1385 list_for_each_entry(alt, &insn->alts, list) {
1386 ret = validate_branch(file, alt->insn, state);
1387 if (ret)
1388 return 1;
1389 }
1390
1391 switch (insn->type) {
1392
1393 case INSN_RETURN:
1394 if (func && has_modified_stack_frame(&state)) {
1395 WARN_FUNC("return with modified stack frame",
1396 sec, insn->offset);
1397 return 1;
1398 }
1399
1400 if (state.bp_scratch) {
1401 WARN("%s uses BP as a scratch register",
1402 insn->func->name);
1403 return 1;
1404 }
1405
1406 return 0;
1407
1408 case INSN_CALL:
1409 if (is_fentry_call(insn))
1410 break;
1411
1412 ret = dead_end_function(file, insn->call_dest);
1413 if (ret == 1)
1414 return 0;
1415 if (ret == -1)
1416 return 1;
1417
1418 /* fallthrough */
1419 case INSN_CALL_DYNAMIC:
1420 if (!nofp && func && !has_valid_stack_frame(&state)) {
1421 WARN_FUNC("call without frame pointer save/setup",
1422 sec, insn->offset);
1423 return 1;
1424 }
1425 break;
1426
1427 case INSN_JUMP_CONDITIONAL:
1428 case INSN_JUMP_UNCONDITIONAL:
1429 if (insn->jump_dest) {
1430 ret = validate_branch(file, insn->jump_dest,
1431 state);
1432 if (ret)
1433 return 1;
1434 } else if (func && has_modified_stack_frame(&state)) {
1435 WARN_FUNC("sibling call from callable instruction with modified stack frame",
1436 sec, insn->offset);
1437 return 1;
1438 } /* else it's a sibling call */
1439
1440 if (insn->type == INSN_JUMP_UNCONDITIONAL)
1441 return 0;
1442
1443 break;
1444
1445 case INSN_JUMP_DYNAMIC:
1446 if (func && list_empty(&insn->alts) &&
1447 has_modified_stack_frame(&state)) {
1448 WARN_FUNC("sibling call from callable instruction with modified stack frame",
1449 sec, insn->offset);
1450 return 1;
1451 }
1452
1453 return 0;
1454
1455 case INSN_STACK:
1456 if (update_insn_state(insn, &state))
1457 return -1;
1458
1459 break;
1460
1461 default:
1462 break;
1463 }
1464
1465 if (insn->dead_end)
1466 return 0;
1467
1468 insn = next_insn_same_sec(file, insn);
1469 if (!insn) {
1470 WARN("%s: unexpected end of section", sec->name);
1471 return 1;
1472 }
1473 }
1474
1475 return 0;
1476}
1477
1478static bool is_kasan_insn(struct instruction *insn)
1479{
1480 return (insn->type == INSN_CALL &&
1481 !strcmp(insn->call_dest->name, "__asan_handle_no_return"));
1482}
1483
1484static bool is_ubsan_insn(struct instruction *insn)
1485{
1486 return (insn->type == INSN_CALL &&
1487 !strcmp(insn->call_dest->name,
1488 "__ubsan_handle_builtin_unreachable"));
1489}
1490
1491static bool ignore_unreachable_insn(struct instruction *insn)
1492{
1493 int i;
1494
1495 if (insn->ignore || insn->type == INSN_NOP)
1496 return true;
1497
1498 /*
1499 * Ignore any unused exceptions. This can happen when a whitelisted
1500 * function has an exception table entry.
1501 */
1502 if (!strcmp(insn->sec->name, ".fixup"))
1503 return true;
1504
1505 /*
1506 * Check if this (or a subsequent) instruction is related to
1507 * CONFIG_UBSAN or CONFIG_KASAN.
1508 *
1509 * End the search at 5 instructions to avoid going into the weeds.
1510 */
1511 if (!insn->func)
1512 return false;
1513 for (i = 0; i < 5; i++) {
1514
1515 if (is_kasan_insn(insn) || is_ubsan_insn(insn))
1516 return true;
1517
1518 if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest) {
1519 insn = insn->jump_dest;
1520 continue;
1521 }
1522
1523 if (insn->offset + insn->len >= insn->func->offset + insn->func->len)
1524 break;
1525 insn = list_next_entry(insn, list);
1526 }
1527
1528 return false;
1529}
1530
1531static int validate_functions(struct objtool_file *file)
1532{
1533 struct section *sec;
1534 struct symbol *func;
1535 struct instruction *insn;
1536 struct insn_state state;
1537 int ret, warnings = 0;
1538
1539 clear_insn_state(&state);
1540
1541 state.cfa = initial_func_cfi.cfa;
1542 memcpy(&state.regs, &initial_func_cfi.regs,
1543 CFI_NUM_REGS * sizeof(struct cfi_reg));
1544 state.stack_size = initial_func_cfi.cfa.offset;
1545
1546 for_each_sec(file, sec) {
1547 list_for_each_entry(func, &sec->symbol_list, list) {
1548 if (func->type != STT_FUNC)
1549 continue;
1550
1551 insn = find_insn(file, sec, func->offset);
1552 if (!insn || insn->ignore)
1553 continue;
1554
1555 ret = validate_branch(file, insn, state);
1556 warnings += ret;
1557 }
1558 }
1559
1560 return warnings;
1561}
1562
1563static int validate_reachable_instructions(struct objtool_file *file)
1564{
1565 struct instruction *insn;
1566
1567 if (file->ignore_unreachables)
1568 return 0;
1569
1570 for_each_insn(file, insn) {
1571 if (insn->visited || ignore_unreachable_insn(insn))
1572 continue;
1573
1574 /*
1575 * gcov produces a lot of unreachable instructions. If we get
1576 * an unreachable warning and the file has gcov enabled, just
1577 * ignore it, and all other such warnings for the file. Do
1578 * this here because this is an expensive function.
1579 */
1580 if (gcov_enabled(file))
1581 return 0;
1582
1583 WARN_FUNC("unreachable instruction", insn->sec, insn->offset);
1584 return 1;
1585 }
1586
1587 return 0;
1588}
1589
1590static void cleanup(struct objtool_file *file)
1591{
1592 struct instruction *insn, *tmpinsn;
1593 struct alternative *alt, *tmpalt;
1594
1595 list_for_each_entry_safe(insn, tmpinsn, &file->insn_list, list) {
1596 list_for_each_entry_safe(alt, tmpalt, &insn->alts, list) {
1597 list_del(&alt->list);
1598 free(alt);
1599 }
1600 list_del(&insn->list);
1601 hash_del(&insn->hash);
1602 free(insn);
1603 }
1604 elf_close(file->elf);
1605}
1606
1607int check(const char *_objname, bool _nofp)
1608{
1609 struct objtool_file file;
1610 int ret, warnings = 0;
1611
1612 objname = _objname;
1613 nofp = _nofp;
1614
1615 file.elf = elf_open(objname);
1616 if (!file.elf)
1617 return 1;
1618
1619 INIT_LIST_HEAD(&file.insn_list);
1620 hash_init(file.insn_hash);
1621 file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard");
1622 file.rodata = find_section_by_name(file.elf, ".rodata");
1623 file.ignore_unreachables = false;
1624 file.c_file = find_section_by_name(file.elf, ".comment");
1625
1626 arch_initial_func_cfi_state(&initial_func_cfi);
1627
1628 ret = decode_sections(&file);
1629 if (ret < 0)
1630 goto out;
1631 warnings += ret;
1632
1633 if (list_empty(&file.insn_list))
1634 goto out;
1635
1636 ret = validate_functions(&file);
1637 if (ret < 0)
1638 goto out;
1639 warnings += ret;
1640
1641 if (!warnings) {
1642 ret = validate_reachable_instructions(&file);
1643 if (ret < 0)
1644 goto out;
1645 warnings += ret;
1646 }
1647
1648out:
1649 cleanup(&file);
1650
1651 /* ignore warnings for now until we get all the code cleaned up */
1652 if (ret || warnings)
1653 return 0;
1654 return 0;
1655}
diff --git a/tools/objtool/check.h b/tools/objtool/check.h
new file mode 100644
index 000000000000..da85f5b00ec6
--- /dev/null
+++ b/tools/objtool/check.h
@@ -0,0 +1,66 @@
1/*
2 * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef _CHECK_H
19#define _CHECK_H
20
21#include <stdbool.h>
22#include "elf.h"
23#include "cfi.h"
24#include "arch.h"
25#include <linux/hashtable.h>
26
27struct insn_state {
28 struct cfi_reg cfa;
29 struct cfi_reg regs[CFI_NUM_REGS];
30 int stack_size;
31 bool bp_scratch;
32 bool drap;
33 int drap_reg;
34};
35
36struct instruction {
37 struct list_head list;
38 struct hlist_node hash;
39 struct section *sec;
40 unsigned long offset;
41 unsigned int len;
42 unsigned char type;
43 unsigned long immediate;
44 bool alt_group, visited, dead_end, ignore;
45 struct symbol *call_dest;
46 struct instruction *jump_dest;
47 struct list_head alts;
48 struct symbol *func;
49 struct stack_op stack_op;
50 struct insn_state state;
51};
52
53struct objtool_file {
54 struct elf *elf;
55 struct list_head insn_list;
56 DECLARE_HASHTABLE(insn_hash, 16);
57 struct section *rodata, *whitelist;
58 bool ignore_unreachables, c_file;
59};
60
61int check(const char *objname, bool nofp);
62
63#define for_each_insn(file, insn) \
64 list_for_each_entry(insn, &file->insn_list, list)
65
66#endif /* _CHECK_H */
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index d897702ce742..1a7e8aa2af58 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -37,6 +37,9 @@
37#define ELF_C_READ_MMAP ELF_C_READ 37#define ELF_C_READ_MMAP ELF_C_READ
38#endif 38#endif
39 39
40#define WARN_ELF(format, ...) \
41 WARN(format ": %s", ##__VA_ARGS__, elf_errmsg(-1))
42
40struct section *find_section_by_name(struct elf *elf, const char *name) 43struct section *find_section_by_name(struct elf *elf, const char *name)
41{ 44{
42 struct section *sec; 45 struct section *sec;
@@ -139,12 +142,12 @@ static int read_sections(struct elf *elf)
139 int i; 142 int i;
140 143
141 if (elf_getshdrnum(elf->elf, &sections_nr)) { 144 if (elf_getshdrnum(elf->elf, &sections_nr)) {
142 perror("elf_getshdrnum"); 145 WARN_ELF("elf_getshdrnum");
143 return -1; 146 return -1;
144 } 147 }
145 148
146 if (elf_getshdrstrndx(elf->elf, &shstrndx)) { 149 if (elf_getshdrstrndx(elf->elf, &shstrndx)) {
147 perror("elf_getshdrstrndx"); 150 WARN_ELF("elf_getshdrstrndx");
148 return -1; 151 return -1;
149 } 152 }
150 153
@@ -165,37 +168,36 @@ static int read_sections(struct elf *elf)
165 168
166 s = elf_getscn(elf->elf, i); 169 s = elf_getscn(elf->elf, i);
167 if (!s) { 170 if (!s) {
168 perror("elf_getscn"); 171 WARN_ELF("elf_getscn");
169 return -1; 172 return -1;
170 } 173 }
171 174
172 sec->idx = elf_ndxscn(s); 175 sec->idx = elf_ndxscn(s);
173 176
174 if (!gelf_getshdr(s, &sec->sh)) { 177 if (!gelf_getshdr(s, &sec->sh)) {
175 perror("gelf_getshdr"); 178 WARN_ELF("gelf_getshdr");
176 return -1; 179 return -1;
177 } 180 }
178 181
179 sec->name = elf_strptr(elf->elf, shstrndx, sec->sh.sh_name); 182 sec->name = elf_strptr(elf->elf, shstrndx, sec->sh.sh_name);
180 if (!sec->name) { 183 if (!sec->name) {
181 perror("elf_strptr"); 184 WARN_ELF("elf_strptr");
182 return -1; 185 return -1;
183 } 186 }
184 187
185 sec->elf_data = elf_getdata(s, NULL); 188 sec->data = elf_getdata(s, NULL);
186 if (!sec->elf_data) { 189 if (!sec->data) {
187 perror("elf_getdata"); 190 WARN_ELF("elf_getdata");
188 return -1; 191 return -1;
189 } 192 }
190 193
191 if (sec->elf_data->d_off != 0 || 194 if (sec->data->d_off != 0 ||
192 sec->elf_data->d_size != sec->sh.sh_size) { 195 sec->data->d_size != sec->sh.sh_size) {
193 WARN("unexpected data attributes for %s", sec->name); 196 WARN("unexpected data attributes for %s", sec->name);
194 return -1; 197 return -1;
195 } 198 }
196 199
197 sec->data = (unsigned long)sec->elf_data->d_buf; 200 sec->len = sec->data->d_size;
198 sec->len = sec->elf_data->d_size;
199 } 201 }
200 202
201 /* sanity check, one more call to elf_nextscn() should return NULL */ 203 /* sanity check, one more call to elf_nextscn() should return NULL */
@@ -232,15 +234,15 @@ static int read_symbols(struct elf *elf)
232 234
233 sym->idx = i; 235 sym->idx = i;
234 236
235 if (!gelf_getsym(symtab->elf_data, i, &sym->sym)) { 237 if (!gelf_getsym(symtab->data, i, &sym->sym)) {
236 perror("gelf_getsym"); 238 WARN_ELF("gelf_getsym");
237 goto err; 239 goto err;
238 } 240 }
239 241
240 sym->name = elf_strptr(elf->elf, symtab->sh.sh_link, 242 sym->name = elf_strptr(elf->elf, symtab->sh.sh_link,
241 sym->sym.st_name); 243 sym->sym.st_name);
242 if (!sym->name) { 244 if (!sym->name) {
243 perror("elf_strptr"); 245 WARN_ELF("elf_strptr");
244 goto err; 246 goto err;
245 } 247 }
246 248
@@ -322,8 +324,8 @@ static int read_relas(struct elf *elf)
322 } 324 }
323 memset(rela, 0, sizeof(*rela)); 325 memset(rela, 0, sizeof(*rela));
324 326
325 if (!gelf_getrela(sec->elf_data, i, &rela->rela)) { 327 if (!gelf_getrela(sec->data, i, &rela->rela)) {
326 perror("gelf_getrela"); 328 WARN_ELF("gelf_getrela");
327 return -1; 329 return -1;
328 } 330 }
329 331
@@ -362,12 +364,6 @@ struct elf *elf_open(const char *name)
362 364
363 INIT_LIST_HEAD(&elf->sections); 365 INIT_LIST_HEAD(&elf->sections);
364 366
365 elf->name = strdup(name);
366 if (!elf->name) {
367 perror("strdup");
368 goto err;
369 }
370
371 elf->fd = open(name, O_RDONLY); 367 elf->fd = open(name, O_RDONLY);
372 if (elf->fd == -1) { 368 if (elf->fd == -1) {
373 perror("open"); 369 perror("open");
@@ -376,12 +372,12 @@ struct elf *elf_open(const char *name)
376 372
377 elf->elf = elf_begin(elf->fd, ELF_C_READ_MMAP, NULL); 373 elf->elf = elf_begin(elf->fd, ELF_C_READ_MMAP, NULL);
378 if (!elf->elf) { 374 if (!elf->elf) {
379 perror("elf_begin"); 375 WARN_ELF("elf_begin");
380 goto err; 376 goto err;
381 } 377 }
382 378
383 if (!gelf_getehdr(elf->elf, &elf->ehdr)) { 379 if (!gelf_getehdr(elf->elf, &elf->ehdr)) {
384 perror("gelf_getehdr"); 380 WARN_ELF("gelf_getehdr");
385 goto err; 381 goto err;
386 } 382 }
387 383
@@ -407,6 +403,12 @@ void elf_close(struct elf *elf)
407 struct symbol *sym, *tmpsym; 403 struct symbol *sym, *tmpsym;
408 struct rela *rela, *tmprela; 404 struct rela *rela, *tmprela;
409 405
406 if (elf->elf)
407 elf_end(elf->elf);
408
409 if (elf->fd > 0)
410 close(elf->fd);
411
410 list_for_each_entry_safe(sec, tmpsec, &elf->sections, list) { 412 list_for_each_entry_safe(sec, tmpsec, &elf->sections, list) {
411 list_for_each_entry_safe(sym, tmpsym, &sec->symbol_list, list) { 413 list_for_each_entry_safe(sym, tmpsym, &sec->symbol_list, list) {
412 list_del(&sym->list); 414 list_del(&sym->list);
@@ -421,11 +423,6 @@ void elf_close(struct elf *elf)
421 list_del(&sec->list); 423 list_del(&sec->list);
422 free(sec); 424 free(sec);
423 } 425 }
424 if (elf->name) 426
425 free(elf->name);
426 if (elf->fd > 0)
427 close(elf->fd);
428 if (elf->elf)
429 elf_end(elf->elf);
430 free(elf); 427 free(elf);
431} 428}
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index 731973e1a3f5..343968b778cb 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -37,10 +37,9 @@ struct section {
37 DECLARE_HASHTABLE(rela_hash, 16); 37 DECLARE_HASHTABLE(rela_hash, 16);
38 struct section *base, *rela; 38 struct section *base, *rela;
39 struct symbol *sym; 39 struct symbol *sym;
40 Elf_Data *elf_data; 40 Elf_Data *data;
41 char *name; 41 char *name;
42 int idx; 42 int idx;
43 unsigned long data;
44 unsigned int len; 43 unsigned int len;
45}; 44};
46 45
@@ -86,6 +85,7 @@ struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset,
86struct symbol *find_containing_func(struct section *sec, unsigned long offset); 85struct symbol *find_containing_func(struct section *sec, unsigned long offset);
87void elf_close(struct elf *elf); 86void elf_close(struct elf *elf);
88 87
89 88#define for_each_sec(file, sec) \
89 list_for_each_entry(sec, &file->elf->sections, list)
90 90
91#endif /* _OBJTOOL_ELF_H */ 91#endif /* _OBJTOOL_ELF_H */
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index bff8abb3a4aa..84f001d52322 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -91,16 +91,16 @@ static int get_alt_entry(struct elf *elf, struct special_entry *entry,
91 alt->jump_or_nop = entry->jump_or_nop; 91 alt->jump_or_nop = entry->jump_or_nop;
92 92
93 if (alt->group) { 93 if (alt->group) {
94 alt->orig_len = *(unsigned char *)(sec->data + offset + 94 alt->orig_len = *(unsigned char *)(sec->data->d_buf + offset +
95 entry->orig_len); 95 entry->orig_len);
96 alt->new_len = *(unsigned char *)(sec->data + offset + 96 alt->new_len = *(unsigned char *)(sec->data->d_buf + offset +
97 entry->new_len); 97 entry->new_len);
98 } 98 }
99 99
100 if (entry->feature) { 100 if (entry->feature) {
101 unsigned short feature; 101 unsigned short feature;
102 102
103 feature = *(unsigned short *)(sec->data + offset + 103 feature = *(unsigned short *)(sec->data->d_buf + offset +
104 entry->feature); 104 entry->feature);
105 105
106 /* 106 /*
diff --git a/tools/objtool/warn.h b/tools/objtool/warn.h
index ac7e07523e84..afd9f7a05f6d 100644
--- a/tools/objtool/warn.h
+++ b/tools/objtool/warn.h
@@ -18,6 +18,13 @@
18#ifndef _WARN_H 18#ifndef _WARN_H
19#define _WARN_H 19#define _WARN_H
20 20
21#include <stdlib.h>
22#include <string.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26#include "elf.h"
27
21extern const char *objname; 28extern const char *objname;
22 29
23static inline char *offstr(struct section *sec, unsigned long offset) 30static inline char *offstr(struct section *sec, unsigned long offset)
@@ -57,4 +64,7 @@ static inline char *offstr(struct section *sec, unsigned long offset)
57 free(_str); \ 64 free(_str); \
58}) 65})
59 66
67#define WARN_ELF(format, ...) \
68 WARN(format ": %s", ##__VA_ARGS__, elf_errmsg(-1))
69
60#endif /* _WARN_H */ 70#endif /* _WARN_H */
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index b0b3007d3c9c..4b6cdbf8f935 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -108,6 +108,9 @@ approach is available to export the data to a postgresql database. Refer to
108script export-to-postgresql.py for more details, and to script 108script export-to-postgresql.py for more details, and to script
109call-graph-from-postgresql.py for an example of using the database. 109call-graph-from-postgresql.py for an example of using the database.
110 110
111There is also script intel-pt-events.py which provides an example of how to
112unpack the raw data for power events and PTWRITE.
113
111As mentioned above, it is easy to capture too much data. One way to limit the 114As mentioned above, it is easy to capture too much data. One way to limit the
112data captured is to use 'snapshot' mode which is explained further below. 115data captured is to use 'snapshot' mode which is explained further below.
113Refer to 'new snapshot option' and 'Intel PT modes of operation' further below. 116Refer to 'new snapshot option' and 'Intel PT modes of operation' further below.
@@ -364,6 +367,42 @@ cyc_thresh Specifies how frequently CYC packets are produced - see cyc
364 367
365 CYC packets are not requested by default. 368 CYC packets are not requested by default.
366 369
370pt Specifies pass-through which enables the 'branch' config term.
371
372 The default config selects 'pt' if it is available, so a user will
373 never need to specify this term.
374
375branch Enable branch tracing. Branch tracing is enabled by default so to
376 disable branch tracing use 'branch=0'.
377
378 The default config selects 'branch' if it is available.
379
380ptw Enable PTWRITE packets which are produced when a ptwrite instruction
381 is executed.
382
383 Support for this feature is indicated by:
384
385 /sys/bus/event_source/devices/intel_pt/caps/ptwrite
386
387 which contains "1" if the feature is supported and
388 "0" otherwise.
389
390fup_on_ptw Enable a FUP packet to follow the PTWRITE packet. The FUP packet
391 provides the address of the ptwrite instruction. In the absence of
392 fup_on_ptw, the decoder will use the address of the previous branch
393 if branch tracing is enabled, otherwise the address will be zero.
394 Note that fup_on_ptw will work even when branch tracing is disabled.
395
396pwr_evt Enable power events. The power events provide information about
397 changes to the CPU C-state.
398
399 Support for this feature is indicated by:
400
401 /sys/bus/event_source/devices/intel_pt/caps/power_event_trace
402
403 which contains "1" if the feature is supported and
404 "0" otherwise.
405
367 406
368new snapshot option 407new snapshot option
369------------------- 408-------------------
@@ -674,13 +713,15 @@ Having no option is the same as
674 713
675which, in turn, is the same as 714which, in turn, is the same as
676 715
677 --itrace=ibxe 716 --itrace=ibxwpe
678 717
679The letters are: 718The letters are:
680 719
681 i synthesize "instructions" events 720 i synthesize "instructions" events
682 b synthesize "branches" events 721 b synthesize "branches" events
683 x synthesize "transactions" events 722 x synthesize "transactions" events
723 w synthesize "ptwrite" events
724 p synthesize "power" events
684 c synthesize branches events (calls only) 725 c synthesize branches events (calls only)
685 r synthesize branches events (returns only) 726 r synthesize branches events (returns only)
686 e synthesize tracing error events 727 e synthesize tracing error events
@@ -699,7 +740,40 @@ and "r" can be combined to get calls and returns.
699'flags' field can be used in perf script to determine whether the event is a 740'flags' field can be used in perf script to determine whether the event is a
700tranasaction start, commit or abort. 741tranasaction start, commit or abort.
701 742
702Error events are new. They show where the decoder lost the trace. Error events 743Note that "instructions", "branches" and "transactions" events depend on code
744flow packets which can be disabled by using the config term "branch=0". Refer
745to the config terms section above.
746
747"ptwrite" events record the payload of the ptwrite instruction and whether
748"fup_on_ptw" was used. "ptwrite" events depend on PTWRITE packets which are
749recorded only if the "ptw" config term was used. Refer to the config terms
750section above. perf script "synth" field displays "ptwrite" information like
751this: "ip: 0 payload: 0x123456789abcdef0" where "ip" is 1 if "fup_on_ptw" was
752used.
753
754"Power" events correspond to power event packets and CBR (core-to-bus ratio)
755packets. While CBR packets are always recorded when tracing is enabled, power
756event packets are recorded only if the "pwr_evt" config term was used. Refer to
757the config terms section above. The power events record information about
758C-state changes, whereas CBR is indicative of CPU frequency. perf script
759"event,synth" fields display information like this:
760 cbr: cbr: 22 freq: 2189 MHz (200%)
761 mwait: hints: 0x60 extensions: 0x1
762 pwre: hw: 0 cstate: 2 sub-cstate: 0
763 exstop: ip: 1
764 pwrx: deepest cstate: 2 last cstate: 2 wake reason: 0x4
765Where:
766 "cbr" includes the frequency and the percentage of maximum non-turbo
767 "mwait" shows mwait hints and extensions
768 "pwre" shows C-state transitions (to a C-state deeper than C0) and
769 whether initiated by hardware
770 "exstop" indicates execution stopped and whether the IP was recorded
771 exactly,
772 "pwrx" indicates return to C0
773For more details refer to the Intel 64 and IA-32 Architectures Software
774Developer Manuals.
775
776Error events show where the decoder lost the trace. Error events
703are quite important. Users must know if what they are seeing is a complete 777are quite important. Users must know if what they are seeing is a complete
704picture or not. 778picture or not.
705 779
diff --git a/tools/perf/Documentation/itrace.txt b/tools/perf/Documentation/itrace.txt
index e2a4c5e0dbe5..a3abe04c779d 100644
--- a/tools/perf/Documentation/itrace.txt
+++ b/tools/perf/Documentation/itrace.txt
@@ -3,13 +3,15 @@
3 c synthesize branches events (calls only) 3 c synthesize branches events (calls only)
4 r synthesize branches events (returns only) 4 r synthesize branches events (returns only)
5 x synthesize transactions events 5 x synthesize transactions events
6 w synthesize ptwrite events
7 p synthesize power events
6 e synthesize error events 8 e synthesize error events
7 d create a debug log 9 d create a debug log
8 g synthesize a call chain (use with i or x) 10 g synthesize a call chain (use with i or x)
9 l synthesize last branch entries (use with i or x) 11 l synthesize last branch entries (use with i or x)
10 s skip initial number of events 12 s skip initial number of events
11 13
12 The default is all events i.e. the same as --itrace=ibxe 14 The default is all events i.e. the same as --itrace=ibxwpe
13 15
14 In addition, the period (default 100000) for instructions events 16 In addition, the period (default 100000) for instructions events
15 can be specified in units of: 17 can be specified in units of:
@@ -26,8 +28,8 @@
26 Also the number of last branch entries (default 64, max. 1024) for 28 Also the number of last branch entries (default 64, max. 1024) for
27 instructions or transactions events can be specified. 29 instructions or transactions events can be specified.
28 30
29 It is also possible to skip events generated (instructions, branches, transactions) 31 It is also possible to skip events generated (instructions, branches, transactions,
30 at the beginning. This is useful to ignore initialization code. 32 ptwrite, power) at the beginning. This is useful to ignore initialization code.
31 33
32 --itrace=i0nss1000000 34 --itrace=i0nss1000000
33 35
diff --git a/tools/perf/Documentation/perf-ftrace.txt b/tools/perf/Documentation/perf-ftrace.txt
index 6e6a8b22c859..721a447f046e 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -48,6 +48,39 @@ OPTIONS
48 Ranges of CPUs are specified with -: 0-2. 48 Ranges of CPUs are specified with -: 0-2.
49 Default is to trace on all online CPUs. 49 Default is to trace on all online CPUs.
50 50
51-T::
52--trace-funcs=::
53 Only trace functions given by the argument. Multiple functions
54 can be given by using this option more than once. The function
55 argument also can be a glob pattern. It will be passed to
56 'set_ftrace_filter' in tracefs.
57
58-N::
59--notrace-funcs=::
60 Do not trace functions given by the argument. Like -T option,
61 this can be used more than once to specify multiple functions
62 (or glob patterns). It will be passed to 'set_ftrace_notrace'
63 in tracefs.
64
65-G::
66--graph-funcs=::
67 Set graph filter on the given function (or a glob pattern).
68 This is useful for the function_graph tracer only and enables
69 tracing for functions executed from the given function.
70 This can be used more than once to specify multiple functions.
71 It will be passed to 'set_graph_function' in tracefs.
72
73-g::
74--nograph-funcs=::
75 Set graph notrace filter on the given function (or a glob pattern).
76 Like -G option, this is useful for the function_graph tracer only
77 and disables tracing for function executed from the given function.
78 This can be used more than once to specify multiple functions.
79 It will be passed to 'set_graph_notrace' in tracefs.
80
81-D::
82--graph-depth=::
83 Set max depth for function graph tracer to follow
51 84
52SEE ALSO 85SEE ALSO
53-------- 86--------
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index e6c9902c6d82..165c2b1d4317 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -240,9 +240,13 @@ Add a probe on schedule() function 12th line with recording cpu local variable:
240 or 240 or
241 ./perf probe --add='schedule:12 cpu' 241 ./perf probe --add='schedule:12 cpu'
242 242
243 this will add one or more probes which has the name start with "schedule". 243Add one or more probes which has the name start with "schedule".
244 244
245 Add probes on lines in schedule() function which calls update_rq_clock(). 245 ./perf probe schedule*
246 or
247 ./perf probe --add='schedule*'
248
249Add probes on lines in schedule() function which calls update_rq_clock().
246 250
247 ./perf probe 'schedule;update_rq_clock*' 251 ./perf probe 'schedule;update_rq_clock*'
248 or 252 or
diff --git a/tools/perf/Documentation/perf-script-perl.txt b/tools/perf/Documentation/perf-script-perl.txt
index dfbb506d2c34..142606c0ec9c 100644
--- a/tools/perf/Documentation/perf-script-perl.txt
+++ b/tools/perf/Documentation/perf-script-perl.txt
@@ -39,7 +39,7 @@ EVENT HANDLERS
39When perf script is invoked using a trace script, a user-defined 39When perf script is invoked using a trace script, a user-defined
40'handler function' is called for each event in the trace. If there's 40'handler function' is called for each event in the trace. If there's
41no handler function defined for a given event type, the event is 41no handler function defined for a given event type, the event is
42ignored (or passed to a 'trace_handled' function, see below) and the 42ignored (or passed to a 'trace_unhandled' function, see below) and the
43next event is processed. 43next event is processed.
44 44
45Most of the event's field values are passed as arguments to the 45Most of the event's field values are passed as arguments to the
diff --git a/tools/perf/Documentation/perf-script-python.txt b/tools/perf/Documentation/perf-script-python.txt
index 54acba221558..51ec2d20068a 100644
--- a/tools/perf/Documentation/perf-script-python.txt
+++ b/tools/perf/Documentation/perf-script-python.txt
@@ -149,10 +149,8 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu,
149 print "id=%d, args=%s\n" % \ 149 print "id=%d, args=%s\n" % \
150 (id, args), 150 (id, args),
151 151
152def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs, 152def trace_unhandled(event_name, context, event_fields_dict):
153 common_pid, common_comm): 153 print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])
154 print_header(event_name, common_cpu, common_secs, common_nsecs,
155 common_pid, common_comm)
156 154
157def print_header(event_name, cpu, secs, nsecs, pid, comm): 155def print_header(event_name, cpu, secs, nsecs, pid, comm):
158 print "%-20s %5u %05u.%09u %8u %-20s " % \ 156 print "%-20s %5u %05u.%09u %8u %-20s " % \
@@ -321,7 +319,7 @@ So those are the essential steps in writing and running a script. The
321process can be generalized to any tracepoint or set of tracepoints 319process can be generalized to any tracepoint or set of tracepoints
322you're interested in - basically find the tracepoint(s) you're 320you're interested in - basically find the tracepoint(s) you're
323interested in by looking at the list of available events shown by 321interested in by looking at the list of available events shown by
324'perf list' and/or look in /sys/kernel/debug/tracing events for 322'perf list' and/or look in /sys/kernel/debug/tracing/events/ for
325detailed event and field info, record the corresponding trace data 323detailed event and field info, record the corresponding trace data
326using 'perf record', passing it the list of interesting events, 324using 'perf record', passing it the list of interesting events,
327generate a skeleton script using 'perf script -g python' and modify the 325generate a skeleton script using 'perf script -g python' and modify the
@@ -334,7 +332,7 @@ right place, you can have your script listed alongside the other
334scripts listed by the 'perf script -l' command e.g.: 332scripts listed by the 'perf script -l' command e.g.:
335 333
336---- 334----
337root@tropicana:~# perf script -l 335# perf script -l
338List of available trace scripts: 336List of available trace scripts:
339 wakeup-latency system-wide min/max/avg wakeup latency 337 wakeup-latency system-wide min/max/avg wakeup latency
340 rw-by-file <comm> r/w activity for a program, by file 338 rw-by-file <comm> r/w activity for a program, by file
@@ -383,8 +381,6 @@ source tree:
383 381
384---- 382----
385# ls -al kernel-source/tools/perf/scripts/python 383# ls -al kernel-source/tools/perf/scripts/python
386
387root@tropicana:/home/trz/src/tip# ls -al tools/perf/scripts/python
388total 32 384total 32
389drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 . 385drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 .
390drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 .. 386drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 ..
@@ -399,7 +395,7 @@ otherwise your script won't show up at run-time), 'perf script -l'
399should show a new entry for your script: 395should show a new entry for your script:
400 396
401---- 397----
402root@tropicana:~# perf script -l 398# perf script -l
403List of available trace scripts: 399List of available trace scripts:
404 wakeup-latency system-wide min/max/avg wakeup latency 400 wakeup-latency system-wide min/max/avg wakeup latency
405 rw-by-file <comm> r/w activity for a program, by file 401 rw-by-file <comm> r/w activity for a program, by file
@@ -437,7 +433,7 @@ EVENT HANDLERS
437When perf script is invoked using a trace script, a user-defined 433When perf script is invoked using a trace script, a user-defined
438'handler function' is called for each event in the trace. If there's 434'handler function' is called for each event in the trace. If there's
439no handler function defined for a given event type, the event is 435no handler function defined for a given event type, the event is
440ignored (or passed to a 'trace_handled' function, see below) and the 436ignored (or passed to a 'trace_unhandled' function, see below) and the
441next event is processed. 437next event is processed.
442 438
443Most of the event's field values are passed as arguments to the 439Most of the event's field values are passed as arguments to the
@@ -532,7 +528,7 @@ can implement a set of optional functions:
532gives scripts a chance to do setup tasks: 528gives scripts a chance to do setup tasks:
533 529
534---- 530----
535def trace_begin: 531def trace_begin():
536 pass 532 pass
537---- 533----
538 534
@@ -541,7 +537,7 @@ def trace_begin:
541 as display results: 537 as display results:
542 538
543---- 539----
544def trace_end: 540def trace_end():
545 pass 541 pass
546---- 542----
547 543
@@ -550,8 +546,7 @@ def trace_end:
550 of common arguments are passed into it: 546 of common arguments are passed into it:
551 547
552---- 548----
553def trace_unhandled(event_name, context, common_cpu, common_secs, 549def trace_unhandled(event_name, context, event_fields_dict):
554 common_nsecs, common_pid, common_comm):
555 pass 550 pass
556---- 551----
557 552
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index cb0eda3925e6..5ee8796be96e 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -116,8 +116,9 @@ OPTIONS
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
119 srcline, period, iregs, brstack, brstacksym, flags, bpf-output, brstackinsn, 119 srcline, period, iregs, brstack, brstacksym, flags, bpf-output, brstackinsn, brstackoff,
120 callindent, insn, insnlen. Field list can be prepended with the type, trace, sw or hw, 120 callindent, insn, insnlen, synth.
121 Field list can be prepended with the type, trace, sw or hw,
121 to indicate to which event type the field list applies. 122 to indicate to which event type the field list applies.
122 e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace 123 e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace
123 124
@@ -130,6 +131,14 @@ OPTIONS
130 i.e., the specified fields apply to all event types if the type string 131 i.e., the specified fields apply to all event types if the type string
131 is not given. 132 is not given.
132 133
134 In addition to overriding fields, it is also possible to add or remove
135 fields from the defaults. For example
136
137 -F -cpu,+insn
138
139 removes the cpu field and adds the insn field. Adding/removing fields
140 cannot be mixed with normal overriding.
141
133 The arguments are processed in the order received. A later usage can 142 The arguments are processed in the order received. A later usage can
134 reset a prior request. e.g.: 143 reset a prior request. e.g.:
135 144
@@ -185,6 +194,9 @@ OPTIONS
185 instruction bytes and the instruction length of the current 194 instruction bytes and the instruction length of the current
186 instruction. 195 instruction.
187 196
197 The synth field is used by synthesized events which may be created when
198 Instruction Trace decoding.
199
188 Finally, a user may not set fields to none for all event types. 200 Finally, a user may not set fields to none for all event types.
189 i.e., -F "" is not allowed. 201 i.e., -F "" is not allowed.
190 202
@@ -203,6 +215,8 @@ OPTIONS
203 is printed. This is the full execution path leading to the sample. This is only supported when the 215 is printed. This is the full execution path leading to the sample. This is only supported when the
204 sample was recorded with perf record -b or -j any. 216 sample was recorded with perf record -b or -j any.
205 217
218 The brstackoff field will print an offset into a specific dso/binary.
219
206-k:: 220-k::
207--vmlinux=<file>:: 221--vmlinux=<file>::
208 vmlinux pathname 222 vmlinux pathname
@@ -311,6 +325,10 @@ include::itrace.txt[]
311 Set the maximum number of program blocks to print with brstackasm for 325 Set the maximum number of program blocks to print with brstackasm for
312 each sample. 326 each sample.
313 327
328--inline::
329 If a callgraph address belongs to an inlined function, the inline stack
330 will be printed. Each entry has function name and file/line.
331
314SEE ALSO 332SEE ALSO
315-------- 333--------
316linkperf:perf-record[1], linkperf:perf-script-perl[1], 334linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index bd0e4417f2be..698076313606 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -239,6 +239,20 @@ taskset.
239--no-merge:: 239--no-merge::
240Do not merge results from same PMUs. 240Do not merge results from same PMUs.
241 241
242--smi-cost::
243Measure SMI cost if msr/aperf/ and msr/smi/ events are supported.
244
245During the measurement, the /sys/device/cpu/freeze_on_smi will be set to
246freeze core counters on SMI.
247The aperf counter will not be effected by the setting.
248The cost of SMI can be measured by (aperf - unhalted core cycles).
249
250In practice, the percentages of SMI cycles is very useful for performance
251oriented analysis. --metric_only will be applied by default.
252The output is SMI cycles%, equals to (aperf - unhalted core cycles) / aperf
253
254Users who wants to get the actual value can apply --no-metric-only.
255
242EXAMPLES 256EXAMPLES
243-------- 257--------
244 258
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 8354d04b392f..bdf0e87f9b29 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -19,18 +19,18 @@ CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
19 19
20include $(srctree)/tools/scripts/Makefile.arch 20include $(srctree)/tools/scripts/Makefile.arch
21 21
22$(call detected_var,ARCH) 22$(call detected_var,SRCARCH)
23 23
24NO_PERF_REGS := 1 24NO_PERF_REGS := 1
25 25
26# Additional ARCH settings for ppc 26# Additional ARCH settings for ppc
27ifeq ($(ARCH),powerpc) 27ifeq ($(SRCARCH),powerpc)
28 NO_PERF_REGS := 0 28 NO_PERF_REGS := 0
29 LIBUNWIND_LIBS := -lunwind -lunwind-ppc64 29 LIBUNWIND_LIBS := -lunwind -lunwind-ppc64
30endif 30endif
31 31
32# Additional ARCH settings for x86 32# Additional ARCH settings for x86
33ifeq ($(ARCH),x86) 33ifeq ($(SRCARCH),x86)
34 $(call detected,CONFIG_X86) 34 $(call detected,CONFIG_X86)
35 ifeq (${IS_64_BIT}, 1) 35 ifeq (${IS_64_BIT}, 1)
36 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT -DHAVE_SYSCALL_TABLE -I$(OUTPUT)arch/x86/include/generated 36 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT -DHAVE_SYSCALL_TABLE -I$(OUTPUT)arch/x86/include/generated
@@ -43,12 +43,12 @@ ifeq ($(ARCH),x86)
43 NO_PERF_REGS := 0 43 NO_PERF_REGS := 0
44endif 44endif
45 45
46ifeq ($(ARCH),arm) 46ifeq ($(SRCARCH),arm)
47 NO_PERF_REGS := 0 47 NO_PERF_REGS := 0
48 LIBUNWIND_LIBS = -lunwind -lunwind-arm 48 LIBUNWIND_LIBS = -lunwind -lunwind-arm
49endif 49endif
50 50
51ifeq ($(ARCH),arm64) 51ifeq ($(SRCARCH),arm64)
52 NO_PERF_REGS := 0 52 NO_PERF_REGS := 0
53 LIBUNWIND_LIBS = -lunwind -lunwind-aarch64 53 LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
54endif 54endif
@@ -61,7 +61,7 @@ endif
61# Disable it on all other architectures in case libdw unwind 61# Disable it on all other architectures in case libdw unwind
62# support is detected in system. Add supported architectures 62# support is detected in system. Add supported architectures
63# to the check. 63# to the check.
64ifneq ($(ARCH),$(filter $(ARCH),x86 arm)) 64ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm powerpc))
65 NO_LIBDW_DWARF_UNWIND := 1 65 NO_LIBDW_DWARF_UNWIND := 1
66endif 66endif
67 67
@@ -115,9 +115,9 @@ endif
115FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS) 115FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS)
116FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf 116FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
117 117
118FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi 118FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(SRCARCH)/include/uapi -I$(srctree)/tools/include/uapi
119# include ARCH specific config 119# include ARCH specific config
120-include $(src-perf)/arch/$(ARCH)/Makefile 120-include $(src-perf)/arch/$(SRCARCH)/Makefile
121 121
122ifdef PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET 122ifdef PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
123 CFLAGS += -DHAVE_ARCH_REGS_QUERY_REGISTER_OFFSET 123 CFLAGS += -DHAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
@@ -228,12 +228,12 @@ ifeq ($(DEBUG),0)
228endif 228endif
229 229
230INC_FLAGS += -I$(src-perf)/util/include 230INC_FLAGS += -I$(src-perf)/util/include
231INC_FLAGS += -I$(src-perf)/arch/$(ARCH)/include 231INC_FLAGS += -I$(src-perf)/arch/$(SRCARCH)/include
232INC_FLAGS += -I$(srctree)/tools/include/uapi 232INC_FLAGS += -I$(srctree)/tools/include/uapi
233INC_FLAGS += -I$(srctree)/tools/include/ 233INC_FLAGS += -I$(srctree)/tools/include/
234INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi 234INC_FLAGS += -I$(srctree)/tools/arch/$(SRCARCH)/include/uapi
235INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/ 235INC_FLAGS += -I$(srctree)/tools/arch/$(SRCARCH)/include/
236INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/ 236INC_FLAGS += -I$(srctree)/tools/arch/$(SRCARCH)/
237 237
238# $(obj-perf) for generated common-cmds.h 238# $(obj-perf) for generated common-cmds.h
239# $(obj-perf)/util for generated bison/flex headers 239# $(obj-perf)/util for generated bison/flex headers
@@ -355,7 +355,7 @@ ifndef NO_LIBELF
355 355
356 ifndef NO_DWARF 356 ifndef NO_DWARF
357 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 357 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
358 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 358 msg := $(warning DWARF register mappings have not been defined for architecture $(SRCARCH), DWARF support disabled);
359 NO_DWARF := 1 359 NO_DWARF := 1
360 else 360 else
361 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) 361 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
@@ -380,7 +380,7 @@ ifndef NO_LIBELF
380 CFLAGS += -DHAVE_BPF_PROLOGUE 380 CFLAGS += -DHAVE_BPF_PROLOGUE
381 $(call detected,CONFIG_BPF_PROLOGUE) 381 $(call detected,CONFIG_BPF_PROLOGUE)
382 else 382 else
383 msg := $(warning BPF prologue is not supported by architecture $(ARCH), missing regs_query_register_offset()); 383 msg := $(warning BPF prologue is not supported by architecture $(SRCARCH), missing regs_query_register_offset());
384 endif 384 endif
385 else 385 else
386 msg := $(warning DWARF support is off, BPF prologue is disabled); 386 msg := $(warning DWARF support is off, BPF prologue is disabled);
@@ -406,7 +406,7 @@ ifdef PERF_HAVE_JITDUMP
406 endif 406 endif
407endif 407endif
408 408
409ifeq ($(ARCH),powerpc) 409ifeq ($(SRCARCH),powerpc)
410 ifndef NO_DWARF 410 ifndef NO_DWARF
411 CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX 411 CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
412 endif 412 endif
@@ -487,7 +487,7 @@ else
487endif 487endif
488 488
489ifndef NO_LOCAL_LIBUNWIND 489ifndef NO_LOCAL_LIBUNWIND
490 ifeq ($(ARCH),$(filter $(ARCH),arm arm64)) 490 ifeq ($(SRCARCH),$(filter $(SRCARCH),arm arm64))
491 $(call feature_check,libunwind-debug-frame) 491 $(call feature_check,libunwind-debug-frame)
492 ifneq ($(feature-libunwind-debug-frame), 1) 492 ifneq ($(feature-libunwind-debug-frame), 1)
493 msg := $(warning No debug_frame support found in libunwind); 493 msg := $(warning No debug_frame support found in libunwind);
@@ -740,7 +740,7 @@ ifeq (${IS_64_BIT}, 1)
740 NO_PERF_READ_VDSO32 := 1 740 NO_PERF_READ_VDSO32 := 1
741 endif 741 endif
742 endif 742 endif
743 ifneq ($(ARCH), x86) 743 ifneq ($(SRCARCH), x86)
744 NO_PERF_READ_VDSOX32 := 1 744 NO_PERF_READ_VDSOX32 := 1
745 endif 745 endif
746 ifndef NO_PERF_READ_VDSOX32 746 ifndef NO_PERF_READ_VDSOX32
@@ -769,7 +769,7 @@ ifdef LIBBABELTRACE
769endif 769endif
770 770
771ifndef NO_AUXTRACE 771ifndef NO_AUXTRACE
772 ifeq ($(ARCH),x86) 772 ifeq ($(SRCARCH),x86)
773 ifeq ($(feature-get_cpuid), 0) 773 ifeq ($(feature-get_cpuid), 0)
774 msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc); 774 msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc);
775 NO_AUXTRACE := 1 775 NO_AUXTRACE := 1
@@ -872,7 +872,7 @@ sysconfdir = $(prefix)/etc
872ETC_PERFCONFIG = etc/perfconfig 872ETC_PERFCONFIG = etc/perfconfig
873endif 873endif
874ifndef lib 874ifndef lib
875ifeq ($(ARCH)$(IS_64_BIT), x861) 875ifeq ($(SRCARCH)$(IS_64_BIT), x861)
876lib = lib64 876lib = lib64
877else 877else
878lib = lib 878lib = lib
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 79fe31f20a17..5008f51a08a2 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -226,7 +226,7 @@ endif
226 226
227ifeq ($(config),0) 227ifeq ($(config),0)
228include $(srctree)/tools/scripts/Makefile.arch 228include $(srctree)/tools/scripts/Makefile.arch
229-include arch/$(ARCH)/Makefile 229-include arch/$(SRCARCH)/Makefile
230endif 230endif
231 231
232# The FEATURE_DUMP_EXPORT holds location of the actual 232# The FEATURE_DUMP_EXPORT holds location of the actual
diff --git a/tools/perf/arch/Build b/tools/perf/arch/Build
index 109eb75cf7de..d9b6af837c7d 100644
--- a/tools/perf/arch/Build
+++ b/tools/perf/arch/Build
@@ -1,2 +1,2 @@
1libperf-y += common.o 1libperf-y += common.o
2libperf-y += $(ARCH)/ 2libperf-y += $(SRCARCH)/
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
index 29361d9b635a..7ce3d1a25133 100644
--- a/tools/perf/arch/arm/util/cs-etm.c
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -17,6 +17,7 @@
17 17
18#include <api/fs/fs.h> 18#include <api/fs/fs.h>
19#include <linux/bitops.h> 19#include <linux/bitops.h>
20#include <linux/compiler.h>
20#include <linux/coresight-pmu.h> 21#include <linux/coresight-pmu.h>
21#include <linux/kernel.h> 22#include <linux/kernel.h>
22#include <linux/log2.h> 23#include <linux/log2.h>
@@ -202,19 +203,18 @@ static int cs_etm_recording_options(struct auxtrace_record *itr,
202 pr_debug2("%s snapshot size: %zu\n", CORESIGHT_ETM_PMU_NAME, 203 pr_debug2("%s snapshot size: %zu\n", CORESIGHT_ETM_PMU_NAME,
203 opts->auxtrace_snapshot_size); 204 opts->auxtrace_snapshot_size);
204 205
205 if (cs_etm_evsel) { 206 /*
206 /* 207 * To obtain the auxtrace buffer file descriptor, the auxtrace
207 * To obtain the auxtrace buffer file descriptor, the auxtrace 208 * event must come first.
208 * event must come first. 209 */
209 */ 210 perf_evlist__to_front(evlist, cs_etm_evsel);
210 perf_evlist__to_front(evlist, cs_etm_evsel); 211
211 /* 212 /*
212 * In the case of per-cpu mmaps, we need the CPU on the 213 * In the case of per-cpu mmaps, we need the CPU on the
213 * AUX event. 214 * AUX event.
214 */ 215 */
215 if (!cpu_map__empty(cpus)) 216 if (!cpu_map__empty(cpus))
216 perf_evsel__set_sample_bit(cs_etm_evsel, CPU); 217 perf_evsel__set_sample_bit(cs_etm_evsel, CPU);
217 }
218 218
219 /* Add dummy event to keep tracking */ 219 /* Add dummy event to keep tracking */
220 if (opts->full_auxtrace) { 220 if (opts->full_auxtrace) {
@@ -583,8 +583,7 @@ static FILE *cs_device__open_file(const char *name)
583 583
584} 584}
585 585
586static __attribute__((format(printf, 2, 3))) 586static int __printf(2, 3) cs_device__print_file(const char *name, const char *fmt, ...)
587int cs_device__print_file(const char *name, const char *fmt, ...)
588{ 587{
589 va_list args; 588 va_list args;
590 FILE *file; 589 FILE *file;
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index 837067f48a4c..6b40e9f01740 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -26,6 +26,7 @@ const char *const arm64_triplets[] = {
26 26
27const char *const powerpc_triplets[] = { 27const char *const powerpc_triplets[] = {
28 "powerpc-unknown-linux-gnu-", 28 "powerpc-unknown-linux-gnu-",
29 "powerpc-linux-gnu-",
29 "powerpc64-unknown-linux-gnu-", 30 "powerpc64-unknown-linux-gnu-",
30 "powerpc64-linux-gnu-", 31 "powerpc64-linux-gnu-",
31 "powerpc64le-linux-gnu-", 32 "powerpc64le-linux-gnu-",
diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build
index 90ad64b231cd..2e6595310420 100644
--- a/tools/perf/arch/powerpc/util/Build
+++ b/tools/perf/arch/powerpc/util/Build
@@ -5,4 +5,6 @@ libperf-y += perf_regs.o
5 5
6libperf-$(CONFIG_DWARF) += dwarf-regs.o 6libperf-$(CONFIG_DWARF) += dwarf-regs.o
7libperf-$(CONFIG_DWARF) += skip-callchain-idx.o 7libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
8
8libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o 9libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
10libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
diff --git a/tools/perf/arch/powerpc/util/unwind-libdw.c b/tools/perf/arch/powerpc/util/unwind-libdw.c
new file mode 100644
index 000000000000..3a24b3c43273
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/unwind-libdw.c
@@ -0,0 +1,73 @@
1#include <elfutils/libdwfl.h>
2#include "../../util/unwind-libdw.h"
3#include "../../util/perf_regs.h"
4#include "../../util/event.h"
5
6/* See backends/ppc_initreg.c and backends/ppc_regs.c in elfutils. */
7static const int special_regs[3][2] = {
8 { 65, PERF_REG_POWERPC_LINK },
9 { 101, PERF_REG_POWERPC_XER },
10 { 109, PERF_REG_POWERPC_CTR },
11};
12
13bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
14{
15 struct unwind_info *ui = arg;
16 struct regs_dump *user_regs = &ui->sample->user_regs;
17 Dwarf_Word dwarf_regs[32], dwarf_nip;
18 size_t i;
19
20#define REG(r) ({ \
21 Dwarf_Word val = 0; \
22 perf_reg_value(&val, user_regs, PERF_REG_POWERPC_##r); \
23 val; \
24})
25
26 dwarf_regs[0] = REG(R0);
27 dwarf_regs[1] = REG(R1);
28 dwarf_regs[2] = REG(R2);
29 dwarf_regs[3] = REG(R3);
30 dwarf_regs[4] = REG(R4);
31 dwarf_regs[5] = REG(R5);
32 dwarf_regs[6] = REG(R6);
33 dwarf_regs[7] = REG(R7);
34 dwarf_regs[8] = REG(R8);
35 dwarf_regs[9] = REG(R9);
36 dwarf_regs[10] = REG(R10);
37 dwarf_regs[11] = REG(R11);
38 dwarf_regs[12] = REG(R12);
39 dwarf_regs[13] = REG(R13);
40 dwarf_regs[14] = REG(R14);
41 dwarf_regs[15] = REG(R15);
42 dwarf_regs[16] = REG(R16);
43 dwarf_regs[17] = REG(R17);
44 dwarf_regs[18] = REG(R18);
45 dwarf_regs[19] = REG(R19);
46 dwarf_regs[20] = REG(R20);
47 dwarf_regs[21] = REG(R21);
48 dwarf_regs[22] = REG(R22);
49 dwarf_regs[23] = REG(R23);
50 dwarf_regs[24] = REG(R24);
51 dwarf_regs[25] = REG(R25);
52 dwarf_regs[26] = REG(R26);
53 dwarf_regs[27] = REG(R27);
54 dwarf_regs[28] = REG(R28);
55 dwarf_regs[29] = REG(R29);
56 dwarf_regs[30] = REG(R30);
57 dwarf_regs[31] = REG(R31);
58 if (!dwfl_thread_state_registers(thread, 0, 32, dwarf_regs))
59 return false;
60
61 dwarf_nip = REG(NIP);
62 dwfl_thread_state_register_pc(thread, dwarf_nip);
63 for (i = 0; i < ARRAY_SIZE(special_regs); i++) {
64 Dwarf_Word val = 0;
65 perf_reg_value(&val, user_regs, special_regs[i][1]);
66 if (!dwfl_thread_state_registers(thread,
67 special_regs[i][0], 1,
68 &val))
69 return false;
70 }
71
72 return true;
73}
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-32.c b/tools/perf/arch/x86/tests/insn-x86-dat-32.c
index 0f196eec9f48..3cbf6fad169f 100644
--- a/tools/perf/arch/x86/tests/insn-x86-dat-32.c
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-32.c
@@ -1664,3 +1664,15 @@
1664"0f c7 1d 78 56 34 12 \txrstors 0x12345678",}, 1664"0f c7 1d 78 56 34 12 \txrstors 0x12345678",},
1665{{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", 1665{{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
1666"0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%eax,%ecx,8)",}, 1666"0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%eax,%ecx,8)",},
1667{{0xf3, 0x0f, 0xae, 0x20, }, 4, 0, "", "",
1668"f3 0f ae 20 \tptwritel (%eax)",},
1669{{0xf3, 0x0f, 0xae, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
1670"f3 0f ae 25 78 56 34 12 \tptwritel 0x12345678",},
1671{{0xf3, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
1672"f3 0f ae a4 c8 78 56 34 12 \tptwritel 0x12345678(%eax,%ecx,8)",},
1673{{0xf3, 0x0f, 0xae, 0x20, }, 4, 0, "", "",
1674"f3 0f ae 20 \tptwritel (%eax)",},
1675{{0xf3, 0x0f, 0xae, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
1676"f3 0f ae 25 78 56 34 12 \tptwritel 0x12345678",},
1677{{0xf3, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
1678"f3 0f ae a4 c8 78 56 34 12 \tptwritel 0x12345678(%eax,%ecx,8)",},
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-64.c b/tools/perf/arch/x86/tests/insn-x86-dat-64.c
index af25bc8240d0..aa512fa944dd 100644
--- a/tools/perf/arch/x86/tests/insn-x86-dat-64.c
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-64.c
@@ -1696,3 +1696,33 @@
1696"0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%rax,%rcx,8)",}, 1696"0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%rax,%rcx,8)",},
1697{{0x41, 0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", 1697{{0x41, 0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
1698"41 0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%r8,%rcx,8)",}, 1698"41 0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%r8,%rcx,8)",},
1699{{0xf3, 0x0f, 0xae, 0x20, }, 4, 0, "", "",
1700"f3 0f ae 20 \tptwritel (%rax)",},
1701{{0xf3, 0x41, 0x0f, 0xae, 0x20, }, 5, 0, "", "",
1702"f3 41 0f ae 20 \tptwritel (%r8)",},
1703{{0xf3, 0x0f, 0xae, 0x24, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
1704"f3 0f ae 24 25 78 56 34 12 \tptwritel 0x12345678",},
1705{{0xf3, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
1706"f3 0f ae a4 c8 78 56 34 12 \tptwritel 0x12345678(%rax,%rcx,8)",},
1707{{0xf3, 0x41, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "",
1708"f3 41 0f ae a4 c8 78 56 34 12 \tptwritel 0x12345678(%r8,%rcx,8)",},
1709{{0xf3, 0x0f, 0xae, 0x20, }, 4, 0, "", "",
1710"f3 0f ae 20 \tptwritel (%rax)",},
1711{{0xf3, 0x41, 0x0f, 0xae, 0x20, }, 5, 0, "", "",
1712"f3 41 0f ae 20 \tptwritel (%r8)",},
1713{{0xf3, 0x0f, 0xae, 0x24, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
1714"f3 0f ae 24 25 78 56 34 12 \tptwritel 0x12345678",},
1715{{0xf3, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
1716"f3 0f ae a4 c8 78 56 34 12 \tptwritel 0x12345678(%rax,%rcx,8)",},
1717{{0xf3, 0x41, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "",
1718"f3 41 0f ae a4 c8 78 56 34 12 \tptwritel 0x12345678(%r8,%rcx,8)",},
1719{{0xf3, 0x48, 0x0f, 0xae, 0x20, }, 5, 0, "", "",
1720"f3 48 0f ae 20 \tptwriteq (%rax)",},
1721{{0xf3, 0x49, 0x0f, 0xae, 0x20, }, 5, 0, "", "",
1722"f3 49 0f ae 20 \tptwriteq (%r8)",},
1723{{0xf3, 0x48, 0x0f, 0xae, 0x24, 0x25, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "",
1724"f3 48 0f ae 24 25 78 56 34 12 \tptwriteq 0x12345678",},
1725{{0xf3, 0x48, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "",
1726"f3 48 0f ae a4 c8 78 56 34 12 \tptwriteq 0x12345678(%rax,%rcx,8)",},
1727{{0xf3, 0x49, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "",
1728"f3 49 0f ae a4 c8 78 56 34 12 \tptwriteq 0x12345678(%r8,%rcx,8)",},
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-src.c b/tools/perf/arch/x86/tests/insn-x86-dat-src.c
index 979487dae8d4..6cdb65d25b79 100644
--- a/tools/perf/arch/x86/tests/insn-x86-dat-src.c
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-src.c
@@ -1343,6 +1343,26 @@ int main(void)
1343 asm volatile("xrstors 0x12345678(%rax,%rcx,8)"); 1343 asm volatile("xrstors 0x12345678(%rax,%rcx,8)");
1344 asm volatile("xrstors 0x12345678(%r8,%rcx,8)"); 1344 asm volatile("xrstors 0x12345678(%r8,%rcx,8)");
1345 1345
1346 /* ptwrite */
1347
1348 asm volatile("ptwrite (%rax)");
1349 asm volatile("ptwrite (%r8)");
1350 asm volatile("ptwrite (0x12345678)");
1351 asm volatile("ptwrite 0x12345678(%rax,%rcx,8)");
1352 asm volatile("ptwrite 0x12345678(%r8,%rcx,8)");
1353
1354 asm volatile("ptwritel (%rax)");
1355 asm volatile("ptwritel (%r8)");
1356 asm volatile("ptwritel (0x12345678)");
1357 asm volatile("ptwritel 0x12345678(%rax,%rcx,8)");
1358 asm volatile("ptwritel 0x12345678(%r8,%rcx,8)");
1359
1360 asm volatile("ptwriteq (%rax)");
1361 asm volatile("ptwriteq (%r8)");
1362 asm volatile("ptwriteq (0x12345678)");
1363 asm volatile("ptwriteq 0x12345678(%rax,%rcx,8)");
1364 asm volatile("ptwriteq 0x12345678(%r8,%rcx,8)");
1365
1346#else /* #ifdef __x86_64__ */ 1366#else /* #ifdef __x86_64__ */
1347 1367
1348 /* bound r32, mem (same op code as EVEX prefix) */ 1368 /* bound r32, mem (same op code as EVEX prefix) */
@@ -2653,6 +2673,16 @@ int main(void)
2653 asm volatile("xrstors (0x12345678)"); 2673 asm volatile("xrstors (0x12345678)");
2654 asm volatile("xrstors 0x12345678(%eax,%ecx,8)"); 2674 asm volatile("xrstors 0x12345678(%eax,%ecx,8)");
2655 2675
2676 /* ptwrite */
2677
2678 asm volatile("ptwrite (%eax)");
2679 asm volatile("ptwrite (0x12345678)");
2680 asm volatile("ptwrite 0x12345678(%eax,%ecx,8)");
2681
2682 asm volatile("ptwritel (%eax)");
2683 asm volatile("ptwritel (0x12345678)");
2684 asm volatile("ptwritel 0x12345678(%eax,%ecx,8)");
2685
2656#endif /* #ifndef __x86_64__ */ 2686#endif /* #ifndef __x86_64__ */
2657 2687
2658 /* Following line is a marker for the awk script - do not change */ 2688 /* Following line is a marker for the awk script - do not change */
diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c
index af2bce7a2cd6..781df40b2966 100644
--- a/tools/perf/arch/x86/util/intel-bts.c
+++ b/tools/perf/arch/x86/util/intel-bts.c
@@ -35,10 +35,6 @@
35#define KiB_MASK(x) (KiB(x) - 1) 35#define KiB_MASK(x) (KiB(x) - 1)
36#define MiB_MASK(x) (MiB(x) - 1) 36#define MiB_MASK(x) (MiB(x) - 1)
37 37
38#define INTEL_BTS_DFLT_SAMPLE_SIZE KiB(4)
39
40#define INTEL_BTS_MAX_SAMPLE_SIZE KiB(60)
41
42struct intel_bts_snapshot_ref { 38struct intel_bts_snapshot_ref {
43 void *ref_buf; 39 void *ref_buf;
44 size_t ref_offset; 40 size_t ref_offset;
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index f630de0206a1..9535be57033f 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -40,10 +40,6 @@
40#define KiB_MASK(x) (KiB(x) - 1) 40#define KiB_MASK(x) (KiB(x) - 1)
41#define MiB_MASK(x) (MiB(x) - 1) 41#define MiB_MASK(x) (MiB(x) - 1)
42 42
43#define INTEL_PT_DEFAULT_SAMPLE_SIZE KiB(4)
44
45#define INTEL_PT_MAX_SAMPLE_SIZE KiB(60)
46
47#define INTEL_PT_PSB_PERIOD_NEAR 256 43#define INTEL_PT_PSB_PERIOD_NEAR 256
48 44
49struct intel_pt_snapshot_ref { 45struct intel_pt_snapshot_ref {
@@ -196,6 +192,7 @@ static u64 intel_pt_default_config(struct perf_pmu *intel_pt_pmu)
196 int psb_cyc, psb_periods, psb_period; 192 int psb_cyc, psb_periods, psb_period;
197 int pos = 0; 193 int pos = 0;
198 u64 config; 194 u64 config;
195 char c;
199 196
200 pos += scnprintf(buf + pos, sizeof(buf) - pos, "tsc"); 197 pos += scnprintf(buf + pos, sizeof(buf) - pos, "tsc");
201 198
@@ -229,6 +226,10 @@ static u64 intel_pt_default_config(struct perf_pmu *intel_pt_pmu)
229 } 226 }
230 } 227 }
231 228
229 if (perf_pmu__scan_file(intel_pt_pmu, "format/pt", "%c", &c) == 1 &&
230 perf_pmu__scan_file(intel_pt_pmu, "format/branch", "%c", &c) == 1)
231 pos += scnprintf(buf + pos, sizeof(buf) - pos, ",pt,branch");
232
232 pr_debug2("%s default config: %s\n", intel_pt_pmu->name, buf); 233 pr_debug2("%s default config: %s\n", intel_pt_pmu->name, buf);
233 234
234 intel_pt_parse_terms(&intel_pt_pmu->format, buf, &config); 235 intel_pt_parse_terms(&intel_pt_pmu->format, buf, &config);
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 27de0c8c5c19..469d65b21122 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -700,7 +700,7 @@ static inline uint32_t lfsr_32(uint32_t lfsr)
700 * kernel (KSM, zero page, etc.) cannot optimize away RAM 700 * kernel (KSM, zero page, etc.) cannot optimize away RAM
701 * accesses: 701 * accesses:
702 */ 702 */
703static inline u64 access_data(u64 *data __attribute__((unused)), u64 val) 703static inline u64 access_data(u64 *data, u64 val)
704{ 704{
705 if (g->p.data_reads) 705 if (g->p.data_reads)
706 val += *data; 706 val += *data;
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 620a467ee304..475999e48f66 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -1725,10 +1725,10 @@ static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name)
1725 tok; tok = strtok_r(NULL, ", ", &tmp)) { \ 1725 tok; tok = strtok_r(NULL, ", ", &tmp)) { \
1726 ret = _fn(hpp_list, tok); \ 1726 ret = _fn(hpp_list, tok); \
1727 if (ret == -EINVAL) { \ 1727 if (ret == -EINVAL) { \
1728 error("Invalid --fields key: `%s'", tok); \ 1728 pr_err("Invalid --fields key: `%s'", tok); \
1729 break; \ 1729 break; \
1730 } else if (ret == -ESRCH) { \ 1730 } else if (ret == -ESRCH) { \
1731 error("Unknown --fields key: `%s'", tok); \ 1731 pr_err("Unknown --fields key: `%s'", tok); \
1732 break; \ 1732 break; \
1733 } \ 1733 } \
1734 } \ 1734 } \
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index 80668fa7556e..ece45582a48d 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -156,7 +156,7 @@ static int parse_config_arg(char *arg, char **var, char **value)
156 156
157int cmd_config(int argc, const char **argv) 157int cmd_config(int argc, const char **argv)
158{ 158{
159 int i, ret = 0; 159 int i, ret = -1;
160 struct perf_config_set *set; 160 struct perf_config_set *set;
161 char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); 161 char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
162 const char *config_filename; 162 const char *config_filename;
@@ -186,10 +186,8 @@ int cmd_config(int argc, const char **argv)
186 * because of reinitializing with options config file location. 186 * because of reinitializing with options config file location.
187 */ 187 */
188 set = perf_config_set__new(); 188 set = perf_config_set__new();
189 if (!set) { 189 if (!set)
190 ret = -1;
191 goto out_err; 190 goto out_err;
192 }
193 191
194 switch (actions) { 192 switch (actions) {
195 case ACTION_LIST: 193 case ACTION_LIST:
@@ -197,41 +195,54 @@ int cmd_config(int argc, const char **argv)
197 pr_err("Error: takes no arguments\n"); 195 pr_err("Error: takes no arguments\n");
198 parse_options_usage(config_usage, config_options, "l", 1); 196 parse_options_usage(config_usage, config_options, "l", 1);
199 } else { 197 } else {
200 ret = show_config(set); 198 if (show_config(set) < 0) {
201 if (ret < 0)
202 pr_err("Nothing configured, " 199 pr_err("Nothing configured, "
203 "please check your %s \n", config_filename); 200 "please check your %s \n", config_filename);
201 goto out_err;
202 }
204 } 203 }
205 break; 204 break;
206 default: 205 default:
207 if (argc) { 206 if (!argc) {
208 for (i = 0; argv[i]; i++) { 207 usage_with_options(config_usage, config_options);
209 char *var, *value; 208 break;
210 char *arg = strdup(argv[i]); 209 }
211
212 if (!arg) {
213 pr_err("%s: strdup failed\n", __func__);
214 ret = -1;
215 break;
216 }
217 210
218 if (parse_config_arg(arg, &var, &value) < 0) { 211 for (i = 0; argv[i]; i++) {
219 free(arg); 212 char *var, *value;
220 ret = -1; 213 char *arg = strdup(argv[i]);
221 break; 214
222 } 215 if (!arg) {
216 pr_err("%s: strdup failed\n", __func__);
217 goto out_err;
218 }
223 219
224 if (value == NULL) 220 if (parse_config_arg(arg, &var, &value) < 0) {
225 ret = show_spec_config(set, var);
226 else
227 ret = set_config(set, config_filename, var, value);
228 free(arg); 221 free(arg);
222 goto out_err;
229 } 223 }
230 } else 224
231 usage_with_options(config_usage, config_options); 225 if (value == NULL) {
226 if (show_spec_config(set, var) < 0) {
227 pr_err("%s is not configured: %s\n",
228 var, config_filename);
229 free(arg);
230 goto out_err;
231 }
232 } else {
233 if (set_config(set, config_filename, var, value) < 0) {
234 pr_err("Failed to set '%s=%s' on %s\n",
235 var, value, config_filename);
236 free(arg);
237 goto out_err;
238 }
239 }
240 free(arg);
241 }
232 } 242 }
233 243
234 perf_config_set__delete(set); 244 ret = 0;
235out_err: 245out_err:
246 perf_config_set__delete(set);
236 return ret; 247 return ret;
237} 248}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index eec5df80f5a3..0cd4cf6a344b 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -1302,7 +1302,10 @@ static int diff__config(const char *var, const char *value,
1302 void *cb __maybe_unused) 1302 void *cb __maybe_unused)
1303{ 1303{
1304 if (!strcmp(var, "diff.order")) { 1304 if (!strcmp(var, "diff.order")) {
1305 sort_compute = perf_config_int(var, value); 1305 int ret;
1306 if (perf_config_int(&ret, var, value) < 0)
1307 return -1;
1308 sort_compute = ret;
1306 return 0; 1309 return 0;
1307 } 1310 }
1308 if (!strcmp(var, "diff.compute")) { 1311 if (!strcmp(var, "diff.compute")) {
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 9e0b35cd0eea..dd26c62c9893 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -28,9 +28,19 @@
28#define DEFAULT_TRACER "function_graph" 28#define DEFAULT_TRACER "function_graph"
29 29
30struct perf_ftrace { 30struct perf_ftrace {
31 struct perf_evlist *evlist; 31 struct perf_evlist *evlist;
32 struct target target; 32 struct target target;
33 const char *tracer; 33 const char *tracer;
34 struct list_head filters;
35 struct list_head notrace;
36 struct list_head graph_funcs;
37 struct list_head nograph_funcs;
38 int graph_depth;
39};
40
41struct filter_entry {
42 struct list_head list;
43 char name[];
34}; 44};
35 45
36static bool done; 46static bool done;
@@ -61,6 +71,7 @@ static int __write_tracing_file(const char *name, const char *val, bool append)
61 int fd, ret = -1; 71 int fd, ret = -1;
62 ssize_t size = strlen(val); 72 ssize_t size = strlen(val);
63 int flags = O_WRONLY; 73 int flags = O_WRONLY;
74 char errbuf[512];
64 75
65 file = get_tracing_file(name); 76 file = get_tracing_file(name);
66 if (!file) { 77 if (!file) {
@@ -75,14 +86,16 @@ static int __write_tracing_file(const char *name, const char *val, bool append)
75 86
76 fd = open(file, flags); 87 fd = open(file, flags);
77 if (fd < 0) { 88 if (fd < 0) {
78 pr_debug("cannot open tracing file: %s\n", name); 89 pr_debug("cannot open tracing file: %s: %s\n",
90 name, str_error_r(errno, errbuf, sizeof(errbuf)));
79 goto out; 91 goto out;
80 } 92 }
81 93
82 if (write(fd, val, size) == size) 94 if (write(fd, val, size) == size)
83 ret = 0; 95 ret = 0;
84 else 96 else
85 pr_debug("write '%s' to tracing/%s failed\n", val, name); 97 pr_debug("write '%s' to tracing/%s failed: %s\n",
98 val, name, str_error_r(errno, errbuf, sizeof(errbuf)));
86 99
87 close(fd); 100 close(fd);
88out: 101out:
@@ -101,6 +114,7 @@ static int append_tracing_file(const char *name, const char *val)
101} 114}
102 115
103static int reset_tracing_cpu(void); 116static int reset_tracing_cpu(void);
117static void reset_tracing_filters(void);
104 118
105static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused) 119static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
106{ 120{
@@ -116,6 +130,10 @@ static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
116 if (reset_tracing_cpu() < 0) 130 if (reset_tracing_cpu() < 0)
117 return -1; 131 return -1;
118 132
133 if (write_tracing_file("max_graph_depth", "0") < 0)
134 return -1;
135
136 reset_tracing_filters();
119 return 0; 137 return 0;
120} 138}
121 139
@@ -181,6 +199,68 @@ static int reset_tracing_cpu(void)
181 return ret; 199 return ret;
182} 200}
183 201
202static int __set_tracing_filter(const char *filter_file, struct list_head *funcs)
203{
204 struct filter_entry *pos;
205
206 list_for_each_entry(pos, funcs, list) {
207 if (append_tracing_file(filter_file, pos->name) < 0)
208 return -1;
209 }
210
211 return 0;
212}
213
214static int set_tracing_filters(struct perf_ftrace *ftrace)
215{
216 int ret;
217
218 ret = __set_tracing_filter("set_ftrace_filter", &ftrace->filters);
219 if (ret < 0)
220 return ret;
221
222 ret = __set_tracing_filter("set_ftrace_notrace", &ftrace->notrace);
223 if (ret < 0)
224 return ret;
225
226 ret = __set_tracing_filter("set_graph_function", &ftrace->graph_funcs);
227 if (ret < 0)
228 return ret;
229
230 /* old kernels do not have this filter */
231 __set_tracing_filter("set_graph_notrace", &ftrace->nograph_funcs);
232
233 return ret;
234}
235
236static void reset_tracing_filters(void)
237{
238 write_tracing_file("set_ftrace_filter", " ");
239 write_tracing_file("set_ftrace_notrace", " ");
240 write_tracing_file("set_graph_function", " ");
241 write_tracing_file("set_graph_notrace", " ");
242}
243
244static int set_tracing_depth(struct perf_ftrace *ftrace)
245{
246 char buf[16];
247
248 if (ftrace->graph_depth == 0)
249 return 0;
250
251 if (ftrace->graph_depth < 0) {
252 pr_err("invalid graph depth: %d\n", ftrace->graph_depth);
253 return -1;
254 }
255
256 snprintf(buf, sizeof(buf), "%d", ftrace->graph_depth);
257
258 if (write_tracing_file("max_graph_depth", buf) < 0)
259 return -1;
260
261 return 0;
262}
263
184static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv) 264static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
185{ 265{
186 char *trace_file; 266 char *trace_file;
@@ -223,11 +303,23 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
223 goto out_reset; 303 goto out_reset;
224 } 304 }
225 305
306 if (set_tracing_filters(ftrace) < 0) {
307 pr_err("failed to set tracing filters\n");
308 goto out_reset;
309 }
310
311 if (set_tracing_depth(ftrace) < 0) {
312 pr_err("failed to set graph depth\n");
313 goto out_reset;
314 }
315
226 if (write_tracing_file("current_tracer", ftrace->tracer) < 0) { 316 if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
227 pr_err("failed to set current_tracer to %s\n", ftrace->tracer); 317 pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
228 goto out_reset; 318 goto out_reset;
229 } 319 }
230 320
321 setup_pager();
322
231 trace_file = get_tracing_file("trace_pipe"); 323 trace_file = get_tracing_file("trace_pipe");
232 if (!trace_file) { 324 if (!trace_file) {
233 pr_err("failed to open trace_pipe\n"); 325 pr_err("failed to open trace_pipe\n");
@@ -251,8 +343,6 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
251 goto out_close_fd; 343 goto out_close_fd;
252 } 344 }
253 345
254 setup_pager();
255
256 perf_evlist__start_workload(ftrace->evlist); 346 perf_evlist__start_workload(ftrace->evlist);
257 347
258 while (!done) { 348 while (!done) {
@@ -307,6 +397,32 @@ static int perf_ftrace_config(const char *var, const char *value, void *cb)
307 return -1; 397 return -1;
308} 398}
309 399
400static int parse_filter_func(const struct option *opt, const char *str,
401 int unset __maybe_unused)
402{
403 struct list_head *head = opt->value;
404 struct filter_entry *entry;
405
406 entry = malloc(sizeof(*entry) + strlen(str) + 1);
407 if (entry == NULL)
408 return -ENOMEM;
409
410 strcpy(entry->name, str);
411 list_add_tail(&entry->list, head);
412
413 return 0;
414}
415
416static void delete_filter_func(struct list_head *head)
417{
418 struct filter_entry *pos, *tmp;
419
420 list_for_each_entry_safe(pos, tmp, head, list) {
421 list_del(&pos->list);
422 free(pos);
423 }
424}
425
310int cmd_ftrace(int argc, const char **argv) 426int cmd_ftrace(int argc, const char **argv)
311{ 427{
312 int ret; 428 int ret;
@@ -330,9 +446,24 @@ int cmd_ftrace(int argc, const char **argv)
330 "system-wide collection from all CPUs"), 446 "system-wide collection from all CPUs"),
331 OPT_STRING('C', "cpu", &ftrace.target.cpu_list, "cpu", 447 OPT_STRING('C', "cpu", &ftrace.target.cpu_list, "cpu",
332 "list of cpus to monitor"), 448 "list of cpus to monitor"),
449 OPT_CALLBACK('T', "trace-funcs", &ftrace.filters, "func",
450 "trace given functions only", parse_filter_func),
451 OPT_CALLBACK('N', "notrace-funcs", &ftrace.notrace, "func",
452 "do not trace given functions", parse_filter_func),
453 OPT_CALLBACK('G', "graph-funcs", &ftrace.graph_funcs, "func",
454 "Set graph filter on given functions", parse_filter_func),
455 OPT_CALLBACK('g', "nograph-funcs", &ftrace.nograph_funcs, "func",
456 "Set nograph filter on given functions", parse_filter_func),
457 OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
458 "Max depth for function graph tracer"),
333 OPT_END() 459 OPT_END()
334 }; 460 };
335 461
462 INIT_LIST_HEAD(&ftrace.filters);
463 INIT_LIST_HEAD(&ftrace.notrace);
464 INIT_LIST_HEAD(&ftrace.graph_funcs);
465 INIT_LIST_HEAD(&ftrace.nograph_funcs);
466
336 ret = perf_config(perf_ftrace_config, &ftrace); 467 ret = perf_config(perf_ftrace_config, &ftrace);
337 if (ret < 0) 468 if (ret < 0)
338 return -1; 469 return -1;
@@ -348,12 +479,14 @@ int cmd_ftrace(int argc, const char **argv)
348 479
349 target__strerror(&ftrace.target, ret, errbuf, 512); 480 target__strerror(&ftrace.target, ret, errbuf, 512);
350 pr_err("%s\n", errbuf); 481 pr_err("%s\n", errbuf);
351 return -EINVAL; 482 goto out_delete_filters;
352 } 483 }
353 484
354 ftrace.evlist = perf_evlist__new(); 485 ftrace.evlist = perf_evlist__new();
355 if (ftrace.evlist == NULL) 486 if (ftrace.evlist == NULL) {
356 return -ENOMEM; 487 ret = -ENOMEM;
488 goto out_delete_filters;
489 }
357 490
358 ret = perf_evlist__create_maps(ftrace.evlist, &ftrace.target); 491 ret = perf_evlist__create_maps(ftrace.evlist, &ftrace.target);
359 if (ret < 0) 492 if (ret < 0)
@@ -364,5 +497,11 @@ int cmd_ftrace(int argc, const char **argv)
364out_delete_evlist: 497out_delete_evlist:
365 perf_evlist__delete(ftrace.evlist); 498 perf_evlist__delete(ftrace.evlist);
366 499
500out_delete_filters:
501 delete_filter_func(&ftrace.filters);
502 delete_filter_func(&ftrace.notrace);
503 delete_filter_func(&ftrace.graph_funcs);
504 delete_filter_func(&ftrace.nograph_funcs);
505
367 return ret; 506 return ret;
368} 507}
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 492f8e14ab09..530a7f2fa0f3 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -108,10 +108,14 @@ out:
108 return ret; 108 return ret;
109} 109}
110 110
111static void exec_woman_emacs(const char *path, const char *page) 111static void exec_failed(const char *cmd)
112{ 112{
113 char sbuf[STRERR_BUFSIZE]; 113 char sbuf[STRERR_BUFSIZE];
114 pr_warning("failed to exec '%s': %s", cmd, str_error_r(errno, sbuf, sizeof(sbuf)));
115}
114 116
117static void exec_woman_emacs(const char *path, const char *page)
118{
115 if (!check_emacsclient_version()) { 119 if (!check_emacsclient_version()) {
116 /* This works only with emacsclient version >= 22. */ 120 /* This works only with emacsclient version >= 22. */
117 char *man_page; 121 char *man_page;
@@ -122,8 +126,7 @@ static void exec_woman_emacs(const char *path, const char *page)
122 execlp(path, "emacsclient", "-e", man_page, NULL); 126 execlp(path, "emacsclient", "-e", man_page, NULL);
123 free(man_page); 127 free(man_page);
124 } 128 }
125 warning("failed to exec '%s': %s", path, 129 exec_failed(path);
126 str_error_r(errno, sbuf, sizeof(sbuf)));
127 } 130 }
128} 131}
129 132
@@ -134,7 +137,6 @@ static void exec_man_konqueror(const char *path, const char *page)
134 if (display && *display) { 137 if (display && *display) {
135 char *man_page; 138 char *man_page;
136 const char *filename = "kfmclient"; 139 const char *filename = "kfmclient";
137 char sbuf[STRERR_BUFSIZE];
138 140
139 /* It's simpler to launch konqueror using kfmclient. */ 141 /* It's simpler to launch konqueror using kfmclient. */
140 if (path) { 142 if (path) {
@@ -155,33 +157,27 @@ static void exec_man_konqueror(const char *path, const char *page)
155 execlp(path, filename, "newTab", man_page, NULL); 157 execlp(path, filename, "newTab", man_page, NULL);
156 free(man_page); 158 free(man_page);
157 } 159 }
158 warning("failed to exec '%s': %s", path, 160 exec_failed(path);
159 str_error_r(errno, sbuf, sizeof(sbuf)));
160 } 161 }
161} 162}
162 163
163static void exec_man_man(const char *path, const char *page) 164static void exec_man_man(const char *path, const char *page)
164{ 165{
165 char sbuf[STRERR_BUFSIZE];
166
167 if (!path) 166 if (!path)
168 path = "man"; 167 path = "man";
169 execlp(path, "man", page, NULL); 168 execlp(path, "man", page, NULL);
170 warning("failed to exec '%s': %s", path, 169 exec_failed(path);
171 str_error_r(errno, sbuf, sizeof(sbuf)));
172} 170}
173 171
174static void exec_man_cmd(const char *cmd, const char *page) 172static void exec_man_cmd(const char *cmd, const char *page)
175{ 173{
176 char sbuf[STRERR_BUFSIZE];
177 char *shell_cmd; 174 char *shell_cmd;
178 175
179 if (asprintf(&shell_cmd, "%s %s", cmd, page) > 0) { 176 if (asprintf(&shell_cmd, "%s %s", cmd, page) > 0) {
180 execl("/bin/sh", "sh", "-c", shell_cmd, NULL); 177 execl("/bin/sh", "sh", "-c", shell_cmd, NULL);
181 free(shell_cmd); 178 free(shell_cmd);
182 } 179 }
183 warning("failed to exec '%s': %s", cmd, 180 exec_failed(cmd);
184 str_error_r(errno, sbuf, sizeof(sbuf)));
185} 181}
186 182
187static void add_man_viewer(const char *name) 183static void add_man_viewer(const char *name)
@@ -214,6 +210,12 @@ static void do_add_man_viewer_info(const char *name,
214 man_viewer_info_list = new; 210 man_viewer_info_list = new;
215} 211}
216 212
213static void unsupported_man_viewer(const char *name, const char *var)
214{
215 pr_warning("'%s': path for unsupported man viewer.\n"
216 "Please consider using 'man.<tool>.%s' instead.", name, var);
217}
218
217static int add_man_viewer_path(const char *name, 219static int add_man_viewer_path(const char *name,
218 size_t len, 220 size_t len,
219 const char *value) 221 const char *value)
@@ -221,9 +223,7 @@ static int add_man_viewer_path(const char *name,
221 if (supported_man_viewer(name, len)) 223 if (supported_man_viewer(name, len))
222 do_add_man_viewer_info(name, len, value); 224 do_add_man_viewer_info(name, len, value);
223 else 225 else
224 warning("'%s': path for unsupported man viewer.\n" 226 unsupported_man_viewer(name, "cmd");
225 "Please consider using 'man.<tool>.cmd' instead.",
226 name);
227 227
228 return 0; 228 return 0;
229} 229}
@@ -233,9 +233,7 @@ static int add_man_viewer_cmd(const char *name,
233 const char *value) 233 const char *value)
234{ 234{
235 if (supported_man_viewer(name, len)) 235 if (supported_man_viewer(name, len))
236 warning("'%s': cmd for supported man viewer.\n" 236 unsupported_man_viewer(name, "path");
237 "Please consider using 'man.<tool>.path' instead.",
238 name);
239 else 237 else
240 do_add_man_viewer_info(name, len, value); 238 do_add_man_viewer_info(name, len, value);
241 239
@@ -247,8 +245,10 @@ static int add_man_viewer_info(const char *var, const char *value)
247 const char *name = var + 4; 245 const char *name = var + 4;
248 const char *subkey = strrchr(name, '.'); 246 const char *subkey = strrchr(name, '.');
249 247
250 if (!subkey) 248 if (!subkey) {
251 return error("Config with no key for man viewer: %s", name); 249 pr_err("Config with no key for man viewer: %s", name);
250 return -1;
251 }
252 252
253 if (!strcmp(subkey, ".path")) { 253 if (!strcmp(subkey, ".path")) {
254 if (!value) 254 if (!value)
@@ -261,7 +261,7 @@ static int add_man_viewer_info(const char *var, const char *value)
261 return add_man_viewer_cmd(name, subkey - name, value); 261 return add_man_viewer_cmd(name, subkey - name, value);
262 } 262 }
263 263
264 warning("'%s': unsupported man viewer sub key.", subkey); 264 pr_warning("'%s': unsupported man viewer sub key.", subkey);
265 return 0; 265 return 0;
266} 266}
267 267
@@ -332,7 +332,7 @@ static void setup_man_path(void)
332 setenv("MANPATH", new_path, 1); 332 setenv("MANPATH", new_path, 1);
333 free(new_path); 333 free(new_path);
334 } else { 334 } else {
335 error("Unable to setup man path"); 335 pr_err("Unable to setup man path");
336 } 336 }
337} 337}
338 338
@@ -349,7 +349,7 @@ static void exec_viewer(const char *name, const char *page)
349 else if (info) 349 else if (info)
350 exec_man_cmd(info, page); 350 exec_man_cmd(info, page);
351 else 351 else
352 warning("'%s': unknown man viewer.", name); 352 pr_warning("'%s': unknown man viewer.", name);
353} 353}
354 354
355static int show_man_page(const char *perf_cmd) 355static int show_man_page(const char *perf_cmd)
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 9409c9464667..0a8a1c45af87 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1715,7 +1715,7 @@ static int setup_slab_sorting(struct list_head *sort_list, const char *arg)
1715 if (!tok) 1715 if (!tok)
1716 break; 1716 break;
1717 if (slab_sort_dimension__add(tok, sort_list) < 0) { 1717 if (slab_sort_dimension__add(tok, sort_list) < 0) {
1718 error("Unknown slab --sort key: '%s'", tok); 1718 pr_err("Unknown slab --sort key: '%s'", tok);
1719 free(str); 1719 free(str);
1720 return -1; 1720 return -1;
1721 } 1721 }
@@ -1741,7 +1741,7 @@ static int setup_page_sorting(struct list_head *sort_list, const char *arg)
1741 if (!tok) 1741 if (!tok)
1742 break; 1742 break;
1743 if (page_sort_dimension__add(tok, sort_list) < 0) { 1743 if (page_sort_dimension__add(tok, sort_list) < 0) {
1744 error("Unknown page --sort key: '%s'", tok); 1744 pr_err("Unknown page --sort key: '%s'", tok);
1745 free(str); 1745 free(str);
1746 return -1; 1746 return -1;
1747 } 1747 }
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index ee7d0a82ccd0..17a14bcce34a 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -453,7 +453,7 @@ try_again:
453 } 453 }
454 454
455 if (perf_evlist__apply_filters(evlist, &pos)) { 455 if (perf_evlist__apply_filters(evlist, &pos)) {
456 error("failed to set filter \"%s\" on event %s with %d (%s)\n", 456 pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
457 pos->filter, perf_evsel__name(pos), errno, 457 pos->filter, perf_evsel__name(pos), errno,
458 str_error_r(errno, msg, sizeof(msg))); 458 str_error_r(errno, msg, sizeof(msg)));
459 rc = -1; 459 rc = -1;
@@ -461,7 +461,7 @@ try_again:
461 } 461 }
462 462
463 if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) { 463 if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) {
464 error("failed to set config \"%s\" on event %s with %d (%s)\n", 464 pr_err("failed to set config \"%s\" on event %s with %d (%s)\n",
465 err_term->val.drv_cfg, perf_evsel__name(pos), errno, 465 err_term->val.drv_cfg, perf_evsel__name(pos), errno,
466 str_error_r(errno, msg, sizeof(msg))); 466 str_error_r(errno, msg, sizeof(msg)));
467 rc = -1; 467 rc = -1;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 22478ff2b706..79a33eb1a10d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -94,10 +94,9 @@ static int report__config(const char *var, const char *value, void *cb)
94 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 94 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
95 return 0; 95 return 0;
96 } 96 }
97 if (!strcmp(var, "report.queue-size")) { 97 if (!strcmp(var, "report.queue-size"))
98 rep->queue_size = perf_config_u64(var, value); 98 return perf_config_u64(&rep->queue_size, var, value);
99 return 0; 99
100 }
101 if (!strcmp(var, "report.sort_order")) { 100 if (!strcmp(var, "report.sort_order")) {
102 default_sort_order = strdup(value); 101 default_sort_order = strdup(value);
103 return 0; 102 return 0;
@@ -558,6 +557,7 @@ static int __cmd_report(struct report *rep)
558 ui__error("failed to set cpu bitmap\n"); 557 ui__error("failed to set cpu bitmap\n");
559 return ret; 558 return ret;
560 } 559 }
560 session->itrace_synth_opts->cpu_bitmap = rep->cpu_bitmap;
561 } 561 }
562 562
563 if (rep->show_threads) { 563 if (rep->show_threads) {
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 39996c53995a..322b4def8411 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -2066,7 +2066,7 @@ static void save_task_callchain(struct perf_sched *sched,
2066 if (thread__resolve_callchain(thread, cursor, evsel, sample, 2066 if (thread__resolve_callchain(thread, cursor, evsel, sample,
2067 NULL, NULL, sched->max_stack + 2) != 0) { 2067 NULL, NULL, sched->max_stack + 2) != 0) {
2068 if (verbose > 0) 2068 if (verbose > 0)
2069 error("Failed to resolve callchain. Skipping\n"); 2069 pr_err("Failed to resolve callchain. Skipping\n");
2070 2070
2071 return; 2071 return;
2072 } 2072 }
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index d05aec491cff..83cdc0a61fd6 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -85,6 +85,8 @@ enum perf_output_field {
85 PERF_OUTPUT_INSN = 1U << 21, 85 PERF_OUTPUT_INSN = 1U << 21,
86 PERF_OUTPUT_INSNLEN = 1U << 22, 86 PERF_OUTPUT_INSNLEN = 1U << 22,
87 PERF_OUTPUT_BRSTACKINSN = 1U << 23, 87 PERF_OUTPUT_BRSTACKINSN = 1U << 23,
88 PERF_OUTPUT_BRSTACKOFF = 1U << 24,
89 PERF_OUTPUT_SYNTH = 1U << 25,
88}; 90};
89 91
90struct output_option { 92struct output_option {
@@ -115,6 +117,13 @@ struct output_option {
115 {.str = "insn", .field = PERF_OUTPUT_INSN}, 117 {.str = "insn", .field = PERF_OUTPUT_INSN},
116 {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN}, 118 {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},
117 {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN}, 119 {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},
120 {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF},
121 {.str = "synth", .field = PERF_OUTPUT_SYNTH},
122};
123
124enum {
125 OUTPUT_TYPE_SYNTH = PERF_TYPE_MAX,
126 OUTPUT_TYPE_MAX
118}; 127};
119 128
120/* default set to maintain compatibility with current format */ 129/* default set to maintain compatibility with current format */
@@ -124,7 +133,7 @@ static struct {
124 unsigned int print_ip_opts; 133 unsigned int print_ip_opts;
125 u64 fields; 134 u64 fields;
126 u64 invalid_fields; 135 u64 invalid_fields;
127} output[PERF_TYPE_MAX] = { 136} output[OUTPUT_TYPE_MAX] = {
128 137
129 [PERF_TYPE_HARDWARE] = { 138 [PERF_TYPE_HARDWARE] = {
130 .user_set = false, 139 .user_set = false,
@@ -182,12 +191,44 @@ static struct {
182 191
183 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, 192 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
184 }, 193 },
194
195 [OUTPUT_TYPE_SYNTH] = {
196 .user_set = false,
197
198 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
199 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
200 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
201 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
202 PERF_OUTPUT_SYNTH,
203
204 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
205 },
185}; 206};
186 207
208static inline int output_type(unsigned int type)
209{
210 switch (type) {
211 case PERF_TYPE_SYNTH:
212 return OUTPUT_TYPE_SYNTH;
213 default:
214 return type;
215 }
216}
217
218static inline unsigned int attr_type(unsigned int type)
219{
220 switch (type) {
221 case OUTPUT_TYPE_SYNTH:
222 return PERF_TYPE_SYNTH;
223 default:
224 return type;
225 }
226}
227
187static bool output_set_by_user(void) 228static bool output_set_by_user(void)
188{ 229{
189 int j; 230 int j;
190 for (j = 0; j < PERF_TYPE_MAX; ++j) { 231 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
191 if (output[j].user_set) 232 if (output[j].user_set)
192 return true; 233 return true;
193 } 234 }
@@ -208,7 +249,7 @@ static const char *output_field2str(enum perf_output_field field)
208 return str; 249 return str;
209} 250}
210 251
211#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x) 252#define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x)
212 253
213static int perf_evsel__do_check_stype(struct perf_evsel *evsel, 254static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
214 u64 sample_type, const char *sample_msg, 255 u64 sample_type, const char *sample_msg,
@@ -216,7 +257,7 @@ static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
216 bool allow_user_set) 257 bool allow_user_set)
217{ 258{
218 struct perf_event_attr *attr = &evsel->attr; 259 struct perf_event_attr *attr = &evsel->attr;
219 int type = attr->type; 260 int type = output_type(attr->type);
220 const char *evname; 261 const char *evname;
221 262
222 if (attr->sample_type & sample_type) 263 if (attr->sample_type & sample_type)
@@ -298,10 +339,10 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
298 "selected.\n"); 339 "selected.\n");
299 return -EINVAL; 340 return -EINVAL;
300 } 341 }
301 if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { 342 if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR) &&
302 pr_err("Display of DSO requested but neither sample IP nor " 343 !PRINT_FIELD(BRSTACK) && !PRINT_FIELD(BRSTACKSYM) && !PRINT_FIELD(BRSTACKOFF)) {
303 "sample address\nis selected. Hence, no addresses to convert " 344 pr_err("Display of DSO requested but no address to convert. Select\n"
304 "to DSO.\n"); 345 "sample IP, sample address, brstack, brstacksym, or brstackoff.\n");
305 return -EINVAL; 346 return -EINVAL;
306 } 347 }
307 if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) { 348 if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
@@ -346,7 +387,7 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
346 387
347static void set_print_ip_opts(struct perf_event_attr *attr) 388static void set_print_ip_opts(struct perf_event_attr *attr)
348{ 389{
349 unsigned int type = attr->type; 390 unsigned int type = output_type(attr->type);
350 391
351 output[type].print_ip_opts = 0; 392 output[type].print_ip_opts = 0;
352 if (PRINT_FIELD(IP)) 393 if (PRINT_FIELD(IP))
@@ -374,16 +415,17 @@ static int perf_session__check_output_opt(struct perf_session *session)
374 unsigned int j; 415 unsigned int j;
375 struct perf_evsel *evsel; 416 struct perf_evsel *evsel;
376 417
377 for (j = 0; j < PERF_TYPE_MAX; ++j) { 418 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
378 evsel = perf_session__find_first_evtype(session, j); 419 evsel = perf_session__find_first_evtype(session, attr_type(j));
379 420
380 /* 421 /*
381 * even if fields is set to 0 (ie., show nothing) event must 422 * even if fields is set to 0 (ie., show nothing) event must
382 * exist if user explicitly includes it on the command line 423 * exist if user explicitly includes it on the command line
383 */ 424 */
384 if (!evsel && output[j].user_set && !output[j].wildcard_set) { 425 if (!evsel && output[j].user_set && !output[j].wildcard_set &&
426 j != OUTPUT_TYPE_SYNTH) {
385 pr_err("%s events do not exist. " 427 pr_err("%s events do not exist. "
386 "Remove corresponding -f option to proceed.\n", 428 "Remove corresponding -F option to proceed.\n",
387 event_type(j)); 429 event_type(j));
388 return -1; 430 return -1;
389 } 431 }
@@ -514,18 +556,43 @@ mispred_str(struct branch_entry *br)
514 return br->flags.predicted ? 'P' : 'M'; 556 return br->flags.predicted ? 'P' : 'M';
515} 557}
516 558
517static void print_sample_brstack(struct perf_sample *sample) 559static void print_sample_brstack(struct perf_sample *sample,
560 struct thread *thread,
561 struct perf_event_attr *attr)
518{ 562{
519 struct branch_stack *br = sample->branch_stack; 563 struct branch_stack *br = sample->branch_stack;
520 u64 i; 564 struct addr_location alf, alt;
565 u64 i, from, to;
521 566
522 if (!(br && br->nr)) 567 if (!(br && br->nr))
523 return; 568 return;
524 569
525 for (i = 0; i < br->nr; i++) { 570 for (i = 0; i < br->nr; i++) {
526 printf(" 0x%"PRIx64"/0x%"PRIx64"/%c/%c/%c/%d ", 571 from = br->entries[i].from;
527 br->entries[i].from, 572 to = br->entries[i].to;
528 br->entries[i].to, 573
574 if (PRINT_FIELD(DSO)) {
575 memset(&alf, 0, sizeof(alf));
576 memset(&alt, 0, sizeof(alt));
577 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf);
578 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt);
579 }
580
581 printf("0x%"PRIx64, from);
582 if (PRINT_FIELD(DSO)) {
583 printf("(");
584 map__fprintf_dsoname(alf.map, stdout);
585 printf(")");
586 }
587
588 printf("/0x%"PRIx64, to);
589 if (PRINT_FIELD(DSO)) {
590 printf("(");
591 map__fprintf_dsoname(alt.map, stdout);
592 printf(")");
593 }
594
595 printf("/%c/%c/%c/%d ",
529 mispred_str( br->entries + i), 596 mispred_str( br->entries + i),
530 br->entries[i].flags.in_tx? 'X' : '-', 597 br->entries[i].flags.in_tx? 'X' : '-',
531 br->entries[i].flags.abort? 'A' : '-', 598 br->entries[i].flags.abort? 'A' : '-',
@@ -534,7 +601,8 @@ static void print_sample_brstack(struct perf_sample *sample)
534} 601}
535 602
536static void print_sample_brstacksym(struct perf_sample *sample, 603static void print_sample_brstacksym(struct perf_sample *sample,
537 struct thread *thread) 604 struct thread *thread,
605 struct perf_event_attr *attr)
538{ 606{
539 struct branch_stack *br = sample->branch_stack; 607 struct branch_stack *br = sample->branch_stack;
540 struct addr_location alf, alt; 608 struct addr_location alf, alt;
@@ -559,8 +627,18 @@ static void print_sample_brstacksym(struct perf_sample *sample,
559 alt.sym = map__find_symbol(alt.map, alt.addr); 627 alt.sym = map__find_symbol(alt.map, alt.addr);
560 628
561 symbol__fprintf_symname_offs(alf.sym, &alf, stdout); 629 symbol__fprintf_symname_offs(alf.sym, &alf, stdout);
630 if (PRINT_FIELD(DSO)) {
631 printf("(");
632 map__fprintf_dsoname(alf.map, stdout);
633 printf(")");
634 }
562 putchar('/'); 635 putchar('/');
563 symbol__fprintf_symname_offs(alt.sym, &alt, stdout); 636 symbol__fprintf_symname_offs(alt.sym, &alt, stdout);
637 if (PRINT_FIELD(DSO)) {
638 printf("(");
639 map__fprintf_dsoname(alt.map, stdout);
640 printf(")");
641 }
564 printf("/%c/%c/%c/%d ", 642 printf("/%c/%c/%c/%d ",
565 mispred_str( br->entries + i), 643 mispred_str( br->entries + i),
566 br->entries[i].flags.in_tx? 'X' : '-', 644 br->entries[i].flags.in_tx? 'X' : '-',
@@ -569,6 +647,51 @@ static void print_sample_brstacksym(struct perf_sample *sample,
569 } 647 }
570} 648}
571 649
650static void print_sample_brstackoff(struct perf_sample *sample,
651 struct thread *thread,
652 struct perf_event_attr *attr)
653{
654 struct branch_stack *br = sample->branch_stack;
655 struct addr_location alf, alt;
656 u64 i, from, to;
657
658 if (!(br && br->nr))
659 return;
660
661 for (i = 0; i < br->nr; i++) {
662
663 memset(&alf, 0, sizeof(alf));
664 memset(&alt, 0, sizeof(alt));
665 from = br->entries[i].from;
666 to = br->entries[i].to;
667
668 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf);
669 if (alf.map && !alf.map->dso->adjust_symbols)
670 from = map__map_ip(alf.map, from);
671
672 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt);
673 if (alt.map && !alt.map->dso->adjust_symbols)
674 to = map__map_ip(alt.map, to);
675
676 printf("0x%"PRIx64, from);
677 if (PRINT_FIELD(DSO)) {
678 printf("(");
679 map__fprintf_dsoname(alf.map, stdout);
680 printf(")");
681 }
682 printf("/0x%"PRIx64, to);
683 if (PRINT_FIELD(DSO)) {
684 printf("(");
685 map__fprintf_dsoname(alt.map, stdout);
686 printf(")");
687 }
688 printf("/%c/%c/%c/%d ",
689 mispred_str(br->entries + i),
690 br->entries[i].flags.in_tx ? 'X' : '-',
691 br->entries[i].flags.abort ? 'A' : '-',
692 br->entries[i].flags.cycles);
693 }
694}
572#define MAXBB 16384UL 695#define MAXBB 16384UL
573 696
574static int grab_bb(u8 *buffer, u64 start, u64 end, 697static int grab_bb(u8 *buffer, u64 start, u64 end,
@@ -906,6 +1029,7 @@ static void print_sample_bts(struct perf_sample *sample,
906 struct machine *machine) 1029 struct machine *machine)
907{ 1030{
908 struct perf_event_attr *attr = &evsel->attr; 1031 struct perf_event_attr *attr = &evsel->attr;
1032 unsigned int type = output_type(attr->type);
909 bool print_srcline_last = false; 1033 bool print_srcline_last = false;
910 1034
911 if (PRINT_FIELD(CALLINDENT)) 1035 if (PRINT_FIELD(CALLINDENT))
@@ -913,7 +1037,7 @@ static void print_sample_bts(struct perf_sample *sample,
913 1037
914 /* print branch_from information */ 1038 /* print branch_from information */
915 if (PRINT_FIELD(IP)) { 1039 if (PRINT_FIELD(IP)) {
916 unsigned int print_opts = output[attr->type].print_ip_opts; 1040 unsigned int print_opts = output[type].print_ip_opts;
917 struct callchain_cursor *cursor = NULL; 1041 struct callchain_cursor *cursor = NULL;
918 1042
919 if (symbol_conf.use_callchain && sample->callchain && 1043 if (symbol_conf.use_callchain && sample->callchain &&
@@ -936,7 +1060,7 @@ static void print_sample_bts(struct perf_sample *sample,
936 /* print branch_to information */ 1060 /* print branch_to information */
937 if (PRINT_FIELD(ADDR) || 1061 if (PRINT_FIELD(ADDR) ||
938 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && 1062 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
939 !output[attr->type].user_set)) { 1063 !output[type].user_set)) {
940 printf(" => "); 1064 printf(" => ");
941 print_sample_addr(sample, thread, attr); 1065 print_sample_addr(sample, thread, attr);
942 } 1066 }
@@ -1079,6 +1203,127 @@ static void print_sample_bpf_output(struct perf_sample *sample)
1079 (char *)(sample->raw_data)); 1203 (char *)(sample->raw_data));
1080} 1204}
1081 1205
1206static void print_sample_spacing(int len, int spacing)
1207{
1208 if (len > 0 && len < spacing)
1209 printf("%*s", spacing - len, "");
1210}
1211
1212static void print_sample_pt_spacing(int len)
1213{
1214 print_sample_spacing(len, 34);
1215}
1216
1217static void print_sample_synth_ptwrite(struct perf_sample *sample)
1218{
1219 struct perf_synth_intel_ptwrite *data = perf_sample__synth_ptr(sample);
1220 int len;
1221
1222 if (perf_sample__bad_synth_size(sample, *data))
1223 return;
1224
1225 len = printf(" IP: %u payload: %#" PRIx64 " ",
1226 data->ip, le64_to_cpu(data->payload));
1227 print_sample_pt_spacing(len);
1228}
1229
1230static void print_sample_synth_mwait(struct perf_sample *sample)
1231{
1232 struct perf_synth_intel_mwait *data = perf_sample__synth_ptr(sample);
1233 int len;
1234
1235 if (perf_sample__bad_synth_size(sample, *data))
1236 return;
1237
1238 len = printf(" hints: %#x extensions: %#x ",
1239 data->hints, data->extensions);
1240 print_sample_pt_spacing(len);
1241}
1242
1243static void print_sample_synth_pwre(struct perf_sample *sample)
1244{
1245 struct perf_synth_intel_pwre *data = perf_sample__synth_ptr(sample);
1246 int len;
1247
1248 if (perf_sample__bad_synth_size(sample, *data))
1249 return;
1250
1251 len = printf(" hw: %u cstate: %u sub-cstate: %u ",
1252 data->hw, data->cstate, data->subcstate);
1253 print_sample_pt_spacing(len);
1254}
1255
1256static void print_sample_synth_exstop(struct perf_sample *sample)
1257{
1258 struct perf_synth_intel_exstop *data = perf_sample__synth_ptr(sample);
1259 int len;
1260
1261 if (perf_sample__bad_synth_size(sample, *data))
1262 return;
1263
1264 len = printf(" IP: %u ", data->ip);
1265 print_sample_pt_spacing(len);
1266}
1267
1268static void print_sample_synth_pwrx(struct perf_sample *sample)
1269{
1270 struct perf_synth_intel_pwrx *data = perf_sample__synth_ptr(sample);
1271 int len;
1272
1273 if (perf_sample__bad_synth_size(sample, *data))
1274 return;
1275
1276 len = printf(" deepest cstate: %u last cstate: %u wake reason: %#x ",
1277 data->deepest_cstate, data->last_cstate,
1278 data->wake_reason);
1279 print_sample_pt_spacing(len);
1280}
1281
1282static void print_sample_synth_cbr(struct perf_sample *sample)
1283{
1284 struct perf_synth_intel_cbr *data = perf_sample__synth_ptr(sample);
1285 unsigned int percent, freq;
1286 int len;
1287
1288 if (perf_sample__bad_synth_size(sample, *data))
1289 return;
1290
1291 freq = (le32_to_cpu(data->freq) + 500) / 1000;
1292 len = printf(" cbr: %2u freq: %4u MHz ", data->cbr, freq);
1293 if (data->max_nonturbo) {
1294 percent = (5 + (1000 * data->cbr) / data->max_nonturbo) / 10;
1295 len += printf("(%3u%%) ", percent);
1296 }
1297 print_sample_pt_spacing(len);
1298}
1299
1300static void print_sample_synth(struct perf_sample *sample,
1301 struct perf_evsel *evsel)
1302{
1303 switch (evsel->attr.config) {
1304 case PERF_SYNTH_INTEL_PTWRITE:
1305 print_sample_synth_ptwrite(sample);
1306 break;
1307 case PERF_SYNTH_INTEL_MWAIT:
1308 print_sample_synth_mwait(sample);
1309 break;
1310 case PERF_SYNTH_INTEL_PWRE:
1311 print_sample_synth_pwre(sample);
1312 break;
1313 case PERF_SYNTH_INTEL_EXSTOP:
1314 print_sample_synth_exstop(sample);
1315 break;
1316 case PERF_SYNTH_INTEL_PWRX:
1317 print_sample_synth_pwrx(sample);
1318 break;
1319 case PERF_SYNTH_INTEL_CBR:
1320 print_sample_synth_cbr(sample);
1321 break;
1322 default:
1323 break;
1324 }
1325}
1326
1082struct perf_script { 1327struct perf_script {
1083 struct perf_tool tool; 1328 struct perf_tool tool;
1084 struct perf_session *session; 1329 struct perf_session *session;
@@ -1132,8 +1377,9 @@ static void process_event(struct perf_script *script,
1132{ 1377{
1133 struct thread *thread = al->thread; 1378 struct thread *thread = al->thread;
1134 struct perf_event_attr *attr = &evsel->attr; 1379 struct perf_event_attr *attr = &evsel->attr;
1380 unsigned int type = output_type(attr->type);
1135 1381
1136 if (output[attr->type].fields == 0) 1382 if (output[type].fields == 0)
1137 return; 1383 return;
1138 1384
1139 print_sample_start(sample, thread, evsel); 1385 print_sample_start(sample, thread, evsel);
@@ -1162,6 +1408,10 @@ static void process_event(struct perf_script *script,
1162 if (PRINT_FIELD(TRACE)) 1408 if (PRINT_FIELD(TRACE))
1163 event_format__print(evsel->tp_format, sample->cpu, 1409 event_format__print(evsel->tp_format, sample->cpu,
1164 sample->raw_data, sample->raw_size); 1410 sample->raw_data, sample->raw_size);
1411
1412 if (attr->type == PERF_TYPE_SYNTH && PRINT_FIELD(SYNTH))
1413 print_sample_synth(sample, evsel);
1414
1165 if (PRINT_FIELD(ADDR)) 1415 if (PRINT_FIELD(ADDR))
1166 print_sample_addr(sample, thread, attr); 1416 print_sample_addr(sample, thread, attr);
1167 1417
@@ -1180,16 +1430,18 @@ static void process_event(struct perf_script *script,
1180 cursor = &callchain_cursor; 1430 cursor = &callchain_cursor;
1181 1431
1182 putchar(cursor ? '\n' : ' '); 1432 putchar(cursor ? '\n' : ' ');
1183 sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout); 1433 sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor, stdout);
1184 } 1434 }
1185 1435
1186 if (PRINT_FIELD(IREGS)) 1436 if (PRINT_FIELD(IREGS))
1187 print_sample_iregs(sample, attr); 1437 print_sample_iregs(sample, attr);
1188 1438
1189 if (PRINT_FIELD(BRSTACK)) 1439 if (PRINT_FIELD(BRSTACK))
1190 print_sample_brstack(sample); 1440 print_sample_brstack(sample, thread, attr);
1191 else if (PRINT_FIELD(BRSTACKSYM)) 1441 else if (PRINT_FIELD(BRSTACKSYM))
1192 print_sample_brstacksym(sample, thread); 1442 print_sample_brstacksym(sample, thread, attr);
1443 else if (PRINT_FIELD(BRSTACKOFF))
1444 print_sample_brstackoff(sample, thread, attr);
1193 1445
1194 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT)) 1446 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
1195 print_sample_bpf_output(sample); 1447 print_sample_bpf_output(sample);
@@ -1325,7 +1577,8 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
1325 evlist = *pevlist; 1577 evlist = *pevlist;
1326 evsel = perf_evlist__last(*pevlist); 1578 evsel = perf_evlist__last(*pevlist);
1327 1579
1328 if (evsel->attr.type >= PERF_TYPE_MAX) 1580 if (evsel->attr.type >= PERF_TYPE_MAX &&
1581 evsel->attr.type != PERF_TYPE_SYNTH)
1329 return 0; 1582 return 0;
1330 1583
1331 evlist__for_each_entry(evlist, pos) { 1584 evlist__for_each_entry(evlist, pos) {
@@ -1727,6 +1980,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
1727 int rc = 0; 1980 int rc = 0;
1728 char *str = strdup(arg); 1981 char *str = strdup(arg);
1729 int type = -1; 1982 int type = -1;
1983 enum { DEFAULT, SET, ADD, REMOVE } change = DEFAULT;
1730 1984
1731 if (!str) 1985 if (!str)
1732 return -ENOMEM; 1986 return -ENOMEM;
@@ -1749,6 +2003,8 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
1749 type = PERF_TYPE_RAW; 2003 type = PERF_TYPE_RAW;
1750 else if (!strcmp(str, "break")) 2004 else if (!strcmp(str, "break"))
1751 type = PERF_TYPE_BREAKPOINT; 2005 type = PERF_TYPE_BREAKPOINT;
2006 else if (!strcmp(str, "synth"))
2007 type = OUTPUT_TYPE_SYNTH;
1752 else { 2008 else {
1753 fprintf(stderr, "Invalid event type in field string.\n"); 2009 fprintf(stderr, "Invalid event type in field string.\n");
1754 rc = -EINVAL; 2010 rc = -EINVAL;
@@ -1772,23 +2028,44 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
1772 goto out; 2028 goto out;
1773 } 2029 }
1774 2030
2031 /* Don't override defaults for +- */
2032 if (strchr(str, '+') || strchr(str, '-'))
2033 goto parse;
2034
1775 if (output_set_by_user()) 2035 if (output_set_by_user())
1776 pr_warning("Overriding previous field request for all events.\n"); 2036 pr_warning("Overriding previous field request for all events.\n");
1777 2037
1778 for (j = 0; j < PERF_TYPE_MAX; ++j) { 2038 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
1779 output[j].fields = 0; 2039 output[j].fields = 0;
1780 output[j].user_set = true; 2040 output[j].user_set = true;
1781 output[j].wildcard_set = true; 2041 output[j].wildcard_set = true;
1782 } 2042 }
1783 } 2043 }
1784 2044
2045parse:
1785 for (tok = strtok_r(tok, ",", &strtok_saveptr); tok; tok = strtok_r(NULL, ",", &strtok_saveptr)) { 2046 for (tok = strtok_r(tok, ",", &strtok_saveptr); tok; tok = strtok_r(NULL, ",", &strtok_saveptr)) {
2047 if (*tok == '+') {
2048 if (change == SET)
2049 goto out_badmix;
2050 change = ADD;
2051 tok++;
2052 } else if (*tok == '-') {
2053 if (change == SET)
2054 goto out_badmix;
2055 change = REMOVE;
2056 tok++;
2057 } else {
2058 if (change != SET && change != DEFAULT)
2059 goto out_badmix;
2060 change = SET;
2061 }
2062
1786 for (i = 0; i < imax; ++i) { 2063 for (i = 0; i < imax; ++i) {
1787 if (strcmp(tok, all_output_options[i].str) == 0) 2064 if (strcmp(tok, all_output_options[i].str) == 0)
1788 break; 2065 break;
1789 } 2066 }
1790 if (i == imax && strcmp(tok, "flags") == 0) { 2067 if (i == imax && strcmp(tok, "flags") == 0) {
1791 print_flags = true; 2068 print_flags = change == REMOVE ? false : true;
1792 continue; 2069 continue;
1793 } 2070 }
1794 if (i == imax) { 2071 if (i == imax) {
@@ -1801,12 +2078,16 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
1801 /* add user option to all events types for 2078 /* add user option to all events types for
1802 * which it is valid 2079 * which it is valid
1803 */ 2080 */
1804 for (j = 0; j < PERF_TYPE_MAX; ++j) { 2081 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
1805 if (output[j].invalid_fields & all_output_options[i].field) { 2082 if (output[j].invalid_fields & all_output_options[i].field) {
1806 pr_warning("\'%s\' not valid for %s events. Ignoring.\n", 2083 pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
1807 all_output_options[i].str, event_type(j)); 2084 all_output_options[i].str, event_type(j));
1808 } else 2085 } else {
1809 output[j].fields |= all_output_options[i].field; 2086 if (change == REMOVE)
2087 output[j].fields &= ~all_output_options[i].field;
2088 else
2089 output[j].fields |= all_output_options[i].field;
2090 }
1810 } 2091 }
1811 } else { 2092 } else {
1812 if (output[type].invalid_fields & all_output_options[i].field) { 2093 if (output[type].invalid_fields & all_output_options[i].field) {
@@ -1826,7 +2107,11 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
1826 "Events will not be displayed.\n", event_type(type)); 2107 "Events will not be displayed.\n", event_type(type));
1827 } 2108 }
1828 } 2109 }
2110 goto out;
1829 2111
2112out_badmix:
2113 fprintf(stderr, "Cannot mix +-field with overridden fields\n");
2114 rc = -EINVAL;
1830out: 2115out:
1831 free(str); 2116 free(str);
1832 return rc; 2117 return rc;
@@ -2444,10 +2729,11 @@ int cmd_script(int argc, const char **argv)
2444 symbol__config_symfs), 2729 symbol__config_symfs),
2445 OPT_CALLBACK('F', "fields", NULL, "str", 2730 OPT_CALLBACK('F', "fields", NULL, "str",
2446 "comma separated output fields prepend with 'type:'. " 2731 "comma separated output fields prepend with 'type:'. "
2447 "Valid types: hw,sw,trace,raw. " 2732 "+field to add and -field to remove."
2733 "Valid types: hw,sw,trace,raw,synth. "
2448 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 2734 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
2449 "addr,symoff,period,iregs,brstack,brstacksym,flags," 2735 "addr,symoff,period,iregs,brstack,brstacksym,flags,"
2450 "bpf-output,callindent,insn,insnlen,brstackinsn", 2736 "bpf-output,callindent,insn,insnlen,brstackinsn,synth",
2451 parse_output_fields), 2737 parse_output_fields),
2452 OPT_BOOLEAN('a', "all-cpus", &system_wide, 2738 OPT_BOOLEAN('a', "all-cpus", &system_wide,
2453 "system-wide collection from all CPUs"), 2739 "system-wide collection from all CPUs"),
@@ -2494,6 +2780,8 @@ int cmd_script(int argc, const char **argv)
2494 "Enable kernel symbol demangling"), 2780 "Enable kernel symbol demangling"),
2495 OPT_STRING(0, "time", &script.time_str, "str", 2781 OPT_STRING(0, "time", &script.time_str, "str",
2496 "Time span of interest (start,stop)"), 2782 "Time span of interest (start,stop)"),
2783 OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
2784 "Show inline function"),
2497 OPT_END() 2785 OPT_END()
2498 }; 2786 };
2499 const char * const script_subcommands[] = { "record", "report", NULL }; 2787 const char * const script_subcommands[] = { "record", "report", NULL };
@@ -2704,6 +2992,7 @@ int cmd_script(int argc, const char **argv)
2704 err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); 2992 err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
2705 if (err < 0) 2993 if (err < 0)
2706 goto out_delete; 2994 goto out_delete;
2995 itrace_synth_opts.cpu_bitmap = cpu_bitmap;
2707 } 2996 }
2708 2997
2709 if (!no_callchain) 2998 if (!no_callchain)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a935b5023732..48ac53b199fc 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -86,6 +86,7 @@
86#define DEFAULT_SEPARATOR " " 86#define DEFAULT_SEPARATOR " "
87#define CNTR_NOT_SUPPORTED "<not supported>" 87#define CNTR_NOT_SUPPORTED "<not supported>"
88#define CNTR_NOT_COUNTED "<not counted>" 88#define CNTR_NOT_COUNTED "<not counted>"
89#define FREEZE_ON_SMI_PATH "devices/cpu/freeze_on_smi"
89 90
90static void print_counters(struct timespec *ts, int argc, const char **argv); 91static void print_counters(struct timespec *ts, int argc, const char **argv);
91 92
@@ -122,6 +123,14 @@ static const char * topdown_attrs[] = {
122 NULL, 123 NULL,
123}; 124};
124 125
126static const char *smi_cost_attrs = {
127 "{"
128 "msr/aperf/,"
129 "msr/smi/,"
130 "cycles"
131 "}"
132};
133
125static struct perf_evlist *evsel_list; 134static struct perf_evlist *evsel_list;
126 135
127static struct target target = { 136static struct target target = {
@@ -137,6 +146,8 @@ static bool null_run = false;
137static int detailed_run = 0; 146static int detailed_run = 0;
138static bool transaction_run; 147static bool transaction_run;
139static bool topdown_run = false; 148static bool topdown_run = false;
149static bool smi_cost = false;
150static bool smi_reset = false;
140static bool big_num = true; 151static bool big_num = true;
141static int big_num_opt = -1; 152static int big_num_opt = -1;
142static const char *csv_sep = NULL; 153static const char *csv_sep = NULL;
@@ -625,14 +636,14 @@ try_again:
625 } 636 }
626 637
627 if (perf_evlist__apply_filters(evsel_list, &counter)) { 638 if (perf_evlist__apply_filters(evsel_list, &counter)) {
628 error("failed to set filter \"%s\" on event %s with %d (%s)\n", 639 pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
629 counter->filter, perf_evsel__name(counter), errno, 640 counter->filter, perf_evsel__name(counter), errno,
630 str_error_r(errno, msg, sizeof(msg))); 641 str_error_r(errno, msg, sizeof(msg)));
631 return -1; 642 return -1;
632 } 643 }
633 644
634 if (perf_evlist__apply_drv_configs(evsel_list, &counter, &err_term)) { 645 if (perf_evlist__apply_drv_configs(evsel_list, &counter, &err_term)) {
635 error("failed to set config \"%s\" on event %s with %d (%s)\n", 646 pr_err("failed to set config \"%s\" on event %s with %d (%s)\n",
636 err_term->val.drv_cfg, perf_evsel__name(counter), errno, 647 err_term->val.drv_cfg, perf_evsel__name(counter), errno,
637 str_error_r(errno, msg, sizeof(msg))); 648 str_error_r(errno, msg, sizeof(msg)));
638 return -1; 649 return -1;
@@ -1578,6 +1589,7 @@ static void print_header(int argc, const char **argv)
1578static void print_footer(void) 1589static void print_footer(void)
1579{ 1590{
1580 FILE *output = stat_config.output; 1591 FILE *output = stat_config.output;
1592 int n;
1581 1593
1582 if (!null_run) 1594 if (!null_run)
1583 fprintf(output, "\n"); 1595 fprintf(output, "\n");
@@ -1590,7 +1602,9 @@ static void print_footer(void)
1590 } 1602 }
1591 fprintf(output, "\n\n"); 1603 fprintf(output, "\n\n");
1592 1604
1593 if (print_free_counters_hint) 1605 if (print_free_counters_hint &&
1606 sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
1607 n > 0)
1594 fprintf(output, 1608 fprintf(output,
1595"Some events weren't counted. Try disabling the NMI watchdog:\n" 1609"Some events weren't counted. Try disabling the NMI watchdog:\n"
1596" echo 0 > /proc/sys/kernel/nmi_watchdog\n" 1610" echo 0 > /proc/sys/kernel/nmi_watchdog\n"
@@ -1779,6 +1793,8 @@ static const struct option stat_options[] = {
1779 "Only print computed metrics. No raw values", enable_metric_only), 1793 "Only print computed metrics. No raw values", enable_metric_only),
1780 OPT_BOOLEAN(0, "topdown", &topdown_run, 1794 OPT_BOOLEAN(0, "topdown", &topdown_run,
1781 "measure topdown level 1 statistics"), 1795 "measure topdown level 1 statistics"),
1796 OPT_BOOLEAN(0, "smi-cost", &smi_cost,
1797 "measure SMI cost"),
1782 OPT_END() 1798 OPT_END()
1783}; 1799};
1784 1800
@@ -2157,6 +2173,39 @@ static int add_default_attributes(void)
2157 return 0; 2173 return 0;
2158 } 2174 }
2159 2175
2176 if (smi_cost) {
2177 int smi;
2178
2179 if (sysfs__read_int(FREEZE_ON_SMI_PATH, &smi) < 0) {
2180 fprintf(stderr, "freeze_on_smi is not supported.\n");
2181 return -1;
2182 }
2183
2184 if (!smi) {
2185 if (sysfs__write_int(FREEZE_ON_SMI_PATH, 1) < 0) {
2186 fprintf(stderr, "Failed to set freeze_on_smi.\n");
2187 return -1;
2188 }
2189 smi_reset = true;
2190 }
2191
2192 if (pmu_have_event("msr", "aperf") &&
2193 pmu_have_event("msr", "smi")) {
2194 if (!force_metric_only)
2195 metric_only = true;
2196 err = parse_events(evsel_list, smi_cost_attrs, NULL);
2197 } else {
2198 fprintf(stderr, "To measure SMI cost, it needs "
2199 "msr/aperf/, msr/smi/ and cpu/cycles/ support\n");
2200 return -1;
2201 }
2202 if (err) {
2203 fprintf(stderr, "Cannot set up SMI cost events\n");
2204 return -1;
2205 }
2206 return 0;
2207 }
2208
2160 if (topdown_run) { 2209 if (topdown_run) {
2161 char *str = NULL; 2210 char *str = NULL;
2162 bool warn = false; 2211 bool warn = false;
@@ -2739,6 +2788,9 @@ int cmd_stat(int argc, const char **argv)
2739 perf_stat__exit_aggr_mode(); 2788 perf_stat__exit_aggr_mode();
2740 perf_evlist__free_stats(evsel_list); 2789 perf_evlist__free_stats(evsel_list);
2741out: 2790out:
2791 if (smi_cost && smi_reset)
2792 sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
2793
2742 perf_evlist__delete(evsel_list); 2794 perf_evlist__delete(evsel_list);
2743 return status; 2795 return status;
2744} 2796}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 10b6362ca0bf..6052376634c0 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -134,7 +134,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
134 return err; 134 return err;
135 } 135 }
136 136
137 err = symbol__disassemble(sym, map, NULL, 0); 137 err = symbol__disassemble(sym, map, NULL, 0, NULL);
138 if (err == 0) { 138 if (err == 0) {
139out_assign: 139out_assign:
140 top->sym_filter_entry = he; 140 top->sym_filter_entry = he;
@@ -958,7 +958,7 @@ static int __cmd_top(struct perf_top *top)
958 958
959 ret = perf_evlist__apply_drv_configs(evlist, &pos, &err_term); 959 ret = perf_evlist__apply_drv_configs(evlist, &pos, &err_term);
960 if (ret) { 960 if (ret) {
961 error("failed to set config \"%s\" on event %s with %d (%s)\n", 961 pr_err("failed to set config \"%s\" on event %s with %d (%s)\n",
962 err_term->val.drv_cfg, perf_evsel__name(pos), errno, 962 err_term->val.drv_cfg, perf_evsel__name(pos), errno,
963 str_error_r(errno, msg, sizeof(msg))); 963 str_error_r(errno, msg, sizeof(msg)));
964 goto out_delete; 964 goto out_delete;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index d014350adc52..4b2a5d298197 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -681,6 +681,10 @@ static struct syscall_fmt {
681 { .name = "mlockall", .errmsg = true, 681 { .name = "mlockall", .errmsg = true,
682 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 682 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
683 { .name = "mmap", .hexret = true, 683 { .name = "mmap", .hexret = true,
684/* The standard mmap maps to old_mmap on s390x */
685#if defined(__s390x__)
686 .alias = "old_mmap",
687#endif
684 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 688 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
685 [2] = SCA_MMAP_PROT, /* prot */ 689 [2] = SCA_MMAP_PROT, /* prot */
686 [3] = SCA_MMAP_FLAGS, /* flags */ }, }, 690 [3] = SCA_MMAP_FLAGS, /* flags */ }, },
diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c
index e9651a9d670e..cf36de7ea255 100644
--- a/tools/perf/jvmti/jvmti_agent.c
+++ b/tools/perf/jvmti/jvmti_agent.c
@@ -304,7 +304,7 @@ jvmti_close(void *agent)
304 FILE *fp = agent; 304 FILE *fp = agent;
305 305
306 if (!fp) { 306 if (!fp) {
307 warnx("jvmti: incalid fd in close_agent"); 307 warnx("jvmti: invalid fd in close_agent");
308 return -1; 308 return -1;
309 } 309 }
310 310
diff --git a/tools/perf/jvmti/jvmti_agent.h b/tools/perf/jvmti/jvmti_agent.h
index bedf5d0ba9ff..c53a41f48b63 100644
--- a/tools/perf/jvmti/jvmti_agent.h
+++ b/tools/perf/jvmti/jvmti_agent.h
@@ -5,8 +5,6 @@
5#include <stdint.h> 5#include <stdint.h>
6#include <jvmti.h> 6#include <jvmti.h>
7 7
8#define __unused __attribute__((unused))
9
10#if defined(__cplusplus) 8#if defined(__cplusplus)
11extern "C" { 9extern "C" {
12#endif 10#endif
diff --git a/tools/perf/jvmti/libjvmti.c b/tools/perf/jvmti/libjvmti.c
index 5612641c69b4..6d710904c837 100644
--- a/tools/perf/jvmti/libjvmti.c
+++ b/tools/perf/jvmti/libjvmti.c
@@ -1,3 +1,4 @@
1#include <linux/compiler.h>
1#include <sys/types.h> 2#include <sys/types.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <string.h> 4#include <string.h>
@@ -238,7 +239,7 @@ code_generated_cb(jvmtiEnv *jvmti,
238} 239}
239 240
240JNIEXPORT jint JNICALL 241JNIEXPORT jint JNICALL
241Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused) 242Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __maybe_unused)
242{ 243{
243 jvmtiEventCallbacks cb; 244 jvmtiEventCallbacks cb;
244 jvmtiCapabilities caps1; 245 jvmtiCapabilities caps1;
@@ -313,7 +314,7 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused)
313} 314}
314 315
315JNIEXPORT void JNICALL 316JNIEXPORT void JNICALL
316Agent_OnUnload(JavaVM *jvm __unused) 317Agent_OnUnload(JavaVM *jvm __maybe_unused)
317{ 318{
318 int ret; 319 int ret;
319 320
diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
index 9213a1273697..999a4e878162 100644
--- a/tools/perf/pmu-events/Build
+++ b/tools/perf/pmu-events/Build
@@ -2,7 +2,7 @@ hostprogs := jevents
2 2
3jevents-y += json.o jsmn.o jevents.o 3jevents-y += json.o jsmn.o jevents.o
4pmu-events-y += pmu-events.o 4pmu-events-y += pmu-events.o
5JDIR = pmu-events/arch/$(ARCH) 5JDIR = pmu-events/arch/$(SRCARCH)
6JSON = $(shell [ -d $(JDIR) ] && \ 6JSON = $(shell [ -d $(JDIR) ] && \
7 find $(JDIR) -name '*.json' -o -name 'mapfile.csv') 7 find $(JDIR) -name '*.json' -o -name 'mapfile.csv')
8# 8#
@@ -10,4 +10,4 @@ JSON = $(shell [ -d $(JDIR) ] && \
10# directory and create tables in pmu-events.c. 10# directory and create tables in pmu-events.c.
11# 11#
12$(OUTPUT)pmu-events/pmu-events.c: $(JSON) $(JEVENTS) 12$(OUTPUT)pmu-events/pmu-events.c: $(JSON) $(JEVENTS)
13 $(Q)$(call echo-cmd,gen)$(JEVENTS) $(ARCH) pmu-events/arch $(OUTPUT)pmu-events/pmu-events.c $(V) 13 $(Q)$(call echo-cmd,gen)$(JEVENTS) $(SRCARCH) pmu-events/arch $(OUTPUT)pmu-events/pmu-events.c $(V)
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
index baa073f38334..bd0aabb2bd0f 100644
--- a/tools/perf/pmu-events/jevents.c
+++ b/tools/perf/pmu-events/jevents.c
@@ -48,10 +48,6 @@
48#include "json.h" 48#include "json.h"
49#include "jevents.h" 49#include "jevents.h"
50 50
51#ifndef __maybe_unused
52#define __maybe_unused __attribute__((unused))
53#endif
54
55int verbose; 51int verbose;
56char *prog; 52char *prog;
57 53
diff --git a/tools/perf/scripts/python/bin/intel-pt-events-record b/tools/perf/scripts/python/bin/intel-pt-events-record
new file mode 100644
index 000000000000..10fe2b6977d4
--- /dev/null
+++ b/tools/perf/scripts/python/bin/intel-pt-events-record
@@ -0,0 +1,13 @@
1#!/bin/bash
2
3#
4# print Intel PT Power Events and PTWRITE. The intel_pt PMU event needs
5# to be specified with appropriate config terms.
6#
7if ! echo "$@" | grep -q intel_pt ; then
8 echo "Options must include the Intel PT event e.g. -e intel_pt/pwr_evt,ptw/"
9 echo "and for power events it probably needs to be system wide i.e. -a option"
10 echo "For example: -a -e intel_pt/pwr_evt,branch=0/ sleep 1"
11 exit 1
12fi
13perf record $@
diff --git a/tools/perf/scripts/python/bin/intel-pt-events-report b/tools/perf/scripts/python/bin/intel-pt-events-report
new file mode 100644
index 000000000000..9a9c92fcd026
--- /dev/null
+++ b/tools/perf/scripts/python/bin/intel-pt-events-report
@@ -0,0 +1,3 @@
1#!/bin/bash
2# description: print Intel PT Power Events and PTWRITE
3perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/intel-pt-events.py \ No newline at end of file
diff --git a/tools/perf/scripts/python/intel-pt-events.py b/tools/perf/scripts/python/intel-pt-events.py
new file mode 100644
index 000000000000..b19172d673af
--- /dev/null
+++ b/tools/perf/scripts/python/intel-pt-events.py
@@ -0,0 +1,128 @@
1# intel-pt-events.py: Print Intel PT Power Events and PTWRITE
2# Copyright (c) 2017, Intel Corporation.
3#
4# This program is free software; you can redistribute it and/or modify it
5# under the terms and conditions of the GNU General Public License,
6# version 2, as published by the Free Software Foundation.
7#
8# This program is distributed in the hope it will be useful, but WITHOUT
9# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11# more details.
12
13import os
14import sys
15import struct
16
17sys.path.append(os.environ['PERF_EXEC_PATH'] + \
18 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
19
20# These perf imports are not used at present
21#from perf_trace_context import *
22#from Core import *
23
24def trace_begin():
25 print "Intel PT Power Events and PTWRITE"
26
27def trace_end():
28 print "End"
29
30def trace_unhandled(event_name, context, event_fields_dict):
31 print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])
32
33def print_ptwrite(raw_buf):
34 data = struct.unpack_from("<IQ", raw_buf)
35 flags = data[0]
36 payload = data[1]
37 exact_ip = flags & 1
38 print "IP: %u payload: %#x" % (exact_ip, payload),
39
40def print_cbr(raw_buf):
41 data = struct.unpack_from("<BBBBII", raw_buf)
42 cbr = data[0]
43 f = (data[4] + 500) / 1000
44 p = ((cbr * 1000 / data[2]) + 5) / 10
45 print "%3u freq: %4u MHz (%3u%%)" % (cbr, f, p),
46
47def print_mwait(raw_buf):
48 data = struct.unpack_from("<IQ", raw_buf)
49 payload = data[1]
50 hints = payload & 0xff
51 extensions = (payload >> 32) & 0x3
52 print "hints: %#x extensions: %#x" % (hints, extensions),
53
54def print_pwre(raw_buf):
55 data = struct.unpack_from("<IQ", raw_buf)
56 payload = data[1]
57 hw = (payload >> 7) & 1
58 cstate = (payload >> 12) & 0xf
59 subcstate = (payload >> 8) & 0xf
60 print "hw: %u cstate: %u sub-cstate: %u" % (hw, cstate, subcstate),
61
62def print_exstop(raw_buf):
63 data = struct.unpack_from("<I", raw_buf)
64 flags = data[0]
65 exact_ip = flags & 1
66 print "IP: %u" % (exact_ip),
67
68def print_pwrx(raw_buf):
69 data = struct.unpack_from("<IQ", raw_buf)
70 payload = data[1]
71 deepest_cstate = payload & 0xf
72 last_cstate = (payload >> 4) & 0xf
73 wake_reason = (payload >> 8) & 0xf
74 print "deepest cstate: %u last cstate: %u wake reason: %#x" % (deepest_cstate, last_cstate, wake_reason),
75
76def print_common_start(comm, sample, name):
77 ts = sample["time"]
78 cpu = sample["cpu"]
79 pid = sample["pid"]
80 tid = sample["tid"]
81 print "%16s %5u/%-5u [%03u] %9u.%09u %7s:" % (comm, pid, tid, cpu, ts / 1000000000, ts %1000000000, name),
82
83def print_common_ip(sample, symbol, dso):
84 ip = sample["ip"]
85 print "%16x %s (%s)" % (ip, symbol, dso)
86
87def process_event(param_dict):
88 event_attr = param_dict["attr"]
89 sample = param_dict["sample"]
90 raw_buf = param_dict["raw_buf"]
91 comm = param_dict["comm"]
92 name = param_dict["ev_name"]
93
94 # Symbol and dso info are not always resolved
95 if (param_dict.has_key("dso")):
96 dso = param_dict["dso"]
97 else:
98 dso = "[unknown]"
99
100 if (param_dict.has_key("symbol")):
101 symbol = param_dict["symbol"]
102 else:
103 symbol = "[unknown]"
104
105 if name == "ptwrite":
106 print_common_start(comm, sample, name)
107 print_ptwrite(raw_buf)
108 print_common_ip(sample, symbol, dso)
109 elif name == "cbr":
110 print_common_start(comm, sample, name)
111 print_cbr(raw_buf)
112 print_common_ip(sample, symbol, dso)
113 elif name == "mwait":
114 print_common_start(comm, sample, name)
115 print_mwait(raw_buf)
116 print_common_ip(sample, symbol, dso)
117 elif name == "pwre":
118 print_common_start(comm, sample, name)
119 print_pwre(raw_buf)
120 print_common_ip(sample, symbol, dso)
121 elif name == "exstop":
122 print_common_start(comm, sample, name)
123 print_exstop(raw_buf)
124 print_common_ip(sample, symbol, dso)
125 elif name == "pwrx":
126 print_common_start(comm, sample, name)
127 print_pwrx(raw_buf)
128 print_common_ip(sample, symbol, dso)
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index af58ebc243ef..84222bdb8689 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -75,7 +75,7 @@ $(OUTPUT)tests/llvm-src-relocation.c: tests/bpf-script-test-relocation.c tests/B
75 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@ 75 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
76 $(Q)echo ';' >> $@ 76 $(Q)echo ';' >> $@
77 77
78ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64 powerpc)) 78ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc))
79perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o 79perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
80endif 80endif
81 81
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index 0dd77494bb58..0e77b2cf61ec 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -18,6 +18,7 @@
18 * permissions. All the event text files are stored there. 18 * permissions. All the event text files are stored there.
19 */ 19 */
20 20
21#include <debug.h>
21#include <errno.h> 22#include <errno.h>
22#include <inttypes.h> 23#include <inttypes.h>
23#include <stdlib.h> 24#include <stdlib.h>
@@ -29,14 +30,11 @@
29#include <sys/stat.h> 30#include <sys/stat.h>
30#include <unistd.h> 31#include <unistd.h>
31#include "../perf.h" 32#include "../perf.h"
32#include "util.h"
33#include <subcmd/exec-cmd.h> 33#include <subcmd/exec-cmd.h>
34#include "tests.h" 34#include "tests.h"
35 35
36#define ENV "PERF_TEST_ATTR" 36#define ENV "PERF_TEST_ATTR"
37 37
38extern int verbose;
39
40static char *dir; 38static char *dir;
41 39
42void test_attr__init(void) 40void test_attr__init(void)
@@ -138,8 +136,10 @@ void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
138{ 136{
139 int errno_saved = errno; 137 int errno_saved = errno;
140 138
141 if (store_event(attr, pid, cpu, fd, group_fd, flags)) 139 if (store_event(attr, pid, cpu, fd, group_fd, flags)) {
142 die("test attr FAILED"); 140 pr_err("test attr FAILED");
141 exit(128);
142 }
143 143
144 errno = errno_saved; 144 errno = errno_saved;
145} 145}
diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py
index 1091bd47adfd..cdf21a9d0c35 100644
--- a/tools/perf/tests/attr.py
+++ b/tools/perf/tests/attr.py
@@ -16,6 +16,13 @@ class Fail(Exception):
16 def getMsg(self): 16 def getMsg(self):
17 return '\'%s\' - %s' % (self.test.path, self.msg) 17 return '\'%s\' - %s' % (self.test.path, self.msg)
18 18
19class Notest(Exception):
20 def __init__(self, test, arch):
21 self.arch = arch
22 self.test = test
23 def getMsg(self):
24 return '[%s] \'%s\'' % (self.arch, self.test.path)
25
19class Unsup(Exception): 26class Unsup(Exception):
20 def __init__(self, test): 27 def __init__(self, test):
21 self.test = test 28 self.test = test
@@ -112,6 +119,9 @@ class Event(dict):
112# 'command' - perf command name 119# 'command' - perf command name
113# 'args' - special command arguments 120# 'args' - special command arguments
114# 'ret' - expected command return value (0 by default) 121# 'ret' - expected command return value (0 by default)
122# 'arch' - architecture specific test (optional)
123# comma separated list, ! at the beginning
124# negates it.
115# 125#
116# [eventX:base] 126# [eventX:base]
117# - one or multiple instances in file 127# - one or multiple instances in file
@@ -134,6 +144,12 @@ class Test(object):
134 except: 144 except:
135 self.ret = 0 145 self.ret = 0
136 146
147 try:
148 self.arch = parser.get('config', 'arch')
149 log.warning("test limitation '%s'" % self.arch)
150 except:
151 self.arch = ''
152
137 self.expect = {} 153 self.expect = {}
138 self.result = {} 154 self.result = {}
139 log.debug(" loading expected events"); 155 log.debug(" loading expected events");
@@ -145,6 +161,31 @@ class Test(object):
145 else: 161 else:
146 return True 162 return True
147 163
164 def skip_test(self, myarch):
165 # If architecture not set always run test
166 if self.arch == '':
167 # log.warning("test for arch %s is ok" % myarch)
168 return False
169
170 # Allow multiple values in assignment separated by ','
171 arch_list = self.arch.split(',')
172
173 # Handle negated list such as !s390x,ppc
174 if arch_list[0][0] == '!':
175 arch_list[0] = arch_list[0][1:]
176 log.warning("excluded architecture list %s" % arch_list)
177 for arch_item in arch_list:
178 # log.warning("test for %s arch is %s" % (arch_item, myarch))
179 if arch_item == myarch:
180 return True
181 return False
182
183 for arch_item in arch_list:
184 # log.warning("test for architecture '%s' current '%s'" % (arch_item, myarch))
185 if arch_item == myarch:
186 return False
187 return True
188
148 def load_events(self, path, events): 189 def load_events(self, path, events):
149 parser_event = ConfigParser.SafeConfigParser() 190 parser_event = ConfigParser.SafeConfigParser()
150 parser_event.read(path) 191 parser_event.read(path)
@@ -168,6 +209,11 @@ class Test(object):
168 events[section] = e 209 events[section] = e
169 210
170 def run_cmd(self, tempdir): 211 def run_cmd(self, tempdir):
212 junk1, junk2, junk3, junk4, myarch = (os.uname())
213
214 if self.skip_test(myarch):
215 raise Notest(self, myarch)
216
171 cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir, 217 cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir,
172 self.perf, self.command, tempdir, self.args) 218 self.perf, self.command, tempdir, self.args)
173 ret = os.WEXITSTATUS(os.system(cmd)) 219 ret = os.WEXITSTATUS(os.system(cmd))
@@ -265,6 +311,8 @@ def run_tests(options):
265 Test(f, options).run() 311 Test(f, options).run()
266 except Unsup, obj: 312 except Unsup, obj:
267 log.warning("unsupp %s" % obj.getMsg()) 313 log.warning("unsupp %s" % obj.getMsg())
314 except Notest, obj:
315 log.warning("skipped %s" % obj.getMsg())
268 316
269def setup_log(verbose): 317def setup_log(verbose):
270 global log 318 global log
diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c
index e7664fe3bd33..39bbb97cd30a 100644
--- a/tools/perf/tests/bp_signal.c
+++ b/tools/perf/tests/bp_signal.c
@@ -62,8 +62,7 @@ static void __test_function(volatile long *ptr)
62} 62}
63#endif 63#endif
64 64
65__attribute__ ((noinline)) 65static noinline int test_function(void)
66static int test_function(void)
67{ 66{
68 __test_function(&the_var); 67 __test_function(&the_var);
69 the_var++; 68 the_var++;
@@ -288,3 +287,17 @@ int test__bp_signal(int subtest __maybe_unused)
288 return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ? 287 return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ?
289 TEST_OK : TEST_FAIL; 288 TEST_OK : TEST_FAIL;
290} 289}
290
291bool test__bp_signal_is_supported(void)
292{
293/*
294 * The powerpc so far does not have support to even create
295 * instruction breakpoint using the perf event interface.
296 * Once it's there we can release this.
297 */
298#ifdef __powerpc__
299 return false;
300#else
301 return true;
302#endif
303}
diff --git a/tools/perf/tests/bp_signal_overflow.c b/tools/perf/tests/bp_signal_overflow.c
index 89f92fa67cc4..3b1ac6f31b15 100644
--- a/tools/perf/tests/bp_signal_overflow.c
+++ b/tools/perf/tests/bp_signal_overflow.c
@@ -28,8 +28,7 @@
28 28
29static int overflows; 29static int overflows;
30 30
31__attribute__ ((noinline)) 31static noinline int test_function(void)
32static int test_function(void)
33{ 32{
34 return time(NULL); 33 return time(NULL);
35} 34}
diff --git a/tools/perf/tests/bpf-script-test-prologue.c b/tools/perf/tests/bpf-script-test-prologue.c
index 7230e62c70fc..b4ebc75e25ae 100644
--- a/tools/perf/tests/bpf-script-test-prologue.c
+++ b/tools/perf/tests/bpf-script-test-prologue.c
@@ -10,6 +10,15 @@
10 10
11#include <uapi/linux/fs.h> 11#include <uapi/linux/fs.h>
12 12
13/*
14 * If CONFIG_PROFILE_ALL_BRANCHES is selected,
15 * 'if' is redefined after include kernel header.
16 * Recover 'if' for BPF object code.
17 */
18#ifdef if
19# undef if
20#endif
21
13#define FMODE_READ 0x1 22#define FMODE_READ 0x1
14#define FMODE_WRITE 0x2 23#define FMODE_WRITE 0x2
15 24
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 9e08d297f1a9..3ccfd58a8c3c 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -97,10 +97,12 @@ static struct test generic_tests[] = {
97 { 97 {
98 .desc = "Breakpoint overflow signal handler", 98 .desc = "Breakpoint overflow signal handler",
99 .func = test__bp_signal, 99 .func = test__bp_signal,
100 .is_supported = test__bp_signal_is_supported,
100 }, 101 },
101 { 102 {
102 .desc = "Breakpoint overflow sampling", 103 .desc = "Breakpoint overflow sampling",
103 .func = test__bp_signal_overflow, 104 .func = test__bp_signal_overflow,
105 .is_supported = test__bp_signal_is_supported,
104 }, 106 },
105 { 107 {
106 .desc = "Number of exit events of a simple workload", 108 .desc = "Number of exit events of a simple workload",
@@ -401,6 +403,11 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
401 if (!perf_test__matches(t, curr, argc, argv)) 403 if (!perf_test__matches(t, curr, argc, argv))
402 continue; 404 continue;
403 405
406 if (t->is_supported && !t->is_supported()) {
407 pr_debug("%2d: %-*s: Disabled\n", i, width, t->desc);
408 continue;
409 }
410
404 pr_info("%2d: %-*s:", i, width, t->desc); 411 pr_info("%2d: %-*s:", i, width, t->desc);
405 412
406 if (intlist__find(skiplist, i)) { 413 if (intlist__find(skiplist, i)) {
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 1f14e7612cbb..94b7c7b02bde 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -229,6 +229,8 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
229 unsigned char buf2[BUFSZ]; 229 unsigned char buf2[BUFSZ];
230 size_t ret_len; 230 size_t ret_len;
231 u64 objdump_addr; 231 u64 objdump_addr;
232 const char *objdump_name;
233 char decomp_name[KMOD_DECOMP_LEN];
232 int ret; 234 int ret;
233 235
234 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); 236 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
@@ -289,9 +291,25 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
289 state->done[state->done_cnt++] = al.map->start; 291 state->done[state->done_cnt++] = al.map->start;
290 } 292 }
291 293
294 objdump_name = al.map->dso->long_name;
295 if (dso__needs_decompress(al.map->dso)) {
296 if (dso__decompress_kmodule_path(al.map->dso, objdump_name,
297 decomp_name,
298 sizeof(decomp_name)) < 0) {
299 pr_debug("decompression failed\n");
300 return -1;
301 }
302
303 objdump_name = decomp_name;
304 }
305
292 /* Read the object code using objdump */ 306 /* Read the object code using objdump */
293 objdump_addr = map__rip_2objdump(al.map, al.addr); 307 objdump_addr = map__rip_2objdump(al.map, al.addr);
294 ret = read_via_objdump(al.map->dso->long_name, objdump_addr, buf2, len); 308 ret = read_via_objdump(objdump_name, objdump_addr, buf2, len);
309
310 if (dso__needs_decompress(al.map->dso))
311 unlink(objdump_name);
312
295 if (ret > 0) { 313 if (ret > 0) {
296 /* 314 /*
297 * The kernel maps are inaccurate - assume objdump is right in 315 * The kernel maps are inaccurate - assume objdump is right in
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index dfe5c89e2049..3e56d08f7995 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -76,8 +76,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
76 return strcmp((const char *) symbol, funcs[idx]); 76 return strcmp((const char *) symbol, funcs[idx]);
77} 77}
78 78
79__attribute__ ((noinline)) 79static noinline int unwind_thread(struct thread *thread)
80static int unwind_thread(struct thread *thread)
81{ 80{
82 struct perf_sample sample; 81 struct perf_sample sample;
83 unsigned long cnt = 0; 82 unsigned long cnt = 0;
@@ -108,8 +107,7 @@ static int unwind_thread(struct thread *thread)
108 107
109static int global_unwind_retval = -INT_MAX; 108static int global_unwind_retval = -INT_MAX;
110 109
111__attribute__ ((noinline)) 110static noinline int compare(void *p1, void *p2)
112static int compare(void *p1, void *p2)
113{ 111{
114 /* Any possible value should be 'thread' */ 112 /* Any possible value should be 'thread' */
115 struct thread *thread = *(struct thread **)p1; 113 struct thread *thread = *(struct thread **)p1;
@@ -128,8 +126,7 @@ static int compare(void *p1, void *p2)
128 return p1 - p2; 126 return p1 - p2;
129} 127}
130 128
131__attribute__ ((noinline)) 129static noinline int krava_3(struct thread *thread)
132static int krava_3(struct thread *thread)
133{ 130{
134 struct thread *array[2] = {thread, thread}; 131 struct thread *array[2] = {thread, thread};
135 void *fp = &bsearch; 132 void *fp = &bsearch;
@@ -147,14 +144,12 @@ static int krava_3(struct thread *thread)
147 return global_unwind_retval; 144 return global_unwind_retval;
148} 145}
149 146
150__attribute__ ((noinline)) 147static noinline int krava_2(struct thread *thread)
151static int krava_2(struct thread *thread)
152{ 148{
153 return krava_3(thread); 149 return krava_3(thread);
154} 150}
155 151
156__attribute__ ((noinline)) 152static noinline int krava_1(struct thread *thread)
157static int krava_1(struct thread *thread)
158{ 153{
159 return krava_2(thread); 154 return krava_2(thread);
160} 155}
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 7fad885491c5..812a053d1941 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -1810,17 +1810,6 @@ static int test_pmu_events(void)
1810 return ret; 1810 return ret;
1811} 1811}
1812 1812
1813static void debug_warn(const char *warn, va_list params)
1814{
1815 char msg[1024];
1816
1817 if (verbose <= 0)
1818 return;
1819
1820 vsnprintf(msg, sizeof(msg), warn, params);
1821 fprintf(stderr, " Warning: %s\n", msg);
1822}
1823
1824int test__parse_events(int subtest __maybe_unused) 1813int test__parse_events(int subtest __maybe_unused)
1825{ 1814{
1826 int ret1, ret2 = 0; 1815 int ret1, ret2 = 0;
@@ -1832,8 +1821,6 @@ do { \
1832 ret2 = ret1; \ 1821 ret2 = ret1; \
1833} while (0) 1822} while (0)
1834 1823
1835 set_warning_routine(debug_warn);
1836
1837 TEST_EVENTS(test__events); 1824 TEST_EVENTS(test__events);
1838 1825
1839 if (test_pmu()) 1826 if (test_pmu())
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 32873ec91a4e..cf00ebad2ef5 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -83,7 +83,7 @@ int test__task_exit(int subtest __maybe_unused)
83 83
84 evsel = perf_evlist__first(evlist); 84 evsel = perf_evlist__first(evlist);
85 evsel->attr.task = 1; 85 evsel->attr.task = 1;
86 evsel->attr.sample_freq = 0; 86 evsel->attr.sample_freq = 1;
87 evsel->attr.inherit = 0; 87 evsel->attr.inherit = 0;
88 evsel->attr.watermark = 0; 88 evsel->attr.watermark = 0;
89 evsel->attr.wakeup_events = 1; 89 evsel->attr.wakeup_events = 1;
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 631859629403..577363809c9b 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -34,6 +34,7 @@ struct test {
34 int (*get_nr)(void); 34 int (*get_nr)(void);
35 const char *(*get_desc)(int subtest); 35 const char *(*get_desc)(int subtest);
36 } subtest; 36 } subtest;
37 bool (*is_supported)(void);
37}; 38};
38 39
39/* Tests */ 40/* Tests */
@@ -99,6 +100,8 @@ const char *test__clang_subtest_get_desc(int subtest);
99int test__clang_subtest_get_nr(void); 100int test__clang_subtest_get_nr(void);
100int test__unit_number__scnprint(int subtest); 101int test__unit_number__scnprint(int subtest);
101 102
103bool test__bp_signal_is_supported(void);
104
102#if defined(__arm__) || defined(__aarch64__) 105#if defined(__arm__) || defined(__aarch64__)
103#ifdef HAVE_DWARF_UNWIND_SUPPORT 106#ifdef HAVE_DWARF_UNWIND_SUPPORT
104struct thread; 107struct thread;
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index d990ad08a3c6..27f41f28dcb4 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -46,12 +46,15 @@ static struct annotate_browser_opt {
46 .jump_arrows = true, 46 .jump_arrows = true,
47}; 47};
48 48
49struct arch;
50
49struct annotate_browser { 51struct annotate_browser {
50 struct ui_browser b; 52 struct ui_browser b;
51 struct rb_root entries; 53 struct rb_root entries;
52 struct rb_node *curr_hot; 54 struct rb_node *curr_hot;
53 struct disasm_line *selection; 55 struct disasm_line *selection;
54 struct disasm_line **offsets; 56 struct disasm_line **offsets;
57 struct arch *arch;
55 int nr_events; 58 int nr_events;
56 u64 start; 59 u64 start;
57 int nr_asm_entries; 60 int nr_asm_entries;
@@ -125,43 +128,57 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
125 int i, pcnt_width = annotate_browser__pcnt_width(ab); 128 int i, pcnt_width = annotate_browser__pcnt_width(ab);
126 double percent_max = 0.0; 129 double percent_max = 0.0;
127 char bf[256]; 130 char bf[256];
131 bool show_title = false;
128 132
129 for (i = 0; i < ab->nr_events; i++) { 133 for (i = 0; i < ab->nr_events; i++) {
130 if (bdl->samples[i].percent > percent_max) 134 if (bdl->samples[i].percent > percent_max)
131 percent_max = bdl->samples[i].percent; 135 percent_max = bdl->samples[i].percent;
132 } 136 }
133 137
138 if ((row == 0) && (dl->offset == -1 || percent_max == 0.0)) {
139 if (ab->have_cycles) {
140 if (dl->ipc == 0.0 && dl->cycles == 0)
141 show_title = true;
142 } else
143 show_title = true;
144 }
145
134 if (dl->offset != -1 && percent_max != 0.0) { 146 if (dl->offset != -1 && percent_max != 0.0) {
135 if (percent_max != 0.0) { 147 for (i = 0; i < ab->nr_events; i++) {
136 for (i = 0; i < ab->nr_events; i++) { 148 ui_browser__set_percent_color(browser,
137 ui_browser__set_percent_color(browser, 149 bdl->samples[i].percent,
138 bdl->samples[i].percent, 150 current_entry);
139 current_entry); 151 if (annotate_browser__opts.show_total_period) {
140 if (annotate_browser__opts.show_total_period) { 152 ui_browser__printf(browser, "%6" PRIu64 " ",
141 ui_browser__printf(browser, "%6" PRIu64 " ", 153 bdl->samples[i].nr);
142 bdl->samples[i].nr); 154 } else {
143 } else { 155 ui_browser__printf(browser, "%6.2f ",
144 ui_browser__printf(browser, "%6.2f ", 156 bdl->samples[i].percent);
145 bdl->samples[i].percent);
146 }
147 } 157 }
148 } else {
149 ui_browser__write_nstring(browser, " ", 7 * ab->nr_events);
150 } 158 }
151 } else { 159 } else {
152 ui_browser__set_percent_color(browser, 0, current_entry); 160 ui_browser__set_percent_color(browser, 0, current_entry);
153 ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); 161
162 if (!show_title)
163 ui_browser__write_nstring(browser, " ", 7 * ab->nr_events);
164 else
165 ui_browser__printf(browser, "%*s", 7, "Percent");
154 } 166 }
155 if (ab->have_cycles) { 167 if (ab->have_cycles) {
156 if (dl->ipc) 168 if (dl->ipc)
157 ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, dl->ipc); 169 ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, dl->ipc);
158 else 170 else if (!show_title)
159 ui_browser__write_nstring(browser, " ", IPC_WIDTH); 171 ui_browser__write_nstring(browser, " ", IPC_WIDTH);
172 else
173 ui_browser__printf(browser, "%*s ", IPC_WIDTH - 1, "IPC");
174
160 if (dl->cycles) 175 if (dl->cycles)
161 ui_browser__printf(browser, "%*" PRIu64 " ", 176 ui_browser__printf(browser, "%*" PRIu64 " ",
162 CYCLES_WIDTH - 1, dl->cycles); 177 CYCLES_WIDTH - 1, dl->cycles);
163 else 178 else if (!show_title)
164 ui_browser__write_nstring(browser, " ", CYCLES_WIDTH); 179 ui_browser__write_nstring(browser, " ", CYCLES_WIDTH);
180 else
181 ui_browser__printf(browser, "%*s ", CYCLES_WIDTH - 1, "Cycle");
165 } 182 }
166 183
167 SLsmg_write_char(' '); 184 SLsmg_write_char(' ');
@@ -1056,7 +1073,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1056 (nr_pcnt - 1); 1073 (nr_pcnt - 1);
1057 } 1074 }
1058 1075
1059 err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), sizeof_bdl); 1076 err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
1077 sizeof_bdl, &browser.arch);
1060 if (err) { 1078 if (err) {
1061 char msg[BUFSIZ]; 1079 char msg[BUFSIZ];
1062 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 1080 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index e99ba86158d2..d903fd493416 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -168,7 +168,8 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
168 if (map->dso->annotate_warned) 168 if (map->dso->annotate_warned)
169 return -1; 169 return -1;
170 170
171 err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 0); 171 err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
172 0, NULL);
172 if (err) { 173 if (err) {
173 char msg[BUFSIZ]; 174 char msg[BUFSIZ];
174 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 175 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 59addd52d9cd..ddb2c6fbdf91 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -210,6 +210,8 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b,
210 return 0; 210 return 0;
211 211
212 ret = b->callchain->max_depth - a->callchain->max_depth; 212 ret = b->callchain->max_depth - a->callchain->max_depth;
213 if (callchain_param.order == ORDER_CALLER)
214 ret = -ret;
213 } 215 }
214 return ret; 216 return ret;
215} 217}
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 683f8340460c..be1caabb9290 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -239,10 +239,20 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
239 const char *s = strchr(ops->raw, '+'); 239 const char *s = strchr(ops->raw, '+');
240 const char *c = strchr(ops->raw, ','); 240 const char *c = strchr(ops->raw, ',');
241 241
242 if (c++ != NULL) 242 /*
243 * skip over possible up to 2 operands to get to address, e.g.:
244 * tbnz w0, #26, ffff0000083cd190 <security_file_permission+0xd0>
245 */
246 if (c++ != NULL) {
243 ops->target.addr = strtoull(c, NULL, 16); 247 ops->target.addr = strtoull(c, NULL, 16);
244 else 248 if (!ops->target.addr) {
249 c = strchr(c, ',');
250 if (c++ != NULL)
251 ops->target.addr = strtoull(c, NULL, 16);
252 }
253 } else {
245 ops->target.addr = strtoull(ops->raw, NULL, 16); 254 ops->target.addr = strtoull(ops->raw, NULL, 16);
255 }
246 256
247 if (s++ != NULL) { 257 if (s++ != NULL) {
248 ops->target.offset = strtoull(s, NULL, 16); 258 ops->target.offset = strtoull(s, NULL, 16);
@@ -257,10 +267,27 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
257static int jump__scnprintf(struct ins *ins, char *bf, size_t size, 267static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
258 struct ins_operands *ops) 268 struct ins_operands *ops)
259{ 269{
270 const char *c = strchr(ops->raw, ',');
271
260 if (!ops->target.addr || ops->target.offset < 0) 272 if (!ops->target.addr || ops->target.offset < 0)
261 return ins__raw_scnprintf(ins, bf, size, ops); 273 return ins__raw_scnprintf(ins, bf, size, ops);
262 274
263 return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset); 275 if (c != NULL) {
276 const char *c2 = strchr(c + 1, ',');
277
278 /* check for 3-op insn */
279 if (c2 != NULL)
280 c = c2;
281 c++;
282
283 /* mirror arch objdump's space-after-comma style */
284 if (*c == ' ')
285 c++;
286 }
287
288 return scnprintf(bf, size, "%-6.6s %.*s%" PRIx64,
289 ins->name, c ? c - ops->raw : 0, ops->raw,
290 ops->target.offset);
264} 291}
265 292
266static struct ins_ops jump_ops = { 293static struct ins_ops jump_ops = {
@@ -1294,6 +1321,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
1294 char linkname[PATH_MAX]; 1321 char linkname[PATH_MAX];
1295 char *build_id_filename; 1322 char *build_id_filename;
1296 char *build_id_path = NULL; 1323 char *build_id_path = NULL;
1324 char *pos;
1297 1325
1298 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && 1326 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1299 !dso__is_kcore(dso)) 1327 !dso__is_kcore(dso))
@@ -1313,7 +1341,14 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
1313 if (!build_id_path) 1341 if (!build_id_path)
1314 return -1; 1342 return -1;
1315 1343
1316 dirname(build_id_path); 1344 /*
1345 * old style build-id cache has name of XX/XXXXXXX.. while
1346 * new style has XX/XXXXXXX../{elf,kallsyms,vdso}.
1347 * extract the build-id part of dirname in the new style only.
1348 */
1349 pos = strrchr(build_id_path, '/');
1350 if (pos && strlen(pos) < SBUILD_ID_SIZE - 2)
1351 dirname(build_id_path);
1317 1352
1318 if (dso__is_kcore(dso) || 1353 if (dso__is_kcore(dso) ||
1319 readlink(build_id_path, linkname, sizeof(linkname)) < 0 || 1354 readlink(build_id_path, linkname, sizeof(linkname)) < 0 ||
@@ -1344,7 +1379,9 @@ static const char *annotate__norm_arch(const char *arch_name)
1344 return normalize_arch((char *)arch_name); 1379 return normalize_arch((char *)arch_name);
1345} 1380}
1346 1381
1347int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_name, size_t privsize) 1382int symbol__disassemble(struct symbol *sym, struct map *map,
1383 const char *arch_name, size_t privsize,
1384 struct arch **parch)
1348{ 1385{
1349 struct dso *dso = map->dso; 1386 struct dso *dso = map->dso;
1350 char command[PATH_MAX * 2]; 1387 char command[PATH_MAX * 2];
@@ -1370,6 +1407,9 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
1370 if (arch == NULL) 1407 if (arch == NULL)
1371 return -ENOTSUP; 1408 return -ENOTSUP;
1372 1409
1410 if (parch)
1411 *parch = arch;
1412
1373 if (arch->init) { 1413 if (arch->init) {
1374 err = arch->init(arch); 1414 err = arch->init(arch);
1375 if (err) { 1415 if (err) {
@@ -1396,31 +1436,10 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
1396 sizeof(symfs_filename)); 1436 sizeof(symfs_filename));
1397 } 1437 }
1398 } else if (dso__needs_decompress(dso)) { 1438 } else if (dso__needs_decompress(dso)) {
1399 char tmp[PATH_MAX]; 1439 char tmp[KMOD_DECOMP_LEN];
1400 struct kmod_path m;
1401 int fd;
1402 bool ret;
1403
1404 if (kmod_path__parse_ext(&m, symfs_filename))
1405 goto out;
1406
1407 snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX");
1408
1409 fd = mkstemp(tmp);
1410 if (fd < 0) {
1411 free(m.ext);
1412 goto out;
1413 }
1414
1415 ret = decompress_to_file(m.ext, symfs_filename, fd);
1416
1417 if (ret)
1418 pr_err("Cannot decompress %s %s\n", m.ext, symfs_filename);
1419
1420 free(m.ext);
1421 close(fd);
1422 1440
1423 if (!ret) 1441 if (dso__decompress_kmodule_path(dso, symfs_filename,
1442 tmp, sizeof(tmp)) < 0)
1424 goto out; 1443 goto out;
1425 1444
1426 strcpy(symfs_filename, tmp); 1445 strcpy(symfs_filename, tmp);
@@ -1429,7 +1448,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
1429 snprintf(command, sizeof(command), 1448 snprintf(command, sizeof(command),
1430 "%s %s%s --start-address=0x%016" PRIx64 1449 "%s %s%s --start-address=0x%016" PRIx64
1431 " --stop-address=0x%016" PRIx64 1450 " --stop-address=0x%016" PRIx64
1432 " -l -d %s %s -C %s 2>/dev/null|grep -v %s:|expand", 1451 " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
1433 objdump_path ? objdump_path : "objdump", 1452 objdump_path ? objdump_path : "objdump",
1434 disassembler_style ? "-M " : "", 1453 disassembler_style ? "-M " : "",
1435 disassembler_style ? disassembler_style : "", 1454 disassembler_style ? disassembler_style : "",
@@ -1887,7 +1906,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1887 struct rb_root source_line = RB_ROOT; 1906 struct rb_root source_line = RB_ROOT;
1888 u64 len; 1907 u64 len;
1889 1908
1890 if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 0) < 0) 1909 if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
1910 0, NULL) < 0)
1891 return -1; 1911 return -1;
1892 1912
1893 len = symbol__size(sym); 1913 len = symbol__size(sym);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 948aa8e6fd39..21055034aedd 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -158,7 +158,9 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
158int symbol__alloc_hist(struct symbol *sym); 158int symbol__alloc_hist(struct symbol *sym);
159void symbol__annotate_zero_histograms(struct symbol *sym); 159void symbol__annotate_zero_histograms(struct symbol *sym);
160 160
161int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_name, size_t privsize); 161int symbol__disassemble(struct symbol *sym, struct map *map,
162 const char *arch_name, size_t privsize,
163 struct arch **parch);
162 164
163enum symbol_disassemble_errno { 165enum symbol_disassemble_errno {
164 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, 166 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 0daf63b9ee3e..5547457566a7 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -322,6 +322,13 @@ static int auxtrace_queues__add_event_buffer(struct auxtrace_queues *queues,
322 return auxtrace_queues__add_buffer(queues, idx, buffer); 322 return auxtrace_queues__add_buffer(queues, idx, buffer);
323} 323}
324 324
325static bool filter_cpu(struct perf_session *session, int cpu)
326{
327 unsigned long *cpu_bitmap = session->itrace_synth_opts->cpu_bitmap;
328
329 return cpu_bitmap && cpu != -1 && !test_bit(cpu, cpu_bitmap);
330}
331
325int auxtrace_queues__add_event(struct auxtrace_queues *queues, 332int auxtrace_queues__add_event(struct auxtrace_queues *queues,
326 struct perf_session *session, 333 struct perf_session *session,
327 union perf_event *event, off_t data_offset, 334 union perf_event *event, off_t data_offset,
@@ -331,6 +338,9 @@ int auxtrace_queues__add_event(struct auxtrace_queues *queues,
331 unsigned int idx; 338 unsigned int idx;
332 int err; 339 int err;
333 340
341 if (filter_cpu(session, event->auxtrace.cpu))
342 return 0;
343
334 buffer = zalloc(sizeof(struct auxtrace_buffer)); 344 buffer = zalloc(sizeof(struct auxtrace_buffer));
335 if (!buffer) 345 if (!buffer)
336 return -ENOMEM; 346 return -ENOMEM;
@@ -947,6 +957,8 @@ void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts)
947 synth_opts->instructions = true; 957 synth_opts->instructions = true;
948 synth_opts->branches = true; 958 synth_opts->branches = true;
949 synth_opts->transactions = true; 959 synth_opts->transactions = true;
960 synth_opts->ptwrites = true;
961 synth_opts->pwr_events = true;
950 synth_opts->errors = true; 962 synth_opts->errors = true;
951 synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE; 963 synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE;
952 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; 964 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
@@ -1030,6 +1042,12 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
1030 case 'x': 1042 case 'x':
1031 synth_opts->transactions = true; 1043 synth_opts->transactions = true;
1032 break; 1044 break;
1045 case 'w':
1046 synth_opts->ptwrites = true;
1047 break;
1048 case 'p':
1049 synth_opts->pwr_events = true;
1050 break;
1033 case 'e': 1051 case 'e':
1034 synth_opts->errors = true; 1052 synth_opts->errors = true;
1035 break; 1053 break;
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 9f0de72d58e2..33b5e6cdf38c 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -59,6 +59,8 @@ enum itrace_period_type {
59 * @instructions: whether to synthesize 'instructions' events 59 * @instructions: whether to synthesize 'instructions' events
60 * @branches: whether to synthesize 'branches' events 60 * @branches: whether to synthesize 'branches' events
61 * @transactions: whether to synthesize events for transactions 61 * @transactions: whether to synthesize events for transactions
62 * @ptwrites: whether to synthesize events for ptwrites
63 * @pwr_events: whether to synthesize power events
62 * @errors: whether to synthesize decoder error events 64 * @errors: whether to synthesize decoder error events
63 * @dont_decode: whether to skip decoding entirely 65 * @dont_decode: whether to skip decoding entirely
64 * @log: write a decoding log 66 * @log: write a decoding log
@@ -72,6 +74,7 @@ enum itrace_period_type {
72 * @period: 'instructions' events period 74 * @period: 'instructions' events period
73 * @period_type: 'instructions' events period type 75 * @period_type: 'instructions' events period type
74 * @initial_skip: skip N events at the beginning. 76 * @initial_skip: skip N events at the beginning.
77 * @cpu_bitmap: CPUs for which to synthesize events, or NULL for all
75 */ 78 */
76struct itrace_synth_opts { 79struct itrace_synth_opts {
77 bool set; 80 bool set;
@@ -79,6 +82,8 @@ struct itrace_synth_opts {
79 bool instructions; 82 bool instructions;
80 bool branches; 83 bool branches;
81 bool transactions; 84 bool transactions;
85 bool ptwrites;
86 bool pwr_events;
82 bool errors; 87 bool errors;
83 bool dont_decode; 88 bool dont_decode;
84 bool log; 89 bool log;
@@ -92,6 +97,7 @@ struct itrace_synth_opts {
92 unsigned long long period; 97 unsigned long long period;
93 enum itrace_period_type period_type; 98 enum itrace_period_type period_type;
94 unsigned long initial_skip; 99 unsigned long initial_skip;
100 unsigned long *cpu_bitmap;
95}; 101};
96 102
97/** 103/**
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 168cc49654e7..e0148b081bdf 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -278,51 +278,6 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
278 return bf; 278 return bf;
279} 279}
280 280
281bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
282{
283 char *id_name = NULL, *ch;
284 struct stat sb;
285 char sbuild_id[SBUILD_ID_SIZE];
286
287 if (!dso->has_build_id)
288 goto err;
289
290 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
291 id_name = build_id_cache__linkname(sbuild_id, NULL, 0);
292 if (!id_name)
293 goto err;
294 if (access(id_name, F_OK))
295 goto err;
296 if (lstat(id_name, &sb) == -1)
297 goto err;
298 if ((size_t)sb.st_size > size - 1)
299 goto err;
300 if (readlink(id_name, bf, size - 1) < 0)
301 goto err;
302
303 bf[sb.st_size] = '\0';
304
305 /*
306 * link should be:
307 * ../../lib/modules/4.4.0-rc4/kernel/net/ipv4/netfilter/nf_nat_ipv4.ko/a09fe3eb3147dafa4e3b31dbd6257e4d696bdc92
308 */
309 ch = strrchr(bf, '/');
310 if (!ch)
311 goto err;
312 if (ch - 3 < bf)
313 goto err;
314
315 free(id_name);
316 return strncmp(".ko", ch - 3, 3) == 0;
317err:
318 pr_err("Invalid build id: %s\n", id_name ? :
319 dso->long_name ? :
320 dso->short_name ? :
321 "[unknown]");
322 free(id_name);
323 return false;
324}
325
326#define dsos__for_each_with_build_id(pos, head) \ 281#define dsos__for_each_with_build_id(pos, head) \
327 list_for_each_entry(pos, head, node) \ 282 list_for_each_entry(pos, head, node) \
328 if (!pos->has_build_id) \ 283 if (!pos->has_build_id) \
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 8a89b195c1fc..96690a55c62c 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -17,7 +17,6 @@ char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
17 size_t size); 17 size_t size);
18 18
19char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); 19char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
20bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size);
21 20
22int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, 21int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
23 struct perf_sample *sample, struct perf_evsel *evsel, 22 struct perf_sample *sample, struct perf_evsel *evsel,
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 0328f297a748..0175765c05b9 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -5,6 +5,7 @@
5#include <subcmd/pager.h> 5#include <subcmd/pager.h>
6#include "../ui/ui.h" 6#include "../ui/ui.h"
7 7
8#include <linux/compiler.h>
8#include <linux/string.h> 9#include <linux/string.h>
9 10
10#define CMD_EXEC_PATH "--exec-path" 11#define CMD_EXEC_PATH "--exec-path"
@@ -24,6 +25,6 @@ static inline int is_absolute_path(const char *path)
24 return path[0] == '/'; 25 return path[0] == '/';
25} 26}
26 27
27char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); 28char *mkpath(const char *fmt, ...) __printf(1, 2);
28 29
29#endif /* __PERF_CACHE_H */ 30#endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 81fc29ac798f..b4204b43ed58 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -621,14 +621,19 @@ enum match_result {
621static enum match_result match_chain_srcline(struct callchain_cursor_node *node, 621static enum match_result match_chain_srcline(struct callchain_cursor_node *node,
622 struct callchain_list *cnode) 622 struct callchain_list *cnode)
623{ 623{
624 char *left = get_srcline(cnode->ms.map->dso, 624 char *left = NULL;
625 char *right = NULL;
626 enum match_result ret = MATCH_EQ;
627 int cmp;
628
629 if (cnode->ms.map)
630 left = get_srcline(cnode->ms.map->dso,
625 map__rip_2objdump(cnode->ms.map, cnode->ip), 631 map__rip_2objdump(cnode->ms.map, cnode->ip),
626 cnode->ms.sym, true, false); 632 cnode->ms.sym, true, false);
627 char *right = get_srcline(node->map->dso, 633 if (node->map)
634 right = get_srcline(node->map->dso,
628 map__rip_2objdump(node->map, node->ip), 635 map__rip_2objdump(node->map, node->ip),
629 node->sym, true, false); 636 node->sym, true, false);
630 enum match_result ret = MATCH_EQ;
631 int cmp;
632 637
633 if (left && right) 638 if (left && right)
634 cmp = strcmp(left, right); 639 cmp = strcmp(left, right);
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 8d724f0fa5a8..31a7dea248d0 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -335,32 +335,42 @@ static int perf_parse_long(const char *value, long *ret)
335 return 0; 335 return 0;
336} 336}
337 337
338static void die_bad_config(const char *name) 338static void bad_config(const char *name)
339{ 339{
340 if (config_file_name) 340 if (config_file_name)
341 die("bad config value for '%s' in %s", name, config_file_name); 341 pr_warning("bad config value for '%s' in %s, ignoring...\n", name, config_file_name);
342 die("bad config value for '%s'", name); 342 else
343 pr_warning("bad config value for '%s', ignoring...\n", name);
343} 344}
344 345
345u64 perf_config_u64(const char *name, const char *value) 346int perf_config_u64(u64 *dest, const char *name, const char *value)
346{ 347{
347 long long ret = 0; 348 long long ret = 0;
348 349
349 if (!perf_parse_llong(value, &ret)) 350 if (!perf_parse_llong(value, &ret)) {
350 die_bad_config(name); 351 bad_config(name);
351 return (u64) ret; 352 return -1;
353 }
354
355 *dest = ret;
356 return 0;
352} 357}
353 358
354int perf_config_int(const char *name, const char *value) 359int perf_config_int(int *dest, const char *name, const char *value)
355{ 360{
356 long ret = 0; 361 long ret = 0;
357 if (!perf_parse_long(value, &ret)) 362 if (!perf_parse_long(value, &ret)) {
358 die_bad_config(name); 363 bad_config(name);
359 return ret; 364 return -1;
365 }
366 *dest = ret;
367 return 0;
360} 368}
361 369
362static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool) 370static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool)
363{ 371{
372 int ret;
373
364 *is_bool = 1; 374 *is_bool = 1;
365 if (!value) 375 if (!value)
366 return 1; 376 return 1;
@@ -371,7 +381,7 @@ static int perf_config_bool_or_int(const char *name, const char *value, int *is_
371 if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off")) 381 if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off"))
372 return 0; 382 return 0;
373 *is_bool = 0; 383 *is_bool = 0;
374 return perf_config_int(name, value); 384 return perf_config_int(&ret, name, value) < 0 ? -1 : ret;
375} 385}
376 386
377int perf_config_bool(const char *name, const char *value) 387int perf_config_bool(const char *name, const char *value)
@@ -657,8 +667,7 @@ static int perf_config_set__init(struct perf_config_set *set)
657 667
658 user_config = strdup(mkpath("%s/.perfconfig", home)); 668 user_config = strdup(mkpath("%s/.perfconfig", home));
659 if (user_config == NULL) { 669 if (user_config == NULL) {
660 warning("Not enough memory to process %s/.perfconfig, " 670 pr_warning("Not enough memory to process %s/.perfconfig, ignoring it.", home);
661 "ignoring it.", home);
662 goto out; 671 goto out;
663 } 672 }
664 673
@@ -671,8 +680,7 @@ static int perf_config_set__init(struct perf_config_set *set)
671 ret = 0; 680 ret = 0;
672 681
673 if (st.st_uid && (st.st_uid != geteuid())) { 682 if (st.st_uid && (st.st_uid != geteuid())) {
674 warning("File %s not owned by current user or root, " 683 pr_warning("File %s not owned by current user or root, ignoring it.", user_config);
675 "ignoring it.", user_config);
676 goto out_free; 684 goto out_free;
677 } 685 }
678 686
@@ -795,7 +803,8 @@ void perf_config_set__delete(struct perf_config_set *set)
795 */ 803 */
796int config_error_nonbool(const char *var) 804int config_error_nonbool(const char *var)
797{ 805{
798 return error("Missing value for '%s'", var); 806 pr_err("Missing value for '%s'", var);
807 return -1;
799} 808}
800 809
801void set_buildid_dir(const char *dir) 810void set_buildid_dir(const char *dir)
diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h
index 1a59a6b43f8b..b6bb11f3f165 100644
--- a/tools/perf/util/config.h
+++ b/tools/perf/util/config.h
@@ -27,8 +27,8 @@ extern const char *config_exclusive_filename;
27typedef int (*config_fn_t)(const char *, const char *, void *); 27typedef int (*config_fn_t)(const char *, const char *, void *);
28int perf_default_config(const char *, const char *, void *); 28int perf_default_config(const char *, const char *, void *);
29int perf_config(config_fn_t fn, void *); 29int perf_config(config_fn_t fn, void *);
30int perf_config_int(const char *, const char *); 30int perf_config_int(int *dest, const char *, const char *);
31u64 perf_config_u64(const char *, const char *); 31int perf_config_u64(u64 *dest, const char *, const char *);
32int perf_config_bool(const char *, const char *); 32int perf_config_bool(const char *, const char *);
33int config_error_nonbool(const char *); 33int config_error_nonbool(const char *);
34const char *perf_etc_perfconfig(void); 34const char *perf_etc_perfconfig(void);
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 89d50318833d..3149b70799fd 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -1444,10 +1444,8 @@ static int convert__config(const char *var, const char *value, void *cb)
1444{ 1444{
1445 struct convert *c = cb; 1445 struct convert *c = cb;
1446 1446
1447 if (!strcmp(var, "convert.queue-size")) { 1447 if (!strcmp(var, "convert.queue-size"))
1448 c->queue_size = perf_config_u64(var, value); 1448 return perf_config_u64(&c->queue_size, var, value);
1449 return 0;
1450 }
1451 1449
1452 return 0; 1450 return 0;
1453} 1451}
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 8a23ea1a71c7..c818bdb1c1ab 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -4,6 +4,7 @@
4 4
5#include <stdbool.h> 5#include <stdbool.h>
6#include <string.h> 6#include <string.h>
7#include <linux/compiler.h>
7#include "event.h" 8#include "event.h"
8#include "../ui/helpline.h" 9#include "../ui/helpline.h"
9#include "../ui/progress.h" 10#include "../ui/progress.h"
@@ -40,16 +41,16 @@ extern int debug_data_convert;
40 41
41#define STRERR_BUFSIZE 128 /* For the buffer size of str_error_r */ 42#define STRERR_BUFSIZE 128 /* For the buffer size of str_error_r */
42 43
43int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 44int dump_printf(const char *fmt, ...) __printf(1, 2);
44void trace_event(union perf_event *event); 45void trace_event(union perf_event *event);
45 46
46int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); 47int ui__error(const char *format, ...) __printf(1, 2);
47int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); 48int ui__warning(const char *format, ...) __printf(1, 2);
48 49
49void pr_stat(const char *fmt, ...); 50void pr_stat(const char *fmt, ...);
50 51
51int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4))); 52int eprintf(int level, int var, const char *fmt, ...) __printf(3, 4);
52int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __attribute__((format(printf, 4, 5))); 53int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __printf(4, 5);
53int veprintf(int level, int var, const char *fmt, va_list args); 54int veprintf(int level, int var, const char *fmt, va_list args);
54 55
55int perf_debug_option(const char *str); 56int perf_debug_option(const char *str);
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index a96a99d2369f..4e7ab611377a 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -248,6 +248,64 @@ bool dso__needs_decompress(struct dso *dso)
248 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; 248 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
249} 249}
250 250
251static int decompress_kmodule(struct dso *dso, const char *name, char *tmpbuf)
252{
253 int fd = -1;
254 struct kmod_path m;
255
256 if (!dso__needs_decompress(dso))
257 return -1;
258
259 if (kmod_path__parse_ext(&m, dso->long_name))
260 return -1;
261
262 if (!m.comp)
263 goto out;
264
265 fd = mkstemp(tmpbuf);
266 if (fd < 0) {
267 dso->load_errno = errno;
268 goto out;
269 }
270
271 if (!decompress_to_file(m.ext, name, fd)) {
272 dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
273 close(fd);
274 fd = -1;
275 }
276
277out:
278 free(m.ext);
279 return fd;
280}
281
282int dso__decompress_kmodule_fd(struct dso *dso, const char *name)
283{
284 char tmpbuf[] = KMOD_DECOMP_NAME;
285 int fd;
286
287 fd = decompress_kmodule(dso, name, tmpbuf);
288 unlink(tmpbuf);
289 return fd;
290}
291
292int dso__decompress_kmodule_path(struct dso *dso, const char *name,
293 char *pathname, size_t len)
294{
295 char tmpbuf[] = KMOD_DECOMP_NAME;
296 int fd;
297
298 fd = decompress_kmodule(dso, name, tmpbuf);
299 if (fd < 0) {
300 unlink(tmpbuf);
301 return -1;
302 }
303
304 strncpy(pathname, tmpbuf, len);
305 close(fd);
306 return 0;
307}
308
251/* 309/*
252 * Parses kernel module specified in @path and updates 310 * Parses kernel module specified in @path and updates
253 * @m argument like: 311 * @m argument like:
@@ -335,6 +393,21 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
335 return 0; 393 return 0;
336} 394}
337 395
396void dso__set_module_info(struct dso *dso, struct kmod_path *m,
397 struct machine *machine)
398{
399 if (machine__is_host(machine))
400 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
401 else
402 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
403
404 /* _KMODULE_COMP should be next to _KMODULE */
405 if (m->kmod && m->comp)
406 dso->symtab_type++;
407
408 dso__set_short_name(dso, strdup(m->name), true);
409}
410
338/* 411/*
339 * Global list of open DSOs and the counter. 412 * Global list of open DSOs and the counter.
340 */ 413 */
@@ -381,7 +454,7 @@ static int do_open(char *name)
381 454
382static int __open_dso(struct dso *dso, struct machine *machine) 455static int __open_dso(struct dso *dso, struct machine *machine)
383{ 456{
384 int fd; 457 int fd = -EINVAL;
385 char *root_dir = (char *)""; 458 char *root_dir = (char *)"";
386 char *name = malloc(PATH_MAX); 459 char *name = malloc(PATH_MAX);
387 460
@@ -392,15 +465,30 @@ static int __open_dso(struct dso *dso, struct machine *machine)
392 root_dir = machine->root_dir; 465 root_dir = machine->root_dir;
393 466
394 if (dso__read_binary_type_filename(dso, dso->binary_type, 467 if (dso__read_binary_type_filename(dso, dso->binary_type,
395 root_dir, name, PATH_MAX)) { 468 root_dir, name, PATH_MAX))
396 free(name); 469 goto out;
397 return -EINVAL;
398 }
399 470
400 if (!is_regular_file(name)) 471 if (!is_regular_file(name))
401 return -EINVAL; 472 goto out;
473
474 if (dso__needs_decompress(dso)) {
475 char newpath[KMOD_DECOMP_LEN];
476 size_t len = sizeof(newpath);
477
478 if (dso__decompress_kmodule_path(dso, name, newpath, len) < 0) {
479 fd = -dso->load_errno;
480 goto out;
481 }
482
483 strcpy(name, newpath);
484 }
402 485
403 fd = do_open(name); 486 fd = do_open(name);
487
488 if (dso__needs_decompress(dso))
489 unlink(name);
490
491out:
404 free(name); 492 free(name);
405 return fd; 493 return fd;
406} 494}
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 12350b171727..bd061ba7b47c 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -244,6 +244,12 @@ bool is_supported_compression(const char *ext);
244bool is_kernel_module(const char *pathname, int cpumode); 244bool is_kernel_module(const char *pathname, int cpumode);
245bool decompress_to_file(const char *ext, const char *filename, int output_fd); 245bool decompress_to_file(const char *ext, const char *filename, int output_fd);
246bool dso__needs_decompress(struct dso *dso); 246bool dso__needs_decompress(struct dso *dso);
247int dso__decompress_kmodule_fd(struct dso *dso, const char *name);
248int dso__decompress_kmodule_path(struct dso *dso, const char *name,
249 char *pathname, size_t len);
250
251#define KMOD_DECOMP_NAME "/tmp/perf-kmod-XXXXXX"
252#define KMOD_DECOMP_LEN sizeof(KMOD_DECOMP_NAME)
247 253
248struct kmod_path { 254struct kmod_path {
249 char *name; 255 char *name;
@@ -259,6 +265,9 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
259#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false) 265#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false)
260#define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true) 266#define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true)
261 267
268void dso__set_module_info(struct dso *dso, struct kmod_path *m,
269 struct machine *machine);
270
262/* 271/*
263 * The dso__data_* external interface provides following functions: 272 * The dso__data_* external interface provides following functions:
264 * dso__data_get_fd 273 * dso__data_get_fd
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 7c3fa1c8cbcd..9967c87af7a6 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -252,6 +252,127 @@ enum auxtrace_error_type {
252 PERF_AUXTRACE_ERROR_MAX 252 PERF_AUXTRACE_ERROR_MAX
253}; 253};
254 254
255/* Attribute type for custom synthesized events */
256#define PERF_TYPE_SYNTH (INT_MAX + 1U)
257
258/* Attribute config for custom synthesized events */
259enum perf_synth_id {
260 PERF_SYNTH_INTEL_PTWRITE,
261 PERF_SYNTH_INTEL_MWAIT,
262 PERF_SYNTH_INTEL_PWRE,
263 PERF_SYNTH_INTEL_EXSTOP,
264 PERF_SYNTH_INTEL_PWRX,
265 PERF_SYNTH_INTEL_CBR,
266};
267
268/*
269 * Raw data formats for synthesized events. Note that 4 bytes of padding are
270 * present to match the 'size' member of PERF_SAMPLE_RAW data which is always
271 * 8-byte aligned. That means we must dereference raw_data with an offset of 4.
272 * Refer perf_sample__synth_ptr() and perf_synth__raw_data(). It also means the
273 * structure sizes are 4 bytes bigger than the raw_size, refer
274 * perf_synth__raw_size().
275 */
276
277struct perf_synth_intel_ptwrite {
278 u32 padding;
279 union {
280 struct {
281 u32 ip : 1,
282 reserved : 31;
283 };
284 u32 flags;
285 };
286 u64 payload;
287};
288
289struct perf_synth_intel_mwait {
290 u32 padding;
291 u32 reserved;
292 union {
293 struct {
294 u64 hints : 8,
295 reserved1 : 24,
296 extensions : 2,
297 reserved2 : 30;
298 };
299 u64 payload;
300 };
301};
302
303struct perf_synth_intel_pwre {
304 u32 padding;
305 u32 reserved;
306 union {
307 struct {
308 u64 reserved1 : 7,
309 hw : 1,
310 subcstate : 4,
311 cstate : 4,
312 reserved2 : 48;
313 };
314 u64 payload;
315 };
316};
317
318struct perf_synth_intel_exstop {
319 u32 padding;
320 union {
321 struct {
322 u32 ip : 1,
323 reserved : 31;
324 };
325 u32 flags;
326 };
327};
328
329struct perf_synth_intel_pwrx {
330 u32 padding;
331 u32 reserved;
332 union {
333 struct {
334 u64 deepest_cstate : 4,
335 last_cstate : 4,
336 wake_reason : 4,
337 reserved1 : 52;
338 };
339 u64 payload;
340 };
341};
342
343struct perf_synth_intel_cbr {
344 u32 padding;
345 union {
346 struct {
347 u32 cbr : 8,
348 reserved1 : 8,
349 max_nonturbo : 8,
350 reserved2 : 8;
351 };
352 u32 flags;
353 };
354 u32 freq;
355 u32 reserved3;
356};
357
358/*
359 * raw_data is always 4 bytes from an 8-byte boundary, so subtract 4 to get
360 * 8-byte alignment.
361 */
362static inline void *perf_sample__synth_ptr(struct perf_sample *sample)
363{
364 return sample->raw_data - 4;
365}
366
367static inline void *perf_synth__raw_data(void *p)
368{
369 return p + 4;
370}
371
372#define perf_synth__raw_size(d) (sizeof(d) - 4)
373
374#define perf_sample__bad_synth_size(s, d) ((s)->raw_size < sizeof(d) - 4)
375
255/* 376/*
256 * The kernel collects the number of events it couldn't send in a stretch and 377 * The kernel collects the number of events it couldn't send in a stretch and
257 * when possible sends this number in a PERF_RECORD_LOST event. The number of 378 * when possible sends this number in a PERF_RECORD_LOST event. The number of
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 94cea4398a13..8d601fbdd8d6 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -1,6 +1,7 @@
1#ifndef __PERF_EVLIST_H 1#ifndef __PERF_EVLIST_H
2#define __PERF_EVLIST_H 1 2#define __PERF_EVLIST_H 1
3 3
4#include <linux/compiler.h>
4#include <linux/kernel.h> 5#include <linux/kernel.h>
5#include <linux/refcount.h> 6#include <linux/refcount.h>
6#include <linux/list.h> 7#include <linux/list.h>
@@ -34,7 +35,7 @@ struct perf_mmap {
34 refcount_t refcnt; 35 refcount_t refcnt;
35 u64 prev; 36 u64 prev;
36 struct auxtrace_mmap auxtrace_mmap; 37 struct auxtrace_mmap auxtrace_mmap;
37 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); 38 char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8);
38}; 39};
39 40
40static inline size_t 41static inline size_t
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index e4f7902d5afa..6f4882f8d61f 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -11,13 +11,17 @@
11#include <errno.h> 11#include <errno.h>
12#include <inttypes.h> 12#include <inttypes.h>
13#include <linux/bitops.h> 13#include <linux/bitops.h>
14#include <api/fs/fs.h>
14#include <api/fs/tracing_path.h> 15#include <api/fs/tracing_path.h>
15#include <traceevent/event-parse.h> 16#include <traceevent/event-parse.h>
16#include <linux/hw_breakpoint.h> 17#include <linux/hw_breakpoint.h>
17#include <linux/perf_event.h> 18#include <linux/perf_event.h>
19#include <linux/compiler.h>
18#include <linux/err.h> 20#include <linux/err.h>
19#include <sys/ioctl.h> 21#include <sys/ioctl.h>
20#include <sys/resource.h> 22#include <sys/resource.h>
23#include <sys/types.h>
24#include <dirent.h>
21#include "asm/bug.h" 25#include "asm/bug.h"
22#include "callchain.h" 26#include "callchain.h"
23#include "cgroup.h" 27#include "cgroup.h"
@@ -273,8 +277,20 @@ struct perf_evsel *perf_evsel__new_cycles(void)
273 struct perf_evsel *evsel; 277 struct perf_evsel *evsel;
274 278
275 event_attr_init(&attr); 279 event_attr_init(&attr);
280 /*
281 * Unnamed union member, not supported as struct member named
282 * initializer in older compilers such as gcc 4.4.7
283 *
284 * Just for probing the precise_ip:
285 */
286 attr.sample_period = 1;
276 287
277 perf_event_attr__set_max_precise_ip(&attr); 288 perf_event_attr__set_max_precise_ip(&attr);
289 /*
290 * Now let the usual logic to set up the perf_event_attr defaults
291 * to kick in when we return and before perf_evsel__open() is called.
292 */
293 attr.sample_period = 0;
278 294
279 evsel = perf_evsel__new(&attr); 295 evsel = perf_evsel__new(&attr);
280 if (evsel == NULL) 296 if (evsel == NULL)
@@ -1429,7 +1445,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
1429} 1445}
1430 1446
1431static int __open_attr__fprintf(FILE *fp, const char *name, const char *val, 1447static int __open_attr__fprintf(FILE *fp, const char *name, const char *val,
1432 void *priv __attribute__((unused))) 1448 void *priv __maybe_unused)
1433{ 1449{
1434 return fprintf(fp, " %-32s %s\n", name, val); 1450 return fprintf(fp, " %-32s %s\n", name, val);
1435} 1451}
@@ -2459,6 +2475,42 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2459 return false; 2475 return false;
2460} 2476}
2461 2477
2478static bool find_process(const char *name)
2479{
2480 size_t len = strlen(name);
2481 DIR *dir;
2482 struct dirent *d;
2483 int ret = -1;
2484
2485 dir = opendir(procfs__mountpoint());
2486 if (!dir)
2487 return false;
2488
2489 /* Walk through the directory. */
2490 while (ret && (d = readdir(dir)) != NULL) {
2491 char path[PATH_MAX];
2492 char *data;
2493 size_t size;
2494
2495 if ((d->d_type != DT_DIR) ||
2496 !strcmp(".", d->d_name) ||
2497 !strcmp("..", d->d_name))
2498 continue;
2499
2500 scnprintf(path, sizeof(path), "%s/%s/comm",
2501 procfs__mountpoint(), d->d_name);
2502
2503 if (filename__read_str(path, &data, &size))
2504 continue;
2505
2506 ret = strncmp(name, data, len);
2507 free(data);
2508 }
2509
2510 closedir(dir);
2511 return ret ? false : true;
2512}
2513
2462int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, 2514int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2463 int err, char *msg, size_t size) 2515 int err, char *msg, size_t size)
2464{ 2516{
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index e415aee6a245..583f3a602506 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -7,6 +7,7 @@
7#include "map.h" 7#include "map.h"
8#include "strlist.h" 8#include "strlist.h"
9#include "symbol.h" 9#include "symbol.h"
10#include "srcline.h"
10 11
11static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...) 12static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
12{ 13{
@@ -168,6 +169,38 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
168 if (!print_oneline) 169 if (!print_oneline)
169 printed += fprintf(fp, "\n"); 170 printed += fprintf(fp, "\n");
170 171
172 if (symbol_conf.inline_name && node->map) {
173 struct inline_node *inode;
174
175 addr = map__rip_2objdump(node->map, node->ip),
176 inode = dso__parse_addr_inlines(node->map->dso, addr);
177
178 if (inode) {
179 struct inline_list *ilist;
180
181 list_for_each_entry(ilist, &inode->val, list) {
182 if (print_arrow)
183 printed += fprintf(fp, " <-");
184
185 /* IP is same, just skip it */
186 if (print_ip)
187 printed += fprintf(fp, "%c%16s",
188 s, "");
189 if (print_sym)
190 printed += fprintf(fp, " %s",
191 ilist->funcname);
192 if (print_srcline)
193 printed += fprintf(fp, "\n %s:%d",
194 ilist->filename,
195 ilist->line_nr);
196 if (!print_oneline)
197 printed += fprintf(fp, "\n");
198 }
199
200 inline_node__delete(inode);
201 }
202 }
203
171 if (symbol_conf.bt_stop_list && 204 if (symbol_conf.bt_stop_list &&
172 node->sym && 205 node->sym &&
173 strlist__has_entry(symbol_conf.bt_stop_list, 206 strlist__has_entry(symbol_conf.bt_stop_list,
diff --git a/tools/perf/util/genelf_debug.c b/tools/perf/util/genelf_debug.c
index 5980f7d256b1..40789d8603d0 100644
--- a/tools/perf/util/genelf_debug.c
+++ b/tools/perf/util/genelf_debug.c
@@ -11,6 +11,7 @@
11 * @remark Copyright 2007 OProfile authors 11 * @remark Copyright 2007 OProfile authors
12 * @author Philippe Elie 12 * @author Philippe Elie
13 */ 13 */
14#include <linux/compiler.h>
14#include <sys/types.h> 15#include <sys/types.h>
15#include <stdio.h> 16#include <stdio.h>
16#include <getopt.h> 17#include <getopt.h>
@@ -125,7 +126,7 @@ struct debug_line_header {
125 * and filesize, last entry is followed by en empty string. 126 * and filesize, last entry is followed by en empty string.
126 */ 127 */
127 /* follow the first program statement */ 128 /* follow the first program statement */
128} __attribute__((packed)); 129} __packed;
129 130
130/* DWARF 2 spec talk only about one possible compilation unit header while 131/* DWARF 2 spec talk only about one possible compilation unit header while
131 * binutils can handle two flavours of dwarf 2, 32 and 64 bits, this is not 132 * binutils can handle two flavours of dwarf 2, 32 and 64 bits, this is not
@@ -138,7 +139,7 @@ struct compilation_unit_header {
138 uhalf version; 139 uhalf version;
139 uword debug_abbrev_offset; 140 uword debug_abbrev_offset;
140 ubyte pointer_size; 141 ubyte pointer_size;
141} __attribute__((packed)); 142} __packed;
142 143
143#define DW_LNS_num_opcode (DW_LNS_set_isa + 1) 144#define DW_LNS_num_opcode (DW_LNS_set_isa + 1)
144 145
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 314a07151fb7..76ed7d03e500 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -8,6 +8,7 @@
8#include <unistd.h> 8#include <unistd.h>
9#include <stdio.h> 9#include <stdio.h>
10#include <stdlib.h> 10#include <stdlib.h>
11#include <linux/compiler.h>
11#include <linux/list.h> 12#include <linux/list.h>
12#include <linux/kernel.h> 13#include <linux/kernel.h>
13#include <linux/bitops.h> 14#include <linux/bitops.h>
@@ -841,7 +842,7 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
841 842
842/* 843/*
843 * default get_cpuid(): nothing gets recorded 844 * default get_cpuid(): nothing gets recorded
844 * actual implementation must be in arch/$(ARCH)/util/header.c 845 * actual implementation must be in arch/$(SRCARCH)/util/header.c
845 */ 846 */
846int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused) 847int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
847{ 848{
@@ -1274,7 +1275,7 @@ error:
1274} 1275}
1275 1276
1276static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val, 1277static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val,
1277 void *priv __attribute__((unused))) 1278 void *priv __maybe_unused)
1278{ 1279{
1279 return fprintf(fp, ", %s = %s", name, val); 1280 return fprintf(fp, ", %s = %s", name, val);
1280} 1281}
@@ -1469,8 +1470,16 @@ static int __event_process_build_id(struct build_id_event *bev,
1469 1470
1470 dso__set_build_id(dso, &bev->build_id); 1471 dso__set_build_id(dso, &bev->build_id);
1471 1472
1472 if (!is_kernel_module(filename, cpumode)) 1473 if (dso_type != DSO_TYPE_USER) {
1473 dso->kernel = dso_type; 1474 struct kmod_path m = { .name = NULL, };
1475
1476 if (!kmod_path__parse_name(&m, filename) && m.kmod)
1477 dso__set_module_info(dso, &m, machine);
1478 else
1479 dso->kernel = dso_type;
1480
1481 free(m.name);
1482 }
1474 1483
1475 build_id__sprintf(dso->build_id, sizeof(dso->build_id), 1484 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1476 sbuild_id); 1485 sbuild_id);
diff --git a/tools/perf/util/help-unknown-cmd.c b/tools/perf/util/help-unknown-cmd.c
index 1c88ad6425b8..15b95300d7f3 100644
--- a/tools/perf/util/help-unknown-cmd.c
+++ b/tools/perf/util/help-unknown-cmd.c
@@ -12,7 +12,7 @@ static int perf_unknown_cmd_config(const char *var, const char *value,
12 void *cb __maybe_unused) 12 void *cb __maybe_unused)
13{ 13{
14 if (!strcmp(var, "help.autocorrect")) 14 if (!strcmp(var, "help.autocorrect"))
15 autocorrect = perf_config_int(var,value); 15 return perf_config_int(&autocorrect, var,value);
16 16
17 return 0; 17 return 0;
18} 18}
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index b2834ac7b1f5..218ee2bac9a5 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -866,8 +866,6 @@ static void intel_bts_print_info(u64 *arr, int start, int finish)
866 fprintf(stdout, intel_bts_info_fmts[i], arr[i]); 866 fprintf(stdout, intel_bts_info_fmts[i], arr[i]);
867} 867}
868 868
869u64 intel_bts_auxtrace_info_priv[INTEL_BTS_AUXTRACE_PRIV_SIZE];
870
871int intel_bts_process_auxtrace_info(union perf_event *event, 869int intel_bts_process_auxtrace_info(union perf_event *event,
872 struct perf_session *session) 870 struct perf_session *session)
873{ 871{
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 7cf7f7aca4d2..aa1593ce551d 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -64,6 +64,25 @@ enum intel_pt_pkt_state {
64 INTEL_PT_STATE_FUP_NO_TIP, 64 INTEL_PT_STATE_FUP_NO_TIP,
65}; 65};
66 66
67static inline bool intel_pt_sample_time(enum intel_pt_pkt_state pkt_state)
68{
69 switch (pkt_state) {
70 case INTEL_PT_STATE_NO_PSB:
71 case INTEL_PT_STATE_NO_IP:
72 case INTEL_PT_STATE_ERR_RESYNC:
73 case INTEL_PT_STATE_IN_SYNC:
74 case INTEL_PT_STATE_TNT:
75 return true;
76 case INTEL_PT_STATE_TIP:
77 case INTEL_PT_STATE_TIP_PGD:
78 case INTEL_PT_STATE_FUP:
79 case INTEL_PT_STATE_FUP_NO_TIP:
80 return false;
81 default:
82 return true;
83 };
84}
85
67#ifdef INTEL_PT_STRICT 86#ifdef INTEL_PT_STRICT
68#define INTEL_PT_STATE_ERR1 INTEL_PT_STATE_NO_PSB 87#define INTEL_PT_STATE_ERR1 INTEL_PT_STATE_NO_PSB
69#define INTEL_PT_STATE_ERR2 INTEL_PT_STATE_NO_PSB 88#define INTEL_PT_STATE_ERR2 INTEL_PT_STATE_NO_PSB
@@ -87,11 +106,13 @@ struct intel_pt_decoder {
87 const unsigned char *buf; 106 const unsigned char *buf;
88 size_t len; 107 size_t len;
89 bool return_compression; 108 bool return_compression;
109 bool branch_enable;
90 bool mtc_insn; 110 bool mtc_insn;
91 bool pge; 111 bool pge;
92 bool have_tma; 112 bool have_tma;
93 bool have_cyc; 113 bool have_cyc;
94 bool fixup_last_mtc; 114 bool fixup_last_mtc;
115 bool have_last_ip;
95 uint64_t pos; 116 uint64_t pos;
96 uint64_t last_ip; 117 uint64_t last_ip;
97 uint64_t ip; 118 uint64_t ip;
@@ -99,6 +120,7 @@ struct intel_pt_decoder {
99 uint64_t timestamp; 120 uint64_t timestamp;
100 uint64_t tsc_timestamp; 121 uint64_t tsc_timestamp;
101 uint64_t ref_timestamp; 122 uint64_t ref_timestamp;
123 uint64_t sample_timestamp;
102 uint64_t ret_addr; 124 uint64_t ret_addr;
103 uint64_t ctc_timestamp; 125 uint64_t ctc_timestamp;
104 uint64_t ctc_delta; 126 uint64_t ctc_delta;
@@ -119,6 +141,7 @@ struct intel_pt_decoder {
119 int pkt_len; 141 int pkt_len;
120 int last_packet_type; 142 int last_packet_type;
121 unsigned int cbr; 143 unsigned int cbr;
144 unsigned int cbr_seen;
122 unsigned int max_non_turbo_ratio; 145 unsigned int max_non_turbo_ratio;
123 double max_non_turbo_ratio_fp; 146 double max_non_turbo_ratio_fp;
124 double cbr_cyc_to_tsc; 147 double cbr_cyc_to_tsc;
@@ -136,9 +159,18 @@ struct intel_pt_decoder {
136 bool continuous_period; 159 bool continuous_period;
137 bool overflow; 160 bool overflow;
138 bool set_fup_tx_flags; 161 bool set_fup_tx_flags;
162 bool set_fup_ptw;
163 bool set_fup_mwait;
164 bool set_fup_pwre;
165 bool set_fup_exstop;
139 unsigned int fup_tx_flags; 166 unsigned int fup_tx_flags;
140 unsigned int tx_flags; 167 unsigned int tx_flags;
168 uint64_t fup_ptw_payload;
169 uint64_t fup_mwait_payload;
170 uint64_t fup_pwre_payload;
171 uint64_t cbr_payload;
141 uint64_t timestamp_insn_cnt; 172 uint64_t timestamp_insn_cnt;
173 uint64_t sample_insn_cnt;
142 uint64_t stuck_ip; 174 uint64_t stuck_ip;
143 int no_progress; 175 int no_progress;
144 int stuck_ip_prd; 176 int stuck_ip_prd;
@@ -192,6 +224,7 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
192 decoder->pgd_ip = params->pgd_ip; 224 decoder->pgd_ip = params->pgd_ip;
193 decoder->data = params->data; 225 decoder->data = params->data;
194 decoder->return_compression = params->return_compression; 226 decoder->return_compression = params->return_compression;
227 decoder->branch_enable = params->branch_enable;
195 228
196 decoder->period = params->period; 229 decoder->period = params->period;
197 decoder->period_type = params->period_type; 230 decoder->period_type = params->period_type;
@@ -398,6 +431,7 @@ static uint64_t intel_pt_calc_ip(const struct intel_pt_pkt *packet,
398static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder) 431static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder)
399{ 432{
400 decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip); 433 decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
434 decoder->have_last_ip = true;
401} 435}
402 436
403static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder) 437static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
@@ -635,6 +669,8 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
635 case INTEL_PT_PAD: 669 case INTEL_PT_PAD:
636 case INTEL_PT_VMCS: 670 case INTEL_PT_VMCS:
637 case INTEL_PT_MNT: 671 case INTEL_PT_MNT:
672 case INTEL_PT_PTWRITE:
673 case INTEL_PT_PTWRITE_IP:
638 return 0; 674 return 0;
639 675
640 case INTEL_PT_MTC: 676 case INTEL_PT_MTC:
@@ -675,6 +711,12 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
675 break; 711 break;
676 712
677 case INTEL_PT_TSC: 713 case INTEL_PT_TSC:
714 /*
715 * For now, do not support using TSC packets - refer
716 * intel_pt_calc_cyc_to_tsc().
717 */
718 if (data->from_mtc)
719 return 1;
678 timestamp = pkt_info->packet.payload | 720 timestamp = pkt_info->packet.payload |
679 (data->timestamp & (0xffULL << 56)); 721 (data->timestamp & (0xffULL << 56));
680 if (data->from_mtc && timestamp < data->timestamp && 722 if (data->from_mtc && timestamp < data->timestamp &&
@@ -733,6 +775,11 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
733 775
734 case INTEL_PT_TIP_PGD: 776 case INTEL_PT_TIP_PGD:
735 case INTEL_PT_TRACESTOP: 777 case INTEL_PT_TRACESTOP:
778 case INTEL_PT_EXSTOP:
779 case INTEL_PT_EXSTOP_IP:
780 case INTEL_PT_MWAIT:
781 case INTEL_PT_PWRE:
782 case INTEL_PT_PWRX:
736 case INTEL_PT_OVF: 783 case INTEL_PT_OVF:
737 case INTEL_PT_BAD: /* Does not happen */ 784 case INTEL_PT_BAD: /* Does not happen */
738 default: 785 default:
@@ -787,6 +834,14 @@ static void intel_pt_calc_cyc_to_tsc(struct intel_pt_decoder *decoder,
787 .cbr_cyc_to_tsc = 0, 834 .cbr_cyc_to_tsc = 0,
788 }; 835 };
789 836
837 /*
838 * For now, do not support using TSC packets for at least the reasons:
839 * 1) timing might have stopped
840 * 2) TSC packets within PSB+ can slip against CYC packets
841 */
842 if (!from_mtc)
843 return;
844
790 intel_pt_pkt_lookahead(decoder, intel_pt_calc_cyc_cb, &data); 845 intel_pt_pkt_lookahead(decoder, intel_pt_calc_cyc_cb, &data);
791} 846}
792 847
@@ -898,6 +953,7 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder,
898 953
899 decoder->tot_insn_cnt += insn_cnt; 954 decoder->tot_insn_cnt += insn_cnt;
900 decoder->timestamp_insn_cnt += insn_cnt; 955 decoder->timestamp_insn_cnt += insn_cnt;
956 decoder->sample_insn_cnt += insn_cnt;
901 decoder->period_insn_cnt += insn_cnt; 957 decoder->period_insn_cnt += insn_cnt;
902 958
903 if (err) { 959 if (err) {
@@ -990,6 +1046,57 @@ out_no_progress:
990 return err; 1046 return err;
991} 1047}
992 1048
1049static bool intel_pt_fup_event(struct intel_pt_decoder *decoder)
1050{
1051 bool ret = false;
1052
1053 if (decoder->set_fup_tx_flags) {
1054 decoder->set_fup_tx_flags = false;
1055 decoder->tx_flags = decoder->fup_tx_flags;
1056 decoder->state.type = INTEL_PT_TRANSACTION;
1057 decoder->state.from_ip = decoder->ip;
1058 decoder->state.to_ip = 0;
1059 decoder->state.flags = decoder->fup_tx_flags;
1060 return true;
1061 }
1062 if (decoder->set_fup_ptw) {
1063 decoder->set_fup_ptw = false;
1064 decoder->state.type = INTEL_PT_PTW;
1065 decoder->state.flags |= INTEL_PT_FUP_IP;
1066 decoder->state.from_ip = decoder->ip;
1067 decoder->state.to_ip = 0;
1068 decoder->state.ptw_payload = decoder->fup_ptw_payload;
1069 return true;
1070 }
1071 if (decoder->set_fup_mwait) {
1072 decoder->set_fup_mwait = false;
1073 decoder->state.type = INTEL_PT_MWAIT_OP;
1074 decoder->state.from_ip = decoder->ip;
1075 decoder->state.to_ip = 0;
1076 decoder->state.mwait_payload = decoder->fup_mwait_payload;
1077 ret = true;
1078 }
1079 if (decoder->set_fup_pwre) {
1080 decoder->set_fup_pwre = false;
1081 decoder->state.type |= INTEL_PT_PWR_ENTRY;
1082 decoder->state.type &= ~INTEL_PT_BRANCH;
1083 decoder->state.from_ip = decoder->ip;
1084 decoder->state.to_ip = 0;
1085 decoder->state.pwre_payload = decoder->fup_pwre_payload;
1086 ret = true;
1087 }
1088 if (decoder->set_fup_exstop) {
1089 decoder->set_fup_exstop = false;
1090 decoder->state.type |= INTEL_PT_EX_STOP;
1091 decoder->state.type &= ~INTEL_PT_BRANCH;
1092 decoder->state.flags |= INTEL_PT_FUP_IP;
1093 decoder->state.from_ip = decoder->ip;
1094 decoder->state.to_ip = 0;
1095 ret = true;
1096 }
1097 return ret;
1098}
1099
993static int intel_pt_walk_fup(struct intel_pt_decoder *decoder) 1100static int intel_pt_walk_fup(struct intel_pt_decoder *decoder)
994{ 1101{
995 struct intel_pt_insn intel_pt_insn; 1102 struct intel_pt_insn intel_pt_insn;
@@ -1003,15 +1110,8 @@ static int intel_pt_walk_fup(struct intel_pt_decoder *decoder)
1003 if (err == INTEL_PT_RETURN) 1110 if (err == INTEL_PT_RETURN)
1004 return 0; 1111 return 0;
1005 if (err == -EAGAIN) { 1112 if (err == -EAGAIN) {
1006 if (decoder->set_fup_tx_flags) { 1113 if (intel_pt_fup_event(decoder))
1007 decoder->set_fup_tx_flags = false;
1008 decoder->tx_flags = decoder->fup_tx_flags;
1009 decoder->state.type = INTEL_PT_TRANSACTION;
1010 decoder->state.from_ip = decoder->ip;
1011 decoder->state.to_ip = 0;
1012 decoder->state.flags = decoder->fup_tx_flags;
1013 return 0; 1114 return 0;
1014 }
1015 return err; 1115 return err;
1016 } 1116 }
1017 decoder->set_fup_tx_flags = false; 1117 decoder->set_fup_tx_flags = false;
@@ -1360,7 +1460,9 @@ static void intel_pt_calc_mtc_timestamp(struct intel_pt_decoder *decoder)
1360 1460
1361static void intel_pt_calc_cbr(struct intel_pt_decoder *decoder) 1461static void intel_pt_calc_cbr(struct intel_pt_decoder *decoder)
1362{ 1462{
1363 unsigned int cbr = decoder->packet.payload; 1463 unsigned int cbr = decoder->packet.payload & 0xff;
1464
1465 decoder->cbr_payload = decoder->packet.payload;
1364 1466
1365 if (decoder->cbr == cbr) 1467 if (decoder->cbr == cbr)
1366 return; 1468 return;
@@ -1417,6 +1519,13 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
1417 case INTEL_PT_TRACESTOP: 1519 case INTEL_PT_TRACESTOP:
1418 case INTEL_PT_BAD: 1520 case INTEL_PT_BAD:
1419 case INTEL_PT_PSB: 1521 case INTEL_PT_PSB:
1522 case INTEL_PT_PTWRITE:
1523 case INTEL_PT_PTWRITE_IP:
1524 case INTEL_PT_EXSTOP:
1525 case INTEL_PT_EXSTOP_IP:
1526 case INTEL_PT_MWAIT:
1527 case INTEL_PT_PWRE:
1528 case INTEL_PT_PWRX:
1420 decoder->have_tma = false; 1529 decoder->have_tma = false;
1421 intel_pt_log("ERROR: Unexpected packet\n"); 1530 intel_pt_log("ERROR: Unexpected packet\n");
1422 return -EAGAIN; 1531 return -EAGAIN;
@@ -1446,7 +1555,8 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
1446 1555
1447 case INTEL_PT_FUP: 1556 case INTEL_PT_FUP:
1448 decoder->pge = true; 1557 decoder->pge = true;
1449 intel_pt_set_last_ip(decoder); 1558 if (decoder->packet.count)
1559 intel_pt_set_last_ip(decoder);
1450 break; 1560 break;
1451 1561
1452 case INTEL_PT_MODE_TSX: 1562 case INTEL_PT_MODE_TSX:
@@ -1497,6 +1607,13 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
1497 case INTEL_PT_MODE_TSX: 1607 case INTEL_PT_MODE_TSX:
1498 case INTEL_PT_BAD: 1608 case INTEL_PT_BAD:
1499 case INTEL_PT_PSBEND: 1609 case INTEL_PT_PSBEND:
1610 case INTEL_PT_PTWRITE:
1611 case INTEL_PT_PTWRITE_IP:
1612 case INTEL_PT_EXSTOP:
1613 case INTEL_PT_EXSTOP_IP:
1614 case INTEL_PT_MWAIT:
1615 case INTEL_PT_PWRE:
1616 case INTEL_PT_PWRX:
1500 intel_pt_log("ERROR: Missing TIP after FUP\n"); 1617 intel_pt_log("ERROR: Missing TIP after FUP\n");
1501 decoder->pkt_state = INTEL_PT_STATE_ERR3; 1618 decoder->pkt_state = INTEL_PT_STATE_ERR3;
1502 return -ENOENT; 1619 return -ENOENT;
@@ -1625,6 +1742,15 @@ next:
1625 break; 1742 break;
1626 } 1743 }
1627 intel_pt_set_last_ip(decoder); 1744 intel_pt_set_last_ip(decoder);
1745 if (!decoder->branch_enable) {
1746 decoder->ip = decoder->last_ip;
1747 if (intel_pt_fup_event(decoder))
1748 return 0;
1749 no_tip = false;
1750 break;
1751 }
1752 if (decoder->set_fup_mwait)
1753 no_tip = true;
1628 err = intel_pt_walk_fup(decoder); 1754 err = intel_pt_walk_fup(decoder);
1629 if (err != -EAGAIN) { 1755 if (err != -EAGAIN) {
1630 if (err) 1756 if (err)
@@ -1650,6 +1776,8 @@ next:
1650 break; 1776 break;
1651 1777
1652 case INTEL_PT_PSB: 1778 case INTEL_PT_PSB:
1779 decoder->last_ip = 0;
1780 decoder->have_last_ip = true;
1653 intel_pt_clear_stack(&decoder->stack); 1781 intel_pt_clear_stack(&decoder->stack);
1654 err = intel_pt_walk_psbend(decoder); 1782 err = intel_pt_walk_psbend(decoder);
1655 if (err == -EAGAIN) 1783 if (err == -EAGAIN)
@@ -1696,6 +1824,16 @@ next:
1696 1824
1697 case INTEL_PT_CBR: 1825 case INTEL_PT_CBR:
1698 intel_pt_calc_cbr(decoder); 1826 intel_pt_calc_cbr(decoder);
1827 if (!decoder->branch_enable &&
1828 decoder->cbr != decoder->cbr_seen) {
1829 decoder->cbr_seen = decoder->cbr;
1830 decoder->state.type = INTEL_PT_CBR_CHG;
1831 decoder->state.from_ip = decoder->ip;
1832 decoder->state.to_ip = 0;
1833 decoder->state.cbr_payload =
1834 decoder->packet.payload;
1835 return 0;
1836 }
1699 break; 1837 break;
1700 1838
1701 case INTEL_PT_MODE_EXEC: 1839 case INTEL_PT_MODE_EXEC:
@@ -1722,6 +1860,71 @@ next:
1722 case INTEL_PT_PAD: 1860 case INTEL_PT_PAD:
1723 break; 1861 break;
1724 1862
1863 case INTEL_PT_PTWRITE_IP:
1864 decoder->fup_ptw_payload = decoder->packet.payload;
1865 err = intel_pt_get_next_packet(decoder);
1866 if (err)
1867 return err;
1868 if (decoder->packet.type == INTEL_PT_FUP) {
1869 decoder->set_fup_ptw = true;
1870 no_tip = true;
1871 } else {
1872 intel_pt_log_at("ERROR: Missing FUP after PTWRITE",
1873 decoder->pos);
1874 }
1875 goto next;
1876
1877 case INTEL_PT_PTWRITE:
1878 decoder->state.type = INTEL_PT_PTW;
1879 decoder->state.from_ip = decoder->ip;
1880 decoder->state.to_ip = 0;
1881 decoder->state.ptw_payload = decoder->packet.payload;
1882 return 0;
1883
1884 case INTEL_PT_MWAIT:
1885 decoder->fup_mwait_payload = decoder->packet.payload;
1886 decoder->set_fup_mwait = true;
1887 break;
1888
1889 case INTEL_PT_PWRE:
1890 if (decoder->set_fup_mwait) {
1891 decoder->fup_pwre_payload =
1892 decoder->packet.payload;
1893 decoder->set_fup_pwre = true;
1894 break;
1895 }
1896 decoder->state.type = INTEL_PT_PWR_ENTRY;
1897 decoder->state.from_ip = decoder->ip;
1898 decoder->state.to_ip = 0;
1899 decoder->state.pwrx_payload = decoder->packet.payload;
1900 return 0;
1901
1902 case INTEL_PT_EXSTOP_IP:
1903 err = intel_pt_get_next_packet(decoder);
1904 if (err)
1905 return err;
1906 if (decoder->packet.type == INTEL_PT_FUP) {
1907 decoder->set_fup_exstop = true;
1908 no_tip = true;
1909 } else {
1910 intel_pt_log_at("ERROR: Missing FUP after EXSTOP",
1911 decoder->pos);
1912 }
1913 goto next;
1914
1915 case INTEL_PT_EXSTOP:
1916 decoder->state.type = INTEL_PT_EX_STOP;
1917 decoder->state.from_ip = decoder->ip;
1918 decoder->state.to_ip = 0;
1919 return 0;
1920
1921 case INTEL_PT_PWRX:
1922 decoder->state.type = INTEL_PT_PWR_EXIT;
1923 decoder->state.from_ip = decoder->ip;
1924 decoder->state.to_ip = 0;
1925 decoder->state.pwrx_payload = decoder->packet.payload;
1926 return 0;
1927
1725 default: 1928 default:
1726 return intel_pt_bug(decoder); 1929 return intel_pt_bug(decoder);
1727 } 1930 }
@@ -1730,8 +1933,9 @@ next:
1730 1933
1731static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder) 1934static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
1732{ 1935{
1733 return decoder->last_ip || decoder->packet.count == 0 || 1936 return decoder->packet.count &&
1734 decoder->packet.count == 3 || decoder->packet.count == 6; 1937 (decoder->have_last_ip || decoder->packet.count == 3 ||
1938 decoder->packet.count == 6);
1735} 1939}
1736 1940
1737/* Walk PSB+ packets to get in sync. */ 1941/* Walk PSB+ packets to get in sync. */
@@ -1750,6 +1954,13 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
1750 __fallthrough; 1954 __fallthrough;
1751 case INTEL_PT_TIP_PGE: 1955 case INTEL_PT_TIP_PGE:
1752 case INTEL_PT_TIP: 1956 case INTEL_PT_TIP:
1957 case INTEL_PT_PTWRITE:
1958 case INTEL_PT_PTWRITE_IP:
1959 case INTEL_PT_EXSTOP:
1960 case INTEL_PT_EXSTOP_IP:
1961 case INTEL_PT_MWAIT:
1962 case INTEL_PT_PWRE:
1963 case INTEL_PT_PWRX:
1753 intel_pt_log("ERROR: Unexpected packet\n"); 1964 intel_pt_log("ERROR: Unexpected packet\n");
1754 return -ENOENT; 1965 return -ENOENT;
1755 1966
@@ -1854,14 +2065,10 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
1854 break; 2065 break;
1855 2066
1856 case INTEL_PT_FUP: 2067 case INTEL_PT_FUP:
1857 if (decoder->overflow) { 2068 if (intel_pt_have_ip(decoder))
1858 if (intel_pt_have_ip(decoder)) 2069 intel_pt_set_ip(decoder);
1859 intel_pt_set_ip(decoder); 2070 if (decoder->ip)
1860 if (decoder->ip) 2071 return 0;
1861 return 0;
1862 }
1863 if (decoder->packet.count)
1864 intel_pt_set_last_ip(decoder);
1865 break; 2072 break;
1866 2073
1867 case INTEL_PT_MTC: 2074 case INTEL_PT_MTC:
@@ -1910,6 +2117,9 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
1910 break; 2117 break;
1911 2118
1912 case INTEL_PT_PSB: 2119 case INTEL_PT_PSB:
2120 decoder->last_ip = 0;
2121 decoder->have_last_ip = true;
2122 intel_pt_clear_stack(&decoder->stack);
1913 err = intel_pt_walk_psb(decoder); 2123 err = intel_pt_walk_psb(decoder);
1914 if (err) 2124 if (err)
1915 return err; 2125 return err;
@@ -1925,6 +2135,13 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
1925 case INTEL_PT_VMCS: 2135 case INTEL_PT_VMCS:
1926 case INTEL_PT_MNT: 2136 case INTEL_PT_MNT:
1927 case INTEL_PT_PAD: 2137 case INTEL_PT_PAD:
2138 case INTEL_PT_PTWRITE:
2139 case INTEL_PT_PTWRITE_IP:
2140 case INTEL_PT_EXSTOP:
2141 case INTEL_PT_EXSTOP_IP:
2142 case INTEL_PT_MWAIT:
2143 case INTEL_PT_PWRE:
2144 case INTEL_PT_PWRX:
1928 default: 2145 default:
1929 break; 2146 break;
1930 } 2147 }
@@ -1935,6 +2152,19 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
1935{ 2152{
1936 int err; 2153 int err;
1937 2154
2155 decoder->set_fup_tx_flags = false;
2156 decoder->set_fup_ptw = false;
2157 decoder->set_fup_mwait = false;
2158 decoder->set_fup_pwre = false;
2159 decoder->set_fup_exstop = false;
2160
2161 if (!decoder->branch_enable) {
2162 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
2163 decoder->overflow = false;
2164 decoder->state.type = 0; /* Do not have a sample */
2165 return 0;
2166 }
2167
1938 intel_pt_log("Scanning for full IP\n"); 2168 intel_pt_log("Scanning for full IP\n");
1939 err = intel_pt_walk_to_ip(decoder); 2169 err = intel_pt_walk_to_ip(decoder);
1940 if (err) 2170 if (err)
@@ -2043,6 +2273,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder)
2043 2273
2044 decoder->pge = false; 2274 decoder->pge = false;
2045 decoder->continuous_period = false; 2275 decoder->continuous_period = false;
2276 decoder->have_last_ip = false;
2046 decoder->last_ip = 0; 2277 decoder->last_ip = 0;
2047 decoder->ip = 0; 2278 decoder->ip = 0;
2048 intel_pt_clear_stack(&decoder->stack); 2279 intel_pt_clear_stack(&decoder->stack);
@@ -2051,6 +2282,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder)
2051 if (err) 2282 if (err)
2052 return err; 2283 return err;
2053 2284
2285 decoder->have_last_ip = true;
2054 decoder->pkt_state = INTEL_PT_STATE_NO_IP; 2286 decoder->pkt_state = INTEL_PT_STATE_NO_IP;
2055 2287
2056 err = intel_pt_walk_psb(decoder); 2288 err = intel_pt_walk_psb(decoder);
@@ -2069,7 +2301,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder)
2069 2301
2070static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder) 2302static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder)
2071{ 2303{
2072 uint64_t est = decoder->timestamp_insn_cnt << 1; 2304 uint64_t est = decoder->sample_insn_cnt << 1;
2073 2305
2074 if (!decoder->cbr || !decoder->max_non_turbo_ratio) 2306 if (!decoder->cbr || !decoder->max_non_turbo_ratio)
2075 goto out; 2307 goto out;
@@ -2077,7 +2309,7 @@ static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder)
2077 est *= decoder->max_non_turbo_ratio; 2309 est *= decoder->max_non_turbo_ratio;
2078 est /= decoder->cbr; 2310 est /= decoder->cbr;
2079out: 2311out:
2080 return decoder->timestamp + est; 2312 return decoder->sample_timestamp + est;
2081} 2313}
2082 2314
2083const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) 2315const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
@@ -2093,8 +2325,10 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
2093 err = intel_pt_sync(decoder); 2325 err = intel_pt_sync(decoder);
2094 break; 2326 break;
2095 case INTEL_PT_STATE_NO_IP: 2327 case INTEL_PT_STATE_NO_IP:
2328 decoder->have_last_ip = false;
2096 decoder->last_ip = 0; 2329 decoder->last_ip = 0;
2097 /* Fall through */ 2330 decoder->ip = 0;
2331 __fallthrough;
2098 case INTEL_PT_STATE_ERR_RESYNC: 2332 case INTEL_PT_STATE_ERR_RESYNC:
2099 err = intel_pt_sync_ip(decoder); 2333 err = intel_pt_sync_ip(decoder);
2100 break; 2334 break;
@@ -2130,15 +2364,29 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
2130 } 2364 }
2131 } while (err == -ENOLINK); 2365 } while (err == -ENOLINK);
2132 2366
2133 decoder->state.err = err ? intel_pt_ext_err(err) : 0; 2367 if (err) {
2134 decoder->state.timestamp = decoder->timestamp; 2368 decoder->state.err = intel_pt_ext_err(err);
2369 decoder->state.from_ip = decoder->ip;
2370 decoder->sample_timestamp = decoder->timestamp;
2371 decoder->sample_insn_cnt = decoder->timestamp_insn_cnt;
2372 } else {
2373 decoder->state.err = 0;
2374 if (decoder->cbr != decoder->cbr_seen && decoder->state.type) {
2375 decoder->cbr_seen = decoder->cbr;
2376 decoder->state.type |= INTEL_PT_CBR_CHG;
2377 decoder->state.cbr_payload = decoder->cbr_payload;
2378 }
2379 if (intel_pt_sample_time(decoder->pkt_state)) {
2380 decoder->sample_timestamp = decoder->timestamp;
2381 decoder->sample_insn_cnt = decoder->timestamp_insn_cnt;
2382 }
2383 }
2384
2385 decoder->state.timestamp = decoder->sample_timestamp;
2135 decoder->state.est_timestamp = intel_pt_est_timestamp(decoder); 2386 decoder->state.est_timestamp = intel_pt_est_timestamp(decoder);
2136 decoder->state.cr3 = decoder->cr3; 2387 decoder->state.cr3 = decoder->cr3;
2137 decoder->state.tot_insn_cnt = decoder->tot_insn_cnt; 2388 decoder->state.tot_insn_cnt = decoder->tot_insn_cnt;
2138 2389
2139 if (err)
2140 decoder->state.from_ip = decoder->ip;
2141
2142 return &decoder->state; 2390 return &decoder->state;
2143} 2391}
2144 2392
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index e90619a43c0c..921b22e8ca0e 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -25,11 +25,18 @@
25#define INTEL_PT_IN_TX (1 << 0) 25#define INTEL_PT_IN_TX (1 << 0)
26#define INTEL_PT_ABORT_TX (1 << 1) 26#define INTEL_PT_ABORT_TX (1 << 1)
27#define INTEL_PT_ASYNC (1 << 2) 27#define INTEL_PT_ASYNC (1 << 2)
28#define INTEL_PT_FUP_IP (1 << 3)
28 29
29enum intel_pt_sample_type { 30enum intel_pt_sample_type {
30 INTEL_PT_BRANCH = 1 << 0, 31 INTEL_PT_BRANCH = 1 << 0,
31 INTEL_PT_INSTRUCTION = 1 << 1, 32 INTEL_PT_INSTRUCTION = 1 << 1,
32 INTEL_PT_TRANSACTION = 1 << 2, 33 INTEL_PT_TRANSACTION = 1 << 2,
34 INTEL_PT_PTW = 1 << 3,
35 INTEL_PT_MWAIT_OP = 1 << 4,
36 INTEL_PT_PWR_ENTRY = 1 << 5,
37 INTEL_PT_EX_STOP = 1 << 6,
38 INTEL_PT_PWR_EXIT = 1 << 7,
39 INTEL_PT_CBR_CHG = 1 << 8,
33}; 40};
34 41
35enum intel_pt_period_type { 42enum intel_pt_period_type {
@@ -63,6 +70,11 @@ struct intel_pt_state {
63 uint64_t timestamp; 70 uint64_t timestamp;
64 uint64_t est_timestamp; 71 uint64_t est_timestamp;
65 uint64_t trace_nr; 72 uint64_t trace_nr;
73 uint64_t ptw_payload;
74 uint64_t mwait_payload;
75 uint64_t pwre_payload;
76 uint64_t pwrx_payload;
77 uint64_t cbr_payload;
66 uint32_t flags; 78 uint32_t flags;
67 enum intel_pt_insn_op insn_op; 79 enum intel_pt_insn_op insn_op;
68 int insn_len; 80 int insn_len;
@@ -87,6 +99,7 @@ struct intel_pt_params {
87 bool (*pgd_ip)(uint64_t ip, void *data); 99 bool (*pgd_ip)(uint64_t ip, void *data);
88 void *data; 100 void *data;
89 bool return_compression; 101 bool return_compression;
102 bool branch_enable;
90 uint64_t period; 103 uint64_t period;
91 enum intel_pt_period_type period_type; 104 enum intel_pt_period_type period_type;
92 unsigned max_non_turbo_ratio; 105 unsigned max_non_turbo_ratio;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.h b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
index debe751dc3d6..45b64f93f358 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
@@ -16,6 +16,7 @@
16#ifndef INCLUDE__INTEL_PT_LOG_H__ 16#ifndef INCLUDE__INTEL_PT_LOG_H__
17#define INCLUDE__INTEL_PT_LOG_H__ 17#define INCLUDE__INTEL_PT_LOG_H__
18 18
19#include <linux/compiler.h>
19#include <stdint.h> 20#include <stdint.h>
20#include <inttypes.h> 21#include <inttypes.h>
21 22
@@ -34,8 +35,7 @@ void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip);
34void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, 35void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
35 uint64_t ip); 36 uint64_t ip);
36 37
37__attribute__((format(printf, 1, 2))) 38void __intel_pt_log(const char *fmt, ...) __printf(1, 2);
38void __intel_pt_log(const char *fmt, ...);
39 39
40#define intel_pt_log(fmt, ...) \ 40#define intel_pt_log(fmt, ...) \
41 do { \ 41 do { \
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 7528ae4f7e28..ba4c9dd18643 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
@@ -64,6 +64,13 @@ static const char * const packet_name[] = {
64 [INTEL_PT_PIP] = "PIP", 64 [INTEL_PT_PIP] = "PIP",
65 [INTEL_PT_OVF] = "OVF", 65 [INTEL_PT_OVF] = "OVF",
66 [INTEL_PT_MNT] = "MNT", 66 [INTEL_PT_MNT] = "MNT",
67 [INTEL_PT_PTWRITE] = "PTWRITE",
68 [INTEL_PT_PTWRITE_IP] = "PTWRITE",
69 [INTEL_PT_EXSTOP] = "EXSTOP",
70 [INTEL_PT_EXSTOP_IP] = "EXSTOP",
71 [INTEL_PT_MWAIT] = "MWAIT",
72 [INTEL_PT_PWRE] = "PWRE",
73 [INTEL_PT_PWRX] = "PWRX",
67}; 74};
68 75
69const char *intel_pt_pkt_name(enum intel_pt_pkt_type type) 76const char *intel_pt_pkt_name(enum intel_pt_pkt_type type)
@@ -123,7 +130,7 @@ static int intel_pt_get_cbr(const unsigned char *buf, size_t len,
123 if (len < 4) 130 if (len < 4)
124 return INTEL_PT_NEED_MORE_BYTES; 131 return INTEL_PT_NEED_MORE_BYTES;
125 packet->type = INTEL_PT_CBR; 132 packet->type = INTEL_PT_CBR;
126 packet->payload = buf[2]; 133 packet->payload = le16_to_cpu(*(uint16_t *)(buf + 2));
127 return 4; 134 return 4;
128} 135}
129 136
@@ -217,12 +224,80 @@ static int intel_pt_get_3byte(const unsigned char *buf, size_t len,
217 } 224 }
218} 225}
219 226
227static int intel_pt_get_ptwrite(const unsigned char *buf, size_t len,
228 struct intel_pt_pkt *packet)
229{
230 packet->count = (buf[1] >> 5) & 0x3;
231 packet->type = buf[1] & BIT(7) ? INTEL_PT_PTWRITE_IP :
232 INTEL_PT_PTWRITE;
233
234 switch (packet->count) {
235 case 0:
236 if (len < 6)
237 return INTEL_PT_NEED_MORE_BYTES;
238 packet->payload = le32_to_cpu(*(uint32_t *)(buf + 2));
239 return 6;
240 case 1:
241 if (len < 10)
242 return INTEL_PT_NEED_MORE_BYTES;
243 packet->payload = le64_to_cpu(*(uint64_t *)(buf + 2));
244 return 10;
245 default:
246 return INTEL_PT_BAD_PACKET;
247 }
248}
249
250static int intel_pt_get_exstop(struct intel_pt_pkt *packet)
251{
252 packet->type = INTEL_PT_EXSTOP;
253 return 2;
254}
255
256static int intel_pt_get_exstop_ip(struct intel_pt_pkt *packet)
257{
258 packet->type = INTEL_PT_EXSTOP_IP;
259 return 2;
260}
261
262static int intel_pt_get_mwait(const unsigned char *buf, size_t len,
263 struct intel_pt_pkt *packet)
264{
265 if (len < 10)
266 return INTEL_PT_NEED_MORE_BYTES;
267 packet->type = INTEL_PT_MWAIT;
268 packet->payload = le64_to_cpu(*(uint64_t *)(buf + 2));
269 return 10;
270}
271
272static int intel_pt_get_pwre(const unsigned char *buf, size_t len,
273 struct intel_pt_pkt *packet)
274{
275 if (len < 4)
276 return INTEL_PT_NEED_MORE_BYTES;
277 packet->type = INTEL_PT_PWRE;
278 memcpy_le64(&packet->payload, buf + 2, 2);
279 return 4;
280}
281
282static int intel_pt_get_pwrx(const unsigned char *buf, size_t len,
283 struct intel_pt_pkt *packet)
284{
285 if (len < 7)
286 return INTEL_PT_NEED_MORE_BYTES;
287 packet->type = INTEL_PT_PWRX;
288 memcpy_le64(&packet->payload, buf + 2, 5);
289 return 7;
290}
291
220static int intel_pt_get_ext(const unsigned char *buf, size_t len, 292static int intel_pt_get_ext(const unsigned char *buf, size_t len,
221 struct intel_pt_pkt *packet) 293 struct intel_pt_pkt *packet)
222{ 294{
223 if (len < 2) 295 if (len < 2)
224 return INTEL_PT_NEED_MORE_BYTES; 296 return INTEL_PT_NEED_MORE_BYTES;
225 297
298 if ((buf[1] & 0x1f) == 0x12)
299 return intel_pt_get_ptwrite(buf, len, packet);
300
226 switch (buf[1]) { 301 switch (buf[1]) {
227 case 0xa3: /* Long TNT */ 302 case 0xa3: /* Long TNT */
228 return intel_pt_get_long_tnt(buf, len, packet); 303 return intel_pt_get_long_tnt(buf, len, packet);
@@ -244,6 +319,16 @@ static int intel_pt_get_ext(const unsigned char *buf, size_t len,
244 return intel_pt_get_tma(buf, len, packet); 319 return intel_pt_get_tma(buf, len, packet);
245 case 0xC3: /* 3-byte header */ 320 case 0xC3: /* 3-byte header */
246 return intel_pt_get_3byte(buf, len, packet); 321 return intel_pt_get_3byte(buf, len, packet);
322 case 0x62: /* EXSTOP no IP */
323 return intel_pt_get_exstop(packet);
324 case 0xE2: /* EXSTOP with IP */
325 return intel_pt_get_exstop_ip(packet);
326 case 0xC2: /* MWAIT */
327 return intel_pt_get_mwait(buf, len, packet);
328 case 0x22: /* PWRE */
329 return intel_pt_get_pwre(buf, len, packet);
330 case 0xA2: /* PWRX */
331 return intel_pt_get_pwrx(buf, len, packet);
247 default: 332 default:
248 return INTEL_PT_BAD_PACKET; 333 return INTEL_PT_BAD_PACKET;
249 } 334 }
@@ -522,6 +607,29 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
522 ret = snprintf(buf, buf_len, "%s 0x%llx (NR=%d)", 607 ret = snprintf(buf, buf_len, "%s 0x%llx (NR=%d)",
523 name, payload, nr); 608 name, payload, nr);
524 return ret; 609 return ret;
610 case INTEL_PT_PTWRITE:
611 return snprintf(buf, buf_len, "%s 0x%llx IP:0", name, payload);
612 case INTEL_PT_PTWRITE_IP:
613 return snprintf(buf, buf_len, "%s 0x%llx IP:1", name, payload);
614 case INTEL_PT_EXSTOP:
615 return snprintf(buf, buf_len, "%s IP:0", name);
616 case INTEL_PT_EXSTOP_IP:
617 return snprintf(buf, buf_len, "%s IP:1", name);
618 case INTEL_PT_MWAIT:
619 return snprintf(buf, buf_len, "%s 0x%llx Hints 0x%x Extensions 0x%x",
620 name, payload, (unsigned int)(payload & 0xff),
621 (unsigned int)((payload >> 32) & 0x3));
622 case INTEL_PT_PWRE:
623 return snprintf(buf, buf_len, "%s 0x%llx HW:%u CState:%u Sub-CState:%u",
624 name, payload, !!(payload & 0x80),
625 (unsigned int)((payload >> 12) & 0xf),
626 (unsigned int)((payload >> 8) & 0xf));
627 case INTEL_PT_PWRX:
628 return snprintf(buf, buf_len, "%s 0x%llx Last CState:%u Deepest CState:%u Wake Reason 0x%x",
629 name, payload,
630 (unsigned int)((payload >> 4) & 0xf),
631 (unsigned int)(payload & 0xf),
632 (unsigned int)((payload >> 8) & 0xf));
525 default: 633 default:
526 break; 634 break;
527 } 635 }
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
index 781bb79883bd..73ddc3a88d07 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
@@ -52,6 +52,13 @@ enum intel_pt_pkt_type {
52 INTEL_PT_PIP, 52 INTEL_PT_PIP,
53 INTEL_PT_OVF, 53 INTEL_PT_OVF,
54 INTEL_PT_MNT, 54 INTEL_PT_MNT,
55 INTEL_PT_PTWRITE,
56 INTEL_PT_PTWRITE_IP,
57 INTEL_PT_EXSTOP,
58 INTEL_PT_EXSTOP_IP,
59 INTEL_PT_MWAIT,
60 INTEL_PT_PWRE,
61 INTEL_PT_PWRX,
55}; 62};
56 63
57struct intel_pt_pkt { 64struct intel_pt_pkt {
diff --git a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
index 767be7c76034..12e377184ee4 100644
--- a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
+++ b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
@@ -1009,7 +1009,7 @@ GrpTable: Grp15
10091: fxstor | RDGSBASE Ry (F3),(11B) 10091: fxstor | RDGSBASE Ry (F3),(11B)
10102: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B) 10102: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B)
10113: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B) 10113: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B)
10124: XSAVE 10124: XSAVE | ptwrite Ey (F3),(11B)
10135: XRSTOR | lfence (11B) 10135: XRSTOR | lfence (11B)
10146: XSAVEOPT | clwb (66) | mfence (11B) 10146: XSAVEOPT | clwb (66) | mfence (11B)
10157: clflush | clflushopt (66) | sfence (11B) 10157: clflush | clflushopt (66) | sfence (11B)
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 4c7718f87a08..b58f9fd1e2ee 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -81,7 +81,6 @@ struct intel_pt {
81 81
82 bool sample_instructions; 82 bool sample_instructions;
83 u64 instructions_sample_type; 83 u64 instructions_sample_type;
84 u64 instructions_sample_period;
85 u64 instructions_id; 84 u64 instructions_id;
86 85
87 bool sample_branches; 86 bool sample_branches;
@@ -93,6 +92,18 @@ struct intel_pt {
93 u64 transactions_sample_type; 92 u64 transactions_sample_type;
94 u64 transactions_id; 93 u64 transactions_id;
95 94
95 bool sample_ptwrites;
96 u64 ptwrites_sample_type;
97 u64 ptwrites_id;
98
99 bool sample_pwr_events;
100 u64 pwr_events_sample_type;
101 u64 mwait_id;
102 u64 pwre_id;
103 u64 exstop_id;
104 u64 pwrx_id;
105 u64 cbr_id;
106
96 bool synth_needs_swap; 107 bool synth_needs_swap;
97 108
98 u64 tsc_bit; 109 u64 tsc_bit;
@@ -103,6 +114,7 @@ struct intel_pt {
103 u64 cyc_bit; 114 u64 cyc_bit;
104 u64 noretcomp_bit; 115 u64 noretcomp_bit;
105 unsigned max_non_turbo_ratio; 116 unsigned max_non_turbo_ratio;
117 unsigned cbr2khz;
106 118
107 unsigned long num_events; 119 unsigned long num_events;
108 120
@@ -668,6 +680,19 @@ static bool intel_pt_return_compression(struct intel_pt *pt)
668 return true; 680 return true;
669} 681}
670 682
683static bool intel_pt_branch_enable(struct intel_pt *pt)
684{
685 struct perf_evsel *evsel;
686 u64 config;
687
688 evlist__for_each_entry(pt->session->evlist, evsel) {
689 if (intel_pt_get_config(pt, &evsel->attr, &config) &&
690 (config & 1) && !(config & 0x2000))
691 return false;
692 }
693 return true;
694}
695
671static unsigned int intel_pt_mtc_period(struct intel_pt *pt) 696static unsigned int intel_pt_mtc_period(struct intel_pt *pt)
672{ 697{
673 struct perf_evsel *evsel; 698 struct perf_evsel *evsel;
@@ -799,6 +824,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
799 params.walk_insn = intel_pt_walk_next_insn; 824 params.walk_insn = intel_pt_walk_next_insn;
800 params.data = ptq; 825 params.data = ptq;
801 params.return_compression = intel_pt_return_compression(pt); 826 params.return_compression = intel_pt_return_compression(pt);
827 params.branch_enable = intel_pt_branch_enable(pt);
802 params.max_non_turbo_ratio = pt->max_non_turbo_ratio; 828 params.max_non_turbo_ratio = pt->max_non_turbo_ratio;
803 params.mtc_period = intel_pt_mtc_period(pt); 829 params.mtc_period = intel_pt_mtc_period(pt);
804 params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n; 830 params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n;
@@ -1044,6 +1070,36 @@ static void intel_pt_update_last_branch_rb(struct intel_pt_queue *ptq)
1044 bs->nr += 1; 1070 bs->nr += 1;
1045} 1071}
1046 1072
1073static inline bool intel_pt_skip_event(struct intel_pt *pt)
1074{
1075 return pt->synth_opts.initial_skip &&
1076 pt->num_events++ < pt->synth_opts.initial_skip;
1077}
1078
1079static void intel_pt_prep_b_sample(struct intel_pt *pt,
1080 struct intel_pt_queue *ptq,
1081 union perf_event *event,
1082 struct perf_sample *sample)
1083{
1084 event->sample.header.type = PERF_RECORD_SAMPLE;
1085 event->sample.header.misc = PERF_RECORD_MISC_USER;
1086 event->sample.header.size = sizeof(struct perf_event_header);
1087
1088 if (!pt->timeless_decoding)
1089 sample->time = tsc_to_perf_time(ptq->timestamp, &pt->tc);
1090
1091 sample->cpumode = PERF_RECORD_MISC_USER;
1092 sample->ip = ptq->state->from_ip;
1093 sample->pid = ptq->pid;
1094 sample->tid = ptq->tid;
1095 sample->addr = ptq->state->to_ip;
1096 sample->period = 1;
1097 sample->cpu = ptq->cpu;
1098 sample->flags = ptq->flags;
1099 sample->insn_len = ptq->insn_len;
1100 memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
1101}
1102
1047static int intel_pt_inject_event(union perf_event *event, 1103static int intel_pt_inject_event(union perf_event *event,
1048 struct perf_sample *sample, u64 type, 1104 struct perf_sample *sample, u64 type,
1049 bool swapped) 1105 bool swapped)
@@ -1052,9 +1108,35 @@ static int intel_pt_inject_event(union perf_event *event,
1052 return perf_event__synthesize_sample(event, type, 0, sample, swapped); 1108 return perf_event__synthesize_sample(event, type, 0, sample, swapped);
1053} 1109}
1054 1110
1055static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) 1111static inline int intel_pt_opt_inject(struct intel_pt *pt,
1112 union perf_event *event,
1113 struct perf_sample *sample, u64 type)
1114{
1115 if (!pt->synth_opts.inject)
1116 return 0;
1117
1118 return intel_pt_inject_event(event, sample, type, pt->synth_needs_swap);
1119}
1120
1121static int intel_pt_deliver_synth_b_event(struct intel_pt *pt,
1122 union perf_event *event,
1123 struct perf_sample *sample, u64 type)
1056{ 1124{
1057 int ret; 1125 int ret;
1126
1127 ret = intel_pt_opt_inject(pt, event, sample, type);
1128 if (ret)
1129 return ret;
1130
1131 ret = perf_session__deliver_synth_event(pt->session, event, sample);
1132 if (ret)
1133 pr_err("Intel PT: failed to deliver event, error %d\n", ret);
1134
1135 return ret;
1136}
1137
1138static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
1139{
1058 struct intel_pt *pt = ptq->pt; 1140 struct intel_pt *pt = ptq->pt;
1059 union perf_event *event = ptq->event_buf; 1141 union perf_event *event = ptq->event_buf;
1060 struct perf_sample sample = { .ip = 0, }; 1142 struct perf_sample sample = { .ip = 0, };
@@ -1066,29 +1148,13 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
1066 if (pt->branches_filter && !(pt->branches_filter & ptq->flags)) 1148 if (pt->branches_filter && !(pt->branches_filter & ptq->flags))
1067 return 0; 1149 return 0;
1068 1150
1069 if (pt->synth_opts.initial_skip && 1151 if (intel_pt_skip_event(pt))
1070 pt->num_events++ < pt->synth_opts.initial_skip)
1071 return 0; 1152 return 0;
1072 1153
1073 event->sample.header.type = PERF_RECORD_SAMPLE; 1154 intel_pt_prep_b_sample(pt, ptq, event, &sample);
1074 event->sample.header.misc = PERF_RECORD_MISC_USER;
1075 event->sample.header.size = sizeof(struct perf_event_header);
1076 1155
1077 if (!pt->timeless_decoding)
1078 sample.time = tsc_to_perf_time(ptq->timestamp, &pt->tc);
1079
1080 sample.cpumode = PERF_RECORD_MISC_USER;
1081 sample.ip = ptq->state->from_ip;
1082 sample.pid = ptq->pid;
1083 sample.tid = ptq->tid;
1084 sample.addr = ptq->state->to_ip;
1085 sample.id = ptq->pt->branches_id; 1156 sample.id = ptq->pt->branches_id;
1086 sample.stream_id = ptq->pt->branches_id; 1157 sample.stream_id = ptq->pt->branches_id;
1087 sample.period = 1;
1088 sample.cpu = ptq->cpu;
1089 sample.flags = ptq->flags;
1090 sample.insn_len = ptq->insn_len;
1091 memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
1092 1158
1093 /* 1159 /*
1094 * perf report cannot handle events without a branch stack when using 1160 * perf report cannot handle events without a branch stack when using
@@ -1105,144 +1171,251 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
1105 sample.branch_stack = (struct branch_stack *)&dummy_bs; 1171 sample.branch_stack = (struct branch_stack *)&dummy_bs;
1106 } 1172 }
1107 1173
1108 if (pt->synth_opts.inject) { 1174 return intel_pt_deliver_synth_b_event(pt, event, &sample,
1109 ret = intel_pt_inject_event(event, &sample, 1175 pt->branches_sample_type);
1110 pt->branches_sample_type, 1176}
1111 pt->synth_needs_swap); 1177
1112 if (ret) 1178static void intel_pt_prep_sample(struct intel_pt *pt,
1113 return ret; 1179 struct intel_pt_queue *ptq,
1180 union perf_event *event,
1181 struct perf_sample *sample)
1182{
1183 intel_pt_prep_b_sample(pt, ptq, event, sample);
1184
1185 if (pt->synth_opts.callchain) {
1186 thread_stack__sample(ptq->thread, ptq->chain,
1187 pt->synth_opts.callchain_sz, sample->ip);
1188 sample->callchain = ptq->chain;
1114 } 1189 }
1115 1190
1116 ret = perf_session__deliver_synth_event(pt->session, event, &sample); 1191 if (pt->synth_opts.last_branch) {
1117 if (ret) 1192 intel_pt_copy_last_branch_rb(ptq);
1118 pr_err("Intel Processor Trace: failed to deliver branch event, error %d\n", 1193 sample->branch_stack = ptq->last_branch;
1119 ret); 1194 }
1195}
1196
1197static inline int intel_pt_deliver_synth_event(struct intel_pt *pt,
1198 struct intel_pt_queue *ptq,
1199 union perf_event *event,
1200 struct perf_sample *sample,
1201 u64 type)
1202{
1203 int ret;
1204
1205 ret = intel_pt_deliver_synth_b_event(pt, event, sample, type);
1206
1207 if (pt->synth_opts.last_branch)
1208 intel_pt_reset_last_branch_rb(ptq);
1120 1209
1121 return ret; 1210 return ret;
1122} 1211}
1123 1212
1124static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) 1213static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
1125{ 1214{
1126 int ret;
1127 struct intel_pt *pt = ptq->pt; 1215 struct intel_pt *pt = ptq->pt;
1128 union perf_event *event = ptq->event_buf; 1216 union perf_event *event = ptq->event_buf;
1129 struct perf_sample sample = { .ip = 0, }; 1217 struct perf_sample sample = { .ip = 0, };
1130 1218
1131 if (pt->synth_opts.initial_skip && 1219 if (intel_pt_skip_event(pt))
1132 pt->num_events++ < pt->synth_opts.initial_skip)
1133 return 0; 1220 return 0;
1134 1221
1135 event->sample.header.type = PERF_RECORD_SAMPLE; 1222 intel_pt_prep_sample(pt, ptq, event, &sample);
1136 event->sample.header.misc = PERF_RECORD_MISC_USER;
1137 event->sample.header.size = sizeof(struct perf_event_header);
1138
1139 if (!pt->timeless_decoding)
1140 sample.time = tsc_to_perf_time(ptq->timestamp, &pt->tc);
1141 1223
1142 sample.cpumode = PERF_RECORD_MISC_USER;
1143 sample.ip = ptq->state->from_ip;
1144 sample.pid = ptq->pid;
1145 sample.tid = ptq->tid;
1146 sample.addr = ptq->state->to_ip;
1147 sample.id = ptq->pt->instructions_id; 1224 sample.id = ptq->pt->instructions_id;
1148 sample.stream_id = ptq->pt->instructions_id; 1225 sample.stream_id = ptq->pt->instructions_id;
1149 sample.period = ptq->state->tot_insn_cnt - ptq->last_insn_cnt; 1226 sample.period = ptq->state->tot_insn_cnt - ptq->last_insn_cnt;
1150 sample.cpu = ptq->cpu;
1151 sample.flags = ptq->flags;
1152 sample.insn_len = ptq->insn_len;
1153 memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
1154 1227
1155 ptq->last_insn_cnt = ptq->state->tot_insn_cnt; 1228 ptq->last_insn_cnt = ptq->state->tot_insn_cnt;
1156 1229
1157 if (pt->synth_opts.callchain) { 1230 return intel_pt_deliver_synth_event(pt, ptq, event, &sample,
1158 thread_stack__sample(ptq->thread, ptq->chain, 1231 pt->instructions_sample_type);
1159 pt->synth_opts.callchain_sz, sample.ip); 1232}
1160 sample.callchain = ptq->chain;
1161 }
1162 1233
1163 if (pt->synth_opts.last_branch) { 1234static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
1164 intel_pt_copy_last_branch_rb(ptq); 1235{
1165 sample.branch_stack = ptq->last_branch; 1236 struct intel_pt *pt = ptq->pt;
1166 } 1237 union perf_event *event = ptq->event_buf;
1238 struct perf_sample sample = { .ip = 0, };
1167 1239
1168 if (pt->synth_opts.inject) { 1240 if (intel_pt_skip_event(pt))
1169 ret = intel_pt_inject_event(event, &sample, 1241 return 0;
1170 pt->instructions_sample_type,
1171 pt->synth_needs_swap);
1172 if (ret)
1173 return ret;
1174 }
1175 1242
1176 ret = perf_session__deliver_synth_event(pt->session, event, &sample); 1243 intel_pt_prep_sample(pt, ptq, event, &sample);
1177 if (ret)
1178 pr_err("Intel Processor Trace: failed to deliver instruction event, error %d\n",
1179 ret);
1180 1244
1181 if (pt->synth_opts.last_branch) 1245 sample.id = ptq->pt->transactions_id;
1182 intel_pt_reset_last_branch_rb(ptq); 1246 sample.stream_id = ptq->pt->transactions_id;
1183 1247
1184 return ret; 1248 return intel_pt_deliver_synth_event(pt, ptq, event, &sample,
1249 pt->transactions_sample_type);
1185} 1250}
1186 1251
1187static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq) 1252static void intel_pt_prep_p_sample(struct intel_pt *pt,
1253 struct intel_pt_queue *ptq,
1254 union perf_event *event,
1255 struct perf_sample *sample)
1256{
1257 intel_pt_prep_sample(pt, ptq, event, sample);
1258
1259 /*
1260 * Zero IP is used to mean "trace start" but that is not the case for
1261 * power or PTWRITE events with no IP, so clear the flags.
1262 */
1263 if (!sample->ip)
1264 sample->flags = 0;
1265}
1266
1267static int intel_pt_synth_ptwrite_sample(struct intel_pt_queue *ptq)
1188{ 1268{
1189 int ret;
1190 struct intel_pt *pt = ptq->pt; 1269 struct intel_pt *pt = ptq->pt;
1191 union perf_event *event = ptq->event_buf; 1270 union perf_event *event = ptq->event_buf;
1192 struct perf_sample sample = { .ip = 0, }; 1271 struct perf_sample sample = { .ip = 0, };
1272 struct perf_synth_intel_ptwrite raw;
1193 1273
1194 if (pt->synth_opts.initial_skip && 1274 if (intel_pt_skip_event(pt))
1195 pt->num_events++ < pt->synth_opts.initial_skip)
1196 return 0; 1275 return 0;
1197 1276
1198 event->sample.header.type = PERF_RECORD_SAMPLE; 1277 intel_pt_prep_p_sample(pt, ptq, event, &sample);
1199 event->sample.header.misc = PERF_RECORD_MISC_USER;
1200 event->sample.header.size = sizeof(struct perf_event_header);
1201 1278
1202 if (!pt->timeless_decoding) 1279 sample.id = ptq->pt->ptwrites_id;
1203 sample.time = tsc_to_perf_time(ptq->timestamp, &pt->tc); 1280 sample.stream_id = ptq->pt->ptwrites_id;
1204 1281
1205 sample.cpumode = PERF_RECORD_MISC_USER; 1282 raw.flags = 0;
1206 sample.ip = ptq->state->from_ip; 1283 raw.ip = !!(ptq->state->flags & INTEL_PT_FUP_IP);
1207 sample.pid = ptq->pid; 1284 raw.payload = cpu_to_le64(ptq->state->ptw_payload);
1208 sample.tid = ptq->tid;
1209 sample.addr = ptq->state->to_ip;
1210 sample.id = ptq->pt->transactions_id;
1211 sample.stream_id = ptq->pt->transactions_id;
1212 sample.period = 1;
1213 sample.cpu = ptq->cpu;
1214 sample.flags = ptq->flags;
1215 sample.insn_len = ptq->insn_len;
1216 memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
1217 1285
1218 if (pt->synth_opts.callchain) { 1286 sample.raw_size = perf_synth__raw_size(raw);
1219 thread_stack__sample(ptq->thread, ptq->chain, 1287 sample.raw_data = perf_synth__raw_data(&raw);
1220 pt->synth_opts.callchain_sz, sample.ip);
1221 sample.callchain = ptq->chain;
1222 }
1223 1288
1224 if (pt->synth_opts.last_branch) { 1289 return intel_pt_deliver_synth_event(pt, ptq, event, &sample,
1225 intel_pt_copy_last_branch_rb(ptq); 1290 pt->ptwrites_sample_type);
1226 sample.branch_stack = ptq->last_branch; 1291}
1227 }
1228 1292
1229 if (pt->synth_opts.inject) { 1293static int intel_pt_synth_cbr_sample(struct intel_pt_queue *ptq)
1230 ret = intel_pt_inject_event(event, &sample, 1294{
1231 pt->transactions_sample_type, 1295 struct intel_pt *pt = ptq->pt;
1232 pt->synth_needs_swap); 1296 union perf_event *event = ptq->event_buf;
1233 if (ret) 1297 struct perf_sample sample = { .ip = 0, };
1234 return ret; 1298 struct perf_synth_intel_cbr raw;
1235 } 1299 u32 flags;
1236 1300
1237 ret = perf_session__deliver_synth_event(pt->session, event, &sample); 1301 if (intel_pt_skip_event(pt))
1238 if (ret) 1302 return 0;
1239 pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n",
1240 ret);
1241 1303
1242 if (pt->synth_opts.last_branch) 1304 intel_pt_prep_p_sample(pt, ptq, event, &sample);
1243 intel_pt_reset_last_branch_rb(ptq);
1244 1305
1245 return ret; 1306 sample.id = ptq->pt->cbr_id;
1307 sample.stream_id = ptq->pt->cbr_id;
1308
1309 flags = (u16)ptq->state->cbr_payload | (pt->max_non_turbo_ratio << 16);
1310 raw.flags = cpu_to_le32(flags);
1311 raw.freq = cpu_to_le32(raw.cbr * pt->cbr2khz);
1312 raw.reserved3 = 0;
1313
1314 sample.raw_size = perf_synth__raw_size(raw);
1315 sample.raw_data = perf_synth__raw_data(&raw);
1316
1317 return intel_pt_deliver_synth_event(pt, ptq, event, &sample,
1318 pt->pwr_events_sample_type);
1319}
1320
1321static int intel_pt_synth_mwait_sample(struct intel_pt_queue *ptq)
1322{
1323 struct intel_pt *pt = ptq->pt;
1324 union perf_event *event = ptq->event_buf;
1325 struct perf_sample sample = { .ip = 0, };
1326 struct perf_synth_intel_mwait raw;
1327
1328 if (intel_pt_skip_event(pt))
1329 return 0;
1330
1331 intel_pt_prep_p_sample(pt, ptq, event, &sample);
1332
1333 sample.id = ptq->pt->mwait_id;
1334 sample.stream_id = ptq->pt->mwait_id;
1335
1336 raw.reserved = 0;
1337 raw.payload = cpu_to_le64(ptq->state->mwait_payload);
1338
1339 sample.raw_size = perf_synth__raw_size(raw);
1340 sample.raw_data = perf_synth__raw_data(&raw);
1341
1342 return intel_pt_deliver_synth_event(pt, ptq, event, &sample,
1343 pt->pwr_events_sample_type);
1344}
1345
1346static int intel_pt_synth_pwre_sample(struct intel_pt_queue *ptq)
1347{
1348 struct intel_pt *pt = ptq->pt;
1349 union perf_event *event = ptq->event_buf;
1350 struct perf_sample sample = { .ip = 0, };
1351 struct perf_synth_intel_pwre raw;
1352
1353 if (intel_pt_skip_event(pt))
1354 return 0;
1355
1356 intel_pt_prep_p_sample(pt, ptq, event, &sample);
1357
1358 sample.id = ptq->pt->pwre_id;
1359 sample.stream_id = ptq->pt->pwre_id;
1360
1361 raw.reserved = 0;
1362 raw.payload = cpu_to_le64(ptq->state->pwre_payload);
1363
1364 sample.raw_size = perf_synth__raw_size(raw);
1365 sample.raw_data = perf_synth__raw_data(&raw);
1366
1367 return intel_pt_deliver_synth_event(pt, ptq, event, &sample,
1368 pt->pwr_events_sample_type);
1369}
1370
1371static int intel_pt_synth_exstop_sample(struct intel_pt_queue *ptq)
1372{
1373 struct intel_pt *pt = ptq->pt;
1374 union perf_event *event = ptq->event_buf;
1375 struct perf_sample sample = { .ip = 0, };
1376 struct perf_synth_intel_exstop raw;
1377
1378 if (intel_pt_skip_event(pt))
1379 return 0;
1380
1381 intel_pt_prep_p_sample(pt, ptq, event, &sample);
1382
1383 sample.id = ptq->pt->exstop_id;
1384 sample.stream_id = ptq->pt->exstop_id;
1385
1386 raw.flags = 0;
1387 raw.ip = !!(ptq->state->flags & INTEL_PT_FUP_IP);
1388
1389 sample.raw_size = perf_synth__raw_size(raw);
1390 sample.raw_data = perf_synth__raw_data(&raw);
1391
1392 return intel_pt_deliver_synth_event(pt, ptq, event, &sample,
1393 pt->pwr_events_sample_type);
1394}
1395
1396static int intel_pt_synth_pwrx_sample(struct intel_pt_queue *ptq)
1397{
1398 struct intel_pt *pt = ptq->pt;
1399 union perf_event *event = ptq->event_buf;
1400 struct perf_sample sample = { .ip = 0, };
1401 struct perf_synth_intel_pwrx raw;
1402
1403 if (intel_pt_skip_event(pt))
1404 return 0;
1405
1406 intel_pt_prep_p_sample(pt, ptq, event, &sample);
1407
1408 sample.id = ptq->pt->pwrx_id;
1409 sample.stream_id = ptq->pt->pwrx_id;
1410
1411 raw.reserved = 0;
1412 raw.payload = cpu_to_le64(ptq->state->pwrx_payload);
1413
1414 sample.raw_size = perf_synth__raw_size(raw);
1415 sample.raw_data = perf_synth__raw_data(&raw);
1416
1417 return intel_pt_deliver_synth_event(pt, ptq, event, &sample,
1418 pt->pwr_events_sample_type);
1246} 1419}
1247 1420
1248static int intel_pt_synth_error(struct intel_pt *pt, int code, int cpu, 1421static int intel_pt_synth_error(struct intel_pt *pt, int code, int cpu,
@@ -1296,6 +1469,10 @@ static inline bool intel_pt_is_switch_ip(struct intel_pt_queue *ptq, u64 ip)
1296 PERF_IP_FLAG_INTERRUPT | PERF_IP_FLAG_TX_ABORT)); 1469 PERF_IP_FLAG_INTERRUPT | PERF_IP_FLAG_TX_ABORT));
1297} 1470}
1298 1471
1472#define INTEL_PT_PWR_EVT (INTEL_PT_MWAIT_OP | INTEL_PT_PWR_ENTRY | \
1473 INTEL_PT_EX_STOP | INTEL_PT_PWR_EXIT | \
1474 INTEL_PT_CBR_CHG)
1475
1299static int intel_pt_sample(struct intel_pt_queue *ptq) 1476static int intel_pt_sample(struct intel_pt_queue *ptq)
1300{ 1477{
1301 const struct intel_pt_state *state = ptq->state; 1478 const struct intel_pt_state *state = ptq->state;
@@ -1307,24 +1484,52 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1307 1484
1308 ptq->have_sample = false; 1485 ptq->have_sample = false;
1309 1486
1310 if (pt->sample_instructions && 1487 if (pt->sample_pwr_events && (state->type & INTEL_PT_PWR_EVT)) {
1311 (state->type & INTEL_PT_INSTRUCTION) && 1488 if (state->type & INTEL_PT_CBR_CHG) {
1312 (!pt->synth_opts.initial_skip || 1489 err = intel_pt_synth_cbr_sample(ptq);
1313 pt->num_events++ >= pt->synth_opts.initial_skip)) { 1490 if (err)
1491 return err;
1492 }
1493 if (state->type & INTEL_PT_MWAIT_OP) {
1494 err = intel_pt_synth_mwait_sample(ptq);
1495 if (err)
1496 return err;
1497 }
1498 if (state->type & INTEL_PT_PWR_ENTRY) {
1499 err = intel_pt_synth_pwre_sample(ptq);
1500 if (err)
1501 return err;
1502 }
1503 if (state->type & INTEL_PT_EX_STOP) {
1504 err = intel_pt_synth_exstop_sample(ptq);
1505 if (err)
1506 return err;
1507 }
1508 if (state->type & INTEL_PT_PWR_EXIT) {
1509 err = intel_pt_synth_pwrx_sample(ptq);
1510 if (err)
1511 return err;
1512 }
1513 }
1514
1515 if (pt->sample_instructions && (state->type & INTEL_PT_INSTRUCTION)) {
1314 err = intel_pt_synth_instruction_sample(ptq); 1516 err = intel_pt_synth_instruction_sample(ptq);
1315 if (err) 1517 if (err)
1316 return err; 1518 return err;
1317 } 1519 }
1318 1520
1319 if (pt->sample_transactions && 1521 if (pt->sample_transactions && (state->type & INTEL_PT_TRANSACTION)) {
1320 (state->type & INTEL_PT_TRANSACTION) &&
1321 (!pt->synth_opts.initial_skip ||
1322 pt->num_events++ >= pt->synth_opts.initial_skip)) {
1323 err = intel_pt_synth_transaction_sample(ptq); 1522 err = intel_pt_synth_transaction_sample(ptq);
1324 if (err) 1523 if (err)
1325 return err; 1524 return err;
1326 } 1525 }
1327 1526
1527 if (pt->sample_ptwrites && (state->type & INTEL_PT_PTW)) {
1528 err = intel_pt_synth_ptwrite_sample(ptq);
1529 if (err)
1530 return err;
1531 }
1532
1328 if (!(state->type & INTEL_PT_BRANCH)) 1533 if (!(state->type & INTEL_PT_BRANCH))
1329 return 0; 1534 return 0;
1330 1535
@@ -1925,36 +2130,65 @@ static int intel_pt_event_synth(struct perf_tool *tool,
1925 NULL); 2130 NULL);
1926} 2131}
1927 2132
1928static int intel_pt_synth_event(struct perf_session *session, 2133static int intel_pt_synth_event(struct perf_session *session, const char *name,
1929 struct perf_event_attr *attr, u64 id) 2134 struct perf_event_attr *attr, u64 id)
1930{ 2135{
1931 struct intel_pt_synth intel_pt_synth; 2136 struct intel_pt_synth intel_pt_synth;
2137 int err;
2138
2139 pr_debug("Synthesizing '%s' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
2140 name, id, (u64)attr->sample_type);
1932 2141
1933 memset(&intel_pt_synth, 0, sizeof(struct intel_pt_synth)); 2142 memset(&intel_pt_synth, 0, sizeof(struct intel_pt_synth));
1934 intel_pt_synth.session = session; 2143 intel_pt_synth.session = session;
1935 2144
1936 return perf_event__synthesize_attr(&intel_pt_synth.dummy_tool, attr, 1, 2145 err = perf_event__synthesize_attr(&intel_pt_synth.dummy_tool, attr, 1,
1937 &id, intel_pt_event_synth); 2146 &id, intel_pt_event_synth);
2147 if (err)
2148 pr_err("%s: failed to synthesize '%s' event type\n",
2149 __func__, name);
2150
2151 return err;
1938} 2152}
1939 2153
1940static int intel_pt_synth_events(struct intel_pt *pt, 2154static void intel_pt_set_event_name(struct perf_evlist *evlist, u64 id,
1941 struct perf_session *session) 2155 const char *name)
1942{ 2156{
1943 struct perf_evlist *evlist = session->evlist;
1944 struct perf_evsel *evsel; 2157 struct perf_evsel *evsel;
1945 struct perf_event_attr attr;
1946 bool found = false;
1947 u64 id;
1948 int err;
1949 2158
1950 evlist__for_each_entry(evlist, evsel) { 2159 evlist__for_each_entry(evlist, evsel) {
1951 if (evsel->attr.type == pt->pmu_type && evsel->ids) { 2160 if (evsel->id && evsel->id[0] == id) {
1952 found = true; 2161 if (evsel->name)
2162 zfree(&evsel->name);
2163 evsel->name = strdup(name);
1953 break; 2164 break;
1954 } 2165 }
1955 } 2166 }
2167}
1956 2168
1957 if (!found) { 2169static struct perf_evsel *intel_pt_evsel(struct intel_pt *pt,
2170 struct perf_evlist *evlist)
2171{
2172 struct perf_evsel *evsel;
2173
2174 evlist__for_each_entry(evlist, evsel) {
2175 if (evsel->attr.type == pt->pmu_type && evsel->ids)
2176 return evsel;
2177 }
2178
2179 return NULL;
2180}
2181
2182static int intel_pt_synth_events(struct intel_pt *pt,
2183 struct perf_session *session)
2184{
2185 struct perf_evlist *evlist = session->evlist;
2186 struct perf_evsel *evsel = intel_pt_evsel(pt, evlist);
2187 struct perf_event_attr attr;
2188 u64 id;
2189 int err;
2190
2191 if (!evsel) {
1958 pr_debug("There are no selected events with Intel Processor Trace data\n"); 2192 pr_debug("There are no selected events with Intel Processor Trace data\n");
1959 return 0; 2193 return 0;
1960 } 2194 }
@@ -1983,6 +2217,25 @@ static int intel_pt_synth_events(struct intel_pt *pt,
1983 if (!id) 2217 if (!id)
1984 id = 1; 2218 id = 1;
1985 2219
2220 if (pt->synth_opts.branches) {
2221 attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
2222 attr.sample_period = 1;
2223 attr.sample_type |= PERF_SAMPLE_ADDR;
2224 err = intel_pt_synth_event(session, "branches", &attr, id);
2225 if (err)
2226 return err;
2227 pt->sample_branches = true;
2228 pt->branches_sample_type = attr.sample_type;
2229 pt->branches_id = id;
2230 id += 1;
2231 attr.sample_type &= ~(u64)PERF_SAMPLE_ADDR;
2232 }
2233
2234 if (pt->synth_opts.callchain)
2235 attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
2236 if (pt->synth_opts.last_branch)
2237 attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
2238
1986 if (pt->synth_opts.instructions) { 2239 if (pt->synth_opts.instructions) {
1987 attr.config = PERF_COUNT_HW_INSTRUCTIONS; 2240 attr.config = PERF_COUNT_HW_INSTRUCTIONS;
1988 if (pt->synth_opts.period_type == PERF_ITRACE_PERIOD_NANOSECS) 2241 if (pt->synth_opts.period_type == PERF_ITRACE_PERIOD_NANOSECS)
@@ -1990,70 +2243,90 @@ static int intel_pt_synth_events(struct intel_pt *pt,
1990 intel_pt_ns_to_ticks(pt, pt->synth_opts.period); 2243 intel_pt_ns_to_ticks(pt, pt->synth_opts.period);
1991 else 2244 else
1992 attr.sample_period = pt->synth_opts.period; 2245 attr.sample_period = pt->synth_opts.period;
1993 pt->instructions_sample_period = attr.sample_period; 2246 err = intel_pt_synth_event(session, "instructions", &attr, id);
1994 if (pt->synth_opts.callchain) 2247 if (err)
1995 attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
1996 if (pt->synth_opts.last_branch)
1997 attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
1998 pr_debug("Synthesizing 'instructions' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
1999 id, (u64)attr.sample_type);
2000 err = intel_pt_synth_event(session, &attr, id);
2001 if (err) {
2002 pr_err("%s: failed to synthesize 'instructions' event type\n",
2003 __func__);
2004 return err; 2248 return err;
2005 }
2006 pt->sample_instructions = true; 2249 pt->sample_instructions = true;
2007 pt->instructions_sample_type = attr.sample_type; 2250 pt->instructions_sample_type = attr.sample_type;
2008 pt->instructions_id = id; 2251 pt->instructions_id = id;
2009 id += 1; 2252 id += 1;
2010 } 2253 }
2011 2254
2255 attr.sample_type &= ~(u64)PERF_SAMPLE_PERIOD;
2256 attr.sample_period = 1;
2257
2012 if (pt->synth_opts.transactions) { 2258 if (pt->synth_opts.transactions) {
2013 attr.config = PERF_COUNT_HW_INSTRUCTIONS; 2259 attr.config = PERF_COUNT_HW_INSTRUCTIONS;
2014 attr.sample_period = 1; 2260 err = intel_pt_synth_event(session, "transactions", &attr, id);
2015 if (pt->synth_opts.callchain) 2261 if (err)
2016 attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
2017 if (pt->synth_opts.last_branch)
2018 attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
2019 pr_debug("Synthesizing 'transactions' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
2020 id, (u64)attr.sample_type);
2021 err = intel_pt_synth_event(session, &attr, id);
2022 if (err) {
2023 pr_err("%s: failed to synthesize 'transactions' event type\n",
2024 __func__);
2025 return err; 2262 return err;
2026 }
2027 pt->sample_transactions = true; 2263 pt->sample_transactions = true;
2264 pt->transactions_sample_type = attr.sample_type;
2028 pt->transactions_id = id; 2265 pt->transactions_id = id;
2266 intel_pt_set_event_name(evlist, id, "transactions");
2029 id += 1; 2267 id += 1;
2030 evlist__for_each_entry(evlist, evsel) {
2031 if (evsel->id && evsel->id[0] == pt->transactions_id) {
2032 if (evsel->name)
2033 zfree(&evsel->name);
2034 evsel->name = strdup("transactions");
2035 break;
2036 }
2037 }
2038 } 2268 }
2039 2269
2040 if (pt->synth_opts.branches) { 2270 attr.type = PERF_TYPE_SYNTH;
2041 attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS; 2271 attr.sample_type |= PERF_SAMPLE_RAW;
2042 attr.sample_period = 1; 2272
2043 attr.sample_type |= PERF_SAMPLE_ADDR; 2273 if (pt->synth_opts.ptwrites) {
2044 attr.sample_type &= ~(u64)PERF_SAMPLE_CALLCHAIN; 2274 attr.config = PERF_SYNTH_INTEL_PTWRITE;
2045 attr.sample_type &= ~(u64)PERF_SAMPLE_BRANCH_STACK; 2275 err = intel_pt_synth_event(session, "ptwrite", &attr, id);
2046 pr_debug("Synthesizing 'branches' event with id %" PRIu64 " sample type %#" PRIx64 "\n", 2276 if (err)
2047 id, (u64)attr.sample_type);
2048 err = intel_pt_synth_event(session, &attr, id);
2049 if (err) {
2050 pr_err("%s: failed to synthesize 'branches' event type\n",
2051 __func__);
2052 return err; 2277 return err;
2053 } 2278 pt->sample_ptwrites = true;
2054 pt->sample_branches = true; 2279 pt->ptwrites_sample_type = attr.sample_type;
2055 pt->branches_sample_type = attr.sample_type; 2280 pt->ptwrites_id = id;
2056 pt->branches_id = id; 2281 intel_pt_set_event_name(evlist, id, "ptwrite");
2282 id += 1;
2283 }
2284
2285 if (pt->synth_opts.pwr_events) {
2286 pt->sample_pwr_events = true;
2287 pt->pwr_events_sample_type = attr.sample_type;
2288
2289 attr.config = PERF_SYNTH_INTEL_CBR;
2290 err = intel_pt_synth_event(session, "cbr", &attr, id);
2291 if (err)
2292 return err;
2293 pt->cbr_id = id;
2294 intel_pt_set_event_name(evlist, id, "cbr");
2295 id += 1;
2296 }
2297
2298 if (pt->synth_opts.pwr_events && (evsel->attr.config & 0x10)) {
2299 attr.config = PERF_SYNTH_INTEL_MWAIT;
2300 err = intel_pt_synth_event(session, "mwait", &attr, id);
2301 if (err)
2302 return err;
2303 pt->mwait_id = id;
2304 intel_pt_set_event_name(evlist, id, "mwait");
2305 id += 1;
2306
2307 attr.config = PERF_SYNTH_INTEL_PWRE;
2308 err = intel_pt_synth_event(session, "pwre", &attr, id);
2309 if (err)
2310 return err;
2311 pt->pwre_id = id;
2312 intel_pt_set_event_name(evlist, id, "pwre");
2313 id += 1;
2314
2315 attr.config = PERF_SYNTH_INTEL_EXSTOP;
2316 err = intel_pt_synth_event(session, "exstop", &attr, id);
2317 if (err)
2318 return err;
2319 pt->exstop_id = id;
2320 intel_pt_set_event_name(evlist, id, "exstop");
2321 id += 1;
2322
2323 attr.config = PERF_SYNTH_INTEL_PWRX;
2324 err = intel_pt_synth_event(session, "pwrx", &attr, id);
2325 if (err)
2326 return err;
2327 pt->pwrx_id = id;
2328 intel_pt_set_event_name(evlist, id, "pwrx");
2329 id += 1;
2057 } 2330 }
2058 2331
2059 pt->synth_needs_swap = evsel->needs_swap; 2332 pt->synth_needs_swap = evsel->needs_swap;
@@ -2322,6 +2595,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2322 intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq); 2595 intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq);
2323 intel_pt_log("Maximum non-turbo ratio %u\n", 2596 intel_pt_log("Maximum non-turbo ratio %u\n",
2324 pt->max_non_turbo_ratio); 2597 pt->max_non_turbo_ratio);
2598 pt->cbr2khz = tsc_freq / pt->max_non_turbo_ratio / 1000;
2325 } 2599 }
2326 2600
2327 if (pt->synth_opts.calls) 2601 if (pt->synth_opts.calls)
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index d97e014c3df3..5de2b86b9880 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -572,16 +572,7 @@ static struct dso *machine__findnew_module_dso(struct machine *machine,
572 if (dso == NULL) 572 if (dso == NULL)
573 goto out_unlock; 573 goto out_unlock;
574 574
575 if (machine__is_host(machine)) 575 dso__set_module_info(dso, m, machine);
576 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
577 else
578 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
579
580 /* _KMODULE_COMP should be next to _KMODULE */
581 if (m->kmod && m->comp)
582 dso->symtab_type++;
583
584 dso__set_short_name(dso, strdup(m->name), true);
585 dso__set_long_name(dso, strdup(filename), true); 576 dso__set_long_name(dso, strdup(filename), true);
586 } 577 }
587 578
@@ -1218,10 +1209,12 @@ int machine__create_kernel_maps(struct machine *machine)
1218 */ 1209 */
1219 map_groups__fixup_end(&machine->kmaps); 1210 map_groups__fixup_end(&machine->kmaps);
1220 1211
1221 if (machine__get_running_kernel_start(machine, &name, &addr)) { 1212 if (!machine__get_running_kernel_start(machine, &name, &addr)) {
1222 } else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) { 1213 if (name &&
1223 machine__destroy_kernel_maps(machine); 1214 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
1224 return -1; 1215 machine__destroy_kernel_maps(machine);
1216 return -1;
1217 }
1225 } 1218 }
1226 1219
1227 return 0; 1220 return 0;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index ea7f450dc609..389e9729331f 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -2,6 +2,7 @@
2#define __PMU_H 2#define __PMU_H
3 3
4#include <linux/bitmap.h> 4#include <linux/bitmap.h>
5#include <linux/compiler.h>
5#include <linux/perf_event.h> 6#include <linux/perf_event.h>
6#include <stdbool.h> 7#include <stdbool.h>
7#include "evsel.h" 8#include "evsel.h"
@@ -83,8 +84,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet,
83 bool long_desc, bool details_flag); 84 bool long_desc, bool details_flag);
84bool pmu_have_event(const char *pname, const char *name); 85bool pmu_have_event(const char *pname, const char *name);
85 86
86int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, 87int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, ...) __scanf(3, 4);
87 ...) __attribute__((format(scanf, 3, 4)));
88 88
89int perf_pmu__test(void); 89int perf_pmu__test(void);
90 90
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 84e7e698411e..a2670e9d652d 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -619,7 +619,7 @@ static int post_process_probe_trace_point(struct probe_trace_point *tp,
619 struct map *map, unsigned long offs) 619 struct map *map, unsigned long offs)
620{ 620{
621 struct symbol *sym; 621 struct symbol *sym;
622 u64 addr = tp->address + tp->offset - offs; 622 u64 addr = tp->address - offs;
623 623
624 sym = map__find_symbol(map, addr); 624 sym = map__find_symbol(map, addr);
625 if (!sym) 625 if (!sym)
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 373842656fb6..5812947418dd 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -1,6 +1,7 @@
1#ifndef _PROBE_EVENT_H 1#ifndef _PROBE_EVENT_H
2#define _PROBE_EVENT_H 2#define _PROBE_EVENT_H
3 3
4#include <linux/compiler.h>
4#include <stdbool.h> 5#include <stdbool.h>
5#include "intlist.h" 6#include "intlist.h"
6 7
@@ -171,8 +172,7 @@ void arch__fix_tev_from_maps(struct perf_probe_event *pev,
171 struct symbol *sym); 172 struct symbol *sym);
172 173
173/* If there is no space to write, returns -E2BIG. */ 174/* If there is no space to write, returns -E2BIG. */
174int e_snprintf(char *str, size_t size, const char *format, ...) 175int e_snprintf(char *str, size_t size, const char *format, ...) __printf(3, 4);
175 __attribute__((format(printf, 3, 4)));
176 176
177/* Maximum index number of event-name postfix */ 177/* Maximum index number of event-name postfix */
178#define MAX_EVENT_INDEX 1024 178#define MAX_EVENT_INDEX 1024
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 9d92af7d0718..57b7a00e6f16 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -28,6 +28,7 @@
28#include <stdbool.h> 28#include <stdbool.h>
29#include <errno.h> 29#include <errno.h>
30#include <linux/bitmap.h> 30#include <linux/bitmap.h>
31#include <linux/compiler.h>
31#include <linux/time64.h> 32#include <linux/time64.h>
32 33
33#include "../../perf.h" 34#include "../../perf.h"
@@ -84,7 +85,7 @@ struct tables {
84 85
85static struct tables tables_global; 86static struct tables tables_global;
86 87
87static void handler_call_die(const char *handler_name) NORETURN; 88static void handler_call_die(const char *handler_name) __noreturn;
88static void handler_call_die(const char *handler_name) 89static void handler_call_die(const char *handler_name)
89{ 90{
90 PyErr_Print(); 91 PyErr_Print();
@@ -1219,7 +1220,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
1219 fprintf(ofp, "# be retrieved using Python functions of the form " 1220 fprintf(ofp, "# be retrieved using Python functions of the form "
1220 "common_*(context).\n"); 1221 "common_*(context).\n");
1221 1222
1222 fprintf(ofp, "# See the perf-trace-python Documentation for the list " 1223 fprintf(ofp, "# See the perf-script-python Documentation for the list "
1223 "of available functions.\n\n"); 1224 "of available functions.\n\n");
1224 1225
1225 fprintf(ofp, "import os\n"); 1226 fprintf(ofp, "import os\n");
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 7dc1096264c5..d19c40a81040 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -2035,7 +2035,7 @@ int perf_session__cpu_bitmap(struct perf_session *session,
2035 2035
2036 if (!(evsel->attr.sample_type & PERF_SAMPLE_CPU)) { 2036 if (!(evsel->attr.sample_type & PERF_SAMPLE_CPU)) {
2037 pr_err("File does not contain CPU events. " 2037 pr_err("File does not contain CPU events. "
2038 "Remove -c option to proceed.\n"); 2038 "Remove -C option to proceed.\n");
2039 return -1; 2039 return -1;
2040 } 2040 }
2041 } 2041 }
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 5762ae4e9e91..8b327c955a4f 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -2532,12 +2532,12 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str,
2532 ret = sort_dimension__add(list, tok, evlist, level); 2532 ret = sort_dimension__add(list, tok, evlist, level);
2533 if (ret == -EINVAL) { 2533 if (ret == -EINVAL) {
2534 if (!cacheline_size && !strncasecmp(tok, "dcacheline", strlen(tok))) 2534 if (!cacheline_size && !strncasecmp(tok, "dcacheline", strlen(tok)))
2535 error("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system"); 2535 pr_err("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system");
2536 else 2536 else
2537 error("Invalid --sort key: `%s'", tok); 2537 pr_err("Invalid --sort key: `%s'", tok);
2538 break; 2538 break;
2539 } else if (ret == -ESRCH) { 2539 } else if (ret == -ESRCH) {
2540 error("Unknown --sort key: `%s'", tok); 2540 pr_err("Unknown --sort key: `%s'", tok);
2541 break; 2541 break;
2542 } 2542 }
2543 } 2543 }
@@ -2594,7 +2594,7 @@ static int setup_sort_order(struct perf_evlist *evlist)
2594 return 0; 2594 return 0;
2595 2595
2596 if (sort_order[1] == '\0') { 2596 if (sort_order[1] == '\0') {
2597 error("Invalid --sort key: `+'"); 2597 pr_err("Invalid --sort key: `+'");
2598 return -EINVAL; 2598 return -EINVAL;
2599 } 2599 }
2600 2600
@@ -2604,7 +2604,7 @@ static int setup_sort_order(struct perf_evlist *evlist)
2604 */ 2604 */
2605 if (asprintf(&new_sort_order, "%s,%s", 2605 if (asprintf(&new_sort_order, "%s,%s",
2606 get_default_sort_order(evlist), sort_order + 1) < 0) { 2606 get_default_sort_order(evlist), sort_order + 1) < 0) {
2607 error("Not enough memory to set up --sort"); 2607 pr_err("Not enough memory to set up --sort");
2608 return -ENOMEM; 2608 return -ENOMEM;
2609 } 2609 }
2610 2610
@@ -2668,7 +2668,7 @@ static int __setup_sorting(struct perf_evlist *evlist)
2668 2668
2669 str = strdup(sort_keys); 2669 str = strdup(sort_keys);
2670 if (str == NULL) { 2670 if (str == NULL) {
2671 error("Not enough memory to setup sort keys"); 2671 pr_err("Not enough memory to setup sort keys");
2672 return -ENOMEM; 2672 return -ENOMEM;
2673 } 2673 }
2674 2674
@@ -2678,7 +2678,7 @@ static int __setup_sorting(struct perf_evlist *evlist)
2678 if (!is_strict_order(field_order)) { 2678 if (!is_strict_order(field_order)) {
2679 str = setup_overhead(str); 2679 str = setup_overhead(str);
2680 if (str == NULL) { 2680 if (str == NULL) {
2681 error("Not enough memory to setup overhead keys"); 2681 pr_err("Not enough memory to setup overhead keys");
2682 return -ENOMEM; 2682 return -ENOMEM;
2683 } 2683 }
2684 } 2684 }
@@ -2834,10 +2834,10 @@ static int setup_output_list(struct perf_hpp_list *list, char *str)
2834 tok; tok = strtok_r(NULL, ", ", &tmp)) { 2834 tok; tok = strtok_r(NULL, ", ", &tmp)) {
2835 ret = output_field_add(list, tok); 2835 ret = output_field_add(list, tok);
2836 if (ret == -EINVAL) { 2836 if (ret == -EINVAL) {
2837 error("Invalid --fields key: `%s'", tok); 2837 pr_err("Invalid --fields key: `%s'", tok);
2838 break; 2838 break;
2839 } else if (ret == -ESRCH) { 2839 } else if (ret == -ESRCH) {
2840 error("Unknown --fields key: `%s'", tok); 2840 pr_err("Unknown --fields key: `%s'", tok);
2841 break; 2841 break;
2842 } 2842 }
2843 } 2843 }
@@ -2877,7 +2877,7 @@ static int __setup_output_field(void)
2877 2877
2878 strp = str = strdup(field_order); 2878 strp = str = strdup(field_order);
2879 if (str == NULL) { 2879 if (str == NULL) {
2880 error("Not enough memory to setup output fields"); 2880 pr_err("Not enough memory to setup output fields");
2881 return -ENOMEM; 2881 return -ENOMEM;
2882 } 2882 }
2883 2883
@@ -2885,7 +2885,7 @@ static int __setup_output_field(void)
2885 strp++; 2885 strp++;
2886 2886
2887 if (!strlen(strp)) { 2887 if (!strlen(strp)) {
2888 error("Invalid --fields key: `+'"); 2888 pr_err("Invalid --fields key: `+'");
2889 goto out; 2889 goto out;
2890 } 2890 }
2891 2891
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index df051a52393c..ebc88a74e67b 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -56,7 +56,10 @@ static int inline_list__append(char *filename, char *funcname, int line_nr,
56 } 56 }
57 } 57 }
58 58
59 list_add_tail(&ilist->list, &node->val); 59 if (callchain_param.order == ORDER_CALLEE)
60 list_add_tail(&ilist->list, &node->val);
61 else
62 list_add(&ilist->list, &node->val);
60 63
61 return 0; 64 return 0;
62} 65}
@@ -200,12 +203,14 @@ static void addr2line_cleanup(struct a2l_data *a2l)
200 203
201#define MAX_INLINE_NEST 1024 204#define MAX_INLINE_NEST 1024
202 205
203static void inline_list__reverse(struct inline_node *node) 206static int inline_list__append_dso_a2l(struct dso *dso,
207 struct inline_node *node)
204{ 208{
205 struct inline_list *ilist, *n; 209 struct a2l_data *a2l = dso->a2l;
210 char *funcname = a2l->funcname ? strdup(a2l->funcname) : NULL;
211 char *filename = a2l->filename ? strdup(a2l->filename) : NULL;
206 212
207 list_for_each_entry_safe_reverse(ilist, n, &node->val, list) 213 return inline_list__append(filename, funcname, a2l->line, node, dso);
208 list_move_tail(&ilist->list, &node->val);
209} 214}
210 215
211static int addr2line(const char *dso_name, u64 addr, 216static int addr2line(const char *dso_name, u64 addr,
@@ -230,36 +235,36 @@ static int addr2line(const char *dso_name, u64 addr,
230 235
231 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); 236 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l);
232 237
233 if (a2l->found && unwind_inlines) { 238 if (!a2l->found)
239 return 0;
240
241 if (unwind_inlines) {
234 int cnt = 0; 242 int cnt = 0;
235 243
244 if (node && inline_list__append_dso_a2l(dso, node))
245 return 0;
246
236 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename, 247 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename,
237 &a2l->funcname, &a2l->line) && 248 &a2l->funcname, &a2l->line) &&
238 cnt++ < MAX_INLINE_NEST) { 249 cnt++ < MAX_INLINE_NEST) {
239 250
240 if (node != NULL) { 251 if (node != NULL) {
241 if (inline_list__append(strdup(a2l->filename), 252 if (inline_list__append_dso_a2l(dso, node))
242 strdup(a2l->funcname),
243 a2l->line, node,
244 dso) != 0)
245 return 0; 253 return 0;
254 // found at least one inline frame
255 ret = 1;
246 } 256 }
247 } 257 }
258 }
248 259
249 if ((node != NULL) && 260 if (file) {
250 (callchain_param.order != ORDER_CALLEE)) { 261 *file = a2l->filename ? strdup(a2l->filename) : NULL;
251 inline_list__reverse(node); 262 ret = *file ? 1 : 0;
252 }
253 } 263 }
254 264
255 if (a2l->found && a2l->filename) { 265 if (line)
256 *file = strdup(a2l->filename);
257 *line = a2l->line; 266 *line = a2l->line;
258 267
259 if (*file)
260 ret = 1;
261 }
262
263 return ret; 268 return ret;
264} 269}
265 270
@@ -278,8 +283,6 @@ void dso__free_a2l(struct dso *dso)
278static struct inline_node *addr2inlines(const char *dso_name, u64 addr, 283static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
279 struct dso *dso) 284 struct dso *dso)
280{ 285{
281 char *file = NULL;
282 unsigned int line = 0;
283 struct inline_node *node; 286 struct inline_node *node;
284 287
285 node = zalloc(sizeof(*node)); 288 node = zalloc(sizeof(*node));
@@ -291,7 +294,7 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
291 INIT_LIST_HEAD(&node->val); 294 INIT_LIST_HEAD(&node->val);
292 node->addr = addr; 295 node->addr = addr;
293 296
294 if (!addr2line(dso_name, addr, &file, &line, dso, TRUE, node)) 297 if (!addr2line(dso_name, addr, NULL, NULL, dso, TRUE, node))
295 goto out_free_inline_node; 298 goto out_free_inline_node;
296 299
297 if (list_empty(&node->val)) 300 if (list_empty(&node->val))
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index ac10cc675d39..719d6cb86952 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -44,6 +44,8 @@ static struct stats runtime_topdown_slots_issued[NUM_CTX][MAX_NR_CPUS];
44static struct stats runtime_topdown_slots_retired[NUM_CTX][MAX_NR_CPUS]; 44static struct stats runtime_topdown_slots_retired[NUM_CTX][MAX_NR_CPUS];
45static struct stats runtime_topdown_fetch_bubbles[NUM_CTX][MAX_NR_CPUS]; 45static struct stats runtime_topdown_fetch_bubbles[NUM_CTX][MAX_NR_CPUS];
46static struct stats runtime_topdown_recovery_bubbles[NUM_CTX][MAX_NR_CPUS]; 46static struct stats runtime_topdown_recovery_bubbles[NUM_CTX][MAX_NR_CPUS];
47static struct stats runtime_smi_num_stats[NUM_CTX][MAX_NR_CPUS];
48static struct stats runtime_aperf_stats[NUM_CTX][MAX_NR_CPUS];
47static struct rblist runtime_saved_values; 49static struct rblist runtime_saved_values;
48static bool have_frontend_stalled; 50static bool have_frontend_stalled;
49 51
@@ -157,6 +159,8 @@ void perf_stat__reset_shadow_stats(void)
157 memset(runtime_topdown_slots_issued, 0, sizeof(runtime_topdown_slots_issued)); 159 memset(runtime_topdown_slots_issued, 0, sizeof(runtime_topdown_slots_issued));
158 memset(runtime_topdown_fetch_bubbles, 0, sizeof(runtime_topdown_fetch_bubbles)); 160 memset(runtime_topdown_fetch_bubbles, 0, sizeof(runtime_topdown_fetch_bubbles));
159 memset(runtime_topdown_recovery_bubbles, 0, sizeof(runtime_topdown_recovery_bubbles)); 161 memset(runtime_topdown_recovery_bubbles, 0, sizeof(runtime_topdown_recovery_bubbles));
162 memset(runtime_smi_num_stats, 0, sizeof(runtime_smi_num_stats));
163 memset(runtime_aperf_stats, 0, sizeof(runtime_aperf_stats));
160 164
161 next = rb_first(&runtime_saved_values.entries); 165 next = rb_first(&runtime_saved_values.entries);
162 while (next) { 166 while (next) {
@@ -217,6 +221,10 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
217 update_stats(&runtime_dtlb_cache_stats[ctx][cpu], count[0]); 221 update_stats(&runtime_dtlb_cache_stats[ctx][cpu], count[0]);
218 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB)) 222 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
219 update_stats(&runtime_itlb_cache_stats[ctx][cpu], count[0]); 223 update_stats(&runtime_itlb_cache_stats[ctx][cpu], count[0]);
224 else if (perf_stat_evsel__is(counter, SMI_NUM))
225 update_stats(&runtime_smi_num_stats[ctx][cpu], count[0]);
226 else if (perf_stat_evsel__is(counter, APERF))
227 update_stats(&runtime_aperf_stats[ctx][cpu], count[0]);
220 228
221 if (counter->collect_stat) { 229 if (counter->collect_stat) {
222 struct saved_value *v = saved_value_lookup(counter, cpu, ctx, 230 struct saved_value *v = saved_value_lookup(counter, cpu, ctx,
@@ -592,6 +600,29 @@ static double td_be_bound(int ctx, int cpu)
592 return sanitize_val(1.0 - sum); 600 return sanitize_val(1.0 - sum);
593} 601}
594 602
603static void print_smi_cost(int cpu, struct perf_evsel *evsel,
604 struct perf_stat_output_ctx *out)
605{
606 double smi_num, aperf, cycles, cost = 0.0;
607 int ctx = evsel_context(evsel);
608 const char *color = NULL;
609
610 smi_num = avg_stats(&runtime_smi_num_stats[ctx][cpu]);
611 aperf = avg_stats(&runtime_aperf_stats[ctx][cpu]);
612 cycles = avg_stats(&runtime_cycles_stats[ctx][cpu]);
613
614 if ((cycles == 0) || (aperf == 0))
615 return;
616
617 if (smi_num)
618 cost = (aperf - cycles) / aperf * 100.00;
619
620 if (cost > 10)
621 color = PERF_COLOR_RED;
622 out->print_metric(out->ctx, color, "%8.1f%%", "SMI cycles%", cost);
623 out->print_metric(out->ctx, NULL, "%4.0f", "SMI#", smi_num);
624}
625
595void perf_stat__print_shadow_stats(struct perf_evsel *evsel, 626void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
596 double avg, int cpu, 627 double avg, int cpu,
597 struct perf_stat_output_ctx *out) 628 struct perf_stat_output_ctx *out)
@@ -825,6 +856,8 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
825 } 856 }
826 snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit); 857 snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
827 print_metric(ctxp, NULL, "%8.3f", unit_buf, ratio); 858 print_metric(ctxp, NULL, "%8.3f", unit_buf, ratio);
859 } else if (perf_stat_evsel__is(evsel, SMI_NUM)) {
860 print_smi_cost(cpu, evsel, out);
828 } else { 861 } else {
829 print_metric(ctxp, NULL, NULL, NULL, 0); 862 print_metric(ctxp, NULL, NULL, NULL, 0);
830 } 863 }
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index c58174443dc1..53b9a994a3dc 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -86,6 +86,8 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
86 ID(TOPDOWN_SLOTS_RETIRED, topdown-slots-retired), 86 ID(TOPDOWN_SLOTS_RETIRED, topdown-slots-retired),
87 ID(TOPDOWN_FETCH_BUBBLES, topdown-fetch-bubbles), 87 ID(TOPDOWN_FETCH_BUBBLES, topdown-fetch-bubbles),
88 ID(TOPDOWN_RECOVERY_BUBBLES, topdown-recovery-bubbles), 88 ID(TOPDOWN_RECOVERY_BUBBLES, topdown-recovery-bubbles),
89 ID(SMI_NUM, msr/smi/),
90 ID(APERF, msr/aperf/),
89}; 91};
90#undef ID 92#undef ID
91 93
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 0a65ae23f495..7522bf10b03e 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -22,6 +22,8 @@ enum perf_stat_evsel_id {
22 PERF_STAT_EVSEL_ID__TOPDOWN_SLOTS_RETIRED, 22 PERF_STAT_EVSEL_ID__TOPDOWN_SLOTS_RETIRED,
23 PERF_STAT_EVSEL_ID__TOPDOWN_FETCH_BUBBLES, 23 PERF_STAT_EVSEL_ID__TOPDOWN_FETCH_BUBBLES,
24 PERF_STAT_EVSEL_ID__TOPDOWN_RECOVERY_BUBBLES, 24 PERF_STAT_EVSEL_ID__TOPDOWN_RECOVERY_BUBBLES,
25 PERF_STAT_EVSEL_ID__SMI_NUM,
26 PERF_STAT_EVSEL_ID__APERF,
25 PERF_STAT_EVSEL_ID__MAX, 27 PERF_STAT_EVSEL_ID__MAX,
26}; 28};
27 29
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index 318424ea561d..802d743378af 100644
--- a/tools/perf/util/strbuf.h
+++ b/tools/perf/util/strbuf.h
@@ -42,6 +42,7 @@
42#include <stdarg.h> 42#include <stdarg.h>
43#include <stddef.h> 43#include <stddef.h>
44#include <string.h> 44#include <string.h>
45#include <linux/compiler.h>
45#include <sys/types.h> 46#include <sys/types.h>
46 47
47extern char strbuf_slopbuf[]; 48extern char strbuf_slopbuf[];
@@ -85,8 +86,7 @@ static inline int strbuf_addstr(struct strbuf *sb, const char *s) {
85 return strbuf_add(sb, s, strlen(s)); 86 return strbuf_add(sb, s, strlen(s));
86} 87}
87 88
88__attribute__((format(printf,2,3))) 89int strbuf_addf(struct strbuf *sb, const char *fmt, ...) __printf(2, 3);
89int strbuf_addf(struct strbuf *sb, const char *fmt, ...);
90 90
91/* XXX: if read fails, any partial read is undone */ 91/* XXX: if read fails, any partial read is undone */
92ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); 92ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index e7ee47f7377a..502505cf236a 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -637,43 +637,6 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)
637 return 0; 637 return 0;
638} 638}
639 639
640static int decompress_kmodule(struct dso *dso, const char *name,
641 enum dso_binary_type type)
642{
643 int fd = -1;
644 char tmpbuf[] = "/tmp/perf-kmod-XXXXXX";
645 struct kmod_path m;
646
647 if (type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP &&
648 type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP &&
649 type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
650 return -1;
651
652 if (type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
653 name = dso->long_name;
654
655 if (kmod_path__parse_ext(&m, name) || !m.comp)
656 return -1;
657
658 fd = mkstemp(tmpbuf);
659 if (fd < 0) {
660 dso->load_errno = errno;
661 goto out;
662 }
663
664 if (!decompress_to_file(m.ext, name, fd)) {
665 dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
666 close(fd);
667 fd = -1;
668 }
669
670 unlink(tmpbuf);
671
672out:
673 free(m.ext);
674 return fd;
675}
676
677bool symsrc__possibly_runtime(struct symsrc *ss) 640bool symsrc__possibly_runtime(struct symsrc *ss)
678{ 641{
679 return ss->dynsym || ss->opdsec; 642 return ss->dynsym || ss->opdsec;
@@ -705,9 +668,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
705 int fd; 668 int fd;
706 669
707 if (dso__needs_decompress(dso)) { 670 if (dso__needs_decompress(dso)) {
708 fd = decompress_kmodule(dso, name, type); 671 fd = dso__decompress_kmodule_fd(dso, name);
709 if (fd < 0) 672 if (fd < 0)
710 return -1; 673 return -1;
674
675 type = dso->symtab_type;
711 } else { 676 } else {
712 fd = open(name, O_RDONLY); 677 fd = open(name, O_RDONLY);
713 if (fd < 0) { 678 if (fd < 0) {
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 8f2b068ff756..e7a98dbd2aed 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1562,10 +1562,6 @@ int dso__load(struct dso *dso, struct map *map)
1562 if (!runtime_ss && syms_ss) 1562 if (!runtime_ss && syms_ss)
1563 runtime_ss = syms_ss; 1563 runtime_ss = syms_ss;
1564 1564
1565 if (syms_ss && syms_ss->type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
1566 if (dso__build_id_is_kmod(dso, name, PATH_MAX))
1567 kmod = true;
1568
1569 if (syms_ss) 1565 if (syms_ss)
1570 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, kmod); 1566 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, kmod);
1571 else 1567 else
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 746bbee645d9..e0a6e9a6a053 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -24,7 +24,7 @@
24#include <errno.h> 24#include <errno.h>
25 25
26#include "../perf.h" 26#include "../perf.h"
27#include "util.h" 27#include "debug.h"
28#include "trace-event.h" 28#include "trace-event.h"
29 29
30#include "sane_ctype.h" 30#include "sane_ctype.h"
@@ -150,7 +150,7 @@ void parse_ftrace_printk(struct pevent *pevent,
150 while (line) { 150 while (line) {
151 addr_str = strtok_r(line, ":", &fmt); 151 addr_str = strtok_r(line, ":", &fmt);
152 if (!addr_str) { 152 if (!addr_str) {
153 warning("printk format with empty entry"); 153 pr_warning("printk format with empty entry");
154 break; 154 break;
155 } 155 }
156 addr = strtoull(addr_str, NULL, 16); 156 addr = strtoull(addr_str, NULL, 16);
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index f90e11a555b2..7755a5e0fe5e 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -39,6 +39,14 @@ static int __report_module(struct addr_location *al, u64 ip,
39 return 0; 39 return 0;
40 40
41 mod = dwfl_addrmodule(ui->dwfl, ip); 41 mod = dwfl_addrmodule(ui->dwfl, ip);
42 if (mod) {
43 Dwarf_Addr s;
44
45 dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL);
46 if (s != al->map->start)
47 mod = 0;
48 }
49
42 if (!mod) 50 if (!mod)
43 mod = dwfl_report_elf(ui->dwfl, dso->short_name, 51 mod = dwfl_report_elf(ui->dwfl, dso->short_name,
44 dso->long_name, -1, al->map->start, 52 dso->long_name, -1, al->map->start,
@@ -168,12 +176,24 @@ frame_callback(Dwfl_Frame *state, void *arg)
168{ 176{
169 struct unwind_info *ui = arg; 177 struct unwind_info *ui = arg;
170 Dwarf_Addr pc; 178 Dwarf_Addr pc;
179 bool isactivation;
171 180
172 if (!dwfl_frame_pc(state, &pc, NULL)) { 181 if (!dwfl_frame_pc(state, &pc, NULL)) {
173 pr_err("%s", dwfl_errmsg(-1)); 182 pr_err("%s", dwfl_errmsg(-1));
174 return DWARF_CB_ABORT; 183 return DWARF_CB_ABORT;
175 } 184 }
176 185
186 // report the module before we query for isactivation
187 report_module(pc, ui);
188
189 if (!dwfl_frame_pc(state, &pc, &isactivation)) {
190 pr_err("%s", dwfl_errmsg(-1));
191 return DWARF_CB_ABORT;
192 }
193
194 if (!isactivation)
195 --pc;
196
177 return entry(pc, ui) || !(--ui->max_stack) ? 197 return entry(pc, ui) || !(--ui->max_stack) ?
178 DWARF_CB_ABORT : DWARF_CB_OK; 198 DWARF_CB_ABORT : DWARF_CB_OK;
179} 199}
@@ -220,7 +240,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
220 240
221 err = dwfl_getthread_frames(ui->dwfl, thread->tid, frame_callback, ui); 241 err = dwfl_getthread_frames(ui->dwfl, thread->tid, frame_callback, ui);
222 242
223 if (err && !ui->max_stack) 243 if (err && ui->max_stack != max_stack)
224 err = 0; 244 err = 0;
225 245
226 /* 246 /*
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index f8455bed6e65..672c2ada9357 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -692,6 +692,17 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
692 692
693 while (!ret && (unw_step(&c) > 0) && i < max_stack) { 693 while (!ret && (unw_step(&c) > 0) && i < max_stack) {
694 unw_get_reg(&c, UNW_REG_IP, &ips[i]); 694 unw_get_reg(&c, UNW_REG_IP, &ips[i]);
695
696 /*
697 * Decrement the IP for any non-activation frames.
698 * this is required to properly find the srcline
699 * for caller frames.
700 * See also the documentation for dwfl_frame_pc(),
701 * which this code tries to replicate.
702 */
703 if (unw_is_signal_frame(&c) <= 0)
704 --ips[i];
705
695 ++i; 706 ++i;
696 } 707 }
697 708
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c
index 996046a66fe5..6cc9d9888ce0 100644
--- a/tools/perf/util/usage.c
+++ b/tools/perf/util/usage.c
@@ -9,75 +9,17 @@
9#include "util.h" 9#include "util.h"
10#include "debug.h" 10#include "debug.h"
11 11
12static void report(const char *prefix, const char *err, va_list params) 12static __noreturn void usage_builtin(const char *err)
13{
14 char msg[1024];
15 vsnprintf(msg, sizeof(msg), err, params);
16 fprintf(stderr, " %s%s\n", prefix, msg);
17}
18
19static NORETURN void usage_builtin(const char *err)
20{ 13{
21 fprintf(stderr, "\n Usage: %s\n", err); 14 fprintf(stderr, "\n Usage: %s\n", err);
22 exit(129); 15 exit(129);
23} 16}
24 17
25static NORETURN void die_builtin(const char *err, va_list params)
26{
27 report(" Fatal: ", err, params);
28 exit(128);
29}
30
31static void error_builtin(const char *err, va_list params)
32{
33 report(" Error: ", err, params);
34}
35
36static void warn_builtin(const char *warn, va_list params)
37{
38 report(" Warning: ", warn, params);
39}
40
41/* If we are in a dlopen()ed .so write to a global variable would segfault 18/* If we are in a dlopen()ed .so write to a global variable would segfault
42 * (ugh), so keep things static. */ 19 * (ugh), so keep things static. */
43static void (*usage_routine)(const char *err) NORETURN = usage_builtin; 20static void (*usage_routine)(const char *err) __noreturn = usage_builtin;
44static void (*error_routine)(const char *err, va_list params) = error_builtin;
45static void (*warn_routine)(const char *err, va_list params) = warn_builtin;
46
47void set_warning_routine(void (*routine)(const char *err, va_list params))
48{
49 warn_routine = routine;
50}
51 21
52void usage(const char *err) 22void usage(const char *err)
53{ 23{
54 usage_routine(err); 24 usage_routine(err);
55} 25}
56
57void die(const char *err, ...)
58{
59 va_list params;
60
61 va_start(params, err);
62 die_builtin(err, params);
63 va_end(params);
64}
65
66int error(const char *err, ...)
67{
68 va_list params;
69
70 va_start(params, err);
71 error_routine(err, params);
72 va_end(params);
73 return -1;
74}
75
76void warning(const char *warn, ...)
77{
78 va_list params;
79
80 va_start(params, warn);
81 warn_routine(warn, params);
82 va_end(params);
83}
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 28c9f335006c..988111e0bab5 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -343,43 +343,6 @@ int perf_event_paranoid(void)
343 343
344 return value; 344 return value;
345} 345}
346
347bool find_process(const char *name)
348{
349 size_t len = strlen(name);
350 DIR *dir;
351 struct dirent *d;
352 int ret = -1;
353
354 dir = opendir(procfs__mountpoint());
355 if (!dir)
356 return false;
357
358 /* Walk through the directory. */
359 while (ret && (d = readdir(dir)) != NULL) {
360 char path[PATH_MAX];
361 char *data;
362 size_t size;
363
364 if ((d->d_type != DT_DIR) ||
365 !strcmp(".", d->d_name) ||
366 !strcmp("..", d->d_name))
367 continue;
368
369 scnprintf(path, sizeof(path), "%s/%s/comm",
370 procfs__mountpoint(), d->d_name);
371
372 if (filename__read_str(path, &data, &size))
373 continue;
374
375 ret = strncmp(name, data, len);
376 free(data);
377 }
378
379 closedir(dir);
380 return ret ? false : true;
381}
382
383static int 346static int
384fetch_ubuntu_kernel_version(unsigned int *puint) 347fetch_ubuntu_kernel_version(unsigned int *puint)
385{ 348{
@@ -387,8 +350,12 @@ fetch_ubuntu_kernel_version(unsigned int *puint)
387 size_t line_len = 0; 350 size_t line_len = 0;
388 char *ptr, *line = NULL; 351 char *ptr, *line = NULL;
389 int version, patchlevel, sublevel, err; 352 int version, patchlevel, sublevel, err;
390 FILE *vsig = fopen("/proc/version_signature", "r"); 353 FILE *vsig;
354
355 if (!puint)
356 return 0;
391 357
358 vsig = fopen("/proc/version_signature", "r");
392 if (!vsig) { 359 if (!vsig) {
393 pr_debug("Open /proc/version_signature failed: %s\n", 360 pr_debug("Open /proc/version_signature failed: %s\n",
394 strerror(errno)); 361 strerror(errno));
@@ -418,8 +385,7 @@ fetch_ubuntu_kernel_version(unsigned int *puint)
418 goto errout; 385 goto errout;
419 } 386 }
420 387
421 if (puint) 388 *puint = (version << 16) + (patchlevel << 8) + sublevel;
422 *puint = (version << 16) + (patchlevel << 8) + sublevel;
423 err = 0; 389 err = 0;
424errout: 390errout:
425 free(line); 391 free(line);
@@ -446,6 +412,9 @@ fetch_kernel_version(unsigned int *puint, char *str,
446 str[str_size - 1] = '\0'; 412 str[str_size - 1] = '\0';
447 } 413 }
448 414
415 if (!puint || int_ver_ready)
416 return 0;
417
449 err = sscanf(utsname.release, "%d.%d.%d", 418 err = sscanf(utsname.release, "%d.%d.%d",
450 &version, &patchlevel, &sublevel); 419 &version, &patchlevel, &sublevel);
451 420
@@ -455,8 +424,7 @@ fetch_kernel_version(unsigned int *puint, char *str,
455 return -1; 424 return -1;
456 } 425 }
457 426
458 if (puint && !int_ver_ready) 427 *puint = (version << 16) + (patchlevel << 8) + sublevel;
459 *puint = (version << 16) + (patchlevel << 8) + sublevel;
460 return 0; 428 return 0;
461} 429}
462 430
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 5dfb9bb6482d..2c9e58a45310 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -1,7 +1,6 @@
1#ifndef GIT_COMPAT_UTIL_H 1#ifndef GIT_COMPAT_UTIL_H
2#define GIT_COMPAT_UTIL_H 2#define GIT_COMPAT_UTIL_H
3 3
4#define _ALL_SOURCE 1
5#define _BSD_SOURCE 1 4#define _BSD_SOURCE 1
6/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */ 5/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
7#define _DEFAULT_SOURCE 1 6#define _DEFAULT_SOURCE 1
@@ -11,24 +10,12 @@
11#include <stddef.h> 10#include <stddef.h>
12#include <stdlib.h> 11#include <stdlib.h>
13#include <stdarg.h> 12#include <stdarg.h>
13#include <linux/compiler.h>
14#include <linux/types.h> 14#include <linux/types.h>
15 15
16#ifdef __GNUC__
17#define NORETURN __attribute__((__noreturn__))
18#else
19#define NORETURN
20#ifndef __attribute__
21#define __attribute__(x)
22#endif
23#endif
24
25/* General helper functions */ 16/* General helper functions */
26void usage(const char *err) NORETURN; 17void usage(const char *err) __noreturn;
27void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); 18void die(const char *err, ...) __noreturn __printf(1, 2);
28int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
29void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
30
31void set_warning_routine(void (*routine)(const char *err, va_list params));
32 19
33static inline void *zalloc(size_t size) 20static inline void *zalloc(size_t size)
34{ 21{
@@ -57,8 +44,6 @@ int hex2u64(const char *ptr, u64 *val);
57extern unsigned int page_size; 44extern unsigned int page_size;
58extern int cacheline_size; 45extern int cacheline_size;
59 46
60bool find_process(const char *name);
61
62int fetch_kernel_version(unsigned int *puint, 47int fetch_kernel_version(unsigned int *puint,
63 char *str, size_t str_sz); 48 char *str, size_t str_sz);
64#define KVER_VERSION(x) (((x) >> 16) & 0xff) 49#define KVER_VERSION(x) (((x) >> 16) & 0xff)
diff --git a/tools/power/acpi/.gitignore b/tools/power/acpi/.gitignore
new file mode 100644
index 000000000000..cba3d994995c
--- /dev/null
+++ b/tools/power/acpi/.gitignore
@@ -0,0 +1,4 @@
1acpidbg
2acpidump
3ec
4include
diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c
index c04e8fea2c60..025c1b07049d 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixxf.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c
@@ -750,9 +750,9 @@ acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 msec_timeout)
750{ 750{
751 acpi_status status = AE_OK; 751 acpi_status status = AE_OK;
752 sem_t *sem = (sem_t *) handle; 752 sem_t *sem = (sem_t *) handle;
753 int ret_val;
753#ifndef ACPI_USE_ALTERNATE_TIMEOUT 754#ifndef ACPI_USE_ALTERNATE_TIMEOUT
754 struct timespec time; 755 struct timespec time;
755 int ret_val;
756#endif 756#endif
757 757
758 if (!sem) { 758 if (!sem) {
@@ -778,7 +778,10 @@ acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 msec_timeout)
778 778
779 case ACPI_WAIT_FOREVER: 779 case ACPI_WAIT_FOREVER:
780 780
781 if (sem_wait(sem)) { 781 while (((ret_val = sem_wait(sem)) == -1) && (errno == EINTR)) {
782 continue; /* Restart if interrupted */
783 }
784 if (ret_val != 0) {
782 status = (AE_TIME); 785 status = (AE_TIME);
783 } 786 }
784 break; 787 break;
@@ -831,7 +834,8 @@ acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 msec_timeout)
831 834
832 while (((ret_val = sem_timedwait(sem, &time)) == -1) 835 while (((ret_val = sem_timedwait(sem, &time)) == -1)
833 && (errno == EINTR)) { 836 && (errno == EINTR)) {
834 continue; 837 continue; /* Restart if interrupted */
838
835 } 839 }
836 840
837 if (ret_val != 0) { 841 if (ret_val != 0) {
diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c
index 6437ef39aeea..5fd5c5b8c7b8 100644
--- a/tools/power/cpupower/utils/helpers/amd.c
+++ b/tools/power/cpupower/utils/helpers/amd.c
@@ -26,6 +26,15 @@ union msr_pstate {
26 unsigned res3:21; 26 unsigned res3:21;
27 unsigned en:1; 27 unsigned en:1;
28 } bits; 28 } bits;
29 struct {
30 unsigned fid:8;
31 unsigned did:6;
32 unsigned vid:8;
33 unsigned iddval:8;
34 unsigned idddiv:2;
35 unsigned res1:30;
36 unsigned en:1;
37 } fam17h_bits;
29 unsigned long long val; 38 unsigned long long val;
30}; 39};
31 40
@@ -35,6 +44,8 @@ static int get_did(int family, union msr_pstate pstate)
35 44
36 if (family == 0x12) 45 if (family == 0x12)
37 t = pstate.val & 0xf; 46 t = pstate.val & 0xf;
47 else if (family == 0x17)
48 t = pstate.fam17h_bits.did;
38 else 49 else
39 t = pstate.bits.did; 50 t = pstate.bits.did;
40 51
@@ -44,16 +55,20 @@ static int get_did(int family, union msr_pstate pstate)
44static int get_cof(int family, union msr_pstate pstate) 55static int get_cof(int family, union msr_pstate pstate)
45{ 56{
46 int t; 57 int t;
47 int fid, did; 58 int fid, did, cof;
48 59
49 did = get_did(family, pstate); 60 did = get_did(family, pstate);
50 61 if (family == 0x17) {
51 t = 0x10; 62 fid = pstate.fam17h_bits.fid;
52 fid = pstate.bits.fid; 63 cof = 200 * fid / did;
53 if (family == 0x11) 64 } else {
54 t = 0x8; 65 t = 0x10;
55 66 fid = pstate.bits.fid;
56 return (100 * (fid + t)) >> did; 67 if (family == 0x11)
68 t = 0x8;
69 cof = (100 * (fid + t)) >> did;
70 }
71 return cof;
57} 72}
58 73
59/* Needs: 74/* Needs:
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index afb66f80554e..799a18be60aa 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -70,6 +70,8 @@ enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
70#define CPUPOWER_CAP_IS_SNB 0x00000020 70#define CPUPOWER_CAP_IS_SNB 0x00000020
71#define CPUPOWER_CAP_INTEL_IDA 0x00000040 71#define CPUPOWER_CAP_INTEL_IDA 0x00000040
72 72
73#define CPUPOWER_AMD_CPBDIS 0x02000000
74
73#define MAX_HW_PSTATES 10 75#define MAX_HW_PSTATES 10
74 76
75struct cpupower_cpu_info { 77struct cpupower_cpu_info {
diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
index 1609243f5c64..601d719d4e60 100644
--- a/tools/power/cpupower/utils/helpers/misc.c
+++ b/tools/power/cpupower/utils/helpers/misc.c
@@ -2,11 +2,14 @@
2 2
3#include "helpers/helpers.h" 3#include "helpers/helpers.h"
4 4
5#define MSR_AMD_HWCR 0xc0010015
6
5int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active, 7int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
6 int *states) 8 int *states)
7{ 9{
8 struct cpupower_cpu_info cpu_info; 10 struct cpupower_cpu_info cpu_info;
9 int ret; 11 int ret;
12 unsigned long long val;
10 13
11 *support = *active = *states = 0; 14 *support = *active = *states = 0;
12 15
@@ -16,10 +19,22 @@ int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
16 19
17 if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CBP) { 20 if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CBP) {
18 *support = 1; 21 *support = 1;
19 amd_pci_get_num_boost_states(active, states); 22
20 if (ret <= 0) 23 /* AMD Family 0x17 does not utilize PCI D18F4 like prior
21 return ret; 24 * families and has no fixed discrete boost states but
22 *support = 1; 25 * has Hardware determined variable increments instead.
26 */
27
28 if (cpu_info.family == 0x17) {
29 if (!read_msr(cpu, MSR_AMD_HWCR, &val)) {
30 if (!(val & CPUPOWER_AMD_CPBDIS))
31 *active = 1;
32 }
33 } else {
34 ret = amd_pci_get_num_boost_states(active, states);
35 if (ret)
36 return ret;
37 }
23 } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA) 38 } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA)
24 *support = *active = 1; 39 *support = *active = 1;
25 return 0; 40 return 0;
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index b11294730771..0dafba2c1e7d 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -57,7 +57,6 @@ unsigned int list_header_only;
57unsigned int dump_only; 57unsigned int dump_only;
58unsigned int do_snb_cstates; 58unsigned int do_snb_cstates;
59unsigned int do_knl_cstates; 59unsigned int do_knl_cstates;
60unsigned int do_skl_residency;
61unsigned int do_slm_cstates; 60unsigned int do_slm_cstates;
62unsigned int use_c1_residency_msr; 61unsigned int use_c1_residency_msr;
63unsigned int has_aperf; 62unsigned int has_aperf;
@@ -93,6 +92,7 @@ unsigned int do_ring_perf_limit_reasons;
93unsigned int crystal_hz; 92unsigned int crystal_hz;
94unsigned long long tsc_hz; 93unsigned long long tsc_hz;
95int base_cpu; 94int base_cpu;
95int do_migrate;
96double discover_bclk(unsigned int family, unsigned int model); 96double discover_bclk(unsigned int family, unsigned int model);
97unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */ 97unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
98 /* IA32_HWP_REQUEST, IA32_HWP_STATUS */ 98 /* IA32_HWP_REQUEST, IA32_HWP_STATUS */
@@ -151,6 +151,8 @@ size_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size;
151#define MAX_ADDED_COUNTERS 16 151#define MAX_ADDED_COUNTERS 16
152 152
153struct thread_data { 153struct thread_data {
154 struct timeval tv_begin;
155 struct timeval tv_end;
154 unsigned long long tsc; 156 unsigned long long tsc;
155 unsigned long long aperf; 157 unsigned long long aperf;
156 unsigned long long mperf; 158 unsigned long long mperf;
@@ -301,6 +303,9 @@ int for_all_cpus(int (func)(struct thread_data *, struct core_data *, struct pkg
301 303
302int cpu_migrate(int cpu) 304int cpu_migrate(int cpu)
303{ 305{
306 if (!do_migrate)
307 return 0;
308
304 CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); 309 CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);
305 CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set); 310 CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set);
306 if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1) 311 if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1)
@@ -384,8 +389,14 @@ struct msr_counter bic[] = {
384 { 0x0, "CPU" }, 389 { 0x0, "CPU" },
385 { 0x0, "Mod%c6" }, 390 { 0x0, "Mod%c6" },
386 { 0x0, "sysfs" }, 391 { 0x0, "sysfs" },
392 { 0x0, "Totl%C0" },
393 { 0x0, "Any%C0" },
394 { 0x0, "GFX%C0" },
395 { 0x0, "CPUGFX%" },
387}; 396};
388 397
398
399
389#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter)) 400#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
390#define BIC_Package (1ULL << 0) 401#define BIC_Package (1ULL << 0)
391#define BIC_Avg_MHz (1ULL << 1) 402#define BIC_Avg_MHz (1ULL << 1)
@@ -426,6 +437,10 @@ struct msr_counter bic[] = {
426#define BIC_CPU (1ULL << 36) 437#define BIC_CPU (1ULL << 36)
427#define BIC_Mod_c6 (1ULL << 37) 438#define BIC_Mod_c6 (1ULL << 37)
428#define BIC_sysfs (1ULL << 38) 439#define BIC_sysfs (1ULL << 38)
440#define BIC_Totl_c0 (1ULL << 39)
441#define BIC_Any_c0 (1ULL << 40)
442#define BIC_GFX_c0 (1ULL << 41)
443#define BIC_CPUGFX (1ULL << 42)
429 444
430unsigned long long bic_enabled = 0xFFFFFFFFFFFFFFFFULL; 445unsigned long long bic_enabled = 0xFFFFFFFFFFFFFFFFULL;
431unsigned long long bic_present = BIC_sysfs; 446unsigned long long bic_present = BIC_sysfs;
@@ -521,6 +536,8 @@ void print_header(char *delim)
521 struct msr_counter *mp; 536 struct msr_counter *mp;
522 int printed = 0; 537 int printed = 0;
523 538
539 if (debug)
540 outp += sprintf(outp, "usec %s", delim);
524 if (DO_BIC(BIC_Package)) 541 if (DO_BIC(BIC_Package))
525 outp += sprintf(outp, "%sPackage", (printed++ ? delim : "")); 542 outp += sprintf(outp, "%sPackage", (printed++ ? delim : ""));
526 if (DO_BIC(BIC_Core)) 543 if (DO_BIC(BIC_Core))
@@ -599,12 +616,14 @@ void print_header(char *delim)
599 if (DO_BIC(BIC_GFXMHz)) 616 if (DO_BIC(BIC_GFXMHz))
600 outp += sprintf(outp, "%sGFXMHz", (printed++ ? delim : "")); 617 outp += sprintf(outp, "%sGFXMHz", (printed++ ? delim : ""));
601 618
602 if (do_skl_residency) { 619 if (DO_BIC(BIC_Totl_c0))
603 outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : "")); 620 outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : ""));
621 if (DO_BIC(BIC_Any_c0))
604 outp += sprintf(outp, "%sAny%%C0", (printed++ ? delim : "")); 622 outp += sprintf(outp, "%sAny%%C0", (printed++ ? delim : ""));
623 if (DO_BIC(BIC_GFX_c0))
605 outp += sprintf(outp, "%sGFX%%C0", (printed++ ? delim : "")); 624 outp += sprintf(outp, "%sGFX%%C0", (printed++ ? delim : ""));
625 if (DO_BIC(BIC_CPUGFX))
606 outp += sprintf(outp, "%sCPUGFX%%", (printed++ ? delim : "")); 626 outp += sprintf(outp, "%sCPUGFX%%", (printed++ ? delim : ""));
607 }
608 627
609 if (DO_BIC(BIC_Pkgpc2)) 628 if (DO_BIC(BIC_Pkgpc2))
610 outp += sprintf(outp, "%sPkg%%pc2", (printed++ ? delim : "")); 629 outp += sprintf(outp, "%sPkg%%pc2", (printed++ ? delim : ""));
@@ -771,6 +790,14 @@ int format_counters(struct thread_data *t, struct core_data *c,
771 (cpu_subset && !CPU_ISSET_S(t->cpu_id, cpu_subset_size, cpu_subset))) 790 (cpu_subset && !CPU_ISSET_S(t->cpu_id, cpu_subset_size, cpu_subset)))
772 return 0; 791 return 0;
773 792
793 if (debug) {
794 /* on each row, print how many usec each timestamp took to gather */
795 struct timeval tv;
796
797 timersub(&t->tv_end, &t->tv_begin, &tv);
798 outp += sprintf(outp, "%5ld\t", tv.tv_sec * 1000000 + tv.tv_usec);
799 }
800
774 interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0; 801 interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0;
775 802
776 tsc = t->tsc * tsc_tweak; 803 tsc = t->tsc * tsc_tweak;
@@ -912,12 +939,14 @@ int format_counters(struct thread_data *t, struct core_data *c,
912 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_mhz); 939 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_mhz);
913 940
914 /* Totl%C0, Any%C0 GFX%C0 CPUGFX% */ 941 /* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
915 if (do_skl_residency) { 942 if (DO_BIC(BIC_Totl_c0))
916 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_wtd_core_c0/tsc); 943 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_wtd_core_c0/tsc);
944 if (DO_BIC(BIC_Any_c0))
917 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_core_c0/tsc); 945 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_core_c0/tsc);
946 if (DO_BIC(BIC_GFX_c0))
918 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_gfxe_c0/tsc); 947 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_gfxe_c0/tsc);
948 if (DO_BIC(BIC_CPUGFX))
919 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_both_core_gfxe_c0/tsc); 949 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_both_core_gfxe_c0/tsc);
920 }
921 950
922 if (DO_BIC(BIC_Pkgpc2)) 951 if (DO_BIC(BIC_Pkgpc2))
923 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc2/tsc); 952 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc2/tsc);
@@ -1038,12 +1067,16 @@ delta_package(struct pkg_data *new, struct pkg_data *old)
1038 int i; 1067 int i;
1039 struct msr_counter *mp; 1068 struct msr_counter *mp;
1040 1069
1041 if (do_skl_residency) { 1070
1071 if (DO_BIC(BIC_Totl_c0))
1042 old->pkg_wtd_core_c0 = new->pkg_wtd_core_c0 - old->pkg_wtd_core_c0; 1072 old->pkg_wtd_core_c0 = new->pkg_wtd_core_c0 - old->pkg_wtd_core_c0;
1073 if (DO_BIC(BIC_Any_c0))
1043 old->pkg_any_core_c0 = new->pkg_any_core_c0 - old->pkg_any_core_c0; 1074 old->pkg_any_core_c0 = new->pkg_any_core_c0 - old->pkg_any_core_c0;
1075 if (DO_BIC(BIC_GFX_c0))
1044 old->pkg_any_gfxe_c0 = new->pkg_any_gfxe_c0 - old->pkg_any_gfxe_c0; 1076 old->pkg_any_gfxe_c0 = new->pkg_any_gfxe_c0 - old->pkg_any_gfxe_c0;
1077 if (DO_BIC(BIC_CPUGFX))
1045 old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0; 1078 old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0;
1046 } 1079
1047 old->pc2 = new->pc2 - old->pc2; 1080 old->pc2 = new->pc2 - old->pc2;
1048 if (DO_BIC(BIC_Pkgpc3)) 1081 if (DO_BIC(BIC_Pkgpc3))
1049 old->pc3 = new->pc3 - old->pc3; 1082 old->pc3 = new->pc3 - old->pc3;
@@ -1292,12 +1325,14 @@ int sum_counters(struct thread_data *t, struct core_data *c,
1292 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 1325 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
1293 return 0; 1326 return 0;
1294 1327
1295 if (do_skl_residency) { 1328 if (DO_BIC(BIC_Totl_c0))
1296 average.packages.pkg_wtd_core_c0 += p->pkg_wtd_core_c0; 1329 average.packages.pkg_wtd_core_c0 += p->pkg_wtd_core_c0;
1330 if (DO_BIC(BIC_Any_c0))
1297 average.packages.pkg_any_core_c0 += p->pkg_any_core_c0; 1331 average.packages.pkg_any_core_c0 += p->pkg_any_core_c0;
1332 if (DO_BIC(BIC_GFX_c0))
1298 average.packages.pkg_any_gfxe_c0 += p->pkg_any_gfxe_c0; 1333 average.packages.pkg_any_gfxe_c0 += p->pkg_any_gfxe_c0;
1334 if (DO_BIC(BIC_CPUGFX))
1299 average.packages.pkg_both_core_gfxe_c0 += p->pkg_both_core_gfxe_c0; 1335 average.packages.pkg_both_core_gfxe_c0 += p->pkg_both_core_gfxe_c0;
1300 }
1301 1336
1302 average.packages.pc2 += p->pc2; 1337 average.packages.pc2 += p->pc2;
1303 if (DO_BIC(BIC_Pkgpc3)) 1338 if (DO_BIC(BIC_Pkgpc3))
@@ -1357,12 +1392,14 @@ void compute_average(struct thread_data *t, struct core_data *c,
1357 average.cores.c7 /= topo.num_cores; 1392 average.cores.c7 /= topo.num_cores;
1358 average.cores.mc6_us /= topo.num_cores; 1393 average.cores.mc6_us /= topo.num_cores;
1359 1394
1360 if (do_skl_residency) { 1395 if (DO_BIC(BIC_Totl_c0))
1361 average.packages.pkg_wtd_core_c0 /= topo.num_packages; 1396 average.packages.pkg_wtd_core_c0 /= topo.num_packages;
1397 if (DO_BIC(BIC_Any_c0))
1362 average.packages.pkg_any_core_c0 /= topo.num_packages; 1398 average.packages.pkg_any_core_c0 /= topo.num_packages;
1399 if (DO_BIC(BIC_GFX_c0))
1363 average.packages.pkg_any_gfxe_c0 /= topo.num_packages; 1400 average.packages.pkg_any_gfxe_c0 /= topo.num_packages;
1401 if (DO_BIC(BIC_CPUGFX))
1364 average.packages.pkg_both_core_gfxe_c0 /= topo.num_packages; 1402 average.packages.pkg_both_core_gfxe_c0 /= topo.num_packages;
1365 }
1366 1403
1367 average.packages.pc2 /= topo.num_packages; 1404 average.packages.pc2 /= topo.num_packages;
1368 if (DO_BIC(BIC_Pkgpc3)) 1405 if (DO_BIC(BIC_Pkgpc3))
@@ -1482,6 +1519,9 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1482 struct msr_counter *mp; 1519 struct msr_counter *mp;
1483 int i; 1520 int i;
1484 1521
1522
1523 gettimeofday(&t->tv_begin, (struct timezone *)NULL);
1524
1485 if (cpu_migrate(cpu)) { 1525 if (cpu_migrate(cpu)) {
1486 fprintf(outf, "Could not migrate to CPU %d\n", cpu); 1526 fprintf(outf, "Could not migrate to CPU %d\n", cpu);
1487 return -1; 1527 return -1;
@@ -1565,7 +1605,7 @@ retry:
1565 1605
1566 /* collect core counters only for 1st thread in core */ 1606 /* collect core counters only for 1st thread in core */
1567 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 1607 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
1568 return 0; 1608 goto done;
1569 1609
1570 if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates) { 1610 if (DO_BIC(BIC_CPU_c3) && !do_slm_cstates && !do_knl_cstates) {
1571 if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3)) 1611 if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3))
@@ -1601,15 +1641,21 @@ retry:
1601 1641
1602 /* collect package counters only for 1st core in package */ 1642 /* collect package counters only for 1st core in package */
1603 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 1643 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
1604 return 0; 1644 goto done;
1605 1645
1606 if (do_skl_residency) { 1646 if (DO_BIC(BIC_Totl_c0)) {
1607 if (get_msr(cpu, MSR_PKG_WEIGHTED_CORE_C0_RES, &p->pkg_wtd_core_c0)) 1647 if (get_msr(cpu, MSR_PKG_WEIGHTED_CORE_C0_RES, &p->pkg_wtd_core_c0))
1608 return -10; 1648 return -10;
1649 }
1650 if (DO_BIC(BIC_Any_c0)) {
1609 if (get_msr(cpu, MSR_PKG_ANY_CORE_C0_RES, &p->pkg_any_core_c0)) 1651 if (get_msr(cpu, MSR_PKG_ANY_CORE_C0_RES, &p->pkg_any_core_c0))
1610 return -11; 1652 return -11;
1653 }
1654 if (DO_BIC(BIC_GFX_c0)) {
1611 if (get_msr(cpu, MSR_PKG_ANY_GFXE_C0_RES, &p->pkg_any_gfxe_c0)) 1655 if (get_msr(cpu, MSR_PKG_ANY_GFXE_C0_RES, &p->pkg_any_gfxe_c0))
1612 return -12; 1656 return -12;
1657 }
1658 if (DO_BIC(BIC_CPUGFX)) {
1613 if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0)) 1659 if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0))
1614 return -13; 1660 return -13;
1615 } 1661 }
@@ -1688,6 +1734,8 @@ retry:
1688 if (get_mp(cpu, mp, &p->counter[i])) 1734 if (get_mp(cpu, mp, &p->counter[i]))
1689 return -10; 1735 return -10;
1690 } 1736 }
1737done:
1738 gettimeofday(&t->tv_end, (struct timezone *)NULL);
1691 1739
1692 return 0; 1740 return 0;
1693} 1741}
@@ -3895,6 +3943,9 @@ void decode_misc_enable_msr(void)
3895{ 3943{
3896 unsigned long long msr; 3944 unsigned long long msr;
3897 3945
3946 if (!genuine_intel)
3947 return;
3948
3898 if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr)) 3949 if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr))
3899 fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%sTCC %sEIST %sMWAIT %sPREFETCH %sTURBO)\n", 3950 fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%sTCC %sEIST %sMWAIT %sPREFETCH %sTURBO)\n",
3900 base_cpu, msr, 3951 base_cpu, msr,
@@ -4198,7 +4249,12 @@ void process_cpuid()
4198 BIC_PRESENT(BIC_Pkgpc10); 4249 BIC_PRESENT(BIC_Pkgpc10);
4199 } 4250 }
4200 do_irtl_hsw = has_hsw_msrs(family, model); 4251 do_irtl_hsw = has_hsw_msrs(family, model);
4201 do_skl_residency = has_skl_msrs(family, model); 4252 if (has_skl_msrs(family, model)) {
4253 BIC_PRESENT(BIC_Totl_c0);
4254 BIC_PRESENT(BIC_Any_c0);
4255 BIC_PRESENT(BIC_GFX_c0);
4256 BIC_PRESENT(BIC_CPUGFX);
4257 }
4202 do_slm_cstates = is_slm(family, model); 4258 do_slm_cstates = is_slm(family, model);
4203 do_knl_cstates = is_knl(family, model); 4259 do_knl_cstates = is_knl(family, model);
4204 4260
@@ -4578,7 +4634,7 @@ int get_and_dump_counters(void)
4578} 4634}
4579 4635
4580void print_version() { 4636void print_version() {
4581 fprintf(outf, "turbostat version 17.04.12" 4637 fprintf(outf, "turbostat version 17.06.23"
4582 " - Len Brown <lenb@kernel.org>\n"); 4638 " - Len Brown <lenb@kernel.org>\n");
4583} 4639}
4584 4640
@@ -4951,6 +5007,7 @@ void cmdline(int argc, char **argv)
4951 {"hide", required_argument, 0, 'H'}, // meh, -h taken by --help 5007 {"hide", required_argument, 0, 'H'}, // meh, -h taken by --help
4952 {"Joules", no_argument, 0, 'J'}, 5008 {"Joules", no_argument, 0, 'J'},
4953 {"list", no_argument, 0, 'l'}, 5009 {"list", no_argument, 0, 'l'},
5010 {"migrate", no_argument, 0, 'm'},
4954 {"out", required_argument, 0, 'o'}, 5011 {"out", required_argument, 0, 'o'},
4955 {"quiet", no_argument, 0, 'q'}, 5012 {"quiet", no_argument, 0, 'q'},
4956 {"show", required_argument, 0, 's'}, 5013 {"show", required_argument, 0, 's'},
@@ -4962,7 +5019,7 @@ void cmdline(int argc, char **argv)
4962 5019
4963 progname = argv[0]; 5020 progname = argv[0];
4964 5021
4965 while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:o:qST:v", 5022 while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:Jmo:qST:v",
4966 long_options, &option_index)) != -1) { 5023 long_options, &option_index)) != -1) {
4967 switch (opt) { 5024 switch (opt) {
4968 case 'a': 5025 case 'a':
@@ -5005,6 +5062,9 @@ void cmdline(int argc, char **argv)
5005 list_header_only++; 5062 list_header_only++;
5006 quiet++; 5063 quiet++;
5007 break; 5064 break;
5065 case 'm':
5066 do_migrate = 1;
5067 break;
5008 case 'o': 5068 case 'o':
5009 outf = fopen_or_die(optarg, "w"); 5069 outf = fopen_or_die(optarg, "w");
5010 break; 5070 break;
diff --git a/tools/power/x86/x86_energy_perf_policy/Makefile b/tools/power/x86/x86_energy_perf_policy/Makefile
index 971c9ffdcb50..a711eec0c895 100644
--- a/tools/power/x86/x86_energy_perf_policy/Makefile
+++ b/tools/power/x86/x86_energy_perf_policy/Makefile
@@ -1,10 +1,27 @@
1DESTDIR ?= 1CC = $(CROSS_COMPILE)gcc
2BUILD_OUTPUT := $(CURDIR)
3PREFIX := /usr
4DESTDIR :=
5
6ifeq ("$(origin O)", "command line")
7 BUILD_OUTPUT := $(O)
8endif
2 9
3x86_energy_perf_policy : x86_energy_perf_policy.c 10x86_energy_perf_policy : x86_energy_perf_policy.c
11CFLAGS += -Wall
12CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
13
14%: %.c
15 @mkdir -p $(BUILD_OUTPUT)
16 $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@
4 17
18.PHONY : clean
5clean : 19clean :
6 rm -f x86_energy_perf_policy 20 @rm -f $(BUILD_OUTPUT)/x86_energy_perf_policy
21
22install : x86_energy_perf_policy
23 install -d $(DESTDIR)$(PREFIX)/bin
24 install $(BUILD_OUTPUT)/x86_energy_perf_policy $(DESTDIR)$(PREFIX)/bin/x86_energy_perf_policy
25 install -d $(DESTDIR)$(PREFIX)/share/man/man8
26 install x86_energy_perf_policy.8 $(DESTDIR)$(PREFIX)/share/man/man8
7 27
8install :
9 install x86_energy_perf_policy ${DESTDIR}/usr/bin/
10 install x86_energy_perf_policy.8 ${DESTDIR}/usr/share/man/man8/
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8 b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
index 8eaaad648cdb..17db1c3af4d0 100644
--- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
+++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
@@ -1,104 +1,213 @@
1.\" This page Copyright (C) 2010 Len Brown <len.brown@intel.com> 1.\" This page Copyright (C) 2010 - 2015 Len Brown <len.brown@intel.com>
2.\" Distributed under the GPL, Copyleft 1994. 2.\" Distributed under the GPL, Copyleft 1994.
3.TH X86_ENERGY_PERF_POLICY 8 3.TH X86_ENERGY_PERF_POLICY 8
4.SH NAME 4.SH NAME
5x86_energy_perf_policy \- read or write MSR_IA32_ENERGY_PERF_BIAS 5x86_energy_perf_policy \- Manage Energy vs. Performance Policy via x86 Model Specific Registers
6.SH SYNOPSIS 6.SH SYNOPSIS
7.ft B
8.B x86_energy_perf_policy 7.B x86_energy_perf_policy
9.RB [ "\-c cpu" ] 8.RB "[ options ] [ scope ] [field \ value]"
10.RB [ "\-v" ]
11.RB "\-r"
12.br 9.br
13.B x86_energy_perf_policy 10.RB "scope: \-\-cpu\ cpu-list | \-\-pkg\ pkg-list"
14.RB [ "\-c cpu" ]
15.RB [ "\-v" ]
16.RB 'performance'
17.br 11.br
18.B x86_energy_perf_policy 12.RB "cpu-list, pkg-list: # | #,# | #-# | all"
19.RB [ "\-c cpu" ]
20.RB [ "\-v" ]
21.RB 'normal'
22.br 13.br
23.B x86_energy_perf_policy 14.RB "field: \-\-all | \-\-epb | \-\-hwp-epp | \-\-hwp-min | \-\-hwp-max | \-\-hwp-desired"
24.RB [ "\-c cpu" ]
25.RB [ "\-v" ]
26.RB 'powersave'
27.br 15.br
28.B x86_energy_perf_policy 16.RB "other: (\-\-force | \-\-hwp-enable | \-\-turbo-enable) value)"
29.RB [ "\-c cpu" ]
30.RB [ "\-v" ]
31.RB n
32.br 17.br
18.RB "value: # | default | performance | balance-performance | balance-power | power"
33.SH DESCRIPTION 19.SH DESCRIPTION
34\fBx86_energy_perf_policy\fP 20\fBx86_energy_perf_policy\fP
35allows software to convey 21displays and updates energy-performance policy settings specific to
36its policy for the relative importance of performance 22Intel Architecture Processors. Settings are accessed via Model Specific Register (MSR)
37versus energy savings to the processor. 23updates, no matter if the Linux cpufreq sub-system is enabled or not.
38 24
39The processor uses this information in model-specific ways 25Policy in MSR_IA32_ENERGY_PERF_BIAS (EPB)
40when it must select trade-offs between performance and 26may affect a wide range of hardware decisions,
41energy efficiency. 27such as how aggressively the hardware enters and exits CPU idle states (C-states)
28and Processor Performance States (P-states).
29This policy hint does not replace explicit OS C-state and P-state selection.
30Rather, it tells the hardware how aggressively to implement those selections.
31Further, it allows the OS to influence energy/performance trade-offs where there
32is no software interface, such as in the opportunistic "turbo-mode" P-state range.
33Note that MSR_IA32_ENERGY_PERF_BIAS is defined per CPU,
34but some implementations
35share a single MSR among all CPUs in each processor package.
36On those systems, a write to EPB on one processor will
37be visible, and will have an effect, on all CPUs
38in the same processor package.
42 39
43This policy hint does not supersede Processor Performance states 40Hardware P-States (HWP) are effectively an expansion of hardware
44(P-states) or CPU Idle power states (C-states), but allows 41P-state control from the opportunistic turbo-mode P-state range
45software to have influence where it would otherwise be unable 42to include the entire range of available P-states.
46to express a preference. 43On Broadwell Xeon, the initial HWP implementation, EBP influenced HWP.
44That influence was removed in subsequent generations,
45where it was moved to the
46Energy_Performance_Preference (EPP) field in
47a pair of dedicated MSRs -- MSR_IA32_HWP_REQUEST and MSR_IA32_HWP_REQUEST_PKG.
47 48
48For example, this setting may tell the hardware how 49EPP is the most commonly managed knob in HWP mode,
49aggressively or conservatively to control frequency 50but MSR_IA32_HWP_REQUEST also allows the user to specify
50in the "turbo range" above the explicitly OS-controlled 51minimum-frequency for Quality-of-Service,
51P-state frequency range. It may also tell the hardware 52and maximum-frequency for power-capping.
52how aggressively is should enter the OS requested C-states. 53MSR_IA32_HWP_REQUEST is defined per-CPU.
53 54
54Support for this feature is indicated by CPUID.06H.ECX.bit3 55MSR_IA32_HWP_REQUEST_PKG has the same capability as MSR_IA32_HWP_REQUEST,
55per the Intel Architectures Software Developer's Manual. 56but it can simultaneously set the default policy for all CPUs within a package.
57A bit in per-CPU MSR_IA32_HWP_REQUEST indicates whether it is
58over-ruled-by or exempt-from MSR_IA32_HWP_REQUEST_PKG.
56 59
57.SS Options 60MSR_HWP_CAPABILITIES shows the default values for the fields
58\fB-c\fP limits operation to a single CPU. 61in MSR_IA32_HWP_REQUEST. It is displayed when no values
59The default is to operate on all CPUs. 62are being written.
60Note that MSR_IA32_ENERGY_PERF_BIAS is defined per 63
61logical processor, but that the initial implementations 64.SS SCOPE OPTIONS
62of the MSR were shared among all processors in each package.
63.PP
64\fB-v\fP increases verbosity. By default
65x86_energy_perf_policy is silent.
66.PP
67\fB-r\fP is for "read-only" mode - the unchanged state
68is read and displayed.
69.PP 65.PP
70.I performance 66\fB-c, --cpu\fP Operate on the MSR_IA32_HWP_REQUEST for each CPU in a CPU-list.
71Set a policy where performance is paramount. 67The CPU-list may be comma-separated CPU numbers, with dash for range
72The processor will be unwilling to sacrifice any performance 68or the string "all". Eg. '--cpu 1,4,6-8' or '--cpu all'.
73for the sake of energy saving. This is the hardware default. 69When --cpu is used, \fB--hwp-use-pkg\fP is available, which specifies whether the per-cpu
70MSR_IA32_HWP_REQUEST should be over-ruled by MSR_IA32_HWP_REQUEST_PKG (1),
71or exempt from MSR_IA32_HWP_REQUEST_PKG (0).
72
73\fB-p, --pkg\fP Operate on the MSR_IA32_HWP_REQUEST_PKG for each package in the package-list.
74The list is a string of individual package numbers separated
75by commas, and or ranges of package numbers separated by a dash,
76or the string "all".
77For example '--pkg 1,3' or '--pkg all'
78
79.SS VALUE OPTIONS
74.PP 80.PP
75.I normal 81.I normal | default
76Set a policy with a normal balance between performance and energy efficiency. 82Set a policy with a normal balance between performance and energy efficiency.
77The processor will tolerate minor performance compromise 83The processor will tolerate minor performance compromise
78for potentially significant energy savings. 84for potentially significant energy savings.
79This reasonable default for most desktops and servers. 85This is a reasonable default for most desktops and servers.
86"default" is a synonym for "normal".
80.PP 87.PP
81.I powersave 88.I performance
89Set a policy for maximum performance,
90accepting no performance sacrifice for the benefit of energy efficiency.
91.PP
92.I balance-performance
93Set a policy with a high priority on performance,
94but allowing some performance loss to benefit energy efficiency.
95.PP
96.I balance-power
97Set a policy where the performance and power are balanced.
98This is the default.
99.PP
100.I power
82Set a policy where the processor can accept 101Set a policy where the processor can accept
83a measurable performance hit to maximize energy efficiency. 102a measurable performance impact to maximize energy efficiency.
103
84.PP 104.PP
85.I n 105The following table shows the mapping from the value strings above to actual MSR values.
86Set MSR_IA32_ENERGY_PERF_BIAS to the specified number. 106This mapping is defined in the Linux-kernel header, msr-index.h.
87The range of valid numbers is 0-15, where 0 is maximum
88performance and 15 is maximum energy efficiency.
89 107
108.nf
109VALUE STRING EPB EPP
110performance 0 0
111balance-performance 4 128
112normal, default 6 128
113balance-power 8 192
114power 15 255
115.fi
116.PP
117For MSR_IA32_HWP_REQUEST performance fields
118(--hwp-min, --hwp-max, --hwp-desired), the value option
119is in units of 100 MHz, Eg. 12 signifies 1200 MHz.
120
121.SS FIELD OPTIONS
122\fB-a, --all value-string\fP Sets all EPB and EPP and HWP limit fields to the value associated with
123the value-string. In addition, enables turbo-mode and HWP-mode, if they were previous disabled.
124Thus "--all normal" will set a system without cpufreq into a well known configuration.
125.PP
126\fB-B, --epb\fP set EPB per-core or per-package.
127See value strings in the table above.
128.PP
129\fB-d, --debug\fP debug increases verbosity. By default
130x86_energy_perf_policy is silent for updates,
131and verbose for read-only mode.
132.PP
133\fB-P, --hwp-epp\fP set HWP.EPP per-core or per-package.
134See value strings in the table above.
135.PP
136\fB-m, --hwp-min\fP request HWP to not go below the specified core/bus ratio.
137The "default" is the value found in IA32_HWP_CAPABILITIES.min.
138.PP
139\fB-M, --hwp-max\fP request HWP not exceed a the specified core/bus ratio.
140The "default" is the value found in IA32_HWP_CAPABILITIES.max.
141.PP
142\fB-D, --hwp-desired\fP request HWP 'desired' frequency.
143The "normal" setting is 0, which
144corresponds to 'full autonomous' HWP control.
145Non-zero performance values request a specific performance
146level on this processor, specified in multiples of 100 MHz.
147.PP
148\fB-w, --hwp-window\fP specify integer number of microsec
149in the sliding window that HWP uses to maintain average frequency.
150This parameter is meaningful only when the "desired" field above is non-zero.
151Default is 0, allowing the HW to choose.
152.SH OTHER OPTIONS
153.PP
154\fB-f, --force\fP writes the specified values without bounds checking.
155.PP
156\fB-U, --hwp-use-pkg\fP (0 | 1), when used in conjunction with --cpu,
157indicates whether the per-CPU MSR_IA32_HWP_REQUEST should be overruled (1)
158or exempt (0) from per-Package MSR_IA32_HWP_REQUEST_PKG settings.
159The default is exempt.
160.PP
161\fB-H, --hwp-enable\fP enable HardWare-P-state (HWP) mode. Once enabled, system RESET is required to disable HWP mode.
162.PP
163\fB-t, --turbo-enable\fP enable (1) or disable (0) turbo mode.
164.PP
165\fB-v, --version\fP print version and exit.
166.PP
167If no request to change policy is made,
168the default behavior is to read
169and display the current system state,
170including the default capabilities.
171.SH WARNING
172.PP
173This utility writes directly to Model Specific Registers.
174There is no locking or coordination should this utility
175be used to modify HWP limit fields at the same time that
176intel_pstate's sysfs attributes access the same MSRs.
177.PP
178Note that --hwp-desired and --hwp-window are considered experimental.
179Future versions of Linux reserve the right to access these
180fields internally -- potentially conflicting with user-space access.
181.SH EXAMPLE
182.nf
183# sudo x86_energy_perf_policy
184cpu0: EPB 6
185cpu0: HWP_REQ: min 6 max 35 des 0 epp 128 window 0x0 (0*10^0us) use_pkg 0
186cpu0: HWP_CAP: low 1 eff 8 guar 27 high 35
187cpu1: EPB 6
188cpu1: HWP_REQ: min 6 max 35 des 0 epp 128 window 0x0 (0*10^0us) use_pkg 0
189cpu1: HWP_CAP: low 1 eff 8 guar 27 high 35
190cpu2: EPB 6
191cpu2: HWP_REQ: min 6 max 35 des 0 epp 128 window 0x0 (0*10^0us) use_pkg 0
192cpu2: HWP_CAP: low 1 eff 8 guar 27 high 35
193cpu3: EPB 6
194cpu3: HWP_REQ: min 6 max 35 des 0 epp 128 window 0x0 (0*10^0us) use_pkg 0
195cpu3: HWP_CAP: low 1 eff 8 guar 27 high 35
196.fi
90.SH NOTES 197.SH NOTES
91.B "x86_energy_perf_policy " 198.B "x86_energy_perf_policy"
92runs only as root. 199runs only as root.
93.SH FILES 200.SH FILES
94.ta 201.ta
95.nf 202.nf
96/dev/cpu/*/msr 203/dev/cpu/*/msr
97.fi 204.fi
98
99.SH "SEE ALSO" 205.SH "SEE ALSO"
206.nf
100msr(4) 207msr(4)
208Intel(R) 64 and IA-32 Architectures Software Developer's Manual
209.fi
101.PP 210.PP
102.SH AUTHORS 211.SH AUTHORS
103.nf 212.nf
104Written by Len Brown <len.brown@intel.com> 213Len Brown
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
index 40b3e5482f8a..65bbe627a425 100644
--- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
+++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
@@ -3,322 +3,1424 @@
3 * policy preference bias on recent X86 processors. 3 * policy preference bias on recent X86 processors.
4 */ 4 */
5/* 5/*
6 * Copyright (c) 2010, Intel Corporation. 6 * Copyright (c) 2010 - 2017 Intel Corporation.
7 * Len Brown <len.brown@intel.com> 7 * Len Brown <len.brown@intel.com>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify it 9 * This program is released under GPL v2
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 */ 10 */
22 11
12#define _GNU_SOURCE
13#include MSRHEADER
23#include <stdio.h> 14#include <stdio.h>
24#include <unistd.h> 15#include <unistd.h>
25#include <sys/types.h> 16#include <sys/types.h>
17#include <sched.h>
26#include <sys/stat.h> 18#include <sys/stat.h>
27#include <sys/resource.h> 19#include <sys/resource.h>
20#include <getopt.h>
21#include <err.h>
28#include <fcntl.h> 22#include <fcntl.h>
29#include <signal.h> 23#include <signal.h>
30#include <sys/time.h> 24#include <sys/time.h>
25#include <limits.h>
31#include <stdlib.h> 26#include <stdlib.h>
32#include <string.h> 27#include <string.h>
28#include <cpuid.h>
29#include <errno.h>
30
31#define OPTARG_NORMAL (INT_MAX - 1)
32#define OPTARG_POWER (INT_MAX - 2)
33#define OPTARG_BALANCE_POWER (INT_MAX - 3)
34#define OPTARG_BALANCE_PERFORMANCE (INT_MAX - 4)
35#define OPTARG_PERFORMANCE (INT_MAX - 5)
36
37struct msr_hwp_cap {
38 unsigned char highest;
39 unsigned char guaranteed;
40 unsigned char efficient;
41 unsigned char lowest;
42};
33 43
34unsigned int verbose; /* set with -v */ 44struct msr_hwp_request {
35unsigned int read_only; /* set with -r */ 45 unsigned char hwp_min;
46 unsigned char hwp_max;
47 unsigned char hwp_desired;
48 unsigned char hwp_epp;
49 unsigned int hwp_window;
50 unsigned char hwp_use_pkg;
51} req_update;
52
53unsigned int debug;
54unsigned int verbose;
55unsigned int force;
36char *progname; 56char *progname;
37unsigned long long new_bias; 57int base_cpu;
38int cpu = -1; 58unsigned char update_epb;
59unsigned long long new_epb;
60unsigned char turbo_is_enabled;
61unsigned char update_turbo;
62unsigned char turbo_update_value;
63unsigned char update_hwp_epp;
64unsigned char update_hwp_min;
65unsigned char update_hwp_max;
66unsigned char update_hwp_desired;
67unsigned char update_hwp_window;
68unsigned char update_hwp_use_pkg;
69unsigned char update_hwp_enable;
70#define hwp_update_enabled() (update_hwp_enable | update_hwp_epp | update_hwp_max | update_hwp_min | update_hwp_desired | update_hwp_window | update_hwp_use_pkg)
71int max_cpu_num;
72int max_pkg_num;
73#define MAX_PACKAGES 64
74unsigned int first_cpu_in_pkg[MAX_PACKAGES];
75unsigned long long pkg_present_set;
76unsigned long long pkg_selected_set;
77cpu_set_t *cpu_present_set;
78cpu_set_t *cpu_selected_set;
79int genuine_intel;
80
81size_t cpu_setsize;
82
83char *proc_stat = "/proc/stat";
84
85unsigned int has_epb; /* MSR_IA32_ENERGY_PERF_BIAS */
86unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
87 /* IA32_HWP_REQUEST, IA32_HWP_STATUS */
88unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */
89unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */
90unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */
91unsigned int has_hwp_request_pkg; /* IA32_HWP_REQUEST_PKG */
92
93unsigned int bdx_highest_ratio;
39 94
40/* 95/*
41 * Usage: 96 * maintain compatibility with original implementation, but don't document it:
42 *
43 * -c cpu: limit action to a single CPU (default is all CPUs)
44 * -v: verbose output (can invoke more than once)
45 * -r: read-only, don't change any settings
46 *
47 * performance
48 * Performance is paramount.
49 * Unwilling to sacrifice any performance
50 * for the sake of energy saving. (hardware default)
51 *
52 * normal
53 * Can tolerate minor performance compromise
54 * for potentially significant energy savings.
55 * (reasonable default for most desktops and servers)
56 *
57 * powersave
58 * Can tolerate significant performance hit
59 * to maximize energy savings.
60 *
61 * n
62 * a numerical value to write to the underlying MSR.
63 */ 97 */
64void usage(void) 98void usage(void)
65{ 99{
66 printf("%s: [-c cpu] [-v] " 100 fprintf(stderr, "%s [options] [scope][field value]\n", progname);
67 "(-r | 'performance' | 'normal' | 'powersave' | n)\n", 101 fprintf(stderr, "scope: --cpu cpu-list [--hwp-use-pkg #] | --pkg pkg-list\n");
68 progname); 102 fprintf(stderr, "field: --all | --epb | --hwp-epp | --hwp-min | --hwp-max | --hwp-desired\n");
103 fprintf(stderr, "other: --hwp-enable | --turbo-enable (0 | 1) | --help | --force\n");
104 fprintf(stderr,
105 "value: ( # | \"normal\" | \"performance\" | \"balance-performance\" | \"balance-power\"| \"power\")\n");
106 fprintf(stderr, "--hwp-window usec\n");
107
108 fprintf(stderr, "Specify only Energy Performance BIAS (legacy usage):\n");
109 fprintf(stderr, "%s: [-c cpu] [-v] (-r | policy-value )\n", progname);
110
69 exit(1); 111 exit(1);
70} 112}
71 113
72#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0 114/*
115 * If bdx_highest_ratio is set,
116 * then we must translate between MSR format and simple ratio
117 * used on the cmdline.
118 */
119int ratio_2_msr_perf(int ratio)
120{
121 int msr_perf;
122
123 if (!bdx_highest_ratio)
124 return ratio;
125
126 msr_perf = ratio * 255 / bdx_highest_ratio;
127
128 if (debug)
129 fprintf(stderr, "%d = ratio_to_msr_perf(%d)\n", msr_perf, ratio);
130
131 return msr_perf;
132}
133int msr_perf_2_ratio(int msr_perf)
134{
135 int ratio;
136 double d;
137
138 if (!bdx_highest_ratio)
139 return msr_perf;
140
141 d = (double)msr_perf * (double) bdx_highest_ratio / 255.0;
142 d = d + 0.5; /* round */
143 ratio = (int)d;
144
145 if (debug)
146 fprintf(stderr, "%d = msr_perf_ratio(%d) {%f}\n", ratio, msr_perf, d);
147
148 return ratio;
149}
150int parse_cmdline_epb(int i)
151{
152 if (!has_epb)
153 errx(1, "EPB not enabled on this platform");
154
155 update_epb = 1;
156
157 switch (i) {
158 case OPTARG_POWER:
159 return ENERGY_PERF_BIAS_POWERSAVE;
160 case OPTARG_BALANCE_POWER:
161 return ENERGY_PERF_BIAS_BALANCE_POWERSAVE;
162 case OPTARG_NORMAL:
163 return ENERGY_PERF_BIAS_NORMAL;
164 case OPTARG_BALANCE_PERFORMANCE:
165 return ENERGY_PERF_BIAS_BALANCE_PERFORMANCE;
166 case OPTARG_PERFORMANCE:
167 return ENERGY_PERF_BIAS_PERFORMANCE;
168 }
169 if (i < 0 || i > ENERGY_PERF_BIAS_POWERSAVE)
170 errx(1, "--epb must be from 0 to 15");
171 return i;
172}
173
174#define HWP_CAP_LOWEST 0
175#define HWP_CAP_HIGHEST 255
176
177/*
178 * "performance" changes hwp_min to cap.highest
179 * All others leave it at cap.lowest
180 */
181int parse_cmdline_hwp_min(int i)
182{
183 update_hwp_min = 1;
184
185 switch (i) {
186 case OPTARG_POWER:
187 case OPTARG_BALANCE_POWER:
188 case OPTARG_NORMAL:
189 case OPTARG_BALANCE_PERFORMANCE:
190 return HWP_CAP_LOWEST;
191 case OPTARG_PERFORMANCE:
192 return HWP_CAP_HIGHEST;
193 }
194 return i;
195}
196/*
197 * "power" changes hwp_max to cap.lowest
198 * All others leave it at cap.highest
199 */
200int parse_cmdline_hwp_max(int i)
201{
202 update_hwp_max = 1;
203
204 switch (i) {
205 case OPTARG_POWER:
206 return HWP_CAP_LOWEST;
207 case OPTARG_NORMAL:
208 case OPTARG_BALANCE_POWER:
209 case OPTARG_BALANCE_PERFORMANCE:
210 case OPTARG_PERFORMANCE:
211 return HWP_CAP_HIGHEST;
212 }
213 return i;
214}
215/*
216 * for --hwp-des, all strings leave it in autonomous mode
217 * If you want to change it, you need to explicitly pick a value
218 */
219int parse_cmdline_hwp_desired(int i)
220{
221 update_hwp_desired = 1;
222
223 switch (i) {
224 case OPTARG_POWER:
225 case OPTARG_BALANCE_POWER:
226 case OPTARG_BALANCE_PERFORMANCE:
227 case OPTARG_NORMAL:
228 case OPTARG_PERFORMANCE:
229 return 0; /* autonomous */
230 }
231 return i;
232}
233
234int parse_cmdline_hwp_window(int i)
235{
236 unsigned int exponent;
237
238 update_hwp_window = 1;
239
240 switch (i) {
241 case OPTARG_POWER:
242 case OPTARG_BALANCE_POWER:
243 case OPTARG_NORMAL:
244 case OPTARG_BALANCE_PERFORMANCE:
245 case OPTARG_PERFORMANCE:
246 return 0;
247 }
248 if (i < 0 || i > 1270000000) {
249 fprintf(stderr, "--hwp-window: 0 for auto; 1 - 1270000000 usec for window duration\n");
250 usage();
251 }
252 for (exponent = 0; ; ++exponent) {
253 if (debug)
254 printf("%d 10^%d\n", i, exponent);
255
256 if (i <= 127)
257 break;
258
259 i = i / 10;
260 }
261 if (debug)
262 fprintf(stderr, "%d*10^%d: 0x%x\n", i, exponent, (exponent << 7) | i);
263
264 return (exponent << 7) | i;
265}
266int parse_cmdline_hwp_epp(int i)
267{
268 update_hwp_epp = 1;
269
270 switch (i) {
271 case OPTARG_POWER:
272 return HWP_EPP_POWERSAVE;
273 case OPTARG_BALANCE_POWER:
274 return HWP_EPP_BALANCE_POWERSAVE;
275 case OPTARG_NORMAL:
276 case OPTARG_BALANCE_PERFORMANCE:
277 return HWP_EPP_BALANCE_PERFORMANCE;
278 case OPTARG_PERFORMANCE:
279 return HWP_EPP_PERFORMANCE;
280 }
281 if (i < 0 || i > 0xff) {
282 fprintf(stderr, "--hwp-epp must be from 0 to 0xff\n");
283 usage();
284 }
285 return i;
286}
287int parse_cmdline_turbo(int i)
288{
289 update_turbo = 1;
290
291 switch (i) {
292 case OPTARG_POWER:
293 return 0;
294 case OPTARG_NORMAL:
295 case OPTARG_BALANCE_POWER:
296 case OPTARG_BALANCE_PERFORMANCE:
297 case OPTARG_PERFORMANCE:
298 return 1;
299 }
300 if (i < 0 || i > 1) {
301 fprintf(stderr, "--turbo-enable: 1 to enable, 0 to disable\n");
302 usage();
303 }
304 return i;
305}
306
307int parse_optarg_string(char *s)
308{
309 int i;
310 char *endptr;
311
312 if (!strncmp(s, "default", 7))
313 return OPTARG_NORMAL;
314
315 if (!strncmp(s, "normal", 6))
316 return OPTARG_NORMAL;
317
318 if (!strncmp(s, "power", 9))
319 return OPTARG_POWER;
320
321 if (!strncmp(s, "balance-power", 17))
322 return OPTARG_BALANCE_POWER;
323
324 if (!strncmp(s, "balance-performance", 19))
325 return OPTARG_BALANCE_PERFORMANCE;
326
327 if (!strncmp(s, "performance", 11))
328 return OPTARG_PERFORMANCE;
329
330 i = strtol(s, &endptr, 0);
331 if (s == endptr) {
332 fprintf(stderr, "no digits in \"%s\"\n", s);
333 usage();
334 }
335 if (i == LONG_MIN || i == LONG_MAX)
336 errx(-1, "%s", s);
337
338 if (i > 0xFF)
339 errx(-1, "%d (0x%x) must be < 256", i, i);
340
341 if (i < 0)
342 errx(-1, "%d (0x%x) must be >= 0", i, i);
343 return i;
344}
345
346void parse_cmdline_all(char *s)
347{
348 force++;
349 update_hwp_enable = 1;
350 req_update.hwp_min = parse_cmdline_hwp_min(parse_optarg_string(s));
351 req_update.hwp_max = parse_cmdline_hwp_max(parse_optarg_string(s));
352 req_update.hwp_epp = parse_cmdline_hwp_epp(parse_optarg_string(s));
353 if (has_epb)
354 new_epb = parse_cmdline_epb(parse_optarg_string(s));
355 turbo_update_value = parse_cmdline_turbo(parse_optarg_string(s));
356 req_update.hwp_desired = parse_cmdline_hwp_desired(parse_optarg_string(s));
357 req_update.hwp_window = parse_cmdline_hwp_window(parse_optarg_string(s));
358}
359
360void validate_cpu_selected_set(void)
361{
362 int cpu;
363
364 if (CPU_COUNT_S(cpu_setsize, cpu_selected_set) == 0)
365 errx(0, "no CPUs requested");
366
367 for (cpu = 0; cpu <= max_cpu_num; ++cpu) {
368 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_selected_set))
369 if (!CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
370 errx(1, "Requested cpu% is not present", cpu);
371 }
372}
373
374void parse_cmdline_cpu(char *s)
375{
376 char *startp, *endp;
377 int cpu = 0;
378
379 if (pkg_selected_set) {
380 usage();
381 errx(1, "--cpu | --pkg");
382 }
383 cpu_selected_set = CPU_ALLOC((max_cpu_num + 1));
384 if (cpu_selected_set == NULL)
385 err(1, "cpu_selected_set");
386 CPU_ZERO_S(cpu_setsize, cpu_selected_set);
387
388 for (startp = s; startp && *startp;) {
389
390 if (*startp == ',') {
391 startp++;
392 continue;
393 }
394
395 if (*startp == '-') {
396 int end_cpu;
73 397
74#define BIAS_PERFORMANCE 0 398 startp++;
75#define BIAS_BALANCE 6 399 end_cpu = strtol(startp, &endp, 10);
76#define BIAS_POWERSAVE 15 400 if (startp == endp)
401 continue;
402
403 while (cpu <= end_cpu) {
404 if (cpu > max_cpu_num)
405 errx(1, "Requested cpu%d exceeds max cpu%d", cpu, max_cpu_num);
406 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
407 cpu++;
408 }
409 startp = endp;
410 continue;
411 }
412
413 if (strncmp(startp, "all", 3) == 0) {
414 for (cpu = 0; cpu <= max_cpu_num; cpu += 1) {
415 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
416 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
417 }
418 startp += 3;
419 if (*startp == 0)
420 break;
421 }
422 /* "--cpu even" is not documented */
423 if (strncmp(startp, "even", 4) == 0) {
424 for (cpu = 0; cpu <= max_cpu_num; cpu += 2) {
425 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
426 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
427 }
428 startp += 4;
429 if (*startp == 0)
430 break;
431 }
432
433 /* "--cpu odd" is not documented */
434 if (strncmp(startp, "odd", 3) == 0) {
435 for (cpu = 1; cpu <= max_cpu_num; cpu += 2) {
436 if (CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set))
437 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
438 }
439 startp += 3;
440 if (*startp == 0)
441 break;
442 }
443
444 cpu = strtol(startp, &endp, 10);
445 if (startp == endp)
446 errx(1, "--cpu cpu-set: confused by '%s'", startp);
447 if (cpu > max_cpu_num)
448 errx(1, "Requested cpu%d exceeds max cpu%d", cpu, max_cpu_num);
449 CPU_SET_S(cpu, cpu_setsize, cpu_selected_set);
450 startp = endp;
451 }
452
453 validate_cpu_selected_set();
454
455}
456
457void parse_cmdline_pkg(char *s)
458{
459 char *startp, *endp;
460 int pkg = 0;
461
462 if (cpu_selected_set) {
463 usage();
464 errx(1, "--pkg | --cpu");
465 }
466 pkg_selected_set = 0;
467
468 for (startp = s; startp && *startp;) {
469
470 if (*startp == ',') {
471 startp++;
472 continue;
473 }
474
475 if (*startp == '-') {
476 int end_pkg;
477
478 startp++;
479 end_pkg = strtol(startp, &endp, 10);
480 if (startp == endp)
481 continue;
482
483 while (pkg <= end_pkg) {
484 if (pkg > max_pkg_num)
485 errx(1, "Requested pkg%d exceeds max pkg%d", pkg, max_pkg_num);
486 pkg_selected_set |= 1 << pkg;
487 pkg++;
488 }
489 startp = endp;
490 continue;
491 }
492
493 if (strncmp(startp, "all", 3) == 0) {
494 pkg_selected_set = pkg_present_set;
495 return;
496 }
497
498 pkg = strtol(startp, &endp, 10);
499 if (pkg > max_pkg_num)
500 errx(1, "Requested pkg%d Exceeds max pkg%d", pkg, max_pkg_num);
501 pkg_selected_set |= 1 << pkg;
502 startp = endp;
503 }
504}
505
506void for_packages(unsigned long long pkg_set, int (func)(int))
507{
508 int pkg_num;
509
510 for (pkg_num = 0; pkg_num <= max_pkg_num; ++pkg_num) {
511 if (pkg_set & (1UL << pkg_num))
512 func(pkg_num);
513 }
514}
515
516void print_version(void)
517{
518 printf("x86_energy_perf_policy 17.05.11 (C) Len Brown <len.brown@intel.com>\n");
519}
77 520
78void cmdline(int argc, char **argv) 521void cmdline(int argc, char **argv)
79{ 522{
80 int opt; 523 int opt;
524 int option_index = 0;
525
526 static struct option long_options[] = {
527 {"all", required_argument, 0, 'a'},
528 {"cpu", required_argument, 0, 'c'},
529 {"pkg", required_argument, 0, 'p'},
530 {"debug", no_argument, 0, 'd'},
531 {"hwp-desired", required_argument, 0, 'D'},
532 {"epb", required_argument, 0, 'B'},
533 {"force", no_argument, 0, 'f'},
534 {"hwp-enable", no_argument, 0, 'e'},
535 {"help", no_argument, 0, 'h'},
536 {"hwp-epp", required_argument, 0, 'P'},
537 {"hwp-min", required_argument, 0, 'm'},
538 {"hwp-max", required_argument, 0, 'M'},
539 {"read", no_argument, 0, 'r'},
540 {"turbo-enable", required_argument, 0, 't'},
541 {"hwp-use-pkg", required_argument, 0, 'u'},
542 {"version", no_argument, 0, 'v'},
543 {"hwp-window", required_argument, 0, 'w'},
544 {0, 0, 0, 0 }
545 };
81 546
82 progname = argv[0]; 547 progname = argv[0];
83 548
84 while ((opt = getopt(argc, argv, "+rvc:")) != -1) { 549 while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw",
550 long_options, &option_index)) != -1) {
85 switch (opt) { 551 switch (opt) {
552 case 'a':
553 parse_cmdline_all(optarg);
554 break;
555 case 'B':
556 new_epb = parse_cmdline_epb(parse_optarg_string(optarg));
557 break;
86 case 'c': 558 case 'c':
87 cpu = atoi(optarg); 559 parse_cmdline_cpu(optarg);
560 break;
561 case 'e':
562 update_hwp_enable = 1;
563 break;
564 case 'h':
565 usage();
566 break;
567 case 'd':
568 debug++;
569 verbose++;
570 break;
571 case 'f':
572 force++;
573 break;
574 case 'D':
575 req_update.hwp_desired = parse_cmdline_hwp_desired(parse_optarg_string(optarg));
576 break;
577 case 'm':
578 req_update.hwp_min = parse_cmdline_hwp_min(parse_optarg_string(optarg));
579 break;
580 case 'M':
581 req_update.hwp_max = parse_cmdline_hwp_max(parse_optarg_string(optarg));
582 break;
583 case 'p':
584 parse_cmdline_pkg(optarg);
585 break;
586 case 'P':
587 req_update.hwp_epp = parse_cmdline_hwp_epp(parse_optarg_string(optarg));
88 break; 588 break;
89 case 'r': 589 case 'r':
90 read_only = 1; 590 /* v1 used -r to specify read-only mode, now the default */
591 break;
592 case 't':
593 turbo_update_value = parse_cmdline_turbo(parse_optarg_string(optarg));
594 break;
595 case 'u':
596 update_hwp_use_pkg++;
597 if (atoi(optarg) == 0)
598 req_update.hwp_use_pkg = 0;
599 else
600 req_update.hwp_use_pkg = 1;
91 break; 601 break;
92 case 'v': 602 case 'v':
93 verbose++; 603 print_version();
604 exit(0);
605 break;
606 case 'w':
607 req_update.hwp_window = parse_cmdline_hwp_window(parse_optarg_string(optarg));
94 break; 608 break;
95 default: 609 default:
96 usage(); 610 usage();
97 } 611 }
98 } 612 }
99 /* if -r, then should be no additional optind */
100 if (read_only && (argc > optind))
101 usage();
102
103 /* 613 /*
104 * if no -r , then must be one additional optind 614 * v1 allowed "performance"|"normal"|"power" with no policy specifier
615 * to update BIAS. Continue to support that, even though no longer documented.
105 */ 616 */
106 if (!read_only) { 617 if (argc == optind + 1)
618 new_epb = parse_cmdline_epb(parse_optarg_string(argv[optind]));
107 619
108 if (argc != optind + 1) { 620 if (argc > optind + 1) {
109 printf("must supply -r or policy param\n"); 621 fprintf(stderr, "stray parameter '%s'\n", argv[optind + 1]);
110 usage(); 622 usage();
111 } 623 }
624}
112 625
113 if (!strcmp("performance", argv[optind])) { 626
114 new_bias = BIAS_PERFORMANCE; 627int get_msr(int cpu, int offset, unsigned long long *msr)
115 } else if (!strcmp("normal", argv[optind])) { 628{
116 new_bias = BIAS_BALANCE; 629 int retval;
117 } else if (!strcmp("powersave", argv[optind])) { 630 char pathname[32];
118 new_bias = BIAS_POWERSAVE; 631 int fd;
119 } else { 632
120 char *endptr; 633 sprintf(pathname, "/dev/cpu/%d/msr", cpu);
121 634 fd = open(pathname, O_RDONLY);
122 new_bias = strtoull(argv[optind], &endptr, 0); 635 if (fd < 0)
123 if (endptr == argv[optind] || 636 err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
124 new_bias > BIAS_POWERSAVE) { 637
125 fprintf(stderr, "invalid value: %s\n", 638 retval = pread(fd, msr, sizeof(*msr), offset);
126 argv[optind]); 639 if (retval != sizeof(*msr))
127 usage(); 640 err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset);
128 } 641
129 } 642 if (debug > 1)
643 fprintf(stderr, "get_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, *msr);
644
645 close(fd);
646 return 0;
647}
648
649int put_msr(int cpu, int offset, unsigned long long new_msr)
650{
651 char pathname[32];
652 int retval;
653 int fd;
654
655 sprintf(pathname, "/dev/cpu/%d/msr", cpu);
656 fd = open(pathname, O_RDWR);
657 if (fd < 0)
658 err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
659
660 retval = pwrite(fd, &new_msr, sizeof(new_msr), offset);
661 if (retval != sizeof(new_msr))
662 err(-2, "pwrite(cpu%d, offset 0x%x, 0x%llx) = %d", cpu, offset, new_msr, retval);
663
664 close(fd);
665
666 if (debug > 1)
667 fprintf(stderr, "put_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, new_msr);
668
669 return 0;
670}
671
672void print_hwp_cap(int cpu, struct msr_hwp_cap *cap, char *str)
673{
674 if (cpu != -1)
675 printf("cpu%d: ", cpu);
676
677 printf("HWP_CAP: low %d eff %d guar %d high %d\n",
678 cap->lowest, cap->efficient, cap->guaranteed, cap->highest);
679}
680void read_hwp_cap(int cpu, struct msr_hwp_cap *cap, unsigned int msr_offset)
681{
682 unsigned long long msr;
683
684 get_msr(cpu, msr_offset, &msr);
685
686 cap->highest = msr_perf_2_ratio(HWP_HIGHEST_PERF(msr));
687 cap->guaranteed = msr_perf_2_ratio(HWP_GUARANTEED_PERF(msr));
688 cap->efficient = msr_perf_2_ratio(HWP_MOSTEFFICIENT_PERF(msr));
689 cap->lowest = msr_perf_2_ratio(HWP_LOWEST_PERF(msr));
690}
691
692void print_hwp_request(int cpu, struct msr_hwp_request *h, char *str)
693{
694 if (cpu != -1)
695 printf("cpu%d: ", cpu);
696
697 if (str)
698 printf("%s", str);
699
700 printf("HWP_REQ: min %d max %d des %d epp %d window 0x%x (%d*10^%dus) use_pkg %d\n",
701 h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp,
702 h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7, h->hwp_use_pkg);
703}
704void print_hwp_request_pkg(int pkg, struct msr_hwp_request *h, char *str)
705{
706 printf("pkg%d: ", pkg);
707
708 if (str)
709 printf("%s", str);
710
711 printf("HWP_REQ_PKG: min %d max %d des %d epp %d window 0x%x (%d*10^%dus)\n",
712 h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp,
713 h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7);
714}
715void read_hwp_request(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset)
716{
717 unsigned long long msr;
718
719 get_msr(cpu, msr_offset, &msr);
720
721 hwp_req->hwp_min = msr_perf_2_ratio((((msr) >> 0) & 0xff));
722 hwp_req->hwp_max = msr_perf_2_ratio((((msr) >> 8) & 0xff));
723 hwp_req->hwp_desired = msr_perf_2_ratio((((msr) >> 16) & 0xff));
724 hwp_req->hwp_epp = (((msr) >> 24) & 0xff);
725 hwp_req->hwp_window = (((msr) >> 32) & 0x3ff);
726 hwp_req->hwp_use_pkg = (((msr) >> 42) & 0x1);
727}
728
729void write_hwp_request(int cpu, struct msr_hwp_request *hwp_req, unsigned int msr_offset)
730{
731 unsigned long long msr = 0;
732
733 if (debug > 1)
734 printf("cpu%d: requesting min %d max %d des %d epp %d window 0x%0x use_pkg %d\n",
735 cpu, hwp_req->hwp_min, hwp_req->hwp_max,
736 hwp_req->hwp_desired, hwp_req->hwp_epp,
737 hwp_req->hwp_window, hwp_req->hwp_use_pkg);
738
739 msr |= HWP_MIN_PERF(ratio_2_msr_perf(hwp_req->hwp_min));
740 msr |= HWP_MAX_PERF(ratio_2_msr_perf(hwp_req->hwp_max));
741 msr |= HWP_DESIRED_PERF(ratio_2_msr_perf(hwp_req->hwp_desired));
742 msr |= HWP_ENERGY_PERF_PREFERENCE(hwp_req->hwp_epp);
743 msr |= HWP_ACTIVITY_WINDOW(hwp_req->hwp_window);
744 msr |= HWP_PACKAGE_CONTROL(hwp_req->hwp_use_pkg);
745
746 put_msr(cpu, msr_offset, msr);
747}
748
749int print_cpu_msrs(int cpu)
750{
751 unsigned long long msr;
752 struct msr_hwp_request req;
753 struct msr_hwp_cap cap;
754
755 if (has_epb) {
756 get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr);
757
758 printf("cpu%d: EPB %u\n", cpu, (unsigned int) msr);
130 } 759 }
760
761 if (!has_hwp)
762 return 0;
763
764 read_hwp_request(cpu, &req, MSR_HWP_REQUEST);
765 print_hwp_request(cpu, &req, "");
766
767 read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES);
768 print_hwp_cap(cpu, &cap, "");
769
770 return 0;
771}
772
773int print_pkg_msrs(int pkg)
774{
775 struct msr_hwp_request req;
776 unsigned long long msr;
777
778 if (!has_hwp)
779 return 0;
780
781 read_hwp_request(first_cpu_in_pkg[pkg], &req, MSR_HWP_REQUEST_PKG);
782 print_hwp_request_pkg(pkg, &req, "");
783
784 if (has_hwp_notify) {
785 get_msr(first_cpu_in_pkg[pkg], MSR_HWP_INTERRUPT, &msr);
786 fprintf(stderr,
787 "pkg%d: MSR_HWP_INTERRUPT: 0x%08llx (Excursion_Min-%sabled, Guaranteed_Perf_Change-%sabled)\n",
788 pkg, msr,
789 ((msr) & 0x2) ? "EN" : "Dis",
790 ((msr) & 0x1) ? "EN" : "Dis");
791 }
792 get_msr(first_cpu_in_pkg[pkg], MSR_HWP_STATUS, &msr);
793 fprintf(stderr,
794 "pkg%d: MSR_HWP_STATUS: 0x%08llx (%sExcursion_Min, %sGuaranteed_Perf_Change)\n",
795 pkg, msr,
796 ((msr) & 0x4) ? "" : "No-",
797 ((msr) & 0x1) ? "" : "No-");
798
799 return 0;
131} 800}
132 801
133/* 802/*
134 * validate_cpuid() 803 * Assumption: All HWP systems have 100 MHz bus clock
135 * returns on success, quietly exits on failure (make verbose with -v)
136 */ 804 */
137void validate_cpuid(void) 805int ratio_2_sysfs_khz(int ratio)
138{ 806{
139 unsigned int eax, ebx, ecx, edx, max_level; 807 int bclk_khz = 100 * 1000; /* 100,000 KHz = 100 MHz */
140 unsigned int fms, family, model, stepping;
141 808
142 eax = ebx = ecx = edx = 0; 809 return ratio * bclk_khz;
810}
811/*
812 * If HWP is enabled and cpufreq sysfs attribtes are present,
813 * then update sysfs, so that it will not become
814 * stale when we write to MSRs.
815 * (intel_pstate's max_perf_pct and min_perf_pct will follow cpufreq,
816 * so we don't have to touch that.)
817 */
818void update_cpufreq_scaling_freq(int is_max, int cpu, unsigned int ratio)
819{
820 char pathname[64];
821 FILE *fp;
822 int retval;
823 int khz;
143 824
144 asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), 825 sprintf(pathname, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_%s_freq",
145 "=d" (edx) : "a" (0)); 826 cpu, is_max ? "max" : "min");
146 827
147 if (ebx != 0x756e6547 || edx != 0x49656e69 || ecx != 0x6c65746e) { 828 fp = fopen(pathname, "w");
148 if (verbose) 829 if (!fp) {
149 fprintf(stderr, "%.4s%.4s%.4s != GenuineIntel", 830 if (debug)
150 (char *)&ebx, (char *)&edx, (char *)&ecx); 831 perror(pathname);
151 exit(1); 832 return;
152 } 833 }
153 834
154 asm("cpuid" : "=a" (fms), "=c" (ecx), "=d" (edx) : "a" (1) : "ebx"); 835 khz = ratio_2_sysfs_khz(ratio);
155 family = (fms >> 8) & 0xf; 836 retval = fprintf(fp, "%d", khz);
156 model = (fms >> 4) & 0xf; 837 if (retval < 0)
157 stepping = fms & 0xf; 838 if (debug)
158 if (family == 6 || family == 0xf) 839 perror("fprintf");
159 model += ((fms >> 16) & 0xf) << 4; 840 if (debug)
841 printf("echo %d > %s\n", khz, pathname);
160 842
161 if (verbose > 1) 843 fclose(fp);
162 printf("CPUID %d levels family:model:stepping " 844}
163 "0x%x:%x:%x (%d:%d:%d)\n", max_level,
164 family, model, stepping, family, model, stepping);
165 845
166 if (!(edx & (1 << 5))) { 846/*
167 if (verbose) 847 * We update all sysfs before updating any MSRs because of
168 printf("CPUID: no MSR\n"); 848 * bugs in cpufreq/intel_pstate where the sysfs writes
169 exit(1); 849 * for a CPU may change the min/max values on other CPUS.
850 */
851
852int update_sysfs(int cpu)
853{
854 if (!has_hwp)
855 return 0;
856
857 if (!hwp_update_enabled())
858 return 0;
859
860 if (access("/sys/devices/system/cpu/cpu0/cpufreq", F_OK))
861 return 0;
862
863 if (update_hwp_min)
864 update_cpufreq_scaling_freq(0, cpu, req_update.hwp_min);
865
866 if (update_hwp_max)
867 update_cpufreq_scaling_freq(1, cpu, req_update.hwp_max);
868
869 return 0;
870}
871
872int verify_hwp_req_self_consistency(int cpu, struct msr_hwp_request *req)
873{
874 /* fail if min > max requested */
875 if (req->hwp_min > req->hwp_max) {
876 errx(1, "cpu%d: requested hwp-min %d > hwp_max %d",
877 cpu, req->hwp_min, req->hwp_max);
170 } 878 }
171 879
172 /* 880 /* fail if desired > max requestd */
173 * Support for MSR_IA32_ENERGY_PERF_BIAS 881 if (req->hwp_desired && (req->hwp_desired > req->hwp_max)) {
174 * is indicated by CPUID.06H.ECX.bit3 882 errx(1, "cpu%d: requested hwp-desired %d > hwp_max %d",
175 */ 883 cpu, req->hwp_desired, req->hwp_max);
176 asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (6));
177 if (verbose)
178 printf("CPUID.06H.ECX: 0x%x\n", ecx);
179 if (!(ecx & (1 << 3))) {
180 if (verbose)
181 printf("CPUID: No MSR_IA32_ENERGY_PERF_BIAS\n");
182 exit(1);
183 } 884 }
184 return; /* success */ 885 /* fail if desired < min requestd */
886 if (req->hwp_desired && (req->hwp_desired < req->hwp_min)) {
887 errx(1, "cpu%d: requested hwp-desired %d < requested hwp_min %d",
888 cpu, req->hwp_desired, req->hwp_min);
889 }
890
891 return 0;
185} 892}
186 893
187unsigned long long get_msr(int cpu, int offset) 894int check_hwp_request_v_hwp_capabilities(int cpu, struct msr_hwp_request *req, struct msr_hwp_cap *cap)
188{ 895{
189 unsigned long long msr; 896 if (update_hwp_max) {
190 char msr_path[32]; 897 if (req->hwp_max > cap->highest)
191 int retval; 898 errx(1, "cpu%d: requested max %d > capabilities highest %d, use --force?",
192 int fd; 899 cpu, req->hwp_max, cap->highest);
900 if (req->hwp_max < cap->lowest)
901 errx(1, "cpu%d: requested max %d < capabilities lowest %d, use --force?",
902 cpu, req->hwp_max, cap->lowest);
903 }
193 904
194 sprintf(msr_path, "/dev/cpu/%d/msr", cpu); 905 if (update_hwp_min) {
195 fd = open(msr_path, O_RDONLY); 906 if (req->hwp_min > cap->highest)
196 if (fd < 0) { 907 errx(1, "cpu%d: requested min %d > capabilities highest %d, use --force?",
197 printf("Try \"# modprobe msr\"\n"); 908 cpu, req->hwp_min, cap->highest);
198 perror(msr_path); 909 if (req->hwp_min < cap->lowest)
199 exit(1); 910 errx(1, "cpu%d: requested min %d < capabilities lowest %d, use --force?",
911 cpu, req->hwp_min, cap->lowest);
200 } 912 }
201 913
202 retval = pread(fd, &msr, sizeof msr, offset); 914 if (update_hwp_min && update_hwp_max && (req->hwp_min > req->hwp_max))
915 errx(1, "cpu%d: requested min %d > requested max %d",
916 cpu, req->hwp_min, req->hwp_max);
203 917
204 if (retval != sizeof msr) { 918 if (update_hwp_desired && req->hwp_desired) {
205 printf("pread cpu%d 0x%x = %d\n", cpu, offset, retval); 919 if (req->hwp_desired > req->hwp_max)
206 exit(-2); 920 errx(1, "cpu%d: requested desired %d > requested max %d, use --force?",
921 cpu, req->hwp_desired, req->hwp_max);
922 if (req->hwp_desired < req->hwp_min)
923 errx(1, "cpu%d: requested desired %d < requested min %d, use --force?",
924 cpu, req->hwp_desired, req->hwp_min);
925 if (req->hwp_desired < cap->lowest)
926 errx(1, "cpu%d: requested desired %d < capabilities lowest %d, use --force?",
927 cpu, req->hwp_desired, cap->lowest);
928 if (req->hwp_desired > cap->highest)
929 errx(1, "cpu%d: requested desired %d > capabilities highest %d, use --force?",
930 cpu, req->hwp_desired, cap->highest);
207 } 931 }
208 close(fd); 932
209 return msr; 933 return 0;
210} 934}
211 935
212unsigned long long put_msr(int cpu, unsigned long long new_msr, int offset) 936int update_hwp_request(int cpu)
213{ 937{
214 unsigned long long old_msr; 938 struct msr_hwp_request req;
215 char msr_path[32]; 939 struct msr_hwp_cap cap;
216 int retval; 940
217 int fd; 941 int msr_offset = MSR_HWP_REQUEST;
942
943 read_hwp_request(cpu, &req, msr_offset);
944 if (debug)
945 print_hwp_request(cpu, &req, "old: ");
946
947 if (update_hwp_min)
948 req.hwp_min = req_update.hwp_min;
949
950 if (update_hwp_max)
951 req.hwp_max = req_update.hwp_max;
952
953 if (update_hwp_desired)
954 req.hwp_desired = req_update.hwp_desired;
955
956 if (update_hwp_window)
957 req.hwp_window = req_update.hwp_window;
958
959 if (update_hwp_epp)
960 req.hwp_epp = req_update.hwp_epp;
961
962 req.hwp_use_pkg = req_update.hwp_use_pkg;
963
964 read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES);
965 if (debug)
966 print_hwp_cap(cpu, &cap, "");
967
968 if (!force)
969 check_hwp_request_v_hwp_capabilities(cpu, &req, &cap);
970
971 verify_hwp_req_self_consistency(cpu, &req);
218 972
219 sprintf(msr_path, "/dev/cpu/%d/msr", cpu); 973 write_hwp_request(cpu, &req, msr_offset);
220 fd = open(msr_path, O_RDWR); 974
221 if (fd < 0) { 975 if (debug) {
222 perror(msr_path); 976 read_hwp_request(cpu, &req, msr_offset);
223 exit(1); 977 print_hwp_request(cpu, &req, "new: ");
224 } 978 }
979 return 0;
980}
981int update_hwp_request_pkg(int pkg)
982{
983 struct msr_hwp_request req;
984 struct msr_hwp_cap cap;
985 int cpu = first_cpu_in_pkg[pkg];
986
987 int msr_offset = MSR_HWP_REQUEST_PKG;
988
989 read_hwp_request(cpu, &req, msr_offset);
990 if (debug)
991 print_hwp_request_pkg(pkg, &req, "old: ");
992
993 if (update_hwp_min)
994 req.hwp_min = req_update.hwp_min;
995
996 if (update_hwp_max)
997 req.hwp_max = req_update.hwp_max;
998
999 if (update_hwp_desired)
1000 req.hwp_desired = req_update.hwp_desired;
1001
1002 if (update_hwp_window)
1003 req.hwp_window = req_update.hwp_window;
1004
1005 if (update_hwp_epp)
1006 req.hwp_epp = req_update.hwp_epp;
1007
1008 read_hwp_cap(cpu, &cap, MSR_HWP_CAPABILITIES);
1009 if (debug)
1010 print_hwp_cap(cpu, &cap, "");
1011
1012 if (!force)
1013 check_hwp_request_v_hwp_capabilities(cpu, &req, &cap);
1014
1015 verify_hwp_req_self_consistency(cpu, &req);
1016
1017 write_hwp_request(cpu, &req, msr_offset);
225 1018
226 retval = pread(fd, &old_msr, sizeof old_msr, offset); 1019 if (debug) {
227 if (retval != sizeof old_msr) { 1020 read_hwp_request(cpu, &req, msr_offset);
228 perror("pwrite"); 1021 print_hwp_request_pkg(pkg, &req, "new: ");
229 printf("pread cpu%d 0x%x = %d\n", cpu, offset, retval);
230 exit(-2);
231 } 1022 }
1023 return 0;
1024}
1025
1026int enable_hwp_on_cpu(int cpu)
1027{
1028 unsigned long long msr;
1029
1030 get_msr(cpu, MSR_PM_ENABLE, &msr);
1031 put_msr(cpu, MSR_PM_ENABLE, 1);
1032
1033 if (verbose)
1034 printf("cpu%d: MSR_PM_ENABLE old: %d new: %d\n", cpu, (unsigned int) msr, 1);
1035
1036 return 0;
1037}
1038
1039int update_cpu_msrs(int cpu)
1040{
1041 unsigned long long msr;
1042
232 1043
233 retval = pwrite(fd, &new_msr, sizeof new_msr, offset); 1044 if (update_epb) {
234 if (retval != sizeof new_msr) { 1045 get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr);
235 perror("pwrite"); 1046 put_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, new_epb);
236 printf("pwrite cpu%d 0x%x = %d\n", cpu, offset, retval); 1047
237 exit(-2); 1048 if (verbose)
1049 printf("cpu%d: ENERGY_PERF_BIAS old: %d new: %d\n",
1050 cpu, (unsigned int) msr, (unsigned int) new_epb);
238 } 1051 }
239 1052
240 close(fd); 1053 if (update_turbo) {
1054 int turbo_is_present_and_disabled;
1055
1056 get_msr(cpu, MSR_IA32_MISC_ENABLE, &msr);
1057
1058 turbo_is_present_and_disabled = ((msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE) != 0);
1059
1060 if (turbo_update_value == 1) {
1061 if (turbo_is_present_and_disabled) {
1062 msr &= ~MSR_IA32_MISC_ENABLE_TURBO_DISABLE;
1063 put_msr(cpu, MSR_IA32_MISC_ENABLE, msr);
1064 if (verbose)
1065 printf("cpu%d: turbo ENABLE\n", cpu);
1066 }
1067 } else {
1068 /*
1069 * if "turbo_is_enabled" were known to be describe this cpu
1070 * then we could use it here to skip redundant disable requests.
1071 * but cpu may be in a different package, so we always write.
1072 */
1073 msr |= MSR_IA32_MISC_ENABLE_TURBO_DISABLE;
1074 put_msr(cpu, MSR_IA32_MISC_ENABLE, msr);
1075 if (verbose)
1076 printf("cpu%d: turbo DISABLE\n", cpu);
1077 }
1078 }
1079
1080 if (!has_hwp)
1081 return 0;
1082
1083 if (!hwp_update_enabled())
1084 return 0;
1085
1086 update_hwp_request(cpu);
1087 return 0;
1088}
1089
1090/*
1091 * Open a file, and exit on failure
1092 */
1093FILE *fopen_or_die(const char *path, const char *mode)
1094{
1095 FILE *filep = fopen(path, "r");
241 1096
242 return old_msr; 1097 if (!filep)
1098 err(1, "%s: open failed", path);
1099 return filep;
243} 1100}
244 1101
245void print_msr(int cpu) 1102unsigned int get_pkg_num(int cpu)
246{ 1103{
247 printf("cpu%d: 0x%016llx\n", 1104 FILE *fp;
248 cpu, get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS)); 1105 char pathname[128];
1106 unsigned int pkg;
1107 int retval;
1108
1109 sprintf(pathname, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu);
1110
1111 fp = fopen_or_die(pathname, "r");
1112 retval = fscanf(fp, "%d\n", &pkg);
1113 if (retval != 1)
1114 errx(1, "%s: failed to parse", pathname);
1115 return pkg;
249} 1116}
250 1117
251void update_msr(int cpu) 1118int set_max_cpu_pkg_num(int cpu)
252{ 1119{
253 unsigned long long previous_msr; 1120 unsigned int pkg;
254 1121
255 previous_msr = put_msr(cpu, new_bias, MSR_IA32_ENERGY_PERF_BIAS); 1122 if (max_cpu_num < cpu)
1123 max_cpu_num = cpu;
256 1124
257 if (verbose) 1125 pkg = get_pkg_num(cpu);
258 printf("cpu%d msr0x%x 0x%016llx -> 0x%016llx\n", 1126
259 cpu, MSR_IA32_ENERGY_PERF_BIAS, previous_msr, new_bias); 1127 if (pkg >= MAX_PACKAGES)
1128 errx(1, "cpu%d: %d >= MAX_PACKAGES (%d)", cpu, pkg, MAX_PACKAGES);
1129
1130 if (pkg > max_pkg_num)
1131 max_pkg_num = pkg;
260 1132
261 return; 1133 if ((pkg_present_set & (1ULL << pkg)) == 0) {
1134 pkg_present_set |= (1ULL << pkg);
1135 first_cpu_in_pkg[pkg] = cpu;
1136 }
1137
1138 return 0;
1139}
1140int mark_cpu_present(int cpu)
1141{
1142 CPU_SET_S(cpu, cpu_setsize, cpu_present_set);
1143 return 0;
262} 1144}
263 1145
264char *proc_stat = "/proc/stat";
265/* 1146/*
266 * run func() on every cpu in /dev/cpu 1147 * run func(cpu) on every cpu in /proc/stat
1148 * return max_cpu number
267 */ 1149 */
268void for_every_cpu(void (func)(int)) 1150int for_all_proc_cpus(int (func)(int))
269{ 1151{
270 FILE *fp; 1152 FILE *fp;
1153 int cpu_num;
271 int retval; 1154 int retval;
272 1155
273 fp = fopen(proc_stat, "r"); 1156 fp = fopen_or_die(proc_stat, "r");
274 if (fp == NULL) {
275 perror(proc_stat);
276 exit(1);
277 }
278 1157
279 retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n"); 1158 retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
280 if (retval != 0) { 1159 if (retval != 0)
281 perror("/proc/stat format"); 1160 err(1, "%s: failed to parse format", proc_stat);
282 exit(1);
283 }
284 1161
285 while (1) { 1162 while (1) {
286 int cpu; 1163 retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num);
287
288 retval = fscanf(fp,
289 "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n",
290 &cpu);
291 if (retval != 1) 1164 if (retval != 1)
292 break; 1165 break;
293 1166
294 func(cpu); 1167 retval = func(cpu_num);
1168 if (retval) {
1169 fclose(fp);
1170 return retval;
1171 }
295 } 1172 }
296 fclose(fp); 1173 fclose(fp);
1174 return 0;
1175}
1176
1177void for_all_cpus_in_set(size_t set_size, cpu_set_t *cpu_set, int (func)(int))
1178{
1179 int cpu_num;
1180
1181 for (cpu_num = 0; cpu_num <= max_cpu_num; ++cpu_num)
1182 if (CPU_ISSET_S(cpu_num, set_size, cpu_set))
1183 func(cpu_num);
1184}
1185
1186void init_data_structures(void)
1187{
1188 for_all_proc_cpus(set_max_cpu_pkg_num);
1189
1190 cpu_setsize = CPU_ALLOC_SIZE((max_cpu_num + 1));
1191
1192 cpu_present_set = CPU_ALLOC((max_cpu_num + 1));
1193 if (cpu_present_set == NULL)
1194 err(3, "CPU_ALLOC");
1195 CPU_ZERO_S(cpu_setsize, cpu_present_set);
1196 for_all_proc_cpus(mark_cpu_present);
1197}
1198
1199/* clear has_hwp if it is not enable (or being enabled) */
1200
1201void verify_hwp_is_enabled(void)
1202{
1203 unsigned long long msr;
1204
1205 if (!has_hwp) /* set in early_cpuid() */
1206 return;
1207
1208 /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */
1209 get_msr(base_cpu, MSR_PM_ENABLE, &msr);
1210 if ((msr & 1) == 0) {
1211 fprintf(stderr, "HWP can be enabled using '--hwp-enable'\n");
1212 has_hwp = 0;
1213 return;
1214 }
1215}
1216
1217int req_update_bounds_check(void)
1218{
1219 if (!hwp_update_enabled())
1220 return 0;
1221
1222 /* fail if min > max requested */
1223 if ((update_hwp_max && update_hwp_min) &&
1224 (req_update.hwp_min > req_update.hwp_max)) {
1225 printf("hwp-min %d > hwp_max %d\n", req_update.hwp_min, req_update.hwp_max);
1226 return -EINVAL;
1227 }
1228
1229 /* fail if desired > max requestd */
1230 if (req_update.hwp_desired && update_hwp_max &&
1231 (req_update.hwp_desired > req_update.hwp_max)) {
1232 printf("hwp-desired cannot be greater than hwp_max\n");
1233 return -EINVAL;
1234 }
1235 /* fail if desired < min requestd */
1236 if (req_update.hwp_desired && update_hwp_min &&
1237 (req_update.hwp_desired < req_update.hwp_min)) {
1238 printf("hwp-desired cannot be less than hwp_min\n");
1239 return -EINVAL;
1240 }
1241
1242 return 0;
1243}
1244
1245void set_base_cpu(void)
1246{
1247 base_cpu = sched_getcpu();
1248 if (base_cpu < 0)
1249 err(-ENODEV, "No valid cpus found");
1250}
1251
1252
1253void probe_dev_msr(void)
1254{
1255 struct stat sb;
1256 char pathname[32];
1257
1258 sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
1259 if (stat(pathname, &sb))
1260 if (system("/sbin/modprobe msr > /dev/null 2>&1"))
1261 err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
1262}
1263/*
1264 * early_cpuid()
1265 * initialize turbo_is_enabled, has_hwp, has_epb
1266 * before cmdline is parsed
1267 */
1268void early_cpuid(void)
1269{
1270 unsigned int eax, ebx, ecx, edx, max_level;
1271 unsigned int fms, family, model;
1272
1273 __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
1274
1275 if (max_level < 6)
1276 errx(1, "Processor not supported\n");
1277
1278 __get_cpuid(1, &fms, &ebx, &ecx, &edx);
1279 family = (fms >> 8) & 0xf;
1280 model = (fms >> 4) & 0xf;
1281 if (family == 6 || family == 0xf)
1282 model += ((fms >> 16) & 0xf) << 4;
1283
1284 if (model == 0x4F) {
1285 unsigned long long msr;
1286
1287 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
1288
1289 bdx_highest_ratio = msr & 0xFF;
1290 }
1291
1292 __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
1293 turbo_is_enabled = (eax >> 1) & 1;
1294 has_hwp = (eax >> 7) & 1;
1295 has_epb = (ecx >> 3) & 1;
1296}
1297
1298/*
1299 * parse_cpuid()
1300 * set
1301 * has_hwp, has_hwp_notify, has_hwp_activity_window, has_hwp_epp, has_hwp_request_pkg, has_epb
1302 */
1303void parse_cpuid(void)
1304{
1305 unsigned int eax, ebx, ecx, edx, max_level;
1306 unsigned int fms, family, model, stepping;
1307
1308 eax = ebx = ecx = edx = 0;
1309
1310 __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
1311
1312 if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
1313 genuine_intel = 1;
1314
1315 if (debug)
1316 fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ",
1317 (char *)&ebx, (char *)&edx, (char *)&ecx);
1318
1319 __get_cpuid(1, &fms, &ebx, &ecx, &edx);
1320 family = (fms >> 8) & 0xf;
1321 model = (fms >> 4) & 0xf;
1322 stepping = fms & 0xf;
1323 if (family == 6 || family == 0xf)
1324 model += ((fms >> 16) & 0xf) << 4;
1325
1326 if (debug) {
1327 fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
1328 max_level, family, model, stepping, family, model, stepping);
1329 fprintf(stderr, "CPUID(1): %s %s %s %s %s %s %s %s\n",
1330 ecx & (1 << 0) ? "SSE3" : "-",
1331 ecx & (1 << 3) ? "MONITOR" : "-",
1332 ecx & (1 << 7) ? "EIST" : "-",
1333 ecx & (1 << 8) ? "TM2" : "-",
1334 edx & (1 << 4) ? "TSC" : "-",
1335 edx & (1 << 5) ? "MSR" : "-",
1336 edx & (1 << 22) ? "ACPI-TM" : "-",
1337 edx & (1 << 29) ? "TM" : "-");
1338 }
1339
1340 if (!(edx & (1 << 5)))
1341 errx(1, "CPUID: no MSR");
1342
1343
1344 __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
1345 /* turbo_is_enabled already set */
1346 /* has_hwp already set */
1347 has_hwp_notify = eax & (1 << 8);
1348 has_hwp_activity_window = eax & (1 << 9);
1349 has_hwp_epp = eax & (1 << 10);
1350 has_hwp_request_pkg = eax & (1 << 11);
1351
1352 if (!has_hwp_request_pkg && update_hwp_use_pkg)
1353 errx(1, "--hwp-use-pkg is not available on this hardware");
1354
1355 /* has_epb already set */
1356
1357 if (debug)
1358 fprintf(stderr,
1359 "CPUID(6): %sTURBO, %sHWP, %sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",
1360 turbo_is_enabled ? "" : "No-",
1361 has_hwp ? "" : "No-",
1362 has_hwp_notify ? "" : "No-",
1363 has_hwp_activity_window ? "" : "No-",
1364 has_hwp_epp ? "" : "No-",
1365 has_hwp_request_pkg ? "" : "No-",
1366 has_epb ? "" : "No-");
1367
1368 return; /* success */
297} 1369}
298 1370
299int main(int argc, char **argv) 1371int main(int argc, char **argv)
300{ 1372{
1373 set_base_cpu();
1374 probe_dev_msr();
1375 init_data_structures();
1376
1377 early_cpuid(); /* initial cpuid parse before cmdline */
1378
301 cmdline(argc, argv); 1379 cmdline(argc, argv);
302 1380
303 if (verbose > 1) 1381 if (debug)
304 printf("x86_energy_perf_policy Nov 24, 2010" 1382 print_version();
305 " - Len Brown <lenb@kernel.org>\n"); 1383
306 if (verbose > 1 && !read_only) 1384 parse_cpuid();
307 printf("new_bias %lld\n", new_bias); 1385
308 1386 /* If CPU-set and PKG-set are not initialized, default to all CPUs */
309 validate_cpuid(); 1387 if ((cpu_selected_set == 0) && (pkg_selected_set == 0))
310 1388 cpu_selected_set = cpu_present_set;
311 if (cpu != -1) { 1389
312 if (read_only) 1390 /*
313 print_msr(cpu); 1391 * If HWP is being enabled, do it now, so that subsequent operations
314 else 1392 * that access HWP registers can work.
315 update_msr(cpu); 1393 */
316 } else { 1394 if (update_hwp_enable)
317 if (read_only) 1395 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, enable_hwp_on_cpu);
318 for_every_cpu(print_msr); 1396
319 else 1397 /* If HWP present, but disabled, warn and ignore from here forward */
320 for_every_cpu(update_msr); 1398 verify_hwp_is_enabled();
1399
1400 if (req_update_bounds_check())
1401 return -EINVAL;
1402
1403 /* display information only, no updates to settings */
1404 if (!update_epb && !update_turbo && !hwp_update_enabled()) {
1405 if (cpu_selected_set)
1406 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, print_cpu_msrs);
1407
1408 if (has_hwp_request_pkg) {
1409 if (pkg_selected_set == 0)
1410 pkg_selected_set = pkg_present_set;
1411
1412 for_packages(pkg_selected_set, print_pkg_msrs);
1413 }
1414
1415 return 0;
321 } 1416 }
322 1417
1418 /* update CPU set */
1419 if (cpu_selected_set) {
1420 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_sysfs);
1421 for_all_cpus_in_set(cpu_setsize, cpu_selected_set, update_cpu_msrs);
1422 } else if (pkg_selected_set)
1423 for_packages(pkg_selected_set, update_hwp_request_pkg);
1424
323 return 0; 1425 return 0;
324} 1426}
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c
index 64cae1a5deff..e1f75a1914a1 100644
--- a/tools/testing/nvdimm/test/iomap.c
+++ b/tools/testing/nvdimm/test/iomap.c
@@ -370,7 +370,7 @@ acpi_status __wrap_acpi_evaluate_object(acpi_handle handle, acpi_string path,
370} 370}
371EXPORT_SYMBOL(__wrap_acpi_evaluate_object); 371EXPORT_SYMBOL(__wrap_acpi_evaluate_object);
372 372
373union acpi_object * __wrap_acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, 373union acpi_object * __wrap_acpi_evaluate_dsm(acpi_handle handle, const guid_t *guid,
374 u64 rev, u64 func, union acpi_object *argv4) 374 u64 rev, u64 func, union acpi_object *argv4)
375{ 375{
376 union acpi_object *obj = ERR_PTR(-ENXIO); 376 union acpi_object *obj = ERR_PTR(-ENXIO);
@@ -379,11 +379,11 @@ union acpi_object * __wrap_acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid,
379 rcu_read_lock(); 379 rcu_read_lock();
380 ops = list_first_or_null_rcu(&iomap_head, typeof(*ops), list); 380 ops = list_first_or_null_rcu(&iomap_head, typeof(*ops), list);
381 if (ops) 381 if (ops)
382 obj = ops->evaluate_dsm(handle, uuid, rev, func, argv4); 382 obj = ops->evaluate_dsm(handle, guid, rev, func, argv4);
383 rcu_read_unlock(); 383 rcu_read_unlock();
384 384
385 if (IS_ERR(obj)) 385 if (IS_ERR(obj))
386 return acpi_evaluate_dsm(handle, uuid, rev, func, argv4); 386 return acpi_evaluate_dsm(handle, guid, rev, func, argv4);
387 return obj; 387 return obj;
388} 388}
389EXPORT_SYMBOL(__wrap_acpi_evaluate_dsm); 389EXPORT_SYMBOL(__wrap_acpi_evaluate_dsm);
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index c2187178fb13..4c2fa98ef39d 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -1559,7 +1559,7 @@ static unsigned long nfit_ctl_handle;
1559union acpi_object *result; 1559union acpi_object *result;
1560 1560
1561static union acpi_object *nfit_test_evaluate_dsm(acpi_handle handle, 1561static union acpi_object *nfit_test_evaluate_dsm(acpi_handle handle,
1562 const u8 *uuid, u64 rev, u64 func, union acpi_object *argv4) 1562 const guid_t *guid, u64 rev, u64 func, union acpi_object *argv4)
1563{ 1563{
1564 if (handle != &nfit_ctl_handle) 1564 if (handle != &nfit_ctl_handle)
1565 return ERR_PTR(-ENXIO); 1565 return ERR_PTR(-ENXIO);
@@ -1943,7 +1943,7 @@ static __init int nfit_test_init(void)
1943 nfit_test->setup = nfit_test0_setup; 1943 nfit_test->setup = nfit_test0_setup;
1944 break; 1944 break;
1945 case 1: 1945 case 1:
1946 nfit_test->num_pm = 1; 1946 nfit_test->num_pm = 2;
1947 nfit_test->dcr_idx = NUM_DCR; 1947 nfit_test->dcr_idx = NUM_DCR;
1948 nfit_test->num_dcr = 2; 1948 nfit_test->num_dcr = 2;
1949 nfit_test->alloc = nfit_test1_alloc; 1949 nfit_test->alloc = nfit_test1_alloc;
diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h
index f54c0032c6ff..d3d63dd5ed38 100644
--- a/tools/testing/nvdimm/test/nfit_test.h
+++ b/tools/testing/nvdimm/test/nfit_test.h
@@ -13,6 +13,7 @@
13#ifndef __NFIT_TEST_H__ 13#ifndef __NFIT_TEST_H__
14#define __NFIT_TEST_H__ 14#define __NFIT_TEST_H__
15#include <linux/list.h> 15#include <linux/list.h>
16#include <linux/uuid.h>
16#include <linux/ioport.h> 17#include <linux/ioport.h>
17#include <linux/spinlock_types.h> 18#include <linux/spinlock_types.h>
18 19
@@ -36,7 +37,8 @@ typedef void *acpi_handle;
36 37
37typedef struct nfit_test_resource *(*nfit_test_lookup_fn)(resource_size_t); 38typedef struct nfit_test_resource *(*nfit_test_lookup_fn)(resource_size_t);
38typedef union acpi_object *(*nfit_test_evaluate_dsm_fn)(acpi_handle handle, 39typedef union acpi_object *(*nfit_test_evaluate_dsm_fn)(acpi_handle handle,
39 const u8 *uuid, u64 rev, u64 func, union acpi_object *argv4); 40 const guid_t *guid, u64 rev, u64 func,
41 union acpi_object *argv4);
40void __iomem *__wrap_ioremap_nocache(resource_size_t offset, 42void __iomem *__wrap_ioremap_nocache(resource_size_t offset,
41 unsigned long size); 43 unsigned long size);
42void __wrap_iounmap(volatile void __iomem *addr); 44void __wrap_iounmap(volatile void __iomem *addr);
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 91edd0566237..2ca51a8a588c 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -11,9 +11,11 @@ endif
11CFLAGS += -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include 11CFLAGS += -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include
12LDLIBS += -lcap -lelf 12LDLIBS += -lcap -lelf
13 13
14TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs 14TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
15 test_align
15 16
16TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o 17TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \
18 test_pkt_md_access.o
17 19
18TEST_PROGS := test_kmod.sh 20TEST_PROGS := test_kmod.sh
19 21
@@ -34,6 +36,7 @@ $(BPFOBJ): force
34CLANG ?= clang 36CLANG ?= clang
35 37
36%.o: %.c 38%.o: %.c
37 $(CLANG) -I. -I../../../include/uapi -I../../../../samples/bpf/ \ 39 $(CLANG) -I. -I./include/uapi -I../../../include/uapi \
40 -I../../../../samples/bpf/ \
38 -Wno-compare-distinct-pointer-types \ 41 -Wno-compare-distinct-pointer-types \
39 -O2 -target bpf -c $< -o $@ 42 -O2 -target bpf -c $< -o $@
diff --git a/tools/testing/selftests/bpf/bpf_endian.h b/tools/testing/selftests/bpf/bpf_endian.h
index 19d0604f8694..487cbfb89beb 100644
--- a/tools/testing/selftests/bpf/bpf_endian.h
+++ b/tools/testing/selftests/bpf/bpf_endian.h
@@ -1,23 +1,42 @@
1#ifndef __BPF_ENDIAN__ 1#ifndef __BPF_ENDIAN__
2#define __BPF_ENDIAN__ 2#define __BPF_ENDIAN__
3 3
4#include <asm/byteorder.h> 4#include <linux/swab.h>
5 5
6#if __BYTE_ORDER == __LITTLE_ENDIAN 6/* LLVM's BPF target selects the endianness of the CPU
7# define __bpf_ntohs(x) __builtin_bswap16(x) 7 * it compiles on, or the user specifies (bpfel/bpfeb),
8# define __bpf_htons(x) __builtin_bswap16(x) 8 * respectively. The used __BYTE_ORDER__ is defined by
9#elif __BYTE_ORDER == __BIG_ENDIAN 9 * the compiler, we cannot rely on __BYTE_ORDER from
10# define __bpf_ntohs(x) (x) 10 * libc headers, since it doesn't reflect the actual
11# define __bpf_htons(x) (x) 11 * requested byte order.
12 *
13 * Note, LLVM's BPF target has different __builtin_bswapX()
14 * semantics. It does map to BPF_ALU | BPF_END | BPF_TO_BE
15 * in bpfel and bpfeb case, which means below, that we map
16 * to cpu_to_be16(). We could use it unconditionally in BPF
17 * case, but better not rely on it, so that this header here
18 * can be used from application and BPF program side, which
19 * use different targets.
20 */
21#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
22# define __bpf_ntohs(x) __builtin_bswap16(x)
23# define __bpf_htons(x) __builtin_bswap16(x)
24# define __bpf_constant_ntohs(x) ___constant_swab16(x)
25# define __bpf_constant_htons(x) ___constant_swab16(x)
26#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
27# define __bpf_ntohs(x) (x)
28# define __bpf_htons(x) (x)
29# define __bpf_constant_ntohs(x) (x)
30# define __bpf_constant_htons(x) (x)
12#else 31#else
13# error "Fix your __BYTE_ORDER?!" 32# error "Fix your compiler's __BYTE_ORDER__?!"
14#endif 33#endif
15 34
16#define bpf_htons(x) \ 35#define bpf_htons(x) \
17 (__builtin_constant_p(x) ? \ 36 (__builtin_constant_p(x) ? \
18 __constant_htons(x) : __bpf_htons(x)) 37 __bpf_constant_htons(x) : __bpf_htons(x))
19#define bpf_ntohs(x) \ 38#define bpf_ntohs(x) \
20 (__builtin_constant_p(x) ? \ 39 (__builtin_constant_p(x) ? \
21 __constant_ntohs(x) : __bpf_ntohs(x)) 40 __bpf_constant_ntohs(x) : __bpf_ntohs(x))
22 41
23#endif 42#endif /* __BPF_ENDIAN__ */
diff --git a/tools/testing/selftests/bpf/include/uapi/linux/types.h b/tools/testing/selftests/bpf/include/uapi/linux/types.h
new file mode 100644
index 000000000000..51841848fbfe
--- /dev/null
+++ b/tools/testing/selftests/bpf/include/uapi/linux/types.h
@@ -0,0 +1,22 @@
1#ifndef _UAPI_LINUX_TYPES_H
2#define _UAPI_LINUX_TYPES_H
3
4#include <asm-generic/int-ll64.h>
5
6/* copied from linux:include/uapi/linux/types.h */
7#define __bitwise
8typedef __u16 __bitwise __le16;
9typedef __u16 __bitwise __be16;
10typedef __u32 __bitwise __le32;
11typedef __u32 __bitwise __be32;
12typedef __u64 __bitwise __le64;
13typedef __u64 __bitwise __be64;
14
15typedef __u16 __bitwise __sum16;
16typedef __u32 __bitwise __wsum;
17
18#define __aligned_u64 __u64 __attribute__((aligned(8)))
19#define __aligned_be64 __be64 __attribute__((aligned(8)))
20#define __aligned_le64 __le64 __attribute__((aligned(8)))
21
22#endif /* _UAPI_LINUX_TYPES_H */
diff --git a/tools/testing/selftests/bpf/test_align.c b/tools/testing/selftests/bpf/test_align.c
new file mode 100644
index 000000000000..bccebd935907
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_align.c
@@ -0,0 +1,458 @@
1#include <asm/types.h>
2#include <linux/types.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <errno.h>
8#include <string.h>
9#include <stddef.h>
10#include <stdbool.h>
11
12#include <sys/resource.h>
13
14#include <linux/unistd.h>
15#include <linux/filter.h>
16#include <linux/bpf_perf_event.h>
17#include <linux/bpf.h>
18
19#include <bpf/bpf.h>
20
21#include "../../../include/linux/filter.h"
22
23#ifndef ARRAY_SIZE
24# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
25#endif
26
27#define MAX_INSNS 512
28#define MAX_MATCHES 16
29
30struct bpf_align_test {
31 const char *descr;
32 struct bpf_insn insns[MAX_INSNS];
33 enum {
34 UNDEF,
35 ACCEPT,
36 REJECT
37 } result;
38 enum bpf_prog_type prog_type;
39 const char *matches[MAX_MATCHES];
40};
41
42static struct bpf_align_test tests[] = {
43 {
44 .descr = "mov",
45 .insns = {
46 BPF_MOV64_IMM(BPF_REG_3, 2),
47 BPF_MOV64_IMM(BPF_REG_3, 4),
48 BPF_MOV64_IMM(BPF_REG_3, 8),
49 BPF_MOV64_IMM(BPF_REG_3, 16),
50 BPF_MOV64_IMM(BPF_REG_3, 32),
51 BPF_MOV64_IMM(BPF_REG_0, 0),
52 BPF_EXIT_INSN(),
53 },
54 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
55 .matches = {
56 "1: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
57 "2: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
58 "3: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
59 "4: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
60 "5: R1=ctx R3=imm32,min_value=32,max_value=32,min_align=32 R10=fp",
61 },
62 },
63 {
64 .descr = "shift",
65 .insns = {
66 BPF_MOV64_IMM(BPF_REG_3, 1),
67 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
68 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
69 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
70 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
71 BPF_ALU64_IMM(BPF_RSH, BPF_REG_3, 4),
72 BPF_MOV64_IMM(BPF_REG_4, 32),
73 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
74 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
75 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
76 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
77 BPF_MOV64_IMM(BPF_REG_0, 0),
78 BPF_EXIT_INSN(),
79 },
80 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
81 .matches = {
82 "1: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp",
83 "2: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
84 "3: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
85 "4: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
86 "5: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
87 "6: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp",
88 "7: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm32,min_value=32,max_value=32,min_align=32 R10=fp",
89 "8: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
90 "9: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
91 "10: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
92 "11: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
93 },
94 },
95 {
96 .descr = "addsub",
97 .insns = {
98 BPF_MOV64_IMM(BPF_REG_3, 4),
99 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 4),
100 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 2),
101 BPF_MOV64_IMM(BPF_REG_4, 8),
102 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
103 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2),
104 BPF_MOV64_IMM(BPF_REG_0, 0),
105 BPF_EXIT_INSN(),
106 },
107 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
108 .matches = {
109 "1: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
110 "2: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=4 R10=fp",
111 "3: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R10=fp",
112 "4: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
113 "5: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm12,min_value=12,max_value=12,min_align=4 R10=fp",
114 "6: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm14,min_value=14,max_value=14,min_align=2 R10=fp",
115 },
116 },
117 {
118 .descr = "mul",
119 .insns = {
120 BPF_MOV64_IMM(BPF_REG_3, 7),
121 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 1),
122 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 2),
123 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 4),
124 BPF_MOV64_IMM(BPF_REG_0, 0),
125 BPF_EXIT_INSN(),
126 },
127 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
128 .matches = {
129 "1: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp",
130 "2: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp",
131 "3: R1=ctx R3=imm14,min_value=14,max_value=14,min_align=2 R10=fp",
132 "4: R1=ctx R3=imm56,min_value=56,max_value=56,min_align=4 R10=fp",
133 },
134 },
135
136#define PREP_PKT_POINTERS \
137 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, \
138 offsetof(struct __sk_buff, data)), \
139 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, \
140 offsetof(struct __sk_buff, data_end))
141
142#define LOAD_UNKNOWN(DST_REG) \
143 PREP_PKT_POINTERS, \
144 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), \
145 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8), \
146 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 1), \
147 BPF_EXIT_INSN(), \
148 BPF_LDX_MEM(BPF_B, DST_REG, BPF_REG_2, 0)
149
150 {
151 .descr = "unknown shift",
152 .insns = {
153 LOAD_UNKNOWN(BPF_REG_3),
154 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
155 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
156 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
157 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
158 LOAD_UNKNOWN(BPF_REG_4),
159 BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 5),
160 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
161 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
162 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
163 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
164 BPF_MOV64_IMM(BPF_REG_0, 0),
165 BPF_EXIT_INSN(),
166 },
167 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
168 .matches = {
169 "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp",
170 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv55,min_align=2 R10=fp",
171 "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv54,min_align=4 R10=fp",
172 "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv53,min_align=8 R10=fp",
173 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv52,min_align=16 R10=fp",
174 "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv56 R10=fp",
175 "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv51,min_align=32 R10=fp",
176 "20: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv52,min_align=16 R10=fp",
177 "21: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv53,min_align=8 R10=fp",
178 "22: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv54,min_align=4 R10=fp",
179 "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv55,min_align=2 R10=fp",
180 },
181 },
182 {
183 .descr = "unknown mul",
184 .insns = {
185 LOAD_UNKNOWN(BPF_REG_3),
186 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
187 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 1),
188 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
189 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
190 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
191 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 4),
192 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
193 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 8),
194 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
195 BPF_MOV64_IMM(BPF_REG_0, 0),
196 BPF_EXIT_INSN(),
197 },
198 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
199 .matches = {
200 "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp",
201 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
202 "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv55,min_align=1 R10=fp",
203 "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
204 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv54,min_align=2 R10=fp",
205 "12: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
206 "13: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv53,min_align=4 R10=fp",
207 "14: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
208 "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv52,min_align=8 R10=fp",
209 "16: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv50,min_align=8 R10=fp"
210 },
211 },
212 {
213 .descr = "packet const offset",
214 .insns = {
215 PREP_PKT_POINTERS,
216 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
217
218 BPF_MOV64_IMM(BPF_REG_0, 0),
219
220 /* Skip over ethernet header. */
221 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
222 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
223 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
224 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
225 BPF_EXIT_INSN(),
226
227 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 0),
228 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 1),
229 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 2),
230 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 3),
231 BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 0),
232 BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 2),
233 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
234
235 BPF_MOV64_IMM(BPF_REG_0, 0),
236 BPF_EXIT_INSN(),
237 },
238 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
239 .matches = {
240 "4: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=0,r=0) R10=fp",
241 "5: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=14,r=0) R10=fp",
242 "6: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R4=pkt(id=0,off=14,r=0) R5=pkt(id=0,off=14,r=0) R10=fp",
243 "10: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv56 R5=pkt(id=0,off=14,r=18) R10=fp",
244 "14: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp",
245 "15: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp",
246 },
247 },
248 {
249 .descr = "packet variable offset",
250 .insns = {
251 LOAD_UNKNOWN(BPF_REG_6),
252 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
253
254 /* First, add a constant to the R5 packet pointer,
255 * then a variable with a known alignment.
256 */
257 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
258 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
259 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
260 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
261 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
262 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
263 BPF_EXIT_INSN(),
264 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
265
266 /* Now, test in the other direction. Adding first
267 * the variable offset to R5, then the constant.
268 */
269 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
270 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
271 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
272 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
273 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
274 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
275 BPF_EXIT_INSN(),
276 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
277
278 /* Test multiple accumulations of unknown values
279 * into a packet pointer.
280 */
281 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
282 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
283 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
284 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 4),
285 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
286 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
287 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
288 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
289 BPF_EXIT_INSN(),
290 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
291
292 BPF_MOV64_IMM(BPF_REG_0, 0),
293 BPF_EXIT_INSN(),
294 },
295 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
296 .matches = {
297 /* Calculated offset in R6 has unknown value, but known
298 * alignment of 4.
299 */
300 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R6=inv54,min_align=4 R10=fp",
301
302 /* Offset is added to packet pointer R5, resulting in known
303 * auxiliary alignment and offset.
304 */
305 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R5=pkt(id=1,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
306
307 /* At the time the word size load is performed from R5,
308 * it's total offset is NET_IP_ALIGN + reg->off (0) +
309 * reg->aux_off (14) which is 16. Then the variable
310 * offset is considered using reg->aux_off_align which
311 * is 4 and meets the load's requirements.
312 */
313 "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=1,off=4,r=4),aux_off=14,aux_off_align=4 R5=pkt(id=1,off=0,r=4),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
314
315
316 /* Variable offset is added to R5 packet pointer,
317 * resulting in auxiliary alignment of 4.
318 */
319 "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=0,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
320
321 /* Constant offset is added to R5, resulting in
322 * reg->off of 14.
323 */
324 "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=14,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
325
326 /* At the time the word size load is performed from R5,
327 * it's total offset is NET_IP_ALIGN + reg->off (14) which
328 * is 16. Then the variable offset is considered using
329 * reg->aux_off_align which is 4 and meets the load's
330 * requirements.
331 */
332 "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=2,off=18,r=18),aux_off_align=4 R5=pkt(id=2,off=14,r=18),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
333
334 /* Constant offset is added to R5 packet pointer,
335 * resulting in reg->off value of 14.
336 */
337 "26: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=0,off=14,r=8) R6=inv54,min_align=4 R10=fp",
338 /* Variable offset is added to R5, resulting in an
339 * auxiliary offset of 14, and an auxiliary alignment of 4.
340 */
341 "27: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
342 /* Constant is added to R5 again, setting reg->off to 4. */
343 "28: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=4,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
344 /* And once more we add a variable, which causes an accumulation
345 * of reg->off into reg->aux_off_align, with resulting value of
346 * 18. The auxiliary alignment stays at 4.
347 */
348 "29: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=4,off=0,r=0),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
349 /* At the time the word size load is performed from R5,
350 * it's total offset is NET_IP_ALIGN + reg->off (0) +
351 * reg->aux_off (18) which is 20. Then the variable offset
352 * is considered using reg->aux_off_align which is 4 and meets
353 * the load's requirements.
354 */
355 "33: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=4,off=4,r=4),aux_off=18,aux_off_align=4 R5=pkt(id=4,off=0,r=4),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
356 },
357 },
358};
359
360static int probe_filter_length(const struct bpf_insn *fp)
361{
362 int len;
363
364 for (len = MAX_INSNS - 1; len > 0; --len)
365 if (fp[len].code != 0 || fp[len].imm != 0)
366 break;
367 return len + 1;
368}
369
370static char bpf_vlog[32768];
371
372static int do_test_single(struct bpf_align_test *test)
373{
374 struct bpf_insn *prog = test->insns;
375 int prog_type = test->prog_type;
376 int prog_len, i;
377 int fd_prog;
378 int ret;
379
380 prog_len = probe_filter_length(prog);
381 fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
382 prog, prog_len, 1, "GPL", 0,
383 bpf_vlog, sizeof(bpf_vlog));
384 if (fd_prog < 0) {
385 printf("Failed to load program.\n");
386 printf("%s", bpf_vlog);
387 ret = 1;
388 } else {
389 ret = 0;
390 for (i = 0; i < MAX_MATCHES; i++) {
391 const char *t, *m = test->matches[i];
392
393 if (!m)
394 break;
395 t = strstr(bpf_vlog, m);
396 if (!t) {
397 printf("Failed to find match: %s\n", m);
398 ret = 1;
399 printf("%s", bpf_vlog);
400 break;
401 }
402 }
403 close(fd_prog);
404 }
405 return ret;
406}
407
408static int do_test(unsigned int from, unsigned int to)
409{
410 int all_pass = 0;
411 int all_fail = 0;
412 unsigned int i;
413
414 for (i = from; i < to; i++) {
415 struct bpf_align_test *test = &tests[i];
416 int fail;
417
418 printf("Test %3d: %s ... ",
419 i, test->descr);
420 fail = do_test_single(test);
421 if (fail) {
422 all_fail++;
423 printf("FAIL\n");
424 } else {
425 all_pass++;
426 printf("PASS\n");
427 }
428 }
429 printf("Results: %d pass %d fail\n",
430 all_pass, all_fail);
431 return all_fail ? EXIT_FAILURE : EXIT_SUCCESS;
432}
433
434int main(int argc, char **argv)
435{
436 unsigned int from = 0, to = ARRAY_SIZE(tests);
437 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
438
439 setrlimit(RLIMIT_MEMLOCK, &rinf);
440
441 if (argc == 3) {
442 unsigned int l = atoi(argv[argc - 2]);
443 unsigned int u = atoi(argv[argc - 1]);
444
445 if (l < to && u < to) {
446 from = l;
447 to = u + 1;
448 }
449 } else if (argc == 2) {
450 unsigned int t = atoi(argv[argc - 1]);
451
452 if (t < to) {
453 from = t;
454 to = t + 1;
455 }
456 }
457 return do_test(from, to);
458}
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 93314524de0d..79601c81e169 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -239,6 +239,54 @@ static void test_hashmap_percpu(int task, void *data)
239 close(fd); 239 close(fd);
240} 240}
241 241
242static void test_hashmap_walk(int task, void *data)
243{
244 int fd, i, max_entries = 100000;
245 long long key, value, next_key;
246 bool next_key_valid = true;
247
248 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
249 max_entries, map_flags);
250 if (fd < 0) {
251 printf("Failed to create hashmap '%s'!\n", strerror(errno));
252 exit(1);
253 }
254
255 for (i = 0; i < max_entries; i++) {
256 key = i; value = key;
257 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
258 }
259
260 for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
261 &next_key) == 0; i++) {
262 key = next_key;
263 assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
264 }
265
266 assert(i == max_entries);
267
268 assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
269 for (i = 0; next_key_valid; i++) {
270 next_key_valid = bpf_map_get_next_key(fd, &key, &next_key) == 0;
271 assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
272 value++;
273 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
274 key = next_key;
275 }
276
277 assert(i == max_entries);
278
279 for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
280 &next_key) == 0; i++) {
281 key = next_key;
282 assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
283 assert(value - 1 == key);
284 }
285
286 assert(i == max_entries);
287 close(fd);
288}
289
242static void test_arraymap(int task, void *data) 290static void test_arraymap(int task, void *data)
243{ 291{
244 int key, next_key, fd; 292 int key, next_key, fd;
@@ -464,6 +512,7 @@ static void test_map_stress(void)
464 run_parallel(100, test_hashmap, NULL); 512 run_parallel(100, test_hashmap, NULL);
465 run_parallel(100, test_hashmap_percpu, NULL); 513 run_parallel(100, test_hashmap_percpu, NULL);
466 run_parallel(100, test_hashmap_sizes, NULL); 514 run_parallel(100, test_hashmap_sizes, NULL);
515 run_parallel(100, test_hashmap_walk, NULL);
467 516
468 run_parallel(100, test_arraymap, NULL); 517 run_parallel(100, test_arraymap, NULL);
469 run_parallel(100, test_arraymap_percpu, NULL); 518 run_parallel(100, test_arraymap_percpu, NULL);
@@ -549,6 +598,7 @@ static void run_all_tests(void)
549{ 598{
550 test_hashmap(0, NULL); 599 test_hashmap(0, NULL);
551 test_hashmap_percpu(0, NULL); 600 test_hashmap_percpu(0, NULL);
601 test_hashmap_walk(0, NULL);
552 602
553 test_arraymap(0, NULL); 603 test_arraymap(0, NULL);
554 test_arraymap_percpu(0, NULL); 604 test_arraymap_percpu(0, NULL);
diff --git a/tools/testing/selftests/bpf/test_obj_id.c b/tools/testing/selftests/bpf/test_obj_id.c
new file mode 100644
index 000000000000..880d2963b472
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_obj_id.c
@@ -0,0 +1,35 @@
1/* Copyright (c) 2017 Facebook
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#include <stddef.h>
8#include <linux/bpf.h>
9#include <linux/pkt_cls.h>
10#include "bpf_helpers.h"
11
12/* It is a dumb bpf program such that it must have no
13 * issue to be loaded since testing the verifier is
14 * not the focus here.
15 */
16
17int _version SEC("version") = 1;
18
19struct bpf_map_def SEC("maps") test_map_id = {
20 .type = BPF_MAP_TYPE_ARRAY,
21 .key_size = sizeof(__u32),
22 .value_size = sizeof(__u64),
23 .max_entries = 1,
24};
25
26SEC("test_obj_id_dummy")
27int test_obj_id(struct __sk_buff *skb)
28{
29 __u32 key = 0;
30 __u64 *value;
31
32 value = bpf_map_lookup_elem(&test_map_id, &key);
33
34 return TC_ACT_OK;
35}
diff --git a/tools/testing/selftests/bpf/test_pkt_access.c b/tools/testing/selftests/bpf/test_pkt_access.c
index 39387bb7e08c..6e11ba11709e 100644
--- a/tools/testing/selftests/bpf/test_pkt_access.c
+++ b/tools/testing/selftests/bpf/test_pkt_access.c
@@ -5,6 +5,7 @@
5 * License as published by the Free Software Foundation. 5 * License as published by the Free Software Foundation.
6 */ 6 */
7#include <stddef.h> 7#include <stddef.h>
8#include <string.h>
8#include <linux/bpf.h> 9#include <linux/bpf.h>
9#include <linux/if_ether.h> 10#include <linux/if_ether.h>
10#include <linux/if_packet.h> 11#include <linux/if_packet.h>
diff --git a/tools/testing/selftests/bpf/test_pkt_md_access.c b/tools/testing/selftests/bpf/test_pkt_md_access.c
new file mode 100644
index 000000000000..71729d47eb85
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_pkt_md_access.c
@@ -0,0 +1,35 @@
1/* Copyright (c) 2017 Facebook
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#include <stddef.h>
8#include <string.h>
9#include <linux/bpf.h>
10#include <linux/pkt_cls.h>
11#include "bpf_helpers.h"
12
13int _version SEC("version") = 1;
14
15#define TEST_FIELD(TYPE, FIELD, MASK) \
16 { \
17 TYPE tmp = *(volatile TYPE *)&skb->FIELD; \
18 if (tmp != ((*(volatile __u32 *)&skb->FIELD) & MASK)) \
19 return TC_ACT_SHOT; \
20 }
21
22SEC("test1")
23int process(struct __sk_buff *skb)
24{
25 TEST_FIELD(__u8, len, 0xFF);
26 TEST_FIELD(__u16, len, 0xFFFF);
27 TEST_FIELD(__u32, len, 0xFFFFFFFF);
28 TEST_FIELD(__u16, protocol, 0xFFFF);
29 TEST_FIELD(__u32, protocol, 0xFFFFFFFF);
30 TEST_FIELD(__u8, hash, 0xFF);
31 TEST_FIELD(__u16, hash, 0xFFFF);
32 TEST_FIELD(__u32, hash, 0xFFFFFFFF);
33
34 return TC_ACT_OK;
35}
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index b59f5ed4ae40..5855cd3d3d45 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -22,6 +22,8 @@ typedef __u16 __sum16;
22 22
23#include <sys/wait.h> 23#include <sys/wait.h>
24#include <sys/resource.h> 24#include <sys/resource.h>
25#include <sys/types.h>
26#include <fcntl.h>
25 27
26#include <linux/bpf.h> 28#include <linux/bpf.h>
27#include <linux/err.h> 29#include <linux/err.h>
@@ -70,6 +72,7 @@ static struct {
70 pass_cnt++; \ 72 pass_cnt++; \
71 printf("%s:PASS:%s %d nsec\n", __func__, tag, duration);\ 73 printf("%s:PASS:%s %d nsec\n", __func__, tag, duration);\
72 } \ 74 } \
75 __ret; \
73}) 76})
74 77
75static int bpf_prog_load(const char *file, enum bpf_prog_type type, 78static int bpf_prog_load(const char *file, enum bpf_prog_type type,
@@ -283,6 +286,224 @@ static void test_tcp_estats(void)
283 bpf_object__close(obj); 286 bpf_object__close(obj);
284} 287}
285 288
289static inline __u64 ptr_to_u64(const void *ptr)
290{
291 return (__u64) (unsigned long) ptr;
292}
293
294static void test_bpf_obj_id(void)
295{
296 const __u64 array_magic_value = 0xfaceb00c;
297 const __u32 array_key = 0;
298 const int nr_iters = 2;
299 const char *file = "./test_obj_id.o";
300 const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
301
302 struct bpf_object *objs[nr_iters];
303 int prog_fds[nr_iters], map_fds[nr_iters];
304 /* +1 to test for the info_len returned by kernel */
305 struct bpf_prog_info prog_infos[nr_iters + 1];
306 struct bpf_map_info map_infos[nr_iters + 1];
307 char jited_insns[128], xlated_insns[128];
308 __u32 i, next_id, info_len, nr_id_found, duration = 0;
309 int sysctl_fd, jit_enabled = 0, err = 0;
310 __u64 array_value;
311
312 sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
313 if (sysctl_fd != -1) {
314 char tmpc;
315
316 if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1)
317 jit_enabled = (tmpc != '0');
318 close(sysctl_fd);
319 }
320
321 err = bpf_prog_get_fd_by_id(0);
322 CHECK(err >= 0 || errno != ENOENT,
323 "get-fd-by-notexist-prog-id", "err %d errno %d\n", err, errno);
324
325 err = bpf_map_get_fd_by_id(0);
326 CHECK(err >= 0 || errno != ENOENT,
327 "get-fd-by-notexist-map-id", "err %d errno %d\n", err, errno);
328
329 for (i = 0; i < nr_iters; i++)
330 objs[i] = NULL;
331
332 /* Check bpf_obj_get_info_by_fd() */
333 for (i = 0; i < nr_iters; i++) {
334 err = bpf_prog_load(file, BPF_PROG_TYPE_SOCKET_FILTER,
335 &objs[i], &prog_fds[i]);
336 /* test_obj_id.o is a dumb prog. It should never fail
337 * to load.
338 */
339 assert(!err);
340
341 /* Check getting prog info */
342 info_len = sizeof(struct bpf_prog_info) * 2;
343 prog_infos[i].jited_prog_insns = ptr_to_u64(jited_insns);
344 prog_infos[i].jited_prog_len = sizeof(jited_insns);
345 prog_infos[i].xlated_prog_insns = ptr_to_u64(xlated_insns);
346 prog_infos[i].xlated_prog_len = sizeof(xlated_insns);
347 err = bpf_obj_get_info_by_fd(prog_fds[i], &prog_infos[i],
348 &info_len);
349 if (CHECK(err ||
350 prog_infos[i].type != BPF_PROG_TYPE_SOCKET_FILTER ||
351 info_len != sizeof(struct bpf_prog_info) ||
352 (jit_enabled && !prog_infos[i].jited_prog_len) ||
353 !prog_infos[i].xlated_prog_len,
354 "get-prog-info(fd)",
355 "err %d errno %d i %d type %d(%d) info_len %u(%lu) jit_enabled %d jited_prog_len %u xlated_prog_len %u\n",
356 err, errno, i,
357 prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER,
358 info_len, sizeof(struct bpf_prog_info),
359 jit_enabled,
360 prog_infos[i].jited_prog_len,
361 prog_infos[i].xlated_prog_len))
362 goto done;
363
364 map_fds[i] = bpf_find_map(__func__, objs[i], "test_map_id");
365 assert(map_fds[i] >= 0);
366 err = bpf_map_update_elem(map_fds[i], &array_key,
367 &array_magic_value, 0);
368 assert(!err);
369
370 /* Check getting map info */
371 info_len = sizeof(struct bpf_map_info) * 2;
372 err = bpf_obj_get_info_by_fd(map_fds[i], &map_infos[i],
373 &info_len);
374 if (CHECK(err ||
375 map_infos[i].type != BPF_MAP_TYPE_ARRAY ||
376 map_infos[i].key_size != sizeof(__u32) ||
377 map_infos[i].value_size != sizeof(__u64) ||
378 map_infos[i].max_entries != 1 ||
379 map_infos[i].map_flags != 0 ||
380 info_len != sizeof(struct bpf_map_info),
381 "get-map-info(fd)",
382 "err %d errno %d type %d(%d) info_len %u(%lu) key_size %u value_size %u max_entries %u map_flags %X\n",
383 err, errno,
384 map_infos[i].type, BPF_MAP_TYPE_ARRAY,
385 info_len, sizeof(struct bpf_map_info),
386 map_infos[i].key_size,
387 map_infos[i].value_size,
388 map_infos[i].max_entries,
389 map_infos[i].map_flags))
390 goto done;
391 }
392
393 /* Check bpf_prog_get_next_id() */
394 nr_id_found = 0;
395 next_id = 0;
396 while (!bpf_prog_get_next_id(next_id, &next_id)) {
397 struct bpf_prog_info prog_info;
398 int prog_fd;
399
400 info_len = sizeof(prog_info);
401
402 prog_fd = bpf_prog_get_fd_by_id(next_id);
403 if (prog_fd < 0 && errno == ENOENT)
404 /* The bpf_prog is in the dead row */
405 continue;
406 if (CHECK(prog_fd < 0, "get-prog-fd(next_id)",
407 "prog_fd %d next_id %d errno %d\n",
408 prog_fd, next_id, errno))
409 break;
410
411 for (i = 0; i < nr_iters; i++)
412 if (prog_infos[i].id == next_id)
413 break;
414
415 if (i == nr_iters)
416 continue;
417
418 nr_id_found++;
419
420 err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len);
421 CHECK(err || info_len != sizeof(struct bpf_prog_info) ||
422 memcmp(&prog_info, &prog_infos[i], info_len),
423 "get-prog-info(next_id->fd)",
424 "err %d errno %d info_len %u(%lu) memcmp %d\n",
425 err, errno, info_len, sizeof(struct bpf_prog_info),
426 memcmp(&prog_info, &prog_infos[i], info_len));
427
428 close(prog_fd);
429 }
430 CHECK(nr_id_found != nr_iters,
431 "check total prog id found by get_next_id",
432 "nr_id_found %u(%u)\n",
433 nr_id_found, nr_iters);
434
435 /* Check bpf_map_get_next_id() */
436 nr_id_found = 0;
437 next_id = 0;
438 while (!bpf_map_get_next_id(next_id, &next_id)) {
439 struct bpf_map_info map_info;
440 int map_fd;
441
442 info_len = sizeof(map_info);
443
444 map_fd = bpf_map_get_fd_by_id(next_id);
445 if (map_fd < 0 && errno == ENOENT)
446 /* The bpf_map is in the dead row */
447 continue;
448 if (CHECK(map_fd < 0, "get-map-fd(next_id)",
449 "map_fd %d next_id %u errno %d\n",
450 map_fd, next_id, errno))
451 break;
452
453 for (i = 0; i < nr_iters; i++)
454 if (map_infos[i].id == next_id)
455 break;
456
457 if (i == nr_iters)
458 continue;
459
460 nr_id_found++;
461
462 err = bpf_map_lookup_elem(map_fd, &array_key, &array_value);
463 assert(!err);
464
465 err = bpf_obj_get_info_by_fd(map_fd, &map_info, &info_len);
466 CHECK(err || info_len != sizeof(struct bpf_map_info) ||
467 memcmp(&map_info, &map_infos[i], info_len) ||
468 array_value != array_magic_value,
469 "check get-map-info(next_id->fd)",
470 "err %d errno %d info_len %u(%lu) memcmp %d array_value %llu(%llu)\n",
471 err, errno, info_len, sizeof(struct bpf_map_info),
472 memcmp(&map_info, &map_infos[i], info_len),
473 array_value, array_magic_value);
474
475 close(map_fd);
476 }
477 CHECK(nr_id_found != nr_iters,
478 "check total map id found by get_next_id",
479 "nr_id_found %u(%u)\n",
480 nr_id_found, nr_iters);
481
482done:
483 for (i = 0; i < nr_iters; i++)
484 bpf_object__close(objs[i]);
485}
486
487static void test_pkt_md_access(void)
488{
489 const char *file = "./test_pkt_md_access.o";
490 struct bpf_object *obj;
491 __u32 duration, retval;
492 int err, prog_fd;
493
494 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
495 if (err)
496 return;
497
498 err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4),
499 NULL, NULL, &retval, &duration);
500 CHECK(err || retval, "",
501 "err %d errno %d retval %d duration %d\n",
502 err, errno, retval, duration);
503
504 bpf_object__close(obj);
505}
506
286int main(void) 507int main(void)
287{ 508{
288 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY }; 509 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
@@ -293,7 +514,9 @@ int main(void)
293 test_xdp(); 514 test_xdp();
294 test_l4lb(); 515 test_l4lb();
295 test_tcp_estats(); 516 test_tcp_estats();
517 test_bpf_obj_id();
518 test_pkt_md_access();
296 519
297 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt); 520 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt);
298 return 0; 521 return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
299} 522}
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 3773562056da..404aec520812 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -49,6 +49,7 @@
49#define MAX_NR_MAPS 4 49#define MAX_NR_MAPS 4
50 50
51#define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0) 51#define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0)
52#define F_LOAD_WITH_STRICT_ALIGNMENT (1 << 1)
52 53
53struct bpf_test { 54struct bpf_test {
54 const char *descr; 55 const char *descr;
@@ -1072,44 +1073,75 @@ static struct bpf_test tests[] = {
1072 .result = ACCEPT, 1073 .result = ACCEPT,
1073 }, 1074 },
1074 { 1075 {
1075 "check cb access: byte, oob 1", 1076 "__sk_buff->hash, offset 0, byte store not permitted",
1076 .insns = { 1077 .insns = {
1077 BPF_MOV64_IMM(BPF_REG_0, 0), 1078 BPF_MOV64_IMM(BPF_REG_0, 0),
1078 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 1079 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
1079 offsetof(struct __sk_buff, cb[4]) + 4), 1080 offsetof(struct __sk_buff, hash)),
1080 BPF_EXIT_INSN(), 1081 BPF_EXIT_INSN(),
1081 }, 1082 },
1082 .errstr = "invalid bpf_context access", 1083 .errstr = "invalid bpf_context access",
1083 .result = REJECT, 1084 .result = REJECT,
1084 }, 1085 },
1085 { 1086 {
1086 "check cb access: byte, oob 2", 1087 "__sk_buff->tc_index, offset 3, byte store not permitted",
1087 .insns = { 1088 .insns = {
1088 BPF_MOV64_IMM(BPF_REG_0, 0), 1089 BPF_MOV64_IMM(BPF_REG_0, 0),
1089 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 1090 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
1090 offsetof(struct __sk_buff, cb[0]) - 1), 1091 offsetof(struct __sk_buff, tc_index) + 3),
1091 BPF_EXIT_INSN(), 1092 BPF_EXIT_INSN(),
1092 }, 1093 },
1093 .errstr = "invalid bpf_context access", 1094 .errstr = "invalid bpf_context access",
1094 .result = REJECT, 1095 .result = REJECT,
1095 }, 1096 },
1096 { 1097 {
1097 "check cb access: byte, oob 3", 1098 "check skb->hash byte load permitted",
1098 .insns = { 1099 .insns = {
1099 BPF_MOV64_IMM(BPF_REG_0, 0), 1100 BPF_MOV64_IMM(BPF_REG_0, 0),
1101#ifdef __LITTLE_ENDIAN
1100 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 1102 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
1101 offsetof(struct __sk_buff, cb[4]) + 4), 1103 offsetof(struct __sk_buff, hash)),
1104#else
1105 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
1106 offsetof(struct __sk_buff, hash) + 3),
1107#endif
1108 BPF_EXIT_INSN(),
1109 },
1110 .result = ACCEPT,
1111 },
1112 {
1113 "check skb->hash byte load not permitted 1",
1114 .insns = {
1115 BPF_MOV64_IMM(BPF_REG_0, 0),
1116 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
1117 offsetof(struct __sk_buff, hash) + 1),
1102 BPF_EXIT_INSN(), 1118 BPF_EXIT_INSN(),
1103 }, 1119 },
1104 .errstr = "invalid bpf_context access", 1120 .errstr = "invalid bpf_context access",
1105 .result = REJECT, 1121 .result = REJECT,
1106 }, 1122 },
1107 { 1123 {
1108 "check cb access: byte, oob 4", 1124 "check skb->hash byte load not permitted 2",
1109 .insns = { 1125 .insns = {
1110 BPF_MOV64_IMM(BPF_REG_0, 0), 1126 BPF_MOV64_IMM(BPF_REG_0, 0),
1111 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 1127 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
1112 offsetof(struct __sk_buff, cb[0]) - 1), 1128 offsetof(struct __sk_buff, hash) + 2),
1129 BPF_EXIT_INSN(),
1130 },
1131 .errstr = "invalid bpf_context access",
1132 .result = REJECT,
1133 },
1134 {
1135 "check skb->hash byte load not permitted 3",
1136 .insns = {
1137 BPF_MOV64_IMM(BPF_REG_0, 0),
1138#ifdef __LITTLE_ENDIAN
1139 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
1140 offsetof(struct __sk_buff, hash) + 3),
1141#else
1142 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
1143 offsetof(struct __sk_buff, hash)),
1144#endif
1113 BPF_EXIT_INSN(), 1145 BPF_EXIT_INSN(),
1114 }, 1146 },
1115 .errstr = "invalid bpf_context access", 1147 .errstr = "invalid bpf_context access",
@@ -1187,44 +1219,53 @@ static struct bpf_test tests[] = {
1187 .result = REJECT, 1219 .result = REJECT,
1188 }, 1220 },
1189 { 1221 {
1190 "check cb access: half, oob 1", 1222 "check __sk_buff->hash, offset 0, half store not permitted",
1191 .insns = { 1223 .insns = {
1192 BPF_MOV64_IMM(BPF_REG_0, 0), 1224 BPF_MOV64_IMM(BPF_REG_0, 0),
1193 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0, 1225 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1194 offsetof(struct __sk_buff, cb[4]) + 4), 1226 offsetof(struct __sk_buff, hash)),
1195 BPF_EXIT_INSN(), 1227 BPF_EXIT_INSN(),
1196 }, 1228 },
1197 .errstr = "invalid bpf_context access", 1229 .errstr = "invalid bpf_context access",
1198 .result = REJECT, 1230 .result = REJECT,
1199 }, 1231 },
1200 { 1232 {
1201 "check cb access: half, oob 2", 1233 "check __sk_buff->tc_index, offset 2, half store not permitted",
1202 .insns = { 1234 .insns = {
1203 BPF_MOV64_IMM(BPF_REG_0, 0), 1235 BPF_MOV64_IMM(BPF_REG_0, 0),
1204 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0, 1236 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_0,
1205 offsetof(struct __sk_buff, cb[0]) - 2), 1237 offsetof(struct __sk_buff, tc_index) + 2),
1206 BPF_EXIT_INSN(), 1238 BPF_EXIT_INSN(),
1207 }, 1239 },
1208 .errstr = "invalid bpf_context access", 1240 .errstr = "invalid bpf_context access",
1209 .result = REJECT, 1241 .result = REJECT,
1210 }, 1242 },
1211 { 1243 {
1212 "check cb access: half, oob 3", 1244 "check skb->hash half load permitted",
1213 .insns = { 1245 .insns = {
1214 BPF_MOV64_IMM(BPF_REG_0, 0), 1246 BPF_MOV64_IMM(BPF_REG_0, 0),
1247#ifdef __LITTLE_ENDIAN
1248 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1249 offsetof(struct __sk_buff, hash)),
1250#else
1215 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 1251 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1216 offsetof(struct __sk_buff, cb[4]) + 4), 1252 offsetof(struct __sk_buff, hash) + 2),
1253#endif
1217 BPF_EXIT_INSN(), 1254 BPF_EXIT_INSN(),
1218 }, 1255 },
1219 .errstr = "invalid bpf_context access", 1256 .result = ACCEPT,
1220 .result = REJECT,
1221 }, 1257 },
1222 { 1258 {
1223 "check cb access: half, oob 4", 1259 "check skb->hash half load not permitted",
1224 .insns = { 1260 .insns = {
1225 BPF_MOV64_IMM(BPF_REG_0, 0), 1261 BPF_MOV64_IMM(BPF_REG_0, 0),
1262#ifdef __LITTLE_ENDIAN
1226 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1, 1263 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1227 offsetof(struct __sk_buff, cb[0]) - 2), 1264 offsetof(struct __sk_buff, hash) + 2),
1265#else
1266 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
1267 offsetof(struct __sk_buff, hash)),
1268#endif
1228 BPF_EXIT_INSN(), 1269 BPF_EXIT_INSN(),
1229 }, 1270 },
1230 .errstr = "invalid bpf_context access", 1271 .errstr = "invalid bpf_context access",
@@ -1367,28 +1408,6 @@ static struct bpf_test tests[] = {
1367 "check cb access: double, oob 2", 1408 "check cb access: double, oob 2",
1368 .insns = { 1409 .insns = {
1369 BPF_MOV64_IMM(BPF_REG_0, 0), 1410 BPF_MOV64_IMM(BPF_REG_0, 0),
1370 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
1371 offsetof(struct __sk_buff, cb[4]) + 8),
1372 BPF_EXIT_INSN(),
1373 },
1374 .errstr = "invalid bpf_context access",
1375 .result = REJECT,
1376 },
1377 {
1378 "check cb access: double, oob 3",
1379 .insns = {
1380 BPF_MOV64_IMM(BPF_REG_0, 0),
1381 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
1382 offsetof(struct __sk_buff, cb[0]) - 8),
1383 BPF_EXIT_INSN(),
1384 },
1385 .errstr = "invalid bpf_context access",
1386 .result = REJECT,
1387 },
1388 {
1389 "check cb access: double, oob 4",
1390 .insns = {
1391 BPF_MOV64_IMM(BPF_REG_0, 0),
1392 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 1411 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1,
1393 offsetof(struct __sk_buff, cb[4])), 1412 offsetof(struct __sk_buff, cb[4])),
1394 BPF_EXIT_INSN(), 1413 BPF_EXIT_INSN(),
@@ -1397,22 +1416,22 @@ static struct bpf_test tests[] = {
1397 .result = REJECT, 1416 .result = REJECT,
1398 }, 1417 },
1399 { 1418 {
1400 "check cb access: double, oob 5", 1419 "check __sk_buff->ifindex dw store not permitted",
1401 .insns = { 1420 .insns = {
1402 BPF_MOV64_IMM(BPF_REG_0, 0), 1421 BPF_MOV64_IMM(BPF_REG_0, 0),
1403 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 1422 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
1404 offsetof(struct __sk_buff, cb[4]) + 8), 1423 offsetof(struct __sk_buff, ifindex)),
1405 BPF_EXIT_INSN(), 1424 BPF_EXIT_INSN(),
1406 }, 1425 },
1407 .errstr = "invalid bpf_context access", 1426 .errstr = "invalid bpf_context access",
1408 .result = REJECT, 1427 .result = REJECT,
1409 }, 1428 },
1410 { 1429 {
1411 "check cb access: double, oob 6", 1430 "check __sk_buff->ifindex dw load not permitted",
1412 .insns = { 1431 .insns = {
1413 BPF_MOV64_IMM(BPF_REG_0, 0), 1432 BPF_MOV64_IMM(BPF_REG_0, 0),
1414 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 1433 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1,
1415 offsetof(struct __sk_buff, cb[0]) - 8), 1434 offsetof(struct __sk_buff, ifindex)),
1416 BPF_EXIT_INSN(), 1435 BPF_EXIT_INSN(),
1417 }, 1436 },
1418 .errstr = "invalid bpf_context access", 1437 .errstr = "invalid bpf_context access",
@@ -2615,6 +2634,195 @@ static struct bpf_test tests[] = {
2615 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2634 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2616 }, 2635 },
2617 { 2636 {
2637 "direct packet access: test17 (pruning, alignment)",
2638 .insns = {
2639 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2640 offsetof(struct __sk_buff, data)),
2641 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2642 offsetof(struct __sk_buff, data_end)),
2643 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
2644 offsetof(struct __sk_buff, mark)),
2645 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
2646 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 14),
2647 BPF_JMP_IMM(BPF_JGT, BPF_REG_7, 1, 4),
2648 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
2649 BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, -4),
2650 BPF_MOV64_IMM(BPF_REG_0, 0),
2651 BPF_EXIT_INSN(),
2652 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
2653 BPF_JMP_A(-6),
2654 },
2655 .errstr = "misaligned packet access off 2+15+-4 size 4",
2656 .result = REJECT,
2657 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2658 .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
2659 },
2660 {
2661 "direct packet access: test18 (imm += pkt_ptr, 1)",
2662 .insns = {
2663 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2664 offsetof(struct __sk_buff, data)),
2665 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2666 offsetof(struct __sk_buff, data_end)),
2667 BPF_MOV64_IMM(BPF_REG_0, 8),
2668 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
2669 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
2670 BPF_STX_MEM(BPF_B, BPF_REG_2, BPF_REG_2, 0),
2671 BPF_MOV64_IMM(BPF_REG_0, 0),
2672 BPF_EXIT_INSN(),
2673 },
2674 .result = ACCEPT,
2675 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2676 },
2677 {
2678 "direct packet access: test19 (imm += pkt_ptr, 2)",
2679 .insns = {
2680 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2681 offsetof(struct __sk_buff, data)),
2682 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2683 offsetof(struct __sk_buff, data_end)),
2684 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
2685 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
2686 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 3),
2687 BPF_MOV64_IMM(BPF_REG_4, 4),
2688 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2),
2689 BPF_STX_MEM(BPF_B, BPF_REG_4, BPF_REG_4, 0),
2690 BPF_MOV64_IMM(BPF_REG_0, 0),
2691 BPF_EXIT_INSN(),
2692 },
2693 .result = ACCEPT,
2694 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2695 },
2696 {
2697 "direct packet access: test20 (x += pkt_ptr, 1)",
2698 .insns = {
2699 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2700 offsetof(struct __sk_buff, data)),
2701 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2702 offsetof(struct __sk_buff, data_end)),
2703 BPF_MOV64_IMM(BPF_REG_0, 0xffffffff),
2704 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
2705 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
2706 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffff),
2707 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
2708 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2),
2709 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4),
2710 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0xffff - 1),
2711 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1),
2712 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
2713 BPF_MOV64_IMM(BPF_REG_0, 0),
2714 BPF_EXIT_INSN(),
2715 },
2716 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2717 .result = ACCEPT,
2718 },
2719 {
2720 "direct packet access: test21 (x += pkt_ptr, 2)",
2721 .insns = {
2722 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2723 offsetof(struct __sk_buff, data)),
2724 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2725 offsetof(struct __sk_buff, data_end)),
2726 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
2727 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
2728 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 9),
2729 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff),
2730 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_4, -8),
2731 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8),
2732 BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 0xffff),
2733 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2),
2734 BPF_MOV64_REG(BPF_REG_5, BPF_REG_4),
2735 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 0xffff - 1),
2736 BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 1),
2737 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
2738 BPF_MOV64_IMM(BPF_REG_0, 0),
2739 BPF_EXIT_INSN(),
2740 },
2741 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2742 .result = ACCEPT,
2743 },
2744 {
2745 "direct packet access: test22 (x += pkt_ptr, 3)",
2746 .insns = {
2747 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2748 offsetof(struct __sk_buff, data)),
2749 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2750 offsetof(struct __sk_buff, data_end)),
2751 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
2752 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
2753 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -8),
2754 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_3, -16),
2755 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_10, -16),
2756 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 11),
2757 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -8),
2758 BPF_MOV64_IMM(BPF_REG_4, 0xffffffff),
2759 BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_4, -8),
2760 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8),
2761 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 48),
2762 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2),
2763 BPF_MOV64_REG(BPF_REG_0, BPF_REG_4),
2764 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2),
2765 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 2),
2766 BPF_MOV64_IMM(BPF_REG_2, 1),
2767 BPF_STX_MEM(BPF_H, BPF_REG_4, BPF_REG_2, 0),
2768 BPF_MOV64_IMM(BPF_REG_0, 0),
2769 BPF_EXIT_INSN(),
2770 },
2771 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2772 .result = ACCEPT,
2773 },
2774 {
2775 "direct packet access: test23 (x += pkt_ptr, 4)",
2776 .insns = {
2777 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2778 offsetof(struct __sk_buff, data)),
2779 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2780 offsetof(struct __sk_buff, data_end)),
2781 BPF_MOV64_IMM(BPF_REG_0, 0xffffffff),
2782 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
2783 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
2784 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffff),
2785 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
2786 BPF_MOV64_IMM(BPF_REG_0, 31),
2787 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_4),
2788 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
2789 BPF_MOV64_REG(BPF_REG_5, BPF_REG_0),
2790 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0xffff - 1),
2791 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
2792 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_0, 0),
2793 BPF_MOV64_IMM(BPF_REG_0, 0),
2794 BPF_EXIT_INSN(),
2795 },
2796 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2797 .result = REJECT,
2798 .errstr = "cannot add integer value with 47 upper zero bits to ptr_to_packet",
2799 },
2800 {
2801 "direct packet access: test24 (x += pkt_ptr, 5)",
2802 .insns = {
2803 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2804 offsetof(struct __sk_buff, data)),
2805 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2806 offsetof(struct __sk_buff, data_end)),
2807 BPF_MOV64_IMM(BPF_REG_0, 0xffffffff),
2808 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
2809 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
2810 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xff),
2811 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
2812 BPF_MOV64_IMM(BPF_REG_0, 64),
2813 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_4),
2814 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
2815 BPF_MOV64_REG(BPF_REG_5, BPF_REG_0),
2816 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0xffff - 1),
2817 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
2818 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_0, 0),
2819 BPF_MOV64_IMM(BPF_REG_0, 0),
2820 BPF_EXIT_INSN(),
2821 },
2822 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2823 .result = ACCEPT,
2824 },
2825 {
2618 "helper access to packet: test1, valid packet_ptr range", 2826 "helper access to packet: test1, valid packet_ptr range",
2619 .insns = { 2827 .insns = {
2620 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 2828 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
@@ -3341,6 +3549,70 @@ static struct bpf_test tests[] = {
3341 .prog_type = BPF_PROG_TYPE_SCHED_CLS 3549 .prog_type = BPF_PROG_TYPE_SCHED_CLS
3342 }, 3550 },
3343 { 3551 {
3552 "alu ops on ptr_to_map_value_or_null, 1",
3553 .insns = {
3554 BPF_MOV64_IMM(BPF_REG_1, 10),
3555 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
3556 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3557 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3558 BPF_LD_MAP_FD(BPF_REG_1, 0),
3559 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
3560 BPF_FUNC_map_lookup_elem),
3561 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
3562 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -2),
3563 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2),
3564 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
3565 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
3566 BPF_EXIT_INSN(),
3567 },
3568 .fixup_map1 = { 4 },
3569 .errstr = "R4 invalid mem access",
3570 .result = REJECT,
3571 .prog_type = BPF_PROG_TYPE_SCHED_CLS
3572 },
3573 {
3574 "alu ops on ptr_to_map_value_or_null, 2",
3575 .insns = {
3576 BPF_MOV64_IMM(BPF_REG_1, 10),
3577 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
3578 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3579 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3580 BPF_LD_MAP_FD(BPF_REG_1, 0),
3581 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
3582 BPF_FUNC_map_lookup_elem),
3583 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
3584 BPF_ALU64_IMM(BPF_AND, BPF_REG_4, -1),
3585 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
3586 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
3587 BPF_EXIT_INSN(),
3588 },
3589 .fixup_map1 = { 4 },
3590 .errstr = "R4 invalid mem access",
3591 .result = REJECT,
3592 .prog_type = BPF_PROG_TYPE_SCHED_CLS
3593 },
3594 {
3595 "alu ops on ptr_to_map_value_or_null, 3",
3596 .insns = {
3597 BPF_MOV64_IMM(BPF_REG_1, 10),
3598 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
3599 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3600 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3601 BPF_LD_MAP_FD(BPF_REG_1, 0),
3602 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
3603 BPF_FUNC_map_lookup_elem),
3604 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
3605 BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 1),
3606 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
3607 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
3608 BPF_EXIT_INSN(),
3609 },
3610 .fixup_map1 = { 4 },
3611 .errstr = "R4 invalid mem access",
3612 .result = REJECT,
3613 .prog_type = BPF_PROG_TYPE_SCHED_CLS
3614 },
3615 {
3344 "invalid memory access with multiple map_lookup_elem calls", 3616 "invalid memory access with multiple map_lookup_elem calls",
3345 .insns = { 3617 .insns = {
3346 BPF_MOV64_IMM(BPF_REG_1, 10), 3618 BPF_MOV64_IMM(BPF_REG_1, 10),
@@ -3660,6 +3932,72 @@ static struct bpf_test tests[] = {
3660 .errstr = "invalid bpf_context access", 3932 .errstr = "invalid bpf_context access",
3661 }, 3933 },
3662 { 3934 {
3935 "leak pointer into ctx 1",
3936 .insns = {
3937 BPF_MOV64_IMM(BPF_REG_0, 0),
3938 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
3939 offsetof(struct __sk_buff, cb[0])),
3940 BPF_LD_MAP_FD(BPF_REG_2, 0),
3941 BPF_STX_XADD(BPF_DW, BPF_REG_1, BPF_REG_2,
3942 offsetof(struct __sk_buff, cb[0])),
3943 BPF_EXIT_INSN(),
3944 },
3945 .fixup_map1 = { 2 },
3946 .errstr_unpriv = "R2 leaks addr into mem",
3947 .result_unpriv = REJECT,
3948 .result = ACCEPT,
3949 },
3950 {
3951 "leak pointer into ctx 2",
3952 .insns = {
3953 BPF_MOV64_IMM(BPF_REG_0, 0),
3954 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
3955 offsetof(struct __sk_buff, cb[0])),
3956 BPF_STX_XADD(BPF_DW, BPF_REG_1, BPF_REG_10,
3957 offsetof(struct __sk_buff, cb[0])),
3958 BPF_EXIT_INSN(),
3959 },
3960 .errstr_unpriv = "R10 leaks addr into mem",
3961 .result_unpriv = REJECT,
3962 .result = ACCEPT,
3963 },
3964 {
3965 "leak pointer into ctx 3",
3966 .insns = {
3967 BPF_MOV64_IMM(BPF_REG_0, 0),
3968 BPF_LD_MAP_FD(BPF_REG_2, 0),
3969 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2,
3970 offsetof(struct __sk_buff, cb[0])),
3971 BPF_EXIT_INSN(),
3972 },
3973 .fixup_map1 = { 1 },
3974 .errstr_unpriv = "R2 leaks addr into ctx",
3975 .result_unpriv = REJECT,
3976 .result = ACCEPT,
3977 },
3978 {
3979 "leak pointer into map val",
3980 .insns = {
3981 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
3982 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
3983 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3984 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
3985 BPF_LD_MAP_FD(BPF_REG_1, 0),
3986 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
3987 BPF_FUNC_map_lookup_elem),
3988 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
3989 BPF_MOV64_IMM(BPF_REG_3, 0),
3990 BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_3, 0),
3991 BPF_STX_XADD(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
3992 BPF_MOV64_IMM(BPF_REG_0, 0),
3993 BPF_EXIT_INSN(),
3994 },
3995 .fixup_map1 = { 4 },
3996 .errstr_unpriv = "R6 leaks addr into mem",
3997 .result_unpriv = REJECT,
3998 .result = ACCEPT,
3999 },
4000 {
3663 "helper access to map: full range", 4001 "helper access to map: full range",
3664 .insns = { 4002 .insns = {
3665 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 4003 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -4937,7 +5275,241 @@ static struct bpf_test tests[] = {
4937 .fixup_map_in_map = { 3 }, 5275 .fixup_map_in_map = { 3 },
4938 .errstr = "R1 type=map_value_or_null expected=map_ptr", 5276 .errstr = "R1 type=map_value_or_null expected=map_ptr",
4939 .result = REJECT, 5277 .result = REJECT,
4940 } 5278 },
5279 {
5280 "ld_abs: check calling conv, r1",
5281 .insns = {
5282 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
5283 BPF_MOV64_IMM(BPF_REG_1, 0),
5284 BPF_LD_ABS(BPF_W, -0x200000),
5285 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
5286 BPF_EXIT_INSN(),
5287 },
5288 .errstr = "R1 !read_ok",
5289 .result = REJECT,
5290 },
5291 {
5292 "ld_abs: check calling conv, r2",
5293 .insns = {
5294 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
5295 BPF_MOV64_IMM(BPF_REG_2, 0),
5296 BPF_LD_ABS(BPF_W, -0x200000),
5297 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
5298 BPF_EXIT_INSN(),
5299 },
5300 .errstr = "R2 !read_ok",
5301 .result = REJECT,
5302 },
5303 {
5304 "ld_abs: check calling conv, r3",
5305 .insns = {
5306 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
5307 BPF_MOV64_IMM(BPF_REG_3, 0),
5308 BPF_LD_ABS(BPF_W, -0x200000),
5309 BPF_MOV64_REG(BPF_REG_0, BPF_REG_3),
5310 BPF_EXIT_INSN(),
5311 },
5312 .errstr = "R3 !read_ok",
5313 .result = REJECT,
5314 },
5315 {
5316 "ld_abs: check calling conv, r4",
5317 .insns = {
5318 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
5319 BPF_MOV64_IMM(BPF_REG_4, 0),
5320 BPF_LD_ABS(BPF_W, -0x200000),
5321 BPF_MOV64_REG(BPF_REG_0, BPF_REG_4),
5322 BPF_EXIT_INSN(),
5323 },
5324 .errstr = "R4 !read_ok",
5325 .result = REJECT,
5326 },
5327 {
5328 "ld_abs: check calling conv, r5",
5329 .insns = {
5330 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
5331 BPF_MOV64_IMM(BPF_REG_5, 0),
5332 BPF_LD_ABS(BPF_W, -0x200000),
5333 BPF_MOV64_REG(BPF_REG_0, BPF_REG_5),
5334 BPF_EXIT_INSN(),
5335 },
5336 .errstr = "R5 !read_ok",
5337 .result = REJECT,
5338 },
5339 {
5340 "ld_abs: check calling conv, r7",
5341 .insns = {
5342 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
5343 BPF_MOV64_IMM(BPF_REG_7, 0),
5344 BPF_LD_ABS(BPF_W, -0x200000),
5345 BPF_MOV64_REG(BPF_REG_0, BPF_REG_7),
5346 BPF_EXIT_INSN(),
5347 },
5348 .result = ACCEPT,
5349 },
5350 {
5351 "ld_ind: check calling conv, r1",
5352 .insns = {
5353 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
5354 BPF_MOV64_IMM(BPF_REG_1, 1),
5355 BPF_LD_IND(BPF_W, BPF_REG_1, -0x200000),
5356 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
5357 BPF_EXIT_INSN(),
5358 },
5359 .errstr = "R1 !read_ok",
5360 .result = REJECT,
5361 },
5362 {
5363 "ld_ind: check calling conv, r2",
5364 .insns = {
5365 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
5366 BPF_MOV64_IMM(BPF_REG_2, 1),
5367 BPF_LD_IND(BPF_W, BPF_REG_2, -0x200000),
5368 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
5369 BPF_EXIT_INSN(),
5370 },
5371 .errstr = "R2 !read_ok",
5372 .result = REJECT,
5373 },
5374 {
5375 "ld_ind: check calling conv, r3",
5376 .insns = {
5377 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
5378 BPF_MOV64_IMM(BPF_REG_3, 1),
5379 BPF_LD_IND(BPF_W, BPF_REG_3, -0x200000),
5380 BPF_MOV64_REG(BPF_REG_0, BPF_REG_3),
5381 BPF_EXIT_INSN(),
5382 },
5383 .errstr = "R3 !read_ok",
5384 .result = REJECT,
5385 },
5386 {
5387 "ld_ind: check calling conv, r4",
5388 .insns = {
5389 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
5390 BPF_MOV64_IMM(BPF_REG_4, 1),
5391 BPF_LD_IND(BPF_W, BPF_REG_4, -0x200000),
5392 BPF_MOV64_REG(BPF_REG_0, BPF_REG_4),
5393 BPF_EXIT_INSN(),
5394 },
5395 .errstr = "R4 !read_ok",
5396 .result = REJECT,
5397 },
5398 {
5399 "ld_ind: check calling conv, r5",
5400 .insns = {
5401 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
5402 BPF_MOV64_IMM(BPF_REG_5, 1),
5403 BPF_LD_IND(BPF_W, BPF_REG_5, -0x200000),
5404 BPF_MOV64_REG(BPF_REG_0, BPF_REG_5),
5405 BPF_EXIT_INSN(),
5406 },
5407 .errstr = "R5 !read_ok",
5408 .result = REJECT,
5409 },
5410 {
5411 "ld_ind: check calling conv, r7",
5412 .insns = {
5413 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
5414 BPF_MOV64_IMM(BPF_REG_7, 1),
5415 BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000),
5416 BPF_MOV64_REG(BPF_REG_0, BPF_REG_7),
5417 BPF_EXIT_INSN(),
5418 },
5419 .result = ACCEPT,
5420 },
5421 {
5422 "check bpf_perf_event_data->sample_period byte load permitted",
5423 .insns = {
5424 BPF_MOV64_IMM(BPF_REG_0, 0),
5425#ifdef __LITTLE_ENDIAN
5426 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
5427 offsetof(struct bpf_perf_event_data, sample_period)),
5428#else
5429 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
5430 offsetof(struct bpf_perf_event_data, sample_period) + 7),
5431#endif
5432 BPF_EXIT_INSN(),
5433 },
5434 .result = ACCEPT,
5435 .prog_type = BPF_PROG_TYPE_PERF_EVENT,
5436 },
5437 {
5438 "check bpf_perf_event_data->sample_period half load permitted",
5439 .insns = {
5440 BPF_MOV64_IMM(BPF_REG_0, 0),
5441#ifdef __LITTLE_ENDIAN
5442 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
5443 offsetof(struct bpf_perf_event_data, sample_period)),
5444#else
5445 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
5446 offsetof(struct bpf_perf_event_data, sample_period) + 6),
5447#endif
5448 BPF_EXIT_INSN(),
5449 },
5450 .result = ACCEPT,
5451 .prog_type = BPF_PROG_TYPE_PERF_EVENT,
5452 },
5453 {
5454 "check bpf_perf_event_data->sample_period word load permitted",
5455 .insns = {
5456 BPF_MOV64_IMM(BPF_REG_0, 0),
5457#ifdef __LITTLE_ENDIAN
5458 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
5459 offsetof(struct bpf_perf_event_data, sample_period)),
5460#else
5461 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
5462 offsetof(struct bpf_perf_event_data, sample_period) + 4),
5463#endif
5464 BPF_EXIT_INSN(),
5465 },
5466 .result = ACCEPT,
5467 .prog_type = BPF_PROG_TYPE_PERF_EVENT,
5468 },
5469 {
5470 "check bpf_perf_event_data->sample_period dword load permitted",
5471 .insns = {
5472 BPF_MOV64_IMM(BPF_REG_0, 0),
5473 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1,
5474 offsetof(struct bpf_perf_event_data, sample_period)),
5475 BPF_EXIT_INSN(),
5476 },
5477 .result = ACCEPT,
5478 .prog_type = BPF_PROG_TYPE_PERF_EVENT,
5479 },
5480 {
5481 "check skb->data half load not permitted",
5482 .insns = {
5483 BPF_MOV64_IMM(BPF_REG_0, 0),
5484#ifdef __LITTLE_ENDIAN
5485 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
5486 offsetof(struct __sk_buff, data)),
5487#else
5488 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
5489 offsetof(struct __sk_buff, data) + 2),
5490#endif
5491 BPF_EXIT_INSN(),
5492 },
5493 .result = REJECT,
5494 .errstr = "invalid bpf_context access",
5495 },
5496 {
5497 "check skb->tc_classid half load not permitted for lwt prog",
5498 .insns = {
5499 BPF_MOV64_IMM(BPF_REG_0, 0),
5500#ifdef __LITTLE_ENDIAN
5501 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
5502 offsetof(struct __sk_buff, tc_classid)),
5503#else
5504 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_1,
5505 offsetof(struct __sk_buff, tc_classid) + 2),
5506#endif
5507 BPF_EXIT_INSN(),
5508 },
5509 .result = REJECT,
5510 .errstr = "invalid bpf_context access",
5511 .prog_type = BPF_PROG_TYPE_LWT_IN,
5512 },
4941}; 5513};
4942 5514
4943static int probe_filter_length(const struct bpf_insn *fp) 5515static int probe_filter_length(const struct bpf_insn *fp)
@@ -5059,9 +5631,9 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
5059 5631
5060 do_test_fixup(test, prog, map_fds); 5632 do_test_fixup(test, prog, map_fds);
5061 5633
5062 fd_prog = bpf_load_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, 5634 fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
5063 prog, prog_len, "GPL", 0, bpf_vlog, 5635 prog, prog_len, test->flags & F_LOAD_WITH_STRICT_ALIGNMENT,
5064 sizeof(bpf_vlog)); 5636 "GPL", 0, bpf_vlog, sizeof(bpf_vlog));
5065 5637
5066 expected_ret = unpriv && test->result_unpriv != UNDEF ? 5638 expected_ret = unpriv && test->result_unpriv != UNDEF ?
5067 test->result_unpriv : test->result; 5639 test->result_unpriv : test->result;
@@ -5187,7 +5759,7 @@ static int do_test(bool unpriv, unsigned int from, unsigned int to)
5187 } 5759 }
5188 5760
5189 printf("Summary: %d PASSED, %d FAILED\n", passes, errors); 5761 printf("Summary: %d PASSED, %d FAILED\n", passes, errors);
5190 return errors ? -errors : 0; 5762 return errors ? EXIT_FAILURE : EXIT_SUCCESS;
5191} 5763}
5192 5764
5193int main(int argc, char **argv) 5765int main(int argc, char **argv)
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index 32e6211e1c6e..717581145cfc 100755
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -58,7 +58,7 @@ parse_opts() { # opts
58 ;; 58 ;;
59 --verbose|-v|-vv) 59 --verbose|-v|-vv)
60 VERBOSE=$((VERBOSE + 1)) 60 VERBOSE=$((VERBOSE + 1))
61 [ $1 == '-vv' ] && VERBOSE=$((VERBOSE + 1)) 61 [ $1 = '-vv' ] && VERBOSE=$((VERBOSE + 1))
62 shift 1 62 shift 1
63 ;; 63 ;;
64 --debug|-d) 64 --debug|-d)
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc
index 07bb3e5930b4..aa31368851c9 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc
@@ -48,7 +48,7 @@ test_event_enabled() {
48 e=`cat $EVENT_ENABLE` 48 e=`cat $EVENT_ENABLE`
49 if [ "$e" != $val ]; then 49 if [ "$e" != $val ]; then
50 echo "Expected $val but found $e" 50 echo "Expected $val but found $e"
51 exit -1 51 exit 1
52 fi 52 fi
53} 53}
54 54
diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions
index 9aec6fcb7729..f2019b37370d 100644
--- a/tools/testing/selftests/ftrace/test.d/functions
+++ b/tools/testing/selftests/ftrace/test.d/functions
@@ -34,10 +34,10 @@ reset_ftrace_filter() { # reset all triggers in set_ftrace_filter
34 echo > set_ftrace_filter 34 echo > set_ftrace_filter
35 grep -v '^#' set_ftrace_filter | while read t; do 35 grep -v '^#' set_ftrace_filter | while read t; do
36 tr=`echo $t | cut -d: -f2` 36 tr=`echo $t | cut -d: -f2`
37 if [ "$tr" == "" ]; then 37 if [ "$tr" = "" ]; then
38 continue 38 continue
39 fi 39 fi
40 if [ $tr == "enable_event" -o $tr == "disable_event" ]; then 40 if [ $tr = "enable_event" -o $tr = "disable_event" ]; then
41 tr=`echo $t | cut -d: -f1-4` 41 tr=`echo $t | cut -d: -f1-4`
42 limit=`echo $t | cut -d: -f5` 42 limit=`echo $t | cut -d: -f5`
43 else 43 else
diff --git a/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
index 4c5a061a5b4e..c73db7863adb 100644
--- a/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
+++ b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
@@ -75,9 +75,13 @@ rmdir foo
75if [ -d foo ]; then 75if [ -d foo ]; then
76 fail "foo still exists" 76 fail "foo still exists"
77fi 77fi
78exit 0
79
80 78
79mkdir foo
80echo "schedule:enable_event:sched:sched_switch" > foo/set_ftrace_filter
81rmdir foo
82if [ -d foo ]; then
83 fail "foo still exists"
84fi
81 85
82 86
83instance_slam() { 87instance_slam() {
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
new file mode 100644
index 000000000000..f4d1ff785d67
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
@@ -0,0 +1,21 @@
1#!/bin/sh
2# description: Register/unregister many kprobe events
3
4# ftrace fentry skip size depends on the machine architecture.
5# Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc
6case `uname -m` in
7 x86_64|i[3456]86) OFFS=5;;
8 ppc*) OFFS=4;;
9 *) OFFS=0;;
10esac
11
12echo "Setup up to 256 kprobes"
13grep t /proc/kallsyms | cut -f3 -d" " | grep -v .*\\..* | \
14head -n 256 | while read i; do echo p ${i}+${OFFS} ; done > kprobe_events ||:
15
16echo 1 > events/kprobes/enable
17echo 0 > events/kprobes/enable
18echo > kprobe_events
19echo "Waiting for unoptimizing & freeing"
20sleep 5
21echo "Done"
diff --git a/tools/testing/selftests/ntb/ntb_test.sh b/tools/testing/selftests/ntb/ntb_test.sh
index a676d3eefefb..13f5198ba0ee 100755
--- a/tools/testing/selftests/ntb/ntb_test.sh
+++ b/tools/testing/selftests/ntb/ntb_test.sh
@@ -305,7 +305,7 @@ function perf_test()
305 echo "Running remote perf test $WITH DMA" 305 echo "Running remote perf test $WITH DMA"
306 write_file "" $REMOTE_PERF/run 306 write_file "" $REMOTE_PERF/run
307 echo -n " " 307 echo -n " "
308 read_file $LOCAL_PERF/run 308 read_file $REMOTE_PERF/run
309 echo " Passed" 309 echo " Passed"
310 310
311 _modprobe -r ntb_perf 311 _modprobe -r ntb_perf
diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore
index 427621792229..2f1f7b013293 100644
--- a/tools/testing/selftests/powerpc/tm/.gitignore
+++ b/tools/testing/selftests/powerpc/tm/.gitignore
@@ -11,3 +11,4 @@ tm-signal-context-chk-fpu
11tm-signal-context-chk-gpr 11tm-signal-context-chk-gpr
12tm-signal-context-chk-vmx 12tm-signal-context-chk-vmx
13tm-signal-context-chk-vsx 13tm-signal-context-chk-vsx
14tm-vmx-unavail
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 5576ee6a51f2..958c11c14acd 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -2,7 +2,8 @@ SIGNAL_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_GEN_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 tm-vmx-unavail \
6 $(SIGNAL_CONTEXT_CHK_TESTS)
6 7
7include ../../lib.mk 8include ../../lib.mk
8 9
@@ -13,6 +14,7 @@ CFLAGS += -mhtm
13$(OUTPUT)/tm-syscall: tm-syscall-asm.S 14$(OUTPUT)/tm-syscall: tm-syscall-asm.S
14$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include 15$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include
15$(OUTPUT)/tm-tmspr: CFLAGS += -pthread 16$(OUTPUT)/tm-tmspr: CFLAGS += -pthread
17$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64
16 18
17SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS)) 19SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS))
18$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S 20$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
diff --git a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
index d9c49f41515e..e79ccd6aada1 100644
--- a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
@@ -42,12 +42,12 @@ int test_body(void)
42 printf("Check DSCR TM context switch: "); 42 printf("Check DSCR TM context switch: ");
43 fflush(stdout); 43 fflush(stdout);
44 for (;;) { 44 for (;;) {
45 rv = 1;
46 asm __volatile__ ( 45 asm __volatile__ (
47 /* set a known value into the DSCR */ 46 /* set a known value into the DSCR */
48 "ld 3, %[dscr1];" 47 "ld 3, %[dscr1];"
49 "mtspr %[sprn_dscr], 3;" 48 "mtspr %[sprn_dscr], 3;"
50 49
50 "li %[rv], 1;"
51 /* start and suspend a transaction */ 51 /* start and suspend a transaction */
52 "tbegin.;" 52 "tbegin.;"
53 "beq 1f;" 53 "beq 1f;"
diff --git a/tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c b/tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c
new file mode 100644
index 000000000000..137185ba4937
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c
@@ -0,0 +1,118 @@
1/*
2 * Copyright 2017, Michael Neuling, IBM Corp.
3 * Licensed under GPLv2.
4 * Original: Breno Leitao <brenohl@br.ibm.com> &
5 * Gustavo Bueno Romero <gromero@br.ibm.com>
6 * Edited: Michael Neuling
7 *
8 * Force VMX unavailable during a transaction and see if it corrupts
9 * the checkpointed VMX register state after the abort.
10 */
11
12#include <inttypes.h>
13#include <htmintrin.h>
14#include <string.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <pthread.h>
18#include <sys/mman.h>
19#include <unistd.h>
20#include <pthread.h>
21
22#include "tm.h"
23#include "utils.h"
24
25int passed;
26
27void *worker(void *unused)
28{
29 __int128 vmx0;
30 uint64_t texasr;
31
32 asm goto (
33 "li 3, 1;" /* Stick non-zero value in VMX0 */
34 "std 3, 0(%[vmx0_ptr]);"
35 "lvx 0, 0, %[vmx0_ptr];"
36
37 /* Wait here a bit so we get scheduled out 255 times */
38 "lis 3, 0x3fff;"
39 "1: ;"
40 "addi 3, 3, -1;"
41 "cmpdi 3, 0;"
42 "bne 1b;"
43
44 /* Kernel will hopefully turn VMX off now */
45
46 "tbegin. ;"
47 "beq failure;"
48
49 /* Cause VMX unavail. Any VMX instruction */
50 "vaddcuw 0,0,0;"
51
52 "tend. ;"
53 "b %l[success];"
54
55 /* Check VMX0 sanity after abort */
56 "failure: ;"
57 "lvx 1, 0, %[vmx0_ptr];"
58 "vcmpequb. 2, 0, 1;"
59 "bc 4, 24, %l[value_mismatch];"
60 "b %l[value_match];"
61 :
62 : [vmx0_ptr] "r"(&vmx0)
63 : "r3"
64 : success, value_match, value_mismatch
65 );
66
67 /* HTM aborted and VMX0 is corrupted */
68value_mismatch:
69 texasr = __builtin_get_texasr();
70
71 printf("\n\n==============\n\n");
72 printf("Failure with error: %lx\n", _TEXASR_FAILURE_CODE(texasr));
73 printf("Summary error : %lx\n", _TEXASR_FAILURE_SUMMARY(texasr));
74 printf("TFIAR exact : %lx\n\n", _TEXASR_TFIAR_EXACT(texasr));
75
76 passed = 0;
77 return NULL;
78
79 /* HTM aborted but VMX0 is correct */
80value_match:
81// printf("!");
82 return NULL;
83
84success:
85// printf(".");
86 return NULL;
87}
88
89int tm_vmx_unavail_test()
90{
91 int threads;
92 pthread_t *thread;
93
94 SKIP_IF(!have_htm());
95
96 passed = 1;
97
98 threads = sysconf(_SC_NPROCESSORS_ONLN) * 4;
99 thread = malloc(sizeof(pthread_t)*threads);
100 if (!thread)
101 return EXIT_FAILURE;
102
103 for (uint64_t i = 0; i < threads; i++)
104 pthread_create(&thread[i], NULL, &worker, NULL);
105
106 for (uint64_t i = 0; i < threads; i++)
107 pthread_join(thread[i], NULL);
108
109 free(thread);
110
111 return passed ? EXIT_SUCCESS : EXIT_FAILURE;
112}
113
114
115int main(int argc, char **argv)
116{
117 return test_harness(tm_vmx_unavail_test, "tm_vmx_unavail_test");
118}
diff --git a/tools/testing/selftests/rcutorture/bin/configcheck.sh b/tools/testing/selftests/rcutorture/bin/configcheck.sh
index eee31e261bf7..70fca318a82b 100755
--- a/tools/testing/selftests/rcutorture/bin/configcheck.sh
+++ b/tools/testing/selftests/rcutorture/bin/configcheck.sh
@@ -27,7 +27,7 @@ cat $1 > $T/.config
27 27
28cat $2 | sed -e 's/\(.*\)=n/# \1 is not set/' -e 's/^#CHECK#//' | 28cat $2 | sed -e 's/\(.*\)=n/# \1 is not set/' -e 's/^#CHECK#//' |
29awk ' 29awk '
30BEGIN { 30{
31 print "if grep -q \"" $0 "\" < '"$T/.config"'"; 31 print "if grep -q \"" $0 "\" < '"$T/.config"'";
32 print "then"; 32 print "then";
33 print "\t:"; 33 print "\t:";
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-build.sh b/tools/testing/selftests/rcutorture/bin/kvm-build.sh
index 00cb0db2643d..c29f2ec0bf9f 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-build.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-build.sh
@@ -45,7 +45,7 @@ T=/tmp/test-linux.sh.$$
45trap 'rm -rf $T' 0 45trap 'rm -rf $T' 0
46mkdir $T 46mkdir $T
47 47
48grep -v 'CONFIG_[A-Z]*_TORTURE_TEST' < ${config_template} > $T/config 48grep -v 'CONFIG_[A-Z]*_TORTURE_TEST=' < ${config_template} > $T/config
49cat << ___EOF___ >> $T/config 49cat << ___EOF___ >> $T/config
50CONFIG_INITRAMFS_SOURCE="$TORTURE_INITRD" 50CONFIG_INITRAMFS_SOURCE="$TORTURE_INITRD"
51CONFIG_VIRTIO_PCI=y 51CONFIG_VIRTIO_PCI=y
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 3b3c1b693ee1..50091de3a911 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -296,10 +296,7 @@ if test -d .git
296then 296then
297 git status >> $resdir/$ds/testid.txt 297 git status >> $resdir/$ds/testid.txt
298 git rev-parse HEAD >> $resdir/$ds/testid.txt 298 git rev-parse HEAD >> $resdir/$ds/testid.txt
299 if ! git diff HEAD > $T/git-diff 2>&1 299 git diff HEAD >> $resdir/$ds/testid.txt
300 then
301 cp $T/git-diff $resdir/$ds
302 fi
303fi 300fi
304___EOF___ 301___EOF___
305awk < $T/cfgcpu.pack \ 302awk < $T/cfgcpu.pack \
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
index a3a1a05a2b5c..6a0b9f69faad 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
@@ -9,6 +9,8 @@ TREE08
9TREE09 9TREE09
10SRCU-N 10SRCU-N
11SRCU-P 11SRCU-P
12SRCU-t
13SRCU-u
12TINY01 14TINY01
13TINY02 15TINY02
14TASKS01 16TASKS01
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-C.boot b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-C.boot
new file mode 100644
index 000000000000..84a7d51b7481
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-C.boot
@@ -0,0 +1 @@
rcutorture.torture_type=srcud
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N
index 1a087c3c8bb8..2da8b49589a0 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N
@@ -5,4 +5,4 @@ CONFIG_HOTPLUG_CPU=y
5CONFIG_PREEMPT_NONE=y 5CONFIG_PREEMPT_NONE=y
6CONFIG_PREEMPT_VOLUNTARY=n 6CONFIG_PREEMPT_VOLUNTARY=n
7CONFIG_PREEMPT=n 7CONFIG_PREEMPT=n
8CONFIG_RCU_EXPERT=y 8#CHECK#CONFIG_RCU_EXPERT=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P
index 4837430a71c0..ab7ccd38232b 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P
@@ -2,7 +2,11 @@ CONFIG_RCU_TRACE=n
2CONFIG_SMP=y 2CONFIG_SMP=y
3CONFIG_NR_CPUS=8 3CONFIG_NR_CPUS=8
4CONFIG_HOTPLUG_CPU=y 4CONFIG_HOTPLUG_CPU=y
5CONFIG_RCU_EXPERT=y
6CONFIG_RCU_FANOUT=2
7CONFIG_RCU_FANOUT_LEAF=2
5CONFIG_PREEMPT_NONE=n 8CONFIG_PREEMPT_NONE=n
6CONFIG_PREEMPT_VOLUNTARY=n 9CONFIG_PREEMPT_VOLUNTARY=n
7CONFIG_PREEMPT=y 10CONFIG_PREEMPT=y
8#CHECK#CONFIG_RCU_EXPERT=n 11CONFIG_DEBUG_LOCK_ALLOC=y
12CONFIG_PROVE_LOCKING=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-t b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-t
new file mode 100644
index 000000000000..6c78022c8cd8
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-t
@@ -0,0 +1,10 @@
1CONFIG_SMP=n
2CONFIG_PREEMPT_NONE=y
3CONFIG_PREEMPT_VOLUNTARY=n
4CONFIG_PREEMPT=n
5#CHECK#CONFIG_TINY_SRCU=y
6CONFIG_RCU_TRACE=n
7CONFIG_DEBUG_LOCK_ALLOC=n
8CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
9CONFIG_DEBUG_ATOMIC_SLEEP=y
10#CHECK#CONFIG_PREEMPT_COUNT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-t.boot b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-t.boot
new file mode 100644
index 000000000000..238bfe3bd0cc
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-t.boot
@@ -0,0 +1 @@
rcutorture.torture_type=srcu
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-u b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-u
new file mode 100644
index 000000000000..6bc24e99862f
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-u
@@ -0,0 +1,9 @@
1CONFIG_SMP=n
2CONFIG_PREEMPT_NONE=y
3CONFIG_PREEMPT_VOLUNTARY=n
4CONFIG_PREEMPT=n
5#CHECK#CONFIG_TINY_SRCU=y
6CONFIG_RCU_TRACE=n
7CONFIG_DEBUG_LOCK_ALLOC=n
8CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
9CONFIG_PREEMPT_COUNT=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-u.boot b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-u.boot
new file mode 100644
index 000000000000..84a7d51b7481
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-u.boot
@@ -0,0 +1 @@
rcutorture.torture_type=srcud
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY02 b/tools/testing/selftests/rcutorture/configs/rcu/TINY02
index a59f7686e219..d8674264318d 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TINY02
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY02
@@ -6,10 +6,9 @@ CONFIG_PREEMPT=n
6CONFIG_HZ_PERIODIC=y 6CONFIG_HZ_PERIODIC=y
7CONFIG_NO_HZ_IDLE=n 7CONFIG_NO_HZ_IDLE=n
8CONFIG_NO_HZ_FULL=n 8CONFIG_NO_HZ_FULL=n
9CONFIG_RCU_TRACE=y
10CONFIG_PROVE_LOCKING=y 9CONFIG_PROVE_LOCKING=y
11CONFIG_PROVE_RCU_REPEATEDLY=y
12#CHECK#CONFIG_PROVE_RCU=y 10#CHECK#CONFIG_PROVE_RCU=y
13CONFIG_DEBUG_LOCK_ALLOC=y 11CONFIG_DEBUG_LOCK_ALLOC=y
12CONFIG_DEBUG_OBJECTS=y
14CONFIG_DEBUG_OBJECTS_RCU_HEAD=y 13CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
15CONFIG_PREEMPT_COUNT=y 14CONFIG_DEBUG_ATOMIC_SLEEP=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01 b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
index 359cb258f639..b5b53973c01e 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE01
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
@@ -10,12 +10,9 @@ CONFIG_RCU_FAST_NO_HZ=y
10CONFIG_RCU_TRACE=y 10CONFIG_RCU_TRACE=y
11CONFIG_HOTPLUG_CPU=y 11CONFIG_HOTPLUG_CPU=y
12CONFIG_MAXSMP=y 12CONFIG_MAXSMP=y
13CONFIG_CPUMASK_OFFSTACK=y
13CONFIG_RCU_NOCB_CPU=y 14CONFIG_RCU_NOCB_CPU=y
14CONFIG_RCU_NOCB_CPU_ZERO=y
15CONFIG_DEBUG_LOCK_ALLOC=n 15CONFIG_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/TREE01.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
index adc3abc82fb8..1d14e1383016 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
@@ -1 +1,5 @@
1rcutorture.torture_type=rcu_bh maxcpus=8 1rcutorture.torture_type=rcu_bh maxcpus=8
2rcutree.gp_preinit_delay=3
3rcutree.gp_init_delay=3
4rcutree.gp_cleanup_delay=3
5rcu_nocbs=0
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE02 b/tools/testing/selftests/rcutorture/configs/rcu/TREE02
index c1ab5926568b..35e639e39366 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE02
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE02
@@ -18,9 +18,6 @@ CONFIG_RCU_NOCB_CPU=n
18CONFIG_DEBUG_LOCK_ALLOC=y 18CONFIG_DEBUG_LOCK_ALLOC=y
19CONFIG_PROVE_LOCKING=n 19CONFIG_PROVE_LOCKING=n
20CONFIG_RCU_BOOST=n 20CONFIG_RCU_BOOST=n
21CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
22CONFIG_RCU_EXPERT=y 21CONFIG_RCU_EXPERT=y
23CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y 22CONFIG_DEBUG_OBJECTS=y
24CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
25CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
26CONFIG_DEBUG_OBJECTS_RCU_HEAD=y 23CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE03 b/tools/testing/selftests/rcutorture/configs/rcu/TREE03
index 3b93ee544e70..2dc31b16e506 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE03
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE03
@@ -14,9 +14,5 @@ CONFIG_RCU_FANOUT_LEAF=2
14CONFIG_RCU_NOCB_CPU=n 14CONFIG_RCU_NOCB_CPU=n
15CONFIG_DEBUG_LOCK_ALLOC=n 15CONFIG_DEBUG_LOCK_ALLOC=n
16CONFIG_RCU_BOOST=y 16CONFIG_RCU_BOOST=y
17CONFIG_RCU_KTHREAD_PRIO=2
18CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 17CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
19CONFIG_RCU_EXPERT=y 18CONFIG_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/TREE03.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot
index 120c0c88d100..5d2cc0bd50a0 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot
@@ -1 +1,5 @@
1rcutorture.onoff_interval=1 rcutorture.onoff_holdoff=30 1rcutorture.onoff_interval=1 rcutorture.onoff_holdoff=30
2rcutree.gp_preinit_delay=3
3rcutree.gp_init_delay=3
4rcutree.gp_cleanup_delay=3
5rcutree.kthread_prio=2
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
index 5af758e783c7..27d22695d64c 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
@@ -15,11 +15,7 @@ CONFIG_SUSPEND=n
15CONFIG_HIBERNATION=n 15CONFIG_HIBERNATION=n
16CONFIG_RCU_FANOUT=4 16CONFIG_RCU_FANOUT=4
17CONFIG_RCU_FANOUT_LEAF=3 17CONFIG_RCU_FANOUT_LEAF=3
18CONFIG_RCU_NOCB_CPU=n
19CONFIG_DEBUG_LOCK_ALLOC=n 18CONFIG_DEBUG_LOCK_ALLOC=n
20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 19CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
21CONFIG_RCU_EXPERT=y 20CONFIG_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 21CONFIG_RCU_EQS_DEBUG=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE05 b/tools/testing/selftests/rcutorture/configs/rcu/TREE05
index d4cdc0d74e16..2dde0d9964e3 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE05
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05
@@ -13,12 +13,8 @@ CONFIG_HOTPLUG_CPU=y
13CONFIG_RCU_FANOUT=6 13CONFIG_RCU_FANOUT=6
14CONFIG_RCU_FANOUT_LEAF=6 14CONFIG_RCU_FANOUT_LEAF=6
15CONFIG_RCU_NOCB_CPU=y 15CONFIG_RCU_NOCB_CPU=y
16CONFIG_RCU_NOCB_CPU_NONE=y
17CONFIG_DEBUG_LOCK_ALLOC=y 16CONFIG_DEBUG_LOCK_ALLOC=y
18CONFIG_PROVE_LOCKING=y 17CONFIG_PROVE_LOCKING=y
19#CHECK#CONFIG_PROVE_RCU=y 18#CHECK#CONFIG_PROVE_RCU=y
20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 19CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
21CONFIG_RCU_EXPERT=y 20CONFIG_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/TREE05.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot
index 15b3e1a86f74..c7fd050dfcd9 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot
@@ -1,2 +1,5 @@
1rcutorture.torture_type=sched 1rcutorture.torture_type=sched
2rcupdate.rcu_self_test_sched=1 2rcupdate.rcu_self_test_sched=1
3rcutree.gp_preinit_delay=3
4rcutree.gp_init_delay=3
5rcutree.gp_cleanup_delay=3
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE06 b/tools/testing/selftests/rcutorture/configs/rcu/TREE06
index 4cb02bd28f08..05a4eec3f27b 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE06
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE06
@@ -18,8 +18,6 @@ CONFIG_RCU_NOCB_CPU=n
18CONFIG_DEBUG_LOCK_ALLOC=y 18CONFIG_DEBUG_LOCK_ALLOC=y
19CONFIG_PROVE_LOCKING=y 19CONFIG_PROVE_LOCKING=y
20#CHECK#CONFIG_PROVE_RCU=y 20#CHECK#CONFIG_PROVE_RCU=y
21CONFIG_DEBUG_OBJECTS=y
21CONFIG_DEBUG_OBJECTS_RCU_HEAD=y 22CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
22CONFIG_RCU_EXPERT=y 23CONFIG_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/TREE06.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot
index dd90f28ed700..ad18b52a2cad 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot
@@ -2,3 +2,6 @@ rcupdate.rcu_self_test=1
2rcupdate.rcu_self_test_bh=1 2rcupdate.rcu_self_test_bh=1
3rcupdate.rcu_self_test_sched=1 3rcupdate.rcu_self_test_sched=1
4rcutree.rcu_fanout_exact=1 4rcutree.rcu_fanout_exact=1
5rcutree.gp_preinit_delay=3
6rcutree.gp_init_delay=3
7rcutree.gp_cleanup_delay=3
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE07 b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
index b12a3ea1867e..0f4759f4232e 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE07
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
@@ -1,6 +1,5 @@
1CONFIG_SMP=y 1CONFIG_SMP=y
2CONFIG_NR_CPUS=16 2CONFIG_NR_CPUS=16
3CONFIG_CPUMASK_OFFSTACK=y
4CONFIG_PREEMPT_NONE=y 3CONFIG_PREEMPT_NONE=y
5CONFIG_PREEMPT_VOLUNTARY=n 4CONFIG_PREEMPT_VOLUNTARY=n
6CONFIG_PREEMPT=n 5CONFIG_PREEMPT=n
@@ -9,16 +8,11 @@ CONFIG_HZ_PERIODIC=n
9CONFIG_NO_HZ_IDLE=n 8CONFIG_NO_HZ_IDLE=n
10CONFIG_NO_HZ_FULL=y 9CONFIG_NO_HZ_FULL=y
11CONFIG_NO_HZ_FULL_ALL=n 10CONFIG_NO_HZ_FULL_ALL=n
12CONFIG_NO_HZ_FULL_SYSIDLE=y
13CONFIG_RCU_FAST_NO_HZ=n 11CONFIG_RCU_FAST_NO_HZ=n
14CONFIG_RCU_TRACE=y 12CONFIG_RCU_TRACE=y
15CONFIG_HOTPLUG_CPU=y 13CONFIG_HOTPLUG_CPU=y
16CONFIG_RCU_FANOUT=2 14CONFIG_RCU_FANOUT=2
17CONFIG_RCU_FANOUT_LEAF=2 15CONFIG_RCU_FANOUT_LEAF=2
18CONFIG_RCU_NOCB_CPU=n
19CONFIG_DEBUG_LOCK_ALLOC=n 16CONFIG_DEBUG_LOCK_ALLOC=n
20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 17CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
21CONFIG_RCU_EXPERT=y 18CONFIG_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 099cc63c6a3b..fb1c763c10c5 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE08
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08
@@ -15,7 +15,6 @@ CONFIG_HIBERNATION=n
15CONFIG_RCU_FANOUT=3 15CONFIG_RCU_FANOUT=3
16CONFIG_RCU_FANOUT_LEAF=2 16CONFIG_RCU_FANOUT_LEAF=2
17CONFIG_RCU_NOCB_CPU=y 17CONFIG_RCU_NOCB_CPU=y
18CONFIG_RCU_NOCB_CPU_ALL=y
19CONFIG_DEBUG_LOCK_ALLOC=n 18CONFIG_DEBUG_LOCK_ALLOC=n
20CONFIG_PROVE_LOCKING=n 19CONFIG_PROVE_LOCKING=n
21CONFIG_RCU_BOOST=n 20CONFIG_RCU_BOOST=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T b/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T
deleted file mode 100644
index 2ad13f0d29cc..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T
+++ /dev/null
@@ -1,21 +0,0 @@
1CONFIG_SMP=y
2CONFIG_NR_CPUS=16
3CONFIG_PREEMPT_NONE=n
4CONFIG_PREEMPT_VOLUNTARY=n
5CONFIG_PREEMPT=y
6#CHECK#CONFIG_PREEMPT_RCU=y
7CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=y
9CONFIG_NO_HZ_FULL=n
10CONFIG_RCU_FAST_NO_HZ=n
11CONFIG_RCU_TRACE=y
12CONFIG_HOTPLUG_CPU=n
13CONFIG_SUSPEND=n
14CONFIG_HIBERNATION=n
15CONFIG_RCU_FANOUT=3
16CONFIG_RCU_FANOUT_LEAF=2
17CONFIG_RCU_NOCB_CPU=y
18CONFIG_RCU_NOCB_CPU_ALL=y
19CONFIG_DEBUG_LOCK_ALLOC=n
20CONFIG_RCU_BOOST=n
21CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot
index fb066dc82769..1bd8efc4141e 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot
@@ -2,3 +2,4 @@ rcutorture.torture_type=sched
2rcupdate.rcu_self_test=1 2rcupdate.rcu_self_test=1
3rcupdate.rcu_self_test_sched=1 3rcupdate.rcu_self_test_sched=1
4rcutree.rcu_fanout_exact=1 4rcutree.rcu_fanout_exact=1
5rcu_nocbs=0-7
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE02-T b/tools/testing/selftests/rcutorture/configs/rcuperf/TINY
index 917d2517b5b5..fb05ef5279b4 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE02-T
+++ b/tools/testing/selftests/rcutorture/configs/rcuperf/TINY
@@ -1,21 +1,16 @@
1CONFIG_SMP=y 1CONFIG_SMP=n
2CONFIG_NR_CPUS=8 2CONFIG_PREEMPT_NONE=y
3CONFIG_PREEMPT_NONE=n
4CONFIG_PREEMPT_VOLUNTARY=n 3CONFIG_PREEMPT_VOLUNTARY=n
5CONFIG_PREEMPT=y 4CONFIG_PREEMPT=n
6#CHECK#CONFIG_PREEMPT_RCU=y 5#CHECK#CONFIG_TINY_RCU=y
7CONFIG_HZ_PERIODIC=n 6CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=y 7CONFIG_NO_HZ_IDLE=y
9CONFIG_NO_HZ_FULL=n 8CONFIG_NO_HZ_FULL=n
10CONFIG_RCU_FAST_NO_HZ=n 9CONFIG_RCU_FAST_NO_HZ=n
11CONFIG_RCU_TRACE=y
12CONFIG_HOTPLUG_CPU=n
13CONFIG_SUSPEND=n
14CONFIG_HIBERNATION=n
15CONFIG_RCU_FANOUT=3
16CONFIG_RCU_FANOUT_LEAF=3
17CONFIG_RCU_NOCB_CPU=n 10CONFIG_RCU_NOCB_CPU=n
18CONFIG_DEBUG_LOCK_ALLOC=y 11CONFIG_DEBUG_LOCK_ALLOC=n
19CONFIG_PROVE_LOCKING=n 12CONFIG_PROVE_LOCKING=n
20CONFIG_RCU_BOOST=n 13CONFIG_RCU_BOOST=n
21CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 14CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
15CONFIG_RCU_EXPERT=y
16CONFIG_RCU_TRACE=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/TREE b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE
index a312f671a29a..721cfda76ab2 100644
--- a/tools/testing/selftests/rcutorture/configs/rcuperf/TREE
+++ b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE
@@ -7,7 +7,6 @@ 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_FAST_NO_HZ=n 9CONFIG_RCU_FAST_NO_HZ=n
10CONFIG_RCU_TRACE=n
11CONFIG_HOTPLUG_CPU=n 10CONFIG_HOTPLUG_CPU=n
12CONFIG_SUSPEND=n 11CONFIG_SUSPEND=n
13CONFIG_HIBERNATION=n 12CONFIG_HIBERNATION=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/TREE54 b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE54
index 985fb170d13c..7629f5dd73b2 100644
--- a/tools/testing/selftests/rcutorture/configs/rcuperf/TREE54
+++ b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE54
@@ -8,7 +8,6 @@ CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=y 8CONFIG_NO_HZ_IDLE=y
9CONFIG_NO_HZ_FULL=n 9CONFIG_NO_HZ_FULL=n
10CONFIG_RCU_FAST_NO_HZ=n 10CONFIG_RCU_FAST_NO_HZ=n
11CONFIG_RCU_TRACE=n
12CONFIG_HOTPLUG_CPU=n 11CONFIG_HOTPLUG_CPU=n
13CONFIG_SUSPEND=n 12CONFIG_SUSPEND=n
14CONFIG_HIBERNATION=n 13CONFIG_HIBERNATION=n
diff --git a/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt b/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt
index 24396ae8355b..a75b16991a92 100644
--- a/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt
+++ b/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt
@@ -18,7 +18,6 @@ CONFIG_PROVE_RCU
18 18
19 In common code tested by TREE_RCU test cases. 19 In common code tested by TREE_RCU test cases.
20 20
21CONFIG_NO_HZ_FULL_SYSIDLE
22CONFIG_RCU_NOCB_CPU 21CONFIG_RCU_NOCB_CPU
23 22
24 Meaningless for TINY_RCU. 23 Meaningless for TINY_RCU.
diff --git a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
index 364801b1a230..9ad3f89c8dc7 100644
--- a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
+++ b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
@@ -9,28 +9,20 @@ CONFIG_DEBUG_OBJECTS_RCU_HEAD -- Do one.
9CONFIG_HOTPLUG_CPU -- Do half. (Every second.) 9CONFIG_HOTPLUG_CPU -- Do half. (Every second.)
10CONFIG_HZ_PERIODIC -- Do one. 10CONFIG_HZ_PERIODIC -- Do one.
11CONFIG_NO_HZ_IDLE -- Do those not otherwise specified. (Groups of two.) 11CONFIG_NO_HZ_IDLE -- Do those not otherwise specified. (Groups of two.)
12CONFIG_NO_HZ_FULL -- Do two, one with CONFIG_NO_HZ_FULL_SYSIDLE. 12CONFIG_NO_HZ_FULL -- Do two, one with partial CPU enablement.
13CONFIG_NO_HZ_FULL_SYSIDLE -- Do one.
14CONFIG_PREEMPT -- Do half. (First three and #8.) 13CONFIG_PREEMPT -- Do half. (First three and #8.)
15CONFIG_PROVE_LOCKING -- Do several, covering CONFIG_DEBUG_LOCK_ALLOC=y and not. 14CONFIG_PROVE_LOCKING -- Do several, covering CONFIG_DEBUG_LOCK_ALLOC=y and not.
16CONFIG_PROVE_RCU -- Hardwired to CONFIG_PROVE_LOCKING. 15CONFIG_PROVE_RCU -- Hardwired to CONFIG_PROVE_LOCKING.
17CONFIG_PROVE_RCU_REPEATEDLY -- Do one.
18CONFIG_RCU_BOOST -- one of PREEMPT_RCU. 16CONFIG_RCU_BOOST -- one of PREEMPT_RCU.
19CONFIG_RCU_KTHREAD_PRIO -- set to 2 for _BOOST testing.
20CONFIG_RCU_FANOUT -- Cover hierarchy, but overlap with others. 17CONFIG_RCU_FANOUT -- Cover hierarchy, but overlap with others.
21CONFIG_RCU_FANOUT_LEAF -- Do one non-default. 18CONFIG_RCU_FANOUT_LEAF -- Do one non-default.
22CONFIG_RCU_FAST_NO_HZ -- Do one, but not with CONFIG_RCU_NOCB_CPU_ALL. 19CONFIG_RCU_FAST_NO_HZ -- Do one, but not with all nohz_full CPUs.
23CONFIG_RCU_NOCB_CPU -- Do three, see below. 20CONFIG_RCU_NOCB_CPU -- Do three, one with no rcu_nocbs CPUs, one with
24CONFIG_RCU_NOCB_CPU_ALL -- Do one. 21 rcu_nocbs=0, and one with all rcu_nocbs CPUs.
25CONFIG_RCU_NOCB_CPU_NONE -- Do one.
26CONFIG_RCU_NOCB_CPU_ZERO -- Do one.
27CONFIG_RCU_TRACE -- Do half. 22CONFIG_RCU_TRACE -- Do half.
28CONFIG_SMP -- Need one !SMP for PREEMPT_RCU. 23CONFIG_SMP -- Need one !SMP for PREEMPT_RCU.
29CONFIG_RCU_EXPERT=n -- Do a few, but these have to be vanilla configurations. 24CONFIG_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. 25CONFIG_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 26
35RCU-bh: Do one with PREEMPT and one with !PREEMPT. 27RCU-bh: Do one with PREEMPT and one with !PREEMPT.
36RCU-sched: Do one with PREEMPT but not BOOST. 28RCU-sched: Do one with PREEMPT but not BOOST.
@@ -52,10 +44,6 @@ CONFIG_64BIT
52 44
53 Used only to check CONFIG_RCU_FANOUT value, inspection suffices. 45 Used only to check CONFIG_RCU_FANOUT value, inspection suffices.
54 46
55CONFIG_NO_HZ_FULL_SYSIDLE_SMALL
56
57 Defer until Frederic uses this.
58
59CONFIG_PREEMPT_COUNT 47CONFIG_PREEMPT_COUNT
60CONFIG_PREEMPT_RCU 48CONFIG_PREEMPT_RCU
61 49
@@ -78,30 +66,16 @@ CONFIG_RCU_TORTURE_TEST_RUNNABLE
78 66
79 Always used in KVM testing. 67 Always used in KVM testing.
80 68
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
87CONFIG_PREEMPT_RCU 69CONFIG_PREEMPT_RCU
88CONFIG_TREE_RCU 70CONFIG_TREE_RCU
89CONFIG_TINY_RCU 71CONFIG_TINY_RCU
90 72
91 These are controlled by CONFIG_PREEMPT and/or CONFIG_SMP. 73 These are controlled by CONFIG_PREEMPT and/or CONFIG_SMP.
92 74
93CONFIG_SPARSE_RCU_POINTER
94
95 Makes sense only for sparse runs, not for kernel builds.
96
97CONFIG_SRCU 75CONFIG_SRCU
98CONFIG_TASKS_RCU 76CONFIG_TASKS_RCU
99 77
100 Selected by CONFIG_RCU_TORTURE_TEST, so cannot disable. 78 Selected by CONFIG_RCU_TORTURE_TEST, so cannot disable.
101 79
102CONFIG_RCU_TRACE
103
104 Implied by CONFIG_RCU_TRACE for Tree RCU.
105
106 80
107boot parameters ignored: TBD 81boot parameters ignored: TBD
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk
index 8ff89043d0a9..c9e8bc5082a7 100755
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk
@@ -1,4 +1,4 @@
1#!/bin/awk -f 1#!/usr/bin/awk -f
2 2
3# Modify SRCU for formal verification. The first argument should be srcu.h and 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 4# the second should be srcu.c. Outputs modified srcu.h and srcu.c into the
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 03f1fa495d74..00a928b833d0 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -1822,6 +1822,23 @@ struct tsync_sibling {
1822 struct __test_metadata *metadata; 1822 struct __test_metadata *metadata;
1823}; 1823};
1824 1824
1825/*
1826 * To avoid joining joined threads (which is not allowed by Bionic),
1827 * make sure we both successfully join and clear the tid to skip a
1828 * later join attempt during fixture teardown. Any remaining threads
1829 * will be directly killed during teardown.
1830 */
1831#define PTHREAD_JOIN(tid, status) \
1832 do { \
1833 int _rc = pthread_join(tid, status); \
1834 if (_rc) { \
1835 TH_LOG("pthread_join of tid %u failed: %d\n", \
1836 (unsigned int)tid, _rc); \
1837 } else { \
1838 tid = 0; \
1839 } \
1840 } while (0)
1841
1825FIXTURE_DATA(TSYNC) { 1842FIXTURE_DATA(TSYNC) {
1826 struct sock_fprog root_prog, apply_prog; 1843 struct sock_fprog root_prog, apply_prog;
1827 struct tsync_sibling sibling[TSYNC_SIBLINGS]; 1844 struct tsync_sibling sibling[TSYNC_SIBLINGS];
@@ -1890,14 +1907,14 @@ FIXTURE_TEARDOWN(TSYNC)
1890 1907
1891 for ( ; sib < self->sibling_count; ++sib) { 1908 for ( ; sib < self->sibling_count; ++sib) {
1892 struct tsync_sibling *s = &self->sibling[sib]; 1909 struct tsync_sibling *s = &self->sibling[sib];
1893 void *status;
1894 1910
1895 if (!s->tid) 1911 if (!s->tid)
1896 continue; 1912 continue;
1897 if (pthread_kill(s->tid, 0)) { 1913 /*
1898 pthread_cancel(s->tid); 1914 * If a thread is still running, it may be stuck, so hit
1899 pthread_join(s->tid, &status); 1915 * it over the head really hard.
1900 } 1916 */
1917 pthread_kill(s->tid, 9);
1901 } 1918 }
1902 pthread_mutex_destroy(&self->mutex); 1919 pthread_mutex_destroy(&self->mutex);
1903 pthread_cond_destroy(&self->cond); 1920 pthread_cond_destroy(&self->cond);
@@ -1987,9 +2004,9 @@ TEST_F(TSYNC, siblings_fail_prctl)
1987 pthread_mutex_unlock(&self->mutex); 2004 pthread_mutex_unlock(&self->mutex);
1988 2005
1989 /* Ensure diverging sibling failed to call prctl. */ 2006 /* Ensure diverging sibling failed to call prctl. */
1990 pthread_join(self->sibling[0].tid, &status); 2007 PTHREAD_JOIN(self->sibling[0].tid, &status);
1991 EXPECT_EQ(SIBLING_EXIT_FAILURE, (long)status); 2008 EXPECT_EQ(SIBLING_EXIT_FAILURE, (long)status);
1992 pthread_join(self->sibling[1].tid, &status); 2009 PTHREAD_JOIN(self->sibling[1].tid, &status);
1993 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status); 2010 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
1994} 2011}
1995 2012
@@ -2029,9 +2046,9 @@ TEST_F(TSYNC, two_siblings_with_ancestor)
2029 } 2046 }
2030 pthread_mutex_unlock(&self->mutex); 2047 pthread_mutex_unlock(&self->mutex);
2031 /* Ensure they are both killed and don't exit cleanly. */ 2048 /* Ensure they are both killed and don't exit cleanly. */
2032 pthread_join(self->sibling[0].tid, &status); 2049 PTHREAD_JOIN(self->sibling[0].tid, &status);
2033 EXPECT_EQ(0x0, (long)status); 2050 EXPECT_EQ(0x0, (long)status);
2034 pthread_join(self->sibling[1].tid, &status); 2051 PTHREAD_JOIN(self->sibling[1].tid, &status);
2035 EXPECT_EQ(0x0, (long)status); 2052 EXPECT_EQ(0x0, (long)status);
2036} 2053}
2037 2054
@@ -2055,9 +2072,9 @@ TEST_F(TSYNC, two_sibling_want_nnp)
2055 pthread_mutex_unlock(&self->mutex); 2072 pthread_mutex_unlock(&self->mutex);
2056 2073
2057 /* Ensure they are both upset about lacking nnp. */ 2074 /* Ensure they are both upset about lacking nnp. */
2058 pthread_join(self->sibling[0].tid, &status); 2075 PTHREAD_JOIN(self->sibling[0].tid, &status);
2059 EXPECT_EQ(SIBLING_EXIT_NEWPRIVS, (long)status); 2076 EXPECT_EQ(SIBLING_EXIT_NEWPRIVS, (long)status);
2060 pthread_join(self->sibling[1].tid, &status); 2077 PTHREAD_JOIN(self->sibling[1].tid, &status);
2061 EXPECT_EQ(SIBLING_EXIT_NEWPRIVS, (long)status); 2078 EXPECT_EQ(SIBLING_EXIT_NEWPRIVS, (long)status);
2062} 2079}
2063 2080
@@ -2095,9 +2112,9 @@ TEST_F(TSYNC, two_siblings_with_no_filter)
2095 pthread_mutex_unlock(&self->mutex); 2112 pthread_mutex_unlock(&self->mutex);
2096 2113
2097 /* Ensure they are both killed and don't exit cleanly. */ 2114 /* Ensure they are both killed and don't exit cleanly. */
2098 pthread_join(self->sibling[0].tid, &status); 2115 PTHREAD_JOIN(self->sibling[0].tid, &status);
2099 EXPECT_EQ(0x0, (long)status); 2116 EXPECT_EQ(0x0, (long)status);
2100 pthread_join(self->sibling[1].tid, &status); 2117 PTHREAD_JOIN(self->sibling[1].tid, &status);
2101 EXPECT_EQ(0x0, (long)status); 2118 EXPECT_EQ(0x0, (long)status);
2102} 2119}
2103 2120
@@ -2140,9 +2157,9 @@ TEST_F(TSYNC, two_siblings_with_one_divergence)
2140 pthread_mutex_unlock(&self->mutex); 2157 pthread_mutex_unlock(&self->mutex);
2141 2158
2142 /* Ensure they are both unkilled. */ 2159 /* Ensure they are both unkilled. */
2143 pthread_join(self->sibling[0].tid, &status); 2160 PTHREAD_JOIN(self->sibling[0].tid, &status);
2144 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status); 2161 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
2145 pthread_join(self->sibling[1].tid, &status); 2162 PTHREAD_JOIN(self->sibling[1].tid, &status);
2146 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status); 2163 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
2147} 2164}
2148 2165
@@ -2199,7 +2216,7 @@ TEST_F(TSYNC, two_siblings_not_under_filter)
2199 TH_LOG("cond broadcast non-zero"); 2216 TH_LOG("cond broadcast non-zero");
2200 } 2217 }
2201 pthread_mutex_unlock(&self->mutex); 2218 pthread_mutex_unlock(&self->mutex);
2202 pthread_join(self->sibling[sib].tid, &status); 2219 PTHREAD_JOIN(self->sibling[sib].tid, &status);
2203 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status); 2220 EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
2204 /* Poll for actual task death. pthread_join doesn't guarantee it. */ 2221 /* Poll for actual task death. pthread_join doesn't guarantee it. */
2205 while (!kill(self->sibling[sib].system_tid, 0)) 2222 while (!kill(self->sibling[sib].system_tid, 0))
@@ -2224,7 +2241,7 @@ TEST_F(TSYNC, two_siblings_not_under_filter)
2224 TH_LOG("cond broadcast non-zero"); 2241 TH_LOG("cond broadcast non-zero");
2225 } 2242 }
2226 pthread_mutex_unlock(&self->mutex); 2243 pthread_mutex_unlock(&self->mutex);
2227 pthread_join(self->sibling[sib].tid, &status); 2244 PTHREAD_JOIN(self->sibling[sib].tid, &status);
2228 EXPECT_EQ(0, (long)status); 2245 EXPECT_EQ(0, (long)status);
2229 /* Poll for actual task death. pthread_join doesn't guarantee it. */ 2246 /* Poll for actual task death. pthread_join doesn't guarantee it. */
2230 while (!kill(self->sibling[sib].system_tid, 0)) 2247 while (!kill(self->sibling[sib].system_tid, 0))
diff --git a/tools/testing/selftests/tc-testing/.gitignore b/tools/testing/selftests/tc-testing/.gitignore
new file mode 100644
index 000000000000..c18dd8d83cee
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/.gitignore
@@ -0,0 +1 @@
__pycache__/
diff --git a/tools/testing/selftests/tc-testing/README b/tools/testing/selftests/tc-testing/README
new file mode 100644
index 000000000000..970ff294fec8
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/README
@@ -0,0 +1,102 @@
1tdc - Linux Traffic Control (tc) unit testing suite
2
3Author: Lucas Bates - lucasb@mojatatu.com
4
5tdc is a Python script to load tc unit tests from a separate JSON file and
6execute them inside a network namespace dedicated to the task.
7
8
9REQUIREMENTS
10------------
11
12* Minimum Python version of 3.4. Earlier 3.X versions may work but are not
13 guaranteed.
14
15* The kernel must have network namespace support
16
17* The kernel must have veth support available, as a veth pair is created
18 prior to running the tests.
19
20* All tc-related features must be built in or available as modules.
21 To check what is required in current setup run:
22 ./tdc.py -c
23
24 Note:
25 In the current release, tdc run will abort due to a failure in setup or
26 teardown commands - which includes not being able to run a test simply
27 because the kernel did not support a specific feature. (This will be
28 handled in a future version - the current workaround is to run the tests
29 on specific test categories that your kernel supports)
30
31
32BEFORE YOU RUN
33--------------
34
35The path to the tc executable that will be most commonly tested can be defined
36in the tdc_config.py file. Find the 'TC' entry in the NAMES dictionary and
37define the path.
38
39If you need to test a different tc executable on the fly, you can do so by
40using the -p option when running tdc:
41 ./tdc.py -p /path/to/tc
42
43
44RUNNING TDC
45-----------
46
47To use tdc, root privileges are required. tdc will not run otherwise.
48
49All tests are executed inside a network namespace to prevent conflicts
50within the host.
51
52Running tdc without any arguments will run all tests. Refer to the section
53on command line arguments for more information, or run:
54 ./tdc.py -h
55
56tdc will list the test names as they are being run, and print a summary in
57TAP (Test Anything Protocol) format when they are done. If tests fail,
58output captured from the failing test will be printed immediately following
59the failed test in the TAP output.
60
61
62USER-DEFINED CONSTANTS
63----------------------
64
65The tdc_config.py file contains multiple values that can be altered to suit
66your needs. Any value in the NAMES dictionary can be altered without affecting
67the tests to be run. These values are used in the tc commands that will be
68executed as part of the test. More will be added as test cases require.
69
70Example:
71 $TC qdisc add dev $DEV1 ingress
72
73
74COMMAND LINE ARGUMENTS
75----------------------
76
77Run tdc.py -h to see the full list of available arguments.
78
79-p PATH Specify the tc executable located at PATH to be used on this
80 test run
81-c Show the available test case categories in this test file
82-c CATEGORY Run only tests that belong to CATEGORY
83-f FILE Read test cases from the JSON file named FILE
84-l [CATEGORY] List all test cases in the JSON file. If CATEGORY is
85 specified, list test cases matching that category.
86-s ID Show the test case matching ID
87-e ID Execute the test case identified by ID
88-i Generate unique ID numbers for test cases with no existing
89 ID number
90
91
92ACKNOWLEDGEMENTS
93----------------
94
95Thanks to:
96
97Jamal Hadi Salim, for providing valuable test cases
98Keara Leibovitz, who wrote the CLI test driver that I used as a base for the
99 first version of the tc testing suite. This work was presented at
100 Netdev 1.2 Tokyo in October 2016.
101Samir Hussain, for providing help while I dove into Python for the first time
102 and being a second eye for this code.
diff --git a/tools/testing/selftests/tc-testing/TODO.txt b/tools/testing/selftests/tc-testing/TODO.txt
new file mode 100644
index 000000000000..6a266d811a78
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/TODO.txt
@@ -0,0 +1,10 @@
1tc Testing Suite To-Do list:
2
3- Determine what tc features are supported in the kernel. If features are not
4 present, prevent the related categories from running.
5
6- Add support for multiple versions of tc to run successively
7
8- Improve error messages when tdc aborts its run
9
10- Allow tdc to write its results to file
diff --git a/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt b/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt
new file mode 100644
index 000000000000..4e09257bc443
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt
@@ -0,0 +1,69 @@
1tdc - Adding test cases for tdc
2
3Author: Lucas Bates - lucasb@mojatatu.com
4
5ADDING TEST CASES
6-----------------
7
8User-defined tests should be added by defining a separate JSON file. This
9will help prevent conflicts when updating the repository. Refer to
10template.json for the required JSON format for test cases.
11
12Include the 'id' field, but do not assign a value. Running tdc with the -i
13option will generate a unique ID for that test case.
14
15tdc will recursively search the 'tc' subdirectory for .json files. Any
16test case files you create in these directories will automatically be included.
17If you wish to store your custom test cases elsewhere, be sure to run tdc
18with the -f argument and the path to your file.
19
20Be aware of required escape characters in the JSON data - particularly when
21defining the match pattern. Refer to the tctests.json file for examples when
22in doubt.
23
24
25TEST CASE STRUCTURE
26-------------------
27
28Each test case has required data:
29
30id: A unique alphanumeric value to identify a particular test case
31name: Descriptive name that explains the command under test
32category: A list of single-word descriptions covering what the command
33 under test is testing. Example: filter, actions, u32, gact, etc.
34setup: The list of commands required to ensure the command under test
35 succeeds. For example: if testing a filter, the command to create
36 the qdisc would appear here.
37cmdUnderTest: The tc command being tested itself.
38expExitCode: The code returned by the command under test upon its termination.
39 tdc will compare this value against the actual returned value.
40verifyCmd: The tc command to be run to verify successful execution.
41 For example: if the command under test creates a gact action,
42 verifyCmd should be "$TC actions show action gact"
43matchPattern: A regular expression to be applied against the output of the
44 verifyCmd to prove the command under test succeeded. This pattern
45 should be as specific as possible so that a false positive is not
46 matched.
47matchCount: How many times the regex in matchPattern should match. A value
48 of 0 is acceptable.
49teardown: The list of commands to clean up after the test is completed.
50 The environment should be returned to the same state as when
51 this test was started: qdiscs deleted, actions flushed, etc.
52
53
54SETUP/TEARDOWN ERRORS
55---------------------
56
57If an error is detected during the setup/teardown process, execution of the
58tests will immediately stop with an error message and the namespace in which
59the tests are run will be destroyed. This is to prevent inaccurate results
60in the test cases.
61
62Repeated failures of the setup/teardown may indicate a problem with the test
63case, or possibly even a bug in one of the commands that are not being tested.
64
65It's possible to include acceptable exit codes with the setup/teardown command
66so that it doesn't halt the script for an error that doesn't matter. Turn the
67individual command into a list, with the command being first, followed by all
68acceptable exit codes for the command.
69
diff --git a/tools/testing/selftests/tc-testing/creating-testcases/template.json b/tools/testing/selftests/tc-testing/creating-testcases/template.json
new file mode 100644
index 000000000000..87971744bdd4
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/creating-testcases/template.json
@@ -0,0 +1,40 @@
1[
2 {
3 "id": "",
4 "name": "",
5 "category": [
6 "",
7 ""
8 ],
9 "setup": [
10 ""
11 ],
12 "cmdUnderTest": "",
13 "expExitCode": "",
14 "verifyCmd": "",
15 "matchPattern": "",
16 "matchCount": "",
17 "teardown": [
18 ""
19 ]
20 },
21 {
22 "id": "",
23 "name": "",
24 "category": [
25 "",
26 ""
27 ],
28 "setup": [
29 ""
30 ],
31 "cmdUnderTest": "",
32 "expExitCode": "",
33 "verifyCmd": "",
34 "matchPattern": "",
35 "matchCount": "",
36 "teardown": [
37 ""
38 ]
39 }
40]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json b/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
new file mode 100644
index 000000000000..af519bc97a8e
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
@@ -0,0 +1,1115 @@
1[
2 {
3 "id": "e89a",
4 "name": "Add valid pass action",
5 "category": [
6 "actions",
7 "gact"
8 ],
9 "setup": [
10 [
11 "$TC actions flush action gact",
12 0,
13 1,
14 255
15 ]
16 ],
17 "cmdUnderTest": "$TC actions add action pass index 8",
18 "expExitCode": "0",
19 "verifyCmd": "$TC actions list action gact",
20 "matchPattern": "action order [0-9]*: gact action pass.*index 8 ref",
21 "matchCount": "1",
22 "teardown": [
23 "$TC actions flush action gact"
24 ]
25 },
26 {
27 "id": "a02c",
28 "name": "Add valid pipe action",
29 "category": [
30 "actions",
31 "gact"
32 ],
33 "setup": [
34 [
35 "$TC actions flush action gact",
36 0,
37 1,
38 255
39 ]
40 ],
41 "cmdUnderTest": "$TC actions add action pipe index 6",
42 "expExitCode": "0",
43 "verifyCmd": "$TC actions list action gact",
44 "matchPattern": "action order [0-9]*: gact action pipe.*index 6 ref",
45 "matchCount": "1",
46 "teardown": [
47 "$TC actions flush action gact"
48 ]
49 },
50 {
51 "id": "feef",
52 "name": "Add valid reclassify action",
53 "category": [
54 "actions",
55 "gact"
56 ],
57 "setup": [
58 [
59 "$TC actions flush action gact",
60 0,
61 1,
62 255
63 ]
64 ],
65 "cmdUnderTest": "$TC actions add action reclassify index 5",
66 "expExitCode": "0",
67 "verifyCmd": "$TC actions list action gact",
68 "matchPattern": "action order [0-9]*: gact action reclassify.*index 5 ref",
69 "matchCount": "1",
70 "teardown": [
71 "$TC actions flush action gact"
72 ]
73 },
74 {
75 "id": "8a7a",
76 "name": "Add valid drop action",
77 "category": [
78 "actions",
79 "gact"
80 ],
81 "setup": [
82 [
83 "$TC actions flush action gact",
84 0,
85 1,
86 255
87 ]
88 ],
89 "cmdUnderTest": "$TC actions add action drop index 30",
90 "expExitCode": "0",
91 "verifyCmd": "$TC actions list action gact",
92 "matchPattern": "action order [0-9]*: gact action drop.*index 30 ref",
93 "matchCount": "1",
94 "teardown": [
95 "$TC actions flush action gact"
96 ]
97 },
98 {
99 "id": "9a52",
100 "name": "Add valid continue action",
101 "category": [
102 "actions",
103 "gact"
104 ],
105 "setup": [
106 [
107 "$TC actions flush action gact",
108 0,
109 1,
110 255
111 ]
112 ],
113 "cmdUnderTest": "$TC actions add action continue index 432",
114 "expExitCode": "0",
115 "verifyCmd": "$TC actions list action gact",
116 "matchPattern": "action order [0-9]*: gact action continue.*index 432 ref",
117 "matchCount": "1",
118 "teardown": [
119 "$TC actions flush action gact"
120 ]
121 },
122 {
123 "id": "d700",
124 "name": "Add invalid action",
125 "category": [
126 "actions",
127 "gact"
128 ],
129 "setup": [
130 [
131 "$TC actions flush action gact",
132 0,
133 1,
134 255
135 ]
136 ],
137 "cmdUnderTest": "$TC actions add action pump index 386",
138 "expExitCode": "255",
139 "verifyCmd": "$TC actions list action gact",
140 "matchPattern": "action order [0-9]*: gact action.*index 386 ref",
141 "matchCount": "0",
142 "teardown": [
143 "$TC actions flush action gact"
144 ]
145 },
146 {
147 "id": "9215",
148 "name": "Add action with duplicate index",
149 "category": [
150 "actions",
151 "gact"
152 ],
153 "setup": [
154 [
155 "$TC actions flush action gact",
156 0,
157 1,
158 255
159 ],
160 "$TC actions add action pipe index 15"
161 ],
162 "cmdUnderTest": "$TC actions add action drop index 15",
163 "expExitCode": "255",
164 "verifyCmd": "$TC actions list action gact",
165 "matchPattern": "action order [0-9]*: gact action drop.*index 15 ref",
166 "matchCount": "0",
167 "teardown": [
168 "$TC actions flush action gact"
169 ]
170 },
171 {
172 "id": "798e",
173 "name": "Add action with index exceeding 32-bit maximum",
174 "category": [
175 "actions",
176 "gact"
177 ],
178 "setup": [
179 [
180 "$TC actions flush action gact",
181 0,
182 1,
183 255
184 ]
185 ],
186 "cmdUnderTest": "$TC actions add action drop index 4294967296",
187 "expExitCode": "255",
188 "verifyCmd": "actions list action gact",
189 "matchPattern": "action order [0-9]*: gact action drop.*index 4294967296 ref",
190 "matchCount": "0",
191 "teardown": [
192 "$TC actions flush action gact"
193 ]
194 },
195 {
196 "id": "22be",
197 "name": "Add action with index at 32-bit maximum",
198 "category": [
199 "actions",
200 "gact"
201 ],
202 "setup": [
203 [
204 "$TC actions flush action gact",
205 0,
206 1,
207 255
208 ]
209 ],
210 "cmdUnderTest": "$TC actions add action drop index 4294967295",
211 "expExitCode": "0",
212 "verifyCmd": "$TC actions list action gact",
213 "matchPattern": "action order [0-9]*: gact action drop.*index 4294967295 ref",
214 "matchCount": "1",
215 "teardown": [
216 "$TC actions flush action gact"
217 ]
218 },
219 {
220 "id": "ac2a",
221 "name": "List actions",
222 "category": [
223 "actions",
224 "gact"
225 ],
226 "setup": [
227 [
228 "$TC actions flush action gact",
229 0,
230 1,
231 255
232 ],
233 "$TC actions add action reclassify index 101",
234 "$TC actions add action reclassify index 102",
235 "$TC actions add action reclassify index 103",
236 "$TC actions add action reclassify index 104",
237 "$TC actions add action reclassify index 105"
238 ],
239 "cmdUnderTest": "$TC actions list action gact",
240 "expExitCode": "0",
241 "verifyCmd": "$TC actions list action gact",
242 "matchPattern": "action order [0-9]*: gact action reclassify",
243 "matchCount": "5",
244 "teardown": [
245 "$TC actions flush action gact"
246 ]
247 },
248 {
249 "id": "63ec",
250 "name": "Delete pass action",
251 "category": [
252 "actions",
253 "gact"
254 ],
255 "setup": [
256 [
257 "$TC actions flush action gact",
258 0,
259 1,
260 255
261 ],
262 "$TC actions add action pass index 1"
263 ],
264 "cmdUnderTest": "$TC actions del action gact index 1",
265 "expExitCode": "0",
266 "verifyCmd": "$TC actions list action gact",
267 "matchPattern": "action order [0-9]*: gact action pass.*index 1 ref",
268 "matchCount": "0",
269 "teardown": [
270 "$TC actions flush action gact"
271 ]
272 },
273 {
274 "id": "46be",
275 "name": "Delete pipe action",
276 "category": [
277 "actions",
278 "gact"
279 ],
280 "setup": [
281 [
282 "$TC actions flush action gact",
283 0,
284 1,
285 255
286 ],
287 "$TC actions add action pipe index 9"
288 ],
289 "cmdUnderTest": "$TC actions del action gact index 9",
290 "expExitCode": "0",
291 "verifyCmd": "$TC actions list action gact",
292 "matchPattern": "action order [0-9]*: gact action pipe.*index 9 ref",
293 "matchCount": "0",
294 "teardown": [
295 "$TC actions flush action gact"
296 ]
297 },
298 {
299 "id": "2e08",
300 "name": "Delete reclassify action",
301 "category": [
302 "actions",
303 "gact"
304 ],
305 "setup": [
306 [
307 "$TC actions flush action gact",
308 0,
309 1,
310 255
311 ],
312 "$TC actions add action reclassify index 65536"
313 ],
314 "cmdUnderTest": "$TC actions del action gact index 65536",
315 "expExitCode": "0",
316 "verifyCmd": "$TC actions list action gact",
317 "matchPattern": "action order [0-9]*: gact action reclassify.*index 65536 ref",
318 "matchCount": "0",
319 "teardown": [
320 "$TC actions flush action gact"
321 ]
322 },
323 {
324 "id": "99c4",
325 "name": "Delete drop action",
326 "category": [
327 "actions",
328 "gact"
329 ],
330 "setup": [
331 [
332 "$TC actions flush action gact",
333 0,
334 1,
335 255
336 ],
337 "$TC actions add action drop index 16"
338 ],
339 "cmdUnderTest": "$TC actions del action gact index 16",
340 "expExitCode": "0",
341 "verifyCmd": "$TC actions list action gact",
342 "matchPattern": "action order [0-9]*: gact action drop.*index 16 ref",
343 "matchCount": "0",
344 "teardown": [
345 "$TC actions flush action gact"
346 ]
347 },
348 {
349 "id": "fb6b",
350 "name": "Delete continue action",
351 "category": [
352 "actions",
353 "gact"
354 ],
355 "setup": [
356 [
357 "$TC actions flush action gact",
358 0,
359 1,
360 255
361 ],
362 "$TC actions add action continue index 32"
363 ],
364 "cmdUnderTest": "$TC actions del action gact index 32",
365 "expExitCode": "0",
366 "verifyCmd": "actions list action gact",
367 "matchPattern": "action order [0-9]*: gact action continue.*index 32 ref",
368 "matchCount": "0",
369 "teardown": [
370 "$TC actions flush action gact"
371 ]
372 },
373 {
374 "id": "0eb3",
375 "name": "Delete non-existent action",
376 "category": [
377 "actions",
378 "gact"
379 ],
380 "setup": [
381 [
382 "$TC actions flush action gact",
383 0,
384 1,
385 255
386 ]
387 ],
388 "cmdUnderTest": "$TC actions del action gact index 2",
389 "expExitCode": "255",
390 "verifyCmd": "$TC actions list action gact",
391 "matchPattern": "action order [0-9]*: gact action",
392 "matchCount": "0",
393 "teardown": [
394 "$TC actions flush action gact"
395 ]
396 },
397 {
398 "id": "5124",
399 "name": "Add mirred mirror to egress action",
400 "category": [
401 "actions",
402 "mirred"
403 ],
404 "setup": [
405 [
406 "$TC actions flush action mirred",
407 0,
408 1,
409 255
410 ]
411 ],
412 "cmdUnderTest": "$TC actions add action mirred egress mirror index 1 dev lo",
413 "expExitCode": "0",
414 "verifyCmd": "$TC actions list action mirred",
415 "matchPattern": "action order [0-9]*: mirred \\(Egress Mirror to device lo\\).*index 1 ref",
416 "matchCount": "1",
417 "teardown": [
418 "$TC actions flush action mirred"
419 ]
420 },
421 {
422 "id": "6fb4",
423 "name": "Add mirred redirect to egress action",
424 "category": [
425 "actions",
426 "mirred"
427 ],
428 "setup": [
429 [
430 "$TC actions flush action mirred",
431 0,
432 1,
433 255
434 ]
435 ],
436 "cmdUnderTest": "$TC actions add action mirred egress redirect index 2 dev lo action pipe",
437 "expExitCode": "0",
438 "verifyCmd": "$TC actions list action mirred",
439 "matchPattern": "action order [0-9]*: mirred \\(Egress Redirect to device lo\\).*index 2 ref",
440 "matchCount": "1",
441 "teardown": [
442 "$TC actions flush action mirred"
443 ]
444 },
445 {
446 "id": "ba38",
447 "name": "Get mirred actions",
448 "category": [
449 "actions",
450 "mirred"
451 ],
452 "setup": [
453 [
454 "$TC actions flush action mirred",
455 0,
456 1,
457 255
458 ],
459 "$TC actions add action mirred egress mirror index 1 dev lo",
460 "$TC actions add action mirred egress redirect index 2 dev lo"
461 ],
462 "cmdUnderTest": "$TC actions show action mirred",
463 "expExitCode": "0",
464 "verifyCmd": "$TC actions list action mirred",
465 "matchPattern": "[Mirror|Redirect] to device lo",
466 "matchCount": "2",
467 "teardown": [
468 "$TC actions flush action mirred"
469 ]
470 },
471 {
472 "id": "d7c0",
473 "name": "Add invalid mirred direction",
474 "category": [
475 "actions",
476 "mirred"
477 ],
478 "setup": [
479 [
480 "$TC actions flush action mirred",
481 0,
482 1,
483 255
484 ]
485 ],
486 "cmdUnderTest": "$TC actions add action mirred inbound mirror index 20 dev lo",
487 "expExitCode": "255",
488 "verifyCmd": "$TC actions list action mirred",
489 "matchPattern": "action order [0-9]*: mirred \\(.*to device lo\\).*index 20 ref",
490 "matchCount": "0",
491 "teardown": [
492 "$TC actions flush action mirred"
493 ]
494 },
495 {
496 "id": "e213",
497 "name": "Add invalid mirred action",
498 "category": [
499 "actions",
500 "mirred"
501 ],
502 "setup": [
503 [
504 "$TC actions flush action mirred",
505 0,
506 1,
507 255
508 ]
509 ],
510 "cmdUnderTest": "$TC actions add action mirred egress remirror index 20 dev lo",
511 "expExitCode": "255",
512 "verifyCmd": "$TC actions list action mirred",
513 "matchPattern": "action order [0-9]*: mirred \\(Egress.*to device lo\\).*index 20 ref",
514 "matchCount": "0",
515 "teardown": [
516 "$TC actions flush action mirred"
517 ]
518 },
519 {
520 "id": "2d89",
521 "name": "Add mirred action with invalid device",
522 "category": [
523 "actions",
524 "mirred"
525 ],
526 "setup": [
527 [
528 "$TC actions flush action mirred",
529 0,
530 1,
531 255
532 ]
533 ],
534 "cmdUnderTest": "$TC actions add action mirred egress mirror index 20 dev eltoh",
535 "expExitCode": "255",
536 "verifyCmd": "$TC actions list action mirred",
537 "matchPattern": "action order [0-9]*: mirred \\(.*to device eltoh\\).*index 20 ref",
538 "matchCount": "0",
539 "teardown": [
540 "$TC actions flush action mirred"
541 ]
542 },
543 {
544 "id": "300b",
545 "name": "Add mirred action with duplicate index",
546 "category": [
547 "actions",
548 "mirred"
549 ],
550 "setup": [
551 [
552 "$TC actions flush action mirred",
553 0,
554 1,
555 255
556 ],
557 "$TC actions add action mirred egress redirect index 15 dev lo"
558 ],
559 "cmdUnderTest": "$TC actions add action mirred egress mirror index 15 dev lo",
560 "expExitCode": "255",
561 "verifyCmd": "$TC actions list action mirred",
562 "matchPattern": "action order [0-9]*: mirred \\(.*to device lo\\).*index 15 ref",
563 "matchCount": "1",
564 "teardown": [
565 "$TC actions flush action mirred"
566 ]
567 },
568 {
569 "id": "a70e",
570 "name": "Delete mirred mirror action",
571 "category": [
572 "actions",
573 "mirred"
574 ],
575 "setup": [
576 [
577 "$TC actions flush action mirred",
578 0,
579 1,
580 255
581 ],
582 "$TC actions add action mirred egress mirror index 5 dev lo"
583 ],
584 "cmdUnderTest": "$TC actions del action mirred index 5",
585 "expExitCode": "0",
586 "verifyCmd": "$TC actions list action mirred",
587 "matchPattern": "action order [0-9]*: mirred \\(Egress Mirror to device lo\\).*index 5 ref",
588 "matchCount": "0",
589 "teardown": [
590 "$TC actions flush action mirred"
591 ]
592 },
593 {
594 "id": "3fb3",
595 "name": "Delete mirred redirect action",
596 "category": [
597 "actions",
598 "mirred"
599 ],
600 "setup": [
601 [
602 "$TC actions flush action mirred",
603 0,
604 1,
605 255
606 ],
607 "$TC actions add action mirred egress redirect index 5 dev lo"
608 ],
609 "cmdUnderTest": "$TC actions del action mirred index 5",
610 "expExitCode": "0",
611 "verifyCmd": "$TC actions list action mirred",
612 "matchPattern": "action order [0-9]*: mirred \\(Egress Redirect to device lo\\).*index 5 ref",
613 "matchCount": "0",
614 "teardown": [
615 "$TC actions flush action mirred"
616 ]
617 },
618 {
619 "id": "b078",
620 "name": "Add simple action",
621 "category": [
622 "actions",
623 "simple"
624 ],
625 "setup": [
626 [
627 "$TC actions flush action simple",
628 0,
629 1,
630 255
631 ]
632 ],
633 "cmdUnderTest": "$TC actions add action simple sdata \"A triumph\" index 60",
634 "expExitCode": "0",
635 "verifyCmd": "$TC actions list action simple",
636 "matchPattern": "action order [0-9]*: Simple <A triumph>.*index 60 ref",
637 "matchCount": "1",
638 "teardown": [
639 "$TC actions flush action simple"
640 ]
641 },
642 {
643 "id": "6d4c",
644 "name": "Add simple action with duplicate index",
645 "category": [
646 "actions",
647 "simple"
648 ],
649 "setup": [
650 [
651 "$TC actions flush action simple",
652 0,
653 1,
654 255
655 ],
656 "$TC actions add action simple sdata \"Aruba\" index 4"
657 ],
658 "cmdUnderTest": "$TC actions add action simple sdata \"Jamaica\" index 4",
659 "expExitCode": "255",
660 "verifyCmd": "$TC actions list action simple",
661 "matchPattern": "action order [0-9]*: Simple <Jamaica>.*ref",
662 "matchCount": "0",
663 "teardown": [
664 "$TC actions flush action simple"
665 ]
666 },
667 {
668 "id": "2542",
669 "name": "List simple actions",
670 "category": [
671 "actions",
672 "simple"
673 ],
674 "setup": [
675 [
676 "$TC actions flush action simple",
677 0,
678 1,
679 255
680 ],
681 "$TC actions add action simple sdata \"Rock\"",
682 "$TC actions add action simple sdata \"Paper\"",
683 "$TC actions add action simple sdata \"Scissors\" index 98"
684 ],
685 "cmdUnderTest": "$TC actions list action simple",
686 "expExitCode": "0",
687 "verifyCmd": "$TC actions list action simple",
688 "matchPattern": "action order [0-9]*: Simple <[A-Z][a-z]*>",
689 "matchCount": "3",
690 "teardown": [
691 "$TC actions flush action simple"
692 ]
693 },
694 {
695 "id": "ea67",
696 "name": "Delete simple action",
697 "category": [
698 "actions",
699 "simple"
700 ],
701 "setup": [
702 [
703 "$TC actions flush action simple",
704 0,
705 1,
706 255
707 ],
708 "$TC actions add action simple sdata \"Blinkenlights\" index 1"
709 ],
710 "cmdUnderTest": "$TC actions delete action simple index 1",
711 "expExitCode": "0",
712 "verifyCmd": "$TC actions list action simple",
713 "matchPattern": "action order [0-9]*: Simple <Blinkenlights>.*index 1 ref",
714 "matchCount": "0",
715 "teardown": [
716 "$TC actions flush action simple"
717 ]
718 },
719 {
720 "id": "8ff1",
721 "name": "Flush simple actions",
722 "category": [
723 "actions",
724 "simple"
725 ],
726 "setup": [
727 [
728 "$TC actions flush action simple",
729 0,
730 1,
731 255
732 ],
733 "$TC actions add action simple sdata \"Kirk\"",
734 "$TC actions add action simple sdata \"Spock\" index 50",
735 "$TC actions add action simple sdata \"McCoy\" index 9"
736 ],
737 "cmdUnderTest": "$TC actions flush action simple",
738 "expExitCode": "0",
739 "verifyCmd": "$TC actions list action simple",
740 "matchPattern": "action order [0-9]*: Simple <[A-Z][a-z]*>",
741 "matchCount": "0",
742 "teardown": [
743 ""
744 ]
745 },
746 {
747 "id": "6236",
748 "name": "Add skbedit action with valid mark",
749 "category": [
750 "actions",
751 "skbedit"
752 ],
753 "setup": [
754 [
755 "$TC actions flush action skbedit",
756 0,
757 1,
758 255
759 ]
760 ],
761 "cmdUnderTest": "$TC actions add action skbedit mark 1",
762 "expExitCode": "0",
763 "verifyCmd": "$TC actions list action skbedit",
764 "matchPattern": "action order [0-9]*: skbedit mark 1",
765 "matchCount": "1",
766 "teardown": [
767 "$TC actions flush action skbedit"
768 ]
769 },
770 {
771 "id": "407b",
772 "name": "Add skbedit action with invalid mark",
773 "category": [
774 "actions",
775 "skbedit"
776 ],
777 "setup": [
778 [
779 "$TC actions flush action skbedit",
780 0,
781 1,
782 255
783 ]
784 ],
785 "cmdUnderTest": "$TC actions add action skbedit mark 666777888999",
786 "expExitCode": "255",
787 "verifyCmd": "$TC actions list action skbedit",
788 "matchPattern": "action order [0-9]*: skbedit mark",
789 "matchCount": "0",
790 "teardown": [
791 "$TC actions flush action skbedit"
792 ]
793 },
794 {
795 "id": "081d",
796 "name": "Add skbedit action with priority",
797 "category": [
798 "actions",
799 "skbedit"
800 ],
801 "setup": [
802 [
803 "$TC actions flush action skbedit",
804 0,
805 1,
806 255
807 ]
808 ],
809 "cmdUnderTest": "$TC actions add action skbedit prio 99",
810 "expExitCode": "0",
811 "verifyCmd": "$TC actions list action skbedit",
812 "matchPattern": "action order [0-9]*: skbedit priority :99",
813 "matchCount": "1",
814 "teardown": [
815 "$TC actions flush action skbedit"
816 ]
817 },
818 {
819 "id": "cc37",
820 "name": "Add skbedit action with invalid priority",
821 "category": [
822 "actions",
823 "skbedit"
824 ],
825 "setup": [
826 [
827 "$TC actions flush action skbedit",
828 0,
829 1,
830 255
831 ]
832 ],
833 "cmdUnderTest": "$TC actions add action skbedit prio foo",
834 "expExitCode": "255",
835 "verifyCmd": "$TC actions list action skbedit",
836 "matchPattern": "action order [0-9]*: skbedit priority",
837 "matchCount": "0",
838 "teardown": [
839 "$TC actions flush action skbedit"
840 ]
841 },
842 {
843 "id": "3c95",
844 "name": "Add skbedit action with queue_mapping",
845 "category": [
846 "actions",
847 "skbedit"
848 ],
849 "setup": [
850 [
851 "$TC actions flush action skbedit",
852 0,
853 1,
854 255
855 ]
856 ],
857 "cmdUnderTest": "$TC actions add action skbedit queue_mapping 909",
858 "expExitCode": "0",
859 "verifyCmd": "$TC actions list action skbedit",
860 "matchPattern": "action order [0-9]*: skbedit queue_mapping 909",
861 "matchCount": "1",
862 "teardown": [
863 "$TC actions flush action skbedit"
864 ]
865 },
866 {
867 "id": "985c",
868 "name": "Add skbedit action with invalid queue_mapping",
869 "category": [
870 "actions",
871 "skbedit"
872 ],
873 "setup": [
874 [
875 "$TC actions flush action skbedit",
876 0,
877 1,
878 255
879 ]
880 ],
881 "cmdUnderTest": "$TC actions add action skbedit queue_mapping 67000",
882 "expExitCode": "255",
883 "verifyCmd": "$TC actions list action skbedit",
884 "matchPattern": "action order [0-9]*: skbedit queue_mapping",
885 "matchCount": "0",
886 "teardown": [
887 "$TC actions flush action skbedit"
888 ]
889 },
890 {
891 "id": "224f",
892 "name": "Add skbedit action with ptype host",
893 "category": [
894 "actions",
895 "skbedit"
896 ],
897 "setup": [
898 [
899 "$TC actions flush action skbedit",
900 0,
901 1,
902 255
903 ]
904 ],
905 "cmdUnderTest": "$TC actions add action skbedit ptype host",
906 "expExitCode": "0",
907 "verifyCmd": "$TC actions list action skbedit",
908 "matchPattern": "action order [0-9]*: skbedit ptype host",
909 "matchCount": "1",
910 "teardown": [
911 "$TC actions flush action skbedit"
912 ]
913 },
914 {
915 "id": "d1a3",
916 "name": "Add skbedit action with ptype otherhost",
917 "category": [
918 "actions",
919 "skbedit"
920 ],
921 "setup": [
922 [
923 "$TC actions flush action skbedit",
924 0,
925 1,
926 255
927 ]
928 ],
929 "cmdUnderTest": "$TC actions add action skbedit ptype otherhost",
930 "expExitCode": "0",
931 "verifyCmd": "$TC actions list action skbedit",
932 "matchPattern": "action order [0-9]*: skbedit ptype otherhost",
933 "matchCount": "1",
934 "teardown": [
935 "$TC actions flush action skbedit"
936 ]
937 },
938 {
939 "id": "b9c6",
940 "name": "Add skbedit action with invalid ptype",
941 "category": [
942 "actions",
943 "skbedit"
944 ],
945 "setup": [
946 [
947 "$TC actions flush action skbedit",
948 0,
949 1,
950 255
951 ]
952 ],
953 "cmdUnderTest": "$TC actions add action skbedit ptype openair",
954 "expExitCode": "255",
955 "verifyCmd": "$TC actions list action skbedit",
956 "matchPattern": "action order [0-9]*: skbedit ptype openair",
957 "matchCount": "0",
958 "teardown": [
959 "$TC actions flush action skbedit"
960 ]
961 },
962 {
963 "id": "5172",
964 "name": "List skbedit actions",
965 "category": [
966 "actions",
967 "skbedit"
968 ],
969 "setup": [
970 [
971 "$TC actions flush action skbedit",
972 0,
973 1,
974 255
975 ],
976 "$TC actions add action skbedit ptype otherhost",
977 "$TC actions add action skbedit ptype broadcast",
978 "$TC actions add action skbedit mark 59",
979 "$TC actions add action skbedit mark 409"
980 ],
981 "cmdUnderTest": "$TC actions list action skbedit",
982 "expExitCode": "0",
983 "verifyCmd": "$TC actions list action skbedit",
984 "matchPattern": "action order [0-9]*: skbedit",
985 "matchCount": "4",
986 "teardown": [
987 "$TC actions flush action skbedit"
988 ]
989 },
990 {
991 "id": "a6d6",
992 "name": "Add skbedit action with index",
993 "category": [
994 "actions",
995 "skbedit"
996 ],
997 "setup": [
998 [
999 "$TC actions flush action skbedit",
1000 0,
1001 1,
1002 255
1003 ]
1004 ],
1005 "cmdUnderTest": "$TC actions add action skbedit mark 808 index 4040404040",
1006 "expExitCode": "0",
1007 "verifyCmd": "$TC actions list action skbedit",
1008 "matchPattern": "index 4040404040",
1009 "matchCount": "1",
1010 "teardown": [
1011 "$TC actions flush action skbedit"
1012 ]
1013 },
1014 {
1015 "id": "38f3",
1016 "name": "Delete skbedit action",
1017 "category": [
1018 "actions",
1019 "skbedit"
1020 ],
1021 "setup": [
1022 [
1023 "$TC actions flush action skbedit",
1024 0,
1025 1,
1026 255
1027 ],
1028 "$TC actions add action skbedit mark 42 index 9009"
1029 ],
1030 "cmdUnderTest": "$TC actions del action skbedit index 9009",
1031 "expExitCode": "0",
1032 "verifyCmd": "$TC actions list action skbedit",
1033 "matchPattern": "action order [0-9]*: skbedit mark 42",
1034 "matchCount": "0",
1035 "teardown": [
1036 "$TC actions flush action skbedit"
1037 ]
1038 },
1039 {
1040 "id": "ce97",
1041 "name": "Flush skbedit actions",
1042 "category": [
1043 "actions",
1044 "skbedit"
1045 ],
1046 "setup": [
1047 "$TC actions add action skbedit mark 500",
1048 "$TC actions add action skbedit mark 501",
1049 "$TC actions add action skbedit mark 502",
1050 "$TC actions add action skbedit mark 503",
1051 "$TC actions add action skbedit mark 504",
1052 "$TC actions add action skbedit mark 505",
1053 "$TC actions add action skbedit mark 506"
1054 ],
1055 "cmdUnderTest": "$TC actions flush action skbedit",
1056 "expExitCode": "0",
1057 "verifyCmd": "$TC actions list action skbedit",
1058 "matchPattern": "action order [0-9]*: skbedit",
1059 "matchCount": "0",
1060 "teardown": [
1061 "$TC actions flush action skbedit"
1062 ]
1063 },
1064 {
1065 "id": "f02c",
1066 "name": "Replace gact action",
1067 "category": [
1068 "actions",
1069 "gact"
1070 ],
1071 "setup": [
1072 [
1073 "$TC actions flush action gact",
1074 0,
1075 1,
1076 255
1077 ],
1078 "$TC actions add action drop index 10",
1079 "$TC actions add action drop index 12"
1080 ],
1081 "cmdUnderTest": "$TC actions replace action ok index 12",
1082 "expExitCode": "0",
1083 "verifyCmd": "$TC actions ls action gact",
1084 "matchPattern": "action order [0-9]*: gact action pass",
1085 "matchCount": "1",
1086 "teardown": [
1087 "$TC actions flush action gact"
1088 ]
1089 },
1090 {
1091 "id": "525f",
1092 "name": "Get gact action by index",
1093 "category": [
1094 "actions",
1095 "gact"
1096 ],
1097 "setup": [
1098 [
1099 "$TC actions flush action gact",
1100 0,
1101 1,
1102 255
1103 ],
1104 "$TC actions add action drop index 3900800700"
1105 ],
1106 "cmdUnderTest": "$TC actions get action gact index 3900800700",
1107 "expExitCode": "0",
1108 "verifyCmd": "$TC actions get action gact index 3900800700",
1109 "matchPattern": "index 3900800700",
1110 "matchCount": "1",
1111 "teardown": [
1112 "$TC actions flush action gact"
1113 ]
1114 }
1115] \ No newline at end of file
diff --git a/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json b/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
new file mode 100644
index 000000000000..c727b96a59b0
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
@@ -0,0 +1,21 @@
1[
2 {
3 "id": "e9a3",
4 "name": "Add u32 with source match",
5 "category": [
6 "filter",
7 "u32"
8 ],
9 "setup": [
10 "$TC qdisc add dev $DEV1 ingress"
11 ],
12 "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: protocol ip prio 1 u32 match ip src 127.0.0.1/32 flowid 1:1 action ok",
13 "expExitCode": "0",
14 "verifyCmd": "$TC filter show dev $DEV1 parent ffff:",
15 "matchPattern": "match 7f000002/ffffffff at 12",
16 "matchCount": "0",
17 "teardown": [
18 "$TC qdisc del dev $DEV1 ingress"
19 ]
20 }
21] \ No newline at end of file
diff --git a/tools/testing/selftests/tc-testing/tdc.py b/tools/testing/selftests/tc-testing/tdc.py
new file mode 100755
index 000000000000..cd61b7844c0d
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tdc.py
@@ -0,0 +1,413 @@
1#!/usr/bin/env python3
2
3"""
4tdc.py - Linux tc (Traffic Control) unit test driver
5
6Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com>
7"""
8
9import re
10import os
11import sys
12import argparse
13import json
14import subprocess
15from collections import OrderedDict
16from string import Template
17
18from tdc_config import *
19from tdc_helper import *
20
21
22USE_NS = True
23
24
25def replace_keywords(cmd):
26 """
27 For a given executable command, substitute any known
28 variables contained within NAMES with the correct values
29 """
30 tcmd = Template(cmd)
31 subcmd = tcmd.safe_substitute(NAMES)
32 return subcmd
33
34
35def exec_cmd(command, nsonly=True):
36 """
37 Perform any required modifications on an executable command, then run
38 it in a subprocess and return the results.
39 """
40 if (USE_NS and nsonly):
41 command = 'ip netns exec $NS ' + command
42
43 if '$' in command:
44 command = replace_keywords(command)
45
46 proc = subprocess.Popen(command,
47 shell=True,
48 stdout=subprocess.PIPE,
49 stderr=subprocess.PIPE)
50 (rawout, serr) = proc.communicate()
51
52 if proc.returncode != 0:
53 foutput = serr.decode("utf-8")
54 else:
55 foutput = rawout.decode("utf-8")
56
57 proc.stdout.close()
58 proc.stderr.close()
59 return proc, foutput
60
61
62def prepare_env(cmdlist):
63 """
64 Execute the setup/teardown commands for a test case. Optionally
65 terminate test execution if the command fails.
66 """
67 for cmdinfo in cmdlist:
68 if (type(cmdinfo) == list):
69 exit_codes = cmdinfo[1:]
70 cmd = cmdinfo[0]
71 else:
72 exit_codes = [0]
73 cmd = cmdinfo
74
75 if (len(cmd) == 0):
76 continue
77
78 (proc, foutput) = exec_cmd(cmd)
79
80 if proc.returncode not in exit_codes:
81 print
82 print("Could not execute:")
83 print(cmd)
84 print("\nError message:")
85 print(foutput)
86 print("\nAborting test run.")
87 ns_destroy()
88 exit(1)
89
90
91def test_runner(filtered_tests):
92 """
93 Driver function for the unit tests.
94
95 Prints information about the tests being run, executes the setup and
96 teardown commands and the command under test itself. Also determines
97 success/failure based on the information in the test case and generates
98 TAP output accordingly.
99 """
100 testlist = filtered_tests
101 tcount = len(testlist)
102 index = 1
103 tap = str(index) + ".." + str(tcount) + "\n"
104
105 for tidx in testlist:
106 result = True
107 tresult = ""
108 print("Test " + tidx["id"] + ": " + tidx["name"])
109 prepare_env(tidx["setup"])
110 (p, procout) = exec_cmd(tidx["cmdUnderTest"])
111 exit_code = p.returncode
112
113 if (exit_code != int(tidx["expExitCode"])):
114 result = False
115 print("exit:", exit_code, int(tidx["expExitCode"]))
116 print(procout)
117 else:
118 match_pattern = re.compile(str(tidx["matchPattern"]), re.DOTALL)
119 (p, procout) = exec_cmd(tidx["verifyCmd"])
120 match_index = re.findall(match_pattern, procout)
121 if len(match_index) != int(tidx["matchCount"]):
122 result = False
123
124 if result == True:
125 tresult += "ok "
126 else:
127 tresult += "not ok "
128 tap += tresult + str(index) + " " + tidx["id"] + " " + tidx["name"] + "\n"
129
130 if result == False:
131 tap += procout
132
133 prepare_env(tidx["teardown"])
134 index += 1
135
136 return tap
137
138
139def ns_create():
140 """
141 Create the network namespace in which the tests will be run and set up
142 the required network devices for it.
143 """
144 if (USE_NS):
145 cmd = 'ip netns add $NS'
146 exec_cmd(cmd, False)
147 cmd = 'ip link add $DEV0 type veth peer name $DEV1'
148 exec_cmd(cmd, False)
149 cmd = 'ip link set $DEV1 netns $NS'
150 exec_cmd(cmd, False)
151 cmd = 'ip link set $DEV0 up'
152 exec_cmd(cmd, False)
153 cmd = 'ip -s $NS link set $DEV1 up'
154 exec_cmd(cmd, False)
155
156
157def ns_destroy():
158 """
159 Destroy the network namespace for testing (and any associated network
160 devices as well)
161 """
162 if (USE_NS):
163 cmd = 'ip netns delete $NS'
164 exec_cmd(cmd, False)
165
166
167def has_blank_ids(idlist):
168 """
169 Search the list for empty ID fields and return true/false accordingly.
170 """
171 return not(all(k for k in idlist))
172
173
174def load_from_file(filename):
175 """
176 Open the JSON file containing the test cases and return them as an
177 ordered dictionary object.
178 """
179 with open(filename) as test_data:
180 testlist = json.load(test_data, object_pairs_hook=OrderedDict)
181 idlist = get_id_list(testlist)
182 if (has_blank_ids(idlist)):
183 for k in testlist:
184 k['filename'] = filename
185 return testlist
186
187
188def args_parse():
189 """
190 Create the argument parser.
191 """
192 parser = argparse.ArgumentParser(description='Linux TC unit tests')
193 return parser
194
195
196def set_args(parser):
197 """
198 Set the command line arguments for tdc.
199 """
200 parser.add_argument('-p', '--path', type=str,
201 help='The full path to the tc executable to use')
202 parser.add_argument('-c', '--category', type=str, nargs='?', const='+c',
203 help='Run tests only from the specified category, or if no category is specified, list known categories.')
204 parser.add_argument('-f', '--file', type=str,
205 help='Run tests from the specified file')
206 parser.add_argument('-l', '--list', type=str, nargs='?', const="", metavar='CATEGORY',
207 help='List all test cases, or those only within the specified category')
208 parser.add_argument('-s', '--show', type=str, nargs=1, metavar='ID', dest='showID',
209 help='Display the test case with specified id')
210 parser.add_argument('-e', '--execute', type=str, nargs=1, metavar='ID',
211 help='Execute the single test case with specified ID')
212 parser.add_argument('-i', '--id', action='store_true', dest='gen_id',
213 help='Generate ID numbers for new test cases')
214 return parser
215 return parser
216
217
218def check_default_settings(args):
219 """
220 Process any arguments overriding the default settings, and ensure the
221 settings are correct.
222 """
223 # Allow for overriding specific settings
224 global NAMES
225
226 if args.path != None:
227 NAMES['TC'] = args.path
228 if not os.path.isfile(NAMES['TC']):
229 print("The specified tc path " + NAMES['TC'] + " does not exist.")
230 exit(1)
231
232
233def get_id_list(alltests):
234 """
235 Generate a list of all IDs in the test cases.
236 """
237 return [x["id"] for x in alltests]
238
239
240def check_case_id(alltests):
241 """
242 Check for duplicate test case IDs.
243 """
244 idl = get_id_list(alltests)
245 return [x for x in idl if idl.count(x) > 1]
246
247
248def does_id_exist(alltests, newid):
249 """
250 Check if a given ID already exists in the list of test cases.
251 """
252 idl = get_id_list(alltests)
253 return (any(newid == x for x in idl))
254
255
256def generate_case_ids(alltests):
257 """
258 If a test case has a blank ID field, generate a random hex ID for it
259 and then write the test cases back to disk.
260 """
261 import random
262 for c in alltests:
263 if (c["id"] == ""):
264 while True:
265 newid = str('%04x' % random.randrange(16**4))
266 if (does_id_exist(alltests, newid)):
267 continue
268 else:
269 c['id'] = newid
270 break
271
272 ufilename = []
273 for c in alltests:
274 if ('filename' in c):
275 ufilename.append(c['filename'])
276 ufilename = get_unique_item(ufilename)
277 for f in ufilename:
278 testlist = []
279 for t in alltests:
280 if 'filename' in t:
281 if t['filename'] == f:
282 del t['filename']
283 testlist.append(t)
284 outfile = open(f, "w")
285 json.dump(testlist, outfile, indent=4)
286 outfile.close()
287
288
289def get_test_cases(args):
290 """
291 If a test case file is specified, retrieve tests from that file.
292 Otherwise, glob for all json files in subdirectories and load from
293 each one.
294 """
295 import fnmatch
296 if args.file != None:
297 if not os.path.isfile(args.file):
298 print("The specified test case file " + args.file + " does not exist.")
299 exit(1)
300 flist = [args.file]
301 else:
302 flist = []
303 for root, dirnames, filenames in os.walk('tc-tests'):
304 for filename in fnmatch.filter(filenames, '*.json'):
305 flist.append(os.path.join(root, filename))
306 alltests = list()
307 for casefile in flist:
308 alltests = alltests + (load_from_file(casefile))
309 return alltests
310
311
312def set_operation_mode(args):
313 """
314 Load the test case data and process remaining arguments to determine
315 what the script should do for this run, and call the appropriate
316 function.
317 """
318 alltests = get_test_cases(args)
319
320 if args.gen_id:
321 idlist = get_id_list(alltests)
322 if (has_blank_ids(idlist)):
323 alltests = generate_case_ids(alltests)
324 else:
325 print("No empty ID fields found in test files.")
326 exit(0)
327
328 duplicate_ids = check_case_id(alltests)
329 if (len(duplicate_ids) > 0):
330 print("The following test case IDs are not unique:")
331 print(str(set(duplicate_ids)))
332 print("Please correct them before continuing.")
333 exit(1)
334
335 ucat = get_test_categories(alltests)
336
337 if args.showID:
338 show_test_case_by_id(alltests, args.showID[0])
339 exit(0)
340
341 if args.execute:
342 target_id = args.execute[0]
343 else:
344 target_id = ""
345
346 if args.category:
347 if (args.category == '+c'):
348 print("Available categories:")
349 print_sll(ucat)
350 exit(0)
351 else:
352 target_category = args.category
353 else:
354 target_category = ""
355
356
357 testcases = get_categorized_testlist(alltests, ucat)
358
359 if args.list:
360 if (len(args.list) == 0):
361 list_test_cases(alltests)
362 exit(0)
363 elif(len(args.list > 0)):
364 if (args.list not in ucat):
365 print("Unknown category " + args.list)
366 print("Available categories:")
367 print_sll(ucat)
368 exit(1)
369 list_test_cases(testcases[args.list])
370 exit(0)
371
372 if (os.geteuid() != 0):
373 print("This script must be run with root privileges.\n")
374 exit(1)
375
376 ns_create()
377
378 if (len(target_category) == 0):
379 if (len(target_id) > 0):
380 alltests = list(filter(lambda x: target_id in x['id'], alltests))
381 if (len(alltests) == 0):
382 print("Cannot find a test case with ID matching " + target_id)
383 exit(1)
384 catresults = test_runner(alltests)
385 print("All test results: " + "\n\n" + catresults)
386 elif (len(target_category) > 0):
387 if (target_category not in ucat):
388 print("Specified category is not present in this file.")
389 exit(1)
390 else:
391 catresults = test_runner(testcases[target_category])
392 print("Category " + target_category + "\n\n" + catresults)
393
394 ns_destroy()
395
396
397def main():
398 """
399 Start of execution; set up argument parser and get the arguments,
400 and start operations.
401 """
402 parser = args_parse()
403 parser = set_args(parser)
404 (args, remaining) = parser.parse_known_args()
405 check_default_settings(args)
406
407 set_operation_mode(args)
408
409 exit(0)
410
411
412if __name__ == "__main__":
413 main()
diff --git a/tools/testing/selftests/tc-testing/tdc_config.py b/tools/testing/selftests/tc-testing/tdc_config.py
new file mode 100644
index 000000000000..01087375a7c3
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tdc_config.py
@@ -0,0 +1,17 @@
1"""
2tdc_config.py - tdc user-specified values
3
4Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com>
5"""
6
7# Dictionary containing all values that can be substituted in executable
8# commands.
9NAMES = {
10 # Substitute your own tc path here
11 'TC': '/sbin/tc',
12 # Name of veth devices to be created for the namespace
13 'DEV0': 'v0p0',
14 'DEV1': 'v0p1',
15 # Name of the namespace to use
16 'NS': 'tcut'
17 }
diff --git a/tools/testing/selftests/tc-testing/tdc_helper.py b/tools/testing/selftests/tc-testing/tdc_helper.py
new file mode 100644
index 000000000000..c3254f861fb2
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tdc_helper.py
@@ -0,0 +1,75 @@
1"""
2tdc_helper.py - tdc helper functions
3
4Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com>
5"""
6
7def get_categorized_testlist(alltests, ucat):
8 """ Sort the master test list into categories. """
9 testcases = dict()
10
11 for category in ucat:
12 testcases[category] = list(filter(lambda x: category in x['category'], alltests))
13
14 return(testcases)
15
16
17def get_unique_item(lst):
18 """ For a list, return a set of the unique items in the list. """
19 return list(set(lst))
20
21
22def get_test_categories(alltests):
23 """ Discover all unique test categories present in the test case file. """
24 ucat = []
25 for t in alltests:
26 ucat.extend(get_unique_item(t['category']))
27 ucat = get_unique_item(ucat)
28 return ucat
29
30def list_test_cases(testlist):
31 """ Print IDs and names of all test cases. """
32 for curcase in testlist:
33 print(curcase['id'] + ': (' + ', '.join(curcase['category']) + ") " + curcase['name'])
34
35
36def list_categories(testlist):
37 """ Show all categories that are present in a test case file. """
38 categories = set(map(lambda x: x['category'], testlist))
39 print("Available categories:")
40 print(", ".join(str(s) for s in categories))
41 print("")
42
43
44def print_list(cmdlist):
45 """ Print a list of strings prepended with a tab. """
46 for l in cmdlist:
47 if (type(l) == list):
48 print("\t" + str(l[0]))
49 else:
50 print("\t" + str(l))
51
52
53def print_sll(items):
54 print("\n".join(str(s) for s in items))
55
56
57def print_test_case(tcase):
58 """ Pretty-printing of a given test case. """
59 for k in tcase.keys():
60 if (type(tcase[k]) == list):
61 print(k + ":")
62 print_list(tcase[k])
63 else:
64 print(k + ": " + tcase[k])
65
66
67def show_test_case_by_id(testlist, caseID):
68 """ Find the specified test case to pretty-print. """
69 if not any(d.get('id', None) == caseID for d in testlist):
70 print("That ID does not exist.")
71 exit(1)
72 else:
73 print_test_case(next((d for d in testlist if d['id'] == caseID)))
74
75
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile
index 5fa1d7e9a915..5801bbefbe89 100644
--- a/tools/testing/selftests/timers/Makefile
+++ b/tools/testing/selftests/timers/Makefile
@@ -1,6 +1,6 @@
1BUILD_FLAGS = -DKTEST 1BUILD_FLAGS = -DKTEST
2CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS) 2CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS)
3LDFLAGS += -lrt -lpthread 3LDFLAGS += -lrt -lpthread -lm
4 4
5# these are all "safe" tests that don't modify 5# these are all "safe" tests that don't modify
6# system time or require escalated privileges 6# system time or require escalated privileges
@@ -8,7 +8,7 @@ TEST_GEN_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
8 inconsistency-check raw_skew threadtest rtctest 8 inconsistency-check raw_skew threadtest rtctest
9 9
10TEST_GEN_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \ 10TEST_GEN_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \
11 skew_consistency clocksource-switch leap-a-day \ 11 skew_consistency clocksource-switch freq-step leap-a-day \
12 leapcrash set-tai set-2038 set-tz 12 leapcrash set-tai set-2038 set-tz
13 13
14 14
@@ -24,6 +24,7 @@ run_destructive_tests: run_tests
24 ./change_skew 24 ./change_skew
25 ./skew_consistency 25 ./skew_consistency
26 ./clocksource-switch 26 ./clocksource-switch
27 ./freq-step
27 ./leap-a-day -s -i 10 28 ./leap-a-day -s -i 10
28 ./leapcrash 29 ./leapcrash
29 ./set-tz 30 ./set-tz
diff --git a/tools/testing/selftests/timers/freq-step.c b/tools/testing/selftests/timers/freq-step.c
new file mode 100644
index 000000000000..e8c61830825a
--- /dev/null
+++ b/tools/testing/selftests/timers/freq-step.c
@@ -0,0 +1,268 @@
1/*
2 * This test checks the response of the system clock to frequency
3 * steps made with adjtimex(). The frequency error and stability of
4 * the CLOCK_MONOTONIC clock relative to the CLOCK_MONOTONIC_RAW clock
5 * is measured in two intervals following the step. The test fails if
6 * values from the second interval exceed specified limits.
7 *
8 * Copyright (C) Miroslav Lichvar <mlichvar@redhat.com> 2017
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 */
19
20#include <math.h>
21#include <stdio.h>
22#include <sys/timex.h>
23#include <time.h>
24#include <unistd.h>
25
26#include "../kselftest.h"
27
28#define SAMPLES 100
29#define SAMPLE_READINGS 10
30#define MEAN_SAMPLE_INTERVAL 0.1
31#define STEP_INTERVAL 1.0
32#define MAX_PRECISION 100e-9
33#define MAX_FREQ_ERROR 10e-6
34#define MAX_STDDEV 1000e-9
35
36struct sample {
37 double offset;
38 double time;
39};
40
41static time_t mono_raw_base;
42static time_t mono_base;
43static long user_hz;
44static double precision;
45static double mono_freq_offset;
46
47static double diff_timespec(struct timespec *ts1, struct timespec *ts2)
48{
49 return ts1->tv_sec - ts2->tv_sec + (ts1->tv_nsec - ts2->tv_nsec) / 1e9;
50}
51
52static double get_sample(struct sample *sample)
53{
54 double delay, mindelay = 0.0;
55 struct timespec ts1, ts2, ts3;
56 int i;
57
58 for (i = 0; i < SAMPLE_READINGS; i++) {
59 clock_gettime(CLOCK_MONOTONIC_RAW, &ts1);
60 clock_gettime(CLOCK_MONOTONIC, &ts2);
61 clock_gettime(CLOCK_MONOTONIC_RAW, &ts3);
62
63 ts1.tv_sec -= mono_raw_base;
64 ts2.tv_sec -= mono_base;
65 ts3.tv_sec -= mono_raw_base;
66
67 delay = diff_timespec(&ts3, &ts1);
68 if (delay <= 1e-9) {
69 i--;
70 continue;
71 }
72
73 if (!i || delay < mindelay) {
74 sample->offset = diff_timespec(&ts2, &ts1);
75 sample->offset -= delay / 2.0;
76 sample->time = ts1.tv_sec + ts1.tv_nsec / 1e9;
77 mindelay = delay;
78 }
79 }
80
81 return mindelay;
82}
83
84static void reset_ntp_error(void)
85{
86 struct timex txc;
87
88 txc.modes = ADJ_SETOFFSET;
89 txc.time.tv_sec = 0;
90 txc.time.tv_usec = 0;
91
92 if (adjtimex(&txc) < 0) {
93 perror("[FAIL] adjtimex");
94 ksft_exit_fail();
95 }
96}
97
98static void set_frequency(double freq)
99{
100 struct timex txc;
101 int tick_offset;
102
103 tick_offset = 1e6 * freq / user_hz;
104
105 txc.modes = ADJ_TICK | ADJ_FREQUENCY;
106 txc.tick = 1000000 / user_hz + tick_offset;
107 txc.freq = (1e6 * freq - user_hz * tick_offset) * (1 << 16);
108
109 if (adjtimex(&txc) < 0) {
110 perror("[FAIL] adjtimex");
111 ksft_exit_fail();
112 }
113}
114
115static void regress(struct sample *samples, int n, double *intercept,
116 double *slope, double *r_stddev, double *r_max)
117{
118 double x, y, r, x_sum, y_sum, xy_sum, x2_sum, r2_sum;
119 int i;
120
121 x_sum = 0.0, y_sum = 0.0, xy_sum = 0.0, x2_sum = 0.0;
122
123 for (i = 0; i < n; i++) {
124 x = samples[i].time;
125 y = samples[i].offset;
126
127 x_sum += x;
128 y_sum += y;
129 xy_sum += x * y;
130 x2_sum += x * x;
131 }
132
133 *slope = (xy_sum - x_sum * y_sum / n) / (x2_sum - x_sum * x_sum / n);
134 *intercept = (y_sum - *slope * x_sum) / n;
135
136 *r_max = 0.0, r2_sum = 0.0;
137
138 for (i = 0; i < n; i++) {
139 x = samples[i].time;
140 y = samples[i].offset;
141 r = fabs(x * *slope + *intercept - y);
142 if (*r_max < r)
143 *r_max = r;
144 r2_sum += r * r;
145 }
146
147 *r_stddev = sqrt(r2_sum / n);
148}
149
150static int run_test(int calibration, double freq_base, double freq_step)
151{
152 struct sample samples[SAMPLES];
153 double intercept, slope, stddev1, max1, stddev2, max2;
154 double freq_error1, freq_error2;
155 int i;
156
157 set_frequency(freq_base);
158
159 for (i = 0; i < 10; i++)
160 usleep(1e6 * MEAN_SAMPLE_INTERVAL / 10);
161
162 reset_ntp_error();
163
164 set_frequency(freq_base + freq_step);
165
166 for (i = 0; i < 10; i++)
167 usleep(rand() % 2000000 * STEP_INTERVAL / 10);
168
169 set_frequency(freq_base);
170
171 for (i = 0; i < SAMPLES; i++) {
172 usleep(rand() % 2000000 * MEAN_SAMPLE_INTERVAL);
173 get_sample(&samples[i]);
174 }
175
176 if (calibration) {
177 regress(samples, SAMPLES, &intercept, &slope, &stddev1, &max1);
178 mono_freq_offset = slope;
179 printf("CLOCK_MONOTONIC_RAW frequency offset: %11.3f ppm\n",
180 1e6 * mono_freq_offset);
181 return 0;
182 }
183
184 regress(samples, SAMPLES / 2, &intercept, &slope, &stddev1, &max1);
185 freq_error1 = slope * (1.0 - mono_freq_offset) - mono_freq_offset -
186 freq_base;
187
188 regress(samples + SAMPLES / 2, SAMPLES / 2, &intercept, &slope,
189 &stddev2, &max2);
190 freq_error2 = slope * (1.0 - mono_freq_offset) - mono_freq_offset -
191 freq_base;
192
193 printf("%6.0f %+10.3f %6.0f %7.0f %+10.3f %6.0f %7.0f\t",
194 1e6 * freq_step,
195 1e6 * freq_error1, 1e9 * stddev1, 1e9 * max1,
196 1e6 * freq_error2, 1e9 * stddev2, 1e9 * max2);
197
198 if (fabs(freq_error2) > MAX_FREQ_ERROR || stddev2 > MAX_STDDEV) {
199 printf("[FAIL]\n");
200 return 1;
201 }
202
203 printf("[OK]\n");
204 return 0;
205}
206
207static void init_test(void)
208{
209 struct timespec ts;
210 struct sample sample;
211
212 if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts)) {
213 perror("[FAIL] clock_gettime(CLOCK_MONOTONIC_RAW)");
214 ksft_exit_fail();
215 }
216
217 mono_raw_base = ts.tv_sec;
218
219 if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
220 perror("[FAIL] clock_gettime(CLOCK_MONOTONIC)");
221 ksft_exit_fail();
222 }
223
224 mono_base = ts.tv_sec;
225
226 user_hz = sysconf(_SC_CLK_TCK);
227
228 precision = get_sample(&sample) / 2.0;
229 printf("CLOCK_MONOTONIC_RAW+CLOCK_MONOTONIC precision: %.0f ns\t\t",
230 1e9 * precision);
231
232 if (precision > MAX_PRECISION) {
233 printf("[SKIP]\n");
234 ksft_exit_skip();
235 }
236
237 printf("[OK]\n");
238 srand(ts.tv_sec ^ ts.tv_nsec);
239
240 run_test(1, 0.0, 0.0);
241}
242
243int main(int argc, char **argv)
244{
245 double freq_base, freq_step;
246 int i, j, fails = 0;
247
248 init_test();
249
250 printf("Checking response to frequency step:\n");
251 printf(" Step 1st interval 2nd interval\n");
252 printf(" Freq Dev Max Freq Dev Max\n");
253
254 for (i = 2; i >= 0; i--) {
255 for (j = 0; j < 5; j++) {
256 freq_base = (rand() % (1 << 24) - (1 << 23)) / 65536e6;
257 freq_step = 10e-6 * (1 << (6 * i));
258 fails += run_test(0, freq_base, freq_step);
259 }
260 }
261
262 set_frequency(0.0);
263
264 if (fails)
265 ksft_exit_fail();
266
267 ksft_exit_pass();
268}
diff --git a/tools/testing/selftests/timers/inconsistency-check.c b/tools/testing/selftests/timers/inconsistency-check.c
index caf1bc9257c4..74c60e8759a0 100644
--- a/tools/testing/selftests/timers/inconsistency-check.c
+++ b/tools/testing/selftests/timers/inconsistency-check.c
@@ -118,7 +118,7 @@ int consistency_test(int clock_type, unsigned long seconds)
118 start_str = ctime(&t); 118 start_str = ctime(&t);
119 119
120 while (seconds == -1 || now - then < seconds) { 120 while (seconds == -1 || now - then < seconds) {
121 inconsistent = 0; 121 inconsistent = -1;
122 122
123 /* Fill list */ 123 /* Fill list */
124 for (i = 0; i < CALLS_PER_LOOP; i++) 124 for (i = 0; i < CALLS_PER_LOOP; i++)
@@ -130,7 +130,7 @@ int consistency_test(int clock_type, unsigned long seconds)
130 inconsistent = i; 130 inconsistent = i;
131 131
132 /* display inconsistency */ 132 /* display inconsistency */
133 if (inconsistent) { 133 if (inconsistent >= 0) {
134 unsigned long long delta; 134 unsigned long long delta;
135 135
136 printf("\%s\n", start_str); 136 printf("\%s\n", start_str);
diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c
index 0692d99b6d8f..2d89b5f686b1 100644
--- a/tools/usb/testusb.c
+++ b/tools/usb/testusb.c
@@ -387,15 +387,17 @@ int main (int argc, char **argv)
387 /* pick defaults that works with all speeds, without short packets. 387 /* pick defaults that works with all speeds, without short packets.
388 * 388 *
389 * Best per-frame data rates: 389 * Best per-frame data rates:
390 * high speed, bulk 512 * 13 * 8 = 53248 390 * super speed,bulk 1024 * 16 * 8 = 131072
391 * interrupt 1024 * 3 * 8 = 24576 391 * interrupt 1024 * 3 * 8 = 24576
392 * full speed, bulk/intr 64 * 19 = 1216 392 * high speed, bulk 512 * 13 * 8 = 53248
393 * interrupt 64 * 1 = 64 393 * interrupt 1024 * 3 * 8 = 24576
394 * low speed, interrupt 8 * 1 = 8 394 * full speed, bulk/intr 64 * 19 = 1216
395 * interrupt 64 * 1 = 64
396 * low speed, interrupt 8 * 1 = 8
395 */ 397 */
396 param.iterations = 1000; 398 param.iterations = 1000;
397 param.length = 1024; 399 param.length = 1024;
398 param.vary = 512; 400 param.vary = 1024;
399 param.sglen = 32; 401 param.sglen = 32;
400 402
401 /* for easy use when hotplugging */ 403 /* for easy use when hotplugging */
@@ -457,7 +459,7 @@ usage:
457 "\t-c iterations default 1000\n" 459 "\t-c iterations default 1000\n"
458 "\t-s transfer length default 1024\n" 460 "\t-s transfer length default 1024\n"
459 "\t-g sglen default 32\n" 461 "\t-g sglen default 32\n"
460 "\t-v vary default 512\n", 462 "\t-v vary default 1024\n",
461 argv[0]); 463 argv[0]);
462 return 1; 464 return 1;
463 } 465 }
diff --git a/tools/usb/usbip/libsrc/vhci_driver.c b/tools/usb/usbip/libsrc/vhci_driver.c
index f659c146cdc8..9bd2cd71645d 100644
--- a/tools/usb/usbip/libsrc/vhci_driver.c
+++ b/tools/usb/usbip/libsrc/vhci_driver.c
@@ -7,6 +7,7 @@
7#include <limits.h> 7#include <limits.h>
8#include <netdb.h> 8#include <netdb.h>
9#include <libudev.h> 9#include <libudev.h>
10#include <dirent.h>
10#include "sysfs_utils.h" 11#include "sysfs_utils.h"
11 12
12#undef PROGNAME 13#undef PROGNAME
@@ -35,18 +36,11 @@ err:
35 return NULL; 36 return NULL;
36} 37}
37 38
38
39
40static int parse_status(const char *value) 39static int parse_status(const char *value)
41{ 40{
42 int ret = 0; 41 int ret = 0;
43 char *c; 42 char *c;
44 43
45
46 for (int i = 0; i < vhci_driver->nports; i++)
47 memset(&vhci_driver->idev[i], 0, sizeof(vhci_driver->idev[i]));
48
49
50 /* skip a header line */ 44 /* skip a header line */
51 c = strchr(value, '\n'); 45 c = strchr(value, '\n');
52 if (!c) 46 if (!c)
@@ -57,9 +51,11 @@ static int parse_status(const char *value)
57 int port, status, speed, devid; 51 int port, status, speed, devid;
58 unsigned long socket; 52 unsigned long socket;
59 char lbusid[SYSFS_BUS_ID_SIZE]; 53 char lbusid[SYSFS_BUS_ID_SIZE];
54 struct usbip_imported_device *idev;
55 char hub[3];
60 56
61 ret = sscanf(c, "%d %d %d %x %lx %31s\n", 57 ret = sscanf(c, "%2s %d %d %d %x %lx %31s\n",
62 &port, &status, &speed, 58 hub, &port, &status, &speed,
63 &devid, &socket, lbusid); 59 &devid, &socket, lbusid);
64 60
65 if (ret < 5) { 61 if (ret < 5) {
@@ -67,34 +63,36 @@ static int parse_status(const char *value)
67 BUG(); 63 BUG();
68 } 64 }
69 65
70 dbg("port %d status %d speed %d devid %x", 66 dbg("hub %s port %d status %d speed %d devid %x",
71 port, status, speed, devid); 67 hub, port, status, speed, devid);
72 dbg("socket %lx lbusid %s", socket, lbusid); 68 dbg("socket %lx lbusid %s", socket, lbusid);
73 69
74
75 /* if a device is connected, look at it */ 70 /* if a device is connected, look at it */
76 { 71 idev = &vhci_driver->idev[port];
77 struct usbip_imported_device *idev = &vhci_driver->idev[port]; 72 memset(idev, 0, sizeof(*idev));
73
74 if (strncmp("hs", hub, 2) == 0)
75 idev->hub = HUB_SPEED_HIGH;
76 else /* strncmp("ss", hub, 2) == 0 */
77 idev->hub = HUB_SPEED_SUPER;
78 78
79 idev->port = port; 79 idev->port = port;
80 idev->status = status; 80 idev->status = status;
81 81
82 idev->devid = devid; 82 idev->devid = devid;
83 83
84 idev->busnum = (devid >> 16); 84 idev->busnum = (devid >> 16);
85 idev->devnum = (devid & 0x0000ffff); 85 idev->devnum = (devid & 0x0000ffff);
86 86
87 if (idev->status != VDEV_ST_NULL 87 if (idev->status != VDEV_ST_NULL
88 && idev->status != VDEV_ST_NOTASSIGNED) { 88 && idev->status != VDEV_ST_NOTASSIGNED) {
89 idev = imported_device_init(idev, lbusid); 89 idev = imported_device_init(idev, lbusid);
90 if (!idev) { 90 if (!idev) {
91 dbg("imported_device_init failed"); 91 dbg("imported_device_init failed");
92 return -1; 92 return -1;
93 }
94 } 93 }
95 } 94 }
96 95
97
98 /* go to the next line */ 96 /* go to the next line */
99 c = strchr(c, '\n'); 97 c = strchr(c, '\n');
100 if (!c) 98 if (!c)
@@ -107,18 +105,33 @@ static int parse_status(const char *value)
107 return 0; 105 return 0;
108} 106}
109 107
108#define MAX_STATUS_NAME 16
109
110static int refresh_imported_device_list(void) 110static int refresh_imported_device_list(void)
111{ 111{
112 const char *attr_status; 112 const char *attr_status;
113 char status[MAX_STATUS_NAME+1] = "status";
114 int i, ret;
113 115
114 attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device, 116 for (i = 0; i < vhci_driver->ncontrollers; i++) {
115 "status"); 117 if (i > 0)
116 if (!attr_status) { 118 snprintf(status, sizeof(status), "status.%d", i);
117 err("udev_device_get_sysattr_value failed"); 119
118 return -1; 120 attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device,
121 status);
122 if (!attr_status) {
123 err("udev_device_get_sysattr_value failed");
124 return -1;
125 }
126
127 dbg("controller %d", i);
128
129 ret = parse_status(attr_status);
130 if (ret != 0)
131 return ret;
119 } 132 }
120 133
121 return parse_status(attr_status); 134 return 0;
122} 135}
123 136
124static int get_nports(void) 137static int get_nports(void)
@@ -134,6 +147,33 @@ static int get_nports(void)
134 return (int)strtoul(attr_nports, NULL, 10); 147 return (int)strtoul(attr_nports, NULL, 10);
135} 148}
136 149
150static int vhci_hcd_filter(const struct dirent *dirent)
151{
152 return strcmp(dirent->d_name, "vhci_hcd") >= 0;
153}
154
155static int get_ncontrollers(void)
156{
157 struct dirent **namelist;
158 struct udev_device *platform;
159 int n;
160
161 platform = udev_device_get_parent(vhci_driver->hc_device);
162 if (platform == NULL)
163 return -1;
164
165 n = scandir(udev_device_get_syspath(platform), &namelist, vhci_hcd_filter, NULL);
166 if (n < 0)
167 err("scandir failed");
168 else {
169 for (int i = 0; i < n; i++)
170 free(namelist[i]);
171 free(namelist);
172 }
173
174 return n;
175}
176
137/* 177/*
138 * Read the given port's record. 178 * Read the given port's record.
139 * 179 *
@@ -213,16 +253,31 @@ int usbip_vhci_driver_open(void)
213 vhci_driver->hc_device = 253 vhci_driver->hc_device =
214 udev_device_new_from_subsystem_sysname(udev_context, 254 udev_device_new_from_subsystem_sysname(udev_context,
215 USBIP_VHCI_BUS_TYPE, 255 USBIP_VHCI_BUS_TYPE,
216 USBIP_VHCI_DRV_NAME); 256 USBIP_VHCI_DEVICE_NAME);
217 if (!vhci_driver->hc_device) { 257 if (!vhci_driver->hc_device) {
218 err("udev_device_new_from_subsystem_sysname failed"); 258 err("udev_device_new_from_subsystem_sysname failed");
219 goto err; 259 goto err;
220 } 260 }
221 261
222 vhci_driver->nports = get_nports(); 262 vhci_driver->nports = get_nports();
223
224 dbg("available ports: %d", vhci_driver->nports); 263 dbg("available ports: %d", vhci_driver->nports);
225 264
265 if (vhci_driver->nports <= 0) {
266 err("no available ports");
267 goto err;
268 } else if (vhci_driver->nports > MAXNPORT) {
269 err("port number exceeds %d", MAXNPORT);
270 goto err;
271 }
272
273 vhci_driver->ncontrollers = get_ncontrollers();
274 dbg("available controllers: %d", vhci_driver->ncontrollers);
275
276 if (vhci_driver->ncontrollers <=0) {
277 err("no available usb controllers");
278 goto err;
279 }
280
226 if (refresh_imported_device_list()) 281 if (refresh_imported_device_list())
227 goto err; 282 goto err;
228 283
@@ -270,11 +325,15 @@ err:
270} 325}
271 326
272 327
273int usbip_vhci_get_free_port(void) 328int usbip_vhci_get_free_port(uint32_t speed)
274{ 329{
275 for (int i = 0; i < vhci_driver->nports; i++) { 330 for (int i = 0; i < vhci_driver->nports; i++) {
331 if (speed == USB_SPEED_SUPER &&
332 vhci_driver->idev[i].hub != HUB_SPEED_SUPER)
333 continue;
334
276 if (vhci_driver->idev[i].status == VDEV_ST_NULL) 335 if (vhci_driver->idev[i].status == VDEV_ST_NULL)
277 return i; 336 return vhci_driver->idev[i].port;
278 } 337 }
279 338
280 return -1; 339 return -1;
diff --git a/tools/usb/usbip/libsrc/vhci_driver.h b/tools/usb/usbip/libsrc/vhci_driver.h
index fa2316cf2cac..4898d3bafb10 100644
--- a/tools/usb/usbip/libsrc/vhci_driver.h
+++ b/tools/usb/usbip/libsrc/vhci_driver.h
@@ -11,9 +11,16 @@
11#include "usbip_common.h" 11#include "usbip_common.h"
12 12
13#define USBIP_VHCI_BUS_TYPE "platform" 13#define USBIP_VHCI_BUS_TYPE "platform"
14#define USBIP_VHCI_DEVICE_NAME "vhci_hcd.0"
14#define MAXNPORT 128 15#define MAXNPORT 128
15 16
17enum hub_speed {
18 HUB_SPEED_HIGH = 0,
19 HUB_SPEED_SUPER,
20};
21
16struct usbip_imported_device { 22struct usbip_imported_device {
23 enum hub_speed hub;
17 uint8_t port; 24 uint8_t port;
18 uint32_t status; 25 uint32_t status;
19 26
@@ -31,6 +38,7 @@ struct usbip_vhci_driver {
31 /* /sys/devices/platform/vhci_hcd */ 38 /* /sys/devices/platform/vhci_hcd */
32 struct udev_device *hc_device; 39 struct udev_device *hc_device;
33 40
41 int ncontrollers;
34 int nports; 42 int nports;
35 struct usbip_imported_device idev[MAXNPORT]; 43 struct usbip_imported_device idev[MAXNPORT];
36}; 44};
@@ -44,7 +52,7 @@ void usbip_vhci_driver_close(void);
44int usbip_vhci_refresh_device_list(void); 52int usbip_vhci_refresh_device_list(void);
45 53
46 54
47int usbip_vhci_get_free_port(void); 55int usbip_vhci_get_free_port(uint32_t speed);
48int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid, 56int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
49 uint32_t speed); 57 uint32_t speed);
50 58
diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c
index 70a6b507fb62..6e89768ffe30 100644
--- a/tools/usb/usbip/src/usbip_attach.c
+++ b/tools/usb/usbip/src/usbip_attach.c
@@ -94,6 +94,7 @@ static int import_device(int sockfd, struct usbip_usb_device *udev)
94{ 94{
95 int rc; 95 int rc;
96 int port; 96 int port;
97 uint32_t speed = udev->speed;
97 98
98 rc = usbip_vhci_driver_open(); 99 rc = usbip_vhci_driver_open();
99 if (rc < 0) { 100 if (rc < 0) {
@@ -101,13 +102,15 @@ static int import_device(int sockfd, struct usbip_usb_device *udev)
101 return -1; 102 return -1;
102 } 103 }
103 104
104 port = usbip_vhci_get_free_port(); 105 port = usbip_vhci_get_free_port(speed);
105 if (port < 0) { 106 if (port < 0) {
106 err("no free port"); 107 err("no free port");
107 usbip_vhci_driver_close(); 108 usbip_vhci_driver_close();
108 return -1; 109 return -1;
109 } 110 }
110 111
112 dbg("got free port %d", port);
113
111 rc = usbip_vhci_attach_device(port, sockfd, udev->busnum, 114 rc = usbip_vhci_attach_device(port, sockfd, udev->busnum,
112 udev->devnum, udev->speed); 115 udev->devnum, udev->speed);
113 if (rc < 0) { 116 if (rc < 0) {