aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2014-06-17 17:30:23 -0400
committerPaul Moore <pmoore@redhat.com>2014-06-17 17:30:23 -0400
commit170b5910d9fbea79de1bb40df22eda5f98250c0c (patch)
treeca9560e878d2842d45c6f99077d0d8b8f8b0f9ba /tools
parent47dd0b76ace953bd2c0479076db0d3e3b9594003 (diff)
parent1860e379875dfe7271c649058aeddffe5afd9d0d (diff)
Merge tag 'v3.15' into next
Linux 3.15
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile17
-rw-r--r--tools/hv/Makefile13
-rw-r--r--tools/hv/hv_fcopy_daemon.c197
-rw-r--r--tools/hv/hv_vss_daemon.c2
-rw-r--r--tools/include/linux/hash.h5
-rw-r--r--tools/lib/api/Makefile2
-rw-r--r--tools/lib/api/fs/debugfs.c4
-rw-r--r--tools/lib/api/fs/fs.c (renamed from tools/perf/util/fs.c)11
-rw-r--r--tools/lib/api/fs/fs.h (renamed from tools/perf/util/include/linux/magic.h)12
-rw-r--r--tools/lib/lockdep/Makefile18
-rw-r--r--tools/lib/lockdep/uinclude/linux/lockdep.h3
-rw-r--r--tools/lib/traceevent/event-parse.c110
-rw-r--r--tools/lib/traceevent/event-parse.h4
-rw-r--r--tools/net/bpf_dbg.c121
-rw-r--r--tools/perf/Documentation/perf-bench.txt22
-rw-r--r--tools/perf/Documentation/perf-mem.txt4
-rw-r--r--tools/perf/Documentation/perf-probe.txt2
-rw-r--r--tools/perf/Documentation/perf-top.txt1
-rw-r--r--tools/perf/MANIFEST1
-rw-r--r--tools/perf/Makefile.perf48
-rw-r--r--tools/perf/arch/arm/Makefile2
-rw-r--r--tools/perf/arch/arm/util/unwind-libunwind.c (renamed from tools/perf/arch/arm/util/unwind.c)2
-rw-r--r--tools/perf/arch/x86/Makefile9
-rw-r--r--tools/perf/arch/x86/include/perf_regs.h6
-rw-r--r--tools/perf/arch/x86/tests/dwarf-unwind.c60
-rw-r--r--tools/perf/arch/x86/tests/regs_load.S98
-rw-r--r--tools/perf/arch/x86/util/unwind-libdw.c51
-rw-r--r--tools/perf/arch/x86/util/unwind-libunwind.c (renamed from tools/perf/arch/x86/util/unwind.c)4
-rw-r--r--tools/perf/bench/bench.h3
-rw-r--r--tools/perf/bench/futex-hash.c212
-rw-r--r--tools/perf/bench/futex-requeue.c211
-rw-r--r--tools/perf/bench/futex-wake.c201
-rw-r--r--tools/perf/bench/futex.h71
-rw-r--r--tools/perf/bench/numa.c4
-rw-r--r--tools/perf/builtin-bench.c12
-rw-r--r--tools/perf/builtin-diff.c7
-rw-r--r--tools/perf/builtin-inject.c1
-rw-r--r--tools/perf/builtin-kvm.c13
-rw-r--r--tools/perf/builtin-probe.c12
-rw-r--r--tools/perf/builtin-record.c32
-rw-r--r--tools/perf/builtin-report.c28
-rw-r--r--tools/perf/builtin-sched.c10
-rw-r--r--tools/perf/builtin-stat.c11
-rw-r--r--tools/perf/builtin-timechart.c4
-rw-r--r--tools/perf/builtin-top.c12
-rw-r--r--tools/perf/config/Makefile277
-rw-r--r--tools/perf/config/Makefile.arch3
-rw-r--r--tools/perf/config/feature-checks/Makefile6
-rw-r--r--tools/perf/config/feature-checks/test-all.c5
-rw-r--r--tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c13
-rw-r--r--tools/perf/design.txt12
-rw-r--r--tools/perf/perf-completion.sh2
-rw-r--r--tools/perf/perf.h18
-rw-r--r--tools/perf/tests/builtin-test.c8
-rw-r--r--tools/perf/tests/code-reading.c1
-rw-r--r--tools/perf/tests/dwarf-unwind.c144
-rw-r--r--tools/perf/tests/hists_link.c1
-rw-r--r--tools/perf/tests/make27
-rw-r--r--tools/perf/tests/parse-events.c2
-rw-r--r--tools/perf/tests/sample-parsing.c17
-rw-r--r--tools/perf/tests/tests.h9
-rw-r--r--tools/perf/ui/browsers/hists.c122
-rw-r--r--tools/perf/ui/gtk/hists.c78
-rw-r--r--tools/perf/ui/hist.c138
-rw-r--r--tools/perf/ui/stdio/hist.c11
-rw-r--r--tools/perf/util/annotate.c14
-rw-r--r--tools/perf/util/cpumap.c2
-rw-r--r--tools/perf/util/data.c9
-rw-r--r--tools/perf/util/dso.c4
-rw-r--r--tools/perf/util/dso.h10
-rw-r--r--tools/perf/util/dwarf-aux.c7
-rw-r--r--tools/perf/util/event.c188
-rw-r--r--tools/perf/util/event.h5
-rw-r--r--tools/perf/util/evsel.c60
-rw-r--r--tools/perf/util/evsel.h18
-rw-r--r--tools/perf/util/fs.h7
-rw-r--r--tools/perf/util/hist.c13
-rw-r--r--tools/perf/util/hist.h29
-rw-r--r--tools/perf/util/include/linux/hash.h5
-rw-r--r--tools/perf/util/include/linux/kernel.h6
-rw-r--r--tools/perf/util/include/linux/list.h1
-rw-r--r--tools/perf/util/include/linux/prefetch.h6
-rw-r--r--tools/perf/util/machine.c95
-rw-r--r--tools/perf/util/machine.h13
-rw-r--r--tools/perf/util/map.h10
-rw-r--r--tools/perf/util/parse-options.c37
-rw-r--r--tools/perf/util/parse-options.h8
-rw-r--r--tools/perf/util/perf_regs.c19
-rw-r--r--tools/perf/util/perf_regs.h13
-rw-r--r--tools/perf/util/pmu.c2
-rw-r--r--tools/perf/util/probe-event.c863
-rw-r--r--tools/perf/util/probe-event.h12
-rw-r--r--tools/perf/util/probe-finder.c217
-rw-r--r--tools/perf/util/probe-finder.h5
-rw-r--r--tools/perf/util/python-ext-sources2
-rw-r--r--tools/perf/util/record.c2
-rw-r--r--tools/perf/util/session.c7
-rw-r--r--tools/perf/util/symbol-elf.c4
-rw-r--r--tools/perf/util/symbol.c63
-rw-r--r--tools/perf/util/symbol.h14
-rw-r--r--tools/perf/util/thread.c21
-rw-r--r--tools/perf/util/thread.h11
-rw-r--r--tools/perf/util/trace-event-parse.c1
-rw-r--r--tools/perf/util/unwind-libdw.c210
-rw-r--r--tools/perf/util/unwind-libdw.h21
-rw-r--r--tools/perf/util/unwind-libunwind.c (renamed from tools/perf/util/unwind.c)50
-rw-r--r--tools/perf/util/unwind.h11
-rw-r--r--tools/perf/util/util.c2
-rw-r--r--tools/power/acpi/Makefile11
-rw-r--r--tools/power/x86/turbostat/turbostat.8127
-rw-r--r--tools/power/x86/turbostat/turbostat.c240
-rw-r--r--tools/testing/ktest/examples/kvm.conf4
-rw-r--r--tools/testing/selftests/powerpc/Makefile2
-rw-r--r--tools/testing/selftests/powerpc/copyloops/Makefile29
-rw-r--r--tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h86
-rw-r--r--tools/testing/selftests/powerpc/copyloops/asm/processor.h0
l---------tools/testing/selftests/powerpc/copyloops/copyuser_64.S1
l---------tools/testing/selftests/powerpc/copyloops/copyuser_power7.S1
l---------tools/testing/selftests/powerpc/copyloops/memcpy_64.S1
l---------tools/testing/selftests/powerpc/copyloops/memcpy_power7.S1
-rw-r--r--tools/testing/selftests/powerpc/copyloops/validate.c99
-rw-r--r--tools/testing/selftests/powerpc/utils.h3
-rw-r--r--tools/testing/selftests/rcutorture/bin/functions.sh1
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh51
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh51
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck.sh13
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh (renamed from tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh)53
-rw-r--r--tools/testing/selftests/rcutorture/bin/kvm.sh276
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/BUSTED6
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/CFLIST1
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/CFcommon2
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/LOCK016
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh43
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/BUSTED7
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/CFLIST (renamed from tools/testing/selftests/rcutorture/configs/CFLIST)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/CFcommon2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-N (renamed from tools/testing/selftests/rcutorture/configs/SRCU-N)3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-N.boot (renamed from tools/testing/selftests/rcutorture/configs/SRCU-N.boot)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-P (renamed from tools/testing/selftests/rcutorture/configs/SRCU-P)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-P.boot (renamed from tools/testing/selftests/rcutorture/configs/SRCU-P.boot)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TINY01 (renamed from tools/testing/selftests/rcutorture/configs/TINY01)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TINY02 (renamed from tools/testing/selftests/rcutorture/configs/TINY02)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE01 (renamed from tools/testing/selftests/rcutorture/configs/TREE01)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot (renamed from tools/testing/selftests/rcutorture/configs/TREE01.boot)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE02 (renamed from tools/testing/selftests/rcutorture/configs/TREE02)3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE03 (renamed from tools/testing/selftests/rcutorture/configs/TREE03)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE04 (renamed from tools/testing/selftests/rcutorture/configs/TREE04)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot (renamed from tools/testing/selftests/rcutorture/configs/TREE04.boot)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE05 (renamed from tools/testing/selftests/rcutorture/configs/TREE05)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot (renamed from tools/testing/selftests/rcutorture/configs/TREE05.boot)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE06 (renamed from tools/testing/selftests/rcutorture/configs/TREE06)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE07 (renamed from tools/testing/selftests/rcutorture/configs/TREE07)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE08 (renamed from tools/testing/selftests/rcutorture/configs/TREE08)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE08-T (renamed from tools/testing/selftests/rcutorture/configs/TREE08-T)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE09 (renamed from tools/testing/selftests/rcutorture/configs/TREE09)1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST (renamed from tools/testing/selftests/rcutorture/configs/v0.0/CFLIST)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v0.0/N1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v0.0/N2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v0.0/N3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v0.0/N4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v0.0/N5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v0.0/NT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH (renamed from tools/testing/selftests/rcutorture/configs/v0.0/NT3-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v0.0/P1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v0.0/P2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v0.0/P3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v0.0/P4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v0.0/P5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v0.0/PT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH (renamed from tools/testing/selftests/rcutorture/configs/v0.0/PT2-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh (renamed from tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh)22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST (renamed from tools/testing/selftests/rcutorture/configs/v3.12/CFLIST)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N6---t-nh-SD-smp-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N7-4-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/N8-2-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v3.12/NT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH (renamed from tools/testing/selftests/rcutorture/configs/v3.12/NT3-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P6---t-nh-SD-smp-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-all)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-none)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v3.12/PT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH (renamed from tools/testing/selftests/rcutorture/configs/v3.12/PT2-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST (renamed from tools/testing/selftests/rcutorture/configs/v3.3/CFLIST)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.3/N1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.3/N2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.3/N3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.3/N4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.3/N5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v3.3/NT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH (renamed from tools/testing/selftests/rcutorture/configs/v3.3/NT3-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.3/P1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.3/P2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.3/P3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.3/P4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.3/P5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v3.3/PT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH (renamed from tools/testing/selftests/rcutorture/configs/v3.3/PT2-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh (renamed from tools/testing/selftests/rcutorture/configs/ver_functions.sh)28
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST (renamed from tools/testing/selftests/rcutorture/configs/v3.5/CFLIST)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.5/N1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.5/N2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.5/N3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.5/N4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.5/N5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v3.5/NT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH (renamed from tools/testing/selftests/rcutorture/configs/v3.5/NT3-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.5/P1-S-T-NH-SD-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.5/P2-2-t-nh-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.5/P3-3-T-nh-SD-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP (renamed from tools/testing/selftests/rcutorture/configs/v3.5/P4-A-t-NH-sd-SMP-HP)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp (renamed from tools/testing/selftests/rcutorture/configs/v3.5/P5-U-T-NH-sd-SMP-hp)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh (renamed from tools/testing/selftests/rcutorture/configs/v3.5/PT1-nh)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH (renamed from tools/testing/selftests/rcutorture/configs/v3.5/PT2-NH)0
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh (renamed from tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh)23
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh (renamed from tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh)26
-rw-r--r--tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt (renamed from tools/testing/selftests/rcutorture/doc/TREE_RCU-Kconfig.txt)0
-rw-r--r--tools/virtio/linux/kmemleak.h3
-rw-r--r--tools/virtio/linux/virtio.h4
-rw-r--r--tools/virtio/virtio_test.c2
-rw-r--r--tools/vm/page-types.c170
234 files changed, 4393 insertions, 1686 deletions
diff --git a/tools/Makefile b/tools/Makefile
index feec3ad5fd09..9a617adc6675 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -7,6 +7,7 @@ help:
7 @echo ' cgroup - cgroup tools' 7 @echo ' cgroup - cgroup tools'
8 @echo ' cpupower - a tool for all things x86 CPU power' 8 @echo ' cpupower - a tool for all things x86 CPU power'
9 @echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer' 9 @echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer'
10 @echo ' hv - tools used when in Hyper-V clients'
10 @echo ' lguest - a minimal 32-bit x86 hypervisor' 11 @echo ' lguest - a minimal 32-bit x86 hypervisor'
11 @echo ' perf - Linux performance measurement and analysis tool' 12 @echo ' perf - Linux performance measurement and analysis tool'
12 @echo ' selftests - various kernel selftests' 13 @echo ' selftests - various kernel selftests'
@@ -40,9 +41,12 @@ acpi: FORCE
40cpupower: FORCE 41cpupower: FORCE
41 $(call descend,power/$@) 42 $(call descend,power/$@)
42 43
43cgroup firewire guest usb virtio vm net: FORCE 44cgroup firewire hv guest usb virtio vm net: FORCE
44 $(call descend,$@) 45 $(call descend,$@)
45 46
47liblockdep: FORCE
48 $(call descend,lib/lockdep)
49
46libapikfs: FORCE 50libapikfs: FORCE
47 $(call descend,lib/api) 51 $(call descend,lib/api)
48 52
@@ -64,7 +68,7 @@ acpi_install:
64cpupower_install: 68cpupower_install:
65 $(call descend,power/$(@:_install=),install) 69 $(call descend,power/$(@:_install=),install)
66 70
67cgroup_install firewire_install lguest_install perf_install usb_install virtio_install vm_install net_install: 71cgroup_install firewire_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install:
68 $(call descend,$(@:_install=),install) 72 $(call descend,$(@:_install=),install)
69 73
70selftests_install: 74selftests_install:
@@ -76,7 +80,7 @@ turbostat_install x86_energy_perf_policy_install:
76tmon_install: 80tmon_install:
77 $(call descend,thermal/$(@:_install=),install) 81 $(call descend,thermal/$(@:_install=),install)
78 82
79install: acpi_install cgroup_install cpupower_install firewire_install lguest_install \ 83install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \
80 perf_install selftests_install turbostat_install usb_install \ 84 perf_install selftests_install turbostat_install usb_install \
81 virtio_install vm_install net_install x86_energy_perf_policy_install \ 85 virtio_install vm_install net_install x86_energy_perf_policy_install \
82 tmon 86 tmon
@@ -87,9 +91,12 @@ acpi_clean:
87cpupower_clean: 91cpupower_clean:
88 $(call descend,power/cpupower,clean) 92 $(call descend,power/cpupower,clean)
89 93
90cgroup_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean: 94cgroup_clean hv_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean:
91 $(call descend,$(@:_clean=),clean) 95 $(call descend,$(@:_clean=),clean)
92 96
97liblockdep_clean:
98 $(call descend,lib/lockdep,clean)
99
93libapikfs_clean: 100libapikfs_clean:
94 $(call descend,lib/api,clean) 101 $(call descend,lib/api,clean)
95 102
@@ -105,7 +112,7 @@ turbostat_clean x86_energy_perf_policy_clean:
105tmon_clean: 112tmon_clean:
106 $(call descend,thermal/tmon,clean) 113 $(call descend,thermal/tmon,clean)
107 114
108clean: acpi_clean cgroup_clean cpupower_clean firewire_clean lguest_clean \ 115clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_clean \
109 perf_clean selftests_clean turbostat_clean usb_clean virtio_clean \ 116 perf_clean selftests_clean turbostat_clean usb_clean virtio_clean \
110 vm_clean net_clean x86_energy_perf_policy_clean tmon_clean 117 vm_clean net_clean x86_energy_perf_policy_clean tmon_clean
111 118
diff --git a/tools/hv/Makefile b/tools/hv/Makefile
new file mode 100644
index 000000000000..bd22f786a60c
--- /dev/null
+++ b/tools/hv/Makefile
@@ -0,0 +1,13 @@
1# Makefile for Hyper-V tools
2
3CC = $(CROSS_COMPILE)gcc
4PTHREAD_LIBS = -lpthread
5WARNINGS = -Wall -Wextra
6CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS)
7
8all: hv_kvp_daemon hv_vss_daemon
9%: %.c
10 $(CC) $(CFLAGS) -o $@ $^
11
12clean:
13 $(RM) hv_kvp_daemon hv_vss_daemon
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c
new file mode 100644
index 000000000000..fba1c75aa484
--- /dev/null
+++ b/tools/hv/hv_fcopy_daemon.c
@@ -0,0 +1,197 @@
1/*
2 * An implementation of host to guest copy functionality for Linux.
3 *
4 * Copyright (C) 2014, Microsoft, Inc.
5 *
6 * Author : K. Y. Srinivasan <kys@microsoft.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published
10 * by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
15 * NON INFRINGEMENT. See the GNU General Public License for more
16 * details.
17 */
18
19
20#include <sys/types.h>
21#include <sys/socket.h>
22#include <sys/poll.h>
23#include <linux/types.h>
24#include <linux/kdev_t.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <unistd.h>
28#include <string.h>
29#include <ctype.h>
30#include <errno.h>
31#include <linux/hyperv.h>
32#include <syslog.h>
33#include <sys/stat.h>
34#include <fcntl.h>
35#include <dirent.h>
36
37static int target_fd;
38static char target_fname[W_MAX_PATH];
39
40static int hv_start_fcopy(struct hv_start_fcopy *smsg)
41{
42 int error = HV_E_FAIL;
43 char *q, *p;
44
45 /*
46 * If possile append a path seperator to the path.
47 */
48 if (strlen((char *)smsg->path_name) < (W_MAX_PATH - 2))
49 strcat((char *)smsg->path_name, "/");
50
51 p = (char *)smsg->path_name;
52 snprintf(target_fname, sizeof(target_fname), "%s/%s",
53 (char *)smsg->path_name, smsg->file_name);
54
55 syslog(LOG_INFO, "Target file name: %s", target_fname);
56 /*
57 * Check to see if the path is already in place; if not,
58 * create if required.
59 */
60 while ((q = strchr(p, '/')) != NULL) {
61 if (q == p) {
62 p++;
63 continue;
64 }
65 *q = '\0';
66 if (access((char *)smsg->path_name, F_OK)) {
67 if (smsg->copy_flags & CREATE_PATH) {
68 if (mkdir((char *)smsg->path_name, 0755)) {
69 syslog(LOG_ERR, "Failed to create %s",
70 (char *)smsg->path_name);
71 goto done;
72 }
73 } else {
74 syslog(LOG_ERR, "Invalid path: %s",
75 (char *)smsg->path_name);
76 goto done;
77 }
78 }
79 p = q + 1;
80 *q = '/';
81 }
82
83 if (!access(target_fname, F_OK)) {
84 syslog(LOG_INFO, "File: %s exists", target_fname);
85 if (!(smsg->copy_flags & OVER_WRITE)) {
86 error = HV_ERROR_ALREADY_EXISTS;
87 goto done;
88 }
89 }
90
91 target_fd = open(target_fname, O_RDWR | O_CREAT | O_CLOEXEC, 0744);
92 if (target_fd == -1) {
93 syslog(LOG_INFO, "Open Failed: %s", strerror(errno));
94 goto done;
95 }
96
97 error = 0;
98done:
99 return error;
100}
101
102static int hv_copy_data(struct hv_do_fcopy *cpmsg)
103{
104 ssize_t bytes_written;
105
106 bytes_written = pwrite(target_fd, cpmsg->data, cpmsg->size,
107 cpmsg->offset);
108
109 if (bytes_written != cpmsg->size)
110 return HV_E_FAIL;
111
112 return 0;
113}
114
115static int hv_copy_finished(void)
116{
117 close(target_fd);
118 return 0;
119}
120static int hv_copy_cancel(void)
121{
122 close(target_fd);
123 unlink(target_fname);
124 return 0;
125
126}
127
128int main(void)
129{
130 int fd, fcopy_fd, len;
131 int error;
132 int version = FCOPY_CURRENT_VERSION;
133 char *buffer[4096 * 2];
134 struct hv_fcopy_hdr *in_msg;
135
136 if (daemon(1, 0)) {
137 syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno));
138 exit(EXIT_FAILURE);
139 }
140
141 openlog("HV_FCOPY", 0, LOG_USER);
142 syslog(LOG_INFO, "HV_FCOPY starting; pid is:%d", getpid());
143
144 fcopy_fd = open("/dev/vmbus/hv_fcopy", O_RDWR);
145
146 if (fcopy_fd < 0) {
147 syslog(LOG_ERR, "open /dev/vmbus/hv_fcopy failed; error: %d %s",
148 errno, strerror(errno));
149 exit(EXIT_FAILURE);
150 }
151
152 /*
153 * Register with the kernel.
154 */
155 if ((write(fcopy_fd, &version, sizeof(int))) != sizeof(int)) {
156 syslog(LOG_ERR, "Registration failed: %s", strerror(errno));
157 exit(EXIT_FAILURE);
158 }
159
160 while (1) {
161 /*
162 * In this loop we process fcopy messages after the
163 * handshake is complete.
164 */
165 len = pread(fcopy_fd, buffer, (4096 * 2), 0);
166 if (len < 0) {
167 syslog(LOG_ERR, "pread failed: %s", strerror(errno));
168 exit(EXIT_FAILURE);
169 }
170 in_msg = (struct hv_fcopy_hdr *)buffer;
171
172 switch (in_msg->operation) {
173 case START_FILE_COPY:
174 error = hv_start_fcopy((struct hv_start_fcopy *)in_msg);
175 break;
176 case WRITE_TO_FILE:
177 error = hv_copy_data((struct hv_do_fcopy *)in_msg);
178 break;
179 case COMPLETE_FCOPY:
180 error = hv_copy_finished();
181 break;
182 case CANCEL_FCOPY:
183 error = hv_copy_cancel();
184 break;
185
186 default:
187 syslog(LOG_ERR, "Unknown operation: %d",
188 in_msg->operation);
189
190 }
191
192 if (pwrite(fcopy_fd, &error, sizeof(int), 0) != sizeof(int)) {
193 syslog(LOG_ERR, "pwrite failed: %s", strerror(errno));
194 exit(EXIT_FAILURE);
195 }
196 }
197}
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index 520de3304571..6a213b8cd7b9 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -87,6 +87,8 @@ static int vss_operate(int operation)
87 continue; 87 continue;
88 if (strcmp(ent->mnt_type, "iso9660") == 0) 88 if (strcmp(ent->mnt_type, "iso9660") == 0)
89 continue; 89 continue;
90 if (strcmp(ent->mnt_type, "vfat") == 0)
91 continue;
90 if (strcmp(ent->mnt_dir, "/") == 0) { 92 if (strcmp(ent->mnt_dir, "/") == 0) {
91 root_seen = 1; 93 root_seen = 1;
92 continue; 94 continue;
diff --git a/tools/include/linux/hash.h b/tools/include/linux/hash.h
new file mode 100644
index 000000000000..d026c6573018
--- /dev/null
+++ b/tools/include/linux/hash.h
@@ -0,0 +1,5 @@
1#include "../../../include/linux/hash.h"
2
3#ifndef _TOOLS_LINUX_HASH_H
4#define _TOOLS_LINUX_HASH_H
5#endif
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index ed2f51e11b80..ce00f7ee6455 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -9,8 +9,10 @@ LIB_H=
9LIB_OBJS= 9LIB_OBJS=
10 10
11LIB_H += fs/debugfs.h 11LIB_H += fs/debugfs.h
12LIB_H += fs/fs.h
12 13
13LIB_OBJS += $(OUTPUT)fs/debugfs.o 14LIB_OBJS += $(OUTPUT)fs/debugfs.o
15LIB_OBJS += $(OUTPUT)fs/fs.o
14 16
15LIBFILE = libapikfs.a 17LIBFILE = libapikfs.a
16 18
diff --git a/tools/lib/api/fs/debugfs.c b/tools/lib/api/fs/debugfs.c
index 7c4347962353..a74fba6d7743 100644
--- a/tools/lib/api/fs/debugfs.c
+++ b/tools/lib/api/fs/debugfs.c
@@ -12,8 +12,8 @@
12char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug"; 12char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug";
13 13
14static const char * const debugfs_known_mountpoints[] = { 14static const char * const debugfs_known_mountpoints[] = {
15 "/sys/kernel/debug/", 15 "/sys/kernel/debug",
16 "/debug/", 16 "/debug",
17 0, 17 0,
18}; 18};
19 19
diff --git a/tools/perf/util/fs.c b/tools/lib/api/fs/fs.c
index f5be1f26e724..5b5eb788996e 100644
--- a/tools/perf/util/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -1,8 +1,13 @@
1/* TODO merge/factor in debugfs.c here */
1 2
2/* TODO merge/factor into tools/lib/lk/debugfs.c */ 3#include <errno.h>
4#include <stdbool.h>
5#include <stdio.h>
6#include <string.h>
7#include <sys/vfs.h>
3 8
4#include "util.h" 9#include "debugfs.h"
5#include "util/fs.h" 10#include "fs.h"
6 11
7static const char * const sysfs__fs_known_mountpoints[] = { 12static const char * const sysfs__fs_known_mountpoints[] = {
8 "/sys", 13 "/sys",
diff --git a/tools/perf/util/include/linux/magic.h b/tools/lib/api/fs/fs.h
index 07d63cf3e0f6..cb7049551f33 100644
--- a/tools/perf/util/include/linux/magic.h
+++ b/tools/lib/api/fs/fs.h
@@ -1,9 +1,5 @@
1#ifndef _PERF_LINUX_MAGIC_H_ 1#ifndef __API_FS__
2#define _PERF_LINUX_MAGIC_H_ 2#define __API_FS__
3
4#ifndef DEBUGFS_MAGIC
5#define DEBUGFS_MAGIC 0x64626720
6#endif
7 3
8#ifndef SYSFS_MAGIC 4#ifndef SYSFS_MAGIC
9#define SYSFS_MAGIC 0x62656572 5#define SYSFS_MAGIC 0x62656572
@@ -13,4 +9,6 @@
13#define PROC_SUPER_MAGIC 0x9fa0 9#define PROC_SUPER_MAGIC 0x9fa0
14#endif 10#endif
15 11
16#endif 12const char *sysfs__mountpoint(void);
13const char *procfs__mountpoint(void);
14#endif /* __API_FS__ */
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
index 07b0b7542511..bba2f5253b6e 100644
--- a/tools/lib/lockdep/Makefile
+++ b/tools/lib/lockdep/Makefile
@@ -1,13 +1,7 @@
1# liblockdep version
2LL_VERSION = 0
3LL_PATCHLEVEL = 0
4LL_EXTRAVERSION = 1
5
6# file format version 1# file format version
7FILE_VERSION = 1 2FILE_VERSION = 1
8 3
9MAKEFLAGS += --no-print-directory 4LIBLOCKDEP_VERSION=$(shell make --no-print-directory -sC ../../.. kernelversion)
10
11 5
12# Makefiles suck: This macro sets a default value of $(2) for the 6# Makefiles suck: This macro sets a default value of $(2) for the
13# variable named by $(1), unless the variable has been set by 7# variable named by $(1), unless the variable has been set by
@@ -98,7 +92,7 @@ export prefix libdir bindir src obj
98libdir_SQ = $(subst ','\'',$(libdir)) 92libdir_SQ = $(subst ','\'',$(libdir))
99bindir_SQ = $(subst ','\'',$(bindir)) 93bindir_SQ = $(subst ','\'',$(bindir))
100 94
101LIB_FILE = liblockdep.a liblockdep.so 95LIB_FILE = liblockdep.a liblockdep.so.$(LIBLOCKDEP_VERSION)
102BIN_FILE = lockdep 96BIN_FILE = lockdep
103 97
104CONFIG_INCLUDES = 98CONFIG_INCLUDES =
@@ -110,8 +104,6 @@ N =
110 104
111export Q VERBOSE 105export Q VERBOSE
112 106
113LIBLOCKDEP_VERSION = $(LL_VERSION).$(LL_PATCHLEVEL).$(LL_EXTRAVERSION)
114
115INCLUDES = -I. -I/usr/local/include -I./uinclude -I./include $(CONFIG_INCLUDES) 107INCLUDES = -I. -I/usr/local/include -I./uinclude -I./include $(CONFIG_INCLUDES)
116 108
117# Set compile option CFLAGS if not set elsewhere 109# Set compile option CFLAGS if not set elsewhere
@@ -146,7 +138,7 @@ do_app_build = \
146 138
147do_compile_shared_library = \ 139do_compile_shared_library = \
148 ($(print_shared_lib_compile) \ 140 ($(print_shared_lib_compile) \
149 $(CC) --shared $^ -o $@ -lpthread -ldl) 141 $(CC) --shared $^ -o $@ -lpthread -ldl -Wl,-soname='"$@"';$(shell ln -s $@ liblockdep.so))
150 142
151do_build_static_lib = \ 143do_build_static_lib = \
152 ($(print_static_lib_build) \ 144 ($(print_static_lib_build) \
@@ -177,7 +169,7 @@ all: all_cmd
177 169
178all_cmd: $(CMD_TARGETS) 170all_cmd: $(CMD_TARGETS)
179 171
180liblockdep.so: $(PEVENT_LIB_OBJS) 172liblockdep.so.$(LIBLOCKDEP_VERSION): $(PEVENT_LIB_OBJS)
181 $(Q)$(do_compile_shared_library) 173 $(Q)$(do_compile_shared_library)
182 174
183liblockdep.a: $(PEVENT_LIB_OBJS) 175liblockdep.a: $(PEVENT_LIB_OBJS)
@@ -238,7 +230,7 @@ install_lib: all_cmd
238install: install_lib 230install: install_lib
239 231
240clean: 232clean:
241 $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d 233 $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d
242 $(RM) tags TAGS 234 $(RM) tags TAGS
243 235
244endif # skip-makefile 236endif # skip-makefile
diff --git a/tools/lib/lockdep/uinclude/linux/lockdep.h b/tools/lib/lockdep/uinclude/linux/lockdep.h
index d0f5d6e50214..c1552c28507e 100644
--- a/tools/lib/lockdep/uinclude/linux/lockdep.h
+++ b/tools/lib/lockdep/uinclude/linux/lockdep.h
@@ -10,6 +10,9 @@
10 10
11#define MAX_LOCK_DEPTH 2000UL 11#define MAX_LOCK_DEPTH 2000UL
12 12
13#define asmlinkage
14#define __visible
15
13#include "../../../include/linux/lockdep.h" 16#include "../../../include/linux/lockdep.h"
14 17
15struct task_struct { 18struct task_struct {
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 1587ea392ad6..b83184f2d484 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -50,6 +50,18 @@ static int show_warning = 1;
50 warning(fmt, ##__VA_ARGS__); \ 50 warning(fmt, ##__VA_ARGS__); \
51 } while (0) 51 } while (0)
52 52
53#define do_warning_event(event, fmt, ...) \
54 do { \
55 if (!show_warning) \
56 continue; \
57 \
58 if (event) \
59 warning("[%s:%s] " fmt, event->system, \
60 event->name, ##__VA_ARGS__); \
61 else \
62 warning(fmt, ##__VA_ARGS__); \
63 } while (0)
64
53static void init_input_buf(const char *buf, unsigned long long size) 65static void init_input_buf(const char *buf, unsigned long long size)
54{ 66{
55 input_buf = buf; 67 input_buf = buf;
@@ -1355,7 +1367,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
1355 } 1367 }
1356 1368
1357 if (!field->type) { 1369 if (!field->type) {
1358 do_warning("%s: no type found", __func__); 1370 do_warning_event(event, "%s: no type found", __func__);
1359 goto fail; 1371 goto fail;
1360 } 1372 }
1361 field->name = last_token; 1373 field->name = last_token;
@@ -1402,7 +1414,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
1402 free_token(token); 1414 free_token(token);
1403 type = read_token(&token); 1415 type = read_token(&token);
1404 if (type == EVENT_NONE) { 1416 if (type == EVENT_NONE) {
1405 do_warning("failed to find token"); 1417 do_warning_event(event, "failed to find token");
1406 goto fail; 1418 goto fail;
1407 } 1419 }
1408 } 1420 }
@@ -1636,7 +1648,7 @@ process_cond(struct event_format *event, struct print_arg *top, char **tok)
1636 right = alloc_arg(); 1648 right = alloc_arg();
1637 1649
1638 if (!arg || !left || !right) { 1650 if (!arg || !left || !right) {
1639 do_warning("%s: not enough memory!", __func__); 1651 do_warning_event(event, "%s: not enough memory!", __func__);
1640 /* arg will be freed at out_free */ 1652 /* arg will be freed at out_free */
1641 free_arg(left); 1653 free_arg(left);
1642 free_arg(right); 1654 free_arg(right);
@@ -1686,7 +1698,7 @@ process_array(struct event_format *event, struct print_arg *top, char **tok)
1686 1698
1687 arg = alloc_arg(); 1699 arg = alloc_arg();
1688 if (!arg) { 1700 if (!arg) {
1689 do_warning("%s: not enough memory!", __func__); 1701 do_warning_event(event, "%s: not enough memory!", __func__);
1690 /* '*tok' is set to top->op.op. No need to free. */ 1702 /* '*tok' is set to top->op.op. No need to free. */
1691 *tok = NULL; 1703 *tok = NULL;
1692 return EVENT_ERROR; 1704 return EVENT_ERROR;
@@ -1792,7 +1804,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
1792 if (arg->type == PRINT_OP && !arg->op.left) { 1804 if (arg->type == PRINT_OP && !arg->op.left) {
1793 /* handle single op */ 1805 /* handle single op */
1794 if (token[1]) { 1806 if (token[1]) {
1795 do_warning("bad op token %s", token); 1807 do_warning_event(event, "bad op token %s", token);
1796 goto out_free; 1808 goto out_free;
1797 } 1809 }
1798 switch (token[0]) { 1810 switch (token[0]) {
@@ -1802,7 +1814,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
1802 case '-': 1814 case '-':
1803 break; 1815 break;
1804 default: 1816 default:
1805 do_warning("bad op token %s", token); 1817 do_warning_event(event, "bad op token %s", token);
1806 goto out_free; 1818 goto out_free;
1807 1819
1808 } 1820 }
@@ -1888,7 +1900,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
1888 char *new_atom; 1900 char *new_atom;
1889 1901
1890 if (left->type != PRINT_ATOM) { 1902 if (left->type != PRINT_ATOM) {
1891 do_warning("bad pointer type"); 1903 do_warning_event(event, "bad pointer type");
1892 goto out_free; 1904 goto out_free;
1893 } 1905 }
1894 new_atom = realloc(left->atom.atom, 1906 new_atom = realloc(left->atom.atom,
@@ -1930,7 +1942,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
1930 type = process_array(event, arg, tok); 1942 type = process_array(event, arg, tok);
1931 1943
1932 } else { 1944 } else {
1933 do_warning("unknown op '%s'", token); 1945 do_warning_event(event, "unknown op '%s'", token);
1934 event->flags |= EVENT_FL_FAILED; 1946 event->flags |= EVENT_FL_FAILED;
1935 /* the arg is now the left side */ 1947 /* the arg is now the left side */
1936 goto out_free; 1948 goto out_free;
@@ -1951,7 +1963,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
1951 return type; 1963 return type;
1952 1964
1953out_warn_free: 1965out_warn_free:
1954 do_warning("%s: not enough memory!", __func__); 1966 do_warning_event(event, "%s: not enough memory!", __func__);
1955out_free: 1967out_free:
1956 free_token(token); 1968 free_token(token);
1957 *tok = NULL; 1969 *tok = NULL;
@@ -2385,7 +2397,7 @@ process_flags(struct event_format *event, struct print_arg *arg, char **tok)
2385 2397
2386 field = alloc_arg(); 2398 field = alloc_arg();
2387 if (!field) { 2399 if (!field) {
2388 do_warning("%s: not enough memory!", __func__); 2400 do_warning_event(event, "%s: not enough memory!", __func__);
2389 goto out_free; 2401 goto out_free;
2390 } 2402 }
2391 2403
@@ -2438,7 +2450,7 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
2438 2450
2439 field = alloc_arg(); 2451 field = alloc_arg();
2440 if (!field) { 2452 if (!field) {
2441 do_warning("%s: not enough memory!", __func__); 2453 do_warning_event(event, "%s: not enough memory!", __func__);
2442 goto out_free; 2454 goto out_free;
2443 } 2455 }
2444 2456
@@ -2477,7 +2489,7 @@ process_hex(struct event_format *event, struct print_arg *arg, char **tok)
2477 2489
2478 field = alloc_arg(); 2490 field = alloc_arg();
2479 if (!field) { 2491 if (!field) {
2480 do_warning("%s: not enough memory!", __func__); 2492 do_warning_event(event, "%s: not enough memory!", __func__);
2481 goto out_free; 2493 goto out_free;
2482 } 2494 }
2483 2495
@@ -2492,7 +2504,7 @@ process_hex(struct event_format *event, struct print_arg *arg, char **tok)
2492 2504
2493 field = alloc_arg(); 2505 field = alloc_arg();
2494 if (!field) { 2506 if (!field) {
2495 do_warning("%s: not enough memory!", __func__); 2507 do_warning_event(event, "%s: not enough memory!", __func__);
2496 *tok = NULL; 2508 *tok = NULL;
2497 return EVENT_ERROR; 2509 return EVENT_ERROR;
2498 } 2510 }
@@ -2555,7 +2567,7 @@ process_dynamic_array(struct event_format *event, struct print_arg *arg, char **
2555 free_token(token); 2567 free_token(token);
2556 arg = alloc_arg(); 2568 arg = alloc_arg();
2557 if (!arg) { 2569 if (!arg) {
2558 do_warning("%s: not enough memory!", __func__); 2570 do_warning_event(event, "%s: not enough memory!", __func__);
2559 *tok = NULL; 2571 *tok = NULL;
2560 return EVENT_ERROR; 2572 return EVENT_ERROR;
2561 } 2573 }
@@ -2614,13 +2626,14 @@ process_paren(struct event_format *event, struct print_arg *arg, char **tok)
2614 2626
2615 /* prevous must be an atom */ 2627 /* prevous must be an atom */
2616 if (arg->type != PRINT_ATOM) { 2628 if (arg->type != PRINT_ATOM) {
2617 do_warning("previous needed to be PRINT_ATOM"); 2629 do_warning_event(event, "previous needed to be PRINT_ATOM");
2618 goto out_free; 2630 goto out_free;
2619 } 2631 }
2620 2632
2621 item_arg = alloc_arg(); 2633 item_arg = alloc_arg();
2622 if (!item_arg) { 2634 if (!item_arg) {
2623 do_warning("%s: not enough memory!", __func__); 2635 do_warning_event(event, "%s: not enough memory!",
2636 __func__);
2624 goto out_free; 2637 goto out_free;
2625 } 2638 }
2626 2639
@@ -2721,21 +2734,24 @@ process_func_handler(struct event_format *event, struct pevent_function_handler
2721 for (i = 0; i < func->nr_args; i++) { 2734 for (i = 0; i < func->nr_args; i++) {
2722 farg = alloc_arg(); 2735 farg = alloc_arg();
2723 if (!farg) { 2736 if (!farg) {
2724 do_warning("%s: not enough memory!", __func__); 2737 do_warning_event(event, "%s: not enough memory!",
2738 __func__);
2725 return EVENT_ERROR; 2739 return EVENT_ERROR;
2726 } 2740 }
2727 2741
2728 type = process_arg(event, farg, &token); 2742 type = process_arg(event, farg, &token);
2729 if (i < (func->nr_args - 1)) { 2743 if (i < (func->nr_args - 1)) {
2730 if (type != EVENT_DELIM || strcmp(token, ",") != 0) { 2744 if (type != EVENT_DELIM || strcmp(token, ",") != 0) {
2731 warning("Error: function '%s()' expects %d arguments but event %s only uses %d", 2745 do_warning_event(event,
2746 "Error: function '%s()' expects %d arguments but event %s only uses %d",
2732 func->name, func->nr_args, 2747 func->name, func->nr_args,
2733 event->name, i + 1); 2748 event->name, i + 1);
2734 goto err; 2749 goto err;
2735 } 2750 }
2736 } else { 2751 } else {
2737 if (type != EVENT_DELIM || strcmp(token, ")") != 0) { 2752 if (type != EVENT_DELIM || strcmp(token, ")") != 0) {
2738 warning("Error: function '%s()' only expects %d arguments but event %s has more", 2753 do_warning_event(event,
2754 "Error: function '%s()' only expects %d arguments but event %s has more",
2739 func->name, func->nr_args, event->name); 2755 func->name, func->nr_args, event->name);
2740 goto err; 2756 goto err;
2741 } 2757 }
@@ -2792,7 +2808,7 @@ process_function(struct event_format *event, struct print_arg *arg,
2792 return process_func_handler(event, func, arg, tok); 2808 return process_func_handler(event, func, arg, tok);
2793 } 2809 }
2794 2810
2795 do_warning("function %s not defined", token); 2811 do_warning_event(event, "function %s not defined", token);
2796 free_token(token); 2812 free_token(token);
2797 return EVENT_ERROR; 2813 return EVENT_ERROR;
2798} 2814}
@@ -2878,7 +2894,7 @@ process_arg_token(struct event_format *event, struct print_arg *arg,
2878 2894
2879 case EVENT_ERROR ... EVENT_NEWLINE: 2895 case EVENT_ERROR ... EVENT_NEWLINE:
2880 default: 2896 default:
2881 do_warning("unexpected type %d", type); 2897 do_warning_event(event, "unexpected type %d", type);
2882 return EVENT_ERROR; 2898 return EVENT_ERROR;
2883 } 2899 }
2884 *tok = token; 2900 *tok = token;
@@ -2901,7 +2917,8 @@ static int event_read_print_args(struct event_format *event, struct print_arg **
2901 2917
2902 arg = alloc_arg(); 2918 arg = alloc_arg();
2903 if (!arg) { 2919 if (!arg) {
2904 do_warning("%s: not enough memory!", __func__); 2920 do_warning_event(event, "%s: not enough memory!",
2921 __func__);
2905 return -1; 2922 return -1;
2906 } 2923 }
2907 2924
@@ -3481,11 +3498,12 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
3481 return val; 3498 return val;
3482 3499
3483out_warning_op: 3500out_warning_op:
3484 do_warning("%s: unknown op '%s'", __func__, arg->op.op); 3501 do_warning_event(event, "%s: unknown op '%s'", __func__, arg->op.op);
3485 return 0; 3502 return 0;
3486 3503
3487out_warning_field: 3504out_warning_field:
3488 do_warning("%s: field %s not found", __func__, arg->field.name); 3505 do_warning_event(event, "%s: field %s not found",
3506 __func__, arg->field.name);
3489 return 0; 3507 return 0;
3490} 3508}
3491 3509
@@ -3591,7 +3609,8 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3591 } 3609 }
3592 str = malloc(len + 1); 3610 str = malloc(len + 1);
3593 if (!str) { 3611 if (!str) {
3594 do_warning("%s: not enough memory!", __func__); 3612 do_warning_event(event, "%s: not enough memory!",
3613 __func__);
3595 return; 3614 return;
3596 } 3615 }
3597 memcpy(str, data + field->offset, len); 3616 memcpy(str, data + field->offset, len);
@@ -3697,7 +3716,8 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3697 return; 3716 return;
3698 3717
3699out_warning_field: 3718out_warning_field:
3700 do_warning("%s: field %s not found", __func__, arg->field.name); 3719 do_warning_event(event, "%s: field %s not found",
3720 __func__, arg->field.name);
3701} 3721}
3702 3722
3703static unsigned long long 3723static unsigned long long
@@ -3742,14 +3762,16 @@ process_defined_func(struct trace_seq *s, void *data, int size,
3742 trace_seq_terminate(&str); 3762 trace_seq_terminate(&str);
3743 string = malloc(sizeof(*string)); 3763 string = malloc(sizeof(*string));
3744 if (!string) { 3764 if (!string) {
3745 do_warning("%s(%d): malloc str", __func__, __LINE__); 3765 do_warning_event(event, "%s(%d): malloc str",
3766 __func__, __LINE__);
3746 goto out_free; 3767 goto out_free;
3747 } 3768 }
3748 string->next = strings; 3769 string->next = strings;
3749 string->str = strdup(str.buffer); 3770 string->str = strdup(str.buffer);
3750 if (!string->str) { 3771 if (!string->str) {
3751 free(string); 3772 free(string);
3752 do_warning("%s(%d): malloc str", __func__, __LINE__); 3773 do_warning_event(event, "%s(%d): malloc str",
3774 __func__, __LINE__);
3753 goto out_free; 3775 goto out_free;
3754 } 3776 }
3755 args[i] = (uintptr_t)string->str; 3777 args[i] = (uintptr_t)string->str;
@@ -3761,7 +3783,7 @@ process_defined_func(struct trace_seq *s, void *data, int size,
3761 * Something went totally wrong, this is not 3783 * Something went totally wrong, this is not
3762 * an input error, something in this code broke. 3784 * an input error, something in this code broke.
3763 */ 3785 */
3764 do_warning("Unexpected end of arguments\n"); 3786 do_warning_event(event, "Unexpected end of arguments\n");
3765 goto out_free; 3787 goto out_free;
3766 } 3788 }
3767 farg = farg->next; 3789 farg = farg->next;
@@ -3811,12 +3833,12 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3811 if (!field) { 3833 if (!field) {
3812 field = pevent_find_field(event, "buf"); 3834 field = pevent_find_field(event, "buf");
3813 if (!field) { 3835 if (!field) {
3814 do_warning("can't find buffer field for binary printk"); 3836 do_warning_event(event, "can't find buffer field for binary printk");
3815 return NULL; 3837 return NULL;
3816 } 3838 }
3817 ip_field = pevent_find_field(event, "ip"); 3839 ip_field = pevent_find_field(event, "ip");
3818 if (!ip_field) { 3840 if (!ip_field) {
3819 do_warning("can't find ip field for binary printk"); 3841 do_warning_event(event, "can't find ip field for binary printk");
3820 return NULL; 3842 return NULL;
3821 } 3843 }
3822 pevent->bprint_buf_field = field; 3844 pevent->bprint_buf_field = field;
@@ -3830,7 +3852,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3830 */ 3852 */
3831 args = alloc_arg(); 3853 args = alloc_arg();
3832 if (!args) { 3854 if (!args) {
3833 do_warning("%s(%d): not enough memory!", __func__, __LINE__); 3855 do_warning_event(event, "%s(%d): not enough memory!",
3856 __func__, __LINE__);
3834 return NULL; 3857 return NULL;
3835 } 3858 }
3836 arg = args; 3859 arg = args;
@@ -3896,7 +3919,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3896 bptr += vsize; 3919 bptr += vsize;
3897 arg = alloc_arg(); 3920 arg = alloc_arg();
3898 if (!arg) { 3921 if (!arg) {
3899 do_warning("%s(%d): not enough memory!", 3922 do_warning_event(event, "%s(%d): not enough memory!",
3900 __func__, __LINE__); 3923 __func__, __LINE__);
3901 goto out_free; 3924 goto out_free;
3902 } 3925 }
@@ -3919,7 +3942,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3919 case 's': 3942 case 's':
3920 arg = alloc_arg(); 3943 arg = alloc_arg();
3921 if (!arg) { 3944 if (!arg) {
3922 do_warning("%s(%d): not enough memory!", 3945 do_warning_event(event, "%s(%d): not enough memory!",
3923 __func__, __LINE__); 3946 __func__, __LINE__);
3924 goto out_free; 3947 goto out_free;
3925 } 3948 }
@@ -3959,7 +3982,7 @@ get_bprint_format(void *data, int size __maybe_unused,
3959 if (!field) { 3982 if (!field) {
3960 field = pevent_find_field(event, "fmt"); 3983 field = pevent_find_field(event, "fmt");
3961 if (!field) { 3984 if (!field) {
3962 do_warning("can't find format field for binary printk"); 3985 do_warning_event(event, "can't find format field for binary printk");
3963 return NULL; 3986 return NULL;
3964 } 3987 }
3965 pevent->bprint_fmt_field = field; 3988 pevent->bprint_fmt_field = field;
@@ -4003,8 +4026,8 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
4003 arg->field.field = 4026 arg->field.field =
4004 pevent_find_any_field(event, arg->field.name); 4027 pevent_find_any_field(event, arg->field.name);
4005 if (!arg->field.field) { 4028 if (!arg->field.field) {
4006 do_warning("%s: field %s not found", 4029 do_warning_event(event, "%s: field %s not found",
4007 __func__, arg->field.name); 4030 __func__, arg->field.name);
4008 return; 4031 return;
4009 } 4032 }
4010 } 4033 }
@@ -4176,7 +4199,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
4176 case '*': 4199 case '*':
4177 /* The argument is the length. */ 4200 /* The argument is the length. */
4178 if (!arg) { 4201 if (!arg) {
4179 do_warning("no argument match"); 4202 do_warning_event(event, "no argument match");
4180 event->flags |= EVENT_FL_FAILED; 4203 event->flags |= EVENT_FL_FAILED;
4181 goto out_failed; 4204 goto out_failed;
4182 } 4205 }
@@ -4213,7 +4236,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
4213 case 'X': 4236 case 'X':
4214 case 'u': 4237 case 'u':
4215 if (!arg) { 4238 if (!arg) {
4216 do_warning("no argument match"); 4239 do_warning_event(event, "no argument match");
4217 event->flags |= EVENT_FL_FAILED; 4240 event->flags |= EVENT_FL_FAILED;
4218 goto out_failed; 4241 goto out_failed;
4219 } 4242 }
@@ -4223,7 +4246,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
4223 4246
4224 /* should never happen */ 4247 /* should never happen */
4225 if (len > 31) { 4248 if (len > 31) {
4226 do_warning("bad format!"); 4249 do_warning_event(event, "bad format!");
4227 event->flags |= EVENT_FL_FAILED; 4250 event->flags |= EVENT_FL_FAILED;
4228 len = 31; 4251 len = 31;
4229 } 4252 }
@@ -4290,13 +4313,13 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
4290 trace_seq_printf(s, format, (long long)val); 4313 trace_seq_printf(s, format, (long long)val);
4291 break; 4314 break;
4292 default: 4315 default:
4293 do_warning("bad count (%d)", ls); 4316 do_warning_event(event, "bad count (%d)", ls);
4294 event->flags |= EVENT_FL_FAILED; 4317 event->flags |= EVENT_FL_FAILED;
4295 } 4318 }
4296 break; 4319 break;
4297 case 's': 4320 case 's':
4298 if (!arg) { 4321 if (!arg) {
4299 do_warning("no matching argument"); 4322 do_warning_event(event, "no matching argument");
4300 event->flags |= EVENT_FL_FAILED; 4323 event->flags |= EVENT_FL_FAILED;
4301 goto out_failed; 4324 goto out_failed;
4302 } 4325 }
@@ -4306,7 +4329,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
4306 4329
4307 /* should never happen */ 4330 /* should never happen */
4308 if (len > 31) { 4331 if (len > 31) {
4309 do_warning("bad format!"); 4332 do_warning_event(event, "bad format!");
4310 event->flags |= EVENT_FL_FAILED; 4333 event->flags |= EVENT_FL_FAILED;
4311 len = 31; 4334 len = 31;
4312 } 4335 }
@@ -4321,6 +4344,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
4321 format, len_arg, arg); 4344 format, len_arg, arg);
4322 trace_seq_terminate(&p); 4345 trace_seq_terminate(&p);
4323 trace_seq_puts(s, p.buffer); 4346 trace_seq_puts(s, p.buffer);
4347 trace_seq_destroy(&p);
4324 arg = arg->next; 4348 arg = arg->next;
4325 break; 4349 break;
4326 default: 4350 default:
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 791c539374c7..feab94281634 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -876,8 +876,8 @@ struct event_filter {
876struct event_filter *pevent_filter_alloc(struct pevent *pevent); 876struct event_filter *pevent_filter_alloc(struct pevent *pevent);
877 877
878/* for backward compatibility */ 878/* for backward compatibility */
879#define FILTER_NONE PEVENT_ERRNO__FILTER_NOT_FOUND 879#define FILTER_NONE PEVENT_ERRNO__NO_FILTER
880#define FILTER_NOEXIST PEVENT_ERRNO__NO_FILTER 880#define FILTER_NOEXIST PEVENT_ERRNO__FILTER_NOT_FOUND
881#define FILTER_MISS PEVENT_ERRNO__FILTER_MISS 881#define FILTER_MISS PEVENT_ERRNO__FILTER_MISS
882#define FILTER_MATCH PEVENT_ERRNO__FILTER_MATCH 882#define FILTER_MATCH PEVENT_ERRNO__FILTER_MATCH
883 883
diff --git a/tools/net/bpf_dbg.c b/tools/net/bpf_dbg.c
index 65dc757f7f7b..9a287bec695a 100644
--- a/tools/net/bpf_dbg.c
+++ b/tools/net/bpf_dbg.c
@@ -87,9 +87,6 @@
87 __attribute__ ((format (printf, (pos_fmtstr), (pos_fmtargs)))) 87 __attribute__ ((format (printf, (pos_fmtstr), (pos_fmtargs))))
88#endif 88#endif
89 89
90#define CMD(_name, _func) { .name = _name, .func = _func, }
91#define OP(_op, _name) [_op] = _name
92
93enum { 90enum {
94 CMD_OK, 91 CMD_OK,
95 CMD_ERR, 92 CMD_ERR,
@@ -145,32 +142,32 @@ static size_t pcap_map_size = 0;
145static char *pcap_ptr_va_start, *pcap_ptr_va_curr; 142static char *pcap_ptr_va_start, *pcap_ptr_va_curr;
146 143
147static const char * const op_table[] = { 144static const char * const op_table[] = {
148 OP(BPF_ST, "st"), 145 [BPF_ST] = "st",
149 OP(BPF_STX, "stx"), 146 [BPF_STX] = "stx",
150 OP(BPF_LD_B, "ldb"), 147 [BPF_LD_B] = "ldb",
151 OP(BPF_LD_H, "ldh"), 148 [BPF_LD_H] = "ldh",
152 OP(BPF_LD_W, "ld"), 149 [BPF_LD_W] = "ld",
153 OP(BPF_LDX, "ldx"), 150 [BPF_LDX] = "ldx",
154 OP(BPF_LDX_B, "ldxb"), 151 [BPF_LDX_B] = "ldxb",
155 OP(BPF_JMP_JA, "ja"), 152 [BPF_JMP_JA] = "ja",
156 OP(BPF_JMP_JEQ, "jeq"), 153 [BPF_JMP_JEQ] = "jeq",
157 OP(BPF_JMP_JGT, "jgt"), 154 [BPF_JMP_JGT] = "jgt",
158 OP(BPF_JMP_JGE, "jge"), 155 [BPF_JMP_JGE] = "jge",
159 OP(BPF_JMP_JSET, "jset"), 156 [BPF_JMP_JSET] = "jset",
160 OP(BPF_ALU_ADD, "add"), 157 [BPF_ALU_ADD] = "add",
161 OP(BPF_ALU_SUB, "sub"), 158 [BPF_ALU_SUB] = "sub",
162 OP(BPF_ALU_MUL, "mul"), 159 [BPF_ALU_MUL] = "mul",
163 OP(BPF_ALU_DIV, "div"), 160 [BPF_ALU_DIV] = "div",
164 OP(BPF_ALU_MOD, "mod"), 161 [BPF_ALU_MOD] = "mod",
165 OP(BPF_ALU_NEG, "neg"), 162 [BPF_ALU_NEG] = "neg",
166 OP(BPF_ALU_AND, "and"), 163 [BPF_ALU_AND] = "and",
167 OP(BPF_ALU_OR, "or"), 164 [BPF_ALU_OR] = "or",
168 OP(BPF_ALU_XOR, "xor"), 165 [BPF_ALU_XOR] = "xor",
169 OP(BPF_ALU_LSH, "lsh"), 166 [BPF_ALU_LSH] = "lsh",
170 OP(BPF_ALU_RSH, "rsh"), 167 [BPF_ALU_RSH] = "rsh",
171 OP(BPF_MISC_TAX, "tax"), 168 [BPF_MISC_TAX] = "tax",
172 OP(BPF_MISC_TXA, "txa"), 169 [BPF_MISC_TXA] = "txa",
173 OP(BPF_RET, "ret"), 170 [BPF_RET] = "ret",
174}; 171};
175 172
176static __check_format_printf(1, 2) int rl_printf(const char *fmt, ...) 173static __check_format_printf(1, 2) int rl_printf(const char *fmt, ...)
@@ -823,7 +820,7 @@ do_div:
823 r->A &= r->X; 820 r->A &= r->X;
824 break; 821 break;
825 case BPF_ALU_AND | BPF_K: 822 case BPF_ALU_AND | BPF_K:
826 r->A &= r->X; 823 r->A &= K;
827 break; 824 break;
828 case BPF_ALU_OR | BPF_X: 825 case BPF_ALU_OR | BPF_X:
829 r->A |= r->X; 826 r->A |= r->X;
@@ -1127,7 +1124,6 @@ static int cmd_step(char *num)
1127static int cmd_select(char *num) 1124static int cmd_select(char *num)
1128{ 1125{
1129 unsigned int which, i; 1126 unsigned int which, i;
1130 struct pcap_pkthdr *hdr;
1131 bool have_next = true; 1127 bool have_next = true;
1132 1128
1133 if (!pcap_loaded() || strlen(num) == 0) 1129 if (!pcap_loaded() || strlen(num) == 0)
@@ -1144,7 +1140,7 @@ static int cmd_select(char *num)
1144 1140
1145 for (i = 0; i < which && (have_next = pcap_next_pkt()); i++) 1141 for (i = 0; i < which && (have_next = pcap_next_pkt()); i++)
1146 /* noop */; 1142 /* noop */;
1147 if (!have_next || (hdr = pcap_curr_pkt()) == NULL) { 1143 if (!have_next || pcap_curr_pkt() == NULL) {
1148 rl_printf("no packet #%u available!\n", which); 1144 rl_printf("no packet #%u available!\n", which);
1149 pcap_reset_pkt(); 1145 pcap_reset_pkt();
1150 return CMD_ERR; 1146 return CMD_ERR;
@@ -1177,9 +1173,8 @@ static int cmd_breakpoint(char *subcmd)
1177static int cmd_run(char *num) 1173static int cmd_run(char *num)
1178{ 1174{
1179 static uint32_t pass = 0, fail = 0; 1175 static uint32_t pass = 0, fail = 0;
1180 struct pcap_pkthdr *hdr;
1181 bool has_limit = true; 1176 bool has_limit = true;
1182 int ret, pkts = 0, i = 0; 1177 int pkts = 0, i = 0;
1183 1178
1184 if (!bpf_prog_loaded() || !pcap_loaded()) 1179 if (!bpf_prog_loaded() || !pcap_loaded())
1185 return CMD_ERR; 1180 return CMD_ERR;
@@ -1189,10 +1184,10 @@ static int cmd_run(char *num)
1189 has_limit = false; 1184 has_limit = false;
1190 1185
1191 do { 1186 do {
1192 hdr = pcap_curr_pkt(); 1187 struct pcap_pkthdr *hdr = pcap_curr_pkt();
1193 ret = bpf_run_all(bpf_image, bpf_prog_len, 1188 int ret = bpf_run_all(bpf_image, bpf_prog_len,
1194 (uint8_t *) hdr + sizeof(*hdr), 1189 (uint8_t *) hdr + sizeof(*hdr),
1195 hdr->caplen, hdr->len); 1190 hdr->caplen, hdr->len);
1196 if (ret > 0) 1191 if (ret > 0)
1197 pass++; 1192 pass++;
1198 else if (ret == 0) 1193 else if (ret == 0)
@@ -1245,14 +1240,14 @@ static int cmd_quit(char *dontcare)
1245} 1240}
1246 1241
1247static const struct shell_cmd cmds[] = { 1242static const struct shell_cmd cmds[] = {
1248 CMD("load", cmd_load), 1243 { .name = "load", .func = cmd_load },
1249 CMD("select", cmd_select), 1244 { .name = "select", .func = cmd_select },
1250 CMD("step", cmd_step), 1245 { .name = "step", .func = cmd_step },
1251 CMD("run", cmd_run), 1246 { .name = "run", .func = cmd_run },
1252 CMD("breakpoint", cmd_breakpoint), 1247 { .name = "breakpoint", .func = cmd_breakpoint },
1253 CMD("disassemble", cmd_disassemble), 1248 { .name = "disassemble", .func = cmd_disassemble },
1254 CMD("dump", cmd_dump), 1249 { .name = "dump", .func = cmd_dump },
1255 CMD("quit", cmd_quit), 1250 { .name = "quit", .func = cmd_quit },
1256}; 1251};
1257 1252
1258static int execf(char *arg) 1253static int execf(char *arg)
@@ -1280,7 +1275,6 @@ out:
1280static char *shell_comp_gen(const char *buf, int state) 1275static char *shell_comp_gen(const char *buf, int state)
1281{ 1276{
1282 static int list_index, len; 1277 static int list_index, len;
1283 const char *name;
1284 1278
1285 if (!state) { 1279 if (!state) {
1286 list_index = 0; 1280 list_index = 0;
@@ -1288,9 +1282,9 @@ static char *shell_comp_gen(const char *buf, int state)
1288 } 1282 }
1289 1283
1290 for (; list_index < array_size(cmds); ) { 1284 for (; list_index < array_size(cmds); ) {
1291 name = cmds[list_index].name; 1285 const char *name = cmds[list_index].name;
1292 list_index++;
1293 1286
1287 list_index++;
1294 if (strncmp(name, buf, len) == 0) 1288 if (strncmp(name, buf, len) == 0)
1295 return strdup(name); 1289 return strdup(name);
1296 } 1290 }
@@ -1322,16 +1316,9 @@ static void init_shell(FILE *fin, FILE *fout)
1322{ 1316{
1323 char file[128]; 1317 char file[128];
1324 1318
1325 memset(file, 0, sizeof(file)); 1319 snprintf(file, sizeof(file), "%s/.bpf_dbg_history", getenv("HOME"));
1326 snprintf(file, sizeof(file) - 1,
1327 "%s/.bpf_dbg_history", getenv("HOME"));
1328
1329 read_history(file); 1320 read_history(file);
1330 1321
1331 memset(file, 0, sizeof(file));
1332 snprintf(file, sizeof(file) - 1,
1333 "%s/.bpf_dbg_init", getenv("HOME"));
1334
1335 rl_instream = fin; 1322 rl_instream = fin;
1336 rl_outstream = fout; 1323 rl_outstream = fout;
1337 1324
@@ -1348,37 +1335,41 @@ static void init_shell(FILE *fin, FILE *fout)
1348 rl_bind_key_in_map('\t', rl_complete, emacs_meta_keymap); 1335 rl_bind_key_in_map('\t', rl_complete, emacs_meta_keymap);
1349 rl_bind_key_in_map('\033', rl_complete, emacs_meta_keymap); 1336 rl_bind_key_in_map('\033', rl_complete, emacs_meta_keymap);
1350 1337
1338 snprintf(file, sizeof(file), "%s/.bpf_dbg_init", getenv("HOME"));
1351 rl_read_init_file(file); 1339 rl_read_init_file(file);
1340
1352 rl_prep_terminal(0); 1341 rl_prep_terminal(0);
1353 rl_set_signals(); 1342 rl_set_signals();
1354 1343
1355 signal(SIGINT, intr_shell); 1344 signal(SIGINT, intr_shell);
1356} 1345}
1357 1346
1358static void exit_shell(void) 1347static void exit_shell(FILE *fin, FILE *fout)
1359{ 1348{
1360 char file[128]; 1349 char file[128];
1361 1350
1362 memset(file, 0, sizeof(file)); 1351 snprintf(file, sizeof(file), "%s/.bpf_dbg_history", getenv("HOME"));
1363 snprintf(file, sizeof(file) - 1,
1364 "%s/.bpf_dbg_history", getenv("HOME"));
1365
1366 write_history(file); 1352 write_history(file);
1353
1367 clear_history(); 1354 clear_history();
1368 rl_deprep_terminal(); 1355 rl_deprep_terminal();
1369 1356
1370 try_close_pcap(); 1357 try_close_pcap();
1358
1359 if (fin != stdin)
1360 fclose(fin);
1361 if (fout != stdout)
1362 fclose(fout);
1371} 1363}
1372 1364
1373static int run_shell_loop(FILE *fin, FILE *fout) 1365static int run_shell_loop(FILE *fin, FILE *fout)
1374{ 1366{
1375 char *buf; 1367 char *buf;
1376 int ret;
1377 1368
1378 init_shell(fin, fout); 1369 init_shell(fin, fout);
1379 1370
1380 while ((buf = readline("> ")) != NULL) { 1371 while ((buf = readline("> ")) != NULL) {
1381 ret = execf(buf); 1372 int ret = execf(buf);
1382 if (ret == CMD_EX) 1373 if (ret == CMD_EX)
1383 break; 1374 break;
1384 if (ret == CMD_OK && strlen(buf) > 0) 1375 if (ret == CMD_OK && strlen(buf) > 0)
@@ -1387,7 +1378,7 @@ static int run_shell_loop(FILE *fin, FILE *fout)
1387 free(buf); 1378 free(buf);
1388 } 1379 }
1389 1380
1390 exit_shell(); 1381 exit_shell(fin, fout);
1391 return 0; 1382 return 0;
1392} 1383}
1393 1384
diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt
index 7065cd6fbdfc..4464ad770d51 100644
--- a/tools/perf/Documentation/perf-bench.txt
+++ b/tools/perf/Documentation/perf-bench.txt
@@ -48,6 +48,12 @@ SUBSYSTEM
48'mem':: 48'mem'::
49 Memory access performance. 49 Memory access performance.
50 50
51'numa'::
52 NUMA scheduling and MM benchmarks.
53
54'futex'::
55 Futex stressing benchmarks.
56
51'all':: 57'all'::
52 All benchmark subsystems. 58 All benchmark subsystems.
53 59
@@ -187,6 +193,22 @@ Show only the result with page faults before memset.
187--no-prefault:: 193--no-prefault::
188Show only the result without page faults before memset. 194Show only the result without page faults before memset.
189 195
196SUITES FOR 'numa'
197~~~~~~~~~~~~~~~~~
198*mem*::
199Suite for evaluating NUMA workloads.
200
201SUITES FOR 'futex'
202~~~~~~~~~~~~~~~~~~
203*hash*::
204Suite for evaluating hash tables.
205
206*wake*::
207Suite for evaluating wake calls.
208
209*requeue*::
210Suite for evaluating requeue calls.
211
190SEE ALSO 212SEE ALSO
191-------- 213--------
192linkperf:perf[1] 214linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 888d51137fbe..1d78a4064da4 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -18,6 +18,10 @@ from it, into perf.data. Perf record options are accepted and are passed through
18"perf mem -t <TYPE> report" displays the result. It invokes perf report with the 18"perf mem -t <TYPE> report" displays the result. It invokes perf report with the
19right set of options to display a memory access profile. 19right set of options to display a memory access profile.
20 20
21Note that on Intel systems the memory latency reported is the use-latency,
22not the pure load (or store latency). Use latency includes any pipeline
23queueing delays in addition to the memory subsystem latency.
24
21OPTIONS 25OPTIONS
22------- 26-------
23<command>...:: 27<command>...::
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index b715cb71592b..1513935c399b 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -136,6 +136,8 @@ Each probe argument follows below syntax.
136'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.) 136'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
137'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type. 137'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type.
138 138
139On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid.
140
139LINE SYNTAX 141LINE SYNTAX
140----------- 142-----------
141Line range is described by following syntax. 143Line range is described by following syntax.
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index cdd8d4946dba..976b00c6cdb1 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -87,7 +87,6 @@ Default is to monitor all CPUS.
87--realtime=<priority>:: 87--realtime=<priority>::
88 Collect data with this RT SCHED_FIFO priority. 88 Collect data with this RT SCHED_FIFO priority.
89 89
90-s <symbol>::
91--sym-annotate=<symbol>:: 90--sym-annotate=<symbol>::
92 Annotate this symbol. 91 Annotate this symbol.
93 92
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index f41572d0dd76..c0c87c87b60f 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -6,6 +6,7 @@ tools/lib/symbol/kallsyms.c
6tools/lib/symbol/kallsyms.h 6tools/lib/symbol/kallsyms.h
7tools/include/asm/bug.h 7tools/include/asm/bug.h
8tools/include/linux/compiler.h 8tools/include/linux/compiler.h
9tools/include/linux/hash.h
9include/linux/const.h 10include/linux/const.h
10include/linux/perf_event.h 11include/linux/perf_event.h
11include/linux/rbtree.h 12include/linux/rbtree.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 7257e7e9e38a..895edd32930c 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -7,6 +7,8 @@ include config/utilities.mak
7 7
8# Define V to have a more verbose compile. 8# Define V to have a more verbose compile.
9# 9#
10# Define VF to have a more verbose feature check output.
11#
10# Define O to save output files in a separate directory. 12# Define O to save output files in a separate directory.
11# 13#
12# Define ARCH as name of target architecture if you want cross-builds. 14# Define ARCH as name of target architecture if you want cross-builds.
@@ -55,6 +57,9 @@ include config/utilities.mak
55# Define NO_LIBAUDIT if you do not want libaudit support 57# Define NO_LIBAUDIT if you do not want libaudit support
56# 58#
57# Define NO_LIBBIONIC if you do not want bionic support 59# Define NO_LIBBIONIC if you do not want bionic support
60#
61# Define NO_LIBDW_DWARF_UNWIND if you do not want libdw support
62# for dwarf backtrace post unwind.
58 63
59ifeq ($(srctree),) 64ifeq ($(srctree),)
60srctree := $(patsubst %/,%,$(dir $(shell pwd))) 65srctree := $(patsubst %/,%,$(dir $(shell pwd)))
@@ -187,13 +192,13 @@ endif
187export PERL_PATH 192export PERL_PATH
188 193
189$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c 194$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
190 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c 195 $(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l
191 196
192$(OUTPUT)util/parse-events-bison.c: util/parse-events.y 197$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
193 $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_ 198 $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
194 199
195$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c 200$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
196 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c 201 $(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
197 202
198$(OUTPUT)util/pmu-bison.c: util/pmu.y 203$(OUTPUT)util/pmu-bison.c: util/pmu.y
199 $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_ 204 $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
@@ -208,7 +213,7 @@ LIB_H += ../../include/uapi/linux/perf_event.h
208LIB_H += ../../include/linux/rbtree.h 213LIB_H += ../../include/linux/rbtree.h
209LIB_H += ../../include/linux/list.h 214LIB_H += ../../include/linux/list.h
210LIB_H += ../../include/uapi/linux/const.h 215LIB_H += ../../include/uapi/linux/const.h
211LIB_H += ../../include/linux/hash.h 216LIB_H += ../include/linux/hash.h
212LIB_H += ../../include/linux/stringify.h 217LIB_H += ../../include/linux/stringify.h
213LIB_H += util/include/linux/bitmap.h 218LIB_H += util/include/linux/bitmap.h
214LIB_H += util/include/linux/bitops.h 219LIB_H += util/include/linux/bitops.h
@@ -218,9 +223,7 @@ LIB_H += util/include/linux/ctype.h
218LIB_H += util/include/linux/kernel.h 223LIB_H += util/include/linux/kernel.h
219LIB_H += util/include/linux/list.h 224LIB_H += util/include/linux/list.h
220LIB_H += util/include/linux/export.h 225LIB_H += util/include/linux/export.h
221LIB_H += util/include/linux/magic.h
222LIB_H += util/include/linux/poison.h 226LIB_H += util/include/linux/poison.h
223LIB_H += util/include/linux/prefetch.h
224LIB_H += util/include/linux/rbtree.h 227LIB_H += util/include/linux/rbtree.h
225LIB_H += util/include/linux/rbtree_augmented.h 228LIB_H += util/include/linux/rbtree_augmented.h
226LIB_H += util/include/linux/string.h 229LIB_H += util/include/linux/string.h
@@ -244,7 +247,6 @@ LIB_H += util/cache.h
244LIB_H += util/callchain.h 247LIB_H += util/callchain.h
245LIB_H += util/build-id.h 248LIB_H += util/build-id.h
246LIB_H += util/debug.h 249LIB_H += util/debug.h
247LIB_H += util/fs.h
248LIB_H += util/pmu.h 250LIB_H += util/pmu.h
249LIB_H += util/event.h 251LIB_H += util/event.h
250LIB_H += util/evsel.h 252LIB_H += util/evsel.h
@@ -306,7 +308,6 @@ LIB_OBJS += $(OUTPUT)util/annotate.o
306LIB_OBJS += $(OUTPUT)util/build-id.o 308LIB_OBJS += $(OUTPUT)util/build-id.o
307LIB_OBJS += $(OUTPUT)util/config.o 309LIB_OBJS += $(OUTPUT)util/config.o
308LIB_OBJS += $(OUTPUT)util/ctype.o 310LIB_OBJS += $(OUTPUT)util/ctype.o
309LIB_OBJS += $(OUTPUT)util/fs.o
310LIB_OBJS += $(OUTPUT)util/pmu.o 311LIB_OBJS += $(OUTPUT)util/pmu.o
311LIB_OBJS += $(OUTPUT)util/environment.o 312LIB_OBJS += $(OUTPUT)util/environment.o
312LIB_OBJS += $(OUTPUT)util/event.o 313LIB_OBJS += $(OUTPUT)util/event.o
@@ -408,6 +409,11 @@ endif
408LIB_OBJS += $(OUTPUT)tests/code-reading.o 409LIB_OBJS += $(OUTPUT)tests/code-reading.o
409LIB_OBJS += $(OUTPUT)tests/sample-parsing.o 410LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
410LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o 411LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
412ifndef NO_DWARF_UNWIND
413ifeq ($(ARCH),x86)
414LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o
415endif
416endif
411 417
412BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 418BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
413BUILTIN_OBJS += $(OUTPUT)builtin-bench.o 419BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
@@ -420,6 +426,9 @@ BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
420endif 426endif
421BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o 427BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
422BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o 428BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
429BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o
430BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o
431BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o
423 432
424BUILTIN_OBJS += $(OUTPUT)builtin-diff.o 433BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
425BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o 434BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
@@ -475,8 +484,13 @@ ifndef NO_DWARF
475endif # NO_DWARF 484endif # NO_DWARF
476endif # NO_LIBELF 485endif # NO_LIBELF
477 486
487ifndef NO_LIBDW_DWARF_UNWIND
488 LIB_OBJS += $(OUTPUT)util/unwind-libdw.o
489 LIB_H += util/unwind-libdw.h
490endif
491
478ifndef NO_LIBUNWIND 492ifndef NO_LIBUNWIND
479 LIB_OBJS += $(OUTPUT)util/unwind.o 493 LIB_OBJS += $(OUTPUT)util/unwind-libunwind.o
480endif 494endif
481LIB_OBJS += $(OUTPUT)tests/keep-tracking.o 495LIB_OBJS += $(OUTPUT)tests/keep-tracking.o
482 496
@@ -533,6 +547,7 @@ ifeq ($(NO_PERF_REGS),0)
533 ifeq ($(ARCH),x86) 547 ifeq ($(ARCH),x86)
534 LIB_H += arch/x86/include/perf_regs.h 548 LIB_H += arch/x86/include/perf_regs.h
535 endif 549 endif
550 LIB_OBJS += $(OUTPUT)util/perf_regs.o
536endif 551endif
537 552
538ifndef NO_LIBNUMA 553ifndef NO_LIBNUMA
@@ -574,7 +589,7 @@ $(GTK_OBJS): $(OUTPUT)%.o: %.c $(LIB_H)
574 $(QUIET_CC)$(CC) -o $@ -c -fPIC $(CFLAGS) $(GTK_CFLAGS) $< 589 $(QUIET_CC)$(CC) -o $@ -c -fPIC $(CFLAGS) $(GTK_CFLAGS) $<
575 590
576$(OUTPUT)libperf-gtk.so: $(GTK_OBJS) $(PERFLIBS) 591$(OUTPUT)libperf-gtk.so: $(GTK_OBJS) $(PERFLIBS)
577 $(QUIET_LINK)$(CC) -o $@ -shared $(ALL_LDFLAGS) $(filter %.o,$^) $(GTK_LIBS) 592 $(QUIET_LINK)$(CC) -o $@ -shared $(LDFLAGS) $(filter %.o,$^) $(GTK_LIBS)
578 593
579$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS 594$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
580 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \ 595 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
@@ -655,6 +670,9 @@ $(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
655 -DPYTHON='"$(PYTHON_WORD)"' \ 670 -DPYTHON='"$(PYTHON_WORD)"' \
656 $< 671 $<
657 672
673$(OUTPUT)tests/dwarf-unwind.o: tests/dwarf-unwind.c
674 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -fno-optimize-sibling-calls $<
675
658$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS 676$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
659 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 677 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
660 678
@@ -707,9 +725,15 @@ $(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
707# we depend the various files onto their directories. 725# we depend the various files onto their directories.
708DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS) 726DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS)
709DIRECTORY_DEPS += $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h 727DIRECTORY_DEPS += $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
710$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS))) 728# no need to add flex objects, because they depend on bison ones
729DIRECTORY_DEPS += $(OUTPUT)util/parse-events-bison.c
730DIRECTORY_DEPS += $(OUTPUT)util/pmu-bison.c
731
732OUTPUT_DIRECTORIES := $(sort $(dir $(DIRECTORY_DEPS)))
733
734$(DIRECTORY_DEPS): | $(OUTPUT_DIRECTORIES)
711# In the second step, we make a rule to actually create these directories 735# In the second step, we make a rule to actually create these directories
712$(sort $(dir $(DIRECTORY_DEPS))): 736$(OUTPUT_DIRECTORIES):
713 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null 737 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
714 738
715$(LIB_FILE): $(LIB_OBJS) 739$(LIB_FILE): $(LIB_OBJS)
@@ -886,7 +910,7 @@ config-clean:
886clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean 910clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
887 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) 911 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
888 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf 912 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
889 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* 913 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
890 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 914 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
891 $(python-clean) 915 $(python-clean)
892 916
diff --git a/tools/perf/arch/arm/Makefile b/tools/perf/arch/arm/Makefile
index fe9b61e322a5..67e9b3d38e89 100644
--- a/tools/perf/arch/arm/Makefile
+++ b/tools/perf/arch/arm/Makefile
@@ -3,5 +3,5 @@ PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o 3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 4endif
5ifndef NO_LIBUNWIND 5ifndef NO_LIBUNWIND
6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o 6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
7endif 7endif
diff --git a/tools/perf/arch/arm/util/unwind.c b/tools/perf/arch/arm/util/unwind-libunwind.c
index da3dc950550c..729ed69a6664 100644
--- a/tools/perf/arch/arm/util/unwind.c
+++ b/tools/perf/arch/arm/util/unwind-libunwind.c
@@ -4,7 +4,7 @@
4#include "perf_regs.h" 4#include "perf_regs.h"
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6 6
7int unwind__arch_reg_id(int regnum) 7int libunwind__arch_reg_id(int regnum)
8{ 8{
9 switch (regnum) { 9 switch (regnum) {
10 case UNW_ARM_R0: 10 case UNW_ARM_R0:
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 8801fe02f206..1641542e3636 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -3,7 +3,14 @@ PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o 3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 4endif
5ifndef NO_LIBUNWIND 5ifndef NO_LIBUNWIND
6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o 6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
7endif
8ifndef NO_LIBDW_DWARF_UNWIND
9LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libdw.o
10endif
11ifndef NO_DWARF_UNWIND
12LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o
13LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o
7endif 14endif
8LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o 15LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
9LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o 16LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o
diff --git a/tools/perf/arch/x86/include/perf_regs.h b/tools/perf/arch/x86/include/perf_regs.h
index e84ca76aae77..fc819ca34a7e 100644
--- a/tools/perf/arch/x86/include/perf_regs.h
+++ b/tools/perf/arch/x86/include/perf_regs.h
@@ -5,14 +5,20 @@
5#include "../../util/types.h" 5#include "../../util/types.h"
6#include <asm/perf_regs.h> 6#include <asm/perf_regs.h>
7 7
8void perf_regs_load(u64 *regs);
9
8#ifndef HAVE_ARCH_X86_64_SUPPORT 10#ifndef HAVE_ARCH_X86_64_SUPPORT
9#define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1) 11#define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1)
12#define PERF_REGS_MAX PERF_REG_X86_32_MAX
13#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32
10#else 14#else
11#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ 15#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \
12 (1ULL << PERF_REG_X86_ES) | \ 16 (1ULL << PERF_REG_X86_ES) | \
13 (1ULL << PERF_REG_X86_FS) | \ 17 (1ULL << PERF_REG_X86_FS) | \
14 (1ULL << PERF_REG_X86_GS)) 18 (1ULL << PERF_REG_X86_GS))
15#define PERF_REGS_MASK (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~REG_NOSUPPORT) 19#define PERF_REGS_MASK (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~REG_NOSUPPORT)
20#define PERF_REGS_MAX PERF_REG_X86_64_MAX
21#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
16#endif 22#endif
17#define PERF_REG_IP PERF_REG_X86_IP 23#define PERF_REG_IP PERF_REG_X86_IP
18#define PERF_REG_SP PERF_REG_X86_SP 24#define PERF_REG_SP PERF_REG_X86_SP
diff --git a/tools/perf/arch/x86/tests/dwarf-unwind.c b/tools/perf/arch/x86/tests/dwarf-unwind.c
new file mode 100644
index 000000000000..83bc2385e6d3
--- /dev/null
+++ b/tools/perf/arch/x86/tests/dwarf-unwind.c
@@ -0,0 +1,60 @@
1#include <string.h>
2#include "perf_regs.h"
3#include "thread.h"
4#include "map.h"
5#include "event.h"
6#include "tests/tests.h"
7
8#define STACK_SIZE 8192
9
10static int sample_ustack(struct perf_sample *sample,
11 struct thread *thread, u64 *regs)
12{
13 struct stack_dump *stack = &sample->user_stack;
14 struct map *map;
15 unsigned long sp;
16 u64 stack_size, *buf;
17
18 buf = malloc(STACK_SIZE);
19 if (!buf) {
20 pr_debug("failed to allocate sample uregs data\n");
21 return -1;
22 }
23
24 sp = (unsigned long) regs[PERF_REG_X86_SP];
25
26 map = map_groups__find(&thread->mg, MAP__VARIABLE, (u64) sp);
27 if (!map) {
28 pr_debug("failed to get stack map\n");
29 free(buf);
30 return -1;
31 }
32
33 stack_size = map->end - sp;
34 stack_size = stack_size > STACK_SIZE ? STACK_SIZE : stack_size;
35
36 memcpy(buf, (void *) sp, stack_size);
37 stack->data = (char *) buf;
38 stack->size = stack_size;
39 return 0;
40}
41
42int test__arch_unwind_sample(struct perf_sample *sample,
43 struct thread *thread)
44{
45 struct regs_dump *regs = &sample->user_regs;
46 u64 *buf;
47
48 buf = malloc(sizeof(u64) * PERF_REGS_MAX);
49 if (!buf) {
50 pr_debug("failed to allocate sample uregs data\n");
51 return -1;
52 }
53
54 perf_regs_load(buf);
55 regs->abi = PERF_SAMPLE_REGS_ABI;
56 regs->regs = buf;
57 regs->mask = PERF_REGS_MASK;
58
59 return sample_ustack(sample, thread, buf);
60}
diff --git a/tools/perf/arch/x86/tests/regs_load.S b/tools/perf/arch/x86/tests/regs_load.S
new file mode 100644
index 000000000000..60875d5c556c
--- /dev/null
+++ b/tools/perf/arch/x86/tests/regs_load.S
@@ -0,0 +1,98 @@
1#include <linux/linkage.h>
2
3#define AX 0
4#define BX 1 * 8
5#define CX 2 * 8
6#define DX 3 * 8
7#define SI 4 * 8
8#define DI 5 * 8
9#define BP 6 * 8
10#define SP 7 * 8
11#define IP 8 * 8
12#define FLAGS 9 * 8
13#define CS 10 * 8
14#define SS 11 * 8
15#define DS 12 * 8
16#define ES 13 * 8
17#define FS 14 * 8
18#define GS 15 * 8
19#define R8 16 * 8
20#define R9 17 * 8
21#define R10 18 * 8
22#define R11 19 * 8
23#define R12 20 * 8
24#define R13 21 * 8
25#define R14 22 * 8
26#define R15 23 * 8
27
28.text
29#ifdef HAVE_ARCH_X86_64_SUPPORT
30ENTRY(perf_regs_load)
31 movq %rax, AX(%rdi)
32 movq %rbx, BX(%rdi)
33 movq %rcx, CX(%rdi)
34 movq %rdx, DX(%rdi)
35 movq %rsi, SI(%rdi)
36 movq %rdi, DI(%rdi)
37 movq %rbp, BP(%rdi)
38
39 leaq 8(%rsp), %rax /* exclude this call. */
40 movq %rax, SP(%rdi)
41
42 movq 0(%rsp), %rax
43 movq %rax, IP(%rdi)
44
45 movq $0, FLAGS(%rdi)
46 movq $0, CS(%rdi)
47 movq $0, SS(%rdi)
48 movq $0, DS(%rdi)
49 movq $0, ES(%rdi)
50 movq $0, FS(%rdi)
51 movq $0, GS(%rdi)
52
53 movq %r8, R8(%rdi)
54 movq %r9, R9(%rdi)
55 movq %r10, R10(%rdi)
56 movq %r11, R11(%rdi)
57 movq %r12, R12(%rdi)
58 movq %r13, R13(%rdi)
59 movq %r14, R14(%rdi)
60 movq %r15, R15(%rdi)
61 ret
62ENDPROC(perf_regs_load)
63#else
64ENTRY(perf_regs_load)
65 push %edi
66 movl 8(%esp), %edi
67 movl %eax, AX(%edi)
68 movl %ebx, BX(%edi)
69 movl %ecx, CX(%edi)
70 movl %edx, DX(%edi)
71 movl %esi, SI(%edi)
72 pop %eax
73 movl %eax, DI(%edi)
74 movl %ebp, BP(%edi)
75
76 leal 4(%esp), %eax /* exclude this call. */
77 movl %eax, SP(%edi)
78
79 movl 0(%esp), %eax
80 movl %eax, IP(%edi)
81
82 movl $0, FLAGS(%edi)
83 movl $0, CS(%edi)
84 movl $0, SS(%edi)
85 movl $0, DS(%edi)
86 movl $0, ES(%edi)
87 movl $0, FS(%edi)
88 movl $0, GS(%edi)
89 ret
90ENDPROC(perf_regs_load)
91#endif
92
93/*
94 * We need to provide note.GNU-stack section, saying that we want
95 * NOT executable stack. Otherwise the final linking will assume that
96 * the ELF stack should not be restricted at all and set it RWX.
97 */
98.section .note.GNU-stack,"",@progbits
diff --git a/tools/perf/arch/x86/util/unwind-libdw.c b/tools/perf/arch/x86/util/unwind-libdw.c
new file mode 100644
index 000000000000..c4b72176ca83
--- /dev/null
+++ b/tools/perf/arch/x86/util/unwind-libdw.c
@@ -0,0 +1,51 @@
1#include <elfutils/libdwfl.h>
2#include "../../util/unwind-libdw.h"
3#include "../../util/perf_regs.h"
4
5bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
6{
7 struct unwind_info *ui = arg;
8 struct regs_dump *user_regs = &ui->sample->user_regs;
9 Dwarf_Word dwarf_regs[17];
10 unsigned nregs;
11
12#define REG(r) ({ \
13 Dwarf_Word val = 0; \
14 perf_reg_value(&val, user_regs, PERF_REG_X86_##r); \
15 val; \
16})
17
18 if (user_regs->abi == PERF_SAMPLE_REGS_ABI_32) {
19 dwarf_regs[0] = REG(AX);
20 dwarf_regs[1] = REG(CX);
21 dwarf_regs[2] = REG(DX);
22 dwarf_regs[3] = REG(BX);
23 dwarf_regs[4] = REG(SP);
24 dwarf_regs[5] = REG(BP);
25 dwarf_regs[6] = REG(SI);
26 dwarf_regs[7] = REG(DI);
27 dwarf_regs[8] = REG(IP);
28 nregs = 9;
29 } else {
30 dwarf_regs[0] = REG(AX);
31 dwarf_regs[1] = REG(DX);
32 dwarf_regs[2] = REG(CX);
33 dwarf_regs[3] = REG(BX);
34 dwarf_regs[4] = REG(SI);
35 dwarf_regs[5] = REG(DI);
36 dwarf_regs[6] = REG(BP);
37 dwarf_regs[7] = REG(SP);
38 dwarf_regs[8] = REG(R8);
39 dwarf_regs[9] = REG(R9);
40 dwarf_regs[10] = REG(R10);
41 dwarf_regs[11] = REG(R11);
42 dwarf_regs[12] = REG(R12);
43 dwarf_regs[13] = REG(R13);
44 dwarf_regs[14] = REG(R14);
45 dwarf_regs[15] = REG(R15);
46 dwarf_regs[16] = REG(IP);
47 nregs = 17;
48 }
49
50 return dwfl_thread_state_registers(thread, 0, nregs, dwarf_regs);
51}
diff --git a/tools/perf/arch/x86/util/unwind.c b/tools/perf/arch/x86/util/unwind-libunwind.c
index 456a88cf5b37..3261f68c6a7c 100644
--- a/tools/perf/arch/x86/util/unwind.c
+++ b/tools/perf/arch/x86/util/unwind-libunwind.c
@@ -5,7 +5,7 @@
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6 6
7#ifdef HAVE_ARCH_X86_64_SUPPORT 7#ifdef HAVE_ARCH_X86_64_SUPPORT
8int unwind__arch_reg_id(int regnum) 8int libunwind__arch_reg_id(int regnum)
9{ 9{
10 int id; 10 int id;
11 11
@@ -69,7 +69,7 @@ int unwind__arch_reg_id(int regnum)
69 return id; 69 return id;
70} 70}
71#else 71#else
72int unwind__arch_reg_id(int regnum) 72int libunwind__arch_reg_id(int regnum)
73{ 73{
74 int id; 74 int id;
75 75
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
index 0fdc85269c4d..eba46709b279 100644
--- a/tools/perf/bench/bench.h
+++ b/tools/perf/bench/bench.h
@@ -31,6 +31,9 @@ extern int bench_sched_pipe(int argc, const char **argv, const char *prefix);
31extern int bench_mem_memcpy(int argc, const char **argv, 31extern int bench_mem_memcpy(int argc, const char **argv,
32 const char *prefix __maybe_unused); 32 const char *prefix __maybe_unused);
33extern int bench_mem_memset(int argc, const char **argv, const char *prefix); 33extern int bench_mem_memset(int argc, const char **argv, const char *prefix);
34extern int bench_futex_hash(int argc, const char **argv, const char *prefix);
35extern int bench_futex_wake(int argc, const char **argv, const char *prefix);
36extern int bench_futex_requeue(int argc, const char **argv, const char *prefix);
34 37
35#define BENCH_FORMAT_DEFAULT_STR "default" 38#define BENCH_FORMAT_DEFAULT_STR "default"
36#define BENCH_FORMAT_DEFAULT 0 39#define BENCH_FORMAT_DEFAULT 0
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
new file mode 100644
index 000000000000..a84206e9c4aa
--- /dev/null
+++ b/tools/perf/bench/futex-hash.c
@@ -0,0 +1,212 @@
1/*
2 * Copyright (C) 2013 Davidlohr Bueso <davidlohr@hp.com>
3 *
4 * futex-hash: Stress the hell out of the Linux kernel futex uaddr hashing.
5 *
6 * This program is particularly useful for measuring the kernel's futex hash
7 * table/function implementation. In order for it to make sense, use with as
8 * many threads and futexes as possible.
9 */
10
11#include "../perf.h"
12#include "../util/util.h"
13#include "../util/stat.h"
14#include "../util/parse-options.h"
15#include "../util/header.h"
16#include "bench.h"
17#include "futex.h"
18
19#include <err.h>
20#include <stdlib.h>
21#include <sys/time.h>
22#include <pthread.h>
23
24static unsigned int nthreads = 0;
25static unsigned int nsecs = 10;
26/* amount of futexes per thread */
27static unsigned int nfutexes = 1024;
28static bool fshared = false, done = false, silent = false;
29
30struct timeval start, end, runtime;
31static pthread_mutex_t thread_lock;
32static unsigned int threads_starting;
33static struct stats throughput_stats;
34static pthread_cond_t thread_parent, thread_worker;
35
36struct worker {
37 int tid;
38 u_int32_t *futex;
39 pthread_t thread;
40 unsigned long ops;
41};
42
43static const struct option options[] = {
44 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
45 OPT_UINTEGER('r', "runtime", &nsecs, "Specify runtime (in seconds)"),
46 OPT_UINTEGER('f', "futexes", &nfutexes, "Specify amount of futexes per threads"),
47 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
48 OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
49 OPT_END()
50};
51
52static const char * const bench_futex_hash_usage[] = {
53 "perf bench futex hash <options>",
54 NULL
55};
56
57static void *workerfn(void *arg)
58{
59 int ret;
60 unsigned int i;
61 struct worker *w = (struct worker *) arg;
62
63 pthread_mutex_lock(&thread_lock);
64 threads_starting--;
65 if (!threads_starting)
66 pthread_cond_signal(&thread_parent);
67 pthread_cond_wait(&thread_worker, &thread_lock);
68 pthread_mutex_unlock(&thread_lock);
69
70 do {
71 for (i = 0; i < nfutexes; i++, w->ops++) {
72 /*
73 * We want the futex calls to fail in order to stress
74 * the hashing of uaddr and not measure other steps,
75 * such as internal waitqueue handling, thus enlarging
76 * the critical region protected by hb->lock.
77 */
78 ret = futex_wait(&w->futex[i], 1234, NULL,
79 fshared ? 0 : FUTEX_PRIVATE_FLAG);
80 if (!silent &&
81 (!ret || errno != EAGAIN || errno != EWOULDBLOCK))
82 warn("Non-expected futex return call");
83 }
84 } while (!done);
85
86 return NULL;
87}
88
89static void toggle_done(int sig __maybe_unused,
90 siginfo_t *info __maybe_unused,
91 void *uc __maybe_unused)
92{
93 /* inform all threads that we're done for the day */
94 done = true;
95 gettimeofday(&end, NULL);
96 timersub(&end, &start, &runtime);
97}
98
99static void print_summary(void)
100{
101 unsigned long avg = avg_stats(&throughput_stats);
102 double stddev = stddev_stats(&throughput_stats);
103
104 printf("%sAveraged %ld operations/sec (+- %.2f%%), total secs = %d\n",
105 !silent ? "\n" : "", avg, rel_stddev_stats(stddev, avg),
106 (int) runtime.tv_sec);
107}
108
109int bench_futex_hash(int argc, const char **argv,
110 const char *prefix __maybe_unused)
111{
112 int ret = 0;
113 cpu_set_t cpu;
114 struct sigaction act;
115 unsigned int i, ncpus;
116 pthread_attr_t thread_attr;
117 struct worker *worker = NULL;
118
119 argc = parse_options(argc, argv, options, bench_futex_hash_usage, 0);
120 if (argc) {
121 usage_with_options(bench_futex_hash_usage, options);
122 exit(EXIT_FAILURE);
123 }
124
125 ncpus = sysconf(_SC_NPROCESSORS_ONLN);
126
127 sigfillset(&act.sa_mask);
128 act.sa_sigaction = toggle_done;
129 sigaction(SIGINT, &act, NULL);
130
131 if (!nthreads) /* default to the number of CPUs */
132 nthreads = ncpus;
133
134 worker = calloc(nthreads, sizeof(*worker));
135 if (!worker)
136 goto errmem;
137
138 printf("Run summary [PID %d]: %d threads, each operating on %d [%s] futexes for %d secs.\n\n",
139 getpid(), nthreads, nfutexes, fshared ? "shared":"private", nsecs);
140
141 init_stats(&throughput_stats);
142 pthread_mutex_init(&thread_lock, NULL);
143 pthread_cond_init(&thread_parent, NULL);
144 pthread_cond_init(&thread_worker, NULL);
145
146 threads_starting = nthreads;
147 pthread_attr_init(&thread_attr);
148 gettimeofday(&start, NULL);
149 for (i = 0; i < nthreads; i++) {
150 worker[i].tid = i;
151 worker[i].futex = calloc(nfutexes, sizeof(*worker[i].futex));
152 if (!worker[i].futex)
153 goto errmem;
154
155 CPU_ZERO(&cpu);
156 CPU_SET(i % ncpus, &cpu);
157
158 ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu);
159 if (ret)
160 err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
161
162 ret = pthread_create(&worker[i].thread, &thread_attr, workerfn,
163 (void *)(struct worker *) &worker[i]);
164 if (ret)
165 err(EXIT_FAILURE, "pthread_create");
166
167 }
168 pthread_attr_destroy(&thread_attr);
169
170 pthread_mutex_lock(&thread_lock);
171 while (threads_starting)
172 pthread_cond_wait(&thread_parent, &thread_lock);
173 pthread_cond_broadcast(&thread_worker);
174 pthread_mutex_unlock(&thread_lock);
175
176 sleep(nsecs);
177 toggle_done(0, NULL, NULL);
178
179 for (i = 0; i < nthreads; i++) {
180 ret = pthread_join(worker[i].thread, NULL);
181 if (ret)
182 err(EXIT_FAILURE, "pthread_join");
183 }
184
185 /* cleanup & report results */
186 pthread_cond_destroy(&thread_parent);
187 pthread_cond_destroy(&thread_worker);
188 pthread_mutex_destroy(&thread_lock);
189
190 for (i = 0; i < nthreads; i++) {
191 unsigned long t = worker[i].ops/runtime.tv_sec;
192 update_stats(&throughput_stats, t);
193 if (!silent) {
194 if (nfutexes == 1)
195 printf("[thread %2d] futex: %p [ %ld ops/sec ]\n",
196 worker[i].tid, &worker[i].futex[0], t);
197 else
198 printf("[thread %2d] futexes: %p ... %p [ %ld ops/sec ]\n",
199 worker[i].tid, &worker[i].futex[0],
200 &worker[i].futex[nfutexes-1], t);
201 }
202
203 free(worker[i].futex);
204 }
205
206 print_summary();
207
208 free(worker);
209 return ret;
210errmem:
211 err(EXIT_FAILURE, "calloc");
212}
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
new file mode 100644
index 000000000000..a16255876f1d
--- /dev/null
+++ b/tools/perf/bench/futex-requeue.c
@@ -0,0 +1,211 @@
1/*
2 * Copyright (C) 2013 Davidlohr Bueso <davidlohr@hp.com>
3 *
4 * futex-requeue: Block a bunch of threads on futex1 and requeue them
5 * on futex2, N at a time.
6 *
7 * This program is particularly useful to measure the latency of nthread
8 * requeues without waking up any tasks -- thus mimicking a regular futex_wait.
9 */
10
11#include "../perf.h"
12#include "../util/util.h"
13#include "../util/stat.h"
14#include "../util/parse-options.h"
15#include "../util/header.h"
16#include "bench.h"
17#include "futex.h"
18
19#include <err.h>
20#include <stdlib.h>
21#include <sys/time.h>
22#include <pthread.h>
23
24static u_int32_t futex1 = 0, futex2 = 0;
25
26/*
27 * How many tasks to requeue at a time.
28 * Default to 1 in order to make the kernel work more.
29 */
30static unsigned int nrequeue = 1;
31
32/*
33 * There can be significant variance from run to run,
34 * the more repeats, the more exact the overall avg and
35 * the better idea of the futex latency.
36 */
37static unsigned int repeat = 10;
38
39static pthread_t *worker;
40static bool done = 0, silent = 0;
41static pthread_mutex_t thread_lock;
42static pthread_cond_t thread_parent, thread_worker;
43static struct stats requeuetime_stats, requeued_stats;
44static unsigned int ncpus, threads_starting, nthreads = 0;
45
46static const struct option options[] = {
47 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
48 OPT_UINTEGER('q', "nrequeue", &nrequeue, "Specify amount of threads to requeue at once"),
49 OPT_UINTEGER('r', "repeat", &repeat, "Specify amount of times to repeat the run"),
50 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
51 OPT_END()
52};
53
54static const char * const bench_futex_requeue_usage[] = {
55 "perf bench futex requeue <options>",
56 NULL
57};
58
59static void print_summary(void)
60{
61 double requeuetime_avg = avg_stats(&requeuetime_stats);
62 double requeuetime_stddev = stddev_stats(&requeuetime_stats);
63 unsigned int requeued_avg = avg_stats(&requeued_stats);
64
65 printf("Requeued %d of %d threads in %.4f ms (+-%.2f%%)\n",
66 requeued_avg,
67 nthreads,
68 requeuetime_avg/1e3,
69 rel_stddev_stats(requeuetime_stddev, requeuetime_avg));
70}
71
72static void *workerfn(void *arg __maybe_unused)
73{
74 pthread_mutex_lock(&thread_lock);
75 threads_starting--;
76 if (!threads_starting)
77 pthread_cond_signal(&thread_parent);
78 pthread_cond_wait(&thread_worker, &thread_lock);
79 pthread_mutex_unlock(&thread_lock);
80
81 futex_wait(&futex1, 0, NULL, FUTEX_PRIVATE_FLAG);
82 return NULL;
83}
84
85static void block_threads(pthread_t *w,
86 pthread_attr_t thread_attr)
87{
88 cpu_set_t cpu;
89 unsigned int i;
90
91 threads_starting = nthreads;
92
93 /* create and block all threads */
94 for (i = 0; i < nthreads; i++) {
95 CPU_ZERO(&cpu);
96 CPU_SET(i % ncpus, &cpu);
97
98 if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu))
99 err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
100
101 if (pthread_create(&w[i], &thread_attr, workerfn, NULL))
102 err(EXIT_FAILURE, "pthread_create");
103 }
104}
105
106static void toggle_done(int sig __maybe_unused,
107 siginfo_t *info __maybe_unused,
108 void *uc __maybe_unused)
109{
110 done = true;
111}
112
113int bench_futex_requeue(int argc, const char **argv,
114 const char *prefix __maybe_unused)
115{
116 int ret = 0;
117 unsigned int i, j;
118 struct sigaction act;
119 pthread_attr_t thread_attr;
120
121 argc = parse_options(argc, argv, options, bench_futex_requeue_usage, 0);
122 if (argc)
123 goto err;
124
125 ncpus = sysconf(_SC_NPROCESSORS_ONLN);
126
127 sigfillset(&act.sa_mask);
128 act.sa_sigaction = toggle_done;
129 sigaction(SIGINT, &act, NULL);
130
131 if (!nthreads)
132 nthreads = ncpus;
133
134 worker = calloc(nthreads, sizeof(*worker));
135 if (!worker)
136 err(EXIT_FAILURE, "calloc");
137
138 printf("Run summary [PID %d]: Requeuing %d threads (from %p to %p), "
139 "%d at a time.\n\n",
140 getpid(), nthreads, &futex1, &futex2, nrequeue);
141
142 init_stats(&requeued_stats);
143 init_stats(&requeuetime_stats);
144 pthread_attr_init(&thread_attr);
145 pthread_mutex_init(&thread_lock, NULL);
146 pthread_cond_init(&thread_parent, NULL);
147 pthread_cond_init(&thread_worker, NULL);
148
149 for (j = 0; j < repeat && !done; j++) {
150 unsigned int nrequeued = 0;
151 struct timeval start, end, runtime;
152
153 /* create, launch & block all threads */
154 block_threads(worker, thread_attr);
155
156 /* make sure all threads are already blocked */
157 pthread_mutex_lock(&thread_lock);
158 while (threads_starting)
159 pthread_cond_wait(&thread_parent, &thread_lock);
160 pthread_cond_broadcast(&thread_worker);
161 pthread_mutex_unlock(&thread_lock);
162
163 usleep(100000);
164
165 /* Ok, all threads are patiently blocked, start requeueing */
166 gettimeofday(&start, NULL);
167 for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue)
168 /*
169 * Do not wakeup any tasks blocked on futex1, allowing
170 * us to really measure futex_wait functionality.
171 */
172 futex_cmp_requeue(&futex1, 0, &futex2, 0, nrequeue,
173 FUTEX_PRIVATE_FLAG);
174 gettimeofday(&end, NULL);
175 timersub(&end, &start, &runtime);
176
177 update_stats(&requeued_stats, nrequeued);
178 update_stats(&requeuetime_stats, runtime.tv_usec);
179
180 if (!silent) {
181 printf("[Run %d]: Requeued %d of %d threads in %.4f ms\n",
182 j + 1, nrequeued, nthreads, runtime.tv_usec/1e3);
183 }
184
185 /* everybody should be blocked on futex2, wake'em up */
186 nrequeued = futex_wake(&futex2, nthreads, FUTEX_PRIVATE_FLAG);
187 if (nthreads != nrequeued)
188 warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads);
189
190 for (i = 0; i < nthreads; i++) {
191 ret = pthread_join(worker[i], NULL);
192 if (ret)
193 err(EXIT_FAILURE, "pthread_join");
194 }
195
196 }
197
198 /* cleanup & report results */
199 pthread_cond_destroy(&thread_parent);
200 pthread_cond_destroy(&thread_worker);
201 pthread_mutex_destroy(&thread_lock);
202 pthread_attr_destroy(&thread_attr);
203
204 print_summary();
205
206 free(worker);
207 return ret;
208err:
209 usage_with_options(bench_futex_requeue_usage, options);
210 exit(EXIT_FAILURE);
211}
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
new file mode 100644
index 000000000000..d096169b161e
--- /dev/null
+++ b/tools/perf/bench/futex-wake.c
@@ -0,0 +1,201 @@
1/*
2 * Copyright (C) 2013 Davidlohr Bueso <davidlohr@hp.com>
3 *
4 * futex-wake: Block a bunch of threads on a futex and wake'em up, N at a time.
5 *
6 * This program is particularly useful to measure the latency of nthread wakeups
7 * in non-error situations: all waiters are queued and all wake calls wakeup
8 * one or more tasks, and thus the waitqueue is never empty.
9 */
10
11#include "../perf.h"
12#include "../util/util.h"
13#include "../util/stat.h"
14#include "../util/parse-options.h"
15#include "../util/header.h"
16#include "bench.h"
17#include "futex.h"
18
19#include <err.h>
20#include <stdlib.h>
21#include <sys/time.h>
22#include <pthread.h>
23
24/* all threads will block on the same futex */
25static u_int32_t futex1 = 0;
26
27/*
28 * How many wakeups to do at a time.
29 * Default to 1 in order to make the kernel work more.
30 */
31static unsigned int nwakes = 1;
32
33/*
34 * There can be significant variance from run to run,
35 * the more repeats, the more exact the overall avg and
36 * the better idea of the futex latency.
37 */
38static unsigned int repeat = 10;
39
40pthread_t *worker;
41static bool done = 0, silent = 0;
42static pthread_mutex_t thread_lock;
43static pthread_cond_t thread_parent, thread_worker;
44static struct stats waketime_stats, wakeup_stats;
45static unsigned int ncpus, threads_starting, nthreads = 0;
46
47static const struct option options[] = {
48 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
49 OPT_UINTEGER('w', "nwakes", &nwakes, "Specify amount of threads to wake at once"),
50 OPT_UINTEGER('r', "repeat", &repeat, "Specify amount of times to repeat the run"),
51 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
52 OPT_END()
53};
54
55static const char * const bench_futex_wake_usage[] = {
56 "perf bench futex wake <options>",
57 NULL
58};
59
60static void *workerfn(void *arg __maybe_unused)
61{
62 pthread_mutex_lock(&thread_lock);
63 threads_starting--;
64 if (!threads_starting)
65 pthread_cond_signal(&thread_parent);
66 pthread_cond_wait(&thread_worker, &thread_lock);
67 pthread_mutex_unlock(&thread_lock);
68
69 futex_wait(&futex1, 0, NULL, FUTEX_PRIVATE_FLAG);
70 return NULL;
71}
72
73static void print_summary(void)
74{
75 double waketime_avg = avg_stats(&waketime_stats);
76 double waketime_stddev = stddev_stats(&waketime_stats);
77 unsigned int wakeup_avg = avg_stats(&wakeup_stats);
78
79 printf("Wokeup %d of %d threads in %.4f ms (+-%.2f%%)\n",
80 wakeup_avg,
81 nthreads,
82 waketime_avg/1e3,
83 rel_stddev_stats(waketime_stddev, waketime_avg));
84}
85
86static void block_threads(pthread_t *w,
87 pthread_attr_t thread_attr)
88{
89 cpu_set_t cpu;
90 unsigned int i;
91
92 threads_starting = nthreads;
93
94 /* create and block all threads */
95 for (i = 0; i < nthreads; i++) {
96 CPU_ZERO(&cpu);
97 CPU_SET(i % ncpus, &cpu);
98
99 if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu))
100 err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
101
102 if (pthread_create(&w[i], &thread_attr, workerfn, NULL))
103 err(EXIT_FAILURE, "pthread_create");
104 }
105}
106
107static void toggle_done(int sig __maybe_unused,
108 siginfo_t *info __maybe_unused,
109 void *uc __maybe_unused)
110{
111 done = true;
112}
113
114int bench_futex_wake(int argc, const char **argv,
115 const char *prefix __maybe_unused)
116{
117 int ret = 0;
118 unsigned int i, j;
119 struct sigaction act;
120 pthread_attr_t thread_attr;
121
122 argc = parse_options(argc, argv, options, bench_futex_wake_usage, 0);
123 if (argc) {
124 usage_with_options(bench_futex_wake_usage, options);
125 exit(EXIT_FAILURE);
126 }
127
128 ncpus = sysconf(_SC_NPROCESSORS_ONLN);
129
130 sigfillset(&act.sa_mask);
131 act.sa_sigaction = toggle_done;
132 sigaction(SIGINT, &act, NULL);
133
134 if (!nthreads)
135 nthreads = ncpus;
136
137 worker = calloc(nthreads, sizeof(*worker));
138 if (!worker)
139 err(EXIT_FAILURE, "calloc");
140
141 printf("Run summary [PID %d]: blocking on %d threads (at futex %p), "
142 "waking up %d at a time.\n\n",
143 getpid(), nthreads, &futex1, nwakes);
144
145 init_stats(&wakeup_stats);
146 init_stats(&waketime_stats);
147 pthread_attr_init(&thread_attr);
148 pthread_mutex_init(&thread_lock, NULL);
149 pthread_cond_init(&thread_parent, NULL);
150 pthread_cond_init(&thread_worker, NULL);
151
152 for (j = 0; j < repeat && !done; j++) {
153 unsigned int nwoken = 0;
154 struct timeval start, end, runtime;
155
156 /* create, launch & block all threads */
157 block_threads(worker, thread_attr);
158
159 /* make sure all threads are already blocked */
160 pthread_mutex_lock(&thread_lock);
161 while (threads_starting)
162 pthread_cond_wait(&thread_parent, &thread_lock);
163 pthread_cond_broadcast(&thread_worker);
164 pthread_mutex_unlock(&thread_lock);
165
166 usleep(100000);
167
168 /* Ok, all threads are patiently blocked, start waking folks up */
169 gettimeofday(&start, NULL);
170 while (nwoken != nthreads)
171 nwoken += futex_wake(&futex1, nwakes, FUTEX_PRIVATE_FLAG);
172 gettimeofday(&end, NULL);
173 timersub(&end, &start, &runtime);
174
175 update_stats(&wakeup_stats, nwoken);
176 update_stats(&waketime_stats, runtime.tv_usec);
177
178 if (!silent) {
179 printf("[Run %d]: Wokeup %d of %d threads in %.4f ms\n",
180 j + 1, nwoken, nthreads, runtime.tv_usec/1e3);
181 }
182
183 for (i = 0; i < nthreads; i++) {
184 ret = pthread_join(worker[i], NULL);
185 if (ret)
186 err(EXIT_FAILURE, "pthread_join");
187 }
188
189 }
190
191 /* cleanup & report results */
192 pthread_cond_destroy(&thread_parent);
193 pthread_cond_destroy(&thread_worker);
194 pthread_mutex_destroy(&thread_lock);
195 pthread_attr_destroy(&thread_attr);
196
197 print_summary();
198
199 free(worker);
200 return ret;
201}
diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
new file mode 100644
index 000000000000..71f2844cf97f
--- /dev/null
+++ b/tools/perf/bench/futex.h
@@ -0,0 +1,71 @@
1/*
2 * Glibc independent futex library for testing kernel functionality.
3 * Shamelessly stolen from Darren Hart <dvhltc@us.ibm.com>
4 * http://git.kernel.org/cgit/linux/kernel/git/dvhart/futextest.git/
5 */
6
7#ifndef _FUTEX_H
8#define _FUTEX_H
9
10#include <unistd.h>
11#include <sys/syscall.h>
12#include <sys/types.h>
13#include <linux/futex.h>
14
15/**
16 * futex() - SYS_futex syscall wrapper
17 * @uaddr: address of first futex
18 * @op: futex op code
19 * @val: typically expected value of uaddr, but varies by op
20 * @timeout: typically an absolute struct timespec (except where noted
21 * otherwise). Overloaded by some ops
22 * @uaddr2: address of second futex for some ops\
23 * @val3: varies by op
24 * @opflags: flags to be bitwise OR'd with op, such as FUTEX_PRIVATE_FLAG
25 *
26 * futex() is used by all the following futex op wrappers. It can also be
27 * used for misuse and abuse testing. Generally, the specific op wrappers
28 * should be used instead. It is a macro instead of an static inline function as
29 * some of the types over overloaded (timeout is used for nr_requeue for
30 * example).
31 *
32 * These argument descriptions are the defaults for all
33 * like-named arguments in the following wrappers except where noted below.
34 */
35#define futex(uaddr, op, val, timeout, uaddr2, val3, opflags) \
36 syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3)
37
38/**
39 * futex_wait() - block on uaddr with optional timeout
40 * @timeout: relative timeout
41 */
42static inline int
43futex_wait(u_int32_t *uaddr, u_int32_t val, struct timespec *timeout, int opflags)
44{
45 return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
46}
47
48/**
49 * futex_wake() - wake one or more tasks blocked on uaddr
50 * @nr_wake: wake up to this many tasks
51 */
52static inline int
53futex_wake(u_int32_t *uaddr, int nr_wake, int opflags)
54{
55 return futex(uaddr, FUTEX_WAKE, nr_wake, NULL, NULL, 0, opflags);
56}
57
58/**
59* futex_cmp_requeue() - requeue tasks from uaddr to uaddr2
60* @nr_wake: wake up to this many tasks
61* @nr_requeue: requeue up to this many tasks
62*/
63static inline int
64futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wake,
65 int nr_requeue, int opflags)
66{
67 return futex(uaddr, FUTEX_CMP_REQUEUE, nr_wake, nr_requeue, uaddr2,
68 val, opflags);
69}
70
71#endif /* _FUTEX_H */
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 97d86d828190..ebfa163b80b5 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -1593,6 +1593,10 @@ static void init_params(struct params *p, const char *name, int argc, const char
1593 p->data_rand_walk = true; 1593 p->data_rand_walk = true;
1594 p->nr_loops = -1; 1594 p->nr_loops = -1;
1595 p->init_random = true; 1595 p->init_random = true;
1596 p->mb_global_str = "1";
1597 p->nr_proc = 1;
1598 p->nr_threads = 1;
1599 p->nr_secs = 5;
1596 p->run_all = argc == 1; 1600 p->run_all = argc == 1;
1597} 1601}
1598 1602
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index 8a987d252780..1e6e77710545 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -12,6 +12,7 @@
12 * sched ... scheduler and IPC performance 12 * sched ... scheduler and IPC performance
13 * mem ... memory access performance 13 * mem ... memory access performance
14 * numa ... NUMA scheduling and MM performance 14 * numa ... NUMA scheduling and MM performance
15 * futex ... Futex performance
15 */ 16 */
16#include "perf.h" 17#include "perf.h"
17#include "util/util.h" 18#include "util/util.h"
@@ -54,6 +55,14 @@ static struct bench mem_benchmarks[] = {
54 { NULL, NULL, NULL } 55 { NULL, NULL, NULL }
55}; 56};
56 57
58static struct bench futex_benchmarks[] = {
59 { "hash", "Benchmark for futex hash table", bench_futex_hash },
60 { "wake", "Benchmark for futex wake calls", bench_futex_wake },
61 { "requeue", "Benchmark for futex requeue calls", bench_futex_requeue },
62 { "all", "Test all futex benchmarks", NULL },
63 { NULL, NULL, NULL }
64};
65
57struct collection { 66struct collection {
58 const char *name; 67 const char *name;
59 const char *summary; 68 const char *summary;
@@ -61,11 +70,12 @@ struct collection {
61}; 70};
62 71
63static struct collection collections[] = { 72static struct collection collections[] = {
64 { "sched", "Scheduler and IPC benchmarks", sched_benchmarks }, 73 { "sched", "Scheduler and IPC benchmarks", sched_benchmarks },
65 { "mem", "Memory access benchmarks", mem_benchmarks }, 74 { "mem", "Memory access benchmarks", mem_benchmarks },
66#ifdef HAVE_LIBNUMA_SUPPORT 75#ifdef HAVE_LIBNUMA_SUPPORT
67 { "numa", "NUMA scheduling and MM benchmarks", numa_benchmarks }, 76 { "numa", "NUMA scheduling and MM benchmarks", numa_benchmarks },
68#endif 77#endif
78 {"futex", "Futex stressing benchmarks", futex_benchmarks },
69 { "all", "All benchmarks", NULL }, 79 { "all", "All benchmarks", NULL },
70 { NULL, NULL, NULL } 80 { NULL, NULL, NULL }
71}; 81};
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index a77e31246c00..204fffe22532 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -952,8 +952,8 @@ static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp,
952 dfmt->header_width, buf); 952 dfmt->header_width, buf);
953} 953}
954 954
955static int hpp__header(struct perf_hpp_fmt *fmt, 955static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
956 struct perf_hpp *hpp) 956 struct perf_evsel *evsel __maybe_unused)
957{ 957{
958 struct diff_hpp_fmt *dfmt = 958 struct diff_hpp_fmt *dfmt =
959 container_of(fmt, struct diff_hpp_fmt, fmt); 959 container_of(fmt, struct diff_hpp_fmt, fmt);
@@ -963,7 +963,8 @@ static int hpp__header(struct perf_hpp_fmt *fmt,
963} 963}
964 964
965static int hpp__width(struct perf_hpp_fmt *fmt, 965static int hpp__width(struct perf_hpp_fmt *fmt,
966 struct perf_hpp *hpp __maybe_unused) 966 struct perf_hpp *hpp __maybe_unused,
967 struct perf_evsel *evsel __maybe_unused)
967{ 968{
968 struct diff_hpp_fmt *dfmt = 969 struct diff_hpp_fmt *dfmt =
969 container_of(fmt, struct diff_hpp_fmt, fmt); 970 container_of(fmt, struct diff_hpp_fmt, fmt);
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index b3466018bbd7..3a7387551369 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -312,7 +312,6 @@ found:
312 sample_sw.period = sample->period; 312 sample_sw.period = sample->period;
313 sample_sw.time = sample->time; 313 sample_sw.time = sample->time;
314 perf_event__synthesize_sample(event_sw, evsel->attr.sample_type, 314 perf_event__synthesize_sample(event_sw, evsel->attr.sample_type,
315 evsel->attr.sample_regs_user,
316 evsel->attr.read_format, &sample_sw, 315 evsel->attr.read_format, &sample_sw,
317 false); 316 false);
318 build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine); 317 build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine);
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index a7350519c63f..0f1e5a2f6ad7 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -404,6 +404,7 @@ static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
404 } 404 }
405 405
406 event->key = *key; 406 event->key = *key;
407 init_stats(&event->total.stats);
407 return event; 408 return event;
408} 409}
409 410
@@ -1691,17 +1692,15 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
1691 OPT_END() 1692 OPT_END()
1692 }; 1693 };
1693 1694
1694 1695 const char *const kvm_subcommands[] = { "top", "record", "report", "diff",
1695 const char * const kvm_usage[] = { 1696 "buildid-list", "stat", NULL };
1696 "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}", 1697 const char *kvm_usage[] = { NULL, NULL };
1697 NULL
1698 };
1699 1698
1700 perf_host = 0; 1699 perf_host = 0;
1701 perf_guest = 1; 1700 perf_guest = 1;
1702 1701
1703 argc = parse_options(argc, argv, kvm_options, kvm_usage, 1702 argc = parse_options_subcommand(argc, argv, kvm_options, kvm_subcommands, kvm_usage,
1704 PARSE_OPT_STOP_AT_NON_OPTION); 1703 PARSE_OPT_STOP_AT_NON_OPTION);
1705 if (!argc) 1704 if (!argc)
1706 usage_with_options(kvm_usage, kvm_options); 1705 usage_with_options(kvm_usage, kvm_options);
1707 1706
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 78948882e3de..cdcd4eb3a57d 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -268,9 +268,9 @@ static int opt_set_filter(const struct option *opt __maybe_unused,
268 return 0; 268 return 0;
269} 269}
270 270
271static void init_params(void) 271static int init_params(void)
272{ 272{
273 line_range__init(&params.line_range); 273 return line_range__init(&params.line_range);
274} 274}
275 275
276static void cleanup_params(void) 276static void cleanup_params(void)
@@ -515,9 +515,11 @@ int cmd_probe(int argc, const char **argv, const char *prefix)
515{ 515{
516 int ret; 516 int ret;
517 517
518 init_params(); 518 ret = init_params();
519 ret = __cmd_probe(argc, argv, prefix); 519 if (!ret) {
520 cleanup_params(); 520 ret = __cmd_probe(argc, argv, prefix);
521 cleanup_params();
522 }
521 523
522 return ret; 524 return ret;
523} 525}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index af47531b82ec..8ce62ef7f6c3 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -374,7 +374,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
374 374
375 session = perf_session__new(file, false, NULL); 375 session = perf_session__new(file, false, NULL);
376 if (session == NULL) { 376 if (session == NULL) {
377 pr_err("Not enough memory for reading perf file header\n"); 377 pr_err("Perf session creation failed.\n");
378 return -1; 378 return -1;
379 } 379 }
380 380
@@ -649,7 +649,7 @@ error:
649 return ret; 649 return ret;
650} 650}
651 651
652#ifdef HAVE_LIBUNWIND_SUPPORT 652#ifdef HAVE_DWARF_UNWIND_SUPPORT
653static int get_stack_size(char *str, unsigned long *_size) 653static int get_stack_size(char *str, unsigned long *_size)
654{ 654{
655 char *endptr; 655 char *endptr;
@@ -675,7 +675,7 @@ static int get_stack_size(char *str, unsigned long *_size)
675 max_size, str); 675 max_size, str);
676 return -1; 676 return -1;
677} 677}
678#endif /* HAVE_LIBUNWIND_SUPPORT */ 678#endif /* HAVE_DWARF_UNWIND_SUPPORT */
679 679
680int record_parse_callchain(const char *arg, struct record_opts *opts) 680int record_parse_callchain(const char *arg, struct record_opts *opts)
681{ 681{
@@ -704,7 +704,7 @@ int record_parse_callchain(const char *arg, struct record_opts *opts)
704 "needed for -g fp\n"); 704 "needed for -g fp\n");
705 break; 705 break;
706 706
707#ifdef HAVE_LIBUNWIND_SUPPORT 707#ifdef HAVE_DWARF_UNWIND_SUPPORT
708 /* Dwarf style */ 708 /* Dwarf style */
709 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 709 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
710 const unsigned long default_stack_dump_size = 8192; 710 const unsigned long default_stack_dump_size = 8192;
@@ -720,7 +720,7 @@ int record_parse_callchain(const char *arg, struct record_opts *opts)
720 ret = get_stack_size(tok, &size); 720 ret = get_stack_size(tok, &size);
721 opts->stack_dump_size = size; 721 opts->stack_dump_size = size;
722 } 722 }
723#endif /* HAVE_LIBUNWIND_SUPPORT */ 723#endif /* HAVE_DWARF_UNWIND_SUPPORT */
724 } else { 724 } else {
725 pr_err("callchain: Unknown --call-graph option " 725 pr_err("callchain: Unknown --call-graph option "
726 "value: %s\n", arg); 726 "value: %s\n", arg);
@@ -735,7 +735,9 @@ int record_parse_callchain(const char *arg, struct record_opts *opts)
735 735
736static void callchain_debug(struct record_opts *opts) 736static void callchain_debug(struct record_opts *opts)
737{ 737{
738 pr_debug("callchain: type %d\n", opts->call_graph); 738 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" };
739
740 pr_debug("callchain: type %s\n", str[opts->call_graph]);
739 741
740 if (opts->call_graph == CALLCHAIN_DWARF) 742 if (opts->call_graph == CALLCHAIN_DWARF)
741 pr_debug("callchain: stack dump size %d\n", 743 pr_debug("callchain: stack dump size %d\n",
@@ -749,6 +751,8 @@ int record_parse_callchain_opt(const struct option *opt,
749 struct record_opts *opts = opt->value; 751 struct record_opts *opts = opt->value;
750 int ret; 752 int ret;
751 753
754 opts->call_graph_enabled = !unset;
755
752 /* --no-call-graph */ 756 /* --no-call-graph */
753 if (unset) { 757 if (unset) {
754 opts->call_graph = CALLCHAIN_NONE; 758 opts->call_graph = CALLCHAIN_NONE;
@@ -769,6 +773,8 @@ int record_callchain_opt(const struct option *opt,
769{ 773{
770 struct record_opts *opts = opt->value; 774 struct record_opts *opts = opt->value;
771 775
776 opts->call_graph_enabled = !unset;
777
772 if (opts->call_graph == CALLCHAIN_NONE) 778 if (opts->call_graph == CALLCHAIN_NONE)
773 opts->call_graph = CALLCHAIN_FP; 779 opts->call_graph = CALLCHAIN_FP;
774 780
@@ -776,6 +782,16 @@ int record_callchain_opt(const struct option *opt,
776 return 0; 782 return 0;
777} 783}
778 784
785static int perf_record_config(const char *var, const char *value, void *cb)
786{
787 struct record *rec = cb;
788
789 if (!strcmp(var, "record.call-graph"))
790 return record_parse_callchain(value, &rec->opts);
791
792 return perf_default_config(var, value, cb);
793}
794
779static const char * const record_usage[] = { 795static const char * const record_usage[] = {
780 "perf record [<options>] [<command>]", 796 "perf record [<options>] [<command>]",
781 "perf record [<options>] -- <command> [<options>]", 797 "perf record [<options>] -- <command> [<options>]",
@@ -807,7 +823,7 @@ static struct record record = {
807 823
808#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 824#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
809 825
810#ifdef HAVE_LIBUNWIND_SUPPORT 826#ifdef HAVE_DWARF_UNWIND_SUPPORT
811const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf"; 827const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf";
812#else 828#else
813const char record_callchain_help[] = CALLCHAIN_HELP "fp"; 829const char record_callchain_help[] = CALLCHAIN_HELP "fp";
@@ -907,6 +923,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
907 if (rec->evlist == NULL) 923 if (rec->evlist == NULL)
908 return -ENOMEM; 924 return -ENOMEM;
909 925
926 perf_config(perf_record_config, rec);
927
910 argc = parse_options(argc, argv, record_options, record_usage, 928 argc = parse_options(argc, argv, record_options, record_usage,
911 PARSE_OPT_STOP_AT_NON_OPTION); 929 PARSE_OPT_STOP_AT_NON_OPTION);
912 if (!argc && target__none(&rec->opts.target)) 930 if (!argc && target__none(&rec->opts.target))
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 02f985f3a396..c8f21137dfd8 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -75,13 +75,10 @@ static int report__config(const char *var, const char *value, void *cb)
75 return perf_default_config(var, value, cb); 75 return perf_default_config(var, value, cb);
76} 76}
77 77
78static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_location *al, 78static int report__add_mem_hist_entry(struct report *rep, struct addr_location *al,
79 struct perf_sample *sample, struct perf_evsel *evsel, 79 struct perf_sample *sample, struct perf_evsel *evsel)
80 union perf_event *event)
81{ 80{
82 struct report *rep = container_of(tool, struct report, tool);
83 struct symbol *parent = NULL; 81 struct symbol *parent = NULL;
84 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
85 struct hist_entry *he; 82 struct hist_entry *he;
86 struct mem_info *mi, *mx; 83 struct mem_info *mi, *mx;
87 uint64_t cost; 84 uint64_t cost;
@@ -90,7 +87,7 @@ static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_locati
90 if (err) 87 if (err)
91 return err; 88 return err;
92 89
93 mi = machine__resolve_mem(al->machine, al->thread, sample, cpumode); 90 mi = sample__resolve_mem(sample, al);
94 if (!mi) 91 if (!mi)
95 return -ENOMEM; 92 return -ENOMEM;
96 93
@@ -131,10 +128,9 @@ out:
131 return err; 128 return err;
132} 129}
133 130
134static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_location *al, 131static int report__add_branch_hist_entry(struct report *rep, struct addr_location *al,
135 struct perf_sample *sample, struct perf_evsel *evsel) 132 struct perf_sample *sample, struct perf_evsel *evsel)
136{ 133{
137 struct report *rep = container_of(tool, struct report, tool);
138 struct symbol *parent = NULL; 134 struct symbol *parent = NULL;
139 unsigned i; 135 unsigned i;
140 struct hist_entry *he; 136 struct hist_entry *he;
@@ -144,8 +140,7 @@ static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_loc
144 if (err) 140 if (err)
145 return err; 141 return err;
146 142
147 bi = machine__resolve_bstack(al->machine, al->thread, 143 bi = sample__resolve_bstack(sample, al);
148 sample->branch_stack);
149 if (!bi) 144 if (!bi)
150 return -ENOMEM; 145 return -ENOMEM;
151 146
@@ -190,10 +185,9 @@ out:
190 return err; 185 return err;
191} 186}
192 187
193static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evsel, 188static int report__add_hist_entry(struct report *rep, struct perf_evsel *evsel,
194 struct addr_location *al, struct perf_sample *sample) 189 struct addr_location *al, struct perf_sample *sample)
195{ 190{
196 struct report *rep = container_of(tool, struct report, tool);
197 struct symbol *parent = NULL; 191 struct symbol *parent = NULL;
198 struct hist_entry *he; 192 struct hist_entry *he;
199 int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack); 193 int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
@@ -237,25 +231,25 @@ static int process_sample_event(struct perf_tool *tool,
237 return -1; 231 return -1;
238 } 232 }
239 233
240 if (al.filtered || (rep->hide_unresolved && al.sym == NULL)) 234 if (rep->hide_unresolved && al.sym == NULL)
241 return 0; 235 return 0;
242 236
243 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap)) 237 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
244 return 0; 238 return 0;
245 239
246 if (sort__mode == SORT_MODE__BRANCH) { 240 if (sort__mode == SORT_MODE__BRANCH) {
247 ret = report__add_branch_hist_entry(tool, &al, sample, evsel); 241 ret = report__add_branch_hist_entry(rep, &al, sample, evsel);
248 if (ret < 0) 242 if (ret < 0)
249 pr_debug("problem adding lbr entry, skipping event\n"); 243 pr_debug("problem adding lbr entry, skipping event\n");
250 } else if (rep->mem_mode == 1) { 244 } else if (rep->mem_mode == 1) {
251 ret = report__add_mem_hist_entry(tool, &al, sample, evsel, event); 245 ret = report__add_mem_hist_entry(rep, &al, sample, evsel);
252 if (ret < 0) 246 if (ret < 0)
253 pr_debug("problem adding mem entry, skipping event\n"); 247 pr_debug("problem adding mem entry, skipping event\n");
254 } else { 248 } else {
255 if (al.map != NULL) 249 if (al.map != NULL)
256 al.map->dso->hit = 1; 250 al.map->dso->hit = 1;
257 251
258 ret = report__add_hist_entry(tool, evsel, &al, sample); 252 ret = report__add_hist_entry(rep, evsel, &al, sample);
259 if (ret < 0) 253 if (ret < 0)
260 pr_debug("problem incrementing symbol period, skipping event\n"); 254 pr_debug("problem incrementing symbol period, skipping event\n");
261 } 255 }
@@ -934,7 +928,7 @@ repeat:
934 * so don't allocate extra space that won't be used in the stdio 928 * so don't allocate extra space that won't be used in the stdio
935 * implementation. 929 * implementation.
936 */ 930 */
937 if (use_browser == 1 && sort__has_sym) { 931 if (ui__has_annotation()) {
938 symbol_conf.priv_size = sizeof(struct annotation); 932 symbol_conf.priv_size = sizeof(struct annotation);
939 machines__set_symbol_filter(&session->machines, 933 machines__set_symbol_filter(&session->machines,
940 symbol__annotate_init); 934 symbol__annotate_init);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 6a76a07b6789..9ac0a495c954 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1124,7 +1124,7 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
1124 1124
1125 avg = work_list->total_lat / work_list->nb_atoms; 1125 avg = work_list->total_lat / work_list->nb_atoms;
1126 1126
1127 printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %9.6f s\n", 1127 printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %13.6f s\n",
1128 (double)work_list->total_runtime / 1e6, 1128 (double)work_list->total_runtime / 1e6,
1129 work_list->nb_atoms, (double)avg / 1e6, 1129 work_list->nb_atoms, (double)avg / 1e6,
1130 (double)work_list->max_lat / 1e6, 1130 (double)work_list->max_lat / 1e6,
@@ -1527,9 +1527,9 @@ static int perf_sched__lat(struct perf_sched *sched)
1527 1527
1528 perf_sched__sort_lat(sched); 1528 perf_sched__sort_lat(sched);
1529 1529
1530 printf("\n ---------------------------------------------------------------------------------------------------------------\n"); 1530 printf("\n -----------------------------------------------------------------------------------------------------------------\n");
1531 printf(" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms | Maximum delay at |\n"); 1531 printf(" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms | Maximum delay at |\n");
1532 printf(" ---------------------------------------------------------------------------------------------------------------\n"); 1532 printf(" -----------------------------------------------------------------------------------------------------------------\n");
1533 1533
1534 next = rb_first(&sched->sorted_atom_root); 1534 next = rb_first(&sched->sorted_atom_root);
1535 1535
@@ -1541,7 +1541,7 @@ static int perf_sched__lat(struct perf_sched *sched)
1541 next = rb_next(next); 1541 next = rb_next(next);
1542 } 1542 }
1543 1543
1544 printf(" -----------------------------------------------------------------------------------------\n"); 1544 printf(" -----------------------------------------------------------------------------------------------------------------\n");
1545 printf(" TOTAL: |%11.3f ms |%9" PRIu64 " |\n", 1545 printf(" TOTAL: |%11.3f ms |%9" PRIu64 " |\n",
1546 (double)sched->all_runtime / 1e6, sched->all_count); 1546 (double)sched->all_runtime / 1e6, sched->all_count);
1547 1547
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8b0e1c9234d9..65a151e36067 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -174,13 +174,20 @@ static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
174 174
175static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) 175static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
176{ 176{
177 memset(evsel->priv, 0, sizeof(struct perf_stat)); 177 int i;
178 struct perf_stat *ps = evsel->priv;
179
180 for (i = 0; i < 3; i++)
181 init_stats(&ps->res_stats[i]);
178} 182}
179 183
180static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) 184static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
181{ 185{
182 evsel->priv = zalloc(sizeof(struct perf_stat)); 186 evsel->priv = zalloc(sizeof(struct perf_stat));
183 return evsel->priv == NULL ? -ENOMEM : 0; 187 if (evsel == NULL)
188 return -ENOMEM;
189 perf_evsel__reset_stat_priv(evsel);
190 return 0;
184} 191}
185 192
186static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) 193static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 25526d6eae59..74db2568b867 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -494,7 +494,7 @@ static const char *cat_backtrace(union perf_event *event,
494 continue; 494 continue;
495 } 495 }
496 496
497 tal.filtered = false; 497 tal.filtered = 0;
498 thread__find_addr_location(al.thread, machine, cpumode, 498 thread__find_addr_location(al.thread, machine, cpumode,
499 MAP__FUNCTION, ip, &tal); 499 MAP__FUNCTION, ip, &tal);
500 500
@@ -1238,7 +1238,7 @@ static int timechart__record(struct timechart *tchart, int argc, const char **ar
1238 for (i = 0; i < old_power_args_nr; i++) 1238 for (i = 0; i < old_power_args_nr; i++)
1239 *p++ = strdup(old_power_args[i]); 1239 *p++ = strdup(old_power_args[i]);
1240 1240
1241 for (j = 1; j < (unsigned int)argc; j++) 1241 for (j = 0; j < (unsigned int)argc; j++)
1242 *p++ = argv[j]; 1242 *p++ = argv[j];
1243 1243
1244 return cmd_record(rec_argc, rec_argv, NULL); 1244 return cmd_record(rec_argc, rec_argv, NULL);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5f989a7d8bc2..65aaa5bbf7ec 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -993,6 +993,16 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
993 return record_parse_callchain_opt(opt, arg, unset); 993 return record_parse_callchain_opt(opt, arg, unset);
994} 994}
995 995
996static int perf_top_config(const char *var, const char *value, void *cb)
997{
998 struct perf_top *top = cb;
999
1000 if (!strcmp(var, "top.call-graph"))
1001 return record_parse_callchain(value, &top->record_opts);
1002
1003 return perf_default_config(var, value, cb);
1004}
1005
996static int 1006static int
997parse_percent_limit(const struct option *opt, const char *arg, 1007parse_percent_limit(const struct option *opt, const char *arg,
998 int unset __maybe_unused) 1008 int unset __maybe_unused)
@@ -1117,6 +1127,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1117 if (top.evlist == NULL) 1127 if (top.evlist == NULL)
1118 return -ENOMEM; 1128 return -ENOMEM;
1119 1129
1130 perf_config(perf_top_config, &top);
1131
1120 argc = parse_options(argc, argv, options, top_usage, 0); 1132 argc = parse_options(argc, argv, options, top_usage, 0);
1121 if (argc) 1133 if (argc)
1122 usage_with_options(top_usage, options); 1134 usage_with_options(top_usage, options);
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 0331ea2701a3..802cf544202b 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -34,6 +34,14 @@ ifeq ($(ARCH),arm)
34 LIBUNWIND_LIBS = -lunwind -lunwind-arm 34 LIBUNWIND_LIBS = -lunwind -lunwind-arm
35endif 35endif
36 36
37# So far there's only x86 libdw unwind support merged in perf.
38# Disable it on all other architectures in case libdw unwind
39# support is detected in system. Add supported architectures
40# to the check.
41ifneq ($(ARCH),x86)
42 NO_LIBDW_DWARF_UNWIND := 1
43endif
44
37ifeq ($(LIBUNWIND_LIBS),) 45ifeq ($(LIBUNWIND_LIBS),)
38 NO_LIBUNWIND := 1 46 NO_LIBUNWIND := 1
39else 47else
@@ -59,6 +67,17 @@ ifeq ($(NO_PERF_REGS),0)
59 CFLAGS += -DHAVE_PERF_REGS_SUPPORT 67 CFLAGS += -DHAVE_PERF_REGS_SUPPORT
60endif 68endif
61 69
70ifndef NO_LIBELF
71 # for linking with debug library, run like:
72 # make DEBUG=1 LIBDW_DIR=/opt/libdw/
73 ifdef LIBDW_DIR
74 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
75 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
76 endif
77 FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
78 FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
79endif
80
62# include ARCH specific config 81# include ARCH specific config
63-include $(src-perf)/arch/$(ARCH)/Makefile 82-include $(src-perf)/arch/$(ARCH)/Makefile
64 83
@@ -98,6 +117,10 @@ CFLAGS += -Wall
98CFLAGS += -Wextra 117CFLAGS += -Wextra
99CFLAGS += -std=gnu99 118CFLAGS += -std=gnu99
100 119
120# Enforce a non-executable stack, as we may regress (again) in the future by
121# adding assembler files missing the .GNU-stack linker note.
122LDFLAGS += -Wl,-z,noexecstack
123
101EXTLIBS = -lelf -lpthread -lrt -lm -ldl 124EXTLIBS = -lelf -lpthread -lrt -lm -ldl
102 125
103ifneq ($(OUTPUT),) 126ifneq ($(OUTPUT),)
@@ -147,7 +170,38 @@ CORE_FEATURE_TESTS = \
147 libunwind \ 170 libunwind \
148 on-exit \ 171 on-exit \
149 stackprotector-all \ 172 stackprotector-all \
150 timerfd 173 timerfd \
174 libdw-dwarf-unwind
175
176LIB_FEATURE_TESTS = \
177 dwarf \
178 glibc \
179 gtk2 \
180 libaudit \
181 libbfd \
182 libelf \
183 libnuma \
184 libperl \
185 libpython \
186 libslang \
187 libunwind \
188 libdw-dwarf-unwind
189
190VF_FEATURE_TESTS = \
191 backtrace \
192 fortify-source \
193 gtk2-infobar \
194 libelf-getphdrnum \
195 libelf-mmap \
196 libpython-version \
197 on-exit \
198 stackprotector-all \
199 timerfd \
200 libunwind-debug-frame \
201 bionic \
202 liberty \
203 liberty-z \
204 cplus-demangle
151 205
152# Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features. 206# Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features.
153# If in the future we need per-feature checks/flags for features not 207# If in the future we need per-feature checks/flags for features not
@@ -161,17 +215,6 @@ endef
161$(foreach feat,$(CORE_FEATURE_TESTS),$(call set_test_all_flags,$(feat))) 215$(foreach feat,$(CORE_FEATURE_TESTS),$(call set_test_all_flags,$(feat)))
162 216
163# 217#
164# So here we detect whether test-all was rebuilt, to be able
165# to skip the print-out of the long features list if the file
166# existed before and after it was built:
167#
168ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all.bin),)
169 test-all-failed := 1
170else
171 test-all-failed := 0
172endif
173
174#
175# Special fast-path for the 'all features are available' case: 218# Special fast-path for the 'all features are available' case:
176# 219#
177$(call feature_check,all,$(MSG)) 220$(call feature_check,all,$(MSG))
@@ -180,15 +223,6 @@ $(call feature_check,all,$(MSG))
180# Just in case the build freshly failed, make sure we print the 223# Just in case the build freshly failed, make sure we print the
181# feature matrix: 224# feature matrix:
182# 225#
183ifeq ($(feature-all), 0)
184 test-all-failed := 1
185endif
186
187ifeq ($(test-all-failed),1)
188 $(info )
189 $(info Auto-detecting system features:)
190endif
191
192ifeq ($(feature-all), 1) 226ifeq ($(feature-all), 1)
193 # 227 #
194 # test-all.c passed - just set all the core feature flags to 1: 228 # test-all.c passed - just set all the core feature flags to 1:
@@ -199,27 +233,6 @@ else
199 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat))) 233 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
200endif 234endif
201 235
202#
203# Print the result of the feature test:
204#
205feature_print = $(eval $(feature_print_code)) $(info $(MSG))
206
207define feature_print_code
208 ifeq ($(feature-$(1)), 1)
209 MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1))
210 else
211 MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
212 endif
213endef
214
215#
216# Only print out our features if we rebuilt the testcases or if a test failed:
217#
218ifeq ($(test-all-failed), 1)
219 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_print,$(feat)))
220 $(info )
221endif
222
223ifeq ($(feature-stackprotector-all), 1) 236ifeq ($(feature-stackprotector-all), 1)
224 CFLAGS += -fstack-protector-all 237 CFLAGS += -fstack-protector-all
225endif 238endif
@@ -264,6 +277,7 @@ ifdef NO_LIBELF
264 NO_DWARF := 1 277 NO_DWARF := 1
265 NO_DEMANGLE := 1 278 NO_DEMANGLE := 1
266 NO_LIBUNWIND := 1 279 NO_LIBUNWIND := 1
280 NO_LIBDW_DWARF_UNWIND := 1
267else 281else
268 ifeq ($(feature-libelf), 0) 282 ifeq ($(feature-libelf), 0)
269 ifeq ($(feature-glibc), 1) 283 ifeq ($(feature-glibc), 1)
@@ -278,17 +292,18 @@ else
278 NO_LIBELF := 1 292 NO_LIBELF := 1
279 NO_DWARF := 1 293 NO_DWARF := 1
280 NO_DEMANGLE := 1 294 NO_DEMANGLE := 1
295 NO_LIBUNWIND := 1
296 NO_LIBDW_DWARF_UNWIND := 1
281 else 297 else
282 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); 298 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
283 endif 299 endif
284 else 300 else
285 # for linking with debug library, run like: 301 ifndef NO_LIBDW_DWARF_UNWIND
286 # make DEBUG=1 LIBDW_DIR=/opt/libdw/ 302 ifneq ($(feature-libdw-dwarf-unwind),1)
287 ifdef LIBDW_DIR 303 NO_LIBDW_DWARF_UNWIND := 1
288 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include 304 msg := $(warning No libdw DWARF unwind found, Please install elfutils-devel/libdw-dev >= 0.158 and/or set LIBDW_DIR);
289 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib 305 endif
290 endif 306 endif
291
292 ifneq ($(feature-dwarf), 1) 307 ifneq ($(feature-dwarf), 1)
293 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); 308 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
294 NO_DWARF := 1 309 NO_DWARF := 1
@@ -324,25 +339,51 @@ endif # NO_LIBELF
324 339
325ifndef NO_LIBUNWIND 340ifndef NO_LIBUNWIND
326 ifneq ($(feature-libunwind), 1) 341 ifneq ($(feature-libunwind), 1)
327 msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1); 342 msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR);
328 NO_LIBUNWIND := 1 343 NO_LIBUNWIND := 1
344 endif
345endif
346
347dwarf-post-unwind := 1
348dwarf-post-unwind-text := BUG
349
350# setup DWARF post unwinder
351ifdef NO_LIBUNWIND
352 ifdef NO_LIBDW_DWARF_UNWIND
353 msg := $(warning Disabling post unwind, no support found.);
354 dwarf-post-unwind := 0
329 else 355 else
330 ifeq ($(ARCH),arm) 356 dwarf-post-unwind-text := libdw
331 $(call feature_check,libunwind-debug-frame) 357 endif
332 ifneq ($(feature-libunwind-debug-frame), 1) 358else
333 msg := $(warning No debug_frame support found in libunwind); 359 dwarf-post-unwind-text := libunwind
334 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME 360 # Enable libunwind support by default.
335 endif 361 ifndef NO_LIBDW_DWARF_UNWIND
336 else 362 NO_LIBDW_DWARF_UNWIND := 1
337 # non-ARM has no dwarf_find_debug_frame() function: 363 endif
364endif
365
366ifeq ($(dwarf-post-unwind),1)
367 CFLAGS += -DHAVE_DWARF_UNWIND_SUPPORT
368else
369 NO_DWARF_UNWIND := 1
370endif
371
372ifndef NO_LIBUNWIND
373 ifeq ($(ARCH),arm)
374 $(call feature_check,libunwind-debug-frame)
375 ifneq ($(feature-libunwind-debug-frame), 1)
376 msg := $(warning No debug_frame support found in libunwind);
338 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME 377 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
339 endif 378 endif
340 379 else
341 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT 380 # non-ARM has no dwarf_find_debug_frame() function:
342 EXTLIBS += $(LIBUNWIND_LIBS) 381 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
343 CFLAGS += $(LIBUNWIND_CFLAGS) 382 endif
344 LDFLAGS += $(LIBUNWIND_LDFLAGS) 383 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
345 endif # ifneq ($(feature-libunwind), 1) 384 EXTLIBS += $(LIBUNWIND_LIBS)
385 CFLAGS += $(LIBUNWIND_CFLAGS)
386 LDFLAGS += $(LIBUNWIND_LDFLAGS)
346endif 387endif
347 388
348ifndef NO_LIBAUDIT 389ifndef NO_LIBAUDIT
@@ -478,7 +519,21 @@ else
478endif 519endif
479 520
480ifeq ($(feature-libbfd), 1) 521ifeq ($(feature-libbfd), 1)
481 EXTLIBS += -lbfd -lz -liberty 522 EXTLIBS += -lbfd
523
524 # call all detections now so we get correct
525 # status in VF output
526 $(call feature_check,liberty)
527 $(call feature_check,liberty-z)
528 $(call feature_check,cplus-demangle)
529
530 ifeq ($(feature-liberty), 1)
531 EXTLIBS += -liberty
532 else
533 ifeq ($(feature-liberty-z), 1)
534 EXTLIBS += -liberty -lz
535 endif
536 endif
482endif 537endif
483 538
484ifdef NO_DEMANGLE 539ifdef NO_DEMANGLE
@@ -489,15 +544,10 @@ else
489 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT 544 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
490 else 545 else
491 ifneq ($(feature-libbfd), 1) 546 ifneq ($(feature-libbfd), 1)
492 $(call feature_check,liberty) 547 ifneq ($(feature-liberty), 1)
493 ifeq ($(feature-liberty), 1) 548 ifneq ($(feature-liberty-z), 1)
494 EXTLIBS += -lbfd -liberty 549 # we dont have neither HAVE_CPLUS_DEMANGLE_SUPPORT
495 else 550 # or any of 'bfd iberty z' trinity
496 $(call feature_check,liberty-z)
497 ifeq ($(feature-liberty-z), 1)
498 EXTLIBS += -lbfd -liberty -lz
499 else
500 $(call feature_check,cplus-demangle)
501 ifeq ($(feature-cplus-demangle), 1) 551 ifeq ($(feature-cplus-demangle), 1)
502 EXTLIBS += -liberty 552 EXTLIBS += -liberty
503 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT 553 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
@@ -602,3 +652,84 @@ ifdef DESTDIR
602plugindir=$(libdir)/traceevent/plugins 652plugindir=$(libdir)/traceevent/plugins
603plugindir_SQ= $(subst ','\'',$(plugindir)) 653plugindir_SQ= $(subst ','\'',$(plugindir))
604endif 654endif
655
656#
657# Print the result of the feature test:
658#
659feature_print_status = $(eval $(feature_print_status_code)) $(info $(MSG))
660
661define feature_print_status_code
662 ifeq ($(feature-$(1)), 1)
663 MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1))
664 else
665 MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
666 endif
667endef
668
669feature_print_var = $(eval $(feature_print_var_code)) $(info $(MSG))
670define feature_print_var_code
671 MSG = $(shell printf '...%30s: %s' $(1) $($(1)))
672endef
673
674feature_print_text = $(eval $(feature_print_text_code)) $(info $(MSG))
675define feature_print_text_code
676 MSG = $(shell printf '...%30s: %s' $(1) $(2))
677endef
678
679PERF_FEATURES := $(foreach feat,$(LIB_FEATURE_TESTS),feature-$(feat)($(feature-$(feat))))
680PERF_FEATURES_FILE := $(shell touch $(OUTPUT)PERF-FEATURES; cat $(OUTPUT)PERF-FEATURES)
681
682ifeq ($(dwarf-post-unwind),1)
683 PERF_FEATURES += dwarf-post-unwind($(dwarf-post-unwind-text))
684endif
685
686# The $(display_lib) controls the default detection message
687# output. It's set if:
688# - detected features differes from stored features from
689# last build (in PERF-FEATURES file)
690# - one of the $(LIB_FEATURE_TESTS) is not detected
691# - VF is enabled
692
693ifneq ("$(PERF_FEATURES)","$(PERF_FEATURES_FILE)")
694 $(shell echo "$(PERF_FEATURES)" > $(OUTPUT)PERF-FEATURES)
695 display_lib := 1
696endif
697
698feature_check = $(eval $(feature_check_code))
699define feature_check_code
700 ifneq ($(feature-$(1)), 1)
701 display_lib := 1
702 endif
703endef
704
705$(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_check,$(feat)))
706
707ifeq ($(VF),1)
708 display_lib := 1
709 display_vf := 1
710endif
711
712ifeq ($(display_lib),1)
713 $(info )
714 $(info Auto-detecting system features:)
715 $(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_print_status,$(feat),))
716
717 ifeq ($(dwarf-post-unwind),1)
718 $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
719 endif
720endif
721
722ifeq ($(display_vf),1)
723 $(foreach feat,$(VF_FEATURE_TESTS),$(call feature_print_status,$(feat),))
724 $(info )
725 $(call feature_print_var,prefix)
726 $(call feature_print_var,bindir)
727 $(call feature_print_var,libdir)
728 $(call feature_print_var,sysconfdir)
729 $(call feature_print_var,LIBUNWIND_DIR)
730 $(call feature_print_var,LIBDW_DIR)
731endif
732
733ifeq ($(display_lib),1)
734 $(info )
735endif
diff --git a/tools/perf/config/Makefile.arch b/tools/perf/config/Makefile.arch
index fef8ae922800..4b06719ee984 100644
--- a/tools/perf/config/Makefile.arch
+++ b/tools/perf/config/Makefile.arch
@@ -5,7 +5,8 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
5 -e s/arm.*/arm/ -e s/sa110/arm/ \ 5 -e s/arm.*/arm/ -e s/sa110/arm/ \
6 -e s/s390x/s390/ -e s/parisc64/parisc/ \ 6 -e s/s390x/s390/ -e s/parisc64/parisc/ \
7 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ 7 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
8 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ ) 8 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
9 -e s/tile.*/tile/ )
9 10
10# Additional ARCH settings for x86 11# Additional ARCH settings for x86
11ifeq ($(ARCH),i386) 12ifeq ($(ARCH),i386)
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 523b7bc10553..2da103c53f89 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -26,7 +26,8 @@ FILES= \
26 test-libunwind-debug-frame.bin \ 26 test-libunwind-debug-frame.bin \
27 test-on-exit.bin \ 27 test-on-exit.bin \
28 test-stackprotector-all.bin \ 28 test-stackprotector-all.bin \
29 test-timerfd.bin 29 test-timerfd.bin \
30 test-libdw-dwarf-unwind.bin
30 31
31CC := $(CROSS_COMPILE)gcc -MD 32CC := $(CROSS_COMPILE)gcc -MD
32PKG_CONFIG := $(CROSS_COMPILE)pkg-config 33PKG_CONFIG := $(CROSS_COMPILE)pkg-config
@@ -141,6 +142,9 @@ test-backtrace.bin:
141test-timerfd.bin: 142test-timerfd.bin:
142 $(BUILD) 143 $(BUILD)
143 144
145test-libdw-dwarf-unwind.bin:
146 $(BUILD)
147
144-include *.d 148-include *.d
145 149
146############################### 150###############################
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
index 9b8a544155bb..fc37eb3ca17b 100644
--- a/tools/perf/config/feature-checks/test-all.c
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -89,6 +89,10 @@
89# include "test-stackprotector-all.c" 89# include "test-stackprotector-all.c"
90#undef main 90#undef main
91 91
92#define main main_test_libdw_dwarf_unwind
93# include "test-libdw-dwarf-unwind.c"
94#undef main
95
92int main(int argc, char *argv[]) 96int main(int argc, char *argv[])
93{ 97{
94 main_test_libpython(); 98 main_test_libpython();
@@ -111,6 +115,7 @@ int main(int argc, char *argv[])
111 main_test_libnuma(); 115 main_test_libnuma();
112 main_test_timerfd(); 116 main_test_timerfd();
113 main_test_stackprotector_all(); 117 main_test_stackprotector_all();
118 main_test_libdw_dwarf_unwind();
114 119
115 return 0; 120 return 0;
116} 121}
diff --git a/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c b/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c
new file mode 100644
index 000000000000..f676a3ff442a
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c
@@ -0,0 +1,13 @@
1
2#include <elfutils/libdwfl.h>
3
4int main(void)
5{
6 /*
7 * This function is guarded via: __nonnull_attribute__ (1, 2).
8 * Passing '1' as arguments value. This code is never executed,
9 * only compiled.
10 */
11 dwfl_thread_getframes((void *) 1, (void *) 1, NULL);
12 return 0;
13}
diff --git a/tools/perf/design.txt b/tools/perf/design.txt
index 63a0e6f04a01..a28dca2582aa 100644
--- a/tools/perf/design.txt
+++ b/tools/perf/design.txt
@@ -18,7 +18,7 @@ underlying hardware counters.
18Performance counters are accessed via special file descriptors. 18Performance counters are accessed via special file descriptors.
19There's one file descriptor per virtual counter used. 19There's one file descriptor per virtual counter used.
20 20
21The special file descriptor is opened via the perf_event_open() 21The special file descriptor is opened via the sys_perf_event_open()
22system call: 22system call:
23 23
24 int sys_perf_event_open(struct perf_event_attr *hw_event_uptr, 24 int sys_perf_event_open(struct perf_event_attr *hw_event_uptr,
@@ -82,7 +82,7 @@ machine-specific.
82If 'raw_type' is 0, then the 'type' field says what kind of counter 82If 'raw_type' is 0, then the 'type' field says what kind of counter
83this is, with the following encoding: 83this is, with the following encoding:
84 84
85enum perf_event_types { 85enum perf_type_id {
86 PERF_TYPE_HARDWARE = 0, 86 PERF_TYPE_HARDWARE = 0,
87 PERF_TYPE_SOFTWARE = 1, 87 PERF_TYPE_SOFTWARE = 1,
88 PERF_TYPE_TRACEPOINT = 2, 88 PERF_TYPE_TRACEPOINT = 2,
@@ -95,7 +95,7 @@ specified by 'event_id':
95 * Generalized performance counter event types, used by the hw_event.event_id 95 * Generalized performance counter event types, used by the hw_event.event_id
96 * parameter of the sys_perf_event_open() syscall: 96 * parameter of the sys_perf_event_open() syscall:
97 */ 97 */
98enum hw_event_ids { 98enum perf_hw_id {
99 /* 99 /*
100 * Common hardware events, generalized by the kernel: 100 * Common hardware events, generalized by the kernel:
101 */ 101 */
@@ -129,7 +129,7 @@ software events, selected by 'event_id':
129 * physical and sw events of the kernel (and allow the profiling of them as 129 * physical and sw events of the kernel (and allow the profiling of them as
130 * well): 130 * well):
131 */ 131 */
132enum sw_event_ids { 132enum perf_sw_ids {
133 PERF_COUNT_SW_CPU_CLOCK = 0, 133 PERF_COUNT_SW_CPU_CLOCK = 0,
134 PERF_COUNT_SW_TASK_CLOCK = 1, 134 PERF_COUNT_SW_TASK_CLOCK = 1,
135 PERF_COUNT_SW_PAGE_FAULTS = 2, 135 PERF_COUNT_SW_PAGE_FAULTS = 2,
@@ -230,7 +230,7 @@ these events are recorded in the ring-buffer (see below).
230The 'comm' bit allows tracking of process comm data on process creation. 230The 'comm' bit allows tracking of process comm data on process creation.
231This too is recorded in the ring-buffer (see below). 231This too is recorded in the ring-buffer (see below).
232 232
233The 'pid' parameter to the perf_event_open() system call allows the 233The 'pid' parameter to the sys_perf_event_open() system call allows the
234counter to be specific to a task: 234counter to be specific to a task:
235 235
236 pid == 0: if the pid parameter is zero, the counter is attached to the 236 pid == 0: if the pid parameter is zero, the counter is attached to the
@@ -260,7 +260,7 @@ The 'flags' parameter is currently unused and must be zero.
260 260
261The 'group_fd' parameter allows counter "groups" to be set up. A 261The 'group_fd' parameter allows counter "groups" to be set up. A
262counter group has one counter which is the group "leader". The leader 262counter group has one counter which is the group "leader". The leader
263is created first, with group_fd = -1 in the perf_event_open call 263is created first, with group_fd = -1 in the sys_perf_event_open call
264that creates it. The rest of the group members are created 264that creates it. The rest of the group members are created
265subsequently, with group_fd giving the fd of the group leader. 265subsequently, with group_fd giving the fd of the group leader.
266(A single counter on its own is created with group_fd = -1 and is 266(A single counter on its own is created with group_fd = -1 and is
diff --git a/tools/perf/perf-completion.sh b/tools/perf/perf-completion.sh
index 496e2abb5482..ae3a57694b6b 100644
--- a/tools/perf/perf-completion.sh
+++ b/tools/perf/perf-completion.sh
@@ -123,7 +123,7 @@ __perf_main ()
123 __perfcomp_colon "$evts" "$cur" 123 __perfcomp_colon "$evts" "$cur"
124 # List subcommands for 'perf kvm' 124 # List subcommands for 'perf kvm'
125 elif [[ $prev == "kvm" ]]; then 125 elif [[ $prev == "kvm" ]]; then
126 subcmds="top record report diff buildid-list stat" 126 subcmds=$($cmd $prev --list-cmds)
127 __perfcomp_colon "$subcmds" "$cur" 127 __perfcomp_colon "$subcmds" "$cur"
128 # List long option names 128 # List long option names
129 elif [[ $cur == --* ]]; then 129 elif [[ $cur == --* ]]; then
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index e84fa26bc1be..5c11ecad02a9 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -12,6 +12,9 @@
12#ifndef __NR_perf_event_open 12#ifndef __NR_perf_event_open
13# define __NR_perf_event_open 336 13# define __NR_perf_event_open 336
14#endif 14#endif
15#ifndef __NR_futex
16# define __NR_futex 240
17#endif
15#endif 18#endif
16 19
17#if defined(__x86_64__) 20#if defined(__x86_64__)
@@ -23,6 +26,9 @@
23#ifndef __NR_perf_event_open 26#ifndef __NR_perf_event_open
24# define __NR_perf_event_open 298 27# define __NR_perf_event_open 298
25#endif 28#endif
29#ifndef __NR_futex
30# define __NR_futex 202
31#endif
26#endif 32#endif
27 33
28#ifdef __powerpc__ 34#ifdef __powerpc__
@@ -139,6 +145,14 @@
139#define CPUINFO_PROC "core ID" 145#define CPUINFO_PROC "core ID"
140#endif 146#endif
141 147
148#ifdef __tile__
149#define mb() asm volatile ("mf" ::: "memory")
150#define wmb() asm volatile ("mf" ::: "memory")
151#define rmb() asm volatile ("mf" ::: "memory")
152#define cpu_relax() asm volatile ("mfspr zero, PASS" ::: "memory")
153#define CPUINFO_PROC "model name"
154#endif
155
142#define barrier() asm volatile ("" ::: "memory") 156#define barrier() asm volatile ("" ::: "memory")
143 157
144#ifndef cpu_relax 158#ifndef cpu_relax
@@ -251,12 +265,14 @@ void pthread__unblock_sigwinch(void);
251enum perf_call_graph_mode { 265enum perf_call_graph_mode {
252 CALLCHAIN_NONE, 266 CALLCHAIN_NONE,
253 CALLCHAIN_FP, 267 CALLCHAIN_FP,
254 CALLCHAIN_DWARF 268 CALLCHAIN_DWARF,
269 CALLCHAIN_MAX
255}; 270};
256 271
257struct record_opts { 272struct record_opts {
258 struct target target; 273 struct target target;
259 int call_graph; 274 int call_graph;
275 bool call_graph_enabled;
260 bool group; 276 bool group;
261 bool inherit_stat; 277 bool inherit_stat;
262 bool no_buffering; 278 bool no_buffering;
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 1e67437fb4ca..b11bf8a08430 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -115,6 +115,14 @@ static struct test {
115 .desc = "Test parsing with no sample_id_all bit set", 115 .desc = "Test parsing with no sample_id_all bit set",
116 .func = test__parse_no_sample_id_all, 116 .func = test__parse_no_sample_id_all,
117 }, 117 },
118#if defined(__x86_64__) || defined(__i386__)
119#ifdef HAVE_DWARF_UNWIND_SUPPORT
120 {
121 .desc = "Test dwarf unwind",
122 .func = test__dwarf_unwind,
123 },
124#endif
125#endif
118 { 126 {
119 .func = NULL, 127 .func = NULL,
120 }, 128 },
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 653a8fe2db95..bfb186900ac0 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -504,6 +504,7 @@ static int do_test_code_reading(bool try_kcore)
504 if (ret < 0) { 504 if (ret < 0) {
505 if (!excl_kernel) { 505 if (!excl_kernel) {
506 excl_kernel = true; 506 excl_kernel = true;
507 perf_evlist__set_maps(evlist, NULL, NULL);
507 perf_evlist__delete(evlist); 508 perf_evlist__delete(evlist);
508 evlist = NULL; 509 evlist = NULL;
509 continue; 510 continue;
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
new file mode 100644
index 000000000000..c059ee81c038
--- /dev/null
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -0,0 +1,144 @@
1#include <linux/compiler.h>
2#include <sys/types.h>
3#include <unistd.h>
4#include "tests.h"
5#include "debug.h"
6#include "machine.h"
7#include "event.h"
8#include "unwind.h"
9#include "perf_regs.h"
10#include "map.h"
11#include "thread.h"
12
13static int mmap_handler(struct perf_tool *tool __maybe_unused,
14 union perf_event *event,
15 struct perf_sample *sample __maybe_unused,
16 struct machine *machine)
17{
18 return machine__process_mmap_event(machine, event, NULL);
19}
20
21static int init_live_machine(struct machine *machine)
22{
23 union perf_event event;
24 pid_t pid = getpid();
25
26 return perf_event__synthesize_mmap_events(NULL, &event, pid, pid,
27 mmap_handler, machine, true);
28}
29
30#define MAX_STACK 6
31
32static int unwind_entry(struct unwind_entry *entry, void *arg)
33{
34 unsigned long *cnt = (unsigned long *) arg;
35 char *symbol = entry->sym ? entry->sym->name : NULL;
36 static const char *funcs[MAX_STACK] = {
37 "test__arch_unwind_sample",
38 "unwind_thread",
39 "krava_3",
40 "krava_2",
41 "krava_1",
42 "test__dwarf_unwind"
43 };
44
45 if (*cnt >= MAX_STACK) {
46 pr_debug("failed: crossed the max stack value %d\n", MAX_STACK);
47 return -1;
48 }
49
50 if (!symbol) {
51 pr_debug("failed: got unresolved address 0x%" PRIx64 "\n",
52 entry->ip);
53 return -1;
54 }
55
56 pr_debug("got: %s 0x%" PRIx64 "\n", symbol, entry->ip);
57 return strcmp((const char *) symbol, funcs[(*cnt)++]);
58}
59
60__attribute__ ((noinline))
61static int unwind_thread(struct thread *thread, struct machine *machine)
62{
63 struct perf_sample sample;
64 unsigned long cnt = 0;
65 int err = -1;
66
67 memset(&sample, 0, sizeof(sample));
68
69 if (test__arch_unwind_sample(&sample, thread)) {
70 pr_debug("failed to get unwind sample\n");
71 goto out;
72 }
73
74 err = unwind__get_entries(unwind_entry, &cnt, machine, thread,
75 &sample, MAX_STACK);
76 if (err)
77 pr_debug("unwind failed\n");
78 else if (cnt != MAX_STACK) {
79 pr_debug("got wrong number of stack entries %lu != %d\n",
80 cnt, MAX_STACK);
81 err = -1;
82 }
83
84 out:
85 free(sample.user_stack.data);
86 free(sample.user_regs.regs);
87 return err;
88}
89
90__attribute__ ((noinline))
91static int krava_3(struct thread *thread, struct machine *machine)
92{
93 return unwind_thread(thread, machine);
94}
95
96__attribute__ ((noinline))
97static int krava_2(struct thread *thread, struct machine *machine)
98{
99 return krava_3(thread, machine);
100}
101
102__attribute__ ((noinline))
103static int krava_1(struct thread *thread, struct machine *machine)
104{
105 return krava_2(thread, machine);
106}
107
108int test__dwarf_unwind(void)
109{
110 struct machines machines;
111 struct machine *machine;
112 struct thread *thread;
113 int err = -1;
114
115 machines__init(&machines);
116
117 machine = machines__find(&machines, HOST_KERNEL_ID);
118 if (!machine) {
119 pr_err("Could not get machine\n");
120 return -1;
121 }
122
123 if (init_live_machine(machine)) {
124 pr_err("Could not init machine\n");
125 goto out;
126 }
127
128 if (verbose > 1)
129 machine__fprintf(machine, stderr);
130
131 thread = machine__find_thread(machine, getpid(), getpid());
132 if (!thread) {
133 pr_err("Could not get thread\n");
134 goto out;
135 }
136
137 err = krava_1(thread, machine);
138
139 out:
140 machine__delete_threads(machine);
141 machine__exit(machine);
142 machines__exit(&machines);
143 return err;
144}
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 2b6519e0e36f..7ccbc7b6ae77 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -101,6 +101,7 @@ static struct machine *setup_fake_machine(struct machines *machines)
101 .mmap = { 101 .mmap = {
102 .header = { .misc = PERF_RECORD_MISC_USER, }, 102 .header = { .misc = PERF_RECORD_MISC_USER, },
103 .pid = fake_mmap_info[i].pid, 103 .pid = fake_mmap_info[i].pid,
104 .tid = fake_mmap_info[i].pid,
104 .start = fake_mmap_info[i].start, 105 .start = fake_mmap_info[i].start,
105 .len = 0x1000ULL, 106 .len = 0x1000ULL,
106 .pgoff = 0ULL, 107 .pgoff = 0ULL,
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 00544b8b644b..2f92d6e7ee00 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -27,6 +27,7 @@ make_no_ui := NO_NEWT=1 NO_SLANG=1 NO_GTK2=1
27make_no_demangle := NO_DEMANGLE=1 27make_no_demangle := NO_DEMANGLE=1
28make_no_libelf := NO_LIBELF=1 28make_no_libelf := NO_LIBELF=1
29make_no_libunwind := NO_LIBUNWIND=1 29make_no_libunwind := NO_LIBUNWIND=1
30make_no_libdw_dwarf_unwind := NO_LIBDW_DWARF_UNWIND=1
30make_no_backtrace := NO_BACKTRACE=1 31make_no_backtrace := NO_BACKTRACE=1
31make_no_libnuma := NO_LIBNUMA=1 32make_no_libnuma := NO_LIBNUMA=1
32make_no_libaudit := NO_LIBAUDIT=1 33make_no_libaudit := NO_LIBAUDIT=1
@@ -35,8 +36,9 @@ make_tags := tags
35make_cscope := cscope 36make_cscope := cscope
36make_help := help 37make_help := help
37make_doc := doc 38make_doc := doc
38make_perf_o := perf.o 39make_perf_o := perf.o
39make_util_map_o := util/map.o 40make_util_map_o := util/map.o
41make_util_pmu_bison_o := util/pmu-bison.o
40make_install := install 42make_install := install
41make_install_bin := install-bin 43make_install_bin := install-bin
42make_install_doc := install-doc 44make_install_doc := install-doc
@@ -44,11 +46,13 @@ make_install_man := install-man
44make_install_html := install-html 46make_install_html := install-html
45make_install_info := install-info 47make_install_info := install-info
46make_install_pdf := install-pdf 48make_install_pdf := install-pdf
49make_static := LDFLAGS=-static
47 50
48# all the NO_* variable combined 51# all the NO_* variable combined
49make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 52make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
50make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 53make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
51make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 54make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
55make_minimal += NO_LIBDW_DWARF_UNWIND=1
52 56
53# $(run) contains all available tests 57# $(run) contains all available tests
54run := make_pure 58run := make_pure
@@ -65,6 +69,7 @@ run += make_no_ui
65run += make_no_demangle 69run += make_no_demangle
66run += make_no_libelf 70run += make_no_libelf
67run += make_no_libunwind 71run += make_no_libunwind
72run += make_no_libdw_dwarf_unwind
68run += make_no_backtrace 73run += make_no_backtrace
69run += make_no_libnuma 74run += make_no_libnuma
70run += make_no_libaudit 75run += make_no_libaudit
@@ -73,6 +78,7 @@ run += make_help
73run += make_doc 78run += make_doc
74run += make_perf_o 79run += make_perf_o
75run += make_util_map_o 80run += make_util_map_o
81run += make_util_pmu_bison_o
76run += make_install 82run += make_install
77run += make_install_bin 83run += make_install_bin
78# FIXME 'install-*' commented out till they're fixed 84# FIXME 'install-*' commented out till they're fixed
@@ -82,6 +88,7 @@ run += make_install_bin
82# run += make_install_info 88# run += make_install_info
83# run += make_install_pdf 89# run += make_install_pdf
84run += make_minimal 90run += make_minimal
91run += make_static
85 92
86ifneq ($(call has,ctags),) 93ifneq ($(call has,ctags),)
87run += make_tags 94run += make_tags
@@ -113,8 +120,9 @@ test_make_doc_O := $(test_ok)
113 120
114test_make_python_perf_so := test -f $(PERF)/python/perf.so 121test_make_python_perf_so := test -f $(PERF)/python/perf.so
115 122
116test_make_perf_o := test -f $(PERF)/perf.o 123test_make_perf_o := test -f $(PERF)/perf.o
117test_make_util_map_o := test -f $(PERF)/util/map.o 124test_make_util_map_o := test -f $(PERF)/util/map.o
125test_make_util_pmu_bison_o := test -f $(PERF)/util/pmu-bison.o
118 126
119define test_dest_files 127define test_dest_files
120 for file in $(1); do \ 128 for file in $(1); do \
@@ -167,13 +175,10 @@ test_make_install_info_O := $(test_ok)
167test_make_install_pdf := $(test_ok) 175test_make_install_pdf := $(test_ok)
168test_make_install_pdf_O := $(test_ok) 176test_make_install_pdf_O := $(test_ok)
169 177
170# Kbuild tests only 178test_make_python_perf_so_O := test -f $$TMP_O/python/perf.so
171#test_make_python_perf_so_O := test -f $$TMP/tools/perf/python/perf.so 179test_make_perf_o_O := test -f $$TMP_O/perf.o
172#test_make_perf_o_O := test -f $$TMP/tools/perf/perf.o 180test_make_util_map_o_O := test -f $$TMP_O/util/map.o
173#test_make_util_map_o_O := test -f $$TMP/tools/perf/util/map.o 181test_make_util_pmu_bison_o_O := test -f $$TMP_O/util/pmu-bison.o
174
175test_make_perf_o_O := true
176test_make_util_map_o_O := true
177 182
178test_default = test -x $(PERF)/perf 183test_default = test -x $(PERF)/perf
179test = $(if $(test_$1),$(test_$1),$(test_default)) 184test = $(if $(test_$1),$(test_$1),$(test_default))
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 4db0ae617d70..8605ff5572ae 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -2,7 +2,7 @@
2#include "parse-events.h" 2#include "parse-events.h"
3#include "evsel.h" 3#include "evsel.h"
4#include "evlist.h" 4#include "evlist.h"
5#include "fs.h" 5#include <api/fs/fs.h>
6#include <api/fs/debugfs.h> 6#include <api/fs/debugfs.h>
7#include "tests.h" 7#include "tests.h"
8#include <linux/hw_breakpoint.h> 8#include <linux/hw_breakpoint.h>
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 1b677202638d..0014d3c8c21c 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -22,8 +22,8 @@
22} while (0) 22} while (0)
23 23
24static bool samples_same(const struct perf_sample *s1, 24static bool samples_same(const struct perf_sample *s1,
25 const struct perf_sample *s2, u64 type, u64 regs_user, 25 const struct perf_sample *s2,
26 u64 read_format) 26 u64 type, u64 read_format)
27{ 27{
28 size_t i; 28 size_t i;
29 29
@@ -95,8 +95,9 @@ static bool samples_same(const struct perf_sample *s1,
95 } 95 }
96 96
97 if (type & PERF_SAMPLE_REGS_USER) { 97 if (type & PERF_SAMPLE_REGS_USER) {
98 size_t sz = hweight_long(regs_user) * sizeof(u64); 98 size_t sz = hweight_long(s1->user_regs.mask) * sizeof(u64);
99 99
100 COMP(user_regs.mask);
100 COMP(user_regs.abi); 101 COMP(user_regs.abi);
101 if (s1->user_regs.abi && 102 if (s1->user_regs.abi &&
102 (!s1->user_regs.regs || !s2->user_regs.regs || 103 (!s1->user_regs.regs || !s2->user_regs.regs ||
@@ -174,6 +175,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
174 .branch_stack = &branch_stack.branch_stack, 175 .branch_stack = &branch_stack.branch_stack,
175 .user_regs = { 176 .user_regs = {
176 .abi = PERF_SAMPLE_REGS_ABI_64, 177 .abi = PERF_SAMPLE_REGS_ABI_64,
178 .mask = sample_regs_user,
177 .regs = user_regs, 179 .regs = user_regs,
178 }, 180 },
179 .user_stack = { 181 .user_stack = {
@@ -201,8 +203,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
201 sample.read.one.id = 99; 203 sample.read.one.id = 99;
202 } 204 }
203 205
204 sz = perf_event__sample_event_size(&sample, sample_type, 206 sz = perf_event__sample_event_size(&sample, sample_type, read_format);
205 sample_regs_user, read_format);
206 bufsz = sz + 4096; /* Add a bit for overrun checking */ 207 bufsz = sz + 4096; /* Add a bit for overrun checking */
207 event = malloc(bufsz); 208 event = malloc(bufsz);
208 if (!event) { 209 if (!event) {
@@ -215,8 +216,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
215 event->header.misc = 0; 216 event->header.misc = 0;
216 event->header.size = sz; 217 event->header.size = sz;
217 218
218 err = perf_event__synthesize_sample(event, sample_type, 219 err = perf_event__synthesize_sample(event, sample_type, read_format,
219 sample_regs_user, read_format,
220 &sample, false); 220 &sample, false);
221 if (err) { 221 if (err) {
222 pr_debug("%s failed for sample_type %#"PRIx64", error %d\n", 222 pr_debug("%s failed for sample_type %#"PRIx64", error %d\n",
@@ -244,8 +244,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
244 goto out_free; 244 goto out_free;
245 } 245 }
246 246
247 if (!samples_same(&sample, &sample_out, sample_type, 247 if (!samples_same(&sample, &sample_out, sample_type, read_format)) {
248 sample_regs_user, read_format)) {
249 pr_debug("parsing failed for sample_type %#"PRIx64"\n", 248 pr_debug("parsing failed for sample_type %#"PRIx64"\n",
250 sample_type); 249 sample_type);
251 goto out_free; 250 goto out_free;
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index e0ac713857ba..a24795ca002d 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -40,5 +40,14 @@ int test__code_reading(void);
40int test__sample_parsing(void); 40int test__sample_parsing(void);
41int test__keep_tracking(void); 41int test__keep_tracking(void);
42int test__parse_no_sample_id_all(void); 42int test__parse_no_sample_id_all(void);
43int test__dwarf_unwind(void);
43 44
45#if defined(__x86_64__) || defined(__i386__)
46#ifdef HAVE_DWARF_UNWIND_SUPPORT
47struct thread;
48struct perf_sample;
49int test__arch_unwind_sample(struct perf_sample *sample,
50 struct thread *thread);
51#endif
52#endif
44#endif /* TESTS_H */ 53#endif /* TESTS_H */
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index b720b92eba6e..7ec871af3f6f 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -587,95 +587,52 @@ struct hpp_arg {
587 bool current_entry; 587 bool current_entry;
588}; 588};
589 589
590static int __hpp__color_callchain(struct hpp_arg *arg) 590static int __hpp__overhead_callback(struct perf_hpp *hpp, bool front)
591{ 591{
592 if (!symbol_conf.use_callchain)
593 return 0;
594
595 slsmg_printf("%c ", arg->folded_sign);
596 return 2;
597}
598
599static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
600 u64 (*get_field)(struct hist_entry *),
601 int (*callchain_cb)(struct hpp_arg *))
602{
603 int ret = 0;
604 double percent = 0.0;
605 struct hists *hists = he->hists;
606 struct hpp_arg *arg = hpp->ptr; 592 struct hpp_arg *arg = hpp->ptr;
607 593
608 if (hists->stats.total_period) 594 if (arg->current_entry && arg->b->navkeypressed)
609 percent = 100.0 * get_field(he) / hists->stats.total_period; 595 ui_browser__set_color(arg->b, HE_COLORSET_SELECTED);
610 596 else
611 ui_browser__set_percent_color(arg->b, percent, arg->current_entry); 597 ui_browser__set_color(arg->b, HE_COLORSET_NORMAL);
612
613 if (callchain_cb)
614 ret += callchain_cb(arg);
615
616 ret += scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
617 slsmg_printf("%s", hpp->buf);
618
619 if (symbol_conf.event_group) {
620 int prev_idx, idx_delta;
621 struct perf_evsel *evsel = hists_to_evsel(hists);
622 struct hist_entry *pair;
623 int nr_members = evsel->nr_members;
624
625 if (nr_members <= 1)
626 goto out;
627 598
628 prev_idx = perf_evsel__group_idx(evsel); 599 if (front) {
600 if (!symbol_conf.use_callchain)
601 return 0;
629 602
630 list_for_each_entry(pair, &he->pairs.head, pairs.node) { 603 slsmg_printf("%c ", arg->folded_sign);
631 u64 period = get_field(pair); 604 return 2;
632 u64 total = pair->hists->stats.total_period; 605 }
633 606
634 if (!total) 607 return 0;
635 continue; 608}
636 609
637 evsel = hists_to_evsel(pair->hists); 610static int __hpp__color_callback(struct perf_hpp *hpp, bool front __maybe_unused)
638 idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1; 611{
612 struct hpp_arg *arg = hpp->ptr;
639 613
640 while (idx_delta--) { 614 if (!arg->current_entry || !arg->b->navkeypressed)
641 /* 615 ui_browser__set_color(arg->b, HE_COLORSET_NORMAL);
642 * zero-fill group members in the middle which 616 return 0;
643 * have no sample 617}
644 */
645 ui_browser__set_percent_color(arg->b, 0.0,
646 arg->current_entry);
647 ret += scnprintf(hpp->buf, hpp->size,
648 " %6.2f%%", 0.0);
649 slsmg_printf("%s", hpp->buf);
650 }
651 618
652 percent = 100.0 * period / total; 619static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
653 ui_browser__set_percent_color(arg->b, percent, 620{
654 arg->current_entry); 621 struct hpp_arg *arg = hpp->ptr;
655 ret += scnprintf(hpp->buf, hpp->size, 622 int ret;
656 " %6.2f%%", percent); 623 va_list args;
657 slsmg_printf("%s", hpp->buf); 624 double percent;
658 625
659 prev_idx = perf_evsel__group_idx(evsel); 626 va_start(args, fmt);
660 } 627 percent = va_arg(args, double);
628 va_end(args);
661 629
662 idx_delta = nr_members - prev_idx - 1; 630 ui_browser__set_percent_color(arg->b, percent, arg->current_entry);
663 631
664 while (idx_delta--) { 632 ret = scnprintf(hpp->buf, hpp->size, fmt, percent);
665 /* 633 slsmg_printf("%s", hpp->buf);
666 * zero-fill group members at last which have no sample
667 */
668 ui_browser__set_percent_color(arg->b, 0.0,
669 arg->current_entry);
670 ret += scnprintf(hpp->buf, hpp->size,
671 " %6.2f%%", 0.0);
672 slsmg_printf("%s", hpp->buf);
673 }
674 }
675out:
676 if (!arg->current_entry || !arg->b->navkeypressed)
677 ui_browser__set_color(arg->b, HE_COLORSET_NORMAL);
678 634
635 advance_hpp(hpp, ret);
679 return ret; 636 return ret;
680} 637}
681 638
@@ -690,14 +647,15 @@ hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,\
690 struct perf_hpp *hpp, \ 647 struct perf_hpp *hpp, \
691 struct hist_entry *he) \ 648 struct hist_entry *he) \
692{ \ 649{ \
693 return __hpp__color_fmt(hpp, he, __hpp_get_##_field, _cb); \ 650 return __hpp__fmt(hpp, he, __hpp_get_##_field, _cb, " %6.2f%%", \
651 __hpp__slsmg_color_printf, true); \
694} 652}
695 653
696__HPP_COLOR_PERCENT_FN(overhead, period, __hpp__color_callchain) 654__HPP_COLOR_PERCENT_FN(overhead, period, __hpp__overhead_callback)
697__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys, NULL) 655__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys, __hpp__color_callback)
698__HPP_COLOR_PERCENT_FN(overhead_us, period_us, NULL) 656__HPP_COLOR_PERCENT_FN(overhead_us, period_us, __hpp__color_callback)
699__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys, NULL) 657__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys, __hpp__color_callback)
700__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us, NULL) 658__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us, __hpp__color_callback)
701 659
702#undef __HPP_COLOR_PERCENT_FN 660#undef __HPP_COLOR_PERCENT_FN
703 661
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 5b95c44f3435..e395ef9b0ae0 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -8,16 +8,24 @@
8 8
9#define MAX_COLUMNS 32 9#define MAX_COLUMNS 32
10 10
11static int __percent_color_snprintf(char *buf, size_t size, double percent) 11static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
12{ 12{
13 int ret = 0; 13 int ret = 0;
14 va_list args;
15 double percent;
14 const char *markup; 16 const char *markup;
17 char *buf = hpp->buf;
18 size_t size = hpp->size;
19
20 va_start(args, fmt);
21 percent = va_arg(args, double);
22 va_end(args);
15 23
16 markup = perf_gtk__get_percent_color(percent); 24 markup = perf_gtk__get_percent_color(percent);
17 if (markup) 25 if (markup)
18 ret += scnprintf(buf, size, markup); 26 ret += scnprintf(buf, size, markup);
19 27
20 ret += scnprintf(buf + ret, size - ret, " %6.2f%%", percent); 28 ret += scnprintf(buf + ret, size - ret, fmt, percent);
21 29
22 if (markup) 30 if (markup)
23 ret += scnprintf(buf + ret, size - ret, "</span>"); 31 ret += scnprintf(buf + ret, size - ret, "</span>");
@@ -25,66 +33,6 @@ static int __percent_color_snprintf(char *buf, size_t size, double percent)
25 return ret; 33 return ret;
26} 34}
27 35
28
29static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
30 u64 (*get_field)(struct hist_entry *))
31{
32 int ret;
33 double percent = 0.0;
34 struct hists *hists = he->hists;
35 struct perf_evsel *evsel = hists_to_evsel(hists);
36
37 if (hists->stats.total_period)
38 percent = 100.0 * get_field(he) / hists->stats.total_period;
39
40 ret = __percent_color_snprintf(hpp->buf, hpp->size, percent);
41
42 if (perf_evsel__is_group_event(evsel)) {
43 int prev_idx, idx_delta;
44 struct hist_entry *pair;
45 int nr_members = evsel->nr_members;
46
47 prev_idx = perf_evsel__group_idx(evsel);
48
49 list_for_each_entry(pair, &he->pairs.head, pairs.node) {
50 u64 period = get_field(pair);
51 u64 total = pair->hists->stats.total_period;
52
53 evsel = hists_to_evsel(pair->hists);
54 idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
55
56 while (idx_delta--) {
57 /*
58 * zero-fill group members in the middle which
59 * have no sample
60 */
61 ret += __percent_color_snprintf(hpp->buf + ret,
62 hpp->size - ret,
63 0.0);
64 }
65
66 percent = 100.0 * period / total;
67 ret += __percent_color_snprintf(hpp->buf + ret,
68 hpp->size - ret,
69 percent);
70
71 prev_idx = perf_evsel__group_idx(evsel);
72 }
73
74 idx_delta = nr_members - prev_idx - 1;
75
76 while (idx_delta--) {
77 /*
78 * zero-fill group members at last which have no sample
79 */
80 ret += __percent_color_snprintf(hpp->buf + ret,
81 hpp->size - ret,
82 0.0);
83 }
84 }
85 return ret;
86}
87
88#define __HPP_COLOR_PERCENT_FN(_type, _field) \ 36#define __HPP_COLOR_PERCENT_FN(_type, _field) \
89static u64 he_get_##_field(struct hist_entry *he) \ 37static u64 he_get_##_field(struct hist_entry *he) \
90{ \ 38{ \
@@ -95,7 +43,8 @@ static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,
95 struct perf_hpp *hpp, \ 43 struct perf_hpp *hpp, \
96 struct hist_entry *he) \ 44 struct hist_entry *he) \
97{ \ 45{ \
98 return __hpp__color_fmt(hpp, he, he_get_##_field); \ 46 return __hpp__fmt(hpp, he, he_get_##_field, NULL, " %6.2f%%", \
47 __percent_color_snprintf, true); \
99} 48}
100 49
101__HPP_COLOR_PERCENT_FN(overhead, period) 50__HPP_COLOR_PERCENT_FN(overhead, period)
@@ -216,7 +165,6 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
216 struct perf_hpp hpp = { 165 struct perf_hpp hpp = {
217 .buf = s, 166 .buf = s,
218 .size = sizeof(s), 167 .size = sizeof(s),
219 .ptr = hists_to_evsel(hists),
220 }; 168 };
221 169
222 nr_cols = 0; 170 nr_cols = 0;
@@ -243,7 +191,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
243 col_idx = 0; 191 col_idx = 0;
244 192
245 perf_hpp__for_each_format(fmt) { 193 perf_hpp__for_each_format(fmt) {
246 fmt->header(fmt, &hpp); 194 fmt->header(fmt, &hpp, hists_to_evsel(hists));
247 195
248 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), 196 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
249 -1, ltrim(s), 197 -1, ltrim(s),
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 78f4c92e9b73..0f403b83e9d1 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -8,16 +8,27 @@
8 8
9/* hist period print (hpp) functions */ 9/* hist period print (hpp) functions */
10 10
11typedef int (*hpp_snprint_fn)(char *buf, size_t size, const char *fmt, ...); 11#define hpp__call_print_fn(hpp, fn, fmt, ...) \
12 12({ \
13static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, 13 int __ret = fn(hpp, fmt, ##__VA_ARGS__); \
14 u64 (*get_field)(struct hist_entry *), 14 advance_hpp(hpp, __ret); \
15 const char *fmt, hpp_snprint_fn print_fn, 15 __ret; \
16 bool fmt_percent) 16})
17
18int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
19 hpp_field_fn get_field, hpp_callback_fn callback,
20 const char *fmt, hpp_snprint_fn print_fn, bool fmt_percent)
17{ 21{
18 int ret; 22 int ret = 0;
19 struct hists *hists = he->hists; 23 struct hists *hists = he->hists;
20 struct perf_evsel *evsel = hists_to_evsel(hists); 24 struct perf_evsel *evsel = hists_to_evsel(hists);
25 char *buf = hpp->buf;
26 size_t size = hpp->size;
27
28 if (callback) {
29 ret = callback(hpp, true);
30 advance_hpp(hpp, ret);
31 }
21 32
22 if (fmt_percent) { 33 if (fmt_percent) {
23 double percent = 0.0; 34 double percent = 0.0;
@@ -26,9 +37,9 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
26 percent = 100.0 * get_field(he) / 37 percent = 100.0 * get_field(he) /
27 hists->stats.total_period; 38 hists->stats.total_period;
28 39
29 ret = print_fn(hpp->buf, hpp->size, fmt, percent); 40 ret += hpp__call_print_fn(hpp, print_fn, fmt, percent);
30 } else 41 } else
31 ret = print_fn(hpp->buf, hpp->size, fmt, get_field(he)); 42 ret += hpp__call_print_fn(hpp, print_fn, fmt, get_field(he));
32 43
33 if (perf_evsel__is_group_event(evsel)) { 44 if (perf_evsel__is_group_event(evsel)) {
34 int prev_idx, idx_delta; 45 int prev_idx, idx_delta;
@@ -52,16 +63,22 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
52 * zero-fill group members in the middle which 63 * zero-fill group members in the middle which
53 * have no sample 64 * have no sample
54 */ 65 */
55 ret += print_fn(hpp->buf + ret, hpp->size - ret, 66 if (fmt_percent) {
56 fmt, 0); 67 ret += hpp__call_print_fn(hpp, print_fn,
68 fmt, 0.0);
69 } else {
70 ret += hpp__call_print_fn(hpp, print_fn,
71 fmt, 0ULL);
72 }
57 } 73 }
58 74
59 if (fmt_percent) 75 if (fmt_percent) {
60 ret += print_fn(hpp->buf + ret, hpp->size - ret, 76 ret += hpp__call_print_fn(hpp, print_fn, fmt,
61 fmt, 100.0 * period / total); 77 100.0 * period / total);
62 else 78 } else {
63 ret += print_fn(hpp->buf + ret, hpp->size - ret, 79 ret += hpp__call_print_fn(hpp, print_fn, fmt,
64 fmt, period); 80 period);
81 }
65 82
66 prev_idx = perf_evsel__group_idx(evsel); 83 prev_idx = perf_evsel__group_idx(evsel);
67 } 84 }
@@ -72,41 +89,87 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
72 /* 89 /*
73 * zero-fill group members at last which have no sample 90 * zero-fill group members at last which have no sample
74 */ 91 */
75 ret += print_fn(hpp->buf + ret, hpp->size - ret, 92 if (fmt_percent) {
76 fmt, 0); 93 ret += hpp__call_print_fn(hpp, print_fn,
94 fmt, 0.0);
95 } else {
96 ret += hpp__call_print_fn(hpp, print_fn,
97 fmt, 0ULL);
98 }
77 } 99 }
78 } 100 }
101
102 if (callback) {
103 int __ret = callback(hpp, false);
104
105 advance_hpp(hpp, __ret);
106 ret += __ret;
107 }
108
109 /*
110 * Restore original buf and size as it's where caller expects
111 * the result will be saved.
112 */
113 hpp->buf = buf;
114 hpp->size = size;
115
79 return ret; 116 return ret;
80} 117}
81 118
82#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \ 119#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
83static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 120static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
84 struct perf_hpp *hpp) \ 121 struct perf_hpp *hpp, \
122 struct perf_evsel *evsel) \
85{ \ 123{ \
86 int len = _min_width; \ 124 int len = _min_width; \
87 \ 125 \
88 if (symbol_conf.event_group) { \ 126 if (symbol_conf.event_group) \
89 struct perf_evsel *evsel = hpp->ptr; \
90 \
91 len = max(len, evsel->nr_members * _unit_width); \ 127 len = max(len, evsel->nr_members * _unit_width); \
92 } \ 128 \
93 return scnprintf(hpp->buf, hpp->size, "%*s", len, _str); \ 129 return scnprintf(hpp->buf, hpp->size, "%*s", len, _str); \
94} 130}
95 131
96#define __HPP_WIDTH_FN(_type, _min_width, _unit_width) \ 132#define __HPP_WIDTH_FN(_type, _min_width, _unit_width) \
97static int hpp__width_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 133static int hpp__width_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
98 struct perf_hpp *hpp __maybe_unused) \ 134 struct perf_hpp *hpp __maybe_unused, \
135 struct perf_evsel *evsel) \
99{ \ 136{ \
100 int len = _min_width; \ 137 int len = _min_width; \
101 \ 138 \
102 if (symbol_conf.event_group) { \ 139 if (symbol_conf.event_group) \
103 struct perf_evsel *evsel = hpp->ptr; \
104 \
105 len = max(len, evsel->nr_members * _unit_width); \ 140 len = max(len, evsel->nr_members * _unit_width); \
106 } \ 141 \
107 return len; \ 142 return len; \
108} 143}
109 144
145static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
146{
147 va_list args;
148 ssize_t ssize = hpp->size;
149 double percent;
150 int ret;
151
152 va_start(args, fmt);
153 percent = va_arg(args, double);
154 ret = value_color_snprintf(hpp->buf, hpp->size, fmt, percent);
155 va_end(args);
156
157 return (ret >= ssize) ? (ssize - 1) : ret;
158}
159
160static int hpp_entry_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
161{
162 va_list args;
163 ssize_t ssize = hpp->size;
164 int ret;
165
166 va_start(args, fmt);
167 ret = vsnprintf(hpp->buf, hpp->size, fmt, args);
168 va_end(args);
169
170 return (ret >= ssize) ? (ssize - 1) : ret;
171}
172
110#define __HPP_COLOR_PERCENT_FN(_type, _field) \ 173#define __HPP_COLOR_PERCENT_FN(_type, _field) \
111static u64 he_get_##_field(struct hist_entry *he) \ 174static u64 he_get_##_field(struct hist_entry *he) \
112{ \ 175{ \
@@ -116,8 +179,8 @@ static u64 he_get_##_field(struct hist_entry *he) \
116static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 179static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
117 struct perf_hpp *hpp, struct hist_entry *he) \ 180 struct perf_hpp *hpp, struct hist_entry *he) \
118{ \ 181{ \
119 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ 182 return __hpp__fmt(hpp, he, he_get_##_field, NULL, " %6.2f%%", \
120 percent_color_snprintf, true); \ 183 hpp_color_scnprintf, true); \
121} 184}
122 185
123#define __HPP_ENTRY_PERCENT_FN(_type, _field) \ 186#define __HPP_ENTRY_PERCENT_FN(_type, _field) \
@@ -125,8 +188,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \
125 struct perf_hpp *hpp, struct hist_entry *he) \ 188 struct perf_hpp *hpp, struct hist_entry *he) \
126{ \ 189{ \
127 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \ 190 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \
128 return __hpp__fmt(hpp, he, he_get_##_field, fmt, \ 191 return __hpp__fmt(hpp, he, he_get_##_field, NULL, fmt, \
129 scnprintf, true); \ 192 hpp_entry_scnprintf, true); \
130} 193}
131 194
132#define __HPP_ENTRY_RAW_FN(_type, _field) \ 195#define __HPP_ENTRY_RAW_FN(_type, _field) \
@@ -139,7 +202,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \
139 struct perf_hpp *hpp, struct hist_entry *he) \ 202 struct perf_hpp *hpp, struct hist_entry *he) \
140{ \ 203{ \
141 const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64; \ 204 const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64; \
142 return __hpp__fmt(hpp, he, he_get_raw_##_field, fmt, scnprintf, false); \ 205 return __hpp__fmt(hpp, he, he_get_raw_##_field, NULL, fmt, \
206 hpp_entry_scnprintf, false); \
143} 207}
144 208
145#define HPP_PERCENT_FNS(_type, _str, _field, _min_width, _unit_width) \ 209#define HPP_PERCENT_FNS(_type, _str, _field, _min_width, _unit_width) \
@@ -263,15 +327,13 @@ unsigned int hists__sort_list_width(struct hists *hists)
263 struct perf_hpp_fmt *fmt; 327 struct perf_hpp_fmt *fmt;
264 struct sort_entry *se; 328 struct sort_entry *se;
265 int i = 0, ret = 0; 329 int i = 0, ret = 0;
266 struct perf_hpp dummy_hpp = { 330 struct perf_hpp dummy_hpp;
267 .ptr = hists_to_evsel(hists),
268 };
269 331
270 perf_hpp__for_each_format(fmt) { 332 perf_hpp__for_each_format(fmt) {
271 if (i) 333 if (i)
272 ret += 2; 334 ret += 2;
273 335
274 ret += fmt->width(fmt, &dummy_hpp); 336 ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists));
275 } 337 }
276 338
277 list_for_each_entry(se, &hist_entry__sort_list, list) 339 list_for_each_entry(se, &hist_entry__sort_list, list)
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 831fbb77d1ff..d59893edf031 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -306,12 +306,6 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
306 return hist_entry_callchain__fprintf(he, total_period, left_margin, fp); 306 return hist_entry_callchain__fprintf(he, total_period, left_margin, fp);
307} 307}
308 308
309static inline void advance_hpp(struct perf_hpp *hpp, int inc)
310{
311 hpp->buf += inc;
312 hpp->size -= inc;
313}
314
315static int hist_entry__period_snprintf(struct perf_hpp *hpp, 309static int hist_entry__period_snprintf(struct perf_hpp *hpp,
316 struct hist_entry *he) 310 struct hist_entry *he)
317{ 311{
@@ -385,7 +379,6 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
385 struct perf_hpp dummy_hpp = { 379 struct perf_hpp dummy_hpp = {
386 .buf = bf, 380 .buf = bf,
387 .size = sizeof(bf), 381 .size = sizeof(bf),
388 .ptr = hists_to_evsel(hists),
389 }; 382 };
390 bool first = true; 383 bool first = true;
391 size_t linesz; 384 size_t linesz;
@@ -404,7 +397,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
404 else 397 else
405 first = false; 398 first = false;
406 399
407 fmt->header(fmt, &dummy_hpp); 400 fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
408 fprintf(fp, "%s", bf); 401 fprintf(fp, "%s", bf);
409 } 402 }
410 403
@@ -449,7 +442,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
449 else 442 else
450 first = false; 443 first = false;
451 444
452 width = fmt->width(fmt, &dummy_hpp); 445 width = fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists));
453 for (i = 0; i < width; i++) 446 for (i = 0; i < width; i++)
454 fprintf(fp, "."); 447 fprintf(fp, ".");
455 } 448 }
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 3aa555ff9d89..809b4c50beae 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1236,6 +1236,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1236 struct dso *dso = map->dso; 1236 struct dso *dso = map->dso;
1237 char *filename; 1237 char *filename;
1238 const char *d_filename; 1238 const char *d_filename;
1239 const char *evsel_name = perf_evsel__name(evsel);
1239 struct annotation *notes = symbol__annotation(sym); 1240 struct annotation *notes = symbol__annotation(sym);
1240 struct disasm_line *pos, *queue = NULL; 1241 struct disasm_line *pos, *queue = NULL;
1241 u64 start = map__rip_2objdump(map, sym->start); 1242 u64 start = map__rip_2objdump(map, sym->start);
@@ -1243,7 +1244,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1243 int more = 0; 1244 int more = 0;
1244 u64 len; 1245 u64 len;
1245 int width = 8; 1246 int width = 8;
1246 int namelen; 1247 int namelen, evsel_name_len, graph_dotted_len;
1247 1248
1248 filename = strdup(dso->long_name); 1249 filename = strdup(dso->long_name);
1249 if (!filename) 1250 if (!filename)
@@ -1256,14 +1257,17 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1256 1257
1257 len = symbol__size(sym); 1258 len = symbol__size(sym);
1258 namelen = strlen(d_filename); 1259 namelen = strlen(d_filename);
1260 evsel_name_len = strlen(evsel_name);
1259 1261
1260 if (perf_evsel__is_group_event(evsel)) 1262 if (perf_evsel__is_group_event(evsel))
1261 width *= evsel->nr_members; 1263 width *= evsel->nr_members;
1262 1264
1263 printf(" %-*.*s| Source code & Disassembly of %s\n", 1265 printf(" %-*.*s| Source code & Disassembly of %s for %s\n",
1264 width, width, "Percent", d_filename); 1266 width, width, "Percent", d_filename, evsel_name);
1265 printf("-%-*.*s-------------------------------------\n", 1267
1266 width+namelen, width+namelen, graph_dotted_line); 1268 graph_dotted_len = width + namelen + evsel_name_len;
1269 printf("-%-*.*s-----------------------------------------\n",
1270 graph_dotted_len, graph_dotted_len, graph_dotted_line);
1267 1271
1268 if (verbose) 1272 if (verbose)
1269 symbol__annotate_hits(sym, evsel); 1273 symbol__annotate_hits(sym, evsel);
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index a9b48c42e81e..7fe4994eeb63 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -1,5 +1,5 @@
1#include "util.h" 1#include "util.h"
2#include "fs.h" 2#include <api/fs/fs.h>
3#include "../perf.h" 3#include "../perf.h"
4#include "cpumap.h" 4#include "cpumap.h"
5#include <assert.h> 5#include <assert.h>
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 1fbcd8bdc11b..55de44ecebef 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -86,10 +86,17 @@ static int open_file_read(struct perf_data_file *file)
86 86
87static int open_file_write(struct perf_data_file *file) 87static int open_file_write(struct perf_data_file *file)
88{ 88{
89 int fd;
90
89 if (check_backup(file)) 91 if (check_backup(file))
90 return -1; 92 return -1;
91 93
92 return open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); 94 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
95
96 if (fd < 0)
97 pr_err("failed to open %s : %s\n", file->path, strerror(errno));
98
99 return fd;
93} 100}
94 101
95static int open_file(struct perf_data_file *file) 102static int open_file(struct perf_data_file *file)
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 4045d086d9d9..64453d63b971 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -45,8 +45,8 @@ int dso__read_binary_type_filename(const struct dso *dso,
45 debuglink--; 45 debuglink--;
46 if (*debuglink == '/') 46 if (*debuglink == '/')
47 debuglink++; 47 debuglink++;
48 filename__read_debuglink(dso->long_name, debuglink, 48 ret = filename__read_debuglink(dso->long_name, debuglink,
49 size - (debuglink - filename)); 49 size - (debuglink - filename));
50 } 50 }
51 break; 51 break;
52 case DSO_BINARY_TYPE__BUILD_ID_CACHE: 52 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index cd7d6f078cdd..ab06f1c03655 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -102,6 +102,16 @@ struct dso {
102 char name[0]; 102 char name[0];
103}; 103};
104 104
105/* dso__for_each_symbol - iterate over the symbols of given type
106 *
107 * @dso: the 'struct dso *' in which symbols itereated
108 * @pos: the 'struct symbol *' to use as a loop cursor
109 * @n: the 'struct rb_node *' to use as a temporary storage
110 * @type: the 'enum map_type' type of symbols
111 */
112#define dso__for_each_symbol(dso, pos, n, type) \
113 symbols__for_each_entry(&(dso)->symbols[(type)], pos, n)
114
105static inline void dso__set_loaded(struct dso *dso, enum map_type type) 115static inline void dso__set_loaded(struct dso *dso, enum map_type type)
106{ 116{
107 dso->loaded |= (1 << type); 117 dso->loaded |= (1 << type);
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index 7defd77105d0..cc66c4049e09 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -747,14 +747,17 @@ struct __find_variable_param {
747static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) 747static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
748{ 748{
749 struct __find_variable_param *fvp = data; 749 struct __find_variable_param *fvp = data;
750 Dwarf_Attribute attr;
750 int tag; 751 int tag;
751 752
752 tag = dwarf_tag(die_mem); 753 tag = dwarf_tag(die_mem);
753 if ((tag == DW_TAG_formal_parameter || 754 if ((tag == DW_TAG_formal_parameter ||
754 tag == DW_TAG_variable) && 755 tag == DW_TAG_variable) &&
755 die_compare_name(die_mem, fvp->name)) 756 die_compare_name(die_mem, fvp->name) &&
757 /* Does the DIE have location information or external instance? */
758 (dwarf_attr(die_mem, DW_AT_external, &attr) ||
759 dwarf_attr(die_mem, DW_AT_location, &attr)))
756 return DIE_FIND_CB_END; 760 return DIE_FIND_CB_END;
757
758 if (dwarf_haspc(die_mem, fvp->addr)) 761 if (dwarf_haspc(die_mem, fvp->addr))
759 return DIE_FIND_CB_CONTINUE; 762 return DIE_FIND_CB_CONTINUE;
760 else 763 else
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index b0f3ca850e9e..9d12aa6dd485 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,6 +1,7 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include "event.h" 2#include "event.h"
3#include "debug.h" 3#include "debug.h"
4#include "hist.h"
4#include "machine.h" 5#include "machine.h"
5#include "sort.h" 6#include "sort.h"
6#include "string.h" 7#include "string.h"
@@ -94,14 +95,10 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
94 95
95static pid_t perf_event__synthesize_comm(struct perf_tool *tool, 96static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
96 union perf_event *event, pid_t pid, 97 union perf_event *event, pid_t pid,
97 int full,
98 perf_event__handler_t process, 98 perf_event__handler_t process,
99 struct machine *machine) 99 struct machine *machine)
100{ 100{
101 char filename[PATH_MAX];
102 size_t size; 101 size_t size;
103 DIR *tasks;
104 struct dirent dirent, *next;
105 pid_t tgid; 102 pid_t tgid;
106 103
107 memset(&event->comm, 0, sizeof(event->comm)); 104 memset(&event->comm, 0, sizeof(event->comm));
@@ -124,55 +121,35 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
124 event->comm.header.size = (sizeof(event->comm) - 121 event->comm.header.size = (sizeof(event->comm) -
125 (sizeof(event->comm.comm) - size) + 122 (sizeof(event->comm.comm) - size) +
126 machine->id_hdr_size); 123 machine->id_hdr_size);
127 if (!full) { 124 event->comm.tid = pid;
128 event->comm.tid = pid;
129 125
130 if (process(tool, event, &synth_sample, machine) != 0) 126 if (process(tool, event, &synth_sample, machine) != 0)
131 return -1; 127 return -1;
132
133 goto out;
134 }
135
136 if (machine__is_default_guest(machine))
137 return 0;
138
139 snprintf(filename, sizeof(filename), "%s/proc/%d/task",
140 machine->root_dir, pid);
141
142 tasks = opendir(filename);
143 if (tasks == NULL) {
144 pr_debug("couldn't open %s\n", filename);
145 return 0;
146 }
147 128
148 while (!readdir_r(tasks, &dirent, &next) && next) { 129out:
149 char *end; 130 return tgid;
150 pid = strtol(dirent.d_name, &end, 10); 131}
151 if (*end)
152 continue;
153 132
154 /* already have tgid; jut want to update the comm */ 133static int perf_event__synthesize_fork(struct perf_tool *tool,
155 (void) perf_event__get_comm_tgid(pid, event->comm.comm, 134 union perf_event *event, pid_t pid,
156 sizeof(event->comm.comm)); 135 pid_t tgid, perf_event__handler_t process,
136 struct machine *machine)
137{
138 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
157 139
158 size = strlen(event->comm.comm) + 1; 140 /* this is really a clone event but we use fork to synthesize it */
159 size = PERF_ALIGN(size, sizeof(u64)); 141 event->fork.ppid = tgid;
160 memset(event->comm.comm + size, 0, machine->id_hdr_size); 142 event->fork.ptid = tgid;
161 event->comm.header.size = (sizeof(event->comm) - 143 event->fork.pid = tgid;
162 (sizeof(event->comm.comm) - size) + 144 event->fork.tid = pid;
163 machine->id_hdr_size); 145 event->fork.header.type = PERF_RECORD_FORK;
164 146
165 event->comm.tid = pid; 147 event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size);
166 148
167 if (process(tool, event, &synth_sample, machine) != 0) { 149 if (process(tool, event, &synth_sample, machine) != 0)
168 tgid = -1; 150 return -1;
169 break;
170 }
171 }
172 151
173 closedir(tasks); 152 return 0;
174out:
175 return tgid;
176} 153}
177 154
178int perf_event__synthesize_mmap_events(struct perf_tool *tool, 155int perf_event__synthesize_mmap_events(struct perf_tool *tool,
@@ -324,17 +301,71 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
324 301
325static int __event__synthesize_thread(union perf_event *comm_event, 302static int __event__synthesize_thread(union perf_event *comm_event,
326 union perf_event *mmap_event, 303 union perf_event *mmap_event,
304 union perf_event *fork_event,
327 pid_t pid, int full, 305 pid_t pid, int full,
328 perf_event__handler_t process, 306 perf_event__handler_t process,
329 struct perf_tool *tool, 307 struct perf_tool *tool,
330 struct machine *machine, bool mmap_data) 308 struct machine *machine, bool mmap_data)
331{ 309{
332 pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full, 310 char filename[PATH_MAX];
311 DIR *tasks;
312 struct dirent dirent, *next;
313 pid_t tgid;
314
315 /* special case: only send one comm event using passed in pid */
316 if (!full) {
317 tgid = perf_event__synthesize_comm(tool, comm_event, pid,
318 process, machine);
319
320 if (tgid == -1)
321 return -1;
322
323 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
324 process, machine, mmap_data);
325 }
326
327 if (machine__is_default_guest(machine))
328 return 0;
329
330 snprintf(filename, sizeof(filename), "%s/proc/%d/task",
331 machine->root_dir, pid);
332
333 tasks = opendir(filename);
334 if (tasks == NULL) {
335 pr_debug("couldn't open %s\n", filename);
336 return 0;
337 }
338
339 while (!readdir_r(tasks, &dirent, &next) && next) {
340 char *end;
341 int rc = 0;
342 pid_t _pid;
343
344 _pid = strtol(dirent.d_name, &end, 10);
345 if (*end)
346 continue;
347
348 tgid = perf_event__synthesize_comm(tool, comm_event, _pid,
349 process, machine);
350 if (tgid == -1)
351 return -1;
352
353 if (_pid == pid) {
354 /* process the parent's maps too */
355 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
356 process, machine, mmap_data);
357 } else {
358 /* only fork the tid's map, to save time */
359 rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
333 process, machine); 360 process, machine);
334 if (tgid == -1) 361 }
335 return -1; 362
336 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 363 if (rc)
337 process, machine, mmap_data); 364 return rc;
365 }
366
367 closedir(tasks);
368 return 0;
338} 369}
339 370
340int perf_event__synthesize_thread_map(struct perf_tool *tool, 371int perf_event__synthesize_thread_map(struct perf_tool *tool,
@@ -343,7 +374,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
343 struct machine *machine, 374 struct machine *machine,
344 bool mmap_data) 375 bool mmap_data)
345{ 376{
346 union perf_event *comm_event, *mmap_event; 377 union perf_event *comm_event, *mmap_event, *fork_event;
347 int err = -1, thread, j; 378 int err = -1, thread, j;
348 379
349 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size); 380 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
@@ -354,9 +385,14 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
354 if (mmap_event == NULL) 385 if (mmap_event == NULL)
355 goto out_free_comm; 386 goto out_free_comm;
356 387
388 fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
389 if (fork_event == NULL)
390 goto out_free_mmap;
391
357 err = 0; 392 err = 0;
358 for (thread = 0; thread < threads->nr; ++thread) { 393 for (thread = 0; thread < threads->nr; ++thread) {
359 if (__event__synthesize_thread(comm_event, mmap_event, 394 if (__event__synthesize_thread(comm_event, mmap_event,
395 fork_event,
360 threads->map[thread], 0, 396 threads->map[thread], 0,
361 process, tool, machine, 397 process, tool, machine,
362 mmap_data)) { 398 mmap_data)) {
@@ -382,6 +418,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
382 /* if not, generate events for it */ 418 /* if not, generate events for it */
383 if (need_leader && 419 if (need_leader &&
384 __event__synthesize_thread(comm_event, mmap_event, 420 __event__synthesize_thread(comm_event, mmap_event,
421 fork_event,
385 comm_event->comm.pid, 0, 422 comm_event->comm.pid, 0,
386 process, tool, machine, 423 process, tool, machine,
387 mmap_data)) { 424 mmap_data)) {
@@ -390,6 +427,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
390 } 427 }
391 } 428 }
392 } 429 }
430 free(fork_event);
431out_free_mmap:
393 free(mmap_event); 432 free(mmap_event);
394out_free_comm: 433out_free_comm:
395 free(comm_event); 434 free(comm_event);
@@ -404,9 +443,12 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
404 DIR *proc; 443 DIR *proc;
405 char proc_path[PATH_MAX]; 444 char proc_path[PATH_MAX];
406 struct dirent dirent, *next; 445 struct dirent dirent, *next;
407 union perf_event *comm_event, *mmap_event; 446 union perf_event *comm_event, *mmap_event, *fork_event;
408 int err = -1; 447 int err = -1;
409 448
449 if (machine__is_default_guest(machine))
450 return 0;
451
410 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size); 452 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
411 if (comm_event == NULL) 453 if (comm_event == NULL)
412 goto out; 454 goto out;
@@ -415,14 +457,15 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
415 if (mmap_event == NULL) 457 if (mmap_event == NULL)
416 goto out_free_comm; 458 goto out_free_comm;
417 459
418 if (machine__is_default_guest(machine)) 460 fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
419 return 0; 461 if (fork_event == NULL)
462 goto out_free_mmap;
420 463
421 snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir); 464 snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
422 proc = opendir(proc_path); 465 proc = opendir(proc_path);
423 466
424 if (proc == NULL) 467 if (proc == NULL)
425 goto out_free_mmap; 468 goto out_free_fork;
426 469
427 while (!readdir_r(proc, &dirent, &next) && next) { 470 while (!readdir_r(proc, &dirent, &next) && next) {
428 char *end; 471 char *end;
@@ -434,12 +477,14 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
434 * We may race with exiting thread, so don't stop just because 477 * We may race with exiting thread, so don't stop just because
435 * one thread couldn't be synthesized. 478 * one thread couldn't be synthesized.
436 */ 479 */
437 __event__synthesize_thread(comm_event, mmap_event, pid, 1, 480 __event__synthesize_thread(comm_event, mmap_event, fork_event, pid,
438 process, tool, machine, mmap_data); 481 1, process, tool, machine, mmap_data);
439 } 482 }
440 483
441 err = 0; 484 err = 0;
442 closedir(proc); 485 closedir(proc);
486out_free_fork:
487 free(fork_event);
443out_free_mmap: 488out_free_mmap:
444 free(mmap_event); 489 free(mmap_event);
445out_free_comm: 490out_free_comm:
@@ -661,7 +706,7 @@ void thread__find_addr_map(struct thread *thread,
661 al->thread = thread; 706 al->thread = thread;
662 al->addr = addr; 707 al->addr = addr;
663 al->cpumode = cpumode; 708 al->cpumode = cpumode;
664 al->filtered = false; 709 al->filtered = 0;
665 710
666 if (machine == NULL) { 711 if (machine == NULL) {
667 al->map = NULL; 712 al->map = NULL;
@@ -687,11 +732,11 @@ void thread__find_addr_map(struct thread *thread,
687 if ((cpumode == PERF_RECORD_MISC_GUEST_USER || 732 if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
688 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) && 733 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) &&
689 !perf_guest) 734 !perf_guest)
690 al->filtered = true; 735 al->filtered |= (1 << HIST_FILTER__GUEST);
691 if ((cpumode == PERF_RECORD_MISC_USER || 736 if ((cpumode == PERF_RECORD_MISC_USER ||
692 cpumode == PERF_RECORD_MISC_KERNEL) && 737 cpumode == PERF_RECORD_MISC_KERNEL) &&
693 !perf_host) 738 !perf_host)
694 al->filtered = true; 739 al->filtered |= (1 << HIST_FILTER__HOST);
695 740
696 return; 741 return;
697 } 742 }
@@ -748,9 +793,6 @@ int perf_event__preprocess_sample(const union perf_event *event,
748 if (thread == NULL) 793 if (thread == NULL)
749 return -1; 794 return -1;
750 795
751 if (thread__is_filtered(thread))
752 goto out_filtered;
753
754 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); 796 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
755 /* 797 /*
756 * Have we already created the kernel maps for this machine? 798 * Have we already created the kernel maps for this machine?
@@ -768,6 +810,10 @@ int perf_event__preprocess_sample(const union perf_event *event,
768 dump_printf(" ...... dso: %s\n", 810 dump_printf(" ...... dso: %s\n",
769 al->map ? al->map->dso->long_name : 811 al->map ? al->map->dso->long_name :
770 al->level == 'H' ? "[hypervisor]" : "<not found>"); 812 al->level == 'H' ? "[hypervisor]" : "<not found>");
813
814 if (thread__is_filtered(thread))
815 al->filtered |= (1 << HIST_FILTER__THREAD);
816
771 al->sym = NULL; 817 al->sym = NULL;
772 al->cpu = sample->cpu; 818 al->cpu = sample->cpu;
773 819
@@ -779,8 +825,9 @@ int perf_event__preprocess_sample(const union perf_event *event,
779 dso->short_name) || 825 dso->short_name) ||
780 (dso->short_name != dso->long_name && 826 (dso->short_name != dso->long_name &&
781 strlist__has_entry(symbol_conf.dso_list, 827 strlist__has_entry(symbol_conf.dso_list,
782 dso->long_name))))) 828 dso->long_name))))) {
783 goto out_filtered; 829 al->filtered |= (1 << HIST_FILTER__DSO);
830 }
784 831
785 al->sym = map__find_symbol(al->map, al->addr, 832 al->sym = map__find_symbol(al->map, al->addr,
786 machine->symbol_filter); 833 machine->symbol_filter);
@@ -788,12 +835,9 @@ int perf_event__preprocess_sample(const union perf_event *event,
788 835
789 if (symbol_conf.sym_list && 836 if (symbol_conf.sym_list &&
790 (!al->sym || !strlist__has_entry(symbol_conf.sym_list, 837 (!al->sym || !strlist__has_entry(symbol_conf.sym_list,
791 al->sym->name))) 838 al->sym->name))) {
792 goto out_filtered; 839 al->filtered |= (1 << HIST_FILTER__SYMBOL);
793 840 }
794 return 0;
795 841
796out_filtered:
797 al->filtered = true;
798 return 0; 842 return 0;
799} 843}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 851fa06f4a42..38457d447a13 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -85,6 +85,7 @@ struct sample_event {
85 85
86struct regs_dump { 86struct regs_dump {
87 u64 abi; 87 u64 abi;
88 u64 mask;
88 u64 *regs; 89 u64 *regs;
89}; 90};
90 91
@@ -259,9 +260,9 @@ int perf_event__preprocess_sample(const union perf_event *event,
259const char *perf_event__name(unsigned int id); 260const char *perf_event__name(unsigned int id);
260 261
261size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, 262size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
262 u64 sample_regs_user, u64 read_format); 263 u64 read_format);
263int perf_event__synthesize_sample(union perf_event *event, u64 type, 264int perf_event__synthesize_sample(union perf_event *event, u64 type,
264 u64 sample_regs_user, u64 read_format, 265 u64 read_format,
265 const struct perf_sample *sample, 266 const struct perf_sample *sample,
266 bool swapped); 267 bool swapped);
267 268
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 55407c594b87..5c28d82b76c4 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -500,6 +500,34 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
500 return ret; 500 return ret;
501} 501}
502 502
503static void
504perf_evsel__config_callgraph(struct perf_evsel *evsel,
505 struct record_opts *opts)
506{
507 bool function = perf_evsel__is_function_event(evsel);
508 struct perf_event_attr *attr = &evsel->attr;
509
510 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
511
512 if (opts->call_graph == CALLCHAIN_DWARF) {
513 if (!function) {
514 perf_evsel__set_sample_bit(evsel, REGS_USER);
515 perf_evsel__set_sample_bit(evsel, STACK_USER);
516 attr->sample_regs_user = PERF_REGS_MASK;
517 attr->sample_stack_user = opts->stack_dump_size;
518 attr->exclude_callchain_user = 1;
519 } else {
520 pr_info("Cannot use DWARF unwind for function trace event,"
521 " falling back to framepointers.\n");
522 }
523 }
524
525 if (function) {
526 pr_info("Disabling user space callchains for function trace event.\n");
527 attr->exclude_callchain_user = 1;
528 }
529}
530
503/* 531/*
504 * The enable_on_exec/disabled value strategy: 532 * The enable_on_exec/disabled value strategy:
505 * 533 *
@@ -595,17 +623,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
595 attr->mmap_data = track; 623 attr->mmap_data = track;
596 } 624 }
597 625
598 if (opts->call_graph) { 626 if (opts->call_graph_enabled)
599 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 627 perf_evsel__config_callgraph(evsel, opts);
600
601 if (opts->call_graph == CALLCHAIN_DWARF) {
602 perf_evsel__set_sample_bit(evsel, REGS_USER);
603 perf_evsel__set_sample_bit(evsel, STACK_USER);
604 attr->sample_regs_user = PERF_REGS_MASK;
605 attr->sample_stack_user = opts->stack_dump_size;
606 attr->exclude_callchain_user = 1;
607 }
608 }
609 628
610 if (target__has_cpu(&opts->target)) 629 if (target__has_cpu(&opts->target))
611 perf_evsel__set_sample_bit(evsel, CPU); 630 perf_evsel__set_sample_bit(evsel, CPU);
@@ -1004,7 +1023,7 @@ retry_sample_id:
1004 1023
1005 group_fd = get_group_fd(evsel, cpu, thread); 1024 group_fd = get_group_fd(evsel, cpu, thread);
1006retry_open: 1025retry_open:
1007 pr_debug2("perf_event_open: pid %d cpu %d group_fd %d flags %#lx\n", 1026 pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx\n",
1008 pid, cpus->map[cpu], group_fd, flags); 1027 pid, cpus->map[cpu], group_fd, flags);
1009 1028
1010 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, 1029 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
@@ -1013,7 +1032,7 @@ retry_open:
1013 group_fd, flags); 1032 group_fd, flags);
1014 if (FD(evsel, cpu, thread) < 0) { 1033 if (FD(evsel, cpu, thread) < 0) {
1015 err = -errno; 1034 err = -errno;
1016 pr_debug2("perf_event_open failed, error %d\n", 1035 pr_debug2("sys_perf_event_open failed, error %d\n",
1017 err); 1036 err);
1018 goto try_fallback; 1037 goto try_fallback;
1019 } 1038 }
@@ -1220,7 +1239,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1220 memset(data, 0, sizeof(*data)); 1239 memset(data, 0, sizeof(*data));
1221 data->cpu = data->pid = data->tid = -1; 1240 data->cpu = data->pid = data->tid = -1;
1222 data->stream_id = data->id = data->time = -1ULL; 1241 data->stream_id = data->id = data->time = -1ULL;
1223 data->period = 1; 1242 data->period = evsel->attr.sample_period;
1224 data->weight = 0; 1243 data->weight = 0;
1225 1244
1226 if (event->header.type != PERF_RECORD_SAMPLE) { 1245 if (event->header.type != PERF_RECORD_SAMPLE) {
@@ -1396,10 +1415,11 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1396 array++; 1415 array++;
1397 1416
1398 if (data->user_regs.abi) { 1417 if (data->user_regs.abi) {
1399 u64 regs_user = evsel->attr.sample_regs_user; 1418 u64 mask = evsel->attr.sample_regs_user;
1400 1419
1401 sz = hweight_long(regs_user) * sizeof(u64); 1420 sz = hweight_long(mask) * sizeof(u64);
1402 OVERFLOW_CHECK(array, sz, max_size); 1421 OVERFLOW_CHECK(array, sz, max_size);
1422 data->user_regs.mask = mask;
1403 data->user_regs.regs = (u64 *)array; 1423 data->user_regs.regs = (u64 *)array;
1404 array = (void *)array + sz; 1424 array = (void *)array + sz;
1405 } 1425 }
@@ -1451,7 +1471,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1451} 1471}
1452 1472
1453size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, 1473size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
1454 u64 sample_regs_user, u64 read_format) 1474 u64 read_format)
1455{ 1475{
1456 size_t sz, result = sizeof(struct sample_event); 1476 size_t sz, result = sizeof(struct sample_event);
1457 1477
@@ -1517,7 +1537,7 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
1517 if (type & PERF_SAMPLE_REGS_USER) { 1537 if (type & PERF_SAMPLE_REGS_USER) {
1518 if (sample->user_regs.abi) { 1538 if (sample->user_regs.abi) {
1519 result += sizeof(u64); 1539 result += sizeof(u64);
1520 sz = hweight_long(sample_regs_user) * sizeof(u64); 1540 sz = hweight_long(sample->user_regs.mask) * sizeof(u64);
1521 result += sz; 1541 result += sz;
1522 } else { 1542 } else {
1523 result += sizeof(u64); 1543 result += sizeof(u64);
@@ -1546,7 +1566,7 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
1546} 1566}
1547 1567
1548int perf_event__synthesize_sample(union perf_event *event, u64 type, 1568int perf_event__synthesize_sample(union perf_event *event, u64 type,
1549 u64 sample_regs_user, u64 read_format, 1569 u64 read_format,
1550 const struct perf_sample *sample, 1570 const struct perf_sample *sample,
1551 bool swapped) 1571 bool swapped)
1552{ 1572{
@@ -1687,7 +1707,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
1687 if (type & PERF_SAMPLE_REGS_USER) { 1707 if (type & PERF_SAMPLE_REGS_USER) {
1688 if (sample->user_regs.abi) { 1708 if (sample->user_regs.abi) {
1689 *array++ = sample->user_regs.abi; 1709 *array++ = sample->user_regs.abi;
1690 sz = hweight_long(sample_regs_user) * sizeof(u64); 1710 sz = hweight_long(sample->user_regs.mask) * sizeof(u64);
1691 memcpy(array, sample->user_regs.regs, sz); 1711 memcpy(array, sample->user_regs.regs, sz);
1692 array = (void *)array + sz; 1712 array = (void *)array + sz;
1693 } else { 1713 } else {
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index f1b325665aae..0c9926cfb292 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -315,6 +315,24 @@ static inline bool perf_evsel__is_group_event(struct perf_evsel *evsel)
315 return perf_evsel__is_group_leader(evsel) && evsel->nr_members > 1; 315 return perf_evsel__is_group_leader(evsel) && evsel->nr_members > 1;
316} 316}
317 317
318/**
319 * perf_evsel__is_function_event - Return whether given evsel is a function
320 * trace event
321 *
322 * @evsel - evsel selector to be tested
323 *
324 * Return %true if event is function trace event
325 */
326static inline bool perf_evsel__is_function_event(struct perf_evsel *evsel)
327{
328#define FUNCTION_EVENT "ftrace:function"
329
330 return evsel->name &&
331 !strncmp(FUNCTION_EVENT, evsel->name, sizeof(FUNCTION_EVENT));
332
333#undef FUNCTION_EVENT
334}
335
318struct perf_attr_details { 336struct perf_attr_details {
319 bool freq; 337 bool freq;
320 bool verbose; 338 bool verbose;
diff --git a/tools/perf/util/fs.h b/tools/perf/util/fs.h
deleted file mode 100644
index 5e09ce1bab0e..000000000000
--- a/tools/perf/util/fs.h
+++ /dev/null
@@ -1,7 +0,0 @@
1#ifndef __PERF_FS
2#define __PERF_FS
3
4const char *sysfs__mountpoint(void);
5const char *procfs__mountpoint(void);
6
7#endif /* __PERF_FS */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index e4e6249b87d4..f38590d7561b 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -13,13 +13,6 @@ static bool hists__filter_entry_by_thread(struct hists *hists,
13static bool hists__filter_entry_by_symbol(struct hists *hists, 13static bool hists__filter_entry_by_symbol(struct hists *hists,
14 struct hist_entry *he); 14 struct hist_entry *he);
15 15
16enum hist_filter {
17 HIST_FILTER__DSO,
18 HIST_FILTER__THREAD,
19 HIST_FILTER__PARENT,
20 HIST_FILTER__SYMBOL,
21};
22
23struct callchain_param callchain_param = { 16struct callchain_param callchain_param = {
24 .mode = CHAIN_GRAPH_REL, 17 .mode = CHAIN_GRAPH_REL,
25 .min_percent = 0.5, 18 .min_percent = 0.5,
@@ -290,7 +283,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
290 if (he->branch_info) { 283 if (he->branch_info) {
291 /* 284 /*
292 * This branch info is (a part of) allocated from 285 * This branch info is (a part of) allocated from
293 * machine__resolve_bstack() and will be freed after 286 * sample__resolve_bstack() and will be freed after
294 * adding new entries. So we need to save a copy. 287 * adding new entries. So we need to save a copy.
295 */ 288 */
296 he->branch_info = malloc(sizeof(*he->branch_info)); 289 he->branch_info = malloc(sizeof(*he->branch_info));
@@ -369,7 +362,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
369 he_stat__add_period(&he->stat, period, weight); 362 he_stat__add_period(&he->stat, period, weight);
370 363
371 /* 364 /*
372 * This mem info was allocated from machine__resolve_mem 365 * This mem info was allocated from sample__resolve_mem
373 * and will not be used anymore. 366 * and will not be used anymore.
374 */ 367 */
375 zfree(&entry->mem_info); 368 zfree(&entry->mem_info);
@@ -429,7 +422,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
429 .weight = weight, 422 .weight = weight,
430 }, 423 },
431 .parent = sym_parent, 424 .parent = sym_parent,
432 .filtered = symbol__parent_filter(sym_parent), 425 .filtered = symbol__parent_filter(sym_parent) | al->filtered,
433 .hists = hists, 426 .hists = hists,
434 .branch_info = bi, 427 .branch_info = bi,
435 .mem_info = mi, 428 .mem_info = mi,
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index a59743fa3ef7..1f1f513dfe7f 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -14,6 +14,15 @@ struct hist_entry;
14struct addr_location; 14struct addr_location;
15struct symbol; 15struct symbol;
16 16
17enum hist_filter {
18 HIST_FILTER__DSO,
19 HIST_FILTER__THREAD,
20 HIST_FILTER__PARENT,
21 HIST_FILTER__SYMBOL,
22 HIST_FILTER__GUEST,
23 HIST_FILTER__HOST,
24};
25
17/* 26/*
18 * The kernel collects the number of events it couldn't send in a stretch and 27 * The kernel collects the number of events it couldn't send in a stretch and
19 * when possible sends this number in a PERF_RECORD_LOST event. The number of 28 * when possible sends this number in a PERF_RECORD_LOST event. The number of
@@ -132,8 +141,10 @@ struct perf_hpp {
132}; 141};
133 142
134struct perf_hpp_fmt { 143struct perf_hpp_fmt {
135 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp); 144 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
136 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp); 145 struct perf_evsel *evsel);
146 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
147 struct perf_evsel *evsel);
137 int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 148 int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
138 struct hist_entry *he); 149 struct hist_entry *he);
139 int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 150 int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -166,6 +177,20 @@ void perf_hpp__init(void);
166void perf_hpp__column_register(struct perf_hpp_fmt *format); 177void perf_hpp__column_register(struct perf_hpp_fmt *format);
167void perf_hpp__column_enable(unsigned col); 178void perf_hpp__column_enable(unsigned col);
168 179
180typedef u64 (*hpp_field_fn)(struct hist_entry *he);
181typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front);
182typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...);
183
184int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
185 hpp_field_fn get_field, hpp_callback_fn callback,
186 const char *fmt, hpp_snprint_fn print_fn, bool fmt_percent);
187
188static inline void advance_hpp(struct perf_hpp *hpp, int inc)
189{
190 hpp->buf += inc;
191 hpp->size -= inc;
192}
193
169static inline size_t perf_hpp__use_color(void) 194static inline size_t perf_hpp__use_color(void)
170{ 195{
171 return !symbol_conf.field_sep; 196 return !symbol_conf.field_sep;
diff --git a/tools/perf/util/include/linux/hash.h b/tools/perf/util/include/linux/hash.h
deleted file mode 100644
index 201f57397997..000000000000
--- a/tools/perf/util/include/linux/hash.h
+++ /dev/null
@@ -1,5 +0,0 @@
1#include "../../../../include/linux/hash.h"
2
3#ifndef PERF_HASH_H
4#define PERF_HASH_H
5#endif
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
index d8c927c868ee..9844c31b7c2b 100644
--- a/tools/perf/util/include/linux/kernel.h
+++ b/tools/perf/util/include/linux/kernel.h
@@ -94,12 +94,6 @@ static inline int scnprintf(char * buf, size_t size, const char * fmt, ...)
94 return (i >= ssize) ? (ssize - 1) : i; 94 return (i >= ssize) ? (ssize - 1) : i;
95} 95}
96 96
97static inline unsigned long
98simple_strtoul(const char *nptr, char **endptr, int base)
99{
100 return strtoul(nptr, endptr, base);
101}
102
103int eprintf(int level, 97int eprintf(int level,
104 const char *fmt, ...) __attribute__((format(printf, 2, 3))); 98 const char *fmt, ...) __attribute__((format(printf, 2, 3)));
105 99
diff --git a/tools/perf/util/include/linux/list.h b/tools/perf/util/include/linux/list.h
index 1d928a0ce997..bfe0a2afd0d2 100644
--- a/tools/perf/util/include/linux/list.h
+++ b/tools/perf/util/include/linux/list.h
@@ -1,5 +1,4 @@
1#include <linux/kernel.h> 1#include <linux/kernel.h>
2#include <linux/prefetch.h>
3 2
4#include "../../../../include/linux/list.h" 3#include "../../../../include/linux/list.h"
5 4
diff --git a/tools/perf/util/include/linux/prefetch.h b/tools/perf/util/include/linux/prefetch.h
deleted file mode 100644
index 7841e485d8c3..000000000000
--- a/tools/perf/util/include/linux/prefetch.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef PERF_LINUX_PREFETCH_H
2#define PERF_LINUX_PREFETCH_H
3
4static inline void prefetch(void *a __attribute__((unused))) { }
5
6#endif
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 620a1983b76b..27c2a5efe450 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -327,9 +327,10 @@ struct thread *machine__findnew_thread(struct machine *machine, pid_t pid,
327 return __machine__findnew_thread(machine, pid, tid, true); 327 return __machine__findnew_thread(machine, pid, tid, true);
328} 328}
329 329
330struct thread *machine__find_thread(struct machine *machine, pid_t tid) 330struct thread *machine__find_thread(struct machine *machine, pid_t pid,
331 pid_t tid)
331{ 332{
332 return __machine__findnew_thread(machine, 0, tid, false); 333 return __machine__findnew_thread(machine, pid, tid, false);
333} 334}
334 335
335int machine__process_comm_event(struct machine *machine, union perf_event *event, 336int machine__process_comm_event(struct machine *machine, union perf_event *event,
@@ -716,7 +717,7 @@ static char *get_kernel_version(const char *root_dir)
716} 717}
717 718
718static int map_groups__set_modules_path_dir(struct map_groups *mg, 719static int map_groups__set_modules_path_dir(struct map_groups *mg,
719 const char *dir_name) 720 const char *dir_name, int depth)
720{ 721{
721 struct dirent *dent; 722 struct dirent *dent;
722 DIR *dir = opendir(dir_name); 723 DIR *dir = opendir(dir_name);
@@ -741,7 +742,15 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
741 !strcmp(dent->d_name, "..")) 742 !strcmp(dent->d_name, ".."))
742 continue; 743 continue;
743 744
744 ret = map_groups__set_modules_path_dir(mg, path); 745 /* Do not follow top-level source and build symlinks */
746 if (depth == 0) {
747 if (!strcmp(dent->d_name, "source") ||
748 !strcmp(dent->d_name, "build"))
749 continue;
750 }
751
752 ret = map_groups__set_modules_path_dir(mg, path,
753 depth + 1);
745 if (ret < 0) 754 if (ret < 0)
746 goto out; 755 goto out;
747 } else { 756 } else {
@@ -785,11 +794,11 @@ static int machine__set_modules_path(struct machine *machine)
785 if (!version) 794 if (!version)
786 return -1; 795 return -1;
787 796
788 snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", 797 snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s",
789 machine->root_dir, version); 798 machine->root_dir, version);
790 free(version); 799 free(version);
791 800
792 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); 801 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0);
793} 802}
794 803
795static int machine__create_module(void *arg, const char *name, u64 start) 804static int machine__create_module(void *arg, const char *name, u64 start)
@@ -1026,7 +1035,7 @@ int machine__process_mmap2_event(struct machine *machine,
1026 } 1035 }
1027 1036
1028 thread = machine__findnew_thread(machine, event->mmap2.pid, 1037 thread = machine__findnew_thread(machine, event->mmap2.pid,
1029 event->mmap2.pid); 1038 event->mmap2.tid);
1030 if (thread == NULL) 1039 if (thread == NULL)
1031 goto out_problem; 1040 goto out_problem;
1032 1041
@@ -1074,7 +1083,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
1074 } 1083 }
1075 1084
1076 thread = machine__findnew_thread(machine, event->mmap.pid, 1085 thread = machine__findnew_thread(machine, event->mmap.pid,
1077 event->mmap.pid); 1086 event->mmap.tid);
1078 if (thread == NULL) 1087 if (thread == NULL)
1079 goto out_problem; 1088 goto out_problem;
1080 1089
@@ -1114,7 +1123,9 @@ static void machine__remove_thread(struct machine *machine, struct thread *th)
1114int machine__process_fork_event(struct machine *machine, union perf_event *event, 1123int machine__process_fork_event(struct machine *machine, union perf_event *event,
1115 struct perf_sample *sample) 1124 struct perf_sample *sample)
1116{ 1125{
1117 struct thread *thread = machine__find_thread(machine, event->fork.tid); 1126 struct thread *thread = machine__find_thread(machine,
1127 event->fork.pid,
1128 event->fork.tid);
1118 struct thread *parent = machine__findnew_thread(machine, 1129 struct thread *parent = machine__findnew_thread(machine,
1119 event->fork.ppid, 1130 event->fork.ppid,
1120 event->fork.ptid); 1131 event->fork.ptid);
@@ -1140,7 +1151,9 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1140int machine__process_exit_event(struct machine *machine, union perf_event *event, 1151int machine__process_exit_event(struct machine *machine, union perf_event *event,
1141 struct perf_sample *sample __maybe_unused) 1152 struct perf_sample *sample __maybe_unused)
1142{ 1153{
1143 struct thread *thread = machine__find_thread(machine, event->fork.tid); 1154 struct thread *thread = machine__find_thread(machine,
1155 event->fork.pid,
1156 event->fork.tid);
1144 1157
1145 if (dump_trace) 1158 if (dump_trace)
1146 perf_event__fprintf_task(event, stdout); 1159 perf_event__fprintf_task(event, stdout);
@@ -1184,39 +1197,22 @@ static bool symbol__match_regex(struct symbol *sym, regex_t *regex)
1184 return 0; 1197 return 0;
1185} 1198}
1186 1199
1187static const u8 cpumodes[] = {
1188 PERF_RECORD_MISC_USER,
1189 PERF_RECORD_MISC_KERNEL,
1190 PERF_RECORD_MISC_GUEST_USER,
1191 PERF_RECORD_MISC_GUEST_KERNEL
1192};
1193#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))
1194
1195static void ip__resolve_ams(struct machine *machine, struct thread *thread, 1200static void ip__resolve_ams(struct machine *machine, struct thread *thread,
1196 struct addr_map_symbol *ams, 1201 struct addr_map_symbol *ams,
1197 u64 ip) 1202 u64 ip)
1198{ 1203{
1199 struct addr_location al; 1204 struct addr_location al;
1200 size_t i;
1201 u8 m;
1202 1205
1203 memset(&al, 0, sizeof(al)); 1206 memset(&al, 0, sizeof(al));
1207 /*
1208 * We cannot use the header.misc hint to determine whether a
1209 * branch stack address is user, kernel, guest, hypervisor.
1210 * Branches may straddle the kernel/user/hypervisor boundaries.
1211 * Thus, we have to try consecutively until we find a match
1212 * or else, the symbol is unknown
1213 */
1214 thread__find_cpumode_addr_location(thread, machine, MAP__FUNCTION, ip, &al);
1204 1215
1205 for (i = 0; i < NCPUMODES; i++) {
1206 m = cpumodes[i];
1207 /*
1208 * We cannot use the header.misc hint to determine whether a
1209 * branch stack address is user, kernel, guest, hypervisor.
1210 * Branches may straddle the kernel/user/hypervisor boundaries.
1211 * Thus, we have to try consecutively until we find a match
1212 * or else, the symbol is unknown
1213 */
1214 thread__find_addr_location(thread, machine, m, MAP__FUNCTION,
1215 ip, &al);
1216 if (al.map)
1217 goto found;
1218 }
1219found:
1220 ams->addr = ip; 1216 ams->addr = ip;
1221 ams->al_addr = al.addr; 1217 ams->al_addr = al.addr;
1222 ams->sym = al.sym; 1218 ams->sym = al.sym;
@@ -1238,37 +1234,35 @@ static void ip__resolve_data(struct machine *machine, struct thread *thread,
1238 ams->map = al.map; 1234 ams->map = al.map;
1239} 1235}
1240 1236
1241struct mem_info *machine__resolve_mem(struct machine *machine, 1237struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1242 struct thread *thr, 1238 struct addr_location *al)
1243 struct perf_sample *sample,
1244 u8 cpumode)
1245{ 1239{
1246 struct mem_info *mi = zalloc(sizeof(*mi)); 1240 struct mem_info *mi = zalloc(sizeof(*mi));
1247 1241
1248 if (!mi) 1242 if (!mi)
1249 return NULL; 1243 return NULL;
1250 1244
1251 ip__resolve_ams(machine, thr, &mi->iaddr, sample->ip); 1245 ip__resolve_ams(al->machine, al->thread, &mi->iaddr, sample->ip);
1252 ip__resolve_data(machine, thr, cpumode, &mi->daddr, sample->addr); 1246 ip__resolve_data(al->machine, al->thread, al->cpumode,
1247 &mi->daddr, sample->addr);
1253 mi->data_src.val = sample->data_src; 1248 mi->data_src.val = sample->data_src;
1254 1249
1255 return mi; 1250 return mi;
1256} 1251}
1257 1252
1258struct branch_info *machine__resolve_bstack(struct machine *machine, 1253struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
1259 struct thread *thr, 1254 struct addr_location *al)
1260 struct branch_stack *bs)
1261{ 1255{
1262 struct branch_info *bi;
1263 unsigned int i; 1256 unsigned int i;
1257 const struct branch_stack *bs = sample->branch_stack;
1258 struct branch_info *bi = calloc(bs->nr, sizeof(struct branch_info));
1264 1259
1265 bi = calloc(bs->nr, sizeof(struct branch_info));
1266 if (!bi) 1260 if (!bi)
1267 return NULL; 1261 return NULL;
1268 1262
1269 for (i = 0; i < bs->nr; i++) { 1263 for (i = 0; i < bs->nr; i++) {
1270 ip__resolve_ams(machine, thr, &bi[i].to, bs->entries[i].to); 1264 ip__resolve_ams(al->machine, al->thread, &bi[i].to, bs->entries[i].to);
1271 ip__resolve_ams(machine, thr, &bi[i].from, bs->entries[i].from); 1265 ip__resolve_ams(al->machine, al->thread, &bi[i].from, bs->entries[i].from);
1272 bi[i].flags = bs->entries[i].flags; 1266 bi[i].flags = bs->entries[i].flags;
1273 } 1267 }
1274 return bi; 1268 return bi;
@@ -1326,7 +1320,7 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1326 continue; 1320 continue;
1327 } 1321 }
1328 1322
1329 al.filtered = false; 1323 al.filtered = 0;
1330 thread__find_addr_location(thread, machine, cpumode, 1324 thread__find_addr_location(thread, machine, cpumode,
1331 MAP__FUNCTION, ip, &al); 1325 MAP__FUNCTION, ip, &al);
1332 if (al.sym != NULL) { 1326 if (al.sym != NULL) {
@@ -1385,8 +1379,7 @@ int machine__resolve_callchain(struct machine *machine,
1385 return 0; 1379 return 0;
1386 1380
1387 return unwind__get_entries(unwind_entry, &callchain_cursor, machine, 1381 return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
1388 thread, evsel->attr.sample_regs_user, 1382 thread, sample, max_stack);
1389 sample, max_stack);
1390 1383
1391} 1384}
1392 1385
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index f77e91e483dc..c8c74a119398 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -41,7 +41,8 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)
41 return machine->vmlinux_maps[type]; 41 return machine->vmlinux_maps[type];
42} 42}
43 43
44struct thread *machine__find_thread(struct machine *machine, pid_t tid); 44struct thread *machine__find_thread(struct machine *machine, pid_t pid,
45 pid_t tid);
45 46
46int machine__process_comm_event(struct machine *machine, union perf_event *event, 47int machine__process_comm_event(struct machine *machine, union perf_event *event,
47 struct perf_sample *sample); 48 struct perf_sample *sample);
@@ -91,12 +92,10 @@ void machine__delete_dead_threads(struct machine *machine);
91void machine__delete_threads(struct machine *machine); 92void machine__delete_threads(struct machine *machine);
92void machine__delete(struct machine *machine); 93void machine__delete(struct machine *machine);
93 94
94struct branch_info *machine__resolve_bstack(struct machine *machine, 95struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
95 struct thread *thread, 96 struct addr_location *al);
96 struct branch_stack *bs); 97struct mem_info *sample__resolve_mem(struct perf_sample *sample,
97struct mem_info *machine__resolve_mem(struct machine *machine, 98 struct addr_location *al);
98 struct thread *thread,
99 struct perf_sample *sample, u8 cpumode);
100int machine__resolve_callchain(struct machine *machine, 99int machine__resolve_callchain(struct machine *machine,
101 struct perf_evsel *evsel, 100 struct perf_evsel *evsel,
102 struct thread *thread, 101 struct thread *thread,
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 257e513205ce..f00f058afb3b 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -90,6 +90,16 @@ u64 map__objdump_2mem(struct map *map, u64 ip);
90 90
91struct symbol; 91struct symbol;
92 92
93/* map__for_each_symbol - iterate over the symbols in the given map
94 *
95 * @map: the 'struct map *' in which symbols itereated
96 * @pos: the 'struct symbol *' to use as a loop cursor
97 * @n: the 'struct rb_node *' to use as a temporary storage
98 * Note: caller must ensure map->dso is not NULL (map is loaded).
99 */
100#define map__for_each_symbol(map, pos, n) \
101 dso__for_each_symbol(map->dso, pos, n, map->type)
102
93typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); 103typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
94 104
95void map__init(struct map *map, enum map_type type, 105void map__init(struct map *map, enum map_type type,
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index d22e3f8017dc..bf48092983c6 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -407,7 +407,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
407 if (internal_help && !strcmp(arg + 2, "help")) 407 if (internal_help && !strcmp(arg + 2, "help"))
408 return usage_with_options_internal(usagestr, options, 0); 408 return usage_with_options_internal(usagestr, options, 0);
409 if (!strcmp(arg + 2, "list-opts")) 409 if (!strcmp(arg + 2, "list-opts"))
410 return PARSE_OPT_LIST; 410 return PARSE_OPT_LIST_OPTS;
411 if (!strcmp(arg + 2, "list-cmds"))
412 return PARSE_OPT_LIST_SUBCMDS;
411 switch (parse_long_opt(ctx, arg + 2, options)) { 413 switch (parse_long_opt(ctx, arg + 2, options)) {
412 case -1: 414 case -1:
413 return parse_options_usage(usagestr, options, arg + 2, 0); 415 return parse_options_usage(usagestr, options, arg + 2, 0);
@@ -433,25 +435,45 @@ int parse_options_end(struct parse_opt_ctx_t *ctx)
433 return ctx->cpidx + ctx->argc; 435 return ctx->cpidx + ctx->argc;
434} 436}
435 437
436int parse_options(int argc, const char **argv, const struct option *options, 438int parse_options_subcommand(int argc, const char **argv, const struct option *options,
437 const char * const usagestr[], int flags) 439 const char *const subcommands[], const char *usagestr[], int flags)
438{ 440{
439 struct parse_opt_ctx_t ctx; 441 struct parse_opt_ctx_t ctx;
440 442
441 perf_header__set_cmdline(argc, argv); 443 perf_header__set_cmdline(argc, argv);
442 444
445 /* build usage string if it's not provided */
446 if (subcommands && !usagestr[0]) {
447 struct strbuf buf = STRBUF_INIT;
448
449 strbuf_addf(&buf, "perf %s [<options>] {", argv[0]);
450 for (int i = 0; subcommands[i]; i++) {
451 if (i)
452 strbuf_addstr(&buf, "|");
453 strbuf_addstr(&buf, subcommands[i]);
454 }
455 strbuf_addstr(&buf, "}");
456
457 usagestr[0] = strdup(buf.buf);
458 strbuf_release(&buf);
459 }
460
443 parse_options_start(&ctx, argc, argv, flags); 461 parse_options_start(&ctx, argc, argv, flags);
444 switch (parse_options_step(&ctx, options, usagestr)) { 462 switch (parse_options_step(&ctx, options, usagestr)) {
445 case PARSE_OPT_HELP: 463 case PARSE_OPT_HELP:
446 exit(129); 464 exit(129);
447 case PARSE_OPT_DONE: 465 case PARSE_OPT_DONE:
448 break; 466 break;
449 case PARSE_OPT_LIST: 467 case PARSE_OPT_LIST_OPTS:
450 while (options->type != OPTION_END) { 468 while (options->type != OPTION_END) {
451 printf("--%s ", options->long_name); 469 printf("--%s ", options->long_name);
452 options++; 470 options++;
453 } 471 }
454 exit(130); 472 exit(130);
473 case PARSE_OPT_LIST_SUBCMDS:
474 for (int i = 0; subcommands[i]; i++)
475 printf("%s ", subcommands[i]);
476 exit(130);
455 default: /* PARSE_OPT_UNKNOWN */ 477 default: /* PARSE_OPT_UNKNOWN */
456 if (ctx.argv[0][1] == '-') { 478 if (ctx.argv[0][1] == '-') {
457 error("unknown option `%s'", ctx.argv[0] + 2); 479 error("unknown option `%s'", ctx.argv[0] + 2);
@@ -464,6 +486,13 @@ int parse_options(int argc, const char **argv, const struct option *options,
464 return parse_options_end(&ctx); 486 return parse_options_end(&ctx);
465} 487}
466 488
489int parse_options(int argc, const char **argv, const struct option *options,
490 const char * const usagestr[], int flags)
491{
492 return parse_options_subcommand(argc, argv, options, NULL,
493 (const char **) usagestr, flags);
494}
495
467#define USAGE_OPTS_WIDTH 24 496#define USAGE_OPTS_WIDTH 24
468#define USAGE_GAP 2 497#define USAGE_GAP 2
469 498
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index cbf0149cf221..d8dac8ac5f37 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -140,6 +140,11 @@ extern int parse_options(int argc, const char **argv,
140 const struct option *options, 140 const struct option *options,
141 const char * const usagestr[], int flags); 141 const char * const usagestr[], int flags);
142 142
143extern int parse_options_subcommand(int argc, const char **argv,
144 const struct option *options,
145 const char *const subcommands[],
146 const char *usagestr[], int flags);
147
143extern NORETURN void usage_with_options(const char * const *usagestr, 148extern NORETURN void usage_with_options(const char * const *usagestr,
144 const struct option *options); 149 const struct option *options);
145 150
@@ -148,7 +153,8 @@ extern NORETURN void usage_with_options(const char * const *usagestr,
148enum { 153enum {
149 PARSE_OPT_HELP = -1, 154 PARSE_OPT_HELP = -1,
150 PARSE_OPT_DONE, 155 PARSE_OPT_DONE,
151 PARSE_OPT_LIST, 156 PARSE_OPT_LIST_OPTS,
157 PARSE_OPT_LIST_SUBCMDS,
152 PARSE_OPT_UNKNOWN, 158 PARSE_OPT_UNKNOWN,
153}; 159};
154 160
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
new file mode 100644
index 000000000000..a3539ef30b15
--- /dev/null
+++ b/tools/perf/util/perf_regs.c
@@ -0,0 +1,19 @@
1#include <errno.h>
2#include "perf_regs.h"
3
4int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
5{
6 int i, idx = 0;
7 u64 mask = regs->mask;
8
9 if (!(mask & (1 << id)))
10 return -EINVAL;
11
12 for (i = 0; i < id; i++) {
13 if (mask & (1 << i))
14 idx++;
15 }
16
17 *valp = regs->regs[idx];
18 return 0;
19}
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index a3d42cd74919..d6e8b6a8d7f3 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -1,8 +1,14 @@
1#ifndef __PERF_REGS_H 1#ifndef __PERF_REGS_H
2#define __PERF_REGS_H 2#define __PERF_REGS_H
3 3
4#include "types.h"
5#include "event.h"
6
4#ifdef HAVE_PERF_REGS_SUPPORT 7#ifdef HAVE_PERF_REGS_SUPPORT
5#include <perf_regs.h> 8#include <perf_regs.h>
9
10int perf_reg_value(u64 *valp, struct regs_dump *regs, int id);
11
6#else 12#else
7#define PERF_REGS_MASK 0 13#define PERF_REGS_MASK 0
8 14
@@ -10,5 +16,12 @@ static inline const char *perf_reg_name(int id __maybe_unused)
10{ 16{
11 return NULL; 17 return NULL;
12} 18}
19
20static inline int perf_reg_value(u64 *valp __maybe_unused,
21 struct regs_dump *regs __maybe_unused,
22 int id __maybe_unused)
23{
24 return 0;
25}
13#endif /* HAVE_PERF_REGS_SUPPORT */ 26#endif /* HAVE_PERF_REGS_SUPPORT */
14#endif /* __PERF_REGS_H */ 27#endif /* __PERF_REGS_H */
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index b752ecb40d86..00a7dcb2f55c 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -3,7 +3,7 @@
3#include <unistd.h> 3#include <unistd.h>
4#include <stdio.h> 4#include <stdio.h>
5#include <dirent.h> 5#include <dirent.h>
6#include "fs.h" 6#include <api/fs/fs.h>
7#include <locale.h> 7#include <locale.h>
8#include "util.h" 8#include "util.h"
9#include "pmu.h" 9#include "pmu.h"
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index d8b048c20cde..0d1542f33d87 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -70,34 +70,32 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)
70} 70}
71 71
72static char *synthesize_perf_probe_point(struct perf_probe_point *pp); 72static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
73static int convert_name_to_addr(struct perf_probe_event *pev,
74 const char *exec);
75static void clear_probe_trace_event(struct probe_trace_event *tev); 73static void clear_probe_trace_event(struct probe_trace_event *tev);
76static struct machine machine; 74static struct machine *host_machine;
77 75
78/* Initialize symbol maps and path of vmlinux/modules */ 76/* Initialize symbol maps and path of vmlinux/modules */
79static int init_vmlinux(void) 77static int init_symbol_maps(bool user_only)
80{ 78{
81 int ret; 79 int ret;
82 80
83 symbol_conf.sort_by_name = true; 81 symbol_conf.sort_by_name = true;
84 if (symbol_conf.vmlinux_name == NULL)
85 symbol_conf.try_vmlinux_path = true;
86 else
87 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
88 ret = symbol__init(); 82 ret = symbol__init();
89 if (ret < 0) { 83 if (ret < 0) {
90 pr_debug("Failed to init symbol map.\n"); 84 pr_debug("Failed to init symbol map.\n");
91 goto out; 85 goto out;
92 } 86 }
93 87
94 ret = machine__init(&machine, "", HOST_KERNEL_ID); 88 if (host_machine || user_only) /* already initialized */
95 if (ret < 0) 89 return 0;
96 goto out;
97 90
98 if (machine__create_kernel_maps(&machine) < 0) { 91 if (symbol_conf.vmlinux_name)
99 pr_debug("machine__create_kernel_maps() failed.\n"); 92 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
100 goto out; 93
94 host_machine = machine__new_host();
95 if (!host_machine) {
96 pr_debug("machine__new_host() failed.\n");
97 symbol__exit();
98 ret = -1;
101 } 99 }
102out: 100out:
103 if (ret < 0) 101 if (ret < 0)
@@ -105,21 +103,66 @@ out:
105 return ret; 103 return ret;
106} 104}
107 105
106static void exit_symbol_maps(void)
107{
108 if (host_machine) {
109 machine__delete(host_machine);
110 host_machine = NULL;
111 }
112 symbol__exit();
113}
114
108static struct symbol *__find_kernel_function_by_name(const char *name, 115static struct symbol *__find_kernel_function_by_name(const char *name,
109 struct map **mapp) 116 struct map **mapp)
110{ 117{
111 return machine__find_kernel_function_by_name(&machine, name, mapp, 118 return machine__find_kernel_function_by_name(host_machine, name, mapp,
112 NULL); 119 NULL);
113} 120}
114 121
122static struct symbol *__find_kernel_function(u64 addr, struct map **mapp)
123{
124 return machine__find_kernel_function(host_machine, addr, mapp, NULL);
125}
126
127static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
128{
129 /* kmap->ref_reloc_sym should be set if host_machine is initialized */
130 struct kmap *kmap;
131
132 if (map__load(host_machine->vmlinux_maps[MAP__FUNCTION], NULL) < 0)
133 return NULL;
134
135 kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]);
136 return kmap->ref_reloc_sym;
137}
138
139static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc)
140{
141 struct ref_reloc_sym *reloc_sym;
142 struct symbol *sym;
143 struct map *map;
144
145 /* ref_reloc_sym is just a label. Need a special fix*/
146 reloc_sym = kernel_get_ref_reloc_sym();
147 if (reloc_sym && strcmp(name, reloc_sym->name) == 0)
148 return (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr;
149 else {
150 sym = __find_kernel_function_by_name(name, &map);
151 if (sym)
152 return map->unmap_ip(map, sym->start) -
153 (reloc) ? 0 : map->reloc;
154 }
155 return 0;
156}
157
115static struct map *kernel_get_module_map(const char *module) 158static struct map *kernel_get_module_map(const char *module)
116{ 159{
117 struct rb_node *nd; 160 struct rb_node *nd;
118 struct map_groups *grp = &machine.kmaps; 161 struct map_groups *grp = &host_machine->kmaps;
119 162
120 /* A file path -- this is an offline module */ 163 /* A file path -- this is an offline module */
121 if (module && strchr(module, '/')) 164 if (module && strchr(module, '/'))
122 return machine__new_module(&machine, 0, module); 165 return machine__new_module(host_machine, 0, module);
123 166
124 if (!module) 167 if (!module)
125 module = "kernel"; 168 module = "kernel";
@@ -141,7 +184,7 @@ static struct dso *kernel_get_module_dso(const char *module)
141 const char *vmlinux_name; 184 const char *vmlinux_name;
142 185
143 if (module) { 186 if (module) {
144 list_for_each_entry(dso, &machine.kernel_dsos, node) { 187 list_for_each_entry(dso, &host_machine->kernel_dsos, node) {
145 if (strncmp(dso->short_name + 1, module, 188 if (strncmp(dso->short_name + 1, module,
146 dso->short_name_len - 2) == 0) 189 dso->short_name_len - 2) == 0)
147 goto found; 190 goto found;
@@ -150,7 +193,7 @@ static struct dso *kernel_get_module_dso(const char *module)
150 return NULL; 193 return NULL;
151 } 194 }
152 195
153 map = machine.vmlinux_maps[MAP__FUNCTION]; 196 map = host_machine->vmlinux_maps[MAP__FUNCTION];
154 dso = map->dso; 197 dso = map->dso;
155 198
156 vmlinux_name = symbol_conf.vmlinux_name; 199 vmlinux_name = symbol_conf.vmlinux_name;
@@ -173,20 +216,6 @@ const char *kernel_get_module_path(const char *module)
173 return (dso) ? dso->long_name : NULL; 216 return (dso) ? dso->long_name : NULL;
174} 217}
175 218
176static int init_user_exec(void)
177{
178 int ret = 0;
179
180 symbol_conf.try_vmlinux_path = false;
181 symbol_conf.sort_by_name = true;
182 ret = symbol__init();
183
184 if (ret < 0)
185 pr_debug("Failed to init symbol map.\n");
186
187 return ret;
188}
189
190static int convert_exec_to_group(const char *exec, char **result) 219static int convert_exec_to_group(const char *exec, char **result)
191{ 220{
192 char *ptr1, *ptr2, *exec_copy; 221 char *ptr1, *ptr2, *exec_copy;
@@ -218,32 +247,23 @@ out:
218 return ret; 247 return ret;
219} 248}
220 249
221static int convert_to_perf_probe_point(struct probe_trace_point *tp, 250static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
222 struct perf_probe_point *pp)
223{ 251{
224 pp->function = strdup(tp->symbol); 252 int i;
225
226 if (pp->function == NULL)
227 return -ENOMEM;
228
229 pp->offset = tp->offset;
230 pp->retprobe = tp->retprobe;
231 253
232 return 0; 254 for (i = 0; i < ntevs; i++)
255 clear_probe_trace_event(tevs + i);
233} 256}
234 257
235#ifdef HAVE_DWARF_SUPPORT 258#ifdef HAVE_DWARF_SUPPORT
259
236/* Open new debuginfo of given module */ 260/* Open new debuginfo of given module */
237static struct debuginfo *open_debuginfo(const char *module) 261static struct debuginfo *open_debuginfo(const char *module)
238{ 262{
239 const char *path; 263 const char *path = module;
240 264
241 /* A file path -- this is an offline module */ 265 if (!module || !strchr(module, '/')) {
242 if (module && strchr(module, '/'))
243 path = module;
244 else {
245 path = kernel_get_module_path(module); 266 path = kernel_get_module_path(module);
246
247 if (!path) { 267 if (!path) {
248 pr_err("Failed to find path of %s module.\n", 268 pr_err("Failed to find path of %s module.\n",
249 module ?: "kernel"); 269 module ?: "kernel");
@@ -253,46 +273,6 @@ static struct debuginfo *open_debuginfo(const char *module)
253 return debuginfo__new(path); 273 return debuginfo__new(path);
254} 274}
255 275
256/*
257 * Convert trace point to probe point with debuginfo
258 * Currently only handles kprobes.
259 */
260static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
261 struct perf_probe_point *pp)
262{
263 struct symbol *sym;
264 struct map *map;
265 u64 addr;
266 int ret = -ENOENT;
267 struct debuginfo *dinfo;
268
269 sym = __find_kernel_function_by_name(tp->symbol, &map);
270 if (sym) {
271 addr = map->unmap_ip(map, sym->start + tp->offset);
272 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
273 tp->offset, addr);
274
275 dinfo = debuginfo__new_online_kernel(addr);
276 if (dinfo) {
277 ret = debuginfo__find_probe_point(dinfo,
278 (unsigned long)addr, pp);
279 debuginfo__delete(dinfo);
280 } else {
281 pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n",
282 addr);
283 ret = -ENOENT;
284 }
285 }
286 if (ret <= 0) {
287 pr_debug("Failed to find corresponding probes from "
288 "debuginfo. Use kprobe event information.\n");
289 return convert_to_perf_probe_point(tp, pp);
290 }
291 pp->retprobe = tp->retprobe;
292
293 return 0;
294}
295
296static int get_text_start_address(const char *exec, unsigned long *address) 276static int get_text_start_address(const char *exec, unsigned long *address)
297{ 277{
298 Elf *elf; 278 Elf *elf;
@@ -321,12 +301,62 @@ out:
321 return ret; 301 return ret;
322} 302}
323 303
304/*
305 * Convert trace point to probe point with debuginfo
306 */
307static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
308 struct perf_probe_point *pp,
309 bool is_kprobe)
310{
311 struct debuginfo *dinfo = NULL;
312 unsigned long stext = 0;
313 u64 addr = tp->address;
314 int ret = -ENOENT;
315
316 /* convert the address to dwarf address */
317 if (!is_kprobe) {
318 if (!addr) {
319 ret = -EINVAL;
320 goto error;
321 }
322 ret = get_text_start_address(tp->module, &stext);
323 if (ret < 0)
324 goto error;
325 addr += stext;
326 } else {
327 addr = kernel_get_symbol_address_by_name(tp->symbol, false);
328 if (addr == 0)
329 goto error;
330 addr += tp->offset;
331 }
332
333 pr_debug("try to find information at %" PRIx64 " in %s\n", addr,
334 tp->module ? : "kernel");
335
336 dinfo = open_debuginfo(tp->module);
337 if (dinfo) {
338 ret = debuginfo__find_probe_point(dinfo,
339 (unsigned long)addr, pp);
340 debuginfo__delete(dinfo);
341 } else {
342 pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n", addr);
343 ret = -ENOENT;
344 }
345
346 if (ret > 0) {
347 pp->retprobe = tp->retprobe;
348 return 0;
349 }
350error:
351 pr_debug("Failed to find corresponding probes from debuginfo.\n");
352 return ret ? : -ENOENT;
353}
354
324static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, 355static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
325 int ntevs, const char *exec) 356 int ntevs, const char *exec)
326{ 357{
327 int i, ret = 0; 358 int i, ret = 0;
328 unsigned long offset, stext = 0; 359 unsigned long stext = 0;
329 char buf[32];
330 360
331 if (!exec) 361 if (!exec)
332 return 0; 362 return 0;
@@ -337,15 +367,9 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
337 367
338 for (i = 0; i < ntevs && ret >= 0; i++) { 368 for (i = 0; i < ntevs && ret >= 0; i++) {
339 /* point.address is the addres of point.symbol + point.offset */ 369 /* point.address is the addres of point.symbol + point.offset */
340 offset = tevs[i].point.address - stext; 370 tevs[i].point.address -= stext;
341 tevs[i].point.offset = 0;
342 zfree(&tevs[i].point.symbol);
343 ret = e_snprintf(buf, 32, "0x%lx", offset);
344 if (ret < 0)
345 break;
346 tevs[i].point.module = strdup(exec); 371 tevs[i].point.module = strdup(exec);
347 tevs[i].point.symbol = strdup(buf); 372 if (!tevs[i].point.module) {
348 if (!tevs[i].point.symbol || !tevs[i].point.module) {
349 ret = -ENOMEM; 373 ret = -ENOMEM;
350 break; 374 break;
351 } 375 }
@@ -388,12 +412,40 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
388 return ret; 412 return ret;
389} 413}
390 414
391static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) 415/* Post processing the probe events */
416static int post_process_probe_trace_events(struct probe_trace_event *tevs,
417 int ntevs, const char *module,
418 bool uprobe)
392{ 419{
420 struct ref_reloc_sym *reloc_sym;
421 char *tmp;
393 int i; 422 int i;
394 423
395 for (i = 0; i < ntevs; i++) 424 if (uprobe)
396 clear_probe_trace_event(tevs + i); 425 return add_exec_to_probe_trace_events(tevs, ntevs, module);
426
427 /* Note that currently ref_reloc_sym based probe is not for drivers */
428 if (module)
429 return add_module_to_probe_trace_events(tevs, ntevs, module);
430
431 reloc_sym = kernel_get_ref_reloc_sym();
432 if (!reloc_sym) {
433 pr_warning("Relocated base symbol is not found!\n");
434 return -EINVAL;
435 }
436
437 for (i = 0; i < ntevs; i++) {
438 if (tevs[i].point.address) {
439 tmp = strdup(reloc_sym->name);
440 if (!tmp)
441 return -ENOMEM;
442 free(tevs[i].point.symbol);
443 tevs[i].point.symbol = tmp;
444 tevs[i].point.offset = tevs[i].point.address -
445 reloc_sym->unrelocated_addr;
446 }
447 }
448 return 0;
397} 449}
398 450
399/* Try to find perf_probe_event with debuginfo */ 451/* Try to find perf_probe_event with debuginfo */
@@ -416,21 +468,16 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
416 return 0; 468 return 0;
417 } 469 }
418 470
471 pr_debug("Try to find probe point from debuginfo.\n");
419 /* Searching trace events corresponding to a probe event */ 472 /* Searching trace events corresponding to a probe event */
420 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs); 473 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
421 474
422 debuginfo__delete(dinfo); 475 debuginfo__delete(dinfo);
423 476
424 if (ntevs > 0) { /* Succeeded to find trace events */ 477 if (ntevs > 0) { /* Succeeded to find trace events */
425 pr_debug("find %d probe_trace_events.\n", ntevs); 478 pr_debug("Found %d probe_trace_events.\n", ntevs);
426 if (target) { 479 ret = post_process_probe_trace_events(*tevs, ntevs,
427 if (pev->uprobes) 480 target, pev->uprobes);
428 ret = add_exec_to_probe_trace_events(*tevs,
429 ntevs, target);
430 else
431 ret = add_module_to_probe_trace_events(*tevs,
432 ntevs, target);
433 }
434 if (ret < 0) { 481 if (ret < 0) {
435 clear_probe_trace_events(*tevs, ntevs); 482 clear_probe_trace_events(*tevs, ntevs);
436 zfree(tevs); 483 zfree(tevs);
@@ -563,20 +610,16 @@ static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
563 * Show line-range always requires debuginfo to find source file and 610 * Show line-range always requires debuginfo to find source file and
564 * line number. 611 * line number.
565 */ 612 */
566int show_line_range(struct line_range *lr, const char *module) 613static int __show_line_range(struct line_range *lr, const char *module)
567{ 614{
568 int l = 1; 615 int l = 1;
569 struct line_node *ln; 616 struct int_node *ln;
570 struct debuginfo *dinfo; 617 struct debuginfo *dinfo;
571 FILE *fp; 618 FILE *fp;
572 int ret; 619 int ret;
573 char *tmp; 620 char *tmp;
574 621
575 /* Search a line range */ 622 /* Search a line range */
576 ret = init_vmlinux();
577 if (ret < 0)
578 return ret;
579
580 dinfo = open_debuginfo(module); 623 dinfo = open_debuginfo(module);
581 if (!dinfo) { 624 if (!dinfo) {
582 pr_warning("Failed to open debuginfo file.\n"); 625 pr_warning("Failed to open debuginfo file.\n");
@@ -623,8 +666,8 @@ int show_line_range(struct line_range *lr, const char *module)
623 goto end; 666 goto end;
624 } 667 }
625 668
626 list_for_each_entry(ln, &lr->line_list, list) { 669 intlist__for_each(ln, lr->line_list) {
627 for (; ln->line > l; l++) { 670 for (; ln->i > l; l++) {
628 ret = show_one_line(fp, l - lr->offset); 671 ret = show_one_line(fp, l - lr->offset);
629 if (ret < 0) 672 if (ret < 0)
630 goto end; 673 goto end;
@@ -646,6 +689,19 @@ end:
646 return ret; 689 return ret;
647} 690}
648 691
692int show_line_range(struct line_range *lr, const char *module)
693{
694 int ret;
695
696 ret = init_symbol_maps(false);
697 if (ret < 0)
698 return ret;
699 ret = __show_line_range(lr, module);
700 exit_symbol_maps();
701
702 return ret;
703}
704
649static int show_available_vars_at(struct debuginfo *dinfo, 705static int show_available_vars_at(struct debuginfo *dinfo,
650 struct perf_probe_event *pev, 706 struct perf_probe_event *pev,
651 int max_vls, struct strfilter *_filter, 707 int max_vls, struct strfilter *_filter,
@@ -707,14 +763,15 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
707 int i, ret = 0; 763 int i, ret = 0;
708 struct debuginfo *dinfo; 764 struct debuginfo *dinfo;
709 765
710 ret = init_vmlinux(); 766 ret = init_symbol_maps(false);
711 if (ret < 0) 767 if (ret < 0)
712 return ret; 768 return ret;
713 769
714 dinfo = open_debuginfo(module); 770 dinfo = open_debuginfo(module);
715 if (!dinfo) { 771 if (!dinfo) {
716 pr_warning("Failed to open debuginfo file.\n"); 772 pr_warning("Failed to open debuginfo file.\n");
717 return -ENOENT; 773 ret = -ENOENT;
774 goto out;
718 } 775 }
719 776
720 setup_pager(); 777 setup_pager();
@@ -724,23 +781,19 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
724 externs); 781 externs);
725 782
726 debuginfo__delete(dinfo); 783 debuginfo__delete(dinfo);
784out:
785 exit_symbol_maps();
727 return ret; 786 return ret;
728} 787}
729 788
730#else /* !HAVE_DWARF_SUPPORT */ 789#else /* !HAVE_DWARF_SUPPORT */
731 790
732static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 791static int
733 struct perf_probe_point *pp) 792find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused,
793 struct perf_probe_point *pp __maybe_unused,
794 bool is_kprobe __maybe_unused)
734{ 795{
735 struct symbol *sym; 796 return -ENOSYS;
736
737 sym = __find_kernel_function_by_name(tp->symbol, NULL);
738 if (!sym) {
739 pr_err("Failed to find symbol %s in kernel.\n", tp->symbol);
740 return -ENOENT;
741 }
742
743 return convert_to_perf_probe_point(tp, pp);
744} 797}
745 798
746static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 799static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
@@ -776,24 +829,22 @@ int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
776 829
777void line_range__clear(struct line_range *lr) 830void line_range__clear(struct line_range *lr)
778{ 831{
779 struct line_node *ln;
780
781 free(lr->function); 832 free(lr->function);
782 free(lr->file); 833 free(lr->file);
783 free(lr->path); 834 free(lr->path);
784 free(lr->comp_dir); 835 free(lr->comp_dir);
785 while (!list_empty(&lr->line_list)) { 836 intlist__delete(lr->line_list);
786 ln = list_first_entry(&lr->line_list, struct line_node, list);
787 list_del(&ln->list);
788 free(ln);
789 }
790 memset(lr, 0, sizeof(*lr)); 837 memset(lr, 0, sizeof(*lr));
791} 838}
792 839
793void line_range__init(struct line_range *lr) 840int line_range__init(struct line_range *lr)
794{ 841{
795 memset(lr, 0, sizeof(*lr)); 842 memset(lr, 0, sizeof(*lr));
796 INIT_LIST_HEAD(&lr->line_list); 843 lr->line_list = intlist__new(NULL);
844 if (!lr->line_list)
845 return -ENOMEM;
846 else
847 return 0;
797} 848}
798 849
799static int parse_line_num(char **ptr, int *val, const char *what) 850static int parse_line_num(char **ptr, int *val, const char *what)
@@ -1267,16 +1318,21 @@ static int parse_probe_trace_command(const char *cmd,
1267 } else 1318 } else
1268 p = argv[1]; 1319 p = argv[1];
1269 fmt1_str = strtok_r(p, "+", &fmt); 1320 fmt1_str = strtok_r(p, "+", &fmt);
1270 tp->symbol = strdup(fmt1_str); 1321 if (fmt1_str[0] == '0') /* only the address started with 0x */
1271 if (tp->symbol == NULL) { 1322 tp->address = strtoul(fmt1_str, NULL, 0);
1272 ret = -ENOMEM; 1323 else {
1273 goto out; 1324 /* Only the symbol-based probe has offset */
1325 tp->symbol = strdup(fmt1_str);
1326 if (tp->symbol == NULL) {
1327 ret = -ENOMEM;
1328 goto out;
1329 }
1330 fmt2_str = strtok_r(NULL, "", &fmt);
1331 if (fmt2_str == NULL)
1332 tp->offset = 0;
1333 else
1334 tp->offset = strtoul(fmt2_str, NULL, 10);
1274 } 1335 }
1275 fmt2_str = strtok_r(NULL, "", &fmt);
1276 if (fmt2_str == NULL)
1277 tp->offset = 0;
1278 else
1279 tp->offset = strtoul(fmt2_str, NULL, 10);
1280 1336
1281 tev->nargs = argc - 2; 1337 tev->nargs = argc - 2;
1282 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 1338 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
@@ -1518,20 +1574,27 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
1518 if (buf == NULL) 1574 if (buf == NULL)
1519 return NULL; 1575 return NULL;
1520 1576
1577 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
1578 tev->group, tev->event);
1579 if (len <= 0)
1580 goto error;
1581
1582 /* Uprobes must have tp->address and tp->module */
1583 if (tev->uprobes && (!tp->address || !tp->module))
1584 goto error;
1585
1586 /* Use the tp->address for uprobes */
1521 if (tev->uprobes) 1587 if (tev->uprobes)
1522 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s:%s", 1588 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx",
1523 tp->retprobe ? 'r' : 'p', 1589 tp->module, tp->address);
1524 tev->group, tev->event,
1525 tp->module, tp->symbol);
1526 else 1590 else
1527 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu", 1591 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu",
1528 tp->retprobe ? 'r' : 'p',
1529 tev->group, tev->event,
1530 tp->module ?: "", tp->module ? ":" : "", 1592 tp->module ?: "", tp->module ? ":" : "",
1531 tp->symbol, tp->offset); 1593 tp->symbol, tp->offset);
1532 1594
1533 if (len <= 0) 1595 if (ret <= 0)
1534 goto error; 1596 goto error;
1597 len += ret;
1535 1598
1536 for (i = 0; i < tev->nargs; i++) { 1599 for (i = 0; i < tev->nargs; i++) {
1537 ret = synthesize_probe_trace_arg(&tev->args[i], buf + len, 1600 ret = synthesize_probe_trace_arg(&tev->args[i], buf + len,
@@ -1547,6 +1610,79 @@ error:
1547 return NULL; 1610 return NULL;
1548} 1611}
1549 1612
1613static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
1614 struct perf_probe_point *pp,
1615 bool is_kprobe)
1616{
1617 struct symbol *sym = NULL;
1618 struct map *map;
1619 u64 addr;
1620 int ret = -ENOENT;
1621
1622 if (!is_kprobe) {
1623 map = dso__new_map(tp->module);
1624 if (!map)
1625 goto out;
1626 addr = tp->address;
1627 sym = map__find_symbol(map, addr, NULL);
1628 } else {
1629 addr = kernel_get_symbol_address_by_name(tp->symbol, true);
1630 if (addr) {
1631 addr += tp->offset;
1632 sym = __find_kernel_function(addr, &map);
1633 }
1634 }
1635 if (!sym)
1636 goto out;
1637
1638 pp->retprobe = tp->retprobe;
1639 pp->offset = addr - map->unmap_ip(map, sym->start);
1640 pp->function = strdup(sym->name);
1641 ret = pp->function ? 0 : -ENOMEM;
1642
1643out:
1644 if (map && !is_kprobe) {
1645 dso__delete(map->dso);
1646 map__delete(map);
1647 }
1648
1649 return ret;
1650}
1651
1652static int convert_to_perf_probe_point(struct probe_trace_point *tp,
1653 struct perf_probe_point *pp,
1654 bool is_kprobe)
1655{
1656 char buf[128];
1657 int ret;
1658
1659 ret = find_perf_probe_point_from_dwarf(tp, pp, is_kprobe);
1660 if (!ret)
1661 return 0;
1662 ret = find_perf_probe_point_from_map(tp, pp, is_kprobe);
1663 if (!ret)
1664 return 0;
1665
1666 pr_debug("Failed to find probe point from both of dwarf and map.\n");
1667
1668 if (tp->symbol) {
1669 pp->function = strdup(tp->symbol);
1670 pp->offset = tp->offset;
1671 } else if (!tp->module && !is_kprobe) {
1672 ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address);
1673 if (ret < 0)
1674 return ret;
1675 pp->function = strdup(buf);
1676 pp->offset = 0;
1677 }
1678 if (pp->function == NULL)
1679 return -ENOMEM;
1680
1681 pp->retprobe = tp->retprobe;
1682
1683 return 0;
1684}
1685
1550static int convert_to_perf_probe_event(struct probe_trace_event *tev, 1686static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1551 struct perf_probe_event *pev, bool is_kprobe) 1687 struct perf_probe_event *pev, bool is_kprobe)
1552{ 1688{
@@ -1560,11 +1696,7 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1560 return -ENOMEM; 1696 return -ENOMEM;
1561 1697
1562 /* Convert trace_point to probe_point */ 1698 /* Convert trace_point to probe_point */
1563 if (is_kprobe) 1699 ret = convert_to_perf_probe_point(&tev->point, &pev->point, is_kprobe);
1564 ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point);
1565 else
1566 ret = convert_to_perf_probe_point(&tev->point, &pev->point);
1567
1568 if (ret < 0) 1700 if (ret < 0)
1569 return ret; 1701 return ret;
1570 1702
@@ -1731,7 +1863,8 @@ static struct strlist *get_probe_trace_command_rawlist(int fd)
1731} 1863}
1732 1864
1733/* Show an event */ 1865/* Show an event */
1734static int show_perf_probe_event(struct perf_probe_event *pev) 1866static int show_perf_probe_event(struct perf_probe_event *pev,
1867 const char *module)
1735{ 1868{
1736 int i, ret; 1869 int i, ret;
1737 char buf[128]; 1870 char buf[128];
@@ -1747,6 +1880,8 @@ static int show_perf_probe_event(struct perf_probe_event *pev)
1747 return ret; 1880 return ret;
1748 1881
1749 printf(" %-20s (on %s", buf, place); 1882 printf(" %-20s (on %s", buf, place);
1883 if (module)
1884 printf(" in %s", module);
1750 1885
1751 if (pev->nargs > 0) { 1886 if (pev->nargs > 0) {
1752 printf(" with"); 1887 printf(" with");
@@ -1784,7 +1919,8 @@ static int __show_perf_probe_events(int fd, bool is_kprobe)
1784 ret = convert_to_perf_probe_event(&tev, &pev, 1919 ret = convert_to_perf_probe_event(&tev, &pev,
1785 is_kprobe); 1920 is_kprobe);
1786 if (ret >= 0) 1921 if (ret >= 0)
1787 ret = show_perf_probe_event(&pev); 1922 ret = show_perf_probe_event(&pev,
1923 tev.point.module);
1788 } 1924 }
1789 clear_perf_probe_event(&pev); 1925 clear_perf_probe_event(&pev);
1790 clear_probe_trace_event(&tev); 1926 clear_probe_trace_event(&tev);
@@ -1807,7 +1943,7 @@ int show_perf_probe_events(void)
1807 if (fd < 0) 1943 if (fd < 0)
1808 return fd; 1944 return fd;
1809 1945
1810 ret = init_vmlinux(); 1946 ret = init_symbol_maps(false);
1811 if (ret < 0) 1947 if (ret < 0)
1812 return ret; 1948 return ret;
1813 1949
@@ -1820,6 +1956,7 @@ int show_perf_probe_events(void)
1820 close(fd); 1956 close(fd);
1821 } 1957 }
1822 1958
1959 exit_symbol_maps();
1823 return ret; 1960 return ret;
1824} 1961}
1825 1962
@@ -1982,7 +2119,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
1982 group = pev->group; 2119 group = pev->group;
1983 pev->event = tev->event; 2120 pev->event = tev->event;
1984 pev->group = tev->group; 2121 pev->group = tev->group;
1985 show_perf_probe_event(pev); 2122 show_perf_probe_event(pev, tev->point.module);
1986 /* Trick here - restore current event/group */ 2123 /* Trick here - restore current event/group */
1987 pev->event = (char *)event; 2124 pev->event = (char *)event;
1988 pev->group = (char *)group; 2125 pev->group = (char *)group;
@@ -2008,113 +2145,175 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2008 return ret; 2145 return ret;
2009} 2146}
2010 2147
2011static int convert_to_probe_trace_events(struct perf_probe_event *pev, 2148static char *looking_function_name;
2012 struct probe_trace_event **tevs, 2149static int num_matched_functions;
2013 int max_tevs, const char *target) 2150
2151static int probe_function_filter(struct map *map __maybe_unused,
2152 struct symbol *sym)
2014{ 2153{
2154 if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) &&
2155 strcmp(looking_function_name, sym->name) == 0) {
2156 num_matched_functions++;
2157 return 0;
2158 }
2159 return 1;
2160}
2161
2162#define strdup_or_goto(str, label) \
2163 ({ char *__p = strdup(str); if (!__p) goto label; __p; })
2164
2165/*
2166 * Find probe function addresses from map.
2167 * Return an error or the number of found probe_trace_event
2168 */
2169static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2170 struct probe_trace_event **tevs,
2171 int max_tevs, const char *target)
2172{
2173 struct map *map = NULL;
2174 struct kmap *kmap = NULL;
2175 struct ref_reloc_sym *reloc_sym = NULL;
2015 struct symbol *sym; 2176 struct symbol *sym;
2016 int ret, i; 2177 struct rb_node *nd;
2017 struct probe_trace_event *tev; 2178 struct probe_trace_event *tev;
2179 struct perf_probe_point *pp = &pev->point;
2180 struct probe_trace_point *tp;
2181 int ret, i;
2018 2182
2019 if (pev->uprobes && !pev->group) { 2183 /* Init maps of given executable or kernel */
2020 /* Replace group name if not given */ 2184 if (pev->uprobes)
2021 ret = convert_exec_to_group(target, &pev->group); 2185 map = dso__new_map(target);
2022 if (ret != 0) { 2186 else
2023 pr_warning("Failed to make a group name.\n"); 2187 map = kernel_get_module_map(target);
2024 return ret; 2188 if (!map) {
2025 } 2189 ret = -EINVAL;
2190 goto out;
2026 } 2191 }
2027 2192
2028 /* Convert perf_probe_event with debuginfo */ 2193 /*
2029 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target); 2194 * Load matched symbols: Since the different local symbols may have
2030 if (ret != 0) 2195 * same name but different addresses, this lists all the symbols.
2031 return ret; /* Found in debuginfo or got an error */ 2196 */
2032 2197 num_matched_functions = 0;
2033 if (pev->uprobes) { 2198 looking_function_name = pp->function;
2034 ret = convert_name_to_addr(pev, target); 2199 ret = map__load(map, probe_function_filter);
2035 if (ret < 0) 2200 if (ret || num_matched_functions == 0) {
2036 return ret; 2201 pr_err("Failed to find symbol %s in %s\n", pp->function,
2202 target ? : "kernel");
2203 ret = -ENOENT;
2204 goto out;
2205 } else if (num_matched_functions > max_tevs) {
2206 pr_err("Too many functions matched in %s\n",
2207 target ? : "kernel");
2208 ret = -E2BIG;
2209 goto out;
2037 } 2210 }
2038 2211
2039 /* Allocate trace event buffer */ 2212 if (!pev->uprobes) {
2040 tev = *tevs = zalloc(sizeof(struct probe_trace_event)); 2213 kmap = map__kmap(map);
2041 if (tev == NULL) 2214 reloc_sym = kmap->ref_reloc_sym;
2042 return -ENOMEM; 2215 if (!reloc_sym) {
2216 pr_warning("Relocated base symbol is not found!\n");
2217 ret = -EINVAL;
2218 goto out;
2219 }
2220 }
2043 2221
2044 /* Copy parameters */ 2222 /* Setup result trace-probe-events */
2045 tev->point.symbol = strdup(pev->point.function); 2223 *tevs = zalloc(sizeof(*tev) * num_matched_functions);
2046 if (tev->point.symbol == NULL) { 2224 if (!*tevs) {
2047 ret = -ENOMEM; 2225 ret = -ENOMEM;
2048 goto error; 2226 goto out;
2049 } 2227 }
2050 2228
2051 if (target) { 2229 ret = 0;
2052 tev->point.module = strdup(target); 2230 map__for_each_symbol(map, sym, nd) {
2053 if (tev->point.module == NULL) { 2231 tev = (*tevs) + ret;
2054 ret = -ENOMEM; 2232 tp = &tev->point;
2055 goto error; 2233 if (ret == num_matched_functions) {
2234 pr_warning("Too many symbols are listed. Skip it.\n");
2235 break;
2056 } 2236 }
2057 } 2237 ret++;
2058
2059 tev->point.offset = pev->point.offset;
2060 tev->point.retprobe = pev->point.retprobe;
2061 tev->nargs = pev->nargs;
2062 tev->uprobes = pev->uprobes;
2063 2238
2064 if (tev->nargs) { 2239 if (pp->offset > sym->end - sym->start) {
2065 tev->args = zalloc(sizeof(struct probe_trace_arg) 2240 pr_warning("Offset %ld is bigger than the size of %s\n",
2066 * tev->nargs); 2241 pp->offset, sym->name);
2067 if (tev->args == NULL) { 2242 ret = -ENOENT;
2068 ret = -ENOMEM; 2243 goto err_out;
2069 goto error; 2244 }
2245 /* Add one probe point */
2246 tp->address = map->unmap_ip(map, sym->start) + pp->offset;
2247 if (reloc_sym) {
2248 tp->symbol = strdup_or_goto(reloc_sym->name, nomem_out);
2249 tp->offset = tp->address - reloc_sym->addr;
2250 } else {
2251 tp->symbol = strdup_or_goto(sym->name, nomem_out);
2252 tp->offset = pp->offset;
2253 }
2254 tp->retprobe = pp->retprobe;
2255 if (target)
2256 tev->point.module = strdup_or_goto(target, nomem_out);
2257 tev->uprobes = pev->uprobes;
2258 tev->nargs = pev->nargs;
2259 if (tev->nargs) {
2260 tev->args = zalloc(sizeof(struct probe_trace_arg) *
2261 tev->nargs);
2262 if (tev->args == NULL)
2263 goto nomem_out;
2070 } 2264 }
2071 for (i = 0; i < tev->nargs; i++) { 2265 for (i = 0; i < tev->nargs; i++) {
2072 if (pev->args[i].name) { 2266 if (pev->args[i].name)
2073 tev->args[i].name = strdup(pev->args[i].name); 2267 tev->args[i].name =
2074 if (tev->args[i].name == NULL) { 2268 strdup_or_goto(pev->args[i].name,
2075 ret = -ENOMEM; 2269 nomem_out);
2076 goto error; 2270
2077 } 2271 tev->args[i].value = strdup_or_goto(pev->args[i].var,
2078 } 2272 nomem_out);
2079 tev->args[i].value = strdup(pev->args[i].var); 2273 if (pev->args[i].type)
2080 if (tev->args[i].value == NULL) { 2274 tev->args[i].type =
2081 ret = -ENOMEM; 2275 strdup_or_goto(pev->args[i].type,
2082 goto error; 2276 nomem_out);
2083 }
2084 if (pev->args[i].type) {
2085 tev->args[i].type = strdup(pev->args[i].type);
2086 if (tev->args[i].type == NULL) {
2087 ret = -ENOMEM;
2088 goto error;
2089 }
2090 }
2091 } 2277 }
2092 } 2278 }
2093 2279
2094 if (pev->uprobes) 2280out:
2095 return 1; 2281 if (map && pev->uprobes) {
2282 /* Only when using uprobe(exec) map needs to be released */
2283 dso__delete(map->dso);
2284 map__delete(map);
2285 }
2286 return ret;
2096 2287
2097 /* Currently just checking function name from symbol map */ 2288nomem_out:
2098 sym = __find_kernel_function_by_name(tev->point.symbol, NULL); 2289 ret = -ENOMEM;
2099 if (!sym) { 2290err_out:
2100 pr_warning("Kernel symbol \'%s\' not found.\n", 2291 clear_probe_trace_events(*tevs, num_matched_functions);
2101 tev->point.symbol); 2292 zfree(tevs);
2102 ret = -ENOENT; 2293 goto out;
2103 goto error; 2294}
2104 } else if (tev->point.offset > sym->end - sym->start) { 2295
2105 pr_warning("Offset specified is greater than size of %s\n", 2296static int convert_to_probe_trace_events(struct perf_probe_event *pev,
2106 tev->point.symbol); 2297 struct probe_trace_event **tevs,
2107 ret = -ENOENT; 2298 int max_tevs, const char *target)
2108 goto error; 2299{
2300 int ret;
2109 2301
2302 if (pev->uprobes && !pev->group) {
2303 /* Replace group name if not given */
2304 ret = convert_exec_to_group(target, &pev->group);
2305 if (ret != 0) {
2306 pr_warning("Failed to make a group name.\n");
2307 return ret;
2308 }
2110 } 2309 }
2111 2310
2112 return 1; 2311 /* Convert perf_probe_event with debuginfo */
2113error: 2312 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target);
2114 clear_probe_trace_event(tev); 2313 if (ret != 0)
2115 free(tev); 2314 return ret; /* Found in debuginfo or got an error */
2116 *tevs = NULL; 2315
2117 return ret; 2316 return find_probe_trace_events_from_map(pev, tevs, max_tevs, target);
2118} 2317}
2119 2318
2120struct __event_package { 2319struct __event_package {
@@ -2135,12 +2334,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
2135 if (pkgs == NULL) 2334 if (pkgs == NULL)
2136 return -ENOMEM; 2335 return -ENOMEM;
2137 2336
2138 if (!pevs->uprobes) 2337 ret = init_symbol_maps(pevs->uprobes);
2139 /* Init vmlinux path */
2140 ret = init_vmlinux();
2141 else
2142 ret = init_user_exec();
2143
2144 if (ret < 0) { 2338 if (ret < 0) {
2145 free(pkgs); 2339 free(pkgs);
2146 return ret; 2340 return ret;
@@ -2174,6 +2368,7 @@ end:
2174 zfree(&pkgs[i].tevs); 2368 zfree(&pkgs[i].tevs);
2175 } 2369 }
2176 free(pkgs); 2370 free(pkgs);
2371 exit_symbol_maps();
2177 2372
2178 return ret; 2373 return ret;
2179} 2374}
@@ -2323,159 +2518,51 @@ static struct strfilter *available_func_filter;
2323static int filter_available_functions(struct map *map __maybe_unused, 2518static int filter_available_functions(struct map *map __maybe_unused,
2324 struct symbol *sym) 2519 struct symbol *sym)
2325{ 2520{
2326 if (sym->binding == STB_GLOBAL && 2521 if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) &&
2327 strfilter__compare(available_func_filter, sym->name)) 2522 strfilter__compare(available_func_filter, sym->name))
2328 return 0; 2523 return 0;
2329 return 1; 2524 return 1;
2330} 2525}
2331 2526
2332static int __show_available_funcs(struct map *map) 2527int show_available_funcs(const char *target, struct strfilter *_filter,
2333{ 2528 bool user)
2334 if (map__load(map, filter_available_functions)) {
2335 pr_err("Failed to load map.\n");
2336 return -EINVAL;
2337 }
2338 if (!dso__sorted_by_name(map->dso, map->type))
2339 dso__sort_by_name(map->dso, map->type);
2340
2341 dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
2342 return 0;
2343}
2344
2345static int available_kernel_funcs(const char *module)
2346{ 2529{
2347 struct map *map; 2530 struct map *map;
2348 int ret; 2531 int ret;
2349 2532
2350 ret = init_vmlinux(); 2533 ret = init_symbol_maps(user);
2351 if (ret < 0) 2534 if (ret < 0)
2352 return ret; 2535 return ret;
2353 2536
2354 map = kernel_get_module_map(module); 2537 /* Get a symbol map */
2538 if (user)
2539 map = dso__new_map(target);
2540 else
2541 map = kernel_get_module_map(target);
2355 if (!map) { 2542 if (!map) {
2356 pr_err("Failed to find %s map.\n", (module) ? : "kernel"); 2543 pr_err("Failed to get a map for %s\n", (target) ? : "kernel");
2357 return -EINVAL; 2544 return -EINVAL;
2358 } 2545 }
2359 return __show_available_funcs(map);
2360}
2361
2362static int available_user_funcs(const char *target)
2363{
2364 struct map *map;
2365 int ret;
2366
2367 ret = init_user_exec();
2368 if (ret < 0)
2369 return ret;
2370
2371 map = dso__new_map(target);
2372 ret = __show_available_funcs(map);
2373 dso__delete(map->dso);
2374 map__delete(map);
2375 return ret;
2376}
2377 2546
2378int show_available_funcs(const char *target, struct strfilter *_filter, 2547 /* Load symbols with given filter */
2379 bool user)
2380{
2381 setup_pager();
2382 available_func_filter = _filter; 2548 available_func_filter = _filter;
2383
2384 if (!user)
2385 return available_kernel_funcs(target);
2386
2387 return available_user_funcs(target);
2388}
2389
2390/*
2391 * uprobe_events only accepts address:
2392 * Convert function and any offset to address
2393 */
2394static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec)
2395{
2396 struct perf_probe_point *pp = &pev->point;
2397 struct symbol *sym;
2398 struct map *map = NULL;
2399 char *function = NULL;
2400 int ret = -EINVAL;
2401 unsigned long long vaddr = 0;
2402
2403 if (!pp->function) {
2404 pr_warning("No function specified for uprobes");
2405 goto out;
2406 }
2407
2408 function = strdup(pp->function);
2409 if (!function) {
2410 pr_warning("Failed to allocate memory by strdup.\n");
2411 ret = -ENOMEM;
2412 goto out;
2413 }
2414
2415 map = dso__new_map(exec);
2416 if (!map) {
2417 pr_warning("Cannot find appropriate DSO for %s.\n", exec);
2418 goto out;
2419 }
2420 available_func_filter = strfilter__new(function, NULL);
2421 if (map__load(map, filter_available_functions)) { 2549 if (map__load(map, filter_available_functions)) {
2422 pr_err("Failed to load map.\n"); 2550 pr_err("Failed to load symbols in %s\n", (target) ? : "kernel");
2423 goto out; 2551 goto end;
2424 }
2425
2426 sym = map__find_symbol_by_name(map, function, NULL);
2427 if (!sym) {
2428 pr_warning("Cannot find %s in DSO %s\n", function, exec);
2429 goto out;
2430 }
2431
2432 if (map->start > sym->start)
2433 vaddr = map->start;
2434 vaddr += sym->start + pp->offset + map->pgoff;
2435 pp->offset = 0;
2436
2437 if (!pev->event) {
2438 pev->event = function;
2439 function = NULL;
2440 }
2441 if (!pev->group) {
2442 char *ptr1, *ptr2, *exec_copy;
2443
2444 pev->group = zalloc(sizeof(char *) * 64);
2445 exec_copy = strdup(exec);
2446 if (!exec_copy) {
2447 ret = -ENOMEM;
2448 pr_warning("Failed to copy exec string.\n");
2449 goto out;
2450 }
2451
2452 ptr1 = strdup(basename(exec_copy));
2453 if (ptr1) {
2454 ptr2 = strpbrk(ptr1, "-._");
2455 if (ptr2)
2456 *ptr2 = '\0';
2457 e_snprintf(pev->group, 64, "%s_%s", PERFPROBE_GROUP,
2458 ptr1);
2459 free(ptr1);
2460 }
2461 free(exec_copy);
2462 }
2463 free(pp->function);
2464 pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS);
2465 if (!pp->function) {
2466 ret = -ENOMEM;
2467 pr_warning("Failed to allocate memory by zalloc.\n");
2468 goto out;
2469 } 2552 }
2470 e_snprintf(pp->function, MAX_PROBE_ARGS, "0x%llx", vaddr); 2553 if (!dso__sorted_by_name(map->dso, map->type))
2471 ret = 0; 2554 dso__sort_by_name(map->dso, map->type);
2472 2555
2473out: 2556 /* Show all (filtered) symbols */
2474 if (map) { 2557 setup_pager();
2558 dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
2559end:
2560 if (user) {
2475 dso__delete(map->dso); 2561 dso__delete(map->dso);
2476 map__delete(map); 2562 map__delete(map);
2477 } 2563 }
2478 if (function) 2564 exit_symbol_maps();
2479 free(function); 2565
2480 return ret; 2566 return ret;
2481} 2567}
2568
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index fcaf7273e85a..776c9347a3b6 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -2,6 +2,7 @@
2#define _PROBE_EVENT_H 2#define _PROBE_EVENT_H
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include "intlist.h"
5#include "strlist.h" 6#include "strlist.h"
6#include "strfilter.h" 7#include "strfilter.h"
7 8
@@ -76,13 +77,6 @@ struct perf_probe_event {
76 struct perf_probe_arg *args; /* Arguments */ 77 struct perf_probe_arg *args; /* Arguments */
77}; 78};
78 79
79
80/* Line number container */
81struct line_node {
82 struct list_head list;
83 int line;
84};
85
86/* Line range */ 80/* Line range */
87struct line_range { 81struct line_range {
88 char *file; /* File name */ 82 char *file; /* File name */
@@ -92,7 +86,7 @@ struct line_range {
92 int offset; /* Start line offset */ 86 int offset; /* Start line offset */
93 char *path; /* Real path name */ 87 char *path; /* Real path name */
94 char *comp_dir; /* Compile directory */ 88 char *comp_dir; /* Compile directory */
95 struct list_head line_list; /* Visible lines */ 89 struct intlist *line_list; /* Visible lines */
96}; 90};
97 91
98/* List of variables */ 92/* List of variables */
@@ -124,7 +118,7 @@ extern int parse_line_range_desc(const char *cmd, struct line_range *lr);
124extern void line_range__clear(struct line_range *lr); 118extern void line_range__clear(struct line_range *lr);
125 119
126/* Initialize line range */ 120/* Initialize line range */
127extern void line_range__init(struct line_range *lr); 121extern int line_range__init(struct line_range *lr);
128 122
129/* Internal use: Return kernel/module path */ 123/* Internal use: Return kernel/module path */
130extern const char *kernel_get_module_path(const char *module); 124extern const char *kernel_get_module_path(const char *module);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 061edb162b5b..9d8eb26f0533 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -34,7 +34,9 @@
34 34
35#include <linux/bitops.h> 35#include <linux/bitops.h>
36#include "event.h" 36#include "event.h"
37#include "dso.h"
37#include "debug.h" 38#include "debug.h"
39#include "intlist.h"
38#include "util.h" 40#include "util.h"
39#include "symbol.h" 41#include "symbol.h"
40#include "probe-finder.h" 42#include "probe-finder.h"
@@ -42,65 +44,6 @@
42/* Kprobe tracer basic type is up to u64 */ 44/* Kprobe tracer basic type is up to u64 */
43#define MAX_BASIC_TYPE_BITS 64 45#define MAX_BASIC_TYPE_BITS 64
44 46
45/* Line number list operations */
46
47/* Add a line to line number list */
48static int line_list__add_line(struct list_head *head, int line)
49{
50 struct line_node *ln;
51 struct list_head *p;
52
53 /* Reverse search, because new line will be the last one */
54 list_for_each_entry_reverse(ln, head, list) {
55 if (ln->line < line) {
56 p = &ln->list;
57 goto found;
58 } else if (ln->line == line) /* Already exist */
59 return 1;
60 }
61 /* List is empty, or the smallest entry */
62 p = head;
63found:
64 pr_debug("line list: add a line %u\n", line);
65 ln = zalloc(sizeof(struct line_node));
66 if (ln == NULL)
67 return -ENOMEM;
68 ln->line = line;
69 INIT_LIST_HEAD(&ln->list);
70 list_add(&ln->list, p);
71 return 0;
72}
73
74/* Check if the line in line number list */
75static int line_list__has_line(struct list_head *head, int line)
76{
77 struct line_node *ln;
78
79 /* Reverse search, because new line will be the last one */
80 list_for_each_entry(ln, head, list)
81 if (ln->line == line)
82 return 1;
83
84 return 0;
85}
86
87/* Init line number list */
88static void line_list__init(struct list_head *head)
89{
90 INIT_LIST_HEAD(head);
91}
92
93/* Free line number list */
94static void line_list__free(struct list_head *head)
95{
96 struct line_node *ln;
97 while (!list_empty(head)) {
98 ln = list_first_entry(head, struct line_node, list);
99 list_del(&ln->list);
100 free(ln);
101 }
102}
103
104/* Dwarf FL wrappers */ 47/* Dwarf FL wrappers */
105static char *debuginfo_path; /* Currently dummy */ 48static char *debuginfo_path; /* Currently dummy */
106 49
@@ -147,80 +90,7 @@ error:
147 return -ENOENT; 90 return -ENOENT;
148} 91}
149 92
150#if _ELFUTILS_PREREQ(0, 148) 93static struct debuginfo *__debuginfo__new(const char *path)
151/* This method is buggy if elfutils is older than 0.148 */
152static int __linux_kernel_find_elf(Dwfl_Module *mod,
153 void **userdata,
154 const char *module_name,
155 Dwarf_Addr base,
156 char **file_name, Elf **elfp)
157{
158 int fd;
159 const char *path = kernel_get_module_path(module_name);
160
161 pr_debug2("Use file %s for %s\n", path, module_name);
162 if (path) {
163 fd = open(path, O_RDONLY);
164 if (fd >= 0) {
165 *file_name = strdup(path);
166 return fd;
167 }
168 }
169 /* If failed, try to call standard method */
170 return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base,
171 file_name, elfp);
172}
173
174static const Dwfl_Callbacks kernel_callbacks = {
175 .find_debuginfo = dwfl_standard_find_debuginfo,
176 .debuginfo_path = &debuginfo_path,
177
178 .find_elf = __linux_kernel_find_elf,
179 .section_address = dwfl_linux_kernel_module_section_address,
180};
181
182/* Get a Dwarf from live kernel image */
183static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
184 Dwarf_Addr addr)
185{
186 dbg->dwfl = dwfl_begin(&kernel_callbacks);
187 if (!dbg->dwfl)
188 return -EINVAL;
189
190 /* Load the kernel dwarves: Don't care the result here */
191 dwfl_linux_kernel_report_kernel(dbg->dwfl);
192 dwfl_linux_kernel_report_modules(dbg->dwfl);
193
194 dbg->dbg = dwfl_addrdwarf(dbg->dwfl, addr, &dbg->bias);
195 /* Here, check whether we could get a real dwarf */
196 if (!dbg->dbg) {
197 pr_debug("Failed to find kernel dwarf at %lx\n",
198 (unsigned long)addr);
199 dwfl_end(dbg->dwfl);
200 memset(dbg, 0, sizeof(*dbg));
201 return -ENOENT;
202 }
203
204 return 0;
205}
206#else
207/* With older elfutils, this just support kernel module... */
208static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
209 Dwarf_Addr addr __maybe_unused)
210{
211 const char *path = kernel_get_module_path("kernel");
212
213 if (!path) {
214 pr_err("Failed to find vmlinux path\n");
215 return -ENOENT;
216 }
217
218 pr_debug2("Use file %s for debuginfo\n", path);
219 return debuginfo__init_offline_dwarf(dbg, path);
220}
221#endif
222
223struct debuginfo *debuginfo__new(const char *path)
224{ 94{
225 struct debuginfo *dbg = zalloc(sizeof(*dbg)); 95 struct debuginfo *dbg = zalloc(sizeof(*dbg));
226 if (!dbg) 96 if (!dbg)
@@ -228,21 +98,44 @@ struct debuginfo *debuginfo__new(const char *path)
228 98
229 if (debuginfo__init_offline_dwarf(dbg, path) < 0) 99 if (debuginfo__init_offline_dwarf(dbg, path) < 0)
230 zfree(&dbg); 100 zfree(&dbg);
231 101 if (dbg)
102 pr_debug("Open Debuginfo file: %s\n", path);
232 return dbg; 103 return dbg;
233} 104}
234 105
235struct debuginfo *debuginfo__new_online_kernel(unsigned long addr) 106enum dso_binary_type distro_dwarf_types[] = {
236{ 107 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
237 struct debuginfo *dbg = zalloc(sizeof(*dbg)); 108 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
109 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
110 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
111 DSO_BINARY_TYPE__NOT_FOUND,
112};
238 113
239 if (!dbg) 114struct debuginfo *debuginfo__new(const char *path)
240 return NULL; 115{
116 enum dso_binary_type *type;
117 char buf[PATH_MAX], nil = '\0';
118 struct dso *dso;
119 struct debuginfo *dinfo = NULL;
120
121 /* Try to open distro debuginfo files */
122 dso = dso__new(path);
123 if (!dso)
124 goto out;
241 125
242 if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) 126 for (type = distro_dwarf_types;
243 zfree(&dbg); 127 !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND;
128 type++) {
129 if (dso__read_binary_type_filename(dso, *type, &nil,
130 buf, PATH_MAX) < 0)
131 continue;
132 dinfo = __debuginfo__new(buf);
133 }
134 dso__delete(dso);
244 135
245 return dbg; 136out:
137 /* if failed to open all distro debuginfo, open given binary */
138 return dinfo ? : __debuginfo__new(path);
246} 139}
247 140
248void debuginfo__delete(struct debuginfo *dbg) 141void debuginfo__delete(struct debuginfo *dbg)
@@ -618,12 +511,12 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
618 511
619 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, 512 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
620 &pf->sp_die, pf->tvar); 513 &pf->sp_die, pf->tvar);
621 if (ret == -ENOENT) 514 if (ret == -ENOENT || ret == -EINVAL)
622 pr_err("Failed to find the location of %s at this address.\n" 515 pr_err("Failed to find the location of %s at this address.\n"
623 " Perhaps, it has been optimized out.\n", pf->pvar->var); 516 " Perhaps, it has been optimized out.\n", pf->pvar->var);
624 else if (ret == -ENOTSUP) 517 else if (ret == -ENOTSUP)
625 pr_err("Sorry, we don't support this variable location yet.\n"); 518 pr_err("Sorry, we don't support this variable location yet.\n");
626 else if (pf->pvar->field) { 519 else if (ret == 0 && pf->pvar->field) {
627 ret = convert_variable_fields(vr_die, pf->pvar->var, 520 ret = convert_variable_fields(vr_die, pf->pvar->var,
628 pf->pvar->field, &pf->tvar->ref, 521 pf->pvar->field, &pf->tvar->ref,
629 &die_mem); 522 &die_mem);
@@ -880,7 +773,7 @@ static int find_probe_point_by_line(struct probe_finder *pf)
880} 773}
881 774
882/* Find lines which match lazy pattern */ 775/* Find lines which match lazy pattern */
883static int find_lazy_match_lines(struct list_head *head, 776static int find_lazy_match_lines(struct intlist *list,
884 const char *fname, const char *pat) 777 const char *fname, const char *pat)
885{ 778{
886 FILE *fp; 779 FILE *fp;
@@ -901,7 +794,7 @@ static int find_lazy_match_lines(struct list_head *head,
901 line[len - 1] = '\0'; 794 line[len - 1] = '\0';
902 795
903 if (strlazymatch(line, pat)) { 796 if (strlazymatch(line, pat)) {
904 line_list__add_line(head, linenum); 797 intlist__add(list, linenum);
905 count++; 798 count++;
906 } 799 }
907 linenum++; 800 linenum++;
@@ -924,7 +817,7 @@ static int probe_point_lazy_walker(const char *fname, int lineno,
924 Dwarf_Die *sc_die, die_mem; 817 Dwarf_Die *sc_die, die_mem;
925 int ret; 818 int ret;
926 819
927 if (!line_list__has_line(&pf->lcache, lineno) || 820 if (!intlist__has_entry(pf->lcache, lineno) ||
928 strtailcmp(fname, pf->fname) != 0) 821 strtailcmp(fname, pf->fname) != 0)
929 return 0; 822 return 0;
930 823
@@ -952,9 +845,9 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
952{ 845{
953 int ret = 0; 846 int ret = 0;
954 847
955 if (list_empty(&pf->lcache)) { 848 if (intlist__empty(pf->lcache)) {
956 /* Matching lazy line pattern */ 849 /* Matching lazy line pattern */
957 ret = find_lazy_match_lines(&pf->lcache, pf->fname, 850 ret = find_lazy_match_lines(pf->lcache, pf->fname,
958 pf->pev->point.lazy_line); 851 pf->pev->point.lazy_line);
959 if (ret <= 0) 852 if (ret <= 0)
960 return ret; 853 return ret;
@@ -1092,11 +985,13 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
1092 985
1093#if _ELFUTILS_PREREQ(0, 142) 986#if _ELFUTILS_PREREQ(0, 142)
1094 /* Get the call frame information from this dwarf */ 987 /* Get the call frame information from this dwarf */
1095 pf->cfi = dwarf_getcfi(dbg->dbg); 988 pf->cfi = dwarf_getcfi_elf(dwarf_getelf(dbg->dbg));
1096#endif 989#endif
1097 990
1098 off = 0; 991 off = 0;
1099 line_list__init(&pf->lcache); 992 pf->lcache = intlist__new(NULL);
993 if (!pf->lcache)
994 return -ENOMEM;
1100 995
1101 /* Fastpath: lookup by function name from .debug_pubnames section */ 996 /* Fastpath: lookup by function name from .debug_pubnames section */
1102 if (pp->function) { 997 if (pp->function) {
@@ -1149,7 +1044,8 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
1149 } 1044 }
1150 1045
1151found: 1046found:
1152 line_list__free(&pf->lcache); 1047 intlist__delete(pf->lcache);
1048 pf->lcache = NULL;
1153 1049
1154 return ret; 1050 return ret;
1155} 1051}
@@ -1537,7 +1433,7 @@ static int line_range_add_line(const char *src, unsigned int lineno,
1537 if (lr->path == NULL) 1433 if (lr->path == NULL)
1538 return -ENOMEM; 1434 return -ENOMEM;
1539 } 1435 }
1540 return line_list__add_line(&lr->line_list, lineno); 1436 return intlist__add(lr->line_list, lineno);
1541} 1437}
1542 1438
1543static int line_range_walk_cb(const char *fname, int lineno, 1439static int line_range_walk_cb(const char *fname, int lineno,
@@ -1545,13 +1441,15 @@ static int line_range_walk_cb(const char *fname, int lineno,
1545 void *data) 1441 void *data)
1546{ 1442{
1547 struct line_finder *lf = data; 1443 struct line_finder *lf = data;
1444 int err;
1548 1445
1549 if ((strtailcmp(fname, lf->fname) != 0) || 1446 if ((strtailcmp(fname, lf->fname) != 0) ||
1550 (lf->lno_s > lineno || lf->lno_e < lineno)) 1447 (lf->lno_s > lineno || lf->lno_e < lineno))
1551 return 0; 1448 return 0;
1552 1449
1553 if (line_range_add_line(fname, lineno, lf->lr) < 0) 1450 err = line_range_add_line(fname, lineno, lf->lr);
1554 return -EINVAL; 1451 if (err < 0 && err != -EEXIST)
1452 return err;
1555 1453
1556 return 0; 1454 return 0;
1557} 1455}
@@ -1565,7 +1463,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1565 1463
1566 /* Update status */ 1464 /* Update status */
1567 if (ret >= 0) 1465 if (ret >= 0)
1568 if (!list_empty(&lf->lr->line_list)) 1466 if (!intlist__empty(lf->lr->line_list))
1569 ret = lf->found = 1; 1467 ret = lf->found = 1;
1570 else 1468 else
1571 ret = 0; /* Lines are not found */ 1469 ret = 0; /* Lines are not found */
@@ -1577,14 +1475,15 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1577 1475
1578static int line_range_inline_cb(Dwarf_Die *in_die, void *data) 1476static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
1579{ 1477{
1580 find_line_range_by_line(in_die, data); 1478 int ret = find_line_range_by_line(in_die, data);
1581 1479
1582 /* 1480 /*
1583 * We have to check all instances of inlined function, because 1481 * We have to check all instances of inlined function, because
1584 * some execution paths can be optimized out depends on the 1482 * some execution paths can be optimized out depends on the
1585 * function argument of instances 1483 * function argument of instances. However, if an error occurs,
1484 * it should be handled by the caller.
1586 */ 1485 */
1587 return 0; 1486 return ret < 0 ? ret : 0;
1588} 1487}
1589 1488
1590/* Search function definition from function name */ 1489/* Search function definition from function name */
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index ffc33cdd25cc..92590b2c7e1c 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -3,6 +3,7 @@
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include "util.h" 5#include "util.h"
6#include "intlist.h"
6#include "probe-event.h" 7#include "probe-event.h"
7 8
8#define MAX_PROBE_BUFFER 1024 9#define MAX_PROBE_BUFFER 1024
@@ -29,8 +30,8 @@ struct debuginfo {
29 Dwarf_Addr bias; 30 Dwarf_Addr bias;
30}; 31};
31 32
33/* This also tries to open distro debuginfo */
32extern struct debuginfo *debuginfo__new(const char *path); 34extern struct debuginfo *debuginfo__new(const char *path);
33extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr);
34extern void debuginfo__delete(struct debuginfo *dbg); 35extern void debuginfo__delete(struct debuginfo *dbg);
35 36
36/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 37/* Find probe_trace_events specified by perf_probe_event from debuginfo */
@@ -66,7 +67,7 @@ struct probe_finder {
66 const char *fname; /* Real file name */ 67 const char *fname; /* Real file name */
67 Dwarf_Die cu_die; /* Current CU */ 68 Dwarf_Die cu_die; /* Current CU */
68 Dwarf_Die sp_die; 69 Dwarf_Die sp_die;
69 struct list_head lcache; /* Line cache for lazy match */ 70 struct intlist *lcache; /* Line cache for lazy match */
70 71
71 /* For variable searching */ 72 /* For variable searching */
72#if _ELFUTILS_PREREQ(0, 142) 73#if _ELFUTILS_PREREQ(0, 142)
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 595bfc73d2ed..16a475a7d492 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -17,6 +17,6 @@ util/xyarray.c
17util/cgroup.c 17util/cgroup.c
18util/rblist.c 18util/rblist.c
19util/strlist.c 19util/strlist.c
20util/fs.c 20../lib/api/fs/fs.c
21util/trace-event.c 21util/trace-event.c
22../../lib/rbtree.c 22../../lib/rbtree.c
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 373762501dad..049e0a09ccd3 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -2,7 +2,7 @@
2#include "evsel.h" 2#include "evsel.h"
3#include "cpumap.h" 3#include "cpumap.h"
4#include "parse-events.h" 4#include "parse-events.h"
5#include "fs.h" 5#include <api/fs/fs.h>
6#include "util.h" 6#include "util.h"
7 7
8typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel); 8typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5da6ce74c676..55960f22233c 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -702,11 +702,12 @@ static void regs_dump__printf(u64 mask, u64 *regs)
702 } 702 }
703} 703}
704 704
705static void regs_user__printf(struct perf_sample *sample, u64 mask) 705static void regs_user__printf(struct perf_sample *sample)
706{ 706{
707 struct regs_dump *user_regs = &sample->user_regs; 707 struct regs_dump *user_regs = &sample->user_regs;
708 708
709 if (user_regs->regs) { 709 if (user_regs->regs) {
710 u64 mask = user_regs->mask;
710 printf("... user regs: mask 0x%" PRIx64 "\n", mask); 711 printf("... user regs: mask 0x%" PRIx64 "\n", mask);
711 regs_dump__printf(mask, user_regs->regs); 712 regs_dump__printf(mask, user_regs->regs);
712 } 713 }
@@ -793,7 +794,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
793 if (!dump_trace) 794 if (!dump_trace)
794 return; 795 return;
795 796
796 printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n", 797 printf("(IP, 0x%x): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n",
797 event->header.misc, sample->pid, sample->tid, sample->ip, 798 event->header.misc, sample->pid, sample->tid, sample->ip,
798 sample->period, sample->addr); 799 sample->period, sample->addr);
799 800
@@ -806,7 +807,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
806 branch_stack__printf(sample); 807 branch_stack__printf(sample);
807 808
808 if (sample_type & PERF_SAMPLE_REGS_USER) 809 if (sample_type & PERF_SAMPLE_REGS_USER)
809 regs_user__printf(sample, evsel->attr.sample_regs_user); 810 regs_user__printf(sample);
810 811
811 if (sample_type & PERF_SAMPLE_STACK_USER) 812 if (sample_type & PERF_SAMPLE_STACK_USER)
812 stack_user__printf(&sample->user_stack); 813 stack_user__printf(&sample->user_stack);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 516d19fb999b..6864661a79dd 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -6,6 +6,7 @@
6#include <inttypes.h> 6#include <inttypes.h>
7 7
8#include "symbol.h" 8#include "symbol.h"
9#include "vdso.h"
9#include <symbol/kallsyms.h> 10#include <symbol/kallsyms.h>
10#include "debug.h" 11#include "debug.h"
11 12
@@ -506,6 +507,8 @@ int filename__read_debuglink(const char *filename, char *debuglink,
506 /* the start of this section is a zero-terminated string */ 507 /* the start of this section is a zero-terminated string */
507 strncpy(debuglink, data->d_buf, size); 508 strncpy(debuglink, data->d_buf, size);
508 509
510 err = 0;
511
509out_elf_end: 512out_elf_end:
510 elf_end(elf); 513 elf_end(elf);
511out_close: 514out_close:
@@ -616,6 +619,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
616 GElf_Shdr shdr; 619 GElf_Shdr shdr;
617 ss->adjust_symbols = (ehdr.e_type == ET_EXEC || 620 ss->adjust_symbols = (ehdr.e_type == ET_EXEC ||
618 ehdr.e_type == ET_REL || 621 ehdr.e_type == ET_REL ||
622 is_vdso_map(dso->short_name) ||
619 elf_section_by_name(elf, &ehdr, &shdr, 623 elf_section_by_name(elf, &ehdr, &shdr,
620 ".gnu.prelink_undo", 624 ".gnu.prelink_undo",
621 NULL) != NULL); 625 NULL) != NULL);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e89afc097d8a..95e249779931 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -410,7 +410,7 @@ struct symbol *dso__find_symbol(struct dso *dso,
410 return symbols__find(&dso->symbols[type], addr); 410 return symbols__find(&dso->symbols[type], addr);
411} 411}
412 412
413struct symbol *dso__first_symbol(struct dso *dso, enum map_type type) 413static struct symbol *dso__first_symbol(struct dso *dso, enum map_type type)
414{ 414{
415 return symbols__first(&dso->symbols[type]); 415 return symbols__first(&dso->symbols[type]);
416} 416}
@@ -1251,6 +1251,46 @@ out_failure:
1251 return -1; 1251 return -1;
1252} 1252}
1253 1253
1254static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1255 enum dso_binary_type type)
1256{
1257 switch (type) {
1258 case DSO_BINARY_TYPE__JAVA_JIT:
1259 case DSO_BINARY_TYPE__DEBUGLINK:
1260 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
1261 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
1262 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
1263 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
1264 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
1265 return !kmod && dso->kernel == DSO_TYPE_USER;
1266
1267 case DSO_BINARY_TYPE__KALLSYMS:
1268 case DSO_BINARY_TYPE__VMLINUX:
1269 case DSO_BINARY_TYPE__KCORE:
1270 return dso->kernel == DSO_TYPE_KERNEL;
1271
1272 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
1273 case DSO_BINARY_TYPE__GUEST_VMLINUX:
1274 case DSO_BINARY_TYPE__GUEST_KCORE:
1275 return dso->kernel == DSO_TYPE_GUEST_KERNEL;
1276
1277 case DSO_BINARY_TYPE__GUEST_KMODULE:
1278 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
1279 /*
1280 * kernel modules know their symtab type - it's set when
1281 * creating a module dso in machine__new_module().
1282 */
1283 return kmod && dso->symtab_type == type;
1284
1285 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
1286 return true;
1287
1288 case DSO_BINARY_TYPE__NOT_FOUND:
1289 default:
1290 return false;
1291 }
1292}
1293
1254int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) 1294int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1255{ 1295{
1256 char *name; 1296 char *name;
@@ -1261,6 +1301,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1261 int ss_pos = 0; 1301 int ss_pos = 0;
1262 struct symsrc ss_[2]; 1302 struct symsrc ss_[2];
1263 struct symsrc *syms_ss = NULL, *runtime_ss = NULL; 1303 struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
1304 bool kmod;
1264 1305
1265 dso__set_loaded(dso, map->type); 1306 dso__set_loaded(dso, map->type);
1266 1307
@@ -1301,7 +1342,11 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1301 if (!name) 1342 if (!name)
1302 return -1; 1343 return -1;
1303 1344
1304 /* Iterate over candidate debug images. 1345 kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
1346 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
1347
1348 /*
1349 * Iterate over candidate debug images.
1305 * Keep track of "interesting" ones (those which have a symtab, dynsym, 1350 * Keep track of "interesting" ones (those which have a symtab, dynsym,
1306 * and/or opd section) for processing. 1351 * and/or opd section) for processing.
1307 */ 1352 */
@@ -1311,6 +1356,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1311 1356
1312 enum dso_binary_type symtab_type = binary_type_symtab[i]; 1357 enum dso_binary_type symtab_type = binary_type_symtab[i];
1313 1358
1359 if (!dso__is_compatible_symtab_type(dso, kmod, symtab_type))
1360 continue;
1361
1314 if (dso__read_binary_type_filename(dso, symtab_type, 1362 if (dso__read_binary_type_filename(dso, symtab_type,
1315 root_dir, name, PATH_MAX)) 1363 root_dir, name, PATH_MAX))
1316 continue; 1364 continue;
@@ -1353,15 +1401,10 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1353 if (!runtime_ss && syms_ss) 1401 if (!runtime_ss && syms_ss)
1354 runtime_ss = syms_ss; 1402 runtime_ss = syms_ss;
1355 1403
1356 if (syms_ss) { 1404 if (syms_ss)
1357 int km; 1405 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, kmod);
1358 1406 else
1359 km = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
1360 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
1361 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, km);
1362 } else {
1363 ret = -1; 1407 ret = -1;
1364 }
1365 1408
1366 if (ret > 0) { 1409 if (ret > 0) {
1367 int nr_plt; 1410 int nr_plt;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index fffe2888a1c7..501e4e722e8e 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -79,6 +79,17 @@ struct symbol {
79void symbol__delete(struct symbol *sym); 79void symbol__delete(struct symbol *sym);
80void symbols__delete(struct rb_root *symbols); 80void symbols__delete(struct rb_root *symbols);
81 81
82/* symbols__for_each_entry - iterate over symbols (rb_root)
83 *
84 * @symbols: the rb_root of symbols
85 * @pos: the 'struct symbol *' to use as a loop cursor
86 * @nd: the 'struct rb_node *' to use as a temporary storage
87 */
88#define symbols__for_each_entry(symbols, pos, nd) \
89 for (nd = rb_first(symbols); \
90 nd && (pos = rb_entry(nd, struct symbol, rb_node)); \
91 nd = rb_next(nd))
92
82static inline size_t symbol__size(const struct symbol *sym) 93static inline size_t symbol__size(const struct symbol *sym)
83{ 94{
84 return sym->end - sym->start + 1; 95 return sym->end - sym->start + 1;
@@ -175,7 +186,7 @@ struct addr_location {
175 struct symbol *sym; 186 struct symbol *sym;
176 u64 addr; 187 u64 addr;
177 char level; 188 char level;
178 bool filtered; 189 u8 filtered;
179 u8 cpumode; 190 u8 cpumode;
180 s32 cpu; 191 s32 cpu;
181}; 192};
@@ -223,7 +234,6 @@ struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
223 u64 addr); 234 u64 addr);
224struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 235struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
225 const char *name); 236 const char *name);
226struct symbol *dso__first_symbol(struct dso *dso, enum map_type type);
227 237
228int filename__read_build_id(const char *filename, void *bf, size_t size); 238int filename__read_build_id(const char *filename, void *bf, size_t size);
229int sysfs__read_build_id(const char *filename, void *bf, size_t size); 239int sysfs__read_build_id(const char *filename, void *bf, size_t size);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 0358882c8910..3ce0498bdae6 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -142,3 +142,24 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
142 142
143 return 0; 143 return 0;
144} 144}
145
146void thread__find_cpumode_addr_location(struct thread *thread,
147 struct machine *machine,
148 enum map_type type, u64 addr,
149 struct addr_location *al)
150{
151 size_t i;
152 const u8 const cpumodes[] = {
153 PERF_RECORD_MISC_USER,
154 PERF_RECORD_MISC_KERNEL,
155 PERF_RECORD_MISC_GUEST_USER,
156 PERF_RECORD_MISC_GUEST_KERNEL
157 };
158
159 for (i = 0; i < ARRAY_SIZE(cpumodes); i++) {
160 thread__find_addr_location(thread, machine, cpumodes[i], type,
161 addr, al);
162 if (al->map)
163 break;
164 }
165}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 5b856bf942e1..9b29f085aede 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -44,12 +44,6 @@ void thread__insert_map(struct thread *thread, struct map *map);
44int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); 44int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
45size_t thread__fprintf(struct thread *thread, FILE *fp); 45size_t thread__fprintf(struct thread *thread, FILE *fp);
46 46
47static inline struct map *thread__find_map(struct thread *thread,
48 enum map_type type, u64 addr)
49{
50 return thread ? map_groups__find(&thread->mg, type, addr) : NULL;
51}
52
53void thread__find_addr_map(struct thread *thread, struct machine *machine, 47void thread__find_addr_map(struct thread *thread, struct machine *machine,
54 u8 cpumode, enum map_type type, u64 addr, 48 u8 cpumode, enum map_type type, u64 addr,
55 struct addr_location *al); 49 struct addr_location *al);
@@ -58,6 +52,11 @@ void thread__find_addr_location(struct thread *thread, struct machine *machine,
58 u8 cpumode, enum map_type type, u64 addr, 52 u8 cpumode, enum map_type type, u64 addr,
59 struct addr_location *al); 53 struct addr_location *al);
60 54
55void thread__find_cpumode_addr_location(struct thread *thread,
56 struct machine *machine,
57 enum map_type type, u64 addr,
58 struct addr_location *al);
59
61static inline void *thread__priv(struct thread *thread) 60static inline void *thread__priv(struct thread *thread)
62{ 61{
63 return thread->priv; 62 return thread->priv;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index e0d6d07f6848..c36636fd825b 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -126,6 +126,7 @@ void event_format__print(struct event_format *event,
126 trace_seq_init(&s); 126 trace_seq_init(&s);
127 pevent_event_info(&s, event, &record); 127 pevent_event_info(&s, event, &record);
128 trace_seq_do_printf(&s); 128 trace_seq_do_printf(&s);
129 trace_seq_destroy(&s);
129} 130}
130 131
131void parse_proc_kallsyms(struct pevent *pevent, 132void parse_proc_kallsyms(struct pevent *pevent,
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
new file mode 100644
index 000000000000..67db73ec3dab
--- /dev/null
+++ b/tools/perf/util/unwind-libdw.c
@@ -0,0 +1,210 @@
1#include <linux/compiler.h>
2#include <elfutils/libdw.h>
3#include <elfutils/libdwfl.h>
4#include <inttypes.h>
5#include <errno.h>
6#include "unwind.h"
7#include "unwind-libdw.h"
8#include "machine.h"
9#include "thread.h"
10#include "types.h"
11#include "event.h"
12#include "perf_regs.h"
13
14static char *debuginfo_path;
15
16static const Dwfl_Callbacks offline_callbacks = {
17 .find_debuginfo = dwfl_standard_find_debuginfo,
18 .debuginfo_path = &debuginfo_path,
19 .section_address = dwfl_offline_section_address,
20};
21
22static int __report_module(struct addr_location *al, u64 ip,
23 struct unwind_info *ui)
24{
25 Dwfl_Module *mod;
26 struct dso *dso = NULL;
27
28 thread__find_addr_location(ui->thread, ui->machine,
29 PERF_RECORD_MISC_USER,
30 MAP__FUNCTION, ip, al);
31
32 if (al->map)
33 dso = al->map->dso;
34
35 if (!dso)
36 return 0;
37
38 mod = dwfl_addrmodule(ui->dwfl, ip);
39 if (!mod)
40 mod = dwfl_report_elf(ui->dwfl, dso->short_name,
41 dso->long_name, -1, al->map->start,
42 false);
43
44 return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1;
45}
46
47static int report_module(u64 ip, struct unwind_info *ui)
48{
49 struct addr_location al;
50
51 return __report_module(&al, ip, ui);
52}
53
54static int entry(u64 ip, struct unwind_info *ui)
55
56{
57 struct unwind_entry e;
58 struct addr_location al;
59
60 if (__report_module(&al, ip, ui))
61 return -1;
62
63 e.ip = ip;
64 e.map = al.map;
65 e.sym = al.sym;
66
67 pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
68 al.sym ? al.sym->name : "''",
69 ip,
70 al.map ? al.map->map_ip(al.map, ip) : (u64) 0);
71
72 return ui->cb(&e, ui->arg);
73}
74
75static pid_t next_thread(Dwfl *dwfl, void *arg, void **thread_argp)
76{
77 /* We want only single thread to be processed. */
78 if (*thread_argp != NULL)
79 return 0;
80
81 *thread_argp = arg;
82 return dwfl_pid(dwfl);
83}
84
85static int access_dso_mem(struct unwind_info *ui, Dwarf_Addr addr,
86 Dwarf_Word *data)
87{
88 struct addr_location al;
89 ssize_t size;
90
91 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
92 MAP__FUNCTION, addr, &al);
93 if (!al.map) {
94 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
95 return -1;
96 }
97
98 if (!al.map->dso)
99 return -1;
100
101 size = dso__data_read_addr(al.map->dso, al.map, ui->machine,
102 addr, (u8 *) data, sizeof(*data));
103
104 return !(size == sizeof(*data));
105}
106
107static bool memory_read(Dwfl *dwfl __maybe_unused, Dwarf_Addr addr, Dwarf_Word *result,
108 void *arg)
109{
110 struct unwind_info *ui = arg;
111 struct stack_dump *stack = &ui->sample->user_stack;
112 u64 start, end;
113 int offset;
114 int ret;
115
116 ret = perf_reg_value(&start, &ui->sample->user_regs, PERF_REG_SP);
117 if (ret)
118 return false;
119
120 end = start + stack->size;
121
122 /* Check overflow. */
123 if (addr + sizeof(Dwarf_Word) < addr)
124 return false;
125
126 if (addr < start || addr + sizeof(Dwarf_Word) > end) {
127 ret = access_dso_mem(ui, addr, result);
128 if (ret) {
129 pr_debug("unwind: access_mem 0x%" PRIx64 " not inside range"
130 " 0x%" PRIx64 "-0x%" PRIx64 "\n",
131 addr, start, end);
132 return false;
133 }
134 return true;
135 }
136
137 offset = addr - start;
138 *result = *(Dwarf_Word *)&stack->data[offset];
139 pr_debug("unwind: access_mem addr 0x%" PRIx64 ", val %lx, offset %d\n",
140 addr, (unsigned long)*result, offset);
141 return true;
142}
143
144static const Dwfl_Thread_Callbacks callbacks = {
145 .next_thread = next_thread,
146 .memory_read = memory_read,
147 .set_initial_registers = libdw__arch_set_initial_registers,
148};
149
150static int
151frame_callback(Dwfl_Frame *state, void *arg)
152{
153 struct unwind_info *ui = arg;
154 Dwarf_Addr pc;
155
156 if (!dwfl_frame_pc(state, &pc, NULL)) {
157 pr_err("%s", dwfl_errmsg(-1));
158 return DWARF_CB_ABORT;
159 }
160
161 return entry(pc, ui) || !(--ui->max_stack) ?
162 DWARF_CB_ABORT : DWARF_CB_OK;
163}
164
165int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
166 struct machine *machine, struct thread *thread,
167 struct perf_sample *data,
168 int max_stack)
169{
170 struct unwind_info ui = {
171 .sample = data,
172 .thread = thread,
173 .machine = machine,
174 .cb = cb,
175 .arg = arg,
176 .max_stack = max_stack,
177 };
178 Dwarf_Word ip;
179 int err = -EINVAL;
180
181 if (!data->user_regs.regs)
182 return -EINVAL;
183
184 ui.dwfl = dwfl_begin(&offline_callbacks);
185 if (!ui.dwfl)
186 goto out;
187
188 err = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP);
189 if (err)
190 goto out;
191
192 err = report_module(ip, &ui);
193 if (err)
194 goto out;
195
196 if (!dwfl_attach_state(ui.dwfl, EM_NONE, thread->tid, &callbacks, &ui))
197 goto out;
198
199 err = dwfl_getthread_frames(ui.dwfl, thread->tid, frame_callback, &ui);
200
201 if (err && !ui.max_stack)
202 err = 0;
203
204 out:
205 if (err)
206 pr_debug("unwind: failed with '%s'\n", dwfl_errmsg(-1));
207
208 dwfl_end(ui.dwfl);
209 return 0;
210}
diff --git a/tools/perf/util/unwind-libdw.h b/tools/perf/util/unwind-libdw.h
new file mode 100644
index 000000000000..417a1426f3ad
--- /dev/null
+++ b/tools/perf/util/unwind-libdw.h
@@ -0,0 +1,21 @@
1#ifndef __PERF_UNWIND_LIBDW_H
2#define __PERF_UNWIND_LIBDW_H
3
4#include <elfutils/libdwfl.h>
5#include "event.h"
6#include "thread.h"
7#include "unwind.h"
8
9bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg);
10
11struct unwind_info {
12 Dwfl *dwfl;
13 struct perf_sample *sample;
14 struct machine *machine;
15 struct thread *thread;
16 unwind_entry_cb_t cb;
17 void *arg;
18 int max_stack;
19};
20
21#endif /* __PERF_UNWIND_LIBDW_H */
diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind-libunwind.c
index 742f23bf35ff..bd5768d74f01 100644
--- a/tools/perf/util/unwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -86,7 +86,6 @@ struct unwind_info {
86 struct perf_sample *sample; 86 struct perf_sample *sample;
87 struct machine *machine; 87 struct machine *machine;
88 struct thread *thread; 88 struct thread *thread;
89 u64 sample_uregs;
90}; 89};
91 90
92#define dw_read(ptr, type, end) ({ \ 91#define dw_read(ptr, type, end) ({ \
@@ -391,30 +390,13 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
391 return !(size == sizeof(*data)); 390 return !(size == sizeof(*data));
392} 391}
393 392
394static int reg_value(unw_word_t *valp, struct regs_dump *regs, int id,
395 u64 sample_regs)
396{
397 int i, idx = 0;
398
399 if (!(sample_regs & (1 << id)))
400 return -EINVAL;
401
402 for (i = 0; i < id; i++) {
403 if (sample_regs & (1 << i))
404 idx++;
405 }
406
407 *valp = regs->regs[idx];
408 return 0;
409}
410
411static int access_mem(unw_addr_space_t __maybe_unused as, 393static int access_mem(unw_addr_space_t __maybe_unused as,
412 unw_word_t addr, unw_word_t *valp, 394 unw_word_t addr, unw_word_t *valp,
413 int __write, void *arg) 395 int __write, void *arg)
414{ 396{
415 struct unwind_info *ui = arg; 397 struct unwind_info *ui = arg;
416 struct stack_dump *stack = &ui->sample->user_stack; 398 struct stack_dump *stack = &ui->sample->user_stack;
417 unw_word_t start, end; 399 u64 start, end;
418 int offset; 400 int offset;
419 int ret; 401 int ret;
420 402
@@ -424,8 +406,7 @@ static int access_mem(unw_addr_space_t __maybe_unused as,
424 return 0; 406 return 0;
425 } 407 }
426 408
427 ret = reg_value(&start, &ui->sample->user_regs, PERF_REG_SP, 409 ret = perf_reg_value(&start, &ui->sample->user_regs, PERF_REG_SP);
428 ui->sample_uregs);
429 if (ret) 410 if (ret)
430 return ret; 411 return ret;
431 412
@@ -438,8 +419,9 @@ static int access_mem(unw_addr_space_t __maybe_unused as,
438 if (addr < start || addr + sizeof(unw_word_t) >= end) { 419 if (addr < start || addr + sizeof(unw_word_t) >= end) {
439 ret = access_dso_mem(ui, addr, valp); 420 ret = access_dso_mem(ui, addr, valp);
440 if (ret) { 421 if (ret) {
441 pr_debug("unwind: access_mem %p not inside range %p-%p\n", 422 pr_debug("unwind: access_mem %p not inside range"
442 (void *)addr, (void *)start, (void *)end); 423 " 0x%" PRIx64 "-0x%" PRIx64 "\n",
424 (void *) addr, start, end);
443 *valp = 0; 425 *valp = 0;
444 return ret; 426 return ret;
445 } 427 }
@@ -448,8 +430,8 @@ static int access_mem(unw_addr_space_t __maybe_unused as,
448 430
449 offset = addr - start; 431 offset = addr - start;
450 *valp = *(unw_word_t *)&stack->data[offset]; 432 *valp = *(unw_word_t *)&stack->data[offset];
451 pr_debug("unwind: access_mem addr %p, val %lx, offset %d\n", 433 pr_debug("unwind: access_mem addr %p val %lx, offset %d\n",
452 (void *)addr, (unsigned long)*valp, offset); 434 (void *) addr, (unsigned long)*valp, offset);
453 return 0; 435 return 0;
454} 436}
455 437
@@ -459,6 +441,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as,
459{ 441{
460 struct unwind_info *ui = arg; 442 struct unwind_info *ui = arg;
461 int id, ret; 443 int id, ret;
444 u64 val;
462 445
463 /* Don't support write, I suspect we don't need it. */ 446 /* Don't support write, I suspect we don't need it. */
464 if (__write) { 447 if (__write) {
@@ -471,16 +454,17 @@ static int access_reg(unw_addr_space_t __maybe_unused as,
471 return 0; 454 return 0;
472 } 455 }
473 456
474 id = unwind__arch_reg_id(regnum); 457 id = libunwind__arch_reg_id(regnum);
475 if (id < 0) 458 if (id < 0)
476 return -EINVAL; 459 return -EINVAL;
477 460
478 ret = reg_value(valp, &ui->sample->user_regs, id, ui->sample_uregs); 461 ret = perf_reg_value(&val, &ui->sample->user_regs, id);
479 if (ret) { 462 if (ret) {
480 pr_err("unwind: can't read reg %d\n", regnum); 463 pr_err("unwind: can't read reg %d\n", regnum);
481 return ret; 464 return ret;
482 } 465 }
483 466
467 *valp = (unw_word_t) val;
484 pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp); 468 pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp);
485 return 0; 469 return 0;
486} 470}
@@ -563,7 +547,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
563 unw_word_t ip; 547 unw_word_t ip;
564 548
565 unw_get_reg(&c, UNW_REG_IP, &ip); 549 unw_get_reg(&c, UNW_REG_IP, &ip);
566 ret = entry(ip, ui->thread, ui->machine, cb, arg); 550 ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0;
567 } 551 }
568 552
569 unw_destroy_addr_space(addr_space); 553 unw_destroy_addr_space(addr_space);
@@ -572,13 +556,11 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
572 556
573int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 557int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
574 struct machine *machine, struct thread *thread, 558 struct machine *machine, struct thread *thread,
575 u64 sample_uregs, struct perf_sample *data, 559 struct perf_sample *data, int max_stack)
576 int max_stack)
577{ 560{
578 unw_word_t ip; 561 u64 ip;
579 struct unwind_info ui = { 562 struct unwind_info ui = {
580 .sample = data, 563 .sample = data,
581 .sample_uregs = sample_uregs,
582 .thread = thread, 564 .thread = thread,
583 .machine = machine, 565 .machine = machine,
584 }; 566 };
@@ -587,7 +569,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
587 if (!data->user_regs.regs) 569 if (!data->user_regs.regs)
588 return -EINVAL; 570 return -EINVAL;
589 571
590 ret = reg_value(&ip, &data->user_regs, PERF_REG_IP, sample_uregs); 572 ret = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP);
591 if (ret) 573 if (ret)
592 return ret; 574 return ret;
593 575
@@ -595,5 +577,5 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
595 if (ret) 577 if (ret)
596 return -ENOMEM; 578 return -ENOMEM;
597 579
598 return get_entries(&ui, cb, arg, max_stack); 580 return --max_stack > 0 ? get_entries(&ui, cb, arg, max_stack) : 0;
599} 581}
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index d5966f49e22c..b031316f221a 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -13,24 +13,25 @@ struct unwind_entry {
13 13
14typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); 14typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
15 15
16#ifdef HAVE_LIBUNWIND_SUPPORT 16#ifdef HAVE_DWARF_UNWIND_SUPPORT
17int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 17int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
18 struct machine *machine, 18 struct machine *machine,
19 struct thread *thread, 19 struct thread *thread,
20 u64 sample_uregs,
21 struct perf_sample *data, int max_stack); 20 struct perf_sample *data, int max_stack);
22int unwind__arch_reg_id(int regnum); 21/* libunwind specific */
22#ifdef HAVE_LIBUNWIND_SUPPORT
23int libunwind__arch_reg_id(int regnum);
24#endif
23#else 25#else
24static inline int 26static inline int
25unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, 27unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
26 void *arg __maybe_unused, 28 void *arg __maybe_unused,
27 struct machine *machine __maybe_unused, 29 struct machine *machine __maybe_unused,
28 struct thread *thread __maybe_unused, 30 struct thread *thread __maybe_unused,
29 u64 sample_uregs __maybe_unused,
30 struct perf_sample *data __maybe_unused, 31 struct perf_sample *data __maybe_unused,
31 int max_stack __maybe_unused) 32 int max_stack __maybe_unused)
32{ 33{
33 return 0; 34 return 0;
34} 35}
35#endif /* HAVE_LIBUNWIND_SUPPORT */ 36#endif /* HAVE_DWARF_UNWIND_SUPPORT */
36#endif /* __UNWIND_H */ 37#endif /* __UNWIND_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 42ad667bb317..9f66549562bd 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,6 +1,6 @@
1#include "../perf.h" 1#include "../perf.h"
2#include "util.h" 2#include "util.h"
3#include "fs.h" 3#include <api/fs/fs.h>
4#include <sys/mman.h> 4#include <sys/mman.h>
5#ifdef HAVE_BACKTRACE_SUPPORT 5#ifdef HAVE_BACKTRACE_SUPPORT
6#include <execinfo.h> 6#include <execinfo.h>
diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile
index d9186a2fdf06..c2c0f20067a5 100644
--- a/tools/power/acpi/Makefile
+++ b/tools/power/acpi/Makefile
@@ -89,15 +89,6 @@ else
89 STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment 89 STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment
90endif 90endif
91 91
92# if DEBUG is enabled, then we do not strip or optimize
93ifeq ($(strip $(DEBUG)),true)
94 CFLAGS += -O1 -g -DDEBUG
95 STRIPCMD = /bin/true -Since_we_are_debugging
96else
97 CFLAGS += $(OPTIMIZATION) -fomit-frame-pointer
98 STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment
99endif
100
101# --- ACPIDUMP BEGIN --- 92# --- ACPIDUMP BEGIN ---
102 93
103vpath %.c \ 94vpath %.c \
@@ -128,7 +119,7 @@ clean:
128 -rm -f $(OUTPUT)acpidump 119 -rm -f $(OUTPUT)acpidump
129 120
130install-tools: 121install-tools:
131 $(INSTALL) -d $(DESTDIR)${bindir} 122 $(INSTALL) -d $(DESTDIR)${sbindir}
132 $(INSTALL_PROGRAM) $(OUTPUT)acpidump $(DESTDIR)${sbindir} 123 $(INSTALL_PROGRAM) $(OUTPUT)acpidump $(DESTDIR)${sbindir}
133 124
134install-man: 125install-man:
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index b4ddb748356c..56bfb523c5bb 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -47,21 +47,22 @@ displays the statistics gathered since it was forked.
47.PP 47.PP
48.SH FIELD DESCRIPTIONS 48.SH FIELD DESCRIPTIONS
49.nf 49.nf
50\fBpk\fP processor package number. 50\fBPackage\fP processor package number.
51\fBcor\fP processor core number. 51\fBCore\fP processor core number.
52\fBCPU\fP Linux CPU (logical processor) number. 52\fBCPU\fP Linux CPU (logical processor) number.
53Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology. 53Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology.
54\fB%c0\fP percent of the interval that the CPU retired instructions. 54\fBAVG_MHz\fP number of cycles executed divided by time elapsed.
55\fBGHz\fP average clock rate while the CPU was in c0 state. 55\fB%Buzy\fP percent of the interval that the CPU retired instructions, aka. % of time in "C0" state.
56\fBTSC\fP average GHz that the TSC ran during the entire interval. 56\fBBzy_MHz\fP average clock rate while the CPU was busy (in "c0" state).
57\fB%c1, %c3, %c6, %c7\fP show the percentage residency in hardware core idle states. 57\fBTSC_MHz\fP average MHz that the TSC ran during the entire interval.
58\fBCTMP\fP Degrees Celsius reported by the per-core Digital Thermal Sensor. 58\fBCPU%c1, CPU%c3, CPU%c6, CPU%c7\fP show the percentage residency in hardware core idle states.
59\fBPTMP\fP Degrees Celsius reported by the per-package Package Thermal Monitor. 59\fBCoreTmp\fP Degrees Celsius reported by the per-core Digital Thermal Sensor.
60\fB%pc2, %pc3, %pc6, %pc7\fP percentage residency in hardware package idle states. 60\fBPkgTtmp\fP Degrees Celsius reported by the per-package Package Thermal Monitor.
61\fBPkg_W\fP Watts consumed by the whole package. 61\fBPkg%pc2, Pkg%pc3, Pkg%pc6, Pkg%pc7\fP percentage residency in hardware package idle states.
62\fBCor_W\fP Watts consumed by the core part of the package. 62\fBPkgWatt\fP Watts consumed by the whole package.
63\fBGFX_W\fP Watts consumed by the Graphics part of the package -- available only on client processors. 63\fBCorWatt\fP Watts consumed by the core part of the package.
64\fBRAM_W\fP Watts consumed by the DRAM DIMMS -- available only on server processors. 64\fBGFXWatt\fP Watts consumed by the Graphics part of the package -- available only on client processors.
65\fBRAMWatt\fP Watts consumed by the DRAM DIMMS -- available only on server processors.
65\fBPKG_%\fP percent of the interval that RAPL throttling was active on the Package. 66\fBPKG_%\fP percent of the interval that RAPL throttling was active on the Package.
66\fBRAM_%\fP percent of the interval that RAPL throttling was active on DRAM. 67\fBRAM_%\fP percent of the interval that RAPL throttling was active on DRAM.
67.fi 68.fi
@@ -78,29 +79,17 @@ For Watts columns, the summary is a system total.
78Subsequent rows show per-CPU statistics. 79Subsequent rows show per-CPU statistics.
79 80
80.nf 81.nf
81[root@sandy]# ./turbostat 82[root@ivy]# ./turbostat
82cor CPU %c0 GHz TSC %c1 %c3 %c6 %c7 CTMP PTMP %pc2 %pc3 %pc6 %pc7 Pkg_W Cor_W GFX_W 83 Core CPU Avg_MHz %Busy Bzy_MHz TSC_MHz SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt
83 0.06 0.80 2.29 0.11 0.00 0.00 99.83 47 40 0.26 0.01 0.44 98.78 3.49 0.12 0.14 84 - - 6 0.36 1596 3492 0 0.59 0.01 99.04 0.00 23 24 23.82 0.01 72.47 0.00 6.40 1.01 0.00
84 0 0 0.07 0.80 2.29 0.07 0.00 0.00 99.86 40 40 0.26 0.01 0.44 98.78 3.49 0.12 0.14 85 0 0 9 0.58 1596 3492 0 0.28 0.01 99.13 0.00 23 24 23.82 0.01 72.47 0.00 6.40 1.01 0.00
85 0 4 0.03 0.80 2.29 0.12 86 0 4 1 0.07 1596 3492 0 0.79
86 1 1 0.04 0.80 2.29 0.25 0.01 0.00 99.71 40 87 1 1 10 0.65 1596 3492 0 0.59 0.00 98.76 0.00 23
87 1 5 0.16 0.80 2.29 0.13 88 1 5 5 0.28 1596 3492 0 0.95
88 2 2 0.05 0.80 2.29 0.06 0.01 0.00 99.88 40 89 2 2 10 0.66 1596 3492 0 0.41 0.01 98.92 0.00 23
89 2 6 0.03 0.80 2.29 0.08 90 2 6 2 0.10 1597 3492 0 0.97
90 3 3 0.05 0.80 2.29 0.08 0.00 0.00 99.87 47 91 3 3 3 0.20 1596 3492 0 0.44 0.00 99.37 0.00 23
91 3 7 0.04 0.84 2.29 0.09 92 3 7 5 0.31 1596 3492 0 0.33
92.fi
93.SH SUMMARY EXAMPLE
94The "-s" option prints the column headers just once,
95and then the one line system summary for each sample interval.
96
97.nf
98[root@wsm]# turbostat -S
99 %c0 GHz TSC %c1 %c3 %c6 CTMP %pc3 %pc6
100 1.40 2.81 3.38 10.78 43.47 44.35 42 13.67 2.09
101 1.34 2.90 3.38 11.48 58.96 28.23 41 19.89 0.15
102 1.55 2.72 3.38 26.73 37.66 34.07 42 2.53 2.80
103 1.37 2.83 3.38 16.95 60.05 21.63 42 5.76 0.20
104.fi 93.fi
105.SH VERBOSE EXAMPLE 94.SH VERBOSE EXAMPLE
106The "-v" option adds verbosity to the output: 95The "-v" option adds verbosity to the output:
@@ -154,55 +143,35 @@ eg. Here a cycle soaker is run on 1 CPU (see %c0) for a few seconds
154until ^C while the other CPUs are mostly idle: 143until ^C while the other CPUs are mostly idle:
155 144
156.nf 145.nf
157[root@x980 lenb]# ./turbostat cat /dev/zero > /dev/null 146root@ivy: turbostat cat /dev/zero > /dev/null
158^C 147^C
159cor CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6 148 Core CPU Avg_MHz %Busy Bzy_MHz TSC_MHz SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt
160 8.86 3.61 3.38 15.06 31.19 44.89 0.00 0.00 149 - - 496 12.75 3886 3492 0 13.16 0.04 74.04 0.00 36 36 0.00 0.00 0.00 0.00 23.15 17.65 0.00
161 0 0 1.46 3.22 3.38 16.84 29.48 52.22 0.00 0.00 150 0 0 22 0.57 3830 3492 0 0.83 0.02 98.59 0.00 27 36 0.00 0.00 0.00 0.00 23.15 17.65 0.00
162 0 6 0.21 3.06 3.38 18.09 151 0 4 9 0.24 3829 3492 0 1.15
163 1 2 0.53 3.33 3.38 2.80 46.40 50.27 152 1 1 4 0.09 3783 3492 0 99.91 0.00 0.00 0.00 36
164 1 8 0.89 3.47 3.38 2.44 153 1 5 3880 99.82 3888 3492 0 0.18
165 2 4 1.36 3.43 3.38 9.04 23.71 65.89 154 2 2 17 0.44 3813 3492 0 0.77 0.04 98.75 0.00 28
166 2 10 0.18 2.86 3.38 10.22 155 2 6 12 0.32 3823 3492 0 0.89
167 8 1 0.04 2.87 3.38 99.96 0.01 0.00 156 3 3 16 0.43 3844 3492 0 0.63 0.11 98.84 0.00 30
168 8 7 99.72 3.63 3.38 0.27 157 3 7 4 0.11 3827 3492 0 0.94
169 9 3 0.31 3.21 3.38 7.64 56.55 35.50 15830.372243 sec
170 9 9 0.08 2.95 3.38 7.88 159
171 10 5 1.42 3.43 3.38 2.14 30.99 65.44
172 10 11 0.16 2.88 3.38 3.40
173.fi 160.fi
174Above the cycle soaker drives cpu7 up its 3.6 GHz turbo limit 161Above the cycle soaker drives cpu5 up its 3.8 GHz turbo limit
175while the other processors are generally in various states of idle. 162while the other processors are generally in various states of idle.
176 163
177Note that cpu1 and cpu7 are HT siblings within core8. 164Note that cpu1 and cpu5 are HT siblings within core1.
178As cpu7 is very busy, it prevents its sibling, cpu1, 165As cpu5 is very busy, it prevents its sibling, cpu1,
179from entering a c-state deeper than c1. 166from entering a c-state deeper than c1.
180 167
181Note that turbostat reports average GHz of 3.63, while 168Note that the Avg_MHz column reflects the total number of cycles executed
182the arithmetic average of the GHz column above is lower. 169divided by the measurement interval. If the %Busy column is 100%,
183This is a weighted average, where the weight is %c0. ie. it is the total number of 170then the processor was running at that speed the entire interval.
184un-halted cycles elapsed per time divided by the number of CPUs. 171The Avg_MHz multiplied by the %Busy results in the Bzy_MHz --
185.SH SMI COUNTING EXAMPLE 172which is the average frequency while the processor was executing --
186On Intel Nehalem and newer processors, MSR 0x34 is a System Management Mode Interrupt (SMI) counter. 173not including any non-busy idle time.
187This counter is shown by default under the "SMI" column. 174
188.nf
189[root@x980 ~]# turbostat
190cor CPU %c0 GHz TSC SMI %c1 %c3 %c6 CTMP %pc3 %pc6
191 0.11 1.91 3.38 0 1.84 0.26 97.79 29 0.82 83.87
192 0 0 0.40 1.63 3.38 0 10.27 0.12 89.20 20 0.82 83.88
193 0 6 0.06 1.63 3.38 0 10.61
194 1 2 0.37 2.63 3.38 0 0.02 0.10 99.51 22
195 1 8 0.01 1.62 3.38 0 0.39
196 2 4 0.07 1.62 3.38 0 0.04 0.07 99.82 23
197 2 10 0.02 1.62 3.38 0 0.09
198 8 1 0.23 1.64 3.38 0 0.10 1.07 98.60 24
199 8 7 0.02 1.64 3.38 0 0.31
200 9 3 0.03 1.62 3.38 0 0.03 0.05 99.89 29
201 9 9 0.02 1.62 3.38 0 0.05
202 10 5 0.07 1.62 3.38 0 0.08 0.12 99.73 27
203 10 11 0.03 1.62 3.38 0 0.13
204^C
205.fi
206.SH NOTES 175.SH NOTES
207 176
208.B "turbostat " 177.B "turbostat "
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 77eb130168da..7c9d8e71eb9e 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -56,7 +56,7 @@ unsigned int do_slm_cstates;
56unsigned int use_c1_residency_msr; 56unsigned int use_c1_residency_msr;
57unsigned int has_aperf; 57unsigned int has_aperf;
58unsigned int has_epb; 58unsigned int has_epb;
59unsigned int units = 1000000000; /* Ghz etc */ 59unsigned int units = 1000000; /* MHz etc */
60unsigned int genuine_intel; 60unsigned int genuine_intel;
61unsigned int has_invariant_tsc; 61unsigned int has_invariant_tsc;
62unsigned int do_nehalem_platform_info; 62unsigned int do_nehalem_platform_info;
@@ -264,88 +264,93 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
264 return 0; 264 return 0;
265} 265}
266 266
267/*
268 * Example Format w/ field column widths:
269 *
270 * Package Core CPU Avg_MHz Bzy_MHz TSC_MHz SMI %Busy CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt
271 * 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567
272 */
273
267void print_header(void) 274void print_header(void)
268{ 275{
269 if (show_pkg) 276 if (show_pkg)
270 outp += sprintf(outp, "pk"); 277 outp += sprintf(outp, "Package ");
271 if (show_pkg)
272 outp += sprintf(outp, " ");
273 if (show_core) 278 if (show_core)
274 outp += sprintf(outp, "cor"); 279 outp += sprintf(outp, " Core ");
275 if (show_cpu) 280 if (show_cpu)
276 outp += sprintf(outp, " CPU"); 281 outp += sprintf(outp, " CPU ");
277 if (show_pkg || show_core || show_cpu) 282 if (has_aperf)
278 outp += sprintf(outp, " "); 283 outp += sprintf(outp, "Avg_MHz ");
279 if (do_nhm_cstates) 284 if (do_nhm_cstates)
280 outp += sprintf(outp, " %%c0"); 285 outp += sprintf(outp, " %%Busy ");
281 if (has_aperf) 286 if (has_aperf)
282 outp += sprintf(outp, " GHz"); 287 outp += sprintf(outp, "Bzy_MHz ");
283 outp += sprintf(outp, " TSC"); 288 outp += sprintf(outp, "TSC_MHz ");
284 if (do_smi) 289 if (do_smi)
285 outp += sprintf(outp, " SMI"); 290 outp += sprintf(outp, " SMI ");
286 if (extra_delta_offset32) 291 if (extra_delta_offset32)
287 outp += sprintf(outp, " count 0x%03X", extra_delta_offset32); 292 outp += sprintf(outp, " count 0x%03X ", extra_delta_offset32);
288 if (extra_delta_offset64) 293 if (extra_delta_offset64)
289 outp += sprintf(outp, " COUNT 0x%03X", extra_delta_offset64); 294 outp += sprintf(outp, " COUNT 0x%03X ", extra_delta_offset64);
290 if (extra_msr_offset32) 295 if (extra_msr_offset32)
291 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32); 296 outp += sprintf(outp, " MSR 0x%03X ", extra_msr_offset32);
292 if (extra_msr_offset64) 297 if (extra_msr_offset64)
293 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64); 298 outp += sprintf(outp, " MSR 0x%03X ", extra_msr_offset64);
294 if (do_nhm_cstates) 299 if (do_nhm_cstates)
295 outp += sprintf(outp, " %%c1"); 300 outp += sprintf(outp, " CPU%%c1 ");
296 if (do_nhm_cstates && !do_slm_cstates) 301 if (do_nhm_cstates && !do_slm_cstates)
297 outp += sprintf(outp, " %%c3"); 302 outp += sprintf(outp, " CPU%%c3 ");
298 if (do_nhm_cstates) 303 if (do_nhm_cstates)
299 outp += sprintf(outp, " %%c6"); 304 outp += sprintf(outp, " CPU%%c6 ");
300 if (do_snb_cstates) 305 if (do_snb_cstates)
301 outp += sprintf(outp, " %%c7"); 306 outp += sprintf(outp, " CPU%%c7 ");
302 307
303 if (do_dts) 308 if (do_dts)
304 outp += sprintf(outp, " CTMP"); 309 outp += sprintf(outp, "CoreTmp ");
305 if (do_ptm) 310 if (do_ptm)
306 outp += sprintf(outp, " PTMP"); 311 outp += sprintf(outp, " PkgTmp ");
307 312
308 if (do_snb_cstates) 313 if (do_snb_cstates)
309 outp += sprintf(outp, " %%pc2"); 314 outp += sprintf(outp, "Pkg%%pc2 ");
310 if (do_nhm_cstates && !do_slm_cstates) 315 if (do_nhm_cstates && !do_slm_cstates)
311 outp += sprintf(outp, " %%pc3"); 316 outp += sprintf(outp, "Pkg%%pc3 ");
312 if (do_nhm_cstates && !do_slm_cstates) 317 if (do_nhm_cstates && !do_slm_cstates)
313 outp += sprintf(outp, " %%pc6"); 318 outp += sprintf(outp, "Pkg%%pc6 ");
314 if (do_snb_cstates) 319 if (do_snb_cstates)
315 outp += sprintf(outp, " %%pc7"); 320 outp += sprintf(outp, "Pkg%%pc7 ");
316 if (do_c8_c9_c10) { 321 if (do_c8_c9_c10) {
317 outp += sprintf(outp, " %%pc8"); 322 outp += sprintf(outp, "Pkg%%pc8 ");
318 outp += sprintf(outp, " %%pc9"); 323 outp += sprintf(outp, "Pkg%%pc9 ");
319 outp += sprintf(outp, " %%pc10"); 324 outp += sprintf(outp, "Pk%%pc10 ");
320 } 325 }
321 326
322 if (do_rapl && !rapl_joules) { 327 if (do_rapl && !rapl_joules) {
323 if (do_rapl & RAPL_PKG) 328 if (do_rapl & RAPL_PKG)
324 outp += sprintf(outp, " Pkg_W"); 329 outp += sprintf(outp, "PkgWatt ");
325 if (do_rapl & RAPL_CORES) 330 if (do_rapl & RAPL_CORES)
326 outp += sprintf(outp, " Cor_W"); 331 outp += sprintf(outp, "CorWatt ");
327 if (do_rapl & RAPL_GFX) 332 if (do_rapl & RAPL_GFX)
328 outp += sprintf(outp, " GFX_W"); 333 outp += sprintf(outp, "GFXWatt ");
329 if (do_rapl & RAPL_DRAM) 334 if (do_rapl & RAPL_DRAM)
330 outp += sprintf(outp, " RAM_W"); 335 outp += sprintf(outp, "RAMWatt ");
331 if (do_rapl & RAPL_PKG_PERF_STATUS) 336 if (do_rapl & RAPL_PKG_PERF_STATUS)
332 outp += sprintf(outp, " PKG_%%"); 337 outp += sprintf(outp, " PKG_%% ");
333 if (do_rapl & RAPL_DRAM_PERF_STATUS) 338 if (do_rapl & RAPL_DRAM_PERF_STATUS)
334 outp += sprintf(outp, " RAM_%%"); 339 outp += sprintf(outp, " RAM_%% ");
335 } else { 340 } else {
336 if (do_rapl & RAPL_PKG) 341 if (do_rapl & RAPL_PKG)
337 outp += sprintf(outp, " Pkg_J"); 342 outp += sprintf(outp, " Pkg_J ");
338 if (do_rapl & RAPL_CORES) 343 if (do_rapl & RAPL_CORES)
339 outp += sprintf(outp, " Cor_J"); 344 outp += sprintf(outp, " Cor_J ");
340 if (do_rapl & RAPL_GFX) 345 if (do_rapl & RAPL_GFX)
341 outp += sprintf(outp, " GFX_J"); 346 outp += sprintf(outp, " GFX_J ");
342 if (do_rapl & RAPL_DRAM) 347 if (do_rapl & RAPL_DRAM)
343 outp += sprintf(outp, " RAM_W"); 348 outp += sprintf(outp, " RAM_W ");
344 if (do_rapl & RAPL_PKG_PERF_STATUS) 349 if (do_rapl & RAPL_PKG_PERF_STATUS)
345 outp += sprintf(outp, " PKG_%%"); 350 outp += sprintf(outp, " PKG_%% ");
346 if (do_rapl & RAPL_DRAM_PERF_STATUS) 351 if (do_rapl & RAPL_DRAM_PERF_STATUS)
347 outp += sprintf(outp, " RAM_%%"); 352 outp += sprintf(outp, " RAM_%% ");
348 outp += sprintf(outp, " time"); 353 outp += sprintf(outp, " time ");
349 354
350 } 355 }
351 outp += sprintf(outp, "\n"); 356 outp += sprintf(outp, "\n");
@@ -410,25 +415,12 @@ int dump_counters(struct thread_data *t, struct core_data *c,
410 415
411/* 416/*
412 * column formatting convention & formats 417 * column formatting convention & formats
413 * package: "pk" 2 columns %2d
414 * core: "cor" 3 columns %3d
415 * CPU: "CPU" 3 columns %3d
416 * Pkg_W: %6.2
417 * Cor_W: %6.2
418 * GFX_W: %5.2
419 * RAM_W: %5.2
420 * GHz: "GHz" 3 columns %3.2
421 * TSC: "TSC" 3 columns %3.2
422 * SMI: "SMI" 4 columns %4d
423 * percentage " %pc3" %6.2
424 * Perf Status percentage: %5.2
425 * "CTMP" 4 columns %4d
426 */ 418 */
427int format_counters(struct thread_data *t, struct core_data *c, 419int format_counters(struct thread_data *t, struct core_data *c,
428 struct pkg_data *p) 420 struct pkg_data *p)
429{ 421{
430 double interval_float; 422 double interval_float;
431 char *fmt5, *fmt6; 423 char *fmt8;
432 424
433 /* if showing only 1st thread in core and this isn't one, bail out */ 425 /* if showing only 1st thread in core and this isn't one, bail out */
434 if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 426 if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
@@ -443,65 +435,52 @@ int format_counters(struct thread_data *t, struct core_data *c,
443 /* topo columns, print blanks on 1st (average) line */ 435 /* topo columns, print blanks on 1st (average) line */
444 if (t == &average.threads) { 436 if (t == &average.threads) {
445 if (show_pkg) 437 if (show_pkg)
446 outp += sprintf(outp, " "); 438 outp += sprintf(outp, " -");
447 if (show_pkg && show_core)
448 outp += sprintf(outp, " ");
449 if (show_core) 439 if (show_core)
450 outp += sprintf(outp, " "); 440 outp += sprintf(outp, " -");
451 if (show_cpu) 441 if (show_cpu)
452 outp += sprintf(outp, " " " "); 442 outp += sprintf(outp, " -");
453 } else { 443 } else {
454 if (show_pkg) { 444 if (show_pkg) {
455 if (p) 445 if (p)
456 outp += sprintf(outp, "%2d", p->package_id); 446 outp += sprintf(outp, "%8d", p->package_id);
457 else 447 else
458 outp += sprintf(outp, " "); 448 outp += sprintf(outp, " -");
459 } 449 }
460 if (show_pkg && show_core)
461 outp += sprintf(outp, " ");
462 if (show_core) { 450 if (show_core) {
463 if (c) 451 if (c)
464 outp += sprintf(outp, "%3d", c->core_id); 452 outp += sprintf(outp, "%8d", c->core_id);
465 else 453 else
466 outp += sprintf(outp, " "); 454 outp += sprintf(outp, " -");
467 } 455 }
468 if (show_cpu) 456 if (show_cpu)
469 outp += sprintf(outp, " %3d", t->cpu_id); 457 outp += sprintf(outp, "%8d", t->cpu_id);
470 } 458 }
459
460 /* AvgMHz */
461 if (has_aperf)
462 outp += sprintf(outp, "%8.0f",
463 1.0 / units * t->aperf / interval_float);
464
471 /* %c0 */ 465 /* %c0 */
472 if (do_nhm_cstates) { 466 if (do_nhm_cstates) {
473 if (show_pkg || show_core || show_cpu)
474 outp += sprintf(outp, " ");
475 if (!skip_c0) 467 if (!skip_c0)
476 outp += sprintf(outp, "%6.2f", 100.0 * t->mperf/t->tsc); 468 outp += sprintf(outp, "%8.2f", 100.0 * t->mperf/t->tsc);
477 else 469 else
478 outp += sprintf(outp, " ****"); 470 outp += sprintf(outp, "********");
479 } 471 }
480 472
481 /* GHz */ 473 /* BzyMHz */
482 if (has_aperf) { 474 if (has_aperf)
483 if (!aperf_mperf_unstable) { 475 outp += sprintf(outp, "%8.0f",
484 outp += sprintf(outp, " %3.2f", 476 1.0 * t->tsc / units * t->aperf / t->mperf / interval_float);
485 1.0 * t->tsc / units * t->aperf /
486 t->mperf / interval_float);
487 } else {
488 if (t->aperf > t->tsc || t->mperf > t->tsc) {
489 outp += sprintf(outp, " ***");
490 } else {
491 outp += sprintf(outp, "%3.1f*",
492 1.0 * t->tsc /
493 units * t->aperf /
494 t->mperf / interval_float);
495 }
496 }
497 }
498 477
499 /* TSC */ 478 /* TSC */
500 outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float); 479 outp += sprintf(outp, "%8.0f", 1.0 * t->tsc/units/interval_float);
501 480
502 /* SMI */ 481 /* SMI */
503 if (do_smi) 482 if (do_smi)
504 outp += sprintf(outp, "%4d", t->smi_count); 483 outp += sprintf(outp, "%8d", t->smi_count);
505 484
506 /* delta */ 485 /* delta */
507 if (extra_delta_offset32) 486 if (extra_delta_offset32)
@@ -520,9 +499,9 @@ int format_counters(struct thread_data *t, struct core_data *c,
520 499
521 if (do_nhm_cstates) { 500 if (do_nhm_cstates) {
522 if (!skip_c1) 501 if (!skip_c1)
523 outp += sprintf(outp, " %6.2f", 100.0 * t->c1/t->tsc); 502 outp += sprintf(outp, "%8.2f", 100.0 * t->c1/t->tsc);
524 else 503 else
525 outp += sprintf(outp, " ****"); 504 outp += sprintf(outp, "********");
526 } 505 }
527 506
528 /* print per-core data only for 1st thread in core */ 507 /* print per-core data only for 1st thread in core */
@@ -530,79 +509,76 @@ int format_counters(struct thread_data *t, struct core_data *c,
530 goto done; 509 goto done;
531 510
532 if (do_nhm_cstates && !do_slm_cstates) 511 if (do_nhm_cstates && !do_slm_cstates)
533 outp += sprintf(outp, " %6.2f", 100.0 * c->c3/t->tsc); 512 outp += sprintf(outp, "%8.2f", 100.0 * c->c3/t->tsc);
534 if (do_nhm_cstates) 513 if (do_nhm_cstates)
535 outp += sprintf(outp, " %6.2f", 100.0 * c->c6/t->tsc); 514 outp += sprintf(outp, "%8.2f", 100.0 * c->c6/t->tsc);
536 if (do_snb_cstates) 515 if (do_snb_cstates)
537 outp += sprintf(outp, " %6.2f", 100.0 * c->c7/t->tsc); 516 outp += sprintf(outp, "%8.2f", 100.0 * c->c7/t->tsc);
538 517
539 if (do_dts) 518 if (do_dts)
540 outp += sprintf(outp, " %4d", c->core_temp_c); 519 outp += sprintf(outp, "%8d", c->core_temp_c);
541 520
542 /* print per-package data only for 1st core in package */ 521 /* print per-package data only for 1st core in package */
543 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 522 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
544 goto done; 523 goto done;
545 524
546 if (do_ptm) 525 if (do_ptm)
547 outp += sprintf(outp, " %4d", p->pkg_temp_c); 526 outp += sprintf(outp, "%8d", p->pkg_temp_c);
548 527
549 if (do_snb_cstates) 528 if (do_snb_cstates)
550 outp += sprintf(outp, " %6.2f", 100.0 * p->pc2/t->tsc); 529 outp += sprintf(outp, "%8.2f", 100.0 * p->pc2/t->tsc);
551 if (do_nhm_cstates && !do_slm_cstates) 530 if (do_nhm_cstates && !do_slm_cstates)
552 outp += sprintf(outp, " %6.2f", 100.0 * p->pc3/t->tsc); 531 outp += sprintf(outp, "%8.2f", 100.0 * p->pc3/t->tsc);
553 if (do_nhm_cstates && !do_slm_cstates) 532 if (do_nhm_cstates && !do_slm_cstates)
554 outp += sprintf(outp, " %6.2f", 100.0 * p->pc6/t->tsc); 533 outp += sprintf(outp, "%8.2f", 100.0 * p->pc6/t->tsc);
555 if (do_snb_cstates) 534 if (do_snb_cstates)
556 outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc); 535 outp += sprintf(outp, "%8.2f", 100.0 * p->pc7/t->tsc);
557 if (do_c8_c9_c10) { 536 if (do_c8_c9_c10) {
558 outp += sprintf(outp, " %6.2f", 100.0 * p->pc8/t->tsc); 537 outp += sprintf(outp, "%8.2f", 100.0 * p->pc8/t->tsc);
559 outp += sprintf(outp, " %6.2f", 100.0 * p->pc9/t->tsc); 538 outp += sprintf(outp, "%8.2f", 100.0 * p->pc9/t->tsc);
560 outp += sprintf(outp, " %6.2f", 100.0 * p->pc10/t->tsc); 539 outp += sprintf(outp, "%8.2f", 100.0 * p->pc10/t->tsc);
561 } 540 }
562 541
563 /* 542 /*
564 * If measurement interval exceeds minimum RAPL Joule Counter range, 543 * If measurement interval exceeds minimum RAPL Joule Counter range,
565 * indicate that results are suspect by printing "**" in fraction place. 544 * indicate that results are suspect by printing "**" in fraction place.
566 */ 545 */
567 if (interval_float < rapl_joule_counter_range) { 546 if (interval_float < rapl_joule_counter_range)
568 fmt5 = " %5.2f"; 547 fmt8 = "%8.2f";
569 fmt6 = " %6.2f"; 548 else
570 } else { 549 fmt8 = " %6.0f**";
571 fmt5 = " %3.0f**";
572 fmt6 = " %4.0f**";
573 }
574 550
575 if (do_rapl && !rapl_joules) { 551 if (do_rapl && !rapl_joules) {
576 if (do_rapl & RAPL_PKG) 552 if (do_rapl & RAPL_PKG)
577 outp += sprintf(outp, fmt6, p->energy_pkg * rapl_energy_units / interval_float); 553 outp += sprintf(outp, fmt8, p->energy_pkg * rapl_energy_units / interval_float);
578 if (do_rapl & RAPL_CORES) 554 if (do_rapl & RAPL_CORES)
579 outp += sprintf(outp, fmt6, p->energy_cores * rapl_energy_units / interval_float); 555 outp += sprintf(outp, fmt8, p->energy_cores * rapl_energy_units / interval_float);
580 if (do_rapl & RAPL_GFX) 556 if (do_rapl & RAPL_GFX)
581 outp += sprintf(outp, fmt5, p->energy_gfx * rapl_energy_units / interval_float); 557 outp += sprintf(outp, fmt8, p->energy_gfx * rapl_energy_units / interval_float);
582 if (do_rapl & RAPL_DRAM) 558 if (do_rapl & RAPL_DRAM)
583 outp += sprintf(outp, fmt5, p->energy_dram * rapl_energy_units / interval_float); 559 outp += sprintf(outp, fmt8, p->energy_dram * rapl_energy_units / interval_float);
584 if (do_rapl & RAPL_PKG_PERF_STATUS) 560 if (do_rapl & RAPL_PKG_PERF_STATUS)
585 outp += sprintf(outp, fmt5, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); 561 outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
586 if (do_rapl & RAPL_DRAM_PERF_STATUS) 562 if (do_rapl & RAPL_DRAM_PERF_STATUS)
587 outp += sprintf(outp, fmt5, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); 563 outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
588 } else { 564 } else {
589 if (do_rapl & RAPL_PKG) 565 if (do_rapl & RAPL_PKG)
590 outp += sprintf(outp, fmt6, 566 outp += sprintf(outp, fmt8,
591 p->energy_pkg * rapl_energy_units); 567 p->energy_pkg * rapl_energy_units);
592 if (do_rapl & RAPL_CORES) 568 if (do_rapl & RAPL_CORES)
593 outp += sprintf(outp, fmt6, 569 outp += sprintf(outp, fmt8,
594 p->energy_cores * rapl_energy_units); 570 p->energy_cores * rapl_energy_units);
595 if (do_rapl & RAPL_GFX) 571 if (do_rapl & RAPL_GFX)
596 outp += sprintf(outp, fmt5, 572 outp += sprintf(outp, fmt8,
597 p->energy_gfx * rapl_energy_units); 573 p->energy_gfx * rapl_energy_units);
598 if (do_rapl & RAPL_DRAM) 574 if (do_rapl & RAPL_DRAM)
599 outp += sprintf(outp, fmt5, 575 outp += sprintf(outp, fmt8,
600 p->energy_dram * rapl_energy_units); 576 p->energy_dram * rapl_energy_units);
601 if (do_rapl & RAPL_PKG_PERF_STATUS) 577 if (do_rapl & RAPL_PKG_PERF_STATUS)
602 outp += sprintf(outp, fmt5, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); 578 outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
603 if (do_rapl & RAPL_DRAM_PERF_STATUS) 579 if (do_rapl & RAPL_DRAM_PERF_STATUS)
604 outp += sprintf(outp, fmt5, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); 580 outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
605 outp += sprintf(outp, fmt5, interval_float); 581 outp += sprintf(outp, fmt8, interval_float);
606 582
607 } 583 }
608done: 584done:
@@ -1516,6 +1492,9 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
1516 case 0x46: /* HSW */ 1492 case 0x46: /* HSW */
1517 case 0x37: /* BYT */ 1493 case 0x37: /* BYT */
1518 case 0x4D: /* AVN */ 1494 case 0x4D: /* AVN */
1495 case 0x3D: /* BDW */
1496 case 0x4F: /* BDX */
1497 case 0x56: /* BDX-DE */
1519 return 1; 1498 return 1;
1520 case 0x2E: /* Nehalem-EX Xeon - Beckton */ 1499 case 0x2E: /* Nehalem-EX Xeon - Beckton */
1521 case 0x2F: /* Westmere-EX Xeon - Eagleton */ 1500 case 0x2F: /* Westmere-EX Xeon - Eagleton */
@@ -1629,9 +1608,12 @@ void rapl_probe(unsigned int family, unsigned int model)
1629 case 0x3C: /* HSW */ 1608 case 0x3C: /* HSW */
1630 case 0x45: /* HSW */ 1609 case 0x45: /* HSW */
1631 case 0x46: /* HSW */ 1610 case 0x46: /* HSW */
1611 case 0x3D: /* BDW */
1632 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO; 1612 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO;
1633 break; 1613 break;
1634 case 0x3F: /* HSX */ 1614 case 0x3F: /* HSX */
1615 case 0x4F: /* BDX */
1616 case 0x56: /* BDX-DE */
1635 do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO; 1617 do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
1636 break; 1618 break;
1637 case 0x2D: 1619 case 0x2D:
@@ -1875,6 +1857,9 @@ int is_snb(unsigned int family, unsigned int model)
1875 case 0x3F: /* HSW */ 1857 case 0x3F: /* HSW */
1876 case 0x45: /* HSW */ 1858 case 0x45: /* HSW */
1877 case 0x46: /* HSW */ 1859 case 0x46: /* HSW */
1860 case 0x3D: /* BDW */
1861 case 0x4F: /* BDX */
1862 case 0x56: /* BDX-DE */
1878 return 1; 1863 return 1;
1879 } 1864 }
1880 return 0; 1865 return 0;
@@ -1886,7 +1871,8 @@ int has_c8_c9_c10(unsigned int family, unsigned int model)
1886 return 0; 1871 return 0;
1887 1872
1888 switch (model) { 1873 switch (model) {
1889 case 0x45: 1874 case 0x45: /* HSW */
1875 case 0x3D: /* BDW */
1890 return 1; 1876 return 1;
1891 } 1877 }
1892 return 0; 1878 return 0;
@@ -2455,7 +2441,7 @@ int main(int argc, char **argv)
2455 cmdline(argc, argv); 2441 cmdline(argc, argv);
2456 2442
2457 if (verbose) 2443 if (verbose)
2458 fprintf(stderr, "turbostat v3.6 Dec 2, 2013" 2444 fprintf(stderr, "turbostat v3.7 Feb 6, 2014"
2459 " - Len Brown <lenb@kernel.org>\n"); 2445 " - Len Brown <lenb@kernel.org>\n");
2460 2446
2461 turbostat_init(); 2447 turbostat_init();
diff --git a/tools/testing/ktest/examples/kvm.conf b/tools/testing/ktest/examples/kvm.conf
index 831c7c5395f1..fbc134f9ac6e 100644
--- a/tools/testing/ktest/examples/kvm.conf
+++ b/tools/testing/ktest/examples/kvm.conf
@@ -10,6 +10,10 @@ MACHINE = Guest
10# Use virsh to read the serial console of the guest 10# Use virsh to read the serial console of the guest
11CONSOLE = virsh console ${MACHINE} 11CONSOLE = virsh console ${MACHINE}
12 12
13# Use SIGKILL to terminate virsh console. We can't kill virsh console
14# by the default signal, SIGINT.
15CLOSE_CONSOLE_SIGNAL = KILL
16
13#*************************************# 17#*************************************#
14# This part is the same as test.conf # 18# This part is the same as test.conf #
15#*************************************# 19#*************************************#
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index bd24ae5aaeab..316194f26ff4 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -13,7 +13,7 @@ CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CUR
13 13
14export CC CFLAGS 14export CC CFLAGS
15 15
16TARGETS = pmu 16TARGETS = pmu copyloops
17 17
18endif 18endif
19 19
diff --git a/tools/testing/selftests/powerpc/copyloops/Makefile b/tools/testing/selftests/powerpc/copyloops/Makefile
new file mode 100644
index 000000000000..6f2d3be227f9
--- /dev/null
+++ b/tools/testing/selftests/powerpc/copyloops/Makefile
@@ -0,0 +1,29 @@
1# The loops are all 64-bit code
2CFLAGS += -m64
3CFLAGS += -I$(CURDIR)
4CFLAGS += -D SELFTEST
5
6# Use our CFLAGS for the implicit .S rule
7ASFLAGS = $(CFLAGS)
8
9PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7
10EXTRA_SOURCES := validate.c ../harness.c
11
12all: $(PROGS)
13
14copyuser_64: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_base
15copyuser_power7: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_power7
16memcpy_64: CPPFLAGS += -D COPY_LOOP=test_memcpy
17memcpy_power7: CPPFLAGS += -D COPY_LOOP=test_memcpy_power7
18
19$(PROGS): $(EXTRA_SOURCES)
20
21run_tests: all
22 @-for PROG in $(PROGS); do \
23 ./$$PROG; \
24 done;
25
26clean:
27 rm -f $(PROGS) *.o
28
29.PHONY: all run_tests clean
diff --git a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
new file mode 100644
index 000000000000..ccd9c84c4e3f
--- /dev/null
+++ b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
@@ -0,0 +1,86 @@
1#include <ppc-asm.h>
2
3#define CONFIG_ALTIVEC
4
5#define r1 1
6
7#define vr0 0
8#define vr1 1
9#define vr2 2
10#define vr3 3
11#define vr4 4
12#define vr5 5
13#define vr6 6
14#define vr7 7
15#define vr8 8
16#define vr9 9
17#define vr10 10
18#define vr11 11
19#define vr12 12
20#define vr13 13
21#define vr14 14
22#define vr15 15
23#define vr16 16
24#define vr17 17
25#define vr18 18
26#define vr19 19
27#define vr20 20
28#define vr21 21
29#define vr22 22
30#define vr23 23
31#define vr24 24
32#define vr25 25
33#define vr26 26
34#define vr27 27
35#define vr28 28
36#define vr29 29
37#define vr30 30
38#define vr31 31
39
40#define R14 r14
41#define R15 r15
42#define R16 r16
43#define R17 r17
44#define R18 r18
45#define R19 r19
46#define R20 r20
47#define R21 r21
48#define R22 r22
49
50#define STACKFRAMESIZE 256
51#define STK_PARAM(i) (48 + ((i)-3)*8)
52#define STK_REG(i) (112 + ((i)-14)*8)
53
54#define _GLOBAL(A) FUNC_START(test_ ## A)
55
56#define PPC_MTOCRF(A, B) mtocrf A, B
57
58FUNC_START(enter_vmx_usercopy)
59 li r3,1
60 blr
61
62FUNC_START(exit_vmx_usercopy)
63 li r3,0
64 blr
65
66FUNC_START(enter_vmx_copy)
67 li r3,1
68 blr
69
70FUNC_START(exit_vmx_copy)
71 blr
72
73FUNC_START(memcpy_power7)
74 blr
75
76FUNC_START(__copy_tofrom_user_power7)
77 blr
78
79FUNC_START(__copy_tofrom_user_base)
80 blr
81
82#define BEGIN_FTR_SECTION
83#define FTR_SECTION_ELSE
84#define ALT_FTR_SECTION_END_IFCLR(x)
85#define ALT_FTR_SECTION_END(x, y)
86#define END_FTR_SECTION_IFCLR(x)
diff --git a/tools/testing/selftests/powerpc/copyloops/asm/processor.h b/tools/testing/selftests/powerpc/copyloops/asm/processor.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/powerpc/copyloops/asm/processor.h
diff --git a/tools/testing/selftests/powerpc/copyloops/copyuser_64.S b/tools/testing/selftests/powerpc/copyloops/copyuser_64.S
new file mode 120000
index 000000000000..f1c418a2521a
--- /dev/null
+++ b/tools/testing/selftests/powerpc/copyloops/copyuser_64.S
@@ -0,0 +1 @@
../../../../../arch/powerpc/lib/copyuser_64.S \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/copyloops/copyuser_power7.S b/tools/testing/selftests/powerpc/copyloops/copyuser_power7.S
new file mode 120000
index 000000000000..478689598298
--- /dev/null
+++ b/tools/testing/selftests/powerpc/copyloops/copyuser_power7.S
@@ -0,0 +1 @@
../../../../../arch/powerpc/lib/copyuser_power7.S \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/copyloops/memcpy_64.S b/tools/testing/selftests/powerpc/copyloops/memcpy_64.S
new file mode 120000
index 000000000000..cce33fb6f9d8
--- /dev/null
+++ b/tools/testing/selftests/powerpc/copyloops/memcpy_64.S
@@ -0,0 +1 @@
../../../../../arch/powerpc/lib/memcpy_64.S \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/copyloops/memcpy_power7.S b/tools/testing/selftests/powerpc/copyloops/memcpy_power7.S
new file mode 120000
index 000000000000..0d6fbfaf3d59
--- /dev/null
+++ b/tools/testing/selftests/powerpc/copyloops/memcpy_power7.S
@@ -0,0 +1 @@
../../../../../arch/powerpc/lib/memcpy_power7.S \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/copyloops/validate.c b/tools/testing/selftests/powerpc/copyloops/validate.c
new file mode 100644
index 000000000000..1750ff57ee58
--- /dev/null
+++ b/tools/testing/selftests/powerpc/copyloops/validate.c
@@ -0,0 +1,99 @@
1#include <malloc.h>
2#include <string.h>
3#include <stdlib.h>
4#include <stdbool.h>
5
6#include "../utils.h"
7
8#define MAX_LEN 8192
9#define MAX_OFFSET 16
10#define MIN_REDZONE 128
11#define BUFLEN (MAX_LEN+MAX_OFFSET+2*MIN_REDZONE)
12#define POISON 0xa5
13
14unsigned long COPY_LOOP(void *to, const void *from, unsigned long size);
15
16static void do_one(char *src, char *dst, unsigned long src_off,
17 unsigned long dst_off, unsigned long len, void *redzone,
18 void *fill)
19{
20 char *srcp, *dstp;
21 unsigned long ret;
22 unsigned long i;
23
24 srcp = src + MIN_REDZONE + src_off;
25 dstp = dst + MIN_REDZONE + dst_off;
26
27 memset(src, POISON, BUFLEN);
28 memset(dst, POISON, BUFLEN);
29 memcpy(srcp, fill, len);
30
31 ret = COPY_LOOP(dstp, srcp, len);
32 if (ret && ret != (unsigned long)dstp) {
33 printf("(%p,%p,%ld) returned %ld\n", dstp, srcp, len, ret);
34 abort();
35 }
36
37 if (memcmp(dstp, srcp, len)) {
38 printf("(%p,%p,%ld) miscompare\n", dstp, srcp, len);
39 printf("src: ");
40 for (i = 0; i < len; i++)
41 printf("%02x ", srcp[i]);
42 printf("\ndst: ");
43 for (i = 0; i < len; i++)
44 printf("%02x ", dstp[i]);
45 printf("\n");
46 abort();
47 }
48
49 if (memcmp(dst, redzone, dstp - dst)) {
50 printf("(%p,%p,%ld) redzone before corrupted\n",
51 dstp, srcp, len);
52 abort();
53 }
54
55 if (memcmp(dstp+len, redzone, dst+BUFLEN-(dstp+len))) {
56 printf("(%p,%p,%ld) redzone after corrupted\n",
57 dstp, srcp, len);
58 abort();
59 }
60}
61
62int test_copy_loop(void)
63{
64 char *src, *dst, *redzone, *fill;
65 unsigned long len, src_off, dst_off;
66 unsigned long i;
67
68 src = memalign(BUFLEN, BUFLEN);
69 dst = memalign(BUFLEN, BUFLEN);
70 redzone = malloc(BUFLEN);
71 fill = malloc(BUFLEN);
72
73 if (!src || !dst || !redzone || !fill) {
74 fprintf(stderr, "malloc failed\n");
75 exit(1);
76 }
77
78 memset(redzone, POISON, BUFLEN);
79
80 /* Fill with sequential bytes */
81 for (i = 0; i < BUFLEN; i++)
82 fill[i] = i & 0xff;
83
84 for (len = 1; len < MAX_LEN; len++) {
85 for (src_off = 0; src_off < MAX_OFFSET; src_off++) {
86 for (dst_off = 0; dst_off < MAX_OFFSET; dst_off++) {
87 do_one(src, dst, src_off, dst_off, len,
88 redzone, fill);
89 }
90 }
91 }
92
93 return 0;
94}
95
96int main(void)
97{
98 return test_harness(test_copy_loop, str(COPY_LOOP));
99}
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h
index 5851c4b0f553..0de064406dab 100644
--- a/tools/testing/selftests/powerpc/utils.h
+++ b/tools/testing/selftests/powerpc/utils.h
@@ -31,4 +31,7 @@ do { \
31 } \ 31 } \
32} while (0) 32} while (0)
33 33
34#define _str(s) #s
35#define str(s) _str(s)
36
34#endif /* _SELFTESTS_POWERPC_UTILS_H */ 37#endif /* _SELFTESTS_POWERPC_UTILS_H */
diff --git a/tools/testing/selftests/rcutorture/bin/functions.sh b/tools/testing/selftests/rcutorture/bin/functions.sh
index 587561d7c035..9b17e810ddc3 100644
--- a/tools/testing/selftests/rcutorture/bin/functions.sh
+++ b/tools/testing/selftests/rcutorture/bin/functions.sh
@@ -96,6 +96,7 @@ identify_qemu () {
96 echo qemu-system-ppc64 96 echo qemu-system-ppc64
97 else 97 else
98 echo Cannot figure out what qemu command to use! 1>&2 98 echo Cannot figure out what qemu command to use! 1>&2
99 echo file $1 output: $u
99 # Usually this will be one of /usr/bin/qemu-system-* 100 # Usually this will be one of /usr/bin/qemu-system-*
100 # Use RCU_QEMU_CMD environment variable or appropriate 101 # Use RCU_QEMU_CMD environment variable or appropriate
101 # argument to top-level script. 102 # argument to top-level script.
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh
new file mode 100755
index 000000000000..829186e19eb1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh
@@ -0,0 +1,51 @@
1#!/bin/bash
2#
3# Analyze a given results directory for locktorture progress.
4#
5# Usage: sh kvm-recheck-lock.sh resdir
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, you can access it online at
19# http://www.gnu.org/licenses/gpl-2.0.html.
20#
21# Copyright (C) IBM Corporation, 2014
22#
23# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
24
25i="$1"
26if test -d $i
27then
28 :
29else
30 echo Unreadable results directory: $i
31 exit 1
32fi
33
34configfile=`echo $i | sed -e 's/^.*\///'`
35ncs=`grep "Writes: Total:" $i/console.log 2> /dev/null | tail -1 | sed -e 's/^.* Total: //' -e 's/ .*$//'`
36if test -z "$ncs"
37then
38 echo $configfile
39else
40 title="$configfile ------- $ncs acquisitions/releases"
41 dur=`sed -e 's/^.* locktorture.shutdown_secs=//' -e 's/ .*$//' < $i/qemu-cmd 2> /dev/null`
42 if test -z "$dur"
43 then
44 :
45 else
46 ncsps=`awk -v ncs=$ncs -v dur=$dur '
47 BEGIN { print ncs / dur }' < /dev/null`
48 title="$title ($ncsps per second)"
49 fi
50 echo $title
51fi
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh
new file mode 100755
index 000000000000..d75b1dc5ae53
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh
@@ -0,0 +1,51 @@
1#!/bin/bash
2#
3# Analyze a given results directory for rcutorture progress.
4#
5# Usage: sh kvm-recheck-rcu.sh resdir
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, you can access it online at
19# http://www.gnu.org/licenses/gpl-2.0.html.
20#
21# Copyright (C) IBM Corporation, 2014
22#
23# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
24
25i="$1"
26if test -d $i
27then
28 :
29else
30 echo Unreadable results directory: $i
31 exit 1
32fi
33
34configfile=`echo $i | sed -e 's/^.*\///'`
35ngps=`grep ver: $i/console.log 2> /dev/null | tail -1 | sed -e 's/^.* ver: //' -e 's/ .*$//'`
36if test -z "$ngps"
37then
38 echo $configfile
39else
40 title="$configfile ------- $ngps grace periods"
41 dur=`sed -e 's/^.* rcutorture.shutdown_secs=//' -e 's/ .*$//' < $i/qemu-cmd 2> /dev/null`
42 if test -z "$dur"
43 then
44 :
45 else
46 ngpsps=`awk -v ngps=$ngps -v dur=$dur '
47 BEGIN { print ngps / dur }' < /dev/null`
48 title="$title ($ngpsps per second)"
49 fi
50 echo $title
51fi
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
index baef09f3469b..a44daaa259a9 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
@@ -1,6 +1,6 @@
1#!/bin/bash 1#!/bin/bash
2# 2#
3# Given the results directories for previous KVM runs of rcutorture, 3# Given the results directories for previous KVM-based torture runs,
4# check the build and console output for errors. Given a directory 4# check the build and console output for errors. Given a directory
5# containing results directories, this recursively checks them all. 5# containing results directories, this recursively checks them all.
6# 6#
@@ -27,11 +27,18 @@
27PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH 27PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH
28for rd in "$@" 28for rd in "$@"
29do 29do
30 firsttime=1
30 dirs=`find $rd -name Make.defconfig.out -print | sort | sed -e 's,/[^/]*$,,' | sort -u` 31 dirs=`find $rd -name Make.defconfig.out -print | sort | sed -e 's,/[^/]*$,,' | sort -u`
31 for i in $dirs 32 for i in $dirs
32 do 33 do
33 configfile=`echo $i | sed -e 's/^.*\///'` 34 if test -n "$firsttime"
34 echo $configfile 35 then
36 firsttime=""
37 resdir=`echo $i | sed -e 's,/$,,' -e 's,/[^/]*$,,'`
38 head -1 $resdir/log
39 fi
40 TORTURE_SUITE="`cat $i/../TORTURE_SUITE`"
41 kvm-recheck-${TORTURE_SUITE}.sh $i
35 configcheck.sh $i/.config $i/ConfigFragment 42 configcheck.sh $i/.config $i/ConfigFragment
36 parse-build.sh $i/Make.out $configfile 43 parse-build.sh $i/Make.out $configfile
37 parse-rcutorture.sh $i/console.log $configfile 44 parse-rcutorture.sh $i/console.log $configfile
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
index 151b23788935..94b28bb37d36 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
@@ -6,15 +6,15 @@
6# Execute this in the source tree. Do not run it as a background task 6# Execute this in the source tree. Do not run it as a background task
7# because qemu does not seem to like that much. 7# because qemu does not seem to like that much.
8# 8#
9# Usage: sh kvm-test-1-rcu.sh config builddir resdir minutes qemu-args bootargs 9# Usage: sh kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args
10# 10#
11# qemu-args defaults to "" -- you will want "-nographic" if running headless. 11# qemu-args defaults to "-nographic", along with arguments specifying the
12# bootargs defaults to "root=/dev/sda noapic selinux=0 console=ttyS0" 12# number of CPUs and other options generated from
13# "initcall_debug debug rcutorture.stat_interval=15" 13# the underlying CPU architecture.
14# "rcutorture.shutdown_secs=$((minutes * 60))" 14# boot_args defaults to value returned by the per_version_boot_params
15# "rcutorture.rcutorture_runnable=1" 15# shell function.
16# 16#
17# Anything you specify for either qemu-args or bootargs is appended to 17# Anything you specify for either qemu-args or boot_args is appended to
18# the default values. The "-smp" value is deduced from the contents of 18# the default values. The "-smp" value is deduced from the contents of
19# the config fragment. 19# the config fragment.
20# 20#
@@ -40,32 +40,34 @@
40 40
41grace=120 41grace=120
42 42
43T=/tmp/kvm-test-1-rcu.sh.$$ 43T=/tmp/kvm-test-1-run.sh.$$
44trap 'rm -rf $T' 0 44trap 'rm -rf $T' 0
45 45
46. $KVM/bin/functions.sh 46. $KVM/bin/functions.sh
47. $KVPATH/ver_functions.sh 47. $KVPATH/ver_functions.sh
48 48
49config_template=${1} 49config_template=${1}
50config_dir=`echo $config_template | sed -e 's,/[^/]*$,,'`
50title=`echo $config_template | sed -e 's/^.*\///'` 51title=`echo $config_template | sed -e 's/^.*\///'`
51builddir=${2} 52builddir=${2}
52if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir" 53if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir"
53then 54then
54 echo "kvm-test-1-rcu.sh :$builddir: Not a writable directory, cannot build into it" 55 echo "kvm-test-1-run.sh :$builddir: Not a writable directory, cannot build into it"
55 exit 1 56 exit 1
56fi 57fi
57resdir=${3} 58resdir=${3}
58if test -z "$resdir" -o ! -d "$resdir" -o ! -w "$resdir" 59if test -z "$resdir" -o ! -d "$resdir" -o ! -w "$resdir"
59then 60then
60 echo "kvm-test-1-rcu.sh :$resdir: Not a writable directory, cannot build into it" 61 echo "kvm-test-1-run.sh :$resdir: Not a writable directory, cannot store results into it"
61 exit 1 62 exit 1
62fi 63fi
63cp $config_template $resdir/ConfigFragment 64cp $config_template $resdir/ConfigFragment
64echo ' ---' `date`: Starting build 65echo ' ---' `date`: Starting build
65echo ' ---' Kconfig fragment at: $config_template >> $resdir/log 66echo ' ---' Kconfig fragment at: $config_template >> $resdir/log
66cat << '___EOF___' >> $T 67if test -r "$config_dir/CFcommon"
67CONFIG_RCU_TORTURE_TEST=y 68then
68___EOF___ 69 cat < $config_dir/CFcommon >> $T
70fi
69# Optimizations below this point 71# Optimizations below this point
70# CONFIG_USB=n 72# CONFIG_USB=n
71# CONFIG_SECURITY=n 73# CONFIG_SECURITY=n
@@ -96,11 +98,23 @@ then
96 cp $builddir/.config $resdir 98 cp $builddir/.config $resdir
97 cp $builddir/arch/x86/boot/bzImage $resdir 99 cp $builddir/arch/x86/boot/bzImage $resdir
98 parse-build.sh $resdir/Make.out $title 100 parse-build.sh $resdir/Make.out $title
101 if test -f $builddir.wait
102 then
103 mv $builddir.wait $builddir.ready
104 fi
99else 105else
100 cp $builddir/Make*.out $resdir 106 cp $builddir/Make*.out $resdir
101 echo Build failed, not running KVM, see $resdir. 107 echo Build failed, not running KVM, see $resdir.
108 if test -f $builddir.wait
109 then
110 mv $builddir.wait $builddir.ready
111 fi
102 exit 1 112 exit 1
103fi 113fi
114while test -f $builddir.ready
115do
116 sleep 1
117done
104minutes=$4 118minutes=$4
105seconds=$(($minutes * 60)) 119seconds=$(($minutes * 60))
106qemu_args=$5 120qemu_args=$5
@@ -111,9 +125,10 @@ kstarttime=`awk 'BEGIN { print systime() }' < /dev/null`
111echo ' ---' `date`: Starting kernel 125echo ' ---' `date`: Starting kernel
112 126
113# Determine the appropriate flavor of qemu command. 127# Determine the appropriate flavor of qemu command.
114QEMU="`identify_qemu $builddir/vmlinux.o`" 128QEMU="`identify_qemu $builddir/vmlinux`"
115 129
116# Generate -smp qemu argument. 130# Generate -smp qemu argument.
131qemu_args="-nographic $qemu_args"
117cpu_count=`configNR_CPUS.sh $config_template` 132cpu_count=`configNR_CPUS.sh $config_template`
118vcpus=`identify_qemu_vcpus` 133vcpus=`identify_qemu_vcpus`
119if test $cpu_count -gt $vcpus 134if test $cpu_count -gt $vcpus
@@ -133,12 +148,8 @@ qemu_append="`identify_qemu_append "$QEMU"`"
133 148
134# Pull in Kconfig-fragment boot parameters 149# Pull in Kconfig-fragment boot parameters
135boot_args="`configfrag_boot_params "$boot_args" "$config_template"`" 150boot_args="`configfrag_boot_params "$boot_args" "$config_template"`"
136# Generate CPU-hotplug boot parameters 151# Generate kernel-version-specific boot parameters
137boot_args="`rcutorture_param_onoff "$boot_args" $builddir/.config`" 152boot_args="`per_version_boot_params "$boot_args" $builddir/.config $seconds`"
138# Generate rcu_barrier() boot parameter
139boot_args="`rcutorture_param_n_barrier_cbs "$boot_args"`"
140# Pull in standard rcutorture boot arguments
141boot_args="$boot_args rcutorture.stat_interval=15 rcutorture.shutdown_secs=$seconds rcutorture.rcutorture_runnable=1"
142 153
143echo $QEMU $qemu_args -m 512 -kernel $builddir/arch/x86/boot/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd 154echo $QEMU $qemu_args -m 512 -kernel $builddir/arch/x86/boot/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
144if test -n "$RCU_BUILDONLY" 155if test -n "$RCU_BUILDONLY"
@@ -188,5 +199,5 @@ then
188fi 199fi
189 200
190cp $builddir/console.log $resdir 201cp $builddir/console.log $resdir
191parse-rcutorture.sh $resdir/console.log $title 202parse-${TORTURE_SUITE}torture.sh $resdir/console.log $title
192parse-console.sh $resdir/console.log $title 203parse-console.sh $resdir/console.log $title
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 1b7923bf6a70..5a78cbf55f06 100644
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -30,14 +30,21 @@
30scriptname=$0 30scriptname=$0
31args="$*" 31args="$*"
32 32
33T=/tmp/kvm.sh.$$
34trap 'rm -rf $T' 0
35mkdir $T
36
33dur=30 37dur=30
38dryrun=""
34KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM 39KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM
35PATH=${KVM}/bin:$PATH; export PATH 40PATH=${KVM}/bin:$PATH; export PATH
36builddir="${KVM}/b1" 41builddir="${KVM}/b1"
37RCU_INITRD="$KVM/initrd"; export RCU_INITRD 42RCU_INITRD="$KVM/initrd"; export RCU_INITRD
38RCU_KMAKE_ARG=""; export RCU_KMAKE_ARG 43RCU_KMAKE_ARG=""; export RCU_KMAKE_ARG
44TORTURE_SUITE=rcu
39resdir="" 45resdir=""
40configs="" 46configs=""
47cpus=0
41ds=`date +%Y.%m.%d-%H:%M:%S` 48ds=`date +%Y.%m.%d-%H:%M:%S`
42kversion="" 49kversion=""
43 50
@@ -49,7 +56,9 @@ usage () {
49 echo " --builddir absolute-pathname" 56 echo " --builddir absolute-pathname"
50 echo " --buildonly" 57 echo " --buildonly"
51 echo " --configs \"config-file list\"" 58 echo " --configs \"config-file list\""
59 echo " --cpus N"
52 echo " --datestamp string" 60 echo " --datestamp string"
61 echo " --dryrun sched|script"
53 echo " --duration minutes" 62 echo " --duration minutes"
54 echo " --interactive" 63 echo " --interactive"
55 echo " --kmake-arg kernel-make-arguments" 64 echo " --kmake-arg kernel-make-arguments"
@@ -58,8 +67,9 @@ usage () {
58 echo " --no-initrd" 67 echo " --no-initrd"
59 echo " --qemu-args qemu-system-..." 68 echo " --qemu-args qemu-system-..."
60 echo " --qemu-cmd qemu-system-..." 69 echo " --qemu-cmd qemu-system-..."
61 echo " --results absolute-pathname"
62 echo " --relbuilddir relative-pathname" 70 echo " --relbuilddir relative-pathname"
71 echo " --results absolute-pathname"
72 echo " --torture rcu"
63 exit 1 73 exit 1
64} 74}
65 75
@@ -85,11 +95,21 @@ do
85 configs="$2" 95 configs="$2"
86 shift 96 shift
87 ;; 97 ;;
98 --cpus)
99 checkarg --cpus "(number)" "$#" "$2" '^[0-9]*$' '^--'
100 cpus=$2
101 shift
102 ;;
88 --datestamp) 103 --datestamp)
89 checkarg --datestamp "(relative pathname)" "$#" "$2" '^[^/]*$' '^--' 104 checkarg --datestamp "(relative pathname)" "$#" "$2" '^[^/]*$' '^--'
90 ds=$2 105 ds=$2
91 shift 106 shift
92 ;; 107 ;;
108 --dryrun)
109 checkarg --dryrun "sched|script" $# "$2" 'sched\|script' '^--'
110 dryrun=$2
111 shift
112 ;;
93 --duration) 113 --duration)
94 checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error' 114 checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error'
95 dur=$2 115 dur=$2
@@ -138,6 +158,11 @@ do
138 resdir=$2 158 resdir=$2
139 shift 159 shift
140 ;; 160 ;;
161 --torture)
162 checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\)$' '^--'
163 TORTURE_SUITE=$2
164 shift
165 ;;
141 *) 166 *)
142 echo Unknown argument $1 167 echo Unknown argument $1
143 usage 168 usage
@@ -146,7 +171,7 @@ do
146 shift 171 shift
147done 172done
148 173
149CONFIGFRAG=${KVM}/configs; export CONFIGFRAG 174CONFIGFRAG=${KVM}/configs/${TORTURE_SUITE}; export CONFIGFRAG
150KVPATH=${CONFIGFRAG}/$kversion; export KVPATH 175KVPATH=${CONFIGFRAG}/$kversion; export KVPATH
151 176
152if test -z "$configs" 177if test -z "$configs"
@@ -157,54 +182,231 @@ fi
157if test -z "$resdir" 182if test -z "$resdir"
158then 183then
159 resdir=$KVM/res 184 resdir=$KVM/res
160 if ! test -e $resdir 185fi
161 then 186
162 mkdir $resdir || : 187if test "$dryrun" = ""
163 fi 188then
164else
165 if ! test -e $resdir 189 if ! test -e $resdir
166 then 190 then
167 mkdir -p "$resdir" || : 191 mkdir -p "$resdir" || :
168 fi 192 fi
169fi 193 mkdir $resdir/$ds
170mkdir $resdir/$ds
171touch $resdir/$ds/log
172echo $scriptname $args >> $resdir/$ds/log
173 194
174pwd > $resdir/$ds/testid.txt 195 # Be noisy only if running the script.
175if test -d .git 196 echo Results directory: $resdir/$ds
176then 197 echo $scriptname $args
177 git status >> $resdir/$ds/testid.txt 198
178 git rev-parse HEAD >> $resdir/$ds/testid.txt 199 touch $resdir/$ds/log
179fi 200 echo $scriptname $args >> $resdir/$ds/log
180builddir=$KVM/b1 201 echo ${TORTURE_SUITE} > $resdir/$ds/TORTURE_SUITE
181if ! test -e $builddir 202
182then 203 pwd > $resdir/$ds/testid.txt
183 mkdir $builddir || : 204 if test -d .git
205 then
206 git status >> $resdir/$ds/testid.txt
207 git rev-parse HEAD >> $resdir/$ds/testid.txt
208 fi
184fi 209fi
185 210
211# Create a file of test-name/#cpus pairs, sorted by decreasing #cpus.
212touch $T/cfgcpu
186for CF in $configs 213for CF in $configs
187do 214do
188 # Running TREE01 multiple times creates TREE01, TREE01.2, TREE01.3, ... 215 if test -f "$CONFIGFRAG/$kversion/$CF"
189 rd=$resdir/$ds/$CF
190 if test -d "${rd}"
191 then 216 then
192 n="`ls -d "${rd}"* | grep '\.[0-9]\+$' | 217 echo $CF `configNR_CPUS.sh $CONFIGFRAG/$kversion/$CF` >> $T/cfgcpu
193 sed -e 's/^.*\.\([0-9]\+\)/\1/' | 218 else
194 sort -k1n | tail -1`" 219 echo "The --configs file $CF does not exist, terminating."
195 if test -z "$n" 220 exit 1
196 then
197 rd="${rd}.2"
198 else
199 n="`expr $n + 1`"
200 rd="${rd}.${n}"
201 fi
202 fi 221 fi
203 mkdir "${rd}"
204 echo Results directory: $rd
205 kvm-test-1-rcu.sh $CONFIGFRAG/$kversion/$CF $builddir $rd $dur "-nographic $RCU_QEMU_ARG" "rcutorture.test_no_idle_hz=1 rcutorture.verbose=1 $RCU_BOOTARGS"
206done 222done
223sort -k2nr $T/cfgcpu > $T/cfgcpu.sort
224
225# Use a greedy bin-packing algorithm, sorting the list accordingly.
226awk < $T/cfgcpu.sort > $T/cfgcpu.pack -v ncpus=$cpus '
227BEGIN {
228 njobs = 0;
229}
230
231{
232 # Read file of tests and corresponding required numbers of CPUs.
233 cf[njobs] = $1;
234 cpus[njobs] = $2;
235 njobs++;
236}
237
238END {
239 alldone = 0;
240 batch = 0;
241 nc = -1;
242
243 # Each pass through the following loop creates on test batch
244 # that can be executed concurrently given ncpus. Note that a
245 # given test that requires more than the available CPUs will run in
246 # their own batch. Such tests just have to make do with what
247 # is available.
248 while (nc != ncpus) {
249 batch++;
250 nc = ncpus;
251
252 # Each pass through the following loop considers one
253 # test for inclusion in the current batch.
254 for (i = 0; i < njobs; i++) {
255 if (done[i])
256 continue; # Already part of a batch.
257 if (nc >= cpus[i] || nc == ncpus) {
258
259 # This test fits into the current batch.
260 done[i] = batch;
261 nc -= cpus[i];
262 if (nc <= 0)
263 break; # Too-big test in its own batch.
264 }
265 }
266 }
267
268 # Dump out the tests in batch order.
269 for (b = 1; b <= batch; b++)
270 for (i = 0; i < njobs; i++)
271 if (done[i] == b)
272 print cf[i], cpus[i];
273}'
274
275# Generate a script to execute the tests in appropriate batches.
276cat << ___EOF___ > $T/script
277TORTURE_SUITE="$TORTURE_SUITE"; export TORTURE_SUITE
278___EOF___
279awk < $T/cfgcpu.pack \
280 -v CONFIGDIR="$CONFIGFRAG/$kversion/" \
281 -v KVM="$KVM" \
282 -v ncpus=$cpus \
283 -v rd=$resdir/$ds/ \
284 -v dur=$dur \
285 -v RCU_QEMU_ARG=$RCU_QEMU_ARG \
286 -v RCU_BOOTARGS=$RCU_BOOTARGS \
287'BEGIN {
288 i = 0;
289}
290
291{
292 cf[i] = $1;
293 cpus[i] = $2;
294 i++;
295}
296
297# Dump out the scripting required to run one test batch.
298function dump(first, pastlast)
299{
300 print "echo ----Start batch: `date`";
301 print "echo ----Start batch: `date` >> " rd "/log";
302 jn=1
303 for (j = first; j < pastlast; j++) {
304 builddir=KVM "/b" jn
305 cpusr[jn] = cpus[j];
306 if (cfrep[cf[j]] == "") {
307 cfr[jn] = cf[j];
308 cfrep[cf[j]] = 1;
309 } else {
310 cfrep[cf[j]]++;
311 cfr[jn] = cf[j] "." cfrep[cf[j]];
312 }
313 if (cpusr[jn] > ncpus && ncpus != 0)
314 ovf = "(!)";
315 else
316 ovf = "";
317 print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date`";
318 print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date` >> " rd "/log";
319 print "rm -f " builddir ".*";
320 print "touch " builddir ".wait";
321 print "mkdir " builddir " > /dev/null 2>&1 || :";
322 print "mkdir " rd cfr[jn] " || :";
323 print "kvm-test-1-run.sh " CONFIGDIR cf[j], builddir, rd cfr[jn], dur " \"" RCU_QEMU_ARG "\" \"" RCU_BOOTARGS "\" > " rd cfr[jn] "/kvm-test-1-run.sh.out 2>&1 &"
324 print "echo ", cfr[jn], cpusr[jn] ovf ": Waiting for build to complete. `date`";
325 print "echo ", cfr[jn], cpusr[jn] ovf ": Waiting for build to complete. `date` >> " rd "/log";
326 print "while test -f " builddir ".wait"
327 print "do"
328 print "\tsleep 1"
329 print "done"
330 print "echo ", cfr[jn], cpusr[jn] ovf ": Build complete. `date`";
331 print "echo ", cfr[jn], cpusr[jn] ovf ": Build complete. `date` >> " rd "/log";
332 jn++;
333 }
334 for (j = 1; j < jn; j++) {
335 builddir=KVM "/b" j
336 print "rm -f " builddir ".ready"
337 print "echo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date`";
338 print "echo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date` >> " rd "/log";
339 }
340 print "wait"
341 print "echo ---- All kernel runs complete. `date`";
342 print "echo ---- All kernel runs complete. `date` >> " rd "/log";
343 for (j = 1; j < jn; j++) {
344 builddir=KVM "/b" j
345 print "echo ----", cfr[j], cpusr[j] ovf ": Build/run results:";
346 print "echo ----", cfr[j], cpusr[j] ovf ": Build/run results: >> " rd "/log";
347 print "cat " rd cfr[j] "/kvm-test-1-run.sh.out";
348 print "cat " rd cfr[j] "/kvm-test-1-run.sh.out >> " rd "/log";
349 }
350}
351
352END {
353 njobs = i;
354 nc = ncpus;
355 first = 0;
356
357 # Each pass through the following loop considers one test.
358 for (i = 0; i < njobs; i++) {
359 if (ncpus == 0) {
360 # Sequential test specified, each test its own batch.
361 dump(i, i + 1);
362 first = i;
363 } else if (nc < cpus[i] && i != 0) {
364 # Out of CPUs, dump out a batch.
365 dump(first, i);
366 first = i;
367 nc = ncpus;
368 }
369 # Account for the CPUs needed by the current test.
370 nc -= cpus[i];
371 }
372 # Dump the last batch.
373 if (ncpus != 0)
374 dump(first, i);
375}' >> $T/script
376
377if test "$dryrun" = script
378then
379 # Dump out the script, but define the environment variables that
380 # it needs to run standalone.
381 echo CONFIGFRAG="$CONFIGFRAG; export CONFIGFRAG"
382 echo KVM="$KVM; export KVM"
383 echo KVPATH="$KVPATH; export KVPATH"
384 echo PATH="$PATH; export PATH"
385 echo RCU_BUILDONLY="$RCU_BUILDONLY; export RCU_BUILDONLY"
386 echo RCU_INITRD="$RCU_INITRD; export RCU_INITRD"
387 echo RCU_KMAKE_ARG="$RCU_KMAKE_ARG; export RCU_KMAKE_ARG"
388 echo RCU_QEMU_CMD="$RCU_QEMU_CMD; export RCU_QEMU_CMD"
389 echo RCU_QEMU_INTERACTIVE="$RCU_QEMU_INTERACTIVE; export RCU_QEMU_INTERACTIVE"
390 echo RCU_QEMU_MAC="$RCU_QEMU_MAC; export RCU_QEMU_MAC"
391 echo "mkdir -p "$resdir" || :"
392 echo "mkdir $resdir/$ds"
393 cat $T/script
394 exit 0
395elif test "$dryrun" = sched
396then
397 # Extract the test run schedule from the script.
398 egrep 'start batch|Starting build\.' $T/script |
399 sed -e 's/:.*$//' -e 's/^echo //'
400 exit 0
401else
402 # Not a dryru, so run the script.
403 sh $T/script
404fi
405
207# Tracing: trace_event=rcu:rcu_grace_period,rcu:rcu_future_grace_period,rcu:rcu_grace_period_init,rcu:rcu_nocb_wake,rcu:rcu_preempt_task,rcu:rcu_unlock_preempted_task,rcu:rcu_quiescent_state_report,rcu:rcu_fqs,rcu:rcu_callback,rcu:rcu_kfree_callback,rcu:rcu_batch_start,rcu:rcu_invoke_callback,rcu:rcu_invoke_kfree_callback,rcu:rcu_batch_end,rcu:rcu_torture_read,rcu:rcu_barrier 406# Tracing: trace_event=rcu:rcu_grace_period,rcu:rcu_future_grace_period,rcu:rcu_grace_period_init,rcu:rcu_nocb_wake,rcu:rcu_preempt_task,rcu:rcu_unlock_preempted_task,rcu:rcu_quiescent_state_report,rcu:rcu_fqs,rcu:rcu_callback,rcu:rcu_kfree_callback,rcu:rcu_batch_start,rcu:rcu_invoke_callback,rcu:rcu_invoke_kfree_callback,rcu:rcu_batch_end,rcu:rcu_torture_read,rcu:rcu_barrier
208 407
408echo
409echo
209echo " --- `date` Test summary:" 410echo " --- `date` Test summary:"
411echo Results directory: $resdir/$ds
210kvm-recheck.sh $resdir/$ds 412kvm-recheck.sh $resdir/$ds
diff --git a/tools/testing/selftests/rcutorture/configs/lock/BUSTED b/tools/testing/selftests/rcutorture/configs/lock/BUSTED
new file mode 100644
index 000000000000..1d1da1477fc3
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/BUSTED
@@ -0,0 +1,6 @@
1CONFIG_SMP=y
2CONFIG_NR_CPUS=4
3CONFIG_HOTPLUG_CPU=y
4CONFIG_PREEMPT_NONE=n
5CONFIG_PREEMPT_VOLUNTARY=n
6CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot b/tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot
new file mode 100644
index 000000000000..6386c15e9770
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot
@@ -0,0 +1 @@
locktorture.torture_type=lock_busted
diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFLIST b/tools/testing/selftests/rcutorture/configs/lock/CFLIST
new file mode 100644
index 000000000000..a061b22d1892
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/CFLIST
@@ -0,0 +1 @@
LOCK01
diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFcommon b/tools/testing/selftests/rcutorture/configs/lock/CFcommon
new file mode 100644
index 000000000000..e372dc269254
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/CFcommon
@@ -0,0 +1,2 @@
1CONFIG_LOCK_TORTURE_TEST=y
2CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK01 b/tools/testing/selftests/rcutorture/configs/lock/LOCK01
new file mode 100644
index 000000000000..a9625e3d6cd9
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK01
@@ -0,0 +1,6 @@
1CONFIG_SMP=y
2CONFIG_NR_CPUS=8
3CONFIG_HOTPLUG_CPU=y
4CONFIG_PREEMPT_NONE=n
5CONFIG_PREEMPT_VOLUNTARY=n
6CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh
new file mode 100644
index 000000000000..9746ea1cd6c7
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh
@@ -0,0 +1,43 @@
1#!/bin/bash
2#
3# Kernel-version-dependent shell functions for the rest of the scripts.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, you can access it online at
17# http://www.gnu.org/licenses/gpl-2.0.html.
18#
19# Copyright (C) IBM Corporation, 2014
20#
21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
22
23# locktorture_param_onoff bootparam-string config-file
24#
25# Adds onoff locktorture module parameters to kernels having it.
26locktorture_param_onoff () {
27 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
28 then
29 echo CPU-hotplug kernel, adding locktorture onoff. 1>&2
30 echo locktorture.onoff_interval=3 locktorture.onoff_holdoff=30
31 fi
32}
33
34# per_version_boot_params bootparam-string config-file seconds
35#
36# Adds per-version torture-module parameters to kernels supporting them.
37per_version_boot_params () {
38 echo $1 `locktorture_param_onoff "$1" "$2"` \
39 locktorture.stat_interval=15 \
40 locktorture.shutdown_secs=$3 \
41 locktorture.locktorture_runnable=1 \
42 locktorture.verbose=1
43}
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED
new file mode 100644
index 000000000000..48d8a245c7fa
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED
@@ -0,0 +1,7 @@
1CONFIG_RCU_TRACE=n
2CONFIG_SMP=y
3CONFIG_NR_CPUS=4
4CONFIG_HOTPLUG_CPU=y
5CONFIG_PREEMPT_NONE=n
6CONFIG_PREEMPT_VOLUNTARY=n
7CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot
new file mode 100644
index 000000000000..6804f9dcfc1b
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot
@@ -0,0 +1 @@
rcutorture.torture_type=rcu_busted
diff --git a/tools/testing/selftests/rcutorture/configs/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
index cd3d29cb0a47..cd3d29cb0a47 100644
--- a/tools/testing/selftests/rcutorture/configs/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFcommon b/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
new file mode 100644
index 000000000000..d2d2a86139db
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
@@ -0,0 +1,2 @@
1CONFIG_RCU_TORTURE_TEST=y
2CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-N b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N
index 10a0e27f4c75..9fbb41b9b314 100644
--- a/tools/testing/selftests/rcutorture/configs/SRCU-N
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N
@@ -1,8 +1,7 @@
1CONFIG_RCU_TRACE=n 1CONFIG_RCU_TRACE=n
2CONFIG_SMP=y 2CONFIG_SMP=y
3CONFIG_NR_CPUS=8 3CONFIG_NR_CPUS=4
4CONFIG_HOTPLUG_CPU=y 4CONFIG_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_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-N.boot b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N.boot
index 238bfe3bd0cc..238bfe3bd0cc 100644
--- a/tools/testing/selftests/rcutorture/configs/SRCU-N.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N.boot
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-P b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P
index 6650e00c6d91..4b6f272dba27 100644
--- a/tools/testing/selftests/rcutorture/configs/SRCU-P
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P
@@ -5,4 +5,3 @@ CONFIG_HOTPLUG_CPU=y
5CONFIG_PREEMPT_NONE=n 5CONFIG_PREEMPT_NONE=n
6CONFIG_PREEMPT_VOLUNTARY=n 6CONFIG_PREEMPT_VOLUNTARY=n
7CONFIG_PREEMPT=y 7CONFIG_PREEMPT=y
8CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-P.boot b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P.boot
index 238bfe3bd0cc..238bfe3bd0cc 100644
--- a/tools/testing/selftests/rcutorture/configs/SRCU-P.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P.boot
diff --git a/tools/testing/selftests/rcutorture/configs/TINY01 b/tools/testing/selftests/rcutorture/configs/rcu/TINY01
index 0c2823f21712..0a63e073a00c 100644
--- a/tools/testing/selftests/rcutorture/configs/TINY01
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY01
@@ -10,4 +10,3 @@ CONFIG_RCU_TRACE=n
10CONFIG_DEBUG_LOCK_ALLOC=n 10CONFIG_DEBUG_LOCK_ALLOC=n
11CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 11CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
12CONFIG_PREEMPT_COUNT=n 12CONFIG_PREEMPT_COUNT=n
13CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TINY02 b/tools/testing/selftests/rcutorture/configs/rcu/TINY02
index e5072d7528b6..f4feaee40776 100644
--- a/tools/testing/selftests/rcutorture/configs/TINY02
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY02
@@ -10,4 +10,3 @@ CONFIG_RCU_TRACE=y
10CONFIG_DEBUG_LOCK_ALLOC=y 10CONFIG_DEBUG_LOCK_ALLOC=y
11CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 11CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
12CONFIG_PREEMPT_COUNT=y 12CONFIG_PREEMPT_COUNT=y
13CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE01 b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
index 141119a00044..9c827ec59a97 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE01
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
@@ -20,4 +20,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
20CONFIG_RCU_CPU_STALL_VERBOSE=n 20CONFIG_RCU_CPU_STALL_VERBOSE=n
21CONFIG_RCU_BOOST=n 21CONFIG_RCU_BOOST=n
22CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 22CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
23CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE01.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
index 0fc8a3428938..0fc8a3428938 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE01.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
diff --git a/tools/testing/selftests/rcutorture/configs/TREE02 b/tools/testing/selftests/rcutorture/configs/rcu/TREE02
index 2d4d09608528..1a777b5f68b5 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE02
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE02
@@ -7,7 +7,7 @@ CONFIG_PREEMPT=y
7CONFIG_HZ_PERIODIC=n 7CONFIG_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 11CONFIG_RCU_TRACE=n
12CONFIG_HOTPLUG_CPU=n 12CONFIG_HOTPLUG_CPU=n
13CONFIG_SUSPEND=n 13CONFIG_SUSPEND=n
@@ -23,4 +23,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
23CONFIG_RCU_CPU_STALL_VERBOSE=y 23CONFIG_RCU_CPU_STALL_VERBOSE=y
24CONFIG_RCU_BOOST=n 24CONFIG_RCU_BOOST=n
25CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 25CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
26CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE03 b/tools/testing/selftests/rcutorture/configs/rcu/TREE03
index a47de5be8a04..c1f111c1561b 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE03
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE03
@@ -20,4 +20,3 @@ CONFIG_RCU_CPU_STALL_VERBOSE=n
20CONFIG_RCU_BOOST=y 20CONFIG_RCU_BOOST=y
21CONFIG_RCU_BOOST_PRIO=2 21CONFIG_RCU_BOOST_PRIO=2
22CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 22CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
23CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
index 8d839b86a1d5..7dbd27ce17a4 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE04
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
@@ -22,4 +22,3 @@ CONFIG_PROVE_RCU_DELAY=n
22CONFIG_RCU_CPU_STALL_INFO=y 22CONFIG_RCU_CPU_STALL_INFO=y
23CONFIG_RCU_CPU_STALL_VERBOSE=y 23CONFIG_RCU_CPU_STALL_VERBOSE=y
24CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 24CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
25CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE04.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
index 0fc8a3428938..0fc8a3428938 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE04.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
diff --git a/tools/testing/selftests/rcutorture/configs/TREE05 b/tools/testing/selftests/rcutorture/configs/rcu/TREE05
index b5ba72ea25cb..d0f32e574743 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE05
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05
@@ -22,4 +22,3 @@ CONFIG_PROVE_RCU_DELAY=y
22CONFIG_RCU_CPU_STALL_INFO=n 22CONFIG_RCU_CPU_STALL_INFO=n
23CONFIG_RCU_CPU_STALL_VERBOSE=n 23CONFIG_RCU_CPU_STALL_VERBOSE=n
24CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 24CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
25CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE05.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot
index 3b42b8b033cd..3b42b8b033cd 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE05.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot
diff --git a/tools/testing/selftests/rcutorture/configs/TREE06 b/tools/testing/selftests/rcutorture/configs/rcu/TREE06
index 7c95ab48d29f..2e477dfb9c57 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE06
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE06
@@ -23,4 +23,3 @@ CONFIG_PROVE_RCU_DELAY=n
23CONFIG_RCU_CPU_STALL_INFO=n 23CONFIG_RCU_CPU_STALL_INFO=n
24CONFIG_RCU_CPU_STALL_VERBOSE=n 24CONFIG_RCU_CPU_STALL_VERBOSE=n
25CONFIG_DEBUG_OBJECTS_RCU_HEAD=y 25CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
26CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE07 b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
index 1467404bdec1..042f86ef362a 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE07
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
@@ -21,4 +21,3 @@ CONFIG_PROVE_RCU_DELAY=n
21CONFIG_RCU_CPU_STALL_INFO=y 21CONFIG_RCU_CPU_STALL_INFO=y
22CONFIG_RCU_CPU_STALL_VERBOSE=n 22CONFIG_RCU_CPU_STALL_VERBOSE=n
23CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 23CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
24CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE08 b/tools/testing/selftests/rcutorture/configs/rcu/TREE08
index 7d097a61ac2a..3438cee1e3c5 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE08
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08
@@ -23,4 +23,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
23CONFIG_RCU_CPU_STALL_VERBOSE=n 23CONFIG_RCU_CPU_STALL_VERBOSE=n
24CONFIG_RCU_BOOST=n 24CONFIG_RCU_BOOST=n
25CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 25CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
26CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE08-T b/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T
index 442c4e450ab3..bf4523d3e44c 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE08-T
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T
@@ -23,4 +23,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
23CONFIG_RCU_CPU_STALL_VERBOSE=n 23CONFIG_RCU_CPU_STALL_VERBOSE=n
24CONFIG_RCU_BOOST=n 24CONFIG_RCU_BOOST=n
25CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 25CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
26CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE09 b/tools/testing/selftests/rcutorture/configs/rcu/TREE09
index 0d1ec0d3dfee..81e4f7c0bf0b 100644
--- a/tools/testing/selftests/rcutorture/configs/TREE09
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE09
@@ -18,4 +18,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
18CONFIG_RCU_CPU_STALL_VERBOSE=n 18CONFIG_RCU_CPU_STALL_VERBOSE=n
19CONFIG_RCU_BOOST=n 19CONFIG_RCU_BOOST=n
20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
21CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST
index 18223947bbcb..18223947bbcb 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP
index d3ef873eb6e7..d3ef873eb6e7 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/N1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp
index 02e418572b1b..02e418572b1b 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/N2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp
index b3100f69c8cf..b3100f69c8cf 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/N3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP
index c56b44530725..c56b44530725 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/N4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp
index 90d924fea9e9..90d924fea9e9 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/N5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh
index 023f312a931c..023f312a931c 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/NT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH
index 6fd0235dae73..6fd0235dae73 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/NT3-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP
index f72402d7c13d..f72402d7c13d 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/P1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp
index 0f3b667d2a9f..0f3b667d2a9f 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/P2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp
index b035e141bf2a..b035e141bf2a 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/P3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP
index 3ccf6a9447f5..3ccf6a9447f5 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/P4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp
index ef624ce73d8e..ef624ce73d8e 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/P5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh
index e3361c3894a1..e3361c3894a1 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/PT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH
index 64abfc3b4d94..64abfc3b4d94 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/PT2-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh
index e8052539af54..5ace37a89780 100644
--- a/tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh
@@ -20,16 +20,14 @@
20# 20#
21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
22 22
23# rcutorture_param_n_barrier_cbs bootparam-string 23# per_version_boot_params bootparam-string config-file seconds
24# 24#
25# Adds n_barrier_cbs rcutorture module parameter to kernels having it. 25# Adds per-version torture-module parameters to kernels supporting them.
26rcutorture_param_n_barrier_cbs () { 26# Which old kernels do not.
27 echo $1 27per_version_boot_params () {
28} 28 echo rcutorture.stat_interval=15 \
29 29 rcutorture.shutdown_secs=$3 \
30# rcutorture_param_onoff bootparam-string config-file 30 rcutorture.rcutorture_runnable=1 \
31# 31 rcutorture.test_no_idle_hz=1 \
32# Adds onoff rcutorture module parameters to kernels having it. 32 rcutorture.verbose=1
33rcutorture_param_onoff () {
34 echo $1
35} 33}
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST
index da4cbc668f2a..da4cbc668f2a 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP
index d81e11d280aa..d81e11d280aa 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp
index 02e418572b1b..02e418572b1b 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp
index b3100f69c8cf..b3100f69c8cf 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP
index c56b44530725..c56b44530725 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp
index 90d924fea9e9..90d924fea9e9 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp
index 0ccc36d72738..0ccc36d72738 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N6---t-nh-SD-smp-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP
index 3f640cf84973..3f640cf84973 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N7-4-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N8-2-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP
index 285da2dd8ac3..285da2dd8ac3 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/N8-2-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh
index 023f312a931c..023f312a931c 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/NT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH
index 6fd0235dae73..6fd0235dae73 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/NT3-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP
index 9647c44cf4b7..9647c44cf4b7 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp
index 0f3b667d2a9f..0f3b667d2a9f 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp
index b035e141bf2a..b035e141bf2a 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP
index 3ccf6a9447f5..3ccf6a9447f5 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp
index ef624ce73d8e..ef624ce73d8e 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp
index f4c9175828bf..f4c9175828bf 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P6---t-nh-SD-smp-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP
index 77a8c5b75763..77a8c5b75763 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-all b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all
index 0eecebc6e95f..0eecebc6e95f 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-all
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-none b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none
index 0eecebc6e95f..0eecebc6e95f 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-none
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp
index 588bc70420cd..588bc70420cd 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh
index e3361c3894a1..e3361c3894a1 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/PT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH
index 64abfc3b4d94..64abfc3b4d94 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.12/PT2-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST
index 18223947bbcb..18223947bbcb 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP
index d81e11d280aa..d81e11d280aa 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/N1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp
index 02e418572b1b..02e418572b1b 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/N2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp
index b3100f69c8cf..b3100f69c8cf 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/N3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP
index c56b44530725..c56b44530725 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/N4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp
index 90d924fea9e9..90d924fea9e9 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/N5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh
index 023f312a931c..023f312a931c 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/NT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH
index 6fd0235dae73..6fd0235dae73 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/NT3-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP
index 9647c44cf4b7..9647c44cf4b7 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/P1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp
index 0f3b667d2a9f..0f3b667d2a9f 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/P2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp
index b035e141bf2a..b035e141bf2a 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/P3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP
index 3ccf6a9447f5..3ccf6a9447f5 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/P4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp
index ef624ce73d8e..ef624ce73d8e 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/P5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh
index e3361c3894a1..e3361c3894a1 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/PT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH
index 64abfc3b4d94..64abfc3b4d94 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/PT2-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH
diff --git a/tools/testing/selftests/rcutorture/configs/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh
index 5e40eadea777..bae55692ce6e 100644
--- a/tools/testing/selftests/rcutorture/configs/ver_functions.sh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh
@@ -20,18 +20,6 @@
20# 20#
21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
22 22
23# rcutorture_param_n_barrier_cbs bootparam-string
24#
25# Adds n_barrier_cbs rcutorture module parameter to kernels having it.
26rcutorture_param_n_barrier_cbs () {
27 if echo $1 | grep -q "rcutorture\.n_barrier_cbs"
28 then
29 echo $1
30 else
31 echo $1 rcutorture.n_barrier_cbs=4
32 fi
33}
34
35# rcutorture_param_onoff bootparam-string config-file 23# rcutorture_param_onoff bootparam-string config-file
36# 24#
37# Adds onoff rcutorture module parameters to kernels having it. 25# Adds onoff rcutorture module parameters to kernels having it.
@@ -39,8 +27,18 @@ rcutorture_param_onoff () {
39 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" 27 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
40 then 28 then
41 echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2 29 echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
42 echo $1 rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 30 echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
43 else
44 echo $1
45 fi 31 fi
46} 32}
33
34# per_version_boot_params bootparam-string config-file seconds
35#
36# Adds per-version torture-module parameters to kernels supporting them.
37per_version_boot_params () {
38 echo $1 `rcutorture_param_onoff "$1" "$2"` \
39 rcutorture.stat_interval=15 \
40 rcutorture.shutdown_secs=$3 \
41 rcutorture.rcutorture_runnable=1 \
42 rcutorture.test_no_idle_hz=1 \
43 rcutorture.verbose=1
44}
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST
index 18223947bbcb..18223947bbcb 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP
index d81e11d280aa..d81e11d280aa 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/N1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp
index 02e418572b1b..02e418572b1b 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/N2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp
index b3100f69c8cf..b3100f69c8cf 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/N3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP
index c56b44530725..c56b44530725 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/N4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp
index 90d924fea9e9..90d924fea9e9 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/N5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh
index 023f312a931c..023f312a931c 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/NT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH
index 6fd0235dae73..6fd0235dae73 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/NT3-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP
index 9647c44cf4b7..9647c44cf4b7 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/P1-S-T-NH-SD-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp
index 0f3b667d2a9f..0f3b667d2a9f 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/P2-2-t-nh-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp
index b035e141bf2a..b035e141bf2a 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/P3-3-T-nh-SD-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP
index 3ccf6a9447f5..3ccf6a9447f5 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/P4-A-t-NH-sd-SMP-HP
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp
index ef624ce73d8e..ef624ce73d8e 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/P5-U-T-NH-sd-SMP-hp
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh
index e3361c3894a1..e3361c3894a1 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/PT1-nh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH
index 64abfc3b4d94..64abfc3b4d94 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/PT2-NH
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh
index 6a5f13aab44d..8977d8d31b19 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh
@@ -26,9 +26,9 @@
26rcutorture_param_n_barrier_cbs () { 26rcutorture_param_n_barrier_cbs () {
27 if echo $1 | grep -q "rcutorture\.n_barrier_cbs" 27 if echo $1 | grep -q "rcutorture\.n_barrier_cbs"
28 then 28 then
29 echo $1 29 :
30 else 30 else
31 echo $1 rcutorture.n_barrier_cbs=4 31 echo rcutorture.n_barrier_cbs=4
32 fi 32 fi
33} 33}
34 34
@@ -38,9 +38,20 @@ rcutorture_param_n_barrier_cbs () {
38rcutorture_param_onoff () { 38rcutorture_param_onoff () {
39 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" 39 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
40 then 40 then
41 echo CPU-hotplug kernel, adding rcutorture onoff. 41 echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
42 echo $1 rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 42 echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
43 else
44 echo $1
45 fi 43 fi
46} 44}
45
46# per_version_boot_params bootparam-string config-file seconds
47#
48# Adds per-version torture-module parameters to kernels supporting them.
49per_version_boot_params () {
50 echo $1 `rcutorture_param_onoff "$1" "$2"` \
51 `rcutorture_param_n_barrier_cbs "$1"` \
52 rcutorture.stat_interval=15 \
53 rcutorture.shutdown_secs=$3 \
54 rcutorture.rcutorture_runnable=1 \
55 rcutorture.test_no_idle_hz=1 \
56 rcutorture.verbose=1
57}
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh
index c37432f3572c..8977d8d31b19 100644
--- a/tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh
@@ -24,7 +24,12 @@
24# 24#
25# Adds n_barrier_cbs rcutorture module parameter to kernels having it. 25# Adds n_barrier_cbs rcutorture module parameter to kernels having it.
26rcutorture_param_n_barrier_cbs () { 26rcutorture_param_n_barrier_cbs () {
27 echo $1 27 if echo $1 | grep -q "rcutorture\.n_barrier_cbs"
28 then
29 :
30 else
31 echo rcutorture.n_barrier_cbs=4
32 fi
28} 33}
29 34
30# rcutorture_param_onoff bootparam-string config-file 35# rcutorture_param_onoff bootparam-string config-file
@@ -33,9 +38,20 @@ rcutorture_param_n_barrier_cbs () {
33rcutorture_param_onoff () { 38rcutorture_param_onoff () {
34 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2" 39 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
35 then 40 then
36 echo CPU-hotplug kernel, adding rcutorture onoff. 41 echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
37 echo $1 rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30 42 echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
38 else
39 echo $1
40 fi 43 fi
41} 44}
45
46# per_version_boot_params bootparam-string config-file seconds
47#
48# Adds per-version torture-module parameters to kernels supporting them.
49per_version_boot_params () {
50 echo $1 `rcutorture_param_onoff "$1" "$2"` \
51 `rcutorture_param_n_barrier_cbs "$1"` \
52 rcutorture.stat_interval=15 \
53 rcutorture.shutdown_secs=$3 \
54 rcutorture.rcutorture_runnable=1 \
55 rcutorture.test_no_idle_hz=1 \
56 rcutorture.verbose=1
57}
diff --git a/tools/testing/selftests/rcutorture/doc/TREE_RCU-Kconfig.txt b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
index adbb76cffb49..adbb76cffb49 100644
--- a/tools/testing/selftests/rcutorture/doc/TREE_RCU-Kconfig.txt
+++ b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
diff --git a/tools/virtio/linux/kmemleak.h b/tools/virtio/linux/kmemleak.h
new file mode 100644
index 000000000000..c07072270e2f
--- /dev/null
+++ b/tools/virtio/linux/kmemleak.h
@@ -0,0 +1,3 @@
1static inline void kmemleak_ignore(const void *ptr)
2{
3}
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h
index 844783040703..5a2d1f0f6bc7 100644
--- a/tools/virtio/linux/virtio.h
+++ b/tools/virtio/linux/virtio.h
@@ -63,7 +63,7 @@ int virtqueue_add_inbuf(struct virtqueue *vq,
63 void *data, 63 void *data,
64 gfp_t gfp); 64 gfp_t gfp);
65 65
66void virtqueue_kick(struct virtqueue *vq); 66bool virtqueue_kick(struct virtqueue *vq);
67 67
68void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len); 68void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len);
69 69
@@ -79,7 +79,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
79 struct virtio_device *vdev, 79 struct virtio_device *vdev,
80 bool weak_barriers, 80 bool weak_barriers,
81 void *pages, 81 void *pages,
82 void (*notify)(struct virtqueue *vq), 82 bool (*notify)(struct virtqueue *vq),
83 void (*callback)(struct virtqueue *vq), 83 void (*callback)(struct virtqueue *vq),
84 const char *name); 84 const char *name);
85void vring_del_virtqueue(struct virtqueue *vq); 85void vring_del_virtqueue(struct virtqueue *vq);
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c
index bdb71a26ae35..00ea679b3826 100644
--- a/tools/virtio/virtio_test.c
+++ b/tools/virtio/virtio_test.c
@@ -172,7 +172,7 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
172 GFP_ATOMIC); 172 GFP_ATOMIC);
173 if (likely(r == 0)) { 173 if (likely(r == 0)) {
174 ++started; 174 ++started;
175 if (unlikely(!virtqueue_kick(vq->vq)) 175 if (unlikely(!virtqueue_kick(vq->vq)))
176 r = -1; 176 r = -1;
177 } 177 }
178 } else 178 } else
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c
index f9be24d9efac..05654f5e48d5 100644
--- a/tools/vm/page-types.c
+++ b/tools/vm/page-types.c
@@ -19,7 +19,8 @@
19 * Authors: Wu Fengguang <fengguang.wu@intel.com> 19 * Authors: Wu Fengguang <fengguang.wu@intel.com>
20 */ 20 */
21 21
22#define _LARGEFILE64_SOURCE 22#define _FILE_OFFSET_BITS 64
23#define _GNU_SOURCE
23#include <stdio.h> 24#include <stdio.h>
24#include <stdlib.h> 25#include <stdlib.h>
25#include <unistd.h> 26#include <unistd.h>
@@ -29,11 +30,14 @@
29#include <getopt.h> 30#include <getopt.h>
30#include <limits.h> 31#include <limits.h>
31#include <assert.h> 32#include <assert.h>
33#include <ftw.h>
34#include <time.h>
32#include <sys/types.h> 35#include <sys/types.h>
33#include <sys/errno.h> 36#include <sys/errno.h>
34#include <sys/fcntl.h> 37#include <sys/fcntl.h>
35#include <sys/mount.h> 38#include <sys/mount.h>
36#include <sys/statfs.h> 39#include <sys/statfs.h>
40#include <sys/mman.h>
37#include "../../include/uapi/linux/magic.h" 41#include "../../include/uapi/linux/magic.h"
38#include "../../include/uapi/linux/kernel-page-flags.h" 42#include "../../include/uapi/linux/kernel-page-flags.h"
39#include <api/fs/debugfs.h> 43#include <api/fs/debugfs.h>
@@ -158,6 +162,7 @@ static int opt_raw; /* for kernel developers */
158static int opt_list; /* list pages (in ranges) */ 162static int opt_list; /* list pages (in ranges) */
159static int opt_no_summary; /* don't show summary */ 163static int opt_no_summary; /* don't show summary */
160static pid_t opt_pid; /* process to walk */ 164static pid_t opt_pid; /* process to walk */
165const char * opt_file;
161 166
162#define MAX_ADDR_RANGES 1024 167#define MAX_ADDR_RANGES 1024
163static int nr_addr_ranges; 168static int nr_addr_ranges;
@@ -253,12 +258,7 @@ static unsigned long do_u64_read(int fd, char *name,
253 if (index > ULONG_MAX / 8) 258 if (index > ULONG_MAX / 8)
254 fatal("index overflow: %lu\n", index); 259 fatal("index overflow: %lu\n", index);
255 260
256 if (lseek(fd, index * 8, SEEK_SET) < 0) { 261 bytes = pread(fd, buf, count * 8, (off_t)index * 8);
257 perror(name);
258 exit(EXIT_FAILURE);
259 }
260
261 bytes = read(fd, buf, count * 8);
262 if (bytes < 0) { 262 if (bytes < 0) {
263 perror(name); 263 perror(name);
264 exit(EXIT_FAILURE); 264 exit(EXIT_FAILURE);
@@ -343,8 +343,8 @@ static char *page_flag_longname(uint64_t flags)
343 * page list and summary 343 * page list and summary
344 */ 344 */
345 345
346static void show_page_range(unsigned long voffset, 346static void show_page_range(unsigned long voffset, unsigned long offset,
347 unsigned long offset, uint64_t flags) 347 unsigned long size, uint64_t flags)
348{ 348{
349 static uint64_t flags0; 349 static uint64_t flags0;
350 static unsigned long voff; 350 static unsigned long voff;
@@ -352,14 +352,16 @@ static void show_page_range(unsigned long voffset,
352 static unsigned long count; 352 static unsigned long count;
353 353
354 if (flags == flags0 && offset == index + count && 354 if (flags == flags0 && offset == index + count &&
355 (!opt_pid || voffset == voff + count)) { 355 size && voffset == voff + count) {
356 count++; 356 count += size;
357 return; 357 return;
358 } 358 }
359 359
360 if (count) { 360 if (count) {
361 if (opt_pid) 361 if (opt_pid)
362 printf("%lx\t", voff); 362 printf("%lx\t", voff);
363 if (opt_file)
364 printf("%lu\t", voff);
363 printf("%lx\t%lx\t%s\n", 365 printf("%lx\t%lx\t%s\n",
364 index, count, page_flag_name(flags0)); 366 index, count, page_flag_name(flags0));
365 } 367 }
@@ -367,7 +369,12 @@ static void show_page_range(unsigned long voffset,
367 flags0 = flags; 369 flags0 = flags;
368 index = offset; 370 index = offset;
369 voff = voffset; 371 voff = voffset;
370 count = 1; 372 count = size;
373}
374
375static void flush_page_range(void)
376{
377 show_page_range(0, 0, 0, 0);
371} 378}
372 379
373static void show_page(unsigned long voffset, 380static void show_page(unsigned long voffset,
@@ -375,6 +382,8 @@ static void show_page(unsigned long voffset,
375{ 382{
376 if (opt_pid) 383 if (opt_pid)
377 printf("%lx\t", voffset); 384 printf("%lx\t", voffset);
385 if (opt_file)
386 printf("%lu\t", voffset);
378 printf("%lx\t%s\n", offset, page_flag_name(flags)); 387 printf("%lx\t%s\n", offset, page_flag_name(flags));
379} 388}
380 389
@@ -565,7 +574,7 @@ static void add_page(unsigned long voffset,
565 unpoison_page(offset); 574 unpoison_page(offset);
566 575
567 if (opt_list == 1) 576 if (opt_list == 1)
568 show_page_range(voffset, offset, flags); 577 show_page_range(voffset, offset, 1, flags);
569 else if (opt_list == 2) 578 else if (opt_list == 2)
570 show_page(voffset, offset, flags); 579 show_page(voffset, offset, flags);
571 580
@@ -667,7 +676,7 @@ static void walk_addr_ranges(void)
667 676
668 for (i = 0; i < nr_addr_ranges; i++) 677 for (i = 0; i < nr_addr_ranges; i++)
669 if (!opt_pid) 678 if (!opt_pid)
670 walk_pfn(0, opt_offset[i], opt_size[i], 0); 679 walk_pfn(opt_offset[i], opt_offset[i], opt_size[i], 0);
671 else 680 else
672 walk_task(opt_offset[i], opt_size[i]); 681 walk_task(opt_offset[i], opt_size[i]);
673 682
@@ -699,9 +708,7 @@ static void usage(void)
699" -a|--addr addr-spec Walk a range of pages\n" 708" -a|--addr addr-spec Walk a range of pages\n"
700" -b|--bits bits-spec Walk pages with specified bits\n" 709" -b|--bits bits-spec Walk pages with specified bits\n"
701" -p|--pid pid Walk process address space\n" 710" -p|--pid pid Walk process address space\n"
702#if 0 /* planned features */
703" -f|--file filename Walk file address space\n" 711" -f|--file filename Walk file address space\n"
704#endif
705" -l|--list Show page details in ranges\n" 712" -l|--list Show page details in ranges\n"
706" -L|--list-each Show page details one by one\n" 713" -L|--list-each Show page details one by one\n"
707" -N|--no-summary Don't show summary info\n" 714" -N|--no-summary Don't show summary info\n"
@@ -799,8 +806,130 @@ static void parse_pid(const char *str)
799 fclose(file); 806 fclose(file);
800} 807}
801 808
809static void show_file(const char *name, const struct stat *st)
810{
811 unsigned long long size = st->st_size;
812 char atime[64], mtime[64];
813 long now = time(NULL);
814
815 printf("%s\tInode: %u\tSize: %llu (%llu pages)\n",
816 name, (unsigned)st->st_ino,
817 size, (size + page_size - 1) / page_size);
818
819 strftime(atime, sizeof(atime), "%c", localtime(&st->st_atime));
820 strftime(mtime, sizeof(mtime), "%c", localtime(&st->st_mtime));
821
822 printf("Modify: %s (%ld seconds ago)\nAccess: %s (%ld seconds ago)\n",
823 mtime, now - st->st_mtime,
824 atime, now - st->st_atime);
825}
826
827static void walk_file(const char *name, const struct stat *st)
828{
829 uint8_t vec[PAGEMAP_BATCH];
830 uint64_t buf[PAGEMAP_BATCH], flags;
831 unsigned long nr_pages, pfn, i;
832 int fd;
833 off_t off;
834 ssize_t len;
835 void *ptr;
836 int first = 1;
837
838 fd = checked_open(name, O_RDONLY|O_NOATIME|O_NOFOLLOW);
839
840 for (off = 0; off < st->st_size; off += len) {
841 nr_pages = (st->st_size - off + page_size - 1) / page_size;
842 if (nr_pages > PAGEMAP_BATCH)
843 nr_pages = PAGEMAP_BATCH;
844 len = nr_pages * page_size;
845
846 ptr = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, off);
847 if (ptr == MAP_FAILED)
848 fatal("mmap failed: %s", name);
849
850 /* determine cached pages */
851 if (mincore(ptr, len, vec))
852 fatal("mincore failed: %s", name);
853
854 /* turn off readahead */
855 if (madvise(ptr, len, MADV_RANDOM))
856 fatal("madvice failed: %s", name);
857
858 /* populate ptes */
859 for (i = 0; i < nr_pages ; i++) {
860 if (vec[i] & 1)
861 (void)*(volatile int *)(ptr + i * page_size);
862 }
863
864 /* turn off harvesting reference bits */
865 if (madvise(ptr, len, MADV_SEQUENTIAL))
866 fatal("madvice failed: %s", name);
867
868 if (pagemap_read(buf, (unsigned long)ptr / page_size,
869 nr_pages) != nr_pages)
870 fatal("cannot read pagemap");
871
872 munmap(ptr, len);
873
874 for (i = 0; i < nr_pages; i++) {
875 pfn = pagemap_pfn(buf[i]);
876 if (!pfn)
877 continue;
878 if (!kpageflags_read(&flags, pfn, 1))
879 continue;
880 if (first && opt_list) {
881 first = 0;
882 flush_page_range();
883 show_file(name, st);
884 }
885 add_page(off / page_size + i, pfn, flags, buf[i]);
886 }
887 }
888
889 close(fd);
890}
891
892int walk_tree(const char *name, const struct stat *st, int type, struct FTW *f)
893{
894 (void)f;
895 switch (type) {
896 case FTW_F:
897 if (S_ISREG(st->st_mode))
898 walk_file(name, st);
899 break;
900 case FTW_DNR:
901 fprintf(stderr, "cannot read dir: %s\n", name);
902 break;
903 }
904 return 0;
905}
906
907static void walk_page_cache(void)
908{
909 struct stat st;
910
911 kpageflags_fd = checked_open(PROC_KPAGEFLAGS, O_RDONLY);
912 pagemap_fd = checked_open("/proc/self/pagemap", O_RDONLY);
913
914 if (stat(opt_file, &st))
915 fatal("stat failed: %s\n", opt_file);
916
917 if (S_ISREG(st.st_mode)) {
918 walk_file(opt_file, &st);
919 } else if (S_ISDIR(st.st_mode)) {
920 /* do not follow symlinks and mountpoints */
921 if (nftw(opt_file, walk_tree, 64, FTW_MOUNT | FTW_PHYS) < 0)
922 fatal("nftw failed: %s\n", opt_file);
923 } else
924 fatal("unhandled file type: %s\n", opt_file);
925
926 close(kpageflags_fd);
927 close(pagemap_fd);
928}
929
802static void parse_file(const char *name) 930static void parse_file(const char *name)
803{ 931{
932 opt_file = name;
804} 933}
805 934
806static void parse_addr_range(const char *optarg) 935static void parse_addr_range(const char *optarg)
@@ -991,15 +1120,20 @@ int main(int argc, char *argv[])
991 1120
992 if (opt_list && opt_pid) 1121 if (opt_list && opt_pid)
993 printf("voffset\t"); 1122 printf("voffset\t");
1123 if (opt_list && opt_file)
1124 printf("foffset\t");
994 if (opt_list == 1) 1125 if (opt_list == 1)
995 printf("offset\tlen\tflags\n"); 1126 printf("offset\tlen\tflags\n");
996 if (opt_list == 2) 1127 if (opt_list == 2)
997 printf("offset\tflags\n"); 1128 printf("offset\tflags\n");
998 1129
999 walk_addr_ranges(); 1130 if (opt_file)
1131 walk_page_cache();
1132 else
1133 walk_addr_ranges();
1000 1134
1001 if (opt_list == 1) 1135 if (opt_list == 1)
1002 show_page_range(0, 0, 0); /* drain the buffer */ 1136 flush_page_range();
1003 1137
1004 if (opt_no_summary) 1138 if (opt_no_summary)
1005 return 0; 1139 return 0;